Unverified Commit b0dfce31 authored by Hannah Stepanek's avatar Hannah Stepanek Committed by GitHub

Merge pull request #1254 from hypothesis/convert-search-status-bar

Convert search status bar to preact
parents 30d4004e cdd54488
'use strict'; 'use strict';
const memoize = require('../util/memoize'); const { Fragment, createElement } = require('preact');
const propTypes = require('prop-types');
const { useMemo } = require('preact/hooks');
const { withServices } = require('../util/service-context');
const uiConstants = require('../ui-constants'); const uiConstants = require('../ui-constants');
const useStore = require('../store/use-store');
// @ngInject const countVisibleAnns = annThread => {
function SearchStatusBarController(store, rootThread) { return annThread.children.reduce(
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) { function(count, child) {
return count + visibleCount(child); return count + countVisibleAnns(child);
}, },
thread.visible ? 1 : 0 annThread.visible ? 1 : 0
); );
}); };
/**
* A bar where the user can clear a selection or search and see whether
* any search results were found.
* */
function SearchStatusBar({
selectedTab,
totalAnnotations,
totalNotes,
rootThread,
}) {
const storeState = useStore(store => store.getState());
const clearSelection = useStore(store => store.clearSelection);
const filterQuery = storeState.filterQuery;
const filterActive = !!storeState.filterQuery;
this.filterMatchCount = function() { const thread = rootThread.thread(storeState);
return visibleCount(thread());
const visibleCount = useMemo(() => {
return countVisibleAnns(thread);
}, [thread]);
const filterResults = () => {
const resultsCount = visibleCount;
switch (resultsCount) {
case 0:
return 'No results for "' + filterQuery + '"';
case 1:
return '1 search result';
default:
return resultsCount + ' search results';
}
}; };
this.areAllAnnotationsVisible = function() { const areNotAllAnnotationsVisible = () => {
if (store.getState().directLinkedGroupFetchFailed) { if (storeState.directLinkedGroupFetchFailed) {
return true; return true;
} }
const selection = store.getState().selectedAnnotationMap; const selection = storeState.selectedAnnotationMap;
if (!selection) { if (!selection) {
return false; return false;
} }
return Object.keys(selection).length > 0; return Object.keys(selection).length > 0;
}; };
this.filterQuery = function() { return (
return store.getState().filterQuery; <div>
}; {filterActive && (
<div className="search-status-bar">
this.filterActive = function() { <button
return !!store.getState().filterQuery; className="primary-action-btn primary-action-btn--short"
}; onClick={clearSelection}
title="Clear the search filter and show all annotations"
this.onClearSelection = function() { >
store.clearSelection(); <i className="primary-action-btn__icon h-icon-close" />
}; Clear search
</button>
<span>{filterResults()}</span>
</div>
)}
{!filterActive && areNotAllAnnotationsVisible() && (
<div className="search-status-bar">
<button
className="primary-action-btn primary-action-btn--short"
onClick={clearSelection}
title="Clear the selection and show all annotations"
>
{selectedTab === uiConstants.TAB_ORPHANS && (
<Fragment>Show all annotations and notes</Fragment>
)}
{selectedTab === uiConstants.TAB_ANNOTATIONS && (
<Fragment>
Show all annotations
{totalAnnotations > 1 && <span> ({totalAnnotations})</span>}
</Fragment>
)}
{selectedTab === uiConstants.TAB_NOTES && (
<Fragment>
Show all notes
{totalNotes > 1 && <span> ({totalNotes})</span>}
</Fragment>
)}
</button>
</div>
)}
</div>
);
} }
module.exports = { SearchStatusBar.propTypes = {
controller: SearchStatusBarController, selectedTab: propTypes.oneOf([
controllerAs: 'vm', uiConstants.TAB_ANNOTATIONS,
bindings: { uiConstants.TAB_ORPHANS,
selectedTab: '<', uiConstants.TAB_NOTES,
totalAnnotations: '<', ]).isRequired,
totalNotes: '<', totalAnnotations: propTypes.number.isRequired,
}, totalNotes: propTypes.number.isRequired,
template: require('../templates/search-status-bar.html'), rootThread: propTypes.object.isRequired,
}; };
SearchStatusBar.injectedProps = ['rootThread'];
module.exports = withServices(SearchStatusBar);
...@@ -181,7 +181,10 @@ function startAngularApp(config) { ...@@ -181,7 +181,10 @@ function startAngularApp(config) {
wrapReactComponent(require('./components/moderation-banner')) wrapReactComponent(require('./components/moderation-banner'))
) )
.component('newNoteBtn', require('./components/new-note-btn')) .component('newNoteBtn', require('./components/new-note-btn'))
.component('searchStatusBar', require('./components/search-status-bar')) .component(
'searchStatusBar',
wrapReactComponent(require('./components/search-status-bar'))
)
.component('selectionTabs', require('./components/selection-tabs')) .component('selectionTabs', require('./components/selection-tabs'))
.component('sidebarContent', require('./components/sidebar-content')) .component('sidebarContent', require('./components/sidebar-content'))
.component( .component(
......
<div class="search-status-bar" ng-if="vm.filterActive()">
<button class="primary-action-btn primary-action-btn--short"
ng-click="vm.onClearSelection()"
title="Clear the search filter and show all annotations"
>
<i class="primary-action-btn__icon h-icon-close"></i> Clear search
</button>
<span ng-pluralize
count="vm.filterMatchCount()"
when="{'0': 'No results for “{{vm.filterQuery()}}”',
'one': '1 search result',
'other': '{} search results'}"></span>
</div>
<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">
<span ng-if="!vm.selectedTab || vm.selectedTab === vm.TAB_ORPHANS">
Show all annotations and notes
</span>
<span ng-if="vm.selectedTab === vm.TAB_ANNOTATIONS">
Show all annotations
<span ng-if="vm.totalAnnotations > 1">
({{vm.totalAnnotations}})
</span>
</span>
<span ng-if="vm.selectedTab === vm.TAB_NOTES">
Show all notes
<span ng-if="vm.totalNotes > 1">
({{vm.totalNotes}})
</span>
</span>
</button>
</div>
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
</selection-tabs> </selection-tabs>
<search-status-bar <search-status-bar
ng-show="!vm.isLoading()" class="search-status-bar"
ng-if="!vm.isLoading()"
selected-tab="vm.selectedTab" selected-tab="vm.selectedTab"
total-annotations="vm.totalAnnotations" total-annotations="vm.totalAnnotations"
total-notes="vm.totalNotes"> 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