Files
flipper/desktop/flipper-plugin/src/ui/data-table/TableContextMenu.tsx
Michel Weststrate 7e4df00138 Implement context menu
Summary:
Re-introduced context menu to DataTable, due to popular demand.

Originally it wasn't there to better align with ant design principles, but in an app like Flipper it makes just too much sense to have it

See e.g. https://fb.workplace.com/groups/flippersupport/permalink/1138285579985432/

changelog: Restored context menu in data tables

Reviewed By: passy

Differential Revision: D28996137

fbshipit-source-id: 16ef4c90997c9313efa62da7576fd453a7853761
2021-06-10 12:57:47 -07:00

146 lines
4.0 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {CopyOutlined, FilterOutlined} from '@ant-design/icons';
import {Checkbox, Menu} from 'antd';
import {
DataTableDispatch,
getSelectedItem,
getSelectedItems,
Selection,
} from './DataTableManager';
import React from 'react';
import {tryGetFlipperLibImplementation} from '../../plugin/FlipperLib';
import {DataTableColumn} from './DataTable';
import {toFirstUpper} from '../../utils/toFirstUpper';
import {DataSource} from '../../data-source/index';
const {Item, SubMenu} = Menu;
function defaultOnCopyRows<T>(items: T[]) {
return JSON.stringify(items.length > 1 ? items : items[0], null, 2);
}
export function tableContextMenuFactory<T>(
datasource: DataSource<T>,
dispatch: DataTableDispatch<T>,
selection: Selection,
columns: DataTableColumn<T>[],
visibleColumns: DataTableColumn<T>[],
onCopyRows: (rows: T[]) => string = defaultOnCopyRows,
onContextMenu?: (selection: undefined | T) => React.ReactElement,
) {
const lib = tryGetFlipperLibImplementation();
if (!lib) {
return (
<Menu>
<Item>Menu not ready</Item>
</Menu>
);
}
const hasSelection = selection.items.size > 0 ?? false;
return (
<Menu>
{onContextMenu
? onContextMenu(getSelectedItem(datasource, selection))
: null}
<SubMenu
key="filter same"
title="Filter on same"
icon={<FilterOutlined />}
disabled={!hasSelection}>
{visibleColumns.map((column, idx) => (
<Item
key={column.key ?? idx}
onClick={() => {
dispatch({
type: 'setColumnFilterFromSelection',
column: column.key,
});
}}>
{friendlyColumnTitle(column)}
</Item>
))}
</SubMenu>
<SubMenu
key="copy cells"
title="Copy cell(s)"
icon={<CopyOutlined />}
disabled={!hasSelection}>
{visibleColumns.map((column, idx) => (
<Item
key={column.key ?? idx}
onClick={() => {
const items = getSelectedItems(datasource, selection);
if (items.length) {
lib.writeTextToClipboard(
items.map((item) => '' + item[column.key]).join('\n'),
);
}
}}>
{friendlyColumnTitle(column)}
</Item>
))}
</SubMenu>
<Item
key="copyToClipboard"
disabled={!hasSelection}
onClick={() => {
const items = getSelectedItems(datasource, selection);
if (items.length) {
lib.writeTextToClipboard(onCopyRows(items));
}
}}>
Copy row(s)
</Item>
{lib.isFB && (
<Item
key="createPaste"
disabled={!hasSelection}
onClick={() => {
const items = getSelectedItems(datasource, selection);
if (items.length) {
lib.createPaste(onCopyRows(items));
}
}}>
Create paste
</Item>
)}
<Menu.Divider />
<SubMenu title="Visible columns" key="visible columns">
{columns.map((column, idx) => (
<Menu.Item key={column.key ?? idx}>
<Checkbox
checked={column.visible}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
dispatch({type: 'toggleColumnVisibility', column: column.key});
}}>
{friendlyColumnTitle(column)}
</Checkbox>
</Menu.Item>
))}
</SubMenu>
<Menu.Item
key="reset"
onClick={() => {
dispatch({type: 'reset'});
}}>
Reset view
</Menu.Item>
</Menu>
);
}
function friendlyColumnTitle(column: DataTableColumn<any>): string {
const name = column.title || column.key;
return toFirstUpper(name);
}