Files
flipper/desktop/flipper-plugin/src/ui/data-table/TableContextMenu.tsx
Michel Weststrate faf8588097 Minor improvements
Summary:
Some styling fixes and minor improvements in DataTable, used by network plugin:

- be able to customise the context menu
- be able to customise how entire rows are copied and presented on the clipboard to be able to deviate from the standard JSON
- deeplink handling was made async, this gives the plugin the opportunity to first handle initial setup and rendering before trying to jump somewhere which is a typical use case for deeplinking

Reviewed By: passy

Differential Revision: D27947186

fbshipit-source-id: a56f081d60520c4bc2ad3c547a8ca5b9357e71a1
2021-04-23 09:29:59 -07:00

142 lines
3.8 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 {DataSource} from '../../state/DataSource';
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
title="Filter on same"
icon={<FilterOutlined />}
disabled={!hasSelection}>
{visibleColumns.map((column) => (
<Item
key={column.key}
onClick={() => {
dispatch({
type: 'setColumnFilterFromSelection',
column: column.key,
});
}}>
{friendlyColumnTitle(column)}
</Item>
))}
</SubMenu>
<SubMenu
title="Copy cell(s)"
icon={<CopyOutlined />}
disabled={!hasSelection}>
{visibleColumns.map((column) => (
<Item
key={column.key}
onClick={() => {
const items = getSelectedItems(datasource, selection);
if (items.length) {
lib.writeTextToClipboard(
items.map((item) => '' + item[column.key]).join('\n'),
);
}
}}>
{friendlyColumnTitle(column)}
</Item>
))}
</SubMenu>
<Item
disabled={!hasSelection}
onClick={() => {
const items = getSelectedItems(datasource, selection);
if (items.length) {
lib.writeTextToClipboard(onCopyRows(items));
}
}}>
Copy row(s)
</Item>
{lib.isFB && (
<Item
disabled={!hasSelection}
onClick={() => {
const items = getSelectedItems(datasource, selection);
if (items.length) {
lib.createPaste(onCopyRows(items));
}
}}>
Create paste
</Item>
)}
<Menu.Divider />
<SubMenu title="Visible columns">
{columns.map((column) => (
<Menu.Item key={column.key}>
<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 name[0].toUpperCase() + name.substr(1);
}