Unverified Commit b22b7a3e authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #1161 from hypothesis/move-search-bar-funcs-to-search-bar

Move sidebar-content funcs to search-status-bar
parents 0198d32b cda20580
'use strict';
const memoize = require('../util/memoize');
const uiConstants = require('../ui-constants');
module.exports = {
controllerAs: 'vm',
controller: function() {
// @ngInject
function SearchStatusBarController(store, rootThread) {
this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS;
this.TAB_NOTES = uiConstants.TAB_NOTES;
this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
const thread = () => {
return rootThread.thread(store.getState());
};
const visibleCount = memoize(thread => {
return thread.children.reduce(
function(count, child) {
return count + visibleCount(child);
},
thread.visible ? 1 : 0
);
});
this.filterMatchCount = function() {
return visibleCount(thread());
};
this.areAllAnnotationsVisible = function() {
if (store.getState().directLinkedGroupFetchFailed) {
return true;
}
const selection = store.getState().selectedAnnotationMap;
if (!selection) {
return false;
}
return Object.keys(selection).length > 0;
};
}
module.exports = {
controller: SearchStatusBarController,
controllerAs: 'vm',
bindings: {
filterActive: '<',
filterMatchCount: '<',
onClearSelection: '&',
searchQuery: '<',
selectedTab: '<',
// Boolean indicating all annotations are visible (none are hidden).
areAllAnnotationsVisible: '<',
totalAnnotations: '<',
totalNotes: '<',
},
......
......@@ -3,7 +3,6 @@
const SearchClient = require('../search-client');
const events = require('../events');
const isThirdPartyService = require('../util/is-third-party-service');
const memoize = require('../util/memoize');
const tabs = require('../tabs');
const uiConstants = require('../ui-constants');
......@@ -279,17 +278,6 @@ function SidebarContentController(
this.focus = focusAnnotation;
this.scrollTo = scrollToAnnotation;
this.areAllAnnotationsVisible = function() {
if (store.getState().directLinkedGroupFetchFailed) {
return true;
}
const selection = store.getState().selectedAnnotationMap;
if (!selection) {
return false;
}
return Object.keys(selection).length > 0;
};
this.selectedGroupUnavailable = function() {
return !this.isLoading() && store.getState().directLinkedGroupFetchFailed;
};
......@@ -328,23 +316,6 @@ function SidebarContentController(
);
};
const visibleCount = memoize(function(thread) {
return thread.children.reduce(
function(count, child) {
return count + visibleCount(child);
},
thread.visible ? 1 : 0
);
});
this.visibleCount = function() {
return visibleCount(thread());
};
this.topLevelThreadCount = function() {
return thread().totalChildren;
};
this.clearSelection = function() {
let selectedTab = store.getState().selectedTab;
if (
......
......@@ -4,33 +4,138 @@ const angular = require('angular');
const util = require('../../directive/test/util');
describe('searchStatusBar', function() {
before(function() {
describe('searchStatusBar', () => {
before(() => {
angular
.module('app', [])
.component('searchStatusBar', require('../search-status-bar'));
});
beforeEach(function() {
angular.mock.module('app');
let fakeRootThread;
let fakeStore;
beforeEach(() => {
fakeRootThread = {
thread: sinon.stub(),
};
fakeStore = {
getState: sinon.stub(),
selectTab: sinon.stub(),
clearSelectedAnnotations: sinon.stub(),
clearDirectLinkedGroupFetchFailed: sinon.stub(),
clearDirectLinkedIds: sinon.stub(),
};
angular.mock.module('app', {
store: fakeStore,
rootThread: fakeRootThread,
});
});
describe('filterMatchCount', () => {
it('returns the total number of visible annotations or replies', () => {
fakeRootThread.thread.returns({
children: [
{
id: '1',
visible: true,
children: [{ id: '3', visible: true, children: [] }],
},
{
id: '2',
visible: false,
children: [],
},
],
});
context('when there is a filter', function() {
it('should display the filter count', function() {
const elem = util.createDirective(document, 'searchStatusBar', {
filterActive: true,
filterMatchCount: 5,
});
assert.include(elem[0].textContent, '5 search results');
const ctrl = elem.ctrl;
assert.equal(ctrl.filterMatchCount(), 2);
});
});
describe('areAllAnnotationsVisible', () => {
it('returns true if the direct-linked group fetch failed', () => {
fakeStore.getState.returns({ directLinkedGroupFetchFailed: true });
const elem = util.createDirective(document, 'searchStatusBar', {});
const ctrl = elem.ctrl;
assert.isTrue(ctrl.areAllAnnotationsVisible());
});
it('returns true if there are annotations selected', () => {
fakeStore.getState.returns({
directLinkedGroupFetchFailed: false,
selectedAnnotationMap: { ann: true },
});
const elem = util.createDirective(document, 'searchStatusBar', {});
const ctrl = elem.ctrl;
assert.isTrue(ctrl.areAllAnnotationsVisible());
});
context('when there is a selection', function() {
it('should display the "Show all annotations (2)" message when there are 2 annotations', function() {
it('returns false if there are no annotations selected', () => {
fakeStore.getState.returns({
directLinkedGroupFetchFailed: false,
selectedAnnotationMap: {},
});
const elem = util.createDirective(document, 'searchStatusBar', {});
const ctrl = elem.ctrl;
assert.isFalse(ctrl.areAllAnnotationsVisible());
});
it('returns false if the `selectedAnnotationMap` is null', () => {
fakeStore.getState.returns({
directLinkedGroupFetchFailed: false,
selectedAnnotationMap: null,
});
const elem = util.createDirective(document, 'searchStatusBar', {});
const ctrl = elem.ctrl;
assert.isFalse(ctrl.areAllAnnotationsVisible());
});
});
context('when there is a filter', () => {
it('should display the filter count', () => {
fakeRootThread.thread.returns({
children: [
{
id: '1',
visible: true,
children: [{ id: '3', visible: true, children: [] }],
},
{
id: '2',
visible: false,
children: [],
},
],
});
const elem = util.createDirective(document, 'searchStatusBar', {
filterActive: true,
});
assert.include(elem[0].textContent, '2 search results');
});
});
context('when there is a selection', () => {
it('should display the "Show all annotations (2)" message when there are 2 annotations', () => {
const msg = 'Show all annotations';
const msgCount = '(2)';
fakeStore.getState.returns({
selectedAnnotationMap: { ann1: true },
});
const elem = util.createDirective(document, 'searchStatusBar', {
areAllAnnotationsVisible: true,
totalAnnotations: 2,
selectedTab: 'annotation',
});
......@@ -39,11 +144,13 @@ describe('searchStatusBar', function() {
assert.include(clearBtn.textContent, msgCount);
});
it('should display the "Show all notes (3)" message when there are 3 notes', function() {
it('should display the "Show all notes (3)" message when there are 3 notes', () => {
const msg = 'Show all notes';
const msgCount = '(3)';
fakeStore.getState.returns({
selectedAnnotationMap: { ann1: true },
});
const elem = util.createDirective(document, 'searchStatusBar', {
areAllAnnotationsVisible: true,
totalNotes: 3,
selectedTab: 'note',
});
......
......@@ -363,10 +363,6 @@ describe('sidebar.components.sidebar-content', function() {
});
});
it('areAllAnnotationsVisible returns true since there is an error message', () => {
assert.isTrue(ctrl.areAllAnnotationsVisible());
});
it('selectedGroupUnavailable returns true', () => {
assert.isTrue(ctrl.selectedGroupUnavailable());
});
......@@ -382,10 +378,6 @@ describe('sidebar.components.sidebar-content', function() {
$scope.$digest();
});
it('areAllAnnotationsVisible returns false since group has no annotations', () => {
assert.isFalse(ctrl.areAllAnnotationsVisible());
});
it('selectedGroupUnavailable returns false', () => {
assert.isFalse(ctrl.selectedGroupUnavailable());
});
......@@ -408,10 +400,6 @@ describe('sidebar.components.sidebar-content', function() {
$scope.$digest();
});
it('areAllAnnotationsVisible is true', function() {
assert.isTrue(ctrl.areAllAnnotationsVisible());
});
it("switches to the selected annotation's group", function() {
assert.calledWith(fakeGroups.focus, '__world__');
assert.calledOnce(fakeAnnotationMapper.loadAnnotations);
......@@ -438,10 +426,6 @@ describe('sidebar.components.sidebar-content', function() {
$scope.$digest();
});
it('areAllAnnotationsVisible is false', function() {
assert.isFalse(ctrl.areAllAnnotationsVisible());
});
it('fetches annotations for the current group', function() {
assert.calledWith(searchClients[0].get, {
uri: [uri],
......@@ -716,25 +700,4 @@ describe('sidebar.components.sidebar-content', function() {
});
});
});
describe('#visibleCount', function() {
it('returns the total number of visible annotations or replies', function() {
fakeRootThread.thread.returns({
children: [
{
id: '1',
visible: true,
children: [{ id: '3', visible: true, children: [] }],
},
{
id: '2',
visible: false,
children: [],
},
],
});
$scope.$digest();
assert.equal(ctrl.visibleCount(), 2);
});
});
});
......@@ -6,12 +6,12 @@
<i class="primary-action-btn__icon h-icon-close"></i> Clear search
</button>
<span ng-pluralize
count="vm.filterMatchCount"
count="vm.filterMatchCount()"
when="{'0': 'No results for “{{vm.searchQuery}}”',
'one': '1 search result',
'other': '{} search results'}"></span>
</div>
<div class="search-status-bar" ng-if="!vm.filterActive && vm.areAllAnnotationsVisible">
<div class="search-status-bar" ng-if="!vm.filterActive && vm.areAllAnnotationsVisible()">
<button class="primary-action-btn primary-action-btn--short"
ng-click="vm.onClearSelection()"
title="Clear the selection and show all annotations">
......
......@@ -11,11 +11,8 @@
<search-status-bar
ng-show="!vm.isLoading()"
filter-active="!!vm.search.query()"
filter-match-count="vm.visibleCount()"
on-clear-selection="vm.clearSelection()"
search-query="vm.search.query()"
are-all-annotations-visible="vm.areAllAnnotationsVisible()"
total-count="vm.topLevelThreadCount()"
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