Added support for plugin supplied context menu items

Reviewed By: passy

Differential Revision: D36781556

fbshipit-source-id: 42124e0324bb2c850099b60410eb20872ebefe3c
This commit is contained in:
Luke De Feo
2022-06-07 04:29:16 -07:00
committed by Facebook GitHub Bot
parent bb401fa70b
commit 0200afca51
3 changed files with 51 additions and 1 deletions

View File

@@ -8,7 +8,7 @@
*/ */
import {DataInspectorExpanded, RootDataContext} from './DataInspectorNode'; import {DataInspectorExpanded, RootDataContext} from './DataInspectorNode';
import {PureComponent} from 'react'; import {PureComponent, ReactElement} from 'react';
import {DataInspectorNode} from './DataInspectorNode'; import {DataInspectorNode} from './DataInspectorNode';
import React from 'react'; import React from 'react';
import {DataValueExtractor} from './DataPreview'; import {DataValueExtractor} from './DataPreview';
@@ -66,6 +66,15 @@ export type DataInspectorProps = {
* Filter nodes by some search text * Filter nodes by some search text
*/ */
filter?: string; filter?: string;
/**
* these should be ant design Menu.Item's
*/
additionalContextMenuItems?: (
parentPath: string[],
value: any,
name?: string,
) => ReactElement[];
}; };
type DataInspectorState = { type DataInspectorState = {
@@ -198,6 +207,7 @@ export class DataInspector extends PureComponent<
parentPath={EMPTY_ARRAY} parentPath={EMPTY_ARRAY}
depth={0} depth={0}
parentAncestry={EMPTY_ARRAY} parentAncestry={EMPTY_ARRAY}
additionalContextMenuItems={this.props.additionalContextMenuItems}
/> />
</HighlightProvider> </HighlightProvider>
</RootDataContext.Provider> </RootDataContext.Provider>

View File

@@ -17,6 +17,7 @@ import {
useCallback, useCallback,
createContext, createContext,
useContext, useContext,
ReactElement,
} from 'react'; } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import DataPreview, {DataValueExtractor, InspectorName} from './DataPreview'; import DataPreview, {DataValueExtractor, InspectorName} from './DataPreview';
@@ -170,6 +171,11 @@ type DataInspectorProps = {
* Object of properties that will have tooltips * Object of properties that will have tooltips
*/ */
tooltips?: any; tooltips?: any;
additionalContextMenuItems?: (
parentPath: string[],
value: any,
name?: string,
) => ReactElement[];
}; };
const defaultValueExtractor: DataValueExtractor = (value: any) => { const defaultValueExtractor: DataValueExtractor = (value: any) => {
@@ -300,6 +306,7 @@ export const DataInspectorNode: React.FC<DataInspectorProps> = memo(
collapsed, collapsed,
tooltips, tooltips,
setValue: setValueProp, setValue: setValueProp,
additionalContextMenuItems,
}) { }) {
const highlighter = useHighlighter(); const highlighter = useHighlighter();
const getRoot = useContext(RootDataContext); const getRoot = useContext(RootDataContext);
@@ -469,6 +476,7 @@ export const DataInspectorNode: React.FC<DataInspectorProps> = memo(
data={metadata.data} data={metadata.data}
diff={metadata.diff} diff={metadata.diff}
tooltips={tooltips} tooltips={tooltips}
additionalContextMenuItems={additionalContextMenuItems}
/> />
); );
@@ -564,8 +572,15 @@ export const DataInspectorNode: React.FC<DataInspectorProps> = memo(
function getContextMenu() { function getContextMenu() {
const lib = tryGetFlipperLibImplementation(); const lib = tryGetFlipperLibImplementation();
const extraItems = additionalContextMenuItems
? [
additionalContextMenuItems(parentPath, value, name),
<Menu.Divider key="extradivider" />,
]
: [];
return ( return (
<Menu> <Menu>
{extraItems}
<Menu.Item <Menu.Item
key="copyClipboard" key="copyClipboard"
onClick={() => { onClick={() => {

View File

@@ -12,6 +12,7 @@ import {render, fireEvent, waitFor, act} from '@testing-library/react';
import {DataInspector} from '../DataInspector'; import {DataInspector} from '../DataInspector';
import {sleep} from 'flipper-common'; import {sleep} from 'flipper-common';
import {Menu} from 'antd';
const json = { const json = {
data: { data: {
@@ -38,6 +39,30 @@ test('changing collapsed property works', async () => {
expect(res.queryAllByText(/cool/).length).toBe(0); expect(res.queryAllByText(/cool/).length).toBe(0);
}); });
test('additional context menu items are rendered', async () => {
const res = render(
<DataInspector
data={json}
expandRoot
additionalContextMenuItems={(parentPath, value, name) => {
return [
<Menu.Item key="test">
path={[...parentPath, name].join('->')}
</Menu.Item>,
];
}}
/>,
);
expect(await res.queryByText('path=data')).toBeFalsy;
fireEvent.contextMenu(await res.findByText(/data/), {});
expect(await res.findByText('path=data')).toBeTruthy;
//try on a nested element
fireEvent.contextMenu(await res.findByText(/awesomely/), {});
expect(await res.findByText('path=data->is->awesomely')).toBeTruthy;
});
test('can manually collapse properties', async () => { test('can manually collapse properties', async () => {
const res = render(<DataInspector data={json} collapsed expandRoot />); const res = render(<DataInspector data={json} collapsed expandRoot />);