fix: show more button even when list box is not in selection (#1554)

* fix: show more button even when list box is not in selection

* fix: failded test case

* fix: activate selection if not yet

* fix: search

* revert: changes for search

* fix: remove isInSelection

* fix: change enabled check

* fix: unit test

* fix: unit test

* test: add unit test to check existence of more button

* fix: change description
This commit is contained in:
linhnguyen-qlik
2024-06-24 12:19:01 +02:00
committed by GitHub
parent 398c444aa6
commit f7d73d64b9
8 changed files with 51 additions and 17 deletions

View File

@@ -146,7 +146,7 @@ function ActionsToolbar({
moreActions = [...newMoreActions, ...more.actions];
}
if (!selections.show && newActions.length === 0) return null;
if (!selections.show && newActions.length === 0 && !moreEnabled) return null;
const handleCloseShowMoreItems = () => {
setShowMoreItems(false);

View File

@@ -121,7 +121,6 @@ function ListBoxInline({ options, layout }) {
const isModalMode = useCallback(() => isModal({ app, appSelections }), [app, appSelections]);
const isInvalid = layout?.qListObject.qDimensionInfo.qError;
const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
const [isInSelection, setIsInSelection] = useState(false);
const { handleKeyDown, handleOnMouseEnter, handleOnMouseLeave, globalKeyDown } = useMemo(
() =>
@@ -162,11 +161,9 @@ function ListBoxInline({ options, layout }) {
}
const show = () => {
setShowToolbar(true);
setIsInSelection(true);
};
const hide = () => {
setShowToolbar(false);
setIsInSelection(false);
if (search === 'toggle') {
setShowSearch(false);
}
@@ -184,7 +181,7 @@ function ListBoxInline({ options, layout }) {
selections.on('activated', show);
selections.on('deactivated', hide);
}
setShowToolbar(selections.isActive());
setShowToolbar(isPopover || selections.isActive());
}
return () => {
@@ -279,7 +276,6 @@ function ListBoxInline({ options, layout }) {
selectionState={selectionState}
selections={selections}
keyboard={keyboard}
isInSelection={isInSelection}
/>
);

View File

@@ -67,7 +67,6 @@ export default function ListBoxHeader({
keyboard,
autoConfirm,
app,
isInSelection,
}) {
const [isToolbarDetached, setIsToolbarDetached] = useState(showDetachedToolbarOnly);
const [isLocked, setLocked] = useState(layout?.qListObject?.qDimensionInfo?.qLocked);
@@ -99,13 +98,13 @@ export default function ListBoxHeader({
(iconData ? BUTTON_ICON_WIDTH : 0);
const toggleLock = getToggleLock({ isLocked, setLocked, settingLockedState, setSettingLockedState, model });
const listboxSelectionToolbarItems = createListboxSelectionToolbar({
layout,
model,
translator,
selectionState,
isDirectQuery,
selections,
});
const extraItems =
@@ -170,6 +169,7 @@ export default function ListBoxHeader({
isDetached: isPopover ? false : isToolbarDetached,
showToolbar,
containerRef,
isPopover,
isLocked,
extraItems,
listboxSelectionToolbarItems,
@@ -214,7 +214,7 @@ export default function ListBoxHeader({
<DimensionIcon
iconData={iconData}
iconStyle={iconStyle}
disabled={isInSelection && isPopover}
disabled={selections.isActive() && isPopover}
translator={translator}
/>
</Grid>

View File

@@ -19,6 +19,7 @@ const selections = {
canClear: () => true,
canConfirm: () => true,
canCancel: () => true,
isActive: () => false,
};
const styles = { content: {}, header: { color: 'red' }, selections: {}, search: {}, background: {} };
let rendererInst;
@@ -230,4 +231,16 @@ describe('<ListBoxHeader />', () => {
// Ensure unlock is visible
expect(unlockCoverButtons).toHaveLength(1);
});
test('Should show more button even when it is not in selection mode for popover', async () => {
hasSelections.mockReturnValue(true);
const testRenderer = await render({ showSearchIcon: true, showLock: true, isPopover: true });
const testInstance = testRenderer.root;
const [actionsToolbar] = testInstance.findAllByType(ActionsToolbar);
// Check existence.
const moreButton = actionsToolbar.props.more;
expect(moreButton.enabled).toEqual(true);
});
});

View File

@@ -6,6 +6,7 @@ describe('getScrollIndex', () => {
let translator;
let selectionState;
let isDirectQuery;
let selections;
afterEach(() => {
jest.resetAllMocks();
@@ -41,6 +42,11 @@ describe('getScrollIndex', () => {
selectionState = {
clearItemStates: jest.fn(),
};
selections = {
isActive: jest.fn(() => false),
begin: jest.fn(),
};
});
const create = (overrides = {}) =>
@@ -50,6 +56,7 @@ describe('getScrollIndex', () => {
translator,
selectionState,
isDirectQuery,
selections,
...overrides,
});
@@ -122,21 +129,25 @@ describe('getScrollIndex', () => {
it('select all', () => {
all.action();
expect(model.selectListObjectAll).toHaveBeenCalledTimes(1);
expect(selections.begin).toHaveBeenCalledTimes(1);
expect(model.selectListObjectAll).toBeCalledWith('/qListObjectDef');
});
it('select possible', () => {
possible.action();
expect(model.selectListObjectPossible).toHaveBeenCalledTimes(1);
expect(selections.begin).toHaveBeenCalledTimes(1);
expect(model.selectListObjectPossible).toBeCalledWith('/qListObjectDef');
});
it('select alternative', () => {
alternative.action();
expect(model.selectListObjectAlternative).toHaveBeenCalledTimes(1);
expect(selections.begin).toHaveBeenCalledTimes(1);
expect(model.selectListObjectAlternative).toBeCalledWith('/qListObjectDef');
});
it('select excluded', () => {
excluded.action();
expect(model.selectListObjectExcluded).toHaveBeenCalledTimes(1);
expect(selections.begin).toHaveBeenCalledTimes(1);
expect(model.selectListObjectExcluded).toBeCalledWith('/qListObjectDef');
});
});

View File

@@ -19,7 +19,7 @@ export default function getListboxActionProps({
},
extraItems,
more: {
enabled: !isLocked,
enabled: !isLocked && (showToolbar || selections.isActive()), // show more button even when popover is not in selection mode
actions: listboxSelectionToolbarItems,
popoverProps: {
elevation: 0,
@@ -30,7 +30,7 @@ export default function getListboxActionProps({
},
},
selections: {
show: showToolbar,
show: showToolbar && selections.isActive(),
api: selections,
onConfirm: () => {
keyboard?.focus();

View File

@@ -3,11 +3,16 @@ import { selectAlternative } from '@nebula.js/ui/icons/select-alternative';
import { selectPossible } from '@nebula.js/ui/icons/select-possible';
import { selectExcluded } from '@nebula.js/ui/icons/select-excluded';
export default ({ layout, model, translator, selectionState, isDirectQuery = false }) => {
export default ({ layout, model, translator, selectionState, isDirectQuery = false, selections }) => {
if (layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne) {
return [];
}
const path = '/qListObjectDef';
const activateSelection = () => {
if (!selections.isActive()) {
selections.begin(path);
}
};
const canSelectAll = () =>
['qOption', 'qAlternative', 'qExcluded', 'qDeselected'].some(
(sc) => layout.qListObject.qDimensionInfo.qStateCounts[sc] > 0
@@ -26,8 +31,9 @@ export default ({ layout, model, translator, selectionState, isDirectQuery = fal
getSvgIconShape: selectAll,
enabled: canSelectAll,
action: () => {
activateSelection();
selectionState.clearItemStates(false);
model.selectListObjectAll('/qListObjectDef');
model.selectListObjectAll(path);
},
},
{
@@ -37,8 +43,9 @@ export default ({ layout, model, translator, selectionState, isDirectQuery = fal
getSvgIconShape: selectPossible,
enabled: canSelectPossible,
action: () => {
activateSelection();
selectionState.clearItemStates(false);
model.selectListObjectPossible('/qListObjectDef');
model.selectListObjectPossible(path);
},
},
isDirectQuery
@@ -50,8 +57,9 @@ export default ({ layout, model, translator, selectionState, isDirectQuery = fal
getSvgIconShape: selectAlternative,
enabled: canSelectAlternative,
action: () => {
activateSelection();
selectionState.clearItemStates(false);
model.selectListObjectAlternative('/qListObjectDef');
model.selectListObjectAlternative(path);
},
},
isDirectQuery
@@ -63,8 +71,9 @@ export default ({ layout, model, translator, selectionState, isDirectQuery = fal
getSvgIconShape: selectExcluded,
enabled: canSelectExcluded,
action: () => {
activateSelection();
selectionState.clearItemStates(false);
model.selectListObjectExcluded('/qListObjectDef');
model.selectListObjectExcluded(path);
},
},
].filter(Boolean);

View File

@@ -259,6 +259,11 @@ window.getFuncs = function getFuncs() {
qListObject: {
qDimensionInfo: {
qLocked: false,
qStateCounts: {
qOption: 0,
qAlternative: 0,
qExcluded: 0,
},
},
qSize: {
qcy: 16,