mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Canvas: Add all options to inline editor (#52834)
Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
parent
cb3f7ccd09
commit
8a2d40c2bc
@ -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"],
|
||||||
|
@ -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) {
|
||||||
|
@ -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`
|
||||||
|
@ -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;
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
@ -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</>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user