Commit ca385805 by Hugo Häggmark Committed by GitHub

PanelEditor: stores option group collapse state (#23781)

* PanelEditor: stores option group collapse state

* Refactor: adds props to OptionsGroup instead
parent 319a0585
......@@ -45,6 +45,7 @@ export const DynamicConfigValueEditor: React.FC<DynamicConfigValueEditorProps> =
if (isCollapsible) {
editor = (
<OptionsGroup
id={item.name}
renderTitle={renderLabel(false, true)}
className={css`
padding-left: 0;
......
......@@ -195,6 +195,7 @@ export const DefaultFieldConfigEditor: React.FC<Props> = ({ data, onChange, conf
</>
);
}}
id={`${k}/${i}`}
key={`${k}/${i}`}
>
{groupedConfigs[k].map(c => {
......
import React, { useState, FC, useEffect } from 'react';
import React, { FC, memo, useCallback, useEffect, useState } from 'react';
import { css, cx } from 'emotion';
import { GrafanaTheme } from '@grafana/data';
import { useTheme, Icon, stylesFactory } from '@grafana/ui';
import { Icon, stylesFactory, useTheme } from '@grafana/ui';
import { PANEL_EDITOR_UI_STATE_STORAGE_KEY } from './state/reducers';
import { useLocalStorage } from 'react-use';
interface Props {
export interface OptionsGroupProps {
id: string;
title?: React.ReactNode;
renderTitle?: (isExpanded: boolean) => React.ReactNode;
defaultToClosed?: boolean;
className?: string;
nested?: boolean;
persistMe?: boolean;
onToggle?: (isExpanded: boolean) => void;
}
export const OptionsGroup: FC<Props> = ({
export const OptionsGroup: FC<OptionsGroupProps> = ({
id,
title,
children,
defaultToClosed,
renderTitle,
className,
nested = false,
persistMe = true,
onToggle,
}) => {
if (persistMe) {
return (
<CollapsibleSectionWithPersistence
id={id}
defaultToClosed={defaultToClosed}
className={className}
nested={nested}
renderTitle={renderTitle}
persistMe={persistMe}
title={title}
onToggle={onToggle}
>
{children}
</CollapsibleSectionWithPersistence>
);
}
return (
<CollapsibleSection
defaultToClosed={defaultToClosed}
className={className}
nested={nested}
renderTitle={renderTitle}
title={title}
onToggle={onToggle}
>
{children}
</CollapsibleSection>
);
};
const CollapsibleSectionWithPersistence: FC<OptionsGroupProps> = memo(props => {
const [value, setValue] = useLocalStorage(getOptionGroupStorageKey(props.id), {
defaultToClosed: props.defaultToClosed,
});
const onToggle = useCallback(
(isExpanded: boolean) => {
setValue({ defaultToClosed: !isExpanded });
if (props.onToggle) {
props.onToggle(isExpanded);
}
},
[setValue, props.onToggle]
);
return <CollapsibleSection {...props} defaultToClosed={value.defaultToClosed} onToggle={onToggle} />;
});
const CollapsibleSection: FC<Omit<OptionsGroupProps, 'id' | 'persistMe'>> = ({
title,
children,
defaultToClosed,
......@@ -106,3 +169,5 @@ const getStyles = stylesFactory((theme: GrafanaTheme, isExpanded: boolean, isNes
),
};
});
const getOptionGroupStorageKey = (id: string): string => `${PANEL_EDITOR_UI_STATE_STORAGE_KEY}.optionGroup[${id}]`;
......@@ -121,7 +121,7 @@ export const OverrideEditor: React.FC<OverrideEditorProps> = ({
};
return (
<OptionsGroup renderTitle={renderOverrideTitle}>
<OptionsGroup renderTitle={renderOverrideTitle} id={name} key={name}>
<Field label={matcherLabel} description={matcherUi.description}>
<matcherUi.component
matcher={matcherUi.matcher}
......
import React, { useMemo } from 'react';
import { PanelOptionsEditorItem, PanelPlugin } from '@grafana/data';
import { set as lodashSet, get as lodashGet } from 'lodash';
import { Label, Field } from '@grafana/ui';
import { get as lodashGet, set as lodashSet } from 'lodash';
import { Field, Label } from '@grafana/ui';
import groupBy from 'lodash/groupBy';
import { OptionsGroup } from './OptionsGroup';
......@@ -50,7 +50,7 @@ export const PanelOptionsEditor: React.FC<PanelOptionsEditorProps<any>> = ({ plu
.filter(e => e !== null);
return optionsToShow.length > 0 ? (
<OptionsGroup title={c} defaultToClosed key={`${c}/${i}`}>
<OptionsGroup title={c} defaultToClosed id={`${c}/${i}`} key={`${c}/${i}`}>
<div>{optionsToShow}</div>
</OptionsGroup>
) : null;
......
......@@ -2,12 +2,12 @@ import React, { FC, useMemo, useRef } from 'react';
import { DashboardModel, PanelModel } from '../../state';
import { FieldConfigSource, PanelData, PanelPlugin, SelectableValue } from '@grafana/data';
import { Counter, DataLinksInlineEditor, Field, Input, RadioButtonGroup, Select, Switch, TextArea } from '@grafana/ui';
import { OptionsGroup } from './OptionsGroup';
import { getPanelLinksVariableSuggestions } from '../../../panel/panellinks/link_srv';
import { getVariables } from '../../../variables/state/selectors';
import { PanelOptionsEditor } from './PanelOptionsEditor';
import { AngularPanelOptions } from './AngularPanelOptions';
import { VisualizationTab } from './VisualizationTab';
import { OptionsGroup } from './OptionsGroup';
interface Props {
panel: PanelModel;
......@@ -48,7 +48,7 @@ export const PanelOptionsTab: FC<Props> = ({
};
// Fist common panel settings Title, description
elements.push(
<OptionsGroup title="Panel settings" key="Panel settings">
<OptionsGroup title="Panel settings" id="Panel settings" key="Panel settings">
<Field label="Panel title">
<Input defaultValue={panel.title} onBlur={e => onPanelConfigChange('title', e.currentTarget.value)} />
</Field>
......@@ -65,7 +65,7 @@ export const PanelOptionsTab: FC<Props> = ({
);
elements.push(
<OptionsGroup title="Panel type" key="Panel type" defaultToClosed onToggle={focusVisPickerInput}>
<OptionsGroup title="Panel type" id="Panel type" key="Panel type" defaultToClosed onToggle={focusVisPickerInput}>
<VisualizationTab panel={panel} ref={visTabInputRef} />
</OptionsGroup>
);
......@@ -73,7 +73,7 @@ export const PanelOptionsTab: FC<Props> = ({
// Old legacy react editor
if (plugin.editor && panel && !plugin.optionEditors) {
elements.push(
<OptionsGroup title="Display" key="legacy react editor">
<OptionsGroup title="Display" id="legacy react editor" key="legacy react editor">
<plugin.editor
data={data}
options={panel.getOptions()}
......@@ -107,8 +107,9 @@ export const PanelOptionsTab: FC<Props> = ({
renderTitle={isExpanded => (
<>Panel links {!isExpanded && panelLinksCount > 0 && <Counter value={panelLinksCount} />}</>
)}
id="panel links"
key="panel links"
defaultToClosed={true}
defaultToClosed
>
<DataLinksInlineEditor
links={panel.links}
......@@ -120,7 +121,7 @@ export const PanelOptionsTab: FC<Props> = ({
);
elements.push(
<OptionsGroup title="Panel repeats" key="panel repeats" defaultToClosed={true}>
<OptionsGroup title="Panel repeats" id="panel repeats" key="panel repeats" defaultToClosed>
<Field
label="Repeat by variable"
description="Repeat this panel for each value in the selected variable.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment