Unverified Commit 21ecaa76 authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #1233 from hypothesis/move-tab-count-to-store

Move tab counts to store
parents d1669ce3 02235b72
......@@ -3,7 +3,7 @@
const propTypes = require('prop-types');
const { createElement } = require('preact');
const annotationMetadata = require('../annotation-metadata');
const annotationMetadata = require('../util/annotation-metadata');
/**
* Render some metadata about an annotation's document and link to it
......
'use strict';
const annotationMetadata = require('../annotation-metadata');
const annotationMetadata = require('../util/annotation-metadata');
const events = require('../events');
const { isThirdPartyUser } = require('../util/account-id');
const serviceConfig = require('../service-config');
......
......@@ -4,7 +4,7 @@ const { createElement } = require('preact');
const classnames = require('classnames');
const propTypes = require('prop-types');
const annotationMetadata = require('../annotation-metadata');
const annotationMetadata = require('../util/annotation-metadata');
const useStore = require('../store/use-store');
const { withServices } = require('../util/service-context');
......
......@@ -21,18 +21,24 @@ const countVisibleAnns = annThread => {
* A bar where the user can clear a selection or search and see whether
* any search results were found.
* */
function SearchStatusBar({
function SearchStatusBar({ rootThread }) {
const {
directLinkedGroupFetchFailed,
filterQuery,
selectedAnnotationMap,
selectedTab,
totalAnnotations,
totalNotes,
rootThread,
}) {
const storeState = useStore(store => store.getState());
} = useStore(store => ({
directLinkedGroupFetchFailed: store.getState().directLinkedGroupFetchFailed,
filterQuery: store.getState().filterQuery,
selectedAnnotationMap: store.getState().selectedAnnotationMap,
selectedTab: store.getState().selectedTab,
}));
const clearSelection = useStore(store => store.clearSelection);
const filterQuery = storeState.filterQuery;
const filterActive = !!storeState.filterQuery;
const filterActive = !!filterQuery;
const annotationCount = useStore(store => store.annotationCount());
const noteCount = useStore(store => store.noteCount());
const thread = rootThread.thread(storeState);
const thread = useStore(store => rootThread.thread(store.getState()));
const visibleCount = useMemo(() => {
return countVisibleAnns(thread);
......@@ -51,10 +57,10 @@ function SearchStatusBar({
};
const areNotAllAnnotationsVisible = () => {
if (storeState.directLinkedGroupFetchFailed) {
if (directLinkedGroupFetchFailed) {
return true;
}
const selection = storeState.selectedAnnotationMap;
const selection = selectedAnnotationMap;
if (!selection) {
return false;
}
......@@ -89,13 +95,13 @@ function SearchStatusBar({
{selectedTab === uiConstants.TAB_ANNOTATIONS && (
<Fragment>
Show all annotations
{totalAnnotations > 1 && <span> ({totalAnnotations})</span>}
{annotationCount > 1 && <span> ({annotationCount})</span>}
</Fragment>
)}
{selectedTab === uiConstants.TAB_NOTES && (
<Fragment>
Show all notes
{totalNotes > 1 && <span> ({totalNotes})</span>}
{noteCount > 1 && <span> ({noteCount})</span>}
</Fragment>
)}
</button>
......@@ -106,13 +112,7 @@ function SearchStatusBar({
}
SearchStatusBar.propTypes = {
selectedTab: propTypes.oneOf([
uiConstants.TAB_ANNOTATIONS,
uiConstants.TAB_ORPHANS,
uiConstants.TAB_NOTES,
]).isRequired,
totalAnnotations: propTypes.number.isRequired,
totalNotes: propTypes.number.isRequired,
// Injected services.
rootThread: propTypes.object.isRequired,
};
......
......@@ -69,16 +69,14 @@ Tab.propTypes = {
* Tabbed display of annotations and notes.
*/
function SelectionTabs({
isWaitingToAnchorAnnotations,
isLoading,
selectedTab,
totalAnnotations,
totalNotes,
totalOrphans,
settings,
session,
}) {
function SelectionTabs({ isLoading, settings, session }) {
const selectedTab = useStore(store => store.getState().selectedTab);
const noteCount = useStore(store => store.noteCount());
const annotationCount = useStore(store => store.annotationCount());
const orphanCount = useStore(store => store.orphanCount());
const isWaitingToAnchorAnnotations = useStore(store =>
store.isWaitingToAnchorAnnotations()
);
// actions
const store = useStore(store => ({
clearSelectedAnnotations: store.clearSelectedAnnotations,
......@@ -94,11 +92,11 @@ function SelectionTabs({
const showAnnotationsUnavailableMessage =
selectedTab === uiConstants.TAB_ANNOTATIONS &&
totalAnnotations === 0 &&
annotationCount === 0 &&
!isWaitingToAnchorAnnotations;
const showNotesUnavailableMessage =
selectedTab === uiConstants.TAB_NOTES && totalNotes === 0;
selectedTab === uiConstants.TAB_NOTES && noteCount === 0;
const showSidebarTutorial = sessionUtil.shouldShowSidebarTutorial(
session.state
......@@ -112,7 +110,7 @@ function SelectionTabs({
})}
>
<Tab
count={totalAnnotations}
count={annotationCount}
isWaitingToAnchor={isWaitingToAnchorAnnotations}
selected={selectedTab === uiConstants.TAB_ANNOTATIONS}
type={uiConstants.TAB_ANNOTATIONS}
......@@ -121,7 +119,7 @@ function SelectionTabs({
Annotations
</Tab>
<Tab
count={totalNotes}
count={noteCount}
isWaitingToAnchor={isWaitingToAnchorAnnotations}
selected={selectedTab === uiConstants.TAB_NOTES}
type={uiConstants.TAB_NOTES}
......@@ -129,9 +127,9 @@ function SelectionTabs({
>
Page Notes
</Tab>
{totalOrphans > 0 && (
{orphanCount > 0 && (
<Tab
count={totalOrphans}
count={orphanCount}
isWaitingToAnchor={isWaitingToAnchorAnnotations}
selected={selectedTab === uiConstants.TAB_ORPHANS}
type={uiConstants.TAB_ORPHANS}
......@@ -182,20 +180,6 @@ 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,
// Injected services.
settings: propTypes.object.isRequired,
......
......@@ -2,7 +2,7 @@
const events = require('../events');
const isThirdPartyService = require('../util/is-third-party-service');
const tabs = require('../tabs');
const tabs = require('../util/tabs');
// @ngInject
function SidebarContentController(
......@@ -22,19 +22,7 @@ function SidebarContentController(
}
const unsubscribeAnnotationUI = store.subscribe(function() {
const state = store.getState();
self.rootThread = thread();
self.selectedTab = state.selectedTab;
const counts = tabs.counts(state.annotations);
Object.assign(self, {
totalNotes: counts.notes,
totalAnnotations: counts.annotations,
totalOrphans: counts.orphans,
waitingToAnchorAnnotations: counts.anchoring > 0,
});
});
$scope.$on('$destroy', unsubscribeAnnotationUI);
......
......@@ -24,7 +24,7 @@ describe('AnnotationDocumentInfo', () => {
fakeDomainAndTitle = sinon.stub();
fakeMetadata = { domainAndTitle: fakeDomainAndTitle };
AnnotationDocumentInfo.$imports.$mock({
'../annotation-metadata': fakeMetadata,
'../util/annotation-metadata': fakeMetadata,
});
});
......
......@@ -21,11 +21,8 @@ describe('SearchStatusBar', () => {
};
fakeStore = {
getState: sinon.stub(),
selectTab: sinon.stub(),
clearSelectedAnnotations: sinon.stub(),
clearDirectLinkedGroupFetchFailed: sinon.stub(),
clearDirectLinkedIds: sinon.stub(),
clearSelection: sinon.stub(),
annotationCount: sinon.stub().returns(1),
noteCount: sinon.stub().returns(0),
};
SearchStatusBar.$imports.$mock({
......@@ -96,13 +93,11 @@ describe('SearchStatusBar', () => {
});
fakeStore.getState.returns({
filterQuery: 'tag:foo',
});
const wrapper = createComponent({
selectedTab: 'annotation',
totalAnnotations: 3,
totalNotes: 0,
});
fakeStore.annotationCount.returns(3);
const wrapper = createComponent({});
const buttonText = wrapper.find('button').text();
assert.equal(buttonText, 'Clear search');
......@@ -117,14 +112,11 @@ describe('SearchStatusBar', () => {
filterQuery: null,
directLinkedGroupFetchFailed: true,
selectedAnnotationMap: { annId: true },
});
const wrapper = createComponent({
selectedTab: 'annotation',
totalAnnotations: 1,
totalNotes: 0,
});
const wrapper = createComponent({});
const buttonText = wrapper.find('button').text();
assert.equal(buttonText, 'Show all annotations');
});
......@@ -134,14 +126,11 @@ describe('SearchStatusBar', () => {
filterQuery: null,
directLinkedGroupFetchFailed: false,
selectedAnnotationMap: { annId: true },
});
const wrapper = createComponent({
selectedTab: 'annotation',
totalAnnotations: 1,
totalNotes: 0,
});
const wrapper = createComponent({});
const buttonText = wrapper.find('button').text();
assert.equal(buttonText, 'Show all annotations');
});
......@@ -152,13 +141,11 @@ describe('SearchStatusBar', () => {
filterQuery: null,
directLinkedGroupFetchFailed: false,
selectedAnnotationMap: selectedAnnotationMap,
});
const wrapper = createComponent({
selectedTab: 'annotation',
totalAnnotations: 1,
totalNotes: 0,
});
const wrapper = createComponent({});
const buttons = wrapper.find('button');
assert.equal(buttons.length, 0);
});
......@@ -203,13 +190,12 @@ describe('SearchStatusBar', () => {
filterQuery: null,
directLinkedGroupFetchFailed: false,
selectedAnnotationMap: { annId: true },
});
const wrapper = createComponent({
selectedTab: test.selectedTab,
totalAnnotations: test.totalAnnotations,
totalNotes: test.totalNotes,
});
fakeStore.noteCount.returns(test.totalNotes);
fakeStore.annotationCount.returns(test.totalAnnotations);
const wrapper = createComponent({});
const buttonText = wrapper.find('button').text();
assert.equal(buttonText, test.expectedText);
......
......@@ -11,23 +11,15 @@ describe('SelectionTabs', function() {
// mock services
let fakeSession;
let fakeSettings;
let fakeStore;
// default props
const defaultProps = {
isLoading: false,
isWaitingToAnchorAnnotations: false,
selectedTab: uiConstants.TAB_ANNOTATIONS,
totalAnnotations: 123,
totalNotes: 456,
totalOrphans: 0,
};
SelectionTabs.$imports.$mock({
'../store/use-store': callback =>
callback({
clearSelectedAnnotations: sinon.stub(),
selectTab: sinon.stub(),
}),
'../store/use-store': callback => callback(fakeStore),
});
function createComponent(props) {
......@@ -64,6 +56,17 @@ describe('SelectionTabs', function() {
fakeSettings = {
enableExperimentalNewNoteButton: false,
};
fakeStore = {
clearSelectedAnnotations: sinon.stub(),
selectTab: sinon.stub(),
annotationCount: sinon.stub().returns(123),
noteCount: sinon.stub().returns(456),
orphanCount: sinon.stub().returns(0),
isWaitingToAnchorAnnotations: sinon.stub().returns(false),
getState: sinon
.stub()
.returns({ selectedTab: uiConstants.TAB_ANNOTATIONS }),
};
});
const unavailableMessage = wrapper =>
......@@ -98,26 +101,23 @@ describe('SelectionTabs', function() {
});
it('should display notes tab as selected', function() {
const wrapper = createDeepComponent({
selectedTab: uiConstants.TAB_NOTES,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
const wrapper = createDeepComponent({});
const tabs = wrapper.find('a');
assert.isTrue(tabs.at(1).hasClass('is-selected'));
});
it('should display orphans tab as selected if there is 1 or more orphans', function() {
const wrapper = createDeepComponent({
selectedTab: uiConstants.TAB_ORPHANS,
totalOrphans: 1,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_ORPHANS });
fakeStore.orphanCount.returns(1);
const wrapper = createDeepComponent({});
const tabs = wrapper.find('a');
assert.isTrue(tabs.at(2).hasClass('is-selected'));
});
it('should not display orphans tab if there are 0 orphans', function() {
const wrapper = createDeepComponent({
selectedTab: uiConstants.TAB_ORPHANS,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_ORPHANS });
const wrapper = createDeepComponent({});
const tabs = wrapper.find('a');
assert.equal(tabs.length, 2);
});
......@@ -139,51 +139,48 @@ describe('SelectionTabs', function() {
});
it('should not display the new-note-btn when the notes tab is active and the new-note-btn is disabled', function() {
const wrapper = createComponent({
selectedTab: uiConstants.TAB_NOTES,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
const wrapper = createComponent({});
assert.equal(wrapper.find(NewNoteBtn).length, 0);
});
it('should display the new-note-btn when the notes tab is active and the new-note-btn is enabled', function() {
fakeSettings.enableExperimentalNewNoteButton = true;
const wrapper = createComponent({
selectedTab: uiConstants.TAB_NOTES,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
const wrapper = createComponent({});
assert.equal(wrapper.find(NewNoteBtn).length, 1);
});
it('should not display a message when its loading annotation count is 0', function() {
fakeStore.annotationCount.returns(0);
const wrapper = createComponent({
totalAnnotations: 0,
isLoading: true,
});
assert.isFalse(wrapper.exists('.annotation-unavailable-message__label'));
});
it('should not display a message when its loading notes count is 0', function() {
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
fakeStore.noteCount.returns(0);
const wrapper = createComponent({
selectedTab: uiConstants.TAB_NOTES,
totalNotes: 0,
isLoading: true,
});
assert.isFalse(wrapper.exists('.annotation-unavailable-message__label'));
});
it('should not display the longer version of the no annotations message when there are no annotations and isWaitingToAnchorAnnotations is true', function() {
fakeStore.annotationCount.returns(0);
fakeStore.isWaitingToAnchorAnnotations.returns(true);
const wrapper = createComponent({
totalAnnotations: 0,
isWaitingToAnchorAnnotations: true,
isLoading: false,
});
assert.isFalse(wrapper.exists('.annotation-unavailable-message__label'));
});
it('should display the longer version of the no notes message when there are no notes', function() {
const wrapper = createComponent({
selectedTab: uiConstants.TAB_NOTES,
totalNotes: 0,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
fakeStore.noteCount.returns(0);
const wrapper = createComponent({});
assert.include(
unavailableMessage(wrapper),
'There are no page notes in this group.'
......@@ -192,10 +189,9 @@ describe('SelectionTabs', function() {
it('should display the prompt to create a note when there are no notes and enableExperimentalNewNoteButton is true', function() {
fakeSettings.enableExperimentalNewNoteButton = true;
const wrapper = createComponent({
selectedTab: uiConstants.TAB_NOTES,
totalNotes: 0,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
fakeStore.noteCount.returns(0);
const wrapper = createComponent({});
assert.include(
wrapper.find('.annotation-unavailable-message__tutorial').text(),
'Create one by clicking the'
......@@ -208,9 +204,8 @@ describe('SelectionTabs', function() {
});
it('should display the longer version of the no annotations message when there are no annotations', function() {
const wrapper = createComponent({
totalAnnotations: 0,
});
fakeStore.annotationCount.returns(0);
const wrapper = createComponent({});
assert.include(
unavailableMessage(wrapper),
'There are no annotations in this group.'
......@@ -229,10 +224,9 @@ describe('SelectionTabs', function() {
context('when the sidebar tutorial is displayed', function() {
it('should display the shorter version of the no notes message when there are no notes', function() {
fakeSession.state.preferences.show_sidebar_tutorial = true;
const wrapper = createComponent({
totalNotes: 0,
selectedTab: uiConstants.TAB_NOTES,
});
fakeStore.getState.returns({ selectedTab: uiConstants.TAB_NOTES });
fakeStore.noteCount.returns(0);
const wrapper = createComponent({});
const msg = unavailableMessage(wrapper);
......@@ -246,9 +240,8 @@ describe('SelectionTabs', function() {
it('should display the shorter version of the no annotations message when there are no annotations', function() {
fakeSession.state.preferences.show_sidebar_tutorial = true;
const wrapper = createComponent({
totalAnnotations: 0,
});
fakeStore.annotationCount.returns(0);
const wrapper = createComponent({});
const msg = unavailableMessage(wrapper);
......
'use strict';
const events = require('../events');
const metadata = require('../annotation-metadata');
const metadata = require('../util/annotation-metadata');
/**
* Component which displays a virtualized list of annotation threads.
......
......@@ -4,7 +4,7 @@ const debounce = require('lodash.debounce');
const events = require('../events');
const bridgeEvents = require('../../shared/bridge-events');
const metadata = require('../annotation-metadata');
const metadata = require('../util/annotation-metadata');
const uiConstants = require('../ui-constants');
/**
......
......@@ -3,8 +3,8 @@
const buildThread = require('../build-thread');
const events = require('../events');
const memoize = require('../util/memoize');
const metadata = require('../annotation-metadata');
const tabs = require('../tabs');
const metadata = require('../util/annotation-metadata');
const tabs = require('../util/tabs');
const uiConstants = require('../ui-constants');
function truthyKeys(map) {
......
......@@ -5,8 +5,10 @@
'use strict';
const { createSelector } = require('reselect');
const arrayUtil = require('../../util/array-util');
const metadata = require('../../annotation-metadata');
const metadata = require('../../util/annotation-metadata');
const uiConstants = require('../../ui-constants');
const selection = require('./selection');
......@@ -388,6 +390,38 @@ function findAnnotationByID(state, id) {
return findByID(state.annotations, id);
}
/**
* Return the number of page notes.
*/
const noteCount = createSelector(
state => state.annotations,
annotations => arrayUtil.countIf(annotations, metadata.isPageNote)
);
/**
* Returns the number of annotations (as opposed to notes or orphans).
*/
const annotationCount = createSelector(
state => state.annotations,
annotations => arrayUtil.countIf(annotations, metadata.isAnnotation)
);
/**
* Returns the number of orphaned annotations.
*/
const orphanCount = createSelector(
state => state.annotations,
annotations => arrayUtil.countIf(annotations, metadata.isOrphan)
);
/**
* Returns true if some annotations have not been anchored yet.
*/
const isWaitingToAnchorAnnotations = createSelector(
state => state.annotations,
annotations => annotations.some(metadata.isWaitingToAnchor)
);
module.exports = {
init: init,
update: update,
......@@ -403,6 +437,10 @@ module.exports = {
selectors: {
annotationExists,
noteCount,
annotationCount,
orphanCount,
isWaitingToAnchorAnnotations,
findAnnotationByID,
findIDsForTags,
savedAnnotations,
......
......@@ -13,9 +13,10 @@
const { createSelector } = require('reselect');
const immutable = require('seamless-immutable');
const arrayUtil = require('../../util/array-util');
const metadata = require('../../util/annotation-metadata');
const toSet = require('../../util/array-util').toSet;
const uiConstants = require('../../ui-constants');
const tabs = require('../../tabs');
const util = require('../util');
......@@ -162,9 +163,12 @@ const update = {
},
ADD_ANNOTATIONS(state, action) {
const counts = tabs.counts(action.annotations);
const noteCount = arrayUtil.countIf(
action.annotations,
metadata.isPageNote
);
// If there are no annotations at all, ADD_ANNOTATIONS will not be called.
const haveOnlyPageNotes = counts.notes === action.annotations.length;
const haveOnlyPageNotes = noteCount === action.annotations.length;
// If this is the init phase and there are only page notes, select the page notes tab.
if (state.annotations.length === 0 && haveOnlyPageNotes) {
return { selectedTab: uiConstants.TAB_NOTES };
......
......@@ -25,6 +25,68 @@ function createStore() {
// in the tests for the whole Redux store
describe('annotations reducer', function() {
describe('isWaitingToAnchorAnnotations', () => {
it('returns true if there are unanchored annotations', () => {
const unanchored = Object.assign(fixtures.oldAnnotation(), {
$orphan: 'undefined',
});
const state = {
annotations: [unanchored, fixtures.defaultAnnotation()],
};
assert.isTrue(selectors.isWaitingToAnchorAnnotations(state));
});
it('returns false if all annotations are anchored', () => {
const state = {
annotations: [
Object.assign(fixtures.oldPageNote(), { $orphan: false }),
Object.assign(fixtures.defaultAnnotation(), { $orphan: false }),
],
};
assert.isFalse(selectors.isWaitingToAnchorAnnotations(state));
});
});
describe('noteCount', () => {
it('returns number of page notes', () => {
const state = {
annotations: [
fixtures.oldPageNote(),
fixtures.oldAnnotation(),
fixtures.defaultAnnotation(),
],
};
assert.deepEqual(selectors.noteCount(state), 1);
});
});
describe('annotationCount', () => {
it('returns number of annotations', () => {
const state = {
annotations: [
fixtures.oldPageNote(),
fixtures.oldAnnotation(),
fixtures.defaultAnnotation(),
],
};
assert.deepEqual(selectors.annotationCount(state), 2);
});
});
describe('orphanCount', () => {
it('returns number of orphaned annotations', () => {
const orphan = Object.assign(fixtures.oldAnnotation(), { $orphan: true });
const state = {
annotations: [
orphan,
fixtures.oldAnnotation(),
fixtures.defaultAnnotation(),
],
};
assert.deepEqual(selectors.orphanCount(state), 1);
});
});
describe('#savedAnnotations', function() {
const savedAnnotations = selectors.savedAnnotations;
......
......@@ -4,7 +4,7 @@ const immutable = require('seamless-immutable');
const storeFactory = require('../index');
const annotationFixtures = require('../../test/annotation-fixtures');
const metadata = require('../../annotation-metadata');
const metadata = require('../../util/annotation-metadata');
const unroll = require('../../../shared/test/util').unroll;
const uiConstants = require('../../ui-constants');
......
<selection-tabs
ng-if="vm.showSelectedTabs()"
is-waiting-to-anchor-annotations="vm.waitingToAnchorAnnotations"
is-loading="vm.isLoading()"
selected-tab="vm.selectedTab"
total-annotations="vm.totalAnnotations"
total-notes="vm.totalNotes"
total-orphans="vm.totalOrphans">
is-loading="vm.isLoading()">
</selection-tabs>
<search-status-bar
class="search-status-bar"
ng-if="!vm.isLoading()"
selected-tab="vm.selectedTab"
total-annotations="vm.totalAnnotations"
total-notes="vm.totalNotes">
ng-if="!vm.isLoading()">
</search-status-bar>
<!-- Display error message if direct-linked annotation fetch failed. -->
......
'use strict';
const buildThread = require('../build-thread');
const metadata = require('../annotation-metadata');
const metadata = require('../util/annotation-metadata');
// Fixture with two top level annotations, one note and one reply
const SIMPLE_FIXTURE = [
......
'use strict';
// Selectors that calculate the annotation counts displayed in tab headings
// and determine which tab an annotation should be displayed in.
// Functions that determine which tab an annotation should be displayed in.
const countIf = require('./util/array-util').countIf;
const metadata = require('./annotation-metadata');
const uiConstants = require('./ui-constants');
const uiConstants = require('../ui-constants');
/**
* Return the tab in which an annotation should be displayed.
......@@ -37,24 +35,7 @@ function shouldShowInTab(ann, tab) {
return tabForAnnotation(ann) === tab;
}
/**
* Return the counts for the headings of different tabs.
*
* @param {Annotation[]} annotations - List of annotations to display
*/
function counts(annotations) {
const counts = {
notes: countIf(annotations, metadata.isPageNote),
annotations: countIf(annotations, metadata.isAnnotation),
orphans: countIf(annotations, metadata.isOrphan),
anchoring: countIf(annotations, metadata.isWaitingToAnchor),
};
return counts;
}
module.exports = {
counts: counts,
shouldShowInTab: shouldShowInTab,
tabForAnnotation: tabForAnnotation,
};
'use strict';
const annotationMetadata = require('../annotation-metadata');
const fixtures = require('./annotation-fixtures');
const fixtures = require('../../test/annotation-fixtures');
const unroll = require('../../shared/test/util').unroll;
const unroll = require('../../../shared/test/util').unroll;
const documentMetadata = annotationMetadata.documentMetadata;
const domainAndTitle = annotationMetadata.domainAndTitle;
......
'use strict';
const fixtures = require('./annotation-fixtures');
const uiConstants = require('../ui-constants');
const fixtures = require('../../test/annotation-fixtures');
const uiConstants = require('../../ui-constants');
const tabs = require('../tabs');
const unroll = require('../../shared/test/util').unroll;
const unroll = require('../../../shared/test/util').unroll;
describe('tabs', function() {
describe('tabForAnnotation', function() {
......@@ -83,22 +83,4 @@ describe('tabs', function() {
]
);
});
describe('counts', function() {
const annotation = Object.assign(fixtures.defaultAnnotation(), {
$orphan: false,
});
const orphan = Object.assign(fixtures.defaultAnnotation(), {
$orphan: true,
});
it('counts Annotations and Orphans separately', function() {
assert.deepEqual(tabs.counts([annotation, orphan], true), {
anchoring: 0,
annotations: 1,
notes: 0,
orphans: 1,
});
});
});
});
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