Skip to content

Commit 16bf358

Browse files
committed
wip
1 parent fc6068e commit 16bf358

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

packages/compass-crud/src/components/table-view/cell-renderer.tsx

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import {
1313
LeafyGreenProvider,
1414
spacing,
1515
withDarkMode,
16+
useContextMenuItems,
1617
} from '@mongodb-js/compass-components';
1718
import { type Document, Element } from 'hadron-document';
19+
import { objectToIdiomaticEJSON } from 'hadron-document';
1820
import type { ICellRendererParams } from 'ag-grid-community';
1921
import type { GridActions, TableHeaderType } from '../../stores/grid-store';
2022
import type { CrudActions } from '../../stores/crud-store';
@@ -257,6 +259,72 @@ const CellRenderer: React.FC<CellRendererProps> = ({
257259
const isEmpty = element === undefined || element === null;
258260
const [isDeleted, setIsDeleted] = useState(false);
259261

262+
// Helper function to check if a string is a URL
263+
const isValidUrl = useCallback((str: string): boolean => {
264+
try {
265+
const url = new URL(str);
266+
return url.protocol === 'http:' || url.protocol === 'https:';
267+
} catch {
268+
return false;
269+
}
270+
}, []);
271+
272+
// Add context menu functionality
273+
const contextMenuRef = useContextMenuItems([
274+
...(element && !isEmpty
275+
? [
276+
{
277+
label: 'Copy field & value',
278+
onAction: () => {
279+
const fieldName = column.getColId();
280+
const fieldStr = `${fieldName}: ${objectToIdiomaticEJSON(
281+
element.currentValue
282+
)}`;
283+
void navigator.clipboard.writeText(fieldStr);
284+
},
285+
},
286+
]
287+
: []),
288+
...(element &&
289+
element.currentType === 'String' &&
290+
isValidUrl(element.currentValue)
291+
? [
292+
{
293+
label: 'Open URL in browser',
294+
onAction: () => {
295+
window.open(element.currentValue, '_blank', 'noopener');
296+
},
297+
},
298+
]
299+
: []),
300+
...(element &&
301+
(element.currentType === 'Object' || element.currentType === 'Array')
302+
? [
303+
{
304+
label: 'Expand field',
305+
onAction: () => {
306+
handleDrillDown({
307+
stopPropagation: () => {},
308+
} as React.MouseEvent);
309+
},
310+
},
311+
]
312+
: []),
313+
...(cellState === ADDED ||
314+
cellState === EDITED ||
315+
cellState === INVALID ||
316+
cellState === DELETED
317+
? [
318+
{
319+
label: 'Undo changes',
320+
onAction: () => {
321+
handleUndo({ stopPropagation: () => {} } as React.MouseEvent);
322+
},
323+
},
324+
]
325+
: []),
326+
]);
327+
260328
const isEditable = useMemo(() => {
261329
/* Can't get the editable() function from here, so have to reevaluate */
262330
let editable = true;
@@ -328,6 +396,7 @@ const CellRenderer: React.FC<CellRendererProps> = ({
328396
elementRemoved,
329397
elementAdded,
330398
elementTypeChanged,
399+
cellState,
331400
]
332401
);
333402

@@ -355,7 +424,7 @@ const CellRenderer: React.FC<CellRendererProps> = ({
355424
// `ag-grid` renders this component outside of the context chain
356425
// so we re-supply the dark mode theme here.
357426
<LeafyGreenProvider darkMode={darkMode}>
358-
<div>
427+
<div ref={contextMenuRef}>
359428
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus*/}
360429
<div
361430
className={

0 commit comments

Comments
 (0)