From 58639ee53e487852a1c563521c08a3e21339855a Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Sun, 9 Feb 2020 18:47:48 +0100 Subject: [PATCH] New Editor: Add ValuePicker for overrides selection (#22048) --- .../FieldConfigs/FieldConfigEditor.tsx | 73 ++++++++++--------- .../components/Forms/Select/Select.story.tsx | 2 +- .../ValuePicker/ValuePicker.story.tsx | 22 ++++++ .../components/ValuePicker/ValuePicker.tsx | 43 +++++++++++ packages/grafana-ui/src/components/index.ts | 1 + 5 files changed, 106 insertions(+), 35 deletions(-) create mode 100644 packages/grafana-ui/src/components/ValuePicker/ValuePicker.story.tsx create mode 100644 packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx diff --git a/packages/grafana-ui/src/components/FieldConfigs/FieldConfigEditor.tsx b/packages/grafana-ui/src/components/FieldConfigs/FieldConfigEditor.tsx index 03c65a9ee6c..16b51367a29 100644 --- a/packages/grafana-ui/src/components/FieldConfigs/FieldConfigEditor.tsx +++ b/packages/grafana-ui/src/components/FieldConfigs/FieldConfigEditor.tsx @@ -11,6 +11,7 @@ import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRe import Forms from '../Forms'; import { fieldMatchersUI } from '../MatchersUI/fieldMatchersUI'; import { ControlledCollapse } from '../Collapse/Collapse'; +import { ValuePicker } from '../ValuePicker/ValuePicker'; interface Props { config: FieldConfigSource; @@ -116,6 +117,9 @@ export class FieldConfigEditor extends React.PureComponent { renderOverrides() { const { config, data, custom } = this.props; + if (config.overrides.length === 0) { + return null; + } let configPropertiesOptions = standardFieldConfigEditorRegistry.list().map(i => ({ label: i.name, @@ -136,11 +140,11 @@ export class FieldConfigEditor extends React.PureComponent { } return ( - <> +
{config.overrides.map((o, i) => { const matcherUi = fieldMatchersUI.get(o.matcher.id); return ( -
+
<> { options={o.matcher.options} onChange={option => this.onMatcherConfigChange(i, option)} /> - { - this.onDynamicConfigValueAdd(i, o.value!, o.custom); - }} - /> - {o.properties.map((p, j) => { - const reg = p.custom ? custom : standardFieldConfigEditorRegistry; - const item = reg?.get(p.prop); - if (!item) { - return
Unknown property: {p.prop}
; - } - return ( - - { - this.onDynamicConfigValueChange(i, j, value); - }} - item={item} - context={{} as any} - /> - - ); - })} +
+ {o.properties.map((p, j) => { + const reg = p.custom ? custom : standardFieldConfigEditorRegistry; + const item = reg?.getIfExists(p.prop); + if (!item) { + return
Unknown property: {p.prop}
; + } + return ( + + { + this.onDynamicConfigValueChange(i, j, value); + }} + item={item} + context={{} as any} + /> + + ); + })} + { + this.onDynamicConfigValueAdd(i, o.value!, o.custom); + }} + /> +
); })} - +
); } renderAddOverride = () => { return ( - ({ label: i.name, value: i.id, description: i.description }))} onChange={value => { const { onChange, config } = this.props; @@ -223,8 +228,8 @@ export class FieldConfigEditor extends React.PureComponent { )} - {this.renderAddOverride()} {this.renderOverrides()} + {this.renderAddOverride()}
); diff --git a/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx b/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx index eb4397b1951..5e42121c6d2 100644 --- a/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx +++ b/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx @@ -16,7 +16,7 @@ export default { decorators: [withCenteredStory, withHorizontallyCenteredStory], }; -const generateOptions = () => { +export const generateOptions = () => { const values = [ 'Sharilyn Markowitz', 'Naomi Striplin', diff --git a/packages/grafana-ui/src/components/ValuePicker/ValuePicker.story.tsx b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.story.tsx new file mode 100644 index 00000000000..629141b5c82 --- /dev/null +++ b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.story.tsx @@ -0,0 +1,22 @@ +import { text } from '@storybook/addon-knobs'; +import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; +import { ValuePicker } from './ValuePicker'; +import React from 'react'; +import { generateOptions } from '../Forms/Select/Select.story'; + +export default { + title: 'General/ValuePicker', + component: ValuePicker, + decorators: [withCenteredStory], +}; + +const options = generateOptions(); + +export const simple = () => { + const label = text('Label', 'Pick an option'); + return ( +
+ console.log(v)} /> +
+ ); +}; diff --git a/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx new file mode 100644 index 00000000000..7a86fb1ae10 --- /dev/null +++ b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx @@ -0,0 +1,43 @@ +import React, { useState } from 'react'; +import { IconType } from '../Icon/types'; +import { SelectableValue } from '@grafana/data'; +import { Button } from '../Forms/Button'; +import { Select } from '../Forms/Select/Select'; + +interface ValuePickerProps { + /** Label to display on the picker button */ + label: string; + /** Icon to display on the picker button */ + icon?: IconType; + /** ValuePicker options */ + options: Array>; + onChange: (value: SelectableValue) => void; +} + +export function ValuePicker({ label, icon, options, onChange }: ValuePickerProps) { + const [isPicking, setIsPicking] = useState(false); + + return ( + <> + {!isPicking && ( + + )} + + {isPicking && ( +