mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Canvas: Cleanup default elements (#52958)
This commit is contained in:
@@ -8636,6 +8636,10 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
|
||||
],
|
||||
"public/app/plugins/panel/canvas/utils.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/dashlist/module.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
|
||||
@@ -55,3 +55,6 @@ export interface CanvasElementItem<TConfig = any, TData = any> extends RegistryI
|
||||
/** Build the configuration UI */
|
||||
registerOptionsUI?: PanelOptionsSupplier<CanvasElementOptions<TConfig>>;
|
||||
}
|
||||
|
||||
export const defaultBgColor = '#D9D9D9';
|
||||
export const defaultTextColor = '#000000';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { TextDimensionEditor } from 'app/features/dimensions/editors/TextDimensi
|
||||
import { TextDimensionConfig } from 'app/features/dimensions/types';
|
||||
import { APIEditor, APIEditorConfig, callApi } from 'app/plugins/panel/canvas/editor/APIEditor';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element';
|
||||
|
||||
interface ButtonData {
|
||||
text?: string;
|
||||
@@ -28,7 +28,7 @@ class ButtonDisplay extends PureComponent<CanvasElementProps<ButtonConfig, Butto
|
||||
};
|
||||
|
||||
return (
|
||||
<Button type="submit" onClick={onClick}>
|
||||
<Button type="submit" onClick={onClick} style={{ background: defaultBgColor }}>
|
||||
{data?.text}
|
||||
</Button>
|
||||
);
|
||||
@@ -43,12 +43,23 @@ export const buttonItem: CanvasElementItem<ButtonConfig, ButtonData> = {
|
||||
display: ButtonDisplay,
|
||||
|
||||
defaultSize: {
|
||||
width: 200,
|
||||
height: 50,
|
||||
width: 32,
|
||||
height: 32,
|
||||
},
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
...options,
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'transparent',
|
||||
},
|
||||
},
|
||||
placement: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
}),
|
||||
|
||||
// Called when data changes
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useStyles2 } from '@grafana/ui';
|
||||
import { DimensionContext, ScalarDimensionConfig } from 'app/features/dimensions';
|
||||
import { ScalarDimensionEditor } from 'app/features/dimensions/editors';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element';
|
||||
|
||||
interface DroneFrontData {
|
||||
rollAngle?: number;
|
||||
@@ -29,22 +29,22 @@ const DroneFrontDisplay: FC<CanvasElementProps<DroneFrontConfig, DroneFrontData>
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 1300 290"
|
||||
style={{ transform: droneFrontTransformStyle }}
|
||||
style={{ transform: droneFrontTransformStyle, stroke: defaultBgColor }}
|
||||
>
|
||||
<g className="arms" stroke="black" strokeWidth="28px">
|
||||
<g className="arms" stroke={defaultBgColor} strokeWidth="28px">
|
||||
<line x1="510" x2="320" y1="100" y2="150" />
|
||||
<line x1="510" x2="320" y1="190" y2="210" />
|
||||
<line x1="790" x2="980" y1="190" y2="210" />
|
||||
<line x1="790" x2="980" y1="100" y2="150" />
|
||||
</g>
|
||||
<g className="body" stroke="black" strokeWidth="28px">
|
||||
<g className="body" stroke={defaultBgColor} strokeWidth="28px">
|
||||
<path
|
||||
fill="none"
|
||||
d=" M 510 130 C 510 124 510 110 510 100 C 510 90 530 71 540 70 C 640 61 670 60 760 70 C 770 71 790 90 790 100 Q 790 120 790 130 L 790 130 Q 790 177 790 196 C 790 207 770 225 760 226 C 670 236 640 236 540 226 C 530 226 510 206 510 196 Q 510 177 510 130 Q 510 133 510 130 Z "
|
||||
/>
|
||||
<circle cx="650" cy="160" r="40" fill="none" />
|
||||
</g>
|
||||
<g className="motors" stroke="black" strokeWidth="28px">
|
||||
<g className="motors" stroke={defaultBgColor} strokeWidth="28px">
|
||||
<path
|
||||
className="motor"
|
||||
fill="none"
|
||||
@@ -56,7 +56,7 @@ const DroneFrontDisplay: FC<CanvasElementProps<DroneFrontConfig, DroneFrontData>
|
||||
d=" M 1050 60 L 980 60 L 980 230 L 990 290 L 1040 290 L 1050 230 L 1050 60 Z "
|
||||
/>
|
||||
</g>
|
||||
<g className="propellers" fill="black">
|
||||
<g className="propellers" fill={defaultBgColor}>
|
||||
<path
|
||||
className="prop"
|
||||
d=" M 270 60 L 300 60 L 300 20 Q 311 30 330 30 Q 349 30 570 10 L 300 10 Q 300 0 290 0 C 286 0 284 0 280 0 Q 270 0 270 10 L 0 10 Q 220 30 240 30 Q 260 30 270 20 L 270 60 Z "
|
||||
@@ -79,11 +79,22 @@ export const droneFrontItem: CanvasElementItem<any, any> = {
|
||||
|
||||
defaultSize: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
height: 26,
|
||||
},
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
...options,
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'transparent',
|
||||
},
|
||||
},
|
||||
placement: {
|
||||
width: options?.placement?.width ?? 100,
|
||||
height: options?.placement?.height ?? 26,
|
||||
top: options?.placement?.top,
|
||||
left: options?.placement?.left,
|
||||
},
|
||||
}),
|
||||
|
||||
// Called when data changes
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useStyles2 } from '@grafana/ui';
|
||||
import { DimensionContext, ScalarDimensionConfig } from 'app/features/dimensions';
|
||||
import { ScalarDimensionEditor } from 'app/features/dimensions/editors';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element';
|
||||
|
||||
interface DroneSideData {
|
||||
pitchAngle?: number;
|
||||
@@ -29,21 +29,21 @@ const DroneSideDisplay: FC<CanvasElementProps<DroneSideConfig, DroneSideData>> =
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 1300 290"
|
||||
style={{ transform: droneSidePitchTransformStyle }}
|
||||
style={{ transform: droneSidePitchTransformStyle, stroke: defaultBgColor }}
|
||||
>
|
||||
<g className="arms" stroke="black" strokeWidth="28px">
|
||||
<g className="arms" stroke={defaultBgColor} strokeWidth="28px">
|
||||
<line x1="510" x2="320" y1="100" y2="150" />
|
||||
<line x1="510" x2="320" y1="190" y2="210" />
|
||||
<line x1="790" x2="980" y1="190" y2="210" />
|
||||
<line x1="790" x2="980" y1="100" y2="150" />
|
||||
</g>
|
||||
<g className="body" stroke="black" strokeWidth="28px">
|
||||
<g className="body" stroke={defaultBgColor} strokeWidth="28px">
|
||||
<path
|
||||
fill="none"
|
||||
d=" M 510 130 C 510 124 510 110 510 100 C 510 90 530 71 540 70 C 640 61 670 60 760 70 C 770 71 790 90 790 100 Q 790 120 790 130 L 790 130 Q 790 177 790 196 C 790 207 770 225 760 226 C 670 236 640 236 540 226 C 530 226 510 206 510 196 Q 510 177 510 130 Q 510 133 510 130 Z "
|
||||
/>
|
||||
</g>
|
||||
<g className="motors" stroke="black" strokeWidth="28px">
|
||||
<g className="motors" stroke={defaultBgColor} strokeWidth="28px">
|
||||
<path
|
||||
className="motor"
|
||||
fill="none"
|
||||
@@ -55,7 +55,7 @@ const DroneSideDisplay: FC<CanvasElementProps<DroneSideConfig, DroneSideData>> =
|
||||
d=" M 1050 60 L 980 60 L 980 230 L 990 290 L 1040 290 L 1050 230 L 1050 60 Z "
|
||||
/>
|
||||
</g>
|
||||
<g className="propellers" fill="black">
|
||||
<g className="propellers" fill={defaultBgColor}>
|
||||
<path
|
||||
className="prop"
|
||||
d=" M 270 60 L 300 60 L 300 20 Q 311 30 330 30 Q 349 30 570 10 L 300 10 Q 300 0 290 0 C 286 0 284 0 280 0 Q 270 0 270 10 L 0 10 Q 220 30 240 30 Q 260 30 270 20 L 270 60 Z "
|
||||
@@ -78,11 +78,22 @@ export const droneSideItem: CanvasElementItem<any, any> = {
|
||||
|
||||
defaultSize: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
height: 26,
|
||||
},
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
...options,
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'transparent',
|
||||
},
|
||||
},
|
||||
placement: {
|
||||
width: options?.placement?.width ?? 100,
|
||||
height: options?.placement?.height ?? 26,
|
||||
top: options?.placement?.top,
|
||||
left: options?.placement?.left,
|
||||
},
|
||||
}),
|
||||
|
||||
// Called when data changes
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useStyles2 } from '@grafana/ui';
|
||||
import { DimensionContext, ScalarDimensionConfig } from 'app/features/dimensions';
|
||||
import { ScalarDimensionEditor } from 'app/features/dimensions/editors';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element';
|
||||
|
||||
interface DroneTopData {
|
||||
bRightRotorRPM?: number;
|
||||
@@ -45,7 +45,7 @@ const DroneTopDisplay: FC<CanvasElementProps<DroneTopConfig, DroneTopData>> = (p
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="-43 -43 640 640"
|
||||
xmlSpace="preserve"
|
||||
style={{ transform: droneTopTransformStyle }}
|
||||
style={{ transform: droneTopTransformStyle, fill: defaultBgColor }}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@@ -95,6 +95,11 @@ export const droneTopItem: CanvasElementItem<any, any> = {
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
...options,
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'transparent',
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
// Called when data changes
|
||||
|
||||
@@ -11,9 +11,9 @@ import {
|
||||
} from 'app/features/dimensions';
|
||||
import { DimensionContext } from 'app/features/dimensions/context';
|
||||
import { ColorDimensionEditor, ResourceDimensionEditor } from 'app/features/dimensions/editors';
|
||||
import { APIEditor, APIEditorConfig, callApi } from 'app/plugins/panel/canvas/editor/APIEditor';
|
||||
import { APIEditorConfig, callApi } from 'app/plugins/panel/canvas/editor/APIEditor';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element';
|
||||
import { LineConfig } from '../types';
|
||||
|
||||
export interface IconConfig {
|
||||
@@ -75,8 +75,8 @@ export const iconItem: CanvasElementItem<IconConfig, IconData> = {
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
placement: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
width: 100,
|
||||
height: 100,
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
@@ -86,7 +86,12 @@ export const iconItem: CanvasElementItem<IconConfig, IconData> = {
|
||||
mode: ResourceDimensionMode.Fixed,
|
||||
fixed: 'img/icons/unicons/question-circle.svg',
|
||||
},
|
||||
fill: { fixed: '#FFF899' },
|
||||
fill: { fixed: defaultBgColor },
|
||||
},
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'transparent',
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -102,7 +107,7 @@ export const iconItem: CanvasElementItem<IconConfig, IconData> = {
|
||||
|
||||
const data: IconData = {
|
||||
path,
|
||||
fill: cfg.fill ? ctx.getColor(cfg.fill).value() : '#CCC',
|
||||
fill: cfg.fill ? ctx.getColor(cfg.fill).value() : defaultBgColor,
|
||||
api: cfg?.api ?? undefined,
|
||||
};
|
||||
|
||||
@@ -140,36 +145,36 @@ export const iconItem: CanvasElementItem<IconConfig, IconData> = {
|
||||
// Configured values
|
||||
fixed: 'grey',
|
||||
},
|
||||
})
|
||||
.addSliderInput({
|
||||
category,
|
||||
path: 'config.stroke.width',
|
||||
name: 'Stroke',
|
||||
defaultValue: 0,
|
||||
settings: {
|
||||
min: 0,
|
||||
max: 10,
|
||||
},
|
||||
})
|
||||
.addCustomEditor({
|
||||
category,
|
||||
id: 'config.stroke.color',
|
||||
path: 'config.stroke.color',
|
||||
name: 'Stroke color',
|
||||
editor: ColorDimensionEditor,
|
||||
settings: {},
|
||||
defaultValue: {
|
||||
// Configured values
|
||||
fixed: 'grey',
|
||||
},
|
||||
showIf: (cfg) => Boolean(cfg?.config?.stroke?.width),
|
||||
})
|
||||
.addCustomEditor({
|
||||
category,
|
||||
id: 'apiSelector',
|
||||
path: 'config.api',
|
||||
name: 'API',
|
||||
editor: APIEditor,
|
||||
});
|
||||
// .addSliderInput({
|
||||
// category,
|
||||
// path: 'config.stroke.width',
|
||||
// name: 'Stroke',
|
||||
// defaultValue: 0,
|
||||
// settings: {
|
||||
// min: 0,
|
||||
// max: 10,
|
||||
// },
|
||||
// })
|
||||
// .addCustomEditor({
|
||||
// category,
|
||||
// id: 'config.stroke.color',
|
||||
// path: 'config.stroke.color',
|
||||
// name: 'Stroke color',
|
||||
// editor: ColorDimensionEditor,
|
||||
// settings: {},
|
||||
// defaultValue: {
|
||||
// // Configured values
|
||||
// fixed: 'grey',
|
||||
// },
|
||||
// showIf: (cfg) => Boolean(cfg?.config?.stroke?.width),
|
||||
// })
|
||||
// .addCustomEditor({
|
||||
// category,
|
||||
// id: 'apiSelector',
|
||||
// path: 'config.api',
|
||||
// name: 'API',
|
||||
// editor: APIEditor,
|
||||
// });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ColorDimensionEditor } from 'app/features/dimensions/editors/ColorDimen
|
||||
import { TextDimensionEditor } from 'app/features/dimensions/editors/TextDimensionEditor';
|
||||
import { ColorDimensionConfig, TextDimensionConfig } from 'app/features/dimensions/types';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor, defaultTextColor } from '../element';
|
||||
|
||||
export enum Align {
|
||||
Left = 'left',
|
||||
@@ -78,15 +78,18 @@ export const textBoxItem: CanvasElementItem<TextBoxConfig, TextBoxData> = {
|
||||
},
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'grey',
|
||||
},
|
||||
},
|
||||
...options,
|
||||
config: {
|
||||
align: Align.Left,
|
||||
align: Align.Center,
|
||||
valign: VAlign.Middle,
|
||||
color: {
|
||||
fixed: defaultTextColor,
|
||||
},
|
||||
},
|
||||
background: {
|
||||
color: {
|
||||
fixed: defaultBgColor,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useStyles2 } from '@grafana/ui';
|
||||
import { DimensionContext, ScalarDimensionConfig } from 'app/features/dimensions';
|
||||
import { ScalarDimensionEditor } from 'app/features/dimensions/editors';
|
||||
|
||||
import { CanvasElementItem, CanvasElementProps } from '../element';
|
||||
import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element';
|
||||
|
||||
interface WindTurbineData {
|
||||
rpm?: number;
|
||||
@@ -24,7 +24,7 @@ const WindTurbineDisplay: FC<CanvasElementProps<WindTurbineConfig, WindTurbineDa
|
||||
const windTurbineAnimation = `spin ${data?.rpm ? 60 / Math.abs(data.rpm) : 0}s linear infinite`;
|
||||
|
||||
return (
|
||||
<svg viewBox="0 0 189.326 283.989" preserveAspectRatio="xMidYMid meet">
|
||||
<svg viewBox="0 0 189.326 283.989" preserveAspectRatio="xMidYMid meet" style={{ fill: defaultBgColor }}>
|
||||
<symbol id="blade">
|
||||
<path
|
||||
fill="#e6e6e6"
|
||||
@@ -74,11 +74,22 @@ export const windTurbineItem: CanvasElementItem<any, any> = {
|
||||
|
||||
defaultSize: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
height: 155,
|
||||
},
|
||||
|
||||
getNewOptions: (options) => ({
|
||||
...options,
|
||||
background: {
|
||||
color: {
|
||||
fixed: 'transparent',
|
||||
},
|
||||
},
|
||||
placement: {
|
||||
width: options?.placement?.width ?? 100,
|
||||
height: options?.placement?.height ?? 155,
|
||||
top: options?.placement?.top,
|
||||
left: options?.placement?.left,
|
||||
},
|
||||
}),
|
||||
|
||||
// Called when data changes
|
||||
|
||||
@@ -15,12 +15,14 @@ export const DEFAULT_CANVAS_ELEMENT_CONFIG: CanvasElementOptions = {
|
||||
name: `Element 1`,
|
||||
};
|
||||
|
||||
export const canvasElementRegistry = new Registry<CanvasElementItem>(() => [
|
||||
export const defaultElementItems = [
|
||||
iconItem, // default for now
|
||||
textBoxItem,
|
||||
buttonItem,
|
||||
droneTopItem,
|
||||
droneFrontItem,
|
||||
droneSideItem,
|
||||
windTurbineItem,
|
||||
];
|
||||
|
||||
const advancedElementItems = [buttonItem, windTurbineItem, droneTopItem, droneFrontItem, droneSideItem];
|
||||
|
||||
export const canvasElementRegistry = new Registry<CanvasElementItem>(() => [
|
||||
...defaultElementItems,
|
||||
...advancedElementItems,
|
||||
]);
|
||||
|
||||
@@ -46,6 +46,7 @@ export class ElementState implements LayerElement {
|
||||
horizontal: HorizontalConstraint.Left,
|
||||
};
|
||||
options.placement = options.placement ?? { width: 100, height: 100, top: 0, left: 0 };
|
||||
options.background = options.background ?? { color: { fixed: 'transparent' } };
|
||||
const scene = this.getScene();
|
||||
if (!options.name) {
|
||||
const newName = scene?.getNextElementName();
|
||||
@@ -321,6 +322,8 @@ export class ElementState implements LayerElement {
|
||||
css.backgroundSize = '100% 100%';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
css.backgroundImage = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ export class Scene {
|
||||
div?: HTMLDivElement;
|
||||
currentLayer?: FrameState;
|
||||
isEditingEnabled?: boolean;
|
||||
shouldShowAdvancedTypes?: boolean;
|
||||
skipNextSelectionBroadcast = false;
|
||||
ignoreDataUpdate = false;
|
||||
|
||||
@@ -66,8 +67,13 @@ export class Scene {
|
||||
|
||||
inlineEditingCallback?: () => void;
|
||||
|
||||
constructor(cfg: CanvasFrameOptions, enableEditing: boolean, public onSave: (cfg: CanvasFrameOptions) => void) {
|
||||
this.root = this.load(cfg, enableEditing);
|
||||
constructor(
|
||||
cfg: CanvasFrameOptions,
|
||||
enableEditing: boolean,
|
||||
showAdvancedTypes: boolean,
|
||||
public onSave: (cfg: CanvasFrameOptions) => void
|
||||
) {
|
||||
this.root = this.load(cfg, enableEditing, showAdvancedTypes);
|
||||
}
|
||||
|
||||
getNextElementName = (isFrame = false) => {
|
||||
@@ -89,7 +95,7 @@ export class Scene {
|
||||
return !this.byName.has(v);
|
||||
};
|
||||
|
||||
load(cfg: CanvasFrameOptions, enableEditing: boolean) {
|
||||
load(cfg: CanvasFrameOptions, enableEditing: boolean, showAdvancedTypes: boolean) {
|
||||
this.root = new RootElement(
|
||||
cfg ?? {
|
||||
type: 'frame',
|
||||
@@ -100,6 +106,7 @@ export class Scene {
|
||||
);
|
||||
|
||||
this.isEditingEnabled = enableEditing;
|
||||
this.shouldShowAdvancedTypes = showAdvancedTypes;
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.div) {
|
||||
|
||||
@@ -52,7 +52,12 @@ export class CanvasPanel extends Component<Props, State> {
|
||||
|
||||
// Only the initial options are ever used.
|
||||
// later changes are all controlled by the scene
|
||||
this.scene = new Scene(this.props.options.root, this.props.options.inlineEditing, this.onUpdateScene);
|
||||
this.scene = new Scene(
|
||||
this.props.options.root,
|
||||
this.props.options.inlineEditing,
|
||||
this.props.options.showAdvancedTypes,
|
||||
this.onUpdateScene
|
||||
);
|
||||
this.scene.updateSize(props.width, props.height);
|
||||
this.scene.updateData(props.data);
|
||||
this.scene.inlineEditingCallback = this.openInlineEdit;
|
||||
@@ -154,9 +159,11 @@ export class CanvasPanel extends Component<Props, State> {
|
||||
// After editing, the options are valid, but the scene was in a different panel or inline editing mode has changed
|
||||
const shouldUpdateSceneAndPanel = this.needsReload && this.props.options !== nextProps.options;
|
||||
const inlineEditingSwitched = this.props.options.inlineEditing !== nextProps.options.inlineEditing;
|
||||
if (shouldUpdateSceneAndPanel || inlineEditingSwitched) {
|
||||
const shouldShowAdvancedTypesSwitched =
|
||||
this.props.options.showAdvancedTypes !== nextProps.options.showAdvancedTypes;
|
||||
if (shouldUpdateSceneAndPanel || inlineEditingSwitched || shouldShowAdvancedTypesSwitched) {
|
||||
this.needsReload = false;
|
||||
this.scene.load(nextProps.options.root, nextProps.options.inlineEditing);
|
||||
this.scene.load(nextProps.options.root, nextProps.options.inlineEditing, nextProps.options.showAdvancedTypes);
|
||||
this.scene.updateSize(nextProps.width, nextProps.height);
|
||||
this.scene.updateData(nextProps.data);
|
||||
changed = true;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { getGlobalStyles } from '../globalStyles';
|
||||
import { PanelOptions } from '../models.gen';
|
||||
import { getTreeData, onNodeDrop, TreeElement } from '../tree';
|
||||
import { DragNode, DropNode } from '../types';
|
||||
import { doSelect } from '../utils';
|
||||
import { doSelect, getElementTypes } from '../utils';
|
||||
|
||||
import { TreeNodeTitle } from './TreeNodeTitle';
|
||||
import { TreeViewEditorProps } from './elementEditor';
|
||||
@@ -133,6 +133,8 @@ export const TreeNavigationEditor = ({ item }: StandardEditorProps<any, TreeView
|
||||
}
|
||||
};
|
||||
|
||||
const typeOptions = getElementTypes(settings.scene.shouldShowAdvancedTypes);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Global styles={globalCSS} />
|
||||
@@ -156,11 +158,7 @@ export const TreeNavigationEditor = ({ item }: StandardEditorProps<any, TreeView
|
||||
|
||||
<HorizontalGroup>
|
||||
<div style={{ marginLeft: '18px' }}>
|
||||
<AddLayerButton
|
||||
onChange={onAddItem}
|
||||
options={canvasElementRegistry.selectOptions().options}
|
||||
label={'Add item'}
|
||||
/>
|
||||
<AddLayerButton onChange={onAddItem} options={typeOptions} label={'Add item'} />
|
||||
</div>
|
||||
{selection.length > 0 && (
|
||||
<Button size="sm" variant="secondary" onClick={onClearSelection}>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { get as lodashGet } from 'lodash';
|
||||
|
||||
import { NestedPanelOptions, NestedValueAccess } from '@grafana/data/src/utils/OptionsUIBuilders';
|
||||
import { CanvasElementOptions, canvasElementRegistry, DEFAULT_CANVAS_ELEMENT_CONFIG } from 'app/features/canvas';
|
||||
import {
|
||||
CanvasElementOptions,
|
||||
canvasElementRegistry,
|
||||
DEFAULT_CANVAS_ELEMENT_CONFIG,
|
||||
defaultElementItems,
|
||||
} from 'app/features/canvas';
|
||||
import { ElementState } from 'app/features/canvas/runtime/element';
|
||||
import { Scene } from 'app/features/canvas/runtime/scene';
|
||||
import { setOptionImmutably } from 'app/features/dashboard/components/PanelEditor/utils';
|
||||
|
||||
import { FrameState } from '../../../../features/canvas/runtime/frame';
|
||||
import { getElementTypes } from '../utils';
|
||||
|
||||
import { PlacementEditor } from './PlacementEditor';
|
||||
import { optionBuilder } from './options';
|
||||
@@ -57,18 +63,21 @@ export function getElementEditor(opts: CanvasEditorOptions): NestedPanelOptions<
|
||||
// Dynamically fill the selected element
|
||||
build: (builder, context) => {
|
||||
const { options } = opts.element;
|
||||
const layerTypes = canvasElementRegistry.selectOptions(
|
||||
options?.type // the selected value
|
||||
? [options.type] // as an array
|
||||
: [DEFAULT_CANVAS_ELEMENT_CONFIG.type]
|
||||
);
|
||||
const current = options?.type ? [options.type] : [DEFAULT_CANVAS_ELEMENT_CONFIG.type];
|
||||
const layerTypes = getElementTypes(opts.scene.shouldShowAdvancedTypes, current);
|
||||
|
||||
const isUnsupported =
|
||||
!opts.scene.shouldShowAdvancedTypes && !defaultElementItems.filter((item) => item.id === options?.type).length;
|
||||
|
||||
builder.addSelect({
|
||||
path: 'type',
|
||||
name: undefined as any, // required, but hide space
|
||||
settings: {
|
||||
options: layerTypes.options,
|
||||
options: layerTypes,
|
||||
},
|
||||
description: isUnsupported
|
||||
? 'Selected element type is not supported by current settings. Please enable advanced element types.'
|
||||
: '',
|
||||
});
|
||||
|
||||
// force clean layer configuration
|
||||
@@ -87,9 +96,6 @@ export function getElementEditor(opts: CanvasEditorOptions): NestedPanelOptions<
|
||||
layer.registerOptionsUI(builder, ctx);
|
||||
}
|
||||
|
||||
optionBuilder.addBackground(builder, ctx);
|
||||
optionBuilder.addBorder(builder, ctx);
|
||||
|
||||
builder.addCustomEditor({
|
||||
category: ['Layout'],
|
||||
id: 'content',
|
||||
@@ -98,6 +104,9 @@ export function getElementEditor(opts: CanvasEditorOptions): NestedPanelOptions<
|
||||
editor: PlacementEditor,
|
||||
settings: opts,
|
||||
});
|
||||
|
||||
optionBuilder.addBackground(builder, ctx);
|
||||
optionBuilder.addBorder(builder, ctx);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@ export const modelVersion = Object.freeze([1, 0]);
|
||||
|
||||
export interface PanelOptions {
|
||||
inlineEditing: boolean;
|
||||
showAdvancedTypes: boolean;
|
||||
root: CanvasFrameOptions;
|
||||
}
|
||||
|
||||
export const defaultPanelOptions: PanelOptions = {
|
||||
inlineEditing: true,
|
||||
showAdvancedTypes: false,
|
||||
root: {
|
||||
elements: [
|
||||
{
|
||||
|
||||
@@ -19,6 +19,13 @@ export const plugin = new PanelPlugin<PanelOptions>(CanvasPanel)
|
||||
defaultValue: true,
|
||||
});
|
||||
|
||||
builder.addBooleanSwitch({
|
||||
path: 'showAdvancedTypes',
|
||||
name: 'Show advanced element types',
|
||||
description: '',
|
||||
defaultValue: false,
|
||||
});
|
||||
|
||||
if (state) {
|
||||
builder.addNestedOptions(getLayerEditor(state));
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { AppEvents } from '@grafana/data/src';
|
||||
|
||||
import appEvents from '../../../core/app_events';
|
||||
import { CanvasElementItem, canvasElementRegistry, defaultElementItems } from '../../../features/canvas';
|
||||
import { ElementState } from '../../../features/canvas/runtime/element';
|
||||
import { FrameState } from '../../../features/canvas/runtime/frame';
|
||||
import { Scene, SelectionParams } from '../../../features/canvas/runtime/scene';
|
||||
@@ -23,3 +24,14 @@ export function doSelect(scene: Scene, element: ElementState | FrameState) {
|
||||
appEvents.emit(AppEvents.alertError, ['Unable to select element, try selecting element in panel instead']);
|
||||
}
|
||||
}
|
||||
|
||||
export function getElementTypes(
|
||||
shouldShowAdvancedTypes: boolean | undefined,
|
||||
current: string[] | undefined = undefined
|
||||
) {
|
||||
return shouldShowAdvancedTypes
|
||||
? canvasElementRegistry.selectOptions(current, (elementItem) => elementItem.id !== 'button').options
|
||||
: canvasElementRegistry.selectOptions(current, (elementItem: CanvasElementItem<any, any>) => {
|
||||
return !!defaultElementItems.filter((item) => item.id === elementItem.id).length;
|
||||
}).options;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user