From 5b3db23b9a0c9b49e123c1b6edbc2fa699aa6443 Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 10 May 2022 17:16:24 +0400 Subject: [PATCH 1/7] thresholds styles --- src/components/editors/ThresholdsEditor.tsx | 24 +++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/components/editors/ThresholdsEditor.tsx b/src/components/editors/ThresholdsEditor.tsx index 3b0a8c8..08bd027 100644 --- a/src/components/editors/ThresholdsEditor.tsx +++ b/src/components/editors/ThresholdsEditor.tsx @@ -1,6 +1,6 @@ import { FieldNamePicker } from '../../grafana/MatchersUI/FieldNamePicker'; -import { StandardEditorProps } from '@grafana/data'; +import { GrafanaTheme, StandardEditorProps } from '@grafana/data'; import { Button, ColorPicker, @@ -9,11 +9,13 @@ import { InlineField, InlineSwitch, Input, + stylesFactory, ThemeContext, } from '@grafana/ui'; import React from 'react'; +import { css } from 'emotion'; import * as _ from 'lodash'; interface Props { @@ -65,11 +67,12 @@ export function ThresholdsEditor({ onChange, value, context }: StandardEditorPro return ( - {() => { - // const styles = getStyles(theme.v1); + {(theme) => { + const styles = getStyles(theme.v1); return (
{config.thresholds.map((threshold, thresholdIdx) => { return ( - + ); } + +interface ThresholdsEditorStyles { + row: string; +} + +const getStyles = stylesFactory((theme: GrafanaTheme): ThresholdsEditorStyles => { + return { + row: css` + margin-bottom: ${theme.spacing.sm}; + `, + }; +}); From c450a4150e08bbac7f7f9f93be236c9b4e7d56d9 Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 10 May 2022 17:30:42 +0400 Subject: [PATCH 2/7] more styles --- src/components/editors/IconsEditor.tsx | 102 ++++++++++++-------- src/components/editors/ThresholdsEditor.tsx | 8 +- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/components/editors/IconsEditor.tsx b/src/components/editors/IconsEditor.tsx index ac6b6ee..db64e56 100644 --- a/src/components/editors/IconsEditor.tsx +++ b/src/components/editors/IconsEditor.tsx @@ -121,7 +121,6 @@ export function IconsEditor({ onChange, value, context }: StandardEditorProps { - console.log(value); // @ts-ignore icons[iconIdx][field][conditionIdx] = value; @@ -138,52 +137,63 @@ export function IconsEditor({ onChange, value, context }: StandardEditorProps { return (
- removeIcon(iconIdx)}> - onIconFieldChange(iconIdx, 'url', (evt.target as any).value)} - /> + removeIcon(iconIdx)} + tooltip="Delete Icon" + > +
+ onIconFieldChange(iconIdx, 'url', (evt.target as any).value)} + /> +
onIconFieldChange(iconIdx, 'position', newVal)} /> - onIconFieldChange(iconIdx, 'size', newVal)} - /> +
+ onIconFieldChange(iconIdx, 'size', newVal)} + /> +
{icon.conditions.map((condition, conditionIdx) => { return ( - - onConditionChange(iconIdx, conditionIdx, 'metrics', newVal)} - item={fieldNamePickerSettings} - /> - onConditionChange(iconIdx, conditionIdx, 'conditions', newVal)} - /> - - onConditionChange(iconIdx, conditionIdx, 'values', (evt.target as any).value) - } - /> - removeCondition(iconIdx, conditionIdx)} - > - +
+ + onConditionChange(iconIdx, conditionIdx, 'metrics', newVal)} + item={fieldNamePickerSettings} + /> + onConditionChange(iconIdx, conditionIdx, 'conditions', newVal)} + /> + + onConditionChange(iconIdx, conditionIdx, 'values', (evt.target as any).value) + } + /> + removeCondition(iconIdx, conditionIdx)} + tooltip="Delete Condition" + > + +
); })}
- } - /> + + + onFieldChange('defaultColor', val)} + enableNamedColors={true} + /> + + + + + + onFieldChange('arcBackground', val)} + enableNamedColors={true} + /> + + {config.thresholds.map((threshold, thresholdIdx) => { return ( - - onThresholdFieldChange(thresholdIdx, 'color', newVal)} - enableNamedColors={true} - /> -
- } - /> onThresholdFieldChange(thresholdIdx, 'useMetric', (evt.target as any).checked)} /> - {threshold.useMetric ? ( - onThresholdFieldChange(thresholdIdx, 'metricName', newVal)} - item={fieldNamePickerSettings} - /> - ) : ( - onThresholdFieldChange(thresholdIdx, 'value', (evt.target as any).value)} - /> - )} - removeThreshold(thresholdIdx)} - tooltip="Delete Threshold" - > + + {threshold.useMetric ? ( + onThresholdFieldChange(thresholdIdx, 'metricName', newVal)} + item={fieldNamePickerSettings} + /> + ) : ( + onThresholdFieldChange(thresholdIdx, 'value', (evt.target as any).value)} + /> + )} + + + + onThresholdFieldChange(thresholdIdx, 'color', newVal)} + enableNamedColors={true} + /> + + + + + removeThreshold(thresholdIdx)} + tooltip="Delete Threshold" + > + + ); })} @@ -157,13 +149,13 @@ export function ThresholdsEditor({ onChange, value, context }: StandardEditorPro } interface ThresholdsEditorStyles { - row: string; + deleteButton: string; } const getStyles = stylesFactory((theme: GrafanaTheme): ThresholdsEditorStyles => { return { - row: css` - margin-bottom: ${theme.spacing.sm}; + deleteButton: css` + margin-right: 0px!important; `, }; }); From 05e1cf33e6beef1d0c3fb420beaae0be336e8164 Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 10 May 2022 18:02:46 +0400 Subject: [PATCH 4/7] "To be supported" for non-gauge visualizations --- src/components/editors/NotSupportedText.tsx | 5 +++++ src/module.ts | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 src/components/editors/NotSupportedText.tsx diff --git a/src/components/editors/NotSupportedText.tsx b/src/components/editors/NotSupportedText.tsx new file mode 100644 index 0000000..22c4432 --- /dev/null +++ b/src/components/editors/NotSupportedText.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export function NotSupportedText() { + return
To be supported soon...
+} diff --git a/src/module.ts b/src/module.ts index e366a4a..ce2912e 100644 --- a/src/module.ts +++ b/src/module.ts @@ -5,6 +5,7 @@ import { IconsEditor } from './components/editors/IconsEditor'; import { ThresholdsEditor } from './components/editors/ThresholdsEditor'; import { PanelPlugin } from '@grafana/data'; +import { NotSupportedText } from 'components/editors/NotSupportedText'; export const plugin = new PanelPlugin(Panel).setPanelOptions((builder) => { return builder @@ -18,21 +19,26 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil { label: 'Gauge', value: Pod.GAUGE, - description: 'Enable gauge pod', }, { label: 'Line', value: Pod.LINE, - description: 'Enable line pod', }, { label: 'Bar', value: Pod.BAR, - description: 'Enable bar pod', }, ], }, }) + .addCustomEditor({ + id: 'notSupportedText', + name: 'This visualization is not supported', + category: ['Visualization'], + path: '', + showIf: (config) => config.visualizationType !== Pod.GAUGE, + editor: NotSupportedText as any, + }) .addFieldNamePicker({ name: 'Value', From 44bcfcac852e8f267b399318f61def66d45f3ea4 Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 10 May 2022 18:10:57 +0400 Subject: [PATCH 5/7] disable named colors --- src/components/editors/ThresholdsEditor.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/editors/ThresholdsEditor.tsx b/src/components/editors/ThresholdsEditor.tsx index 358a3e2..f31df00 100644 --- a/src/components/editors/ThresholdsEditor.tsx +++ b/src/components/editors/ThresholdsEditor.tsx @@ -78,7 +78,7 @@ export function ThresholdsEditor({ onChange, value, context }: StandardEditorPro onFieldChange('defaultColor', val)} - enableNamedColors={true} + enableNamedColors={false} /> @@ -88,7 +88,7 @@ export function ThresholdsEditor({ onChange, value, context }: StandardEditorPro onFieldChange('arcBackground', val)} - enableNamedColors={true} + enableNamedColors={false} /> @@ -122,7 +122,7 @@ export function ThresholdsEditor({ onChange, value, context }: StandardEditorPro onThresholdFieldChange(thresholdIdx, 'color', newVal)} - enableNamedColors={true} + enableNamedColors={false} /> From c6b93ef3c01bef429b7d30ee7a622cc41083f5df Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 10 May 2022 18:21:02 +0400 Subject: [PATCH 6/7] all options --- src/module.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/module.ts b/src/module.ts index ce2912e..18f561e 100644 --- a/src/module.ts +++ b/src/module.ts @@ -53,6 +53,7 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil category: ['Extremum'], showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.min.useMetric, }) + // TODO: move these 2 editors into one-row custom editor .addFieldNamePicker({ name: 'Min', path: 'gauge.min.metricName', @@ -67,6 +68,37 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil showIf: (config) => config.visualizationType === Pod.GAUGE, }) + // note: `gauge.unit` will contain unit name, not it's string representation + // to format value with unit, use `getValueFormat` function from `@grafana/data` + .addUnitPicker({ + path: 'gauge.unit', + name: 'Unit', + category: ['Value Format'], + showIf: (config) => config.visualizationType === Pod.GAUGE, + }) + .addNumberInput({ + path: 'gauge.decimals', + name: 'Decimals', + settings: { + placeholder: 'auto', + min: 0, + max: 5, + }, + category: ['Value Format'], + showIf: (config) => config.visualizationType === Pod.GAUGE, + }) + .addSliderInput({ + path: 'gauge.size', + defaultValue: 20, + name: 'Size (px)', + settings: { + min: 1, + max: 50, + }, + category: ['Value Format'], + showIf: (config) => config.visualizationType === Pod.GAUGE, + }) + .addNumberInput({ path: 'gauge.max.value', name: 'Max', From f75abc9349073cb771746c70db7bec5b9bd17983 Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 10 May 2022 18:33:03 +0400 Subject: [PATCH 7/7] new UseMetricEditor --- src/components/editors/UseMetricEditor.tsx | 62 ++++++++++++++++++++++ src/module.ts | 53 ++++++------------ 2 files changed, 79 insertions(+), 36 deletions(-) create mode 100644 src/components/editors/UseMetricEditor.tsx diff --git a/src/components/editors/UseMetricEditor.tsx b/src/components/editors/UseMetricEditor.tsx new file mode 100644 index 0000000..37f7de0 --- /dev/null +++ b/src/components/editors/UseMetricEditor.tsx @@ -0,0 +1,62 @@ +import { FieldNamePicker } from '../../grafana/MatchersUI/FieldNamePicker'; + +import { StandardEditorProps } from '@grafana/data'; +import { + HorizontalGroup, + InlineField, + InlineSwitch, + Input, +} from '@grafana/ui'; + +import React from 'react'; + +import * as _ from 'lodash'; + + +type UseMetricConfig = { + useMetric: boolean; + value?: number; + metricName?: string; +}; + +const fieldNamePickerSettings = { + settings: { width: 24 }, +} as any; + +export function UseMetricEditor({ onChange, value, context }: StandardEditorProps) { + const config = value; + + const onFieldChange = (field: keyof UseMetricConfig, value: any) => { + // @ts-ignore + config[field] = value; + + onChange(config); + } + + return ( + + + onFieldChange('useMetric', (evt.target as any).checked)} + /> + + + {config.useMetric ? ( + onFieldChange('metricName', newVal)} + item={fieldNamePickerSettings} + /> + ) : ( + onFieldChange('value', (evt.target as any).value)} + /> + )} + + + ) +} diff --git a/src/module.ts b/src/module.ts index 18f561e..af79332 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,11 +1,14 @@ import { PanelOptions, Pod } from './types'; import { Panel } from './components/Panel'; + import { IconsEditor } from './components/editors/IconsEditor'; import { ThresholdsEditor } from './components/editors/ThresholdsEditor'; +import { NotSupportedText } from './components/editors/NotSupportedText'; +import { UseMetricEditor } from './components/editors/UseMetricEditor'; import { PanelPlugin } from '@grafana/data'; -import { NotSupportedText } from 'components/editors/NotSupportedText'; + export const plugin = new PanelPlugin(Panel).setPanelOptions((builder) => { return builder @@ -46,26 +49,22 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil category: ['Extremum'], showIf: (config) => config.visualizationType === Pod.GAUGE, }) - - .addNumberInput({ - path: 'gauge.min.value', - name: 'Min', - category: ['Extremum'], - showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.min.useMetric, - }) - // TODO: move these 2 editors into one-row custom editor - .addFieldNamePicker({ + // TODO: defaults? + .addCustomEditor({ + id: 'min', name: 'Min', - path: 'gauge.min.metricName', + path: 'gauge.min', category: ['Extremum'], - showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.min.useMetric, - }) - .addBooleanSwitch({ - path: 'gauge.min.useMetric', - name: 'Use metric', - defaultValue: false, + showIf: (config) => config.visualizationType === Pod.GAUGE, + editor: UseMetricEditor as any, + }). + addCustomEditor({ + id: 'max', + name: 'Max', + path: 'gauge.max', category: ['Extremum'], showIf: (config) => config.visualizationType === Pod.GAUGE, + editor: UseMetricEditor as any, }) // note: `gauge.unit` will contain unit name, not it's string representation @@ -99,25 +98,6 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil showIf: (config) => config.visualizationType === Pod.GAUGE, }) - .addNumberInput({ - path: 'gauge.max.value', - name: 'Max', - category: ['Extremum'], - showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.max.useMetric, - }) - .addFieldNamePicker({ - name: 'Max', - path: 'gauge.max.metricName', - category: ['Extremum'], - showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.max.useMetric, - }) - .addBooleanSwitch({ - path: 'gauge.max.useMetric', - name: 'Use metric', - defaultValue: false, - category: ['Extremum'], - showIf: (config) => config.visualizationType === Pod.GAUGE, - }) .addBooleanSwitch({ path: 'gauge.reversed', name: 'Reversed', @@ -125,6 +105,7 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil category: ['Direction'], showIf: (config) => config.visualizationType === Pod.GAUGE, }) + .addCustomEditor({ id: 'icons', path: 'gauge.icons',