From c002a39456c55fa6f232c740b75af45a1cfe384d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 28 Feb 2020 11:04:40 +0100 Subject: [PATCH] NewPanelEditor: Angular panel options, and angular component state to redux major change (#22448) * NewPanelEdit: Added angular options to new panel editor and started looking and angular component state * Moved angular component state to redux * Close to working 100% * Think everything is working * AlertTab: Alert tab now gets angularComponent from redux * Fixed panel menu access to angular panel component * Added new tests * Fixed unit test * Fixed strict null errors * Fixed typescript issues * fixed issues --- .../src/valueFormats/valueFormats.ts | 15 ++- .../components/DataLinks/DataLinksEditor.tsx | 106 +++++++-------- .../src/components/Table/Table.story.tsx | 18 +-- .../TableInputCSV/TableInputCSV.story.tsx | 2 +- .../ThresholdsEditor/ThresholdsEditor.tsx | 73 ++++++----- .../ThresholdsEditor.test.tsx | 2 +- public/app/features/alerting/AlertTab.tsx | 33 +++-- .../PanelEditor/AngularPanelOptions.tsx | 122 ++++++++++++++++++ .../components/PanelEditor/PanelEditor.tsx | 31 +++-- .../PanelEditor/state/actions.test.ts | 66 +++++++++- .../components/PanelEditor/state/actions.ts | 9 +- .../__snapshots__/DashboardPage.test.tsx.snap | 7 - .../dashboard/dashgrid/DashboardPanel.tsx | 7 +- .../dashboard/dashgrid/PanelChromeAngular.tsx | 53 ++++++-- .../dashgrid/PanelHeader/PanelHeader.tsx | 6 +- .../__snapshots__/DashboardGrid.test.tsx.snap | 20 --- .../panel_editor/AngularPanelOptions.tsx | 45 +++++-- .../panel_editor/VisualizationTab.tsx | 11 +- .../dashboard/state/PanelModel.test.ts | 17 --- .../features/dashboard/state/PanelModel.ts | 27 +--- .../app/features/dashboard/state/actions.ts | 12 +- .../app/features/dashboard/state/reducers.ts | 10 ++ .../features/dashboard/utils/getPanelMenu.ts | 12 +- .../panel/bargauge/BarGaugePanelEditor.tsx | 7 +- .../plugins/panel/gauge/GaugePanelEditor.tsx | 7 +- .../plugins/panel/stat/StatPanelEditor.tsx | 7 +- public/app/types/dashboard.ts | 2 + 27 files changed, 464 insertions(+), 263 deletions(-) create mode 100644 public/app/features/dashboard/components/PanelEditor/AngularPanelOptions.tsx diff --git a/packages/grafana-data/src/valueFormats/valueFormats.ts b/packages/grafana-data/src/valueFormats/valueFormats.ts index 020de440f24..d888d6e2ee5 100644 --- a/packages/grafana-data/src/valueFormats/valueFormats.ts +++ b/packages/grafana-data/src/valueFormats/valueFormats.ts @@ -176,37 +176,50 @@ function buildFormats() { hasBuiltIndex = true; } -export function getValueFormat(id: string): ValueFormatter { +export function getValueFormat(id?: string | null): ValueFormatter { + if (!id) { + return toFixedUnit(''); + } + if (!hasBuiltIndex) { buildFormats(); } const fmt = index[id]; + if (!fmt && id) { const idx = id.indexOf(':'); + if (idx > 0) { const key = id.substring(0, idx); const sub = id.substring(idx + 1); + if (key === 'prefix') { return toFixedUnit(sub, true); } + if (key === 'time') { return toDateTimeValueFormatter(sub); } + if (key === 'si') { const offset = getOffsetFromSIPrefix(sub.charAt(0)); const unit = offset === 0 ? sub : sub.substring(1); return decimalSIPrefix(unit, offset); } + if (key === 'count') { return simpleCountUnit(sub); } + if (key === 'currency') { return currency(sub); } } + return toFixedUnit(id); } + return fmt; } diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx index 34278b9f6a3..b3e33522204 100644 --- a/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx +++ b/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx @@ -11,7 +11,7 @@ import { DataLinkEditor } from './DataLinkEditor'; import { useTheme } from '../../themes/ThemeContext'; interface DataLinksEditorProps { - value: DataLink[]; + value?: DataLink[]; onChange: (links: DataLink[], callback?: () => void) => void; suggestions: VariableSuggestion[]; maxLinks?: number; @@ -25,59 +25,61 @@ export const enableDatalinksPrismSyntax = () => { }; }; -export const DataLinksEditor: FC = React.memo(({ value, onChange, suggestions, maxLinks }) => { - const theme = useTheme(); - enableDatalinksPrismSyntax(); +export const DataLinksEditor: FC = React.memo( + ({ value = [], onChange, suggestions, maxLinks }) => { + const theme = useTheme(); + enableDatalinksPrismSyntax(); - const onAdd = () => { - onChange(value ? [...value, { url: '', title: '' }] : [{ url: '', title: '' }]); - }; + const onAdd = () => { + onChange(value ? [...value, { url: '', title: '' }] : [{ url: '', title: '' }]); + }; - const onLinkChanged = (linkIndex: number, newLink: DataLink, callback?: () => void) => { - onChange( - value.map((item, listIndex) => { - if (linkIndex === listIndex) { - return newLink; - } - return item; - }), - callback + const onLinkChanged = (linkIndex: number, newLink: DataLink, callback?: () => void) => { + onChange( + value.map((item, listIndex) => { + if (linkIndex === listIndex) { + return newLink; + } + return item; + }), + callback + ); + }; + + const onRemove = (link: DataLink) => { + onChange(value.filter(item => item !== link)); + }; + + return ( + <> + {value && value.length > 0 && ( +
+ {value.map((link, index) => ( + + ))} +
+ )} + + {(!value || (value && value.length < (maxLinks || Infinity))) && ( + + )} + ); - }; - - const onRemove = (link: DataLink) => { - onChange(value.filter(item => item !== link)); - }; - - return ( - <> - {value && value.length > 0 && ( -
- {value.map((link, index) => ( - - ))} -
- )} - - {(!value || (value && value.length < (maxLinks || Infinity))) && ( - - )} - - ); -}); + } +); DataLinksEditor.displayName = 'DataLinksEditor'; diff --git a/packages/grafana-ui/src/components/Table/Table.story.tsx b/packages/grafana-ui/src/components/Table/Table.story.tsx index fcd776a5c83..ba133ef82ae 100644 --- a/packages/grafana-ui/src/components/Table/Table.story.tsx +++ b/packages/grafana-ui/src/components/Table/Table.story.tsx @@ -105,10 +105,10 @@ export const BarGaugeCell = () => { { matcher: { id: FieldMatcherID.byName, options: 'Progress' }, properties: [ - { path: 'custom.width', value: '200' }, - { path: 'custom.displayMode', value: 'gradient-gauge' }, - { path: 'min', value: '0' }, - { path: 'max', value: '100' }, + { prop: 'width', value: '200', custom: true }, + { prop: 'displayMode', value: 'gradient-gauge', custom: true }, + { prop: 'min', value: '0' }, + { prop: 'max', value: '100' }, ], }, ]); @@ -141,11 +141,11 @@ export const ColoredCells = () => { { matcher: { id: FieldMatcherID.byName, options: 'Progress' }, properties: [ - { path: 'custom.width', value: '80' }, - { path: 'custom.displayMode', value: 'color-background' }, - { path: 'min', value: '0' }, - { path: 'max', value: '100' }, - { path: 'thresholds', value: defaultThresholds }, + { prop: 'width', value: '80', custom: true }, + { prop: 'displayMode', value: 'color-background', custom: true }, + { prop: 'min', value: '0' }, + { prop: 'max', value: '100' }, + { prop: 'thresholds', value: defaultThresholds }, ], }, ]); diff --git a/packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx b/packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx index c0070b8ec8a..87839533f51 100644 --- a/packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx +++ b/packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx @@ -6,7 +6,7 @@ import { action } from '@storybook/addon-actions'; import { DataFrame } from '@grafana/data'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; -const TableInputStories = storiesOf('General/Table/Input', module); +const TableInputStories = storiesOf('General/Experimental/TableInputCSV', module); TableInputStories.addDecorator(withCenteredStory); diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx index 6cfbc7e00ec..522b34b8e0a 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx @@ -6,21 +6,10 @@ import { ThemeContext } from '../../themes/ThemeContext'; import { Input } from '../Input/Input'; import { ColorPicker } from '../ColorPicker/ColorPicker'; import { css } from 'emotion'; -import Select from '../Select/Select'; import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup'; -const modes: Array> = [ - { value: ThresholdsMode.Absolute, label: 'Absolute', description: 'Pick thresholds based on the absolute values' }, - { - value: ThresholdsMode.Percentage, - label: 'Percentage', - description: 'Pick threshold based on the percent between min/max', - }, -]; - export interface Props { - showAlphaUI?: boolean; - thresholds: ThresholdsConfig; + thresholds?: ThresholdsConfig; onChange: (thresholds: ThresholdsConfig) => void; } @@ -34,25 +23,11 @@ interface ThresholdWithKey extends Threshold { let counter = 100; -function toThresholdsWithKey(steps?: Threshold[]): ThresholdWithKey[] { - if (!steps || steps.length === 0) { - steps = [{ value: -Infinity, color: 'green' }]; - } - - return steps.map(t => { - return { - color: t.color, - value: t.value === null ? -Infinity : t.value, - key: counter++, - }; - }); -} - export class ThresholdsEditor extends PureComponent { constructor(props: Props) { super(props); - const steps = toThresholdsWithKey(props.thresholds!.steps); + const steps = toThresholdsWithKey(props.thresholds); steps[0].value = -Infinity; this.state = { steps }; @@ -165,14 +140,16 @@ export class ThresholdsEditor extends PureComponent { onModeChanged = (item: SelectableValue) => { if (item.value) { this.props.onChange({ - ...this.props.thresholds, + ...getThresholdOrDefault(this.props.thresholds), mode: item.value, }); } }; renderInput = (threshold: ThresholdWithKey) => { - const isPercent = this.props.thresholds.mode === ThresholdsMode.Percentage; + const config = getThresholdOrDefault(this.props.thresholds); + const isPercent = config.mode === ThresholdsMode.Percentage; + return (
@@ -218,7 +195,7 @@ export class ThresholdsEditor extends PureComponent { render() { const { steps } = this.state; - const t = this.props.thresholds; + return ( @@ -243,12 +220,6 @@ export class ThresholdsEditor extends PureComponent { ); })}
- - {this.props.showAlphaUI && ( -
-