Commit 8977ca5f authored by Robert Knight's avatar Robert Knight

Simplify tab counts calculation and move into a separate module

Refactor some repetition in the functions that produced the counts for
the Annotations, Page Notes and Orphans tabs and extract it into a
separate module where it is easier to test.

Moving this into a single function also makes it easier to memoize
later, so we can avoid recalculating it when the list of annotations has
not changed between two app states.
parent 384676df
'use strict';
var metadata = require('./annotation-metadata');
function countIf(list, predicate) {
return list.reduce(function (count, item) {
return predicate(item) ? count + 1 : count;
}, 0);
}
/**
* Return a count of the number of Annotations, Page Notes, Orphans and
* annotations still being anchored in a set of `annotations`
*/
function tabCounts(annotations, opts) {
opts = opts || {separateOrphans: false};
var counts = {
notes: countIf(annotations, metadata.isPageNote),
annotations: countIf(annotations, metadata.isAnnotation),
orphans: countIf(annotations, metadata.isOrphan),
anchoring: countIf(annotations, metadata.isWaitingToAnchor),
};
if (opts.separateOrphans) {
return counts;
} else {
return Object.assign({}, counts, {
annotations: counts.annotations + counts.orphans,
orphans: 0,
});
}
}
module.exports = tabCounts;
'use strict';
var fixtures = require('./annotation-fixtures');
var tabCounts = require('../tab-counts');
describe('tabCounts', function () {
var annotation = Object.assign(fixtures.defaultAnnotation(), {$orphan:false});
var orphan = Object.assign(fixtures.defaultAnnotation(), {$orphan:true});
it('counts Annotations and Orphans together when the Orphans tab is not enabled', function () {
assert.deepEqual(tabCounts([annotation, orphan]), {
anchoring: 0,
annotations: 2,
notes: 0,
orphans: 0,
});
});
it('counts Annotations and Orphans separately when the Orphans tab is enabled', function () {
assert.deepEqual(tabCounts([annotation, orphan], {separateOrphans: true}), {
anchoring: 0,
annotations: 1,
notes: 0,
orphans: 1,
});
});
});
...@@ -5,6 +5,7 @@ var events = require('./events'); ...@@ -5,6 +5,7 @@ var events = require('./events');
var memoize = require('./util/memoize'); var memoize = require('./util/memoize');
var metadata = require('./annotation-metadata'); var metadata = require('./annotation-metadata');
var scopeTimeout = require('./util/scope-timeout'); var scopeTimeout = require('./util/scope-timeout');
var tabCounts = require('./tab-counts');
var uiConstants = require('./ui-constants'); var uiConstants = require('./ui-constants');
function firstKey(object) { function firstKey(object) {
...@@ -38,48 +39,6 @@ module.exports = function WidgetController( ...@@ -38,48 +39,6 @@ module.exports = function WidgetController(
features, groups, rootThread, settings, streamer, streamFilter, store, features, groups, rootThread, settings, streamer, streamFilter, store,
VirtualThreadList VirtualThreadList
) { ) {
/**
* Returns the number of annotations which are not yet anchored.
*/
function countWaitingToAnchorAnnotations (annotations) {
var total = annotations.reduce(function (count, annotation) {
return annotation && metadata.isWaitingToAnchor(annotation) ? count + 1 : count;
}, 0);
return total;
}
/**
* Returns the number of top level annotations which are unanchored i.e orphans.
*/
function countOrphans(annotations) {
var total = annotations.reduce(function (count, annotation) {
return annotation && metadata.isOrphan(annotation) ? count + 1 : count;
}, 0);
return total;
}
/**
* Returns the number of top level annotations which are of type annotations
* and not notes or replies.
*/
function countAnnotations(annotations) {
var total = annotations.reduce(function (count, annotation) {
return annotation && metadata.isAnnotation(annotation) ? count + 1 : count;
}, 0);
return total;
}
/**
* Returns the number of top level annotations which are of type notes.
*/
function countNotes(annotations) {
var total = annotations.reduce(function (count, annotation) {
return annotation && metadata.isPageNote(annotation) ? count + 1 : count;
}, 0);
return total;
}
/** /**
* Returns the height of the thread for an annotation if it exists in the view * Returns the height of the thread for an annotation if it exists in the view
* or undefined otherwise. * or undefined otherwise.
...@@ -114,19 +73,21 @@ module.exports = function WidgetController( ...@@ -114,19 +73,21 @@ module.exports = function WidgetController(
// to reserve space for threads which are not actually rendered. // to reserve space for threads which are not actually rendered.
var visibleThreads = new VirtualThreadList($scope, window, thread()); var visibleThreads = new VirtualThreadList($scope, window, thread());
var unsubscribeAnnotationUI = annotationUI.subscribe(function () { var unsubscribeAnnotationUI = annotationUI.subscribe(function () {
visibleThreads.setRootThread(thread()); var state = annotationUI.getState();
$scope.selectedTab = annotationUI.getState().selectedTab;
$scope.waitingToAnchorAnnotations = countWaitingToAnchorAnnotations(annotationUI.getState().annotations) > 0; visibleThreads.setRootThread(thread());
$scope.selectedTab = state.selectedTab;
$scope.totalNotes = countNotes(annotationUI.getState().annotations); var counts = tabCounts(state.annotations, {
$scope.totalOrphans = countOrphans(annotationUI.getState().annotations); separateOrphans: features.flagEnabled('orphans_tab'),
});
if (!features.flagEnabled('orphans_tab')) { Object.assign($scope, {
$scope.totalAnnotations = $scope.totalAnnotations + $scope.totalOrphans; totalNotes: counts.notes,
} else { totalAnnotations: counts.annotations,
$scope.totalAnnotations = countAnnotations(annotationUI.getState().annotations); totalOrphans: counts.orphans,
} waitingToAnchorAnnotations: counts.anchoring > 0,
});
}); });
$scope.$on('$destroy', unsubscribeAnnotationUI); $scope.$on('$destroy', unsubscribeAnnotationUI);
......
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