Commit c01bc2b3 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Address tech debt in `selection` pertaining to tabs and sort options

- Remove logic yanking user away from orphans tab when clearing a
  selection
- Make sure all `selection` module actions use `setTab` when changing
  tab value
- Simplify tab constants
- Remove `sortKeysAvailable` from state and add selector instead
parent 5a9f32ee
...@@ -17,9 +17,7 @@ export default function SortMenu() { ...@@ -17,9 +17,7 @@ export default function SortMenu() {
const sortKey = useStore(store => store.getState().selection.sortKey); const sortKey = useStore(store => store.getState().selection.sortKey);
// All available sorting options. These change depending on current // All available sorting options. These change depending on current
// "tab" or context. // "tab" or context.
const sortKeysAvailable = useStore( const sortKeysAvailable = useStore(store => store.sortKeys());
store => store.getState().selection.sortKeysAvailable
);
const menuItems = sortKeysAvailable.map(sortOption => { const menuItems = sortKeysAvailable.map(sortOption => {
return ( return (
......
...@@ -18,12 +18,12 @@ describe('SortMenu', () => { ...@@ -18,12 +18,12 @@ describe('SortMenu', () => {
fakeState = { fakeState = {
selection: { selection: {
sortKey: 'Location', sortKey: 'Location',
sortKeysAvailable: ['Newest', 'Oldest', 'Location'],
}, },
}; };
fakeStore = { fakeStore = {
setSortKey: sinon.stub(), setSortKey: sinon.stub(),
getState: sinon.stub().returns(fakeState), getState: sinon.stub().returns(fakeState),
sortKeys: sinon.stub().returns(['Newest', 'Oldest', 'Location']),
}; };
$imports.$mock(mockImportedComponents()); $imports.$mock(mockImportedComponents());
...@@ -41,8 +41,8 @@ describe('SortMenu', () => { ...@@ -41,8 +41,8 @@ describe('SortMenu', () => {
const menuItems = wrapper.find('MenuItem'); const menuItems = wrapper.find('MenuItem');
assert.lengthOf(menuItems, fakeState.selection.sortKeysAvailable.length); assert.lengthOf(menuItems, fakeStore.sortKeys().length);
fakeState.selection.sortKeysAvailable.forEach(sortKey => { fakeStore.sortKeys().forEach(sortKey => {
assert.lengthOf( assert.lengthOf(
menuItems.filterWhere(menuItem => menuItem.prop('label') === sortKey), menuItems.filterWhere(menuItem => menuItem.prop('label') === sortKey),
1 1
......
...@@ -43,8 +43,6 @@ describe('rootThread', function () { ...@@ -43,8 +43,6 @@ describe('rootThread', function () {
selection: { selection: {
filterQuery: null, filterQuery: null,
highlighted: [], highlighted: [],
sortKey: 'Location',
sortKeysAvailable: ['Location'],
}, },
route: { route: {
name: 'sidebar', name: 'sidebar',
...@@ -214,7 +212,6 @@ describe('rootThread', function () { ...@@ -214,7 +212,6 @@ describe('rootThread', function () {
it(`sort order is correct when sorting by ${testCase.order}`, () => { it(`sort order is correct when sorting by ${testCase.order}`, () => {
fakeBuildThread.reset(); fakeBuildThread.reset();
fakeStore.state.selection.sortKey = testCase.order; fakeStore.state.selection.sortKey = testCase.order;
fakeStore.state.selection.sortKeysAvailable = [testCase.order];
rootThread.thread(fakeStore.state); rootThread.thread(fakeStore.state);
const sortCompareFn = fakeBuildThread.args[0][1].sortCompareFn; const sortCompareFn = fakeBuildThread.args[0][1].sortCompareFn;
......
...@@ -16,34 +16,14 @@ import * as metadata from '../../util/annotation-metadata'; ...@@ -16,34 +16,14 @@ import * as metadata from '../../util/annotation-metadata';
import { countIf } from '../../util/array'; import { countIf } from '../../util/array';
import * as util from '../util'; import * as util from '../util';
/**
* Default starting tab.
*/
const TAB_DEFAULT = uiConstants.TAB_ANNOTATIONS;
/** /**
* Default sort keys for each tab. * Default sort keys for each tab.
*/ */
const TAB_SORTKEY_DEFAULT = {}; const TAB_SORTKEY_DEFAULT = {
TAB_SORTKEY_DEFAULT[uiConstants.TAB_ANNOTATIONS] = 'Location'; [uiConstants.TAB_ANNOTATIONS]: 'Location',
TAB_SORTKEY_DEFAULT[uiConstants.TAB_NOTES] = 'Oldest'; [uiConstants.TAB_NOTES]: 'Oldest',
TAB_SORTKEY_DEFAULT[uiConstants.TAB_ORPHANS] = 'Location'; [uiConstants.TAB_ORPHANS]: 'Location',
};
/**
* Available sort keys for each tab.
*/
const TAB_SORTKEYS_AVAILABLE = {};
TAB_SORTKEYS_AVAILABLE[uiConstants.TAB_ANNOTATIONS] = [
'Newest',
'Oldest',
'Location',
];
TAB_SORTKEYS_AVAILABLE[uiConstants.TAB_NOTES] = ['Newest', 'Oldest'];
TAB_SORTKEYS_AVAILABLE[uiConstants.TAB_ORPHANS] = [
'Newest',
'Oldest',
'Location',
];
/** /**
* Utility function that returns all of the properties of an object whose * Utility function that returns all of the properties of an object whose
...@@ -80,29 +60,6 @@ function initialSelection(settings) { ...@@ -80,29 +60,6 @@ function initialSelection(settings) {
return selection; return selection;
} }
const setTab = (selectedTab, newTab) => {
// Do nothing if the "new tab" is not a valid tab.
if (
[
uiConstants.TAB_ANNOTATIONS,
uiConstants.TAB_NOTES,
uiConstants.TAB_ORPHANS,
].indexOf(newTab) === -1
) {
return {};
}
// Shortcut if the tab is already correct, to avoid resetting the sortKey
// unnecessarily.
if (selectedTab === newTab) {
return {};
}
return {
selectedTab: newTab,
sortKey: TAB_SORTKEY_DEFAULT[newTab],
sortKeysAvailable: TAB_SORTKEYS_AVAILABLE[newTab],
};
};
function init(settings) { function init(settings) {
return { return {
/** /**
...@@ -138,7 +95,6 @@ function init(settings) { ...@@ -138,7 +95,6 @@ function init(settings) {
highlighted: {}, highlighted: {},
filterQuery: settings.query || null, filterQuery: settings.query || null,
selectedTab: TAB_DEFAULT,
focusMode: { focusMode: {
enabled: settings.hasOwnProperty('focus'), enabled: settings.hasOwnProperty('focus'),
focused: true, focused: true,
...@@ -146,25 +102,30 @@ function init(settings) { ...@@ -146,25 +102,30 @@ function init(settings) {
config: { ...(settings.focus ? settings.focus : {}) }, config: { ...(settings.focus ? settings.focus : {}) },
}, },
selectedTab: uiConstants.TAB_ANNOTATIONS,
// Key by which annotations are currently sorted. // Key by which annotations are currently sorted.
sortKey: TAB_SORTKEY_DEFAULT[TAB_DEFAULT], sortKey: TAB_SORTKEY_DEFAULT[uiConstants.TAB_ANNOTATIONS],
// Keys by which annotations can be sorted.
sortKeysAvailable: TAB_SORTKEYS_AVAILABLE[TAB_DEFAULT],
}; };
} }
const update = { const setTab = (newTab, oldTab) => {
CLEAR_SELECTION: function (state) { // Do nothing if the "new tab" is not a valid tab or is the same as the
let selectedTab = state.selectedTab; // tab already selected. This will avoid resetting the `sortKey`, too.
if (selectedTab === uiConstants.TAB_ORPHANS) { if (!uiConstants.TABS.includes(newTab) || oldTab === newTab) {
selectedTab = uiConstants.TAB_ANNOTATIONS; return {};
} }
const tabSettings = setTab(state.selectedTab, selectedTab); return {
selectedTab: newTab,
sortKey: TAB_SORTKEY_DEFAULT[newTab],
};
};
const update = {
CLEAR_SELECTION: function () {
return { return {
filterQuery: null, filterQuery: null,
forcedVisible: {}, forcedVisible: {},
selected: {}, selected: {},
...tabSettings,
}; };
}, },
...@@ -235,7 +196,7 @@ const update = { ...@@ -235,7 +196,7 @@ const update = {
}, },
SELECT_TAB: function (state, action) { SELECT_TAB: function (state, action) {
return setTab(state.selectedTab, action.tab); return setTab(action.tab, state.selectedTab);
}, },
/** /**
...@@ -251,7 +212,7 @@ const update = { ...@@ -251,7 +212,7 @@ const update = {
const haveOnlyPageNotes = noteCount === topLevelAnnotations.length; const haveOnlyPageNotes = noteCount === topLevelAnnotations.length;
if (action.currentAnnotationCount === 0 && haveOnlyPageNotes) { if (action.currentAnnotationCount === 0 && haveOnlyPageNotes) {
return { selectedTab: uiConstants.TAB_NOTES }; return setTab(uiConstants.TAB_NOTES, state.selectedTab);
} }
return {}; return {};
}, },
...@@ -263,16 +224,18 @@ const update = { ...@@ -263,16 +224,18 @@ const update = {
delete selection[annotation.id]; delete selection[annotation.id];
} }
}); });
let selectedTab = state.selectedTab; let newTab = state.selectedTab;
// If the orphans tab is selected but no remaining annotations are orphans,
// switch back to annotations tab
if ( if (
selectedTab === uiConstants.TAB_ORPHANS && newTab === uiConstants.TAB_ORPHANS &&
countIf(action.remainingAnnotations, metadata.isOrphan) === 0 countIf(action.remainingAnnotations, metadata.isOrphan) === 0
) { ) {
selectedTab = uiConstants.TAB_ANNOTATIONS; newTab = uiConstants.TAB_ANNOTATIONS;
} }
return { return {
...setTab(newTab, state.selectedTab),
selected: selection, selected: selection,
selectedTab: selectedTab,
}; };
}, },
...@@ -379,11 +342,15 @@ function highlightAnnotations(ids) { ...@@ -379,11 +342,15 @@ function highlightAnnotations(ids) {
}; };
} }
/** Set the type annotations to be displayed. */ /**
function selectTab(type) { * Set the currently-selected tab to `tabKey`.
*
* @param {'annotation'|'note'|'orphan'} tabKey
*/
function selectTab(tabKey) {
return { return {
type: actions.SELECT_TAB, type: actions.SELECT_TAB,
tab: type, tab: tabKey,
}; };
} }
...@@ -586,6 +553,20 @@ const selectedAnnotations = createSelector( ...@@ -586,6 +553,20 @@ const selectedAnnotations = createSelector(
selection => trueKeys(selection) selection => trueKeys(selection)
); );
/**
* Retrieve applicable sort options for the currently-selected tab.
*
* @return {string[]}
*/
function sortKeys(state) {
const sortKeysForTab = ['Newest', 'Oldest'];
if (state.selection.selectedTab !== uiConstants.TAB_NOTES) {
// Location is inapplicable to Notes tab
sortKeysForTab.push('Location');
}
return sortKeysForTab;
}
export default { export default {
init: init, init: init,
namespace: 'selection', namespace: 'selection',
...@@ -622,5 +603,6 @@ export default { ...@@ -622,5 +603,6 @@ export default {
hasAppliedFilter, hasAppliedFilter,
hasSelectedAnnotations, hasSelectedAnnotations,
selectedAnnotations, selectedAnnotations,
sortKeys,
}, },
}; };
...@@ -423,28 +423,17 @@ describe('sidebar/store/modules/selection', () => { ...@@ -423,28 +423,17 @@ describe('sidebar/store/modules/selection', () => {
it('allows sorting annotations by time and document location', function () { it('allows sorting annotations by time and document location', function () {
store.selectTab(uiConstants.TAB_ANNOTATIONS); store.selectTab(uiConstants.TAB_ANNOTATIONS);
assert.deepEqual(getSelectionState().sortKeysAvailable, [ assert.deepEqual(store.sortKeys(), ['Newest', 'Oldest', 'Location']);
'Newest',
'Oldest',
'Location',
]);
}); });
it('allows sorting page notes by time', function () { it('allows sorting page notes by time', function () {
store.selectTab(uiConstants.TAB_NOTES); store.selectTab(uiConstants.TAB_NOTES);
assert.deepEqual(getSelectionState().sortKeysAvailable, [ assert.deepEqual(store.sortKeys(), ['Newest', 'Oldest']);
'Newest',
'Oldest',
]);
}); });
it('allows sorting orphans by time and document location', function () { it('allows sorting orphans by time and document location', function () {
store.selectTab(uiConstants.TAB_ORPHANS); store.selectTab(uiConstants.TAB_ORPHANS);
assert.deepEqual(getSelectionState().sortKeysAvailable, [ assert.deepEqual(store.sortKeys(), ['Newest', 'Oldest', 'Location']);
'Newest',
'Oldest',
'Location',
]);
}); });
it('sorts annotations by document location by default', function () { it('sorts annotations by document location by default', function () {
......
...@@ -87,25 +87,6 @@ describe('store', function () { ...@@ -87,25 +87,6 @@ describe('store', function () {
assert.equal(store.getState().selection.sortKey, 'Location'); assert.equal(store.getState().selection.sortKey, 'Location');
}); });
it('sets `sortKeysAvailable` to available annotation sort keys if set to Orphans', () => {
store.selectTab(uiConstants.TAB_ORPHANS);
store.clearSelection();
assert.deepEqual(store.getState().selection.sortKeysAvailable, [
'Newest',
'Oldest',
'Location',
]);
});
it('sets `selectedTab` to Annotations if set to Orphans', () => {
store.selectTab(uiConstants.TAB_ORPHANS);
store.clearSelection();
assert.equal(
store.getState().selection.selectedTab,
uiConstants.TAB_ANNOTATIONS
);
});
it('does not change `selectedTab` if set to something other than Orphans', () => { it('does not change `selectedTab` if set to something other than Orphans', () => {
store.selectTab(uiConstants.TAB_NOTES); store.selectTab(uiConstants.TAB_NOTES);
store.clearSelection(); store.clearSelection();
......
...@@ -6,6 +6,7 @@ export default { ...@@ -6,6 +6,7 @@ export default {
PANEL_HELP: 'help', PANEL_HELP: 'help',
PANEL_LOGIN_PROMPT: 'loginPrompt', PANEL_LOGIN_PROMPT: 'loginPrompt',
PANEL_SHARE_ANNOTATIONS: 'shareGroupAnnotations', PANEL_SHARE_ANNOTATIONS: 'shareGroupAnnotations',
TABS: ['annotation', 'note', 'orphan'],
TAB_ANNOTATIONS: 'annotation', TAB_ANNOTATIONS: 'annotation',
TAB_NOTES: 'note', TAB_NOTES: 'note',
TAB_ORPHANS: 'orphan', TAB_ORPHANS: 'orphan',
......
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