From 539edba31baa555a3e417e3db592b57acf762f6f Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Sat, 18 Apr 2020 14:05:38 +0200 Subject: [PATCH] Overrides: Show option group counters for options that represent collections (#23655) --- .../src/types/OptionsUIRegistryBuilder.ts | 5 +++ .../grafana-ui/src/utils/standardEditors.tsx | 3 ++ .../PanelEditor/DynamicConfigValueEditor.tsx | 17 ++++++---- .../PanelEditor/FieldConfigEditor.tsx | 31 ++++++++++++++++++- .../PanelEditor/OptionsPaneContent.tsx | 8 ++++- .../PanelEditor/PanelOptionsTab.tsx | 12 ++++++- 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts b/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts index 9586383214a..d0f26f0ec0a 100644 --- a/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts +++ b/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts @@ -41,6 +41,11 @@ export interface OptionsEditorItem ex * @param currentConfig Current options values */ showIf?: (currentConfig: TOptions) => boolean; + /** + * Function that returns number of items if given option represents a collection, i.e. array of items. + * @param value + */ + getItemsCount?: (value?: TValue) => number; } /** diff --git a/packages/grafana-ui/src/utils/standardEditors.tsx b/packages/grafana-ui/src/utils/standardEditors.tsx index 3bdcea7b38e..e65ba51653b 100644 --- a/packages/grafana-ui/src/utils/standardEditors.tsx +++ b/packages/grafana-ui/src/utils/standardEditors.tsx @@ -143,6 +143,7 @@ export const getStandardFieldConfigs = () => { }, shouldApply: field => field.type === FieldType.number, category: ['Color & thresholds'], + getItemsCount: value => (value ? value.steps.length : 0), }; const mappings: FieldConfigPropertyItem = { @@ -158,6 +159,7 @@ export const getStandardFieldConfigs = () => { defaultValue: [], shouldApply: field => field.type === FieldType.number, category: ['Value mappings'], + getItemsCount: (value?) => (value ? value.length : 0), }; const noValue: FieldConfigPropertyItem = { @@ -191,6 +193,7 @@ export const getStandardFieldConfigs = () => { }, shouldApply: () => true, category: ['Data links'], + getItemsCount: value => (value ? value.length : 0), }; const color: FieldConfigPropertyItem = { diff --git a/public/app/features/dashboard/components/PanelEditor/DynamicConfigValueEditor.tsx b/public/app/features/dashboard/components/PanelEditor/DynamicConfigValueEditor.tsx index 15de760f714..3046cbf4e80 100644 --- a/public/app/features/dashboard/components/PanelEditor/DynamicConfigValueEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/DynamicConfigValueEditor.tsx @@ -1,8 +1,9 @@ import { DynamicConfigValue, FieldConfigOptionsRegistry, FieldOverrideContext, GrafanaTheme } from '@grafana/data'; import React from 'react'; -import { Field, HorizontalGroup, IconButton, IconName, Label, stylesFactory, useTheme } from '@grafana/ui'; +import { Field, HorizontalGroup, IconButton, Label, stylesFactory, useTheme } from '@grafana/ui'; import { css, cx } from 'emotion'; import { OptionsGroup } from './OptionsGroup'; +import { Counter } from '@grafana/ui/src/components/Tabs/Counter'; interface DynamicConfigValueEditorProps { property: DynamicConfigValue; registry: FieldConfigOptionsRegistry; @@ -28,11 +29,15 @@ export const DynamicConfigValueEditor: React.FC = return null; } let editor; - const renderLabel = (iconName: IconName, includeDescription = true) => () => ( + + const renderLabel = (includeDescription = true, includeCounter = false) => (isExpanded = false) => ( - +
- +
); @@ -40,7 +45,7 @@ export const DynamicConfigValueEditor: React.FC = if (isCollapsible) { editor = ( = } else { editor = (
- + { diff --git a/public/app/features/dashboard/components/PanelEditor/FieldConfigEditor.tsx b/public/app/features/dashboard/components/PanelEditor/FieldConfigEditor.tsx index 1ec53f4aa22..ade7f808477 100644 --- a/public/app/features/dashboard/components/PanelEditor/FieldConfigEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/FieldConfigEditor.tsx @@ -13,6 +13,7 @@ import { getDataLinksVariableSuggestions } from '../../../panel/panellinks/link_ import { OverrideEditor } from './OverrideEditor'; import groupBy from 'lodash/groupBy'; import { OptionsGroup } from './OptionsGroup'; +import { Counter } from '@grafana/ui/src/components/Tabs/Counter'; interface Props { plugin: PanelPlugin; @@ -180,8 +181,19 @@ export const DefaultFieldConfigEditor: React.FC = ({ data, onChange, conf return ( <> {Object.keys(groupedConfigs).map((k, i) => { + const groupItemsCounter = countGroupItems(groupedConfigs[k], config); + return ( - + { + return ( + <> + {k} {!isExpanded && groupItemsCounter && } + + ); + }} + key={`${k}/${i}`} + > <> {groupedConfigs[k].map(c => { return renderEditor(c); @@ -193,3 +205,20 @@ export const DefaultFieldConfigEditor: React.FC = ({ data, onChange, conf ); }; + +const countGroupItems = (group: FieldConfigPropertyItem[], config: FieldConfigSource) => { + let counter = 0; + + for (const item of group) { + const value = item.isCustom + ? config.defaults.custom + ? config.defaults.custom[item.path] + : undefined + : (config.defaults as any)[item.path]; + if (item.getItemsCount && item.getItemsCount(value) > 0) { + counter = counter + item.getItemsCount(value); + } + } + + return counter === 0 ? undefined : counter; +}; diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx index adae6f20efe..cff46e45e6e 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx @@ -91,6 +91,7 @@ export const OptionsPaneContent: React.FC<{ onClose={onClose} setSearchMode={setSearchMode} setActiveTab={setActiveTab} + panel={panel} /> @@ -128,7 +129,11 @@ export const TabsBarContent: React.FC<{ onClose: () => void; setSearchMode: (mode: boolean) => void; setActiveTab: (tab: string) => void; -}> = ({ width, showFields, isSearching, activeTab, onClose, setSearchMode, setActiveTab, styles }) => { + panel: PanelModel; +}> = ({ width, showFields, isSearching, activeTab, onClose, setSearchMode, setActiveTab, styles, panel }) => { + const overridesCount = + panel.getFieldConfig().overrides.length === 0 ? undefined : panel.getFieldConfig().overrides.length; + if (isSearching) { const defaultStyles = { transition: 'width 50ms ease-in-out', @@ -190,6 +195,7 @@ export const TabsBarContent: React.FC<{ setActiveTab(item.value)} /> diff --git a/public/app/features/dashboard/components/PanelEditor/PanelOptionsTab.tsx b/public/app/features/dashboard/components/PanelEditor/PanelOptionsTab.tsx index 400440c3110..bb0c88d3243 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelOptionsTab.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelOptionsTab.tsx @@ -7,6 +7,7 @@ import { getPanelLinksVariableSuggestions } from '../../../panel/panellinks/link import { getVariables } from '../../../variables/state/selectors'; import { PanelOptionsEditor } from './PanelOptionsEditor'; import { AngularPanelOptions } from '../../panel_editor/AngularPanelOptions'; +import { Counter } from '@grafana/ui/src/components/Tabs/Counter'; interface Props { panel: PanelModel; @@ -29,6 +30,7 @@ export const PanelOptionsTab: FC = ({ }) => { const elements: JSX.Element[] = []; const linkVariablesSuggestions = useMemo(() => getPanelLinksVariableSuggestions(), []); + const panelLinksCount = panel && panel.links ? panel.links.length : undefined; const variableOptions = getVariableOptions(); const directionOptions = [ @@ -89,7 +91,15 @@ export const PanelOptionsTab: FC = ({ } elements.push( - + ( + <> + Panel links {!isExpanded && panelLinksCount && panelLinksCount !== 0 && } + + )} + key="panel links" + defaultToClosed={true} + > onPanelConfigChange('links', links)}