Canvas: Add all options to inline editor (#52834)

Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
Ryan McKinley 2022-07-27 16:20:39 -07:00 committed by GitHub
parent cb3f7ccd09
commit 8a2d40c2bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 49 deletions

View File

@ -8622,9 +8622,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"], [0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Do not use any type assertions.", "5"], [0, 0, 0, "Unexpected any. Specify a different type.", "5"]
[0, 0, 0, "Unexpected any. Specify a different type.", "6"]
], ],
"public/app/plugins/panel/canvas/editor/APIEditor.tsx:5381": [ "public/app/plugins/panel/canvas/editor/APIEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "0"],

View File

@ -126,7 +126,7 @@ export class CanvasPanel extends Component<Props, State> {
}); });
this.setState({ refresh: this.state.refresh + 1 }); this.setState({ refresh: this.state.refresh + 1 });
// console.log('send changes', root); activePanelSubject.next({ panel: this });
}; };
shouldComponentUpdate(nextProps: Props, nextState: State) { shouldComponentUpdate(nextProps: Props, nextState: State) {

View File

@ -19,7 +19,7 @@ type Props = {
const OFFSET_X = 10; const OFFSET_X = 10;
const OFFSET_Y = 32; const OFFSET_Y = 32;
export const InlineEdit = ({ onClose, id, scene }: Props) => { export function InlineEdit({ onClose, id, scene }: Props) {
const root = scene.root.div!.getBoundingClientRect(); const root = scene.root.div!.getBoundingClientRect();
const windowHeight = window.innerHeight; const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth; const windowWidth = window.innerWidth;
@ -96,7 +96,7 @@ export const InlineEdit = ({ onClose, id, scene }: Props) => {
</div> </div>
</Portal> </Portal>
); );
}; }
const getStyles = (theme: GrafanaTheme2) => ({ const getStyles = (theme: GrafanaTheme2) => ({
inlineEditorContainer: css` inlineEditorContainer: css`

View File

@ -1,13 +1,12 @@
import { css } from '@emotion/css';
import { get as lodashGet } from 'lodash'; import { get as lodashGet } from 'lodash';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { useObservable } from 'react-use'; import { useObservable } from 'react-use';
import { GrafanaTheme2, PanelOptionsEditorBuilder, StandardEditorContext } from '@grafana/data'; import { DataFrame, PanelOptionsEditorBuilder, StandardEditorContext } from '@grafana/data';
import { PanelOptionsSupplier } from '@grafana/data/src/panel/PanelPlugin'; import { PanelOptionsSupplier } from '@grafana/data/src/panel/PanelPlugin';
import { NestedValueAccess } from '@grafana/data/src/utils/OptionsUIBuilders'; import { NestedValueAccess } from '@grafana/data/src/utils/OptionsUIBuilders';
import { useStyles2 } from '@grafana/ui';
import { FrameState } from 'app/features/canvas/runtime/frame'; import { FrameState } from 'app/features/canvas/runtime/frame';
import { OptionsPaneCategory } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategory';
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
import { fillOptionsPaneItems } from 'app/features/dashboard/components/PanelEditor/getVisualizationOptions'; import { fillOptionsPaneItems } from 'app/features/dashboard/components/PanelEditor/getVisualizationOptions';
import { setOptionImmutably } from 'app/features/dashboard/components/PanelEditor/utils'; import { setOptionImmutably } from 'app/features/dashboard/components/PanelEditor/utils';
@ -16,15 +15,13 @@ import { activePanelSubject, InstanceState } from './CanvasPanel';
import { getElementEditor } from './editor/elementEditor'; import { getElementEditor } from './editor/elementEditor';
import { getLayerEditor } from './editor/layerEditor'; import { getLayerEditor } from './editor/layerEditor';
export const InlineEditBody = () => { export function InlineEditBody() {
const activePanel = useObservable(activePanelSubject); const activePanel = useObservable(activePanelSubject);
const instanceState = activePanel?.panel.context?.instanceState; const instanceState = activePanel?.panel.context?.instanceState;
const styles = useStyles2(getStyles);
const pane = useMemo(() => { const pane = useMemo(() => {
const p = activePanel?.panel;
const state: InstanceState = instanceState; const state: InstanceState = instanceState;
if (!state) { if (!state || !p) {
return new OptionsPaneCategoryDescriptor({ id: 'root', title: 'root' }); return new OptionsPaneCategoryDescriptor({ id: 'root', title: 'root' });
} }
@ -46,33 +43,41 @@ export const InlineEditBody = () => {
} }
}; };
return getOptionsPaneCategoryDescriptor({}, supplier); return getOptionsPaneCategoryDescriptor(
}, [instanceState]); {
options: p.props.options,
onChange: p.props.onOptionsChange,
data: p.props.data?.series,
},
supplier
);
}, [instanceState, activePanel]);
return <>{pane.categories.map((p) => renderOptionsPaneCategoryDescriptor(p))}</>;
}
// Recursively render options
function renderOptionsPaneCategoryDescriptor(pane: OptionsPaneCategoryDescriptor) {
return ( return (
<div> <OptionsPaneCategory {...pane.props} key={pane.props.id}>
<div>{pane.items.map((v) => v.render())}</div> <div>{pane.items.map((v) => v.render())}</div>
<div> {pane.categories.map((c) => renderOptionsPaneCategoryDescriptor(c))}
{pane.categories.map((c) => { </OptionsPaneCategory>
return (
<div key={c.props.id} className={styles.wrap}>
<h5>{c.props.title}</h5>
<div className={styles.item}>{c.items.map((s) => s.render())}</div>
</div>
);
})}
</div>
</div>
); );
}; }
interface EditorProps<T> {
onChange: (v: T) => void;
options: T;
data?: DataFrame[];
}
// 🤮🤮🤮🤮 this oddly does not actually do anything, but structure is required. I'll try to clean it up...
function getOptionsPaneCategoryDescriptor<T = any>( function getOptionsPaneCategoryDescriptor<T = any>(
props: any, props: EditorProps<T>,
supplier: PanelOptionsSupplier<T> supplier: PanelOptionsSupplier<T>
): OptionsPaneCategoryDescriptor { ): OptionsPaneCategoryDescriptor {
const context: StandardEditorContext<unknown, unknown> = { const context: StandardEditorContext<unknown, unknown> = {
data: props.input, data: props.data ?? [],
options: props.options, options: props.options,
}; };
@ -101,13 +106,3 @@ function getOptionsPaneCategoryDescriptor<T = any>(
fillOptionsPaneItems(supplier, access, getOptionsPaneCategory, context); fillOptionsPaneItems(supplier, access, getOptionsPaneCategory, context);
return root; return root;
} }
const getStyles = (theme: GrafanaTheme2) => ({
wrap: css`
border-top: 1px solid ${theme.colors.border.strong};
padding: 10px;
`,
item: css`
padding-left: 10px;
`,
});

View File

@ -1,4 +1,4 @@
import React, { FC, useCallback } from 'react'; import React, { useCallback } from 'react';
import { AppEvents, StandardEditorProps, StandardEditorsRegistryItem, StringFieldConfigSettings } from '@grafana/data'; import { AppEvents, StandardEditorProps, StandardEditorsRegistryItem, StringFieldConfigSettings } from '@grafana/data';
import { config, getBackendSrv } from '@grafana/runtime'; import { config, getBackendSrv } from '@grafana/runtime';
@ -39,8 +39,9 @@ export const callApi = (api: APIEditorConfig, isTest = false) => {
} }
}; };
export const APIEditor: FC<StandardEditorProps<APIEditorConfig, any, any>> = (props) => { type Props = StandardEditorProps<APIEditorConfig, any, any>;
const { value, context, onChange } = props;
export function APIEditor({ value, context, onChange }: Props) {
const labelWidth = 9; const labelWidth = 9;
const onEndpointChange = useCallback( const onEndpointChange = useCallback(
@ -117,4 +118,4 @@ export const APIEditor: FC<StandardEditorProps<APIEditorConfig, any, any>> = (pr
) : ( ) : (
<>Must enable disableSanitizeHtml feature flag to access</> <>Must enable disableSanitizeHtml feature flag to access</>
); );
}; }

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { useObservable } from 'react-use'; import { useObservable } from 'react-use';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -31,7 +31,9 @@ const verticalOptions: Array<SelectableValue<VerticalConstraint>> = [
{ label: 'Scale', value: VerticalConstraint.Scale }, { label: 'Scale', value: VerticalConstraint.Scale },
]; ];
export const PlacementEditor: FC<StandardEditorProps<any, CanvasEditorOptions, PanelOptions>> = ({ item }) => { type Props = StandardEditorProps<any, CanvasEditorOptions, PanelOptions>;
export function PlacementEditor({ item }: Props) {
const settings = item.settings; const settings = item.settings;
// Will force a rerender whenever the subject changes // Will force a rerender whenever the subject changes
@ -136,4 +138,4 @@ export const PlacementEditor: FC<StandardEditorProps<any, CanvasEditorOptions, P
</Field> </Field>
</div> </div>
); );
}; }