From 0200afca51920f04434dda9e5193136b325974cf Mon Sep 17 00:00:00 2001 From: Luke De Feo Date: Tue, 7 Jun 2022 04:29:16 -0700 Subject: [PATCH] Added support for plugin supplied context menu items Reviewed By: passy Differential Revision: D36781556 fbshipit-source-id: 42124e0324bb2c850099b60410eb20872ebefe3c --- .../src/ui/data-inspector/DataInspector.tsx | 12 ++++++++- .../ui/data-inspector/DataInspectorNode.tsx | 15 +++++++++++ .../__tests__/DataInspector.node.tsx | 25 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx b/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx index 3db0d544d..39f4c7721 100644 --- a/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx +++ b/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx @@ -8,7 +8,7 @@ */ import {DataInspectorExpanded, RootDataContext} from './DataInspectorNode'; -import {PureComponent} from 'react'; +import {PureComponent, ReactElement} from 'react'; import {DataInspectorNode} from './DataInspectorNode'; import React from 'react'; import {DataValueExtractor} from './DataPreview'; @@ -66,6 +66,15 @@ export type DataInspectorProps = { * Filter nodes by some search text */ filter?: string; + + /** + * these should be ant design Menu.Item's + */ + additionalContextMenuItems?: ( + parentPath: string[], + value: any, + name?: string, + ) => ReactElement[]; }; type DataInspectorState = { @@ -198,6 +207,7 @@ export class DataInspector extends PureComponent< parentPath={EMPTY_ARRAY} depth={0} parentAncestry={EMPTY_ARRAY} + additionalContextMenuItems={this.props.additionalContextMenuItems} /> diff --git a/desktop/flipper-plugin/src/ui/data-inspector/DataInspectorNode.tsx b/desktop/flipper-plugin/src/ui/data-inspector/DataInspectorNode.tsx index a5dbb1154..3d2a14518 100644 --- a/desktop/flipper-plugin/src/ui/data-inspector/DataInspectorNode.tsx +++ b/desktop/flipper-plugin/src/ui/data-inspector/DataInspectorNode.tsx @@ -17,6 +17,7 @@ import { useCallback, createContext, useContext, + ReactElement, } from 'react'; import styled from '@emotion/styled'; import DataPreview, {DataValueExtractor, InspectorName} from './DataPreview'; @@ -170,6 +171,11 @@ type DataInspectorProps = { * Object of properties that will have tooltips */ tooltips?: any; + additionalContextMenuItems?: ( + parentPath: string[], + value: any, + name?: string, + ) => ReactElement[]; }; const defaultValueExtractor: DataValueExtractor = (value: any) => { @@ -300,6 +306,7 @@ export const DataInspectorNode: React.FC = memo( collapsed, tooltips, setValue: setValueProp, + additionalContextMenuItems, }) { const highlighter = useHighlighter(); const getRoot = useContext(RootDataContext); @@ -469,6 +476,7 @@ export const DataInspectorNode: React.FC = memo( data={metadata.data} diff={metadata.diff} tooltips={tooltips} + additionalContextMenuItems={additionalContextMenuItems} /> ); @@ -564,8 +572,15 @@ export const DataInspectorNode: React.FC = memo( function getContextMenu() { const lib = tryGetFlipperLibImplementation(); + const extraItems = additionalContextMenuItems + ? [ + additionalContextMenuItems(parentPath, value, name), + , + ] + : []; return ( + {extraItems} { diff --git a/desktop/flipper-plugin/src/ui/data-inspector/__tests__/DataInspector.node.tsx b/desktop/flipper-plugin/src/ui/data-inspector/__tests__/DataInspector.node.tsx index dee2a916b..abf31c55f 100644 --- a/desktop/flipper-plugin/src/ui/data-inspector/__tests__/DataInspector.node.tsx +++ b/desktop/flipper-plugin/src/ui/data-inspector/__tests__/DataInspector.node.tsx @@ -12,6 +12,7 @@ import {render, fireEvent, waitFor, act} from '@testing-library/react'; import {DataInspector} from '../DataInspector'; import {sleep} from 'flipper-common'; +import {Menu} from 'antd'; const json = { data: { @@ -38,6 +39,30 @@ test('changing collapsed property works', async () => { expect(res.queryAllByText(/cool/).length).toBe(0); }); +test('additional context menu items are rendered', async () => { + const res = render( + { + return [ + + path={[...parentPath, name].join('->')} + , + ]; + }} + />, + ); + + 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 () => { const res = render();