Skip to content

Commit a964905

Browse files
authored
chore(compass-context-menu): conditionally filter groups COMPASS-9645 (#7158)
Changes the hooks to support passing undefined groups and items for cleaner conditional rendering and to avoid cases where we would end up passing [] as a group (thus leading to groups without any items).
1 parent 6025ad1 commit a964905

File tree

5 files changed

+78
-65
lines changed

5 files changed

+78
-65
lines changed

packages/compass-components/src/components/context-menu.spec.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import { render, screen, userEvent } from '@mongodb-js/testing-library-compass';
33
import { expect } from 'chai';
44
import sinon from 'sinon';
55
import { ContextMenuProvider } from '@mongodb-js/compass-context-menu';
6-
import { useContextMenuItems, ContextMenu } from './context-menu';
7-
import type { ContextMenuItem } from '@mongodb-js/compass-context-menu';
6+
import {
7+
useContextMenuItems,
8+
ContextMenu,
9+
type ContextMenuItem,
10+
} from './context-menu';
811

912
describe('useContextMenuItems', function () {
1013
const menuTestTriggerId = 'test-trigger';

packages/compass-components/src/components/context-menu.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,41 @@ export function ContextMenu({ menu }: ContextMenuWrapperProps) {
117117
);
118118
}
119119

120+
/** Registers context menu items - items that are `undefined` will get filtered. */
120121
export function useContextMenuItems(
121-
getItems: () => ContextMenuItem[],
122+
getItems: () => (ContextMenuItem | undefined)[],
122123
dependencies: React.DependencyList | undefined
123124
): React.RefCallback<HTMLElement> {
124-
// eslint-disable-next-line react-hooks/exhaustive-deps
125-
const memoizedItems = useMemo(getItems, dependencies);
125+
const memoizedItems = useMemo(
126+
() =>
127+
getItems().filter((item): item is ContextMenuItem => item !== undefined),
128+
// eslint-disable-next-line react-hooks/exhaustive-deps
129+
dependencies
130+
);
126131
const contextMenu = useContextMenu();
127132
return contextMenu.registerItems(memoizedItems);
128133
}
129134

135+
/** Registers context menu groups - groups and items that are `undefined` will get filtered. */
130136
export function useContextMenuGroups(
131-
getGroups: () => ContextMenuItemGroup[],
137+
getGroups: () => ((ContextMenuItem | undefined)[] | undefined)[],
132138
dependencies: React.DependencyList | undefined
133139
): React.RefCallback<HTMLElement> {
134-
// eslint-disable-next-line react-hooks/exhaustive-deps
135-
const memoizedGroups = useMemo(getGroups, dependencies);
140+
const memoizedGroups: ContextMenuItem[][] = useMemo(
141+
() => {
142+
const groups = getGroups();
143+
// Cleanup all undefined fields across items and groups which is used
144+
// for conditional displaying of groups and items.
145+
return groups
146+
.filter(
147+
(groupItems): groupItems is ContextMenuItem[] =>
148+
groupItems !== undefined && groupItems.length > 0
149+
)
150+
.map((groupItems) => groupItems.filter((item) => item !== undefined));
151+
},
152+
// eslint-disable-next-line react-hooks/exhaustive-deps
153+
dependencies
154+
);
136155
const contextMenu = useContextMenu();
137156
return contextMenu.registerItems(...memoizedGroups);
138157
}

packages/compass-components/src/components/document-list/element.tsx

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -501,24 +501,22 @@ export const HadronElement: React.FunctionComponent<{
501501
// Add context menu hook for the field
502502
const fieldContextMenuRef = useContextMenuItems(
503503
() => [
504-
...(onUpdateQuery
505-
? [
506-
{
507-
label: isFieldInQuery(
504+
onUpdateQuery
505+
? {
506+
label: isFieldInQuery(
507+
getNestedKeyPathForElement(element),
508+
element.generateObject()
509+
)
510+
? 'Remove from query'
511+
: 'Add to query',
512+
onAction: () => {
513+
onUpdateQuery(
508514
getNestedKeyPathForElement(element),
509515
element.generateObject()
510-
)
511-
? 'Remove from query'
512-
: 'Add to query',
513-
onAction: () => {
514-
onUpdateQuery(
515-
getNestedKeyPathForElement(element),
516-
element.generateObject()
517-
);
518-
},
516+
);
519517
},
520-
]
521-
: []),
518+
}
519+
: undefined,
522520
{
523521
label: 'Copy field & value',
524522
onAction: () => {
@@ -527,16 +525,14 @@ export const HadronElement: React.FunctionComponent<{
527525
);
528526
},
529527
},
530-
...(type.value === 'String' && isValidUrl(value.value)
531-
? [
532-
{
533-
label: 'Open URL in browser',
534-
onAction: () => {
535-
window.open(value.value, '_blank', 'noopener');
536-
},
528+
type.value === 'String' && isValidUrl(value.value)
529+
? {
530+
label: 'Open URL in browser',
531+
onAction: () => {
532+
window.open(value.value, '_blank', 'noopener');
537533
},
538-
]
539-
: []),
534+
}
535+
: undefined,
540536
],
541537
[element, key.value, value.value, type.value, onUpdateQuery, isFieldInQuery]
542538
);

packages/compass-crud/src/components/crud-toolbar.tsx

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -217,26 +217,22 @@ const CrudToolbar: React.FunctionComponent<CrudToolbarProps> = ({
217217
onCollapseAllClicked();
218218
},
219219
},
220-
...(isImportExportEnabled
221-
? [
222-
{
223-
label: 'Import JSON or CSV file',
224-
onAction: () => {
225-
insertDataHandler('import-file');
226-
},
220+
isImportExportEnabled
221+
? {
222+
label: 'Import JSON or CSV file',
223+
onAction: () => {
224+
insertDataHandler('import-file');
227225
},
228-
]
229-
: []),
230-
...(!readonly
231-
? [
232-
{
233-
label: 'Insert document...',
234-
onAction: () => {
235-
insertDataHandler('insert-document');
236-
},
226+
}
227+
: undefined,
228+
!readonly
229+
? {
230+
label: 'Insert document...',
231+
onAction: () => {
232+
insertDataHandler('insert-document');
237233
},
238-
]
239-
: []),
234+
}
235+
: undefined,
240236
...(isImportExportEnabled
241237
? [
242238
{

packages/compass-crud/src/components/use-document-item-context-menu.tsx

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,23 @@ export function useDocumentItemContextMenu({
1515
openInsertDocumentDialog,
1616
}: UseDocumentItemContextMenuProps) {
1717
const { expanded: isExpanded, editing: isEditing } = doc;
18+
1819
return useContextMenuGroups(
1920
() => [
20-
[
21-
...(isEditable
22-
? [
23-
{
24-
label: isEditing ? 'Cancel editing' : 'Edit document',
25-
onAction: () => {
26-
if (isEditing) {
27-
doc.finishEditing();
28-
} else {
29-
doc.startEditing();
30-
}
31-
},
21+
isEditable
22+
? [
23+
{
24+
label: isEditing ? 'Cancel editing' : 'Edit document',
25+
onAction: () => {
26+
if (isEditing) {
27+
doc.finishEditing();
28+
} else {
29+
doc.startEditing();
30+
}
3231
},
33-
]
34-
: []),
35-
],
32+
},
33+
]
34+
: undefined,
3635
[
3736
{
3837
label: isExpanded ? 'Collapse all fields' : 'Expand all fields',

0 commit comments

Comments
 (0)