Unverified Commit 25d8df56 authored by Kyle Keating's avatar Kyle Keating Committed by GitHub

Merge pull request #1269 from hypothesis/react-selection-tabs

Add react selection-tabs component
parents 8813b8cf 1efb767b
'use strict';
const classnames = require('classnames');
const propTypes = require('prop-types');
const { createElement } = require('preact');
const { Fragment } = require('preact');
const NewNoteBnt = require('./new-note-btn');
const sessionUtil = require('../util/session-util');
const uiConstants = require('../ui-constants');
const useStore = require('../store/use-store');
const { withServices } = require('../util/service-context');
/**
* Display name of the tab and annotation count.
*/
function Tab({
children,
count,
isWaitingToAnchor,
onChangeTab,
selected,
type,
}) {
return (
<a
className={classnames('selection-tabs__type', {
'is-selected': selected,
})}
onMouseDown={onChangeTab.bind(this, type)}
onTouchStart={onChangeTab.bind(this, type)}
>
{children}
{count > 0 && !isWaitingToAnchor && (
<span className="selection-tabs__count"> {count}</span>
)}
</a>
);
}
Tab.propTypes = {
/**
* Child components.
*/
children: propTypes.node.isRequired,
/**
* The total annotations for this tab.
*/
count: propTypes.number.isRequired,
/**
* Are there any annotations still waiting to anchor?
*/
isWaitingToAnchor: propTypes.bool.isRequired,
/**
* Callback when this tab is active with type as a parameter.
*/
onChangeTab: propTypes.func.isRequired,
/**
* Is this tab currently selected?
*/
selected: propTypes.bool.isRequired,
/**
* The type value for this tab. One of
* 'annotation', 'note', or 'orphan'.
*/
type: propTypes.oneOf(['annotation', 'note', 'orphan']).isRequired,
};
module.exports = {
controllerAs: 'vm',
//@ngInject
controller: function($element, store, features, session, settings) {
this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS;
this.TAB_NOTES = uiConstants.TAB_NOTES;
this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
/**
* Tabbed display of annotations and notes.
*/
this.isThemeClean = settings.theme === 'clean';
function SelectionTabs({
isWaitingToAnchorAnnotations,
isLoading,
selectedTab,
totalAnnotations,
totalNotes,
totalOrphans,
settings,
session,
}) {
// actions
const store = useStore(store => ({
clearSelectedAnnotations: store.clearSelectedAnnotations,
selectTab: store.selectTab,
}));
this.enableExperimentalNewNoteButton =
settings.enableExperimentalNewNoteButton;
const isThemeClean = settings.theme === 'clean';
this.selectTab = function(type) {
const selectTab = function(type) {
store.clearSelectedAnnotations();
store.selectTab(type);
};
this.showAnnotationsUnavailableMessage = function() {
return (
this.selectedTab === this.TAB_ANNOTATIONS &&
this.totalAnnotations === 0 &&
!this.isWaitingToAnchorAnnotations
const showAnnotationsUnavailableMessage =
selectedTab === uiConstants.TAB_ANNOTATIONS &&
totalAnnotations === 0 &&
!isWaitingToAnchorAnnotations;
const showNotesUnavailableMessage =
selectedTab === uiConstants.TAB_NOTES && totalNotes === 0;
const showSidebarTutorial = sessionUtil.shouldShowSidebarTutorial(
session.state
);
};
this.showNotesUnavailableMessage = function() {
return this.selectedTab === this.TAB_NOTES && this.totalNotes === 0;
};
return (
<Fragment>
<div
className={classnames('selection-tabs', {
'selection-tabs--theme-clean': isThemeClean,
})}
>
<Tab
count={totalAnnotations}
isWaitingToAnchor={isWaitingToAnchorAnnotations}
selected={selectedTab === uiConstants.TAB_ANNOTATIONS}
type={uiConstants.TAB_ANNOTATIONS}
onChangeTab={selectTab}
>
Annotations
</Tab>
<Tab
count={totalNotes}
isWaitingToAnchor={isWaitingToAnchorAnnotations}
selected={selectedTab === uiConstants.TAB_NOTES}
type={uiConstants.TAB_NOTES}
onChangeTab={selectTab}
>
Page Notes
</Tab>
{totalOrphans > 0 && (
<Tab
count={totalOrphans}
isWaitingToAnchor={isWaitingToAnchorAnnotations}
selected={selectedTab === uiConstants.TAB_ORPHANS}
type={uiConstants.TAB_ORPHANS}
onChangeTab={selectTab}
>
Orphans
</Tab>
)}
</div>
{selectedTab === uiConstants.TAB_NOTES &&
settings.enableExperimentalNewNoteButton && <NewNoteBnt />}
{!isLoading && (
<div className="selection-tabs__empty-message">
{showNotesUnavailableMessage && (
<div className="annotation-unavailable-message">
<p className="annotation-unavailable-message__label">
There are no page notes in this group.
{settings.enableExperimentalNewNoteButton &&
!showSidebarTutorial && (
<div className="annotation-unavailable-message__tutorial">
Create one by clicking the{' '}
<i className="help-icon h-icon-note" /> button.
</div>
)}
</p>
</div>
)}
{showAnnotationsUnavailableMessage && (
<div className="annotation-unavailable-message">
<p className="annotation-unavailable-message__label">
There are no annotations in this group.
{!showSidebarTutorial && (
<div className="annotation-unavailable-message__tutorial">
Create one by selecting some text and clicking the{' '}
<i className="help-icon h-icon-annotate" /> button.
</div>
)}
</p>
</div>
)}
</div>
)}
</Fragment>
);
}
SelectionTabs.propTypes = {
/**
* Are we waiting on any annotations from the server?
*/
isLoading: propTypes.bool.isRequired,
/**
* Are there any annotations still waiting to anchor?
*/
isWaitingToAnchorAnnotations: propTypes.bool.isRequired,
/**
* The currently selected tab (annotations, notes or orphans).
*/
selectedTab: propTypes.oneOf(['annotation', 'note', 'orphan']).isRequired,
/**
* The totals for each respect tab.
*/
totalAnnotations: propTypes.number.isRequired,
totalNotes: propTypes.number.isRequired,
totalOrphans: propTypes.number.isRequired,
this.showSidebarTutorial = function() {
return sessionUtil.shouldShowSidebarTutorial(session.state);
};
},
bindings: {
isLoading: '<',
isWaitingToAnchorAnnotations: '<',
selectedTab: '<',
totalAnnotations: '<',
totalNotes: '<',
totalOrphans: '<',
},
template: require('../templates/selection-tabs.html'),
// Injected services.
settings: propTypes.object.isRequired,
session: propTypes.object.isRequired,
};
SelectionTabs.injectedProps = ['session', 'settings'];
module.exports = withServices(SelectionTabs);
......@@ -188,7 +188,10 @@ function startAngularApp(config) {
'newNoteBtn',
wrapReactComponent(require('./components/new-note-btn'))
)
.component('selectionTabs', require('./components/selection-tabs'))
.component(
'selectionTabs',
wrapReactComponent(require('./components/selection-tabs'))
)
.component('sidebarContent', require('./components/sidebar-content'))
.component(
'sidebarContentError',
......
<!-- Tabbed display of annotations and notes. -->
<div class="selection-tabs"
ng-class="{'selection-tabs--theme-clean' : vm.isThemeClean }">
<a class="selection-tabs__type"
href="#"
ng-class="{'is-selected': vm.selectedTab === vm.TAB_ANNOTATIONS}"
h-on-touch="vm.selectTab(vm.TAB_ANNOTATIONS)">
Annotations
<span class="selection-tabs__count"
ng-if="vm.totalAnnotations > 0 && !vm.isWaitingToAnchorAnnotations">
{{ vm.totalAnnotations }}
</span>
</a>
<a class="selection-tabs__type"
href="#"
ng-class="{'is-selected': vm.selectedTab === vm.TAB_NOTES}"
h-on-touch="vm.selectTab(vm.TAB_NOTES)">
Page Notes
<span class="selection-tabs__count"
ng-if="vm.totalNotes > 0 && !vm.isWaitingToAnchorAnnotations">
{{ vm.totalNotes }}
</span>
</a>
<a class="selection-tabs__type selection-tabs__type--orphan"
ng-if="vm.totalOrphans > 0"
href="#"
ng-class="{'is-selected': vm.selectedTab === vm.TAB_ORPHANS}"
h-on-touch="vm.selectTab(vm.TAB_ORPHANS)">
Orphans
<span class="selection-tabs__count"
ng-if="vm.totalOrphans > 0 && !vm.isWaitingToAnchorAnnotations">
{{ vm.totalOrphans }}
</span>
</a>
</div>
<new-note-btn
ng-if="vm.selectedTab === vm.TAB_NOTES && vm.enableExperimentalNewNoteButton">
</new-note-btn>
<div ng-if="!vm.isLoading()" class="selection-tabs__empty-message">
<div ng-if="vm.showNotesUnavailableMessage()" class="annotation-unavailable-message">
<p class="annotation-unavailable-message__label">
There are no page notes in this group.
<br />
<div ng-if="!vm.enableExperimentalNewNoteButton && !vm.showSidebarTutorial()" class="annotation-unavailable-message__tutorial">
Create one by clicking the
<i class="help-icon h-icon-note"></i>
button.
</div>
</p>
</div>
<div ng-if="vm.showAnnotationsUnavailableMessage()" class="annotation-unavailable-message">
<p class="annotation-unavailable-message__label">
There are no annotations in this group.
<br />
<div ng-if="!vm.showSidebarTutorial()" class="annotation-unavailable-message__tutorial">
Create one by selecting some text and clicking the
<i class="help-icon h-icon-annotate"></i> button.
</div>
</p>
</div>
</div>
<selection-tabs
ng-if="vm.showSelectedTabs()"
is-waiting-to-anchor-annotations="vm.waitingToAnchorAnnotations"
is-loading="vm.isLoading"
is-loading="vm.isLoading()"
selected-tab="vm.selectedTab"
total-annotations="vm.totalAnnotations"
total-notes="vm.totalNotes"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment