import React, { CSSProperties, useCallback, useState } from 'react'; import Transition from 'react-transition-group/Transition'; import { FieldConfigSource, GrafanaTheme, PanelPlugin, SelectableValue } from '@grafana/data'; import { DashboardModel, PanelModel } from '../../state'; import { CustomScrollbar, Icon, Input, Select, stylesFactory, Tab, TabContent, TabsBar, useTheme } from '@grafana/ui'; import { DefaultFieldConfigEditor, OverrideFieldConfigEditor } from './FieldConfigEditor'; import { css } from 'emotion'; import { PanelOptionsTab } from './PanelOptionsTab'; import { DashNavButton } from 'app/features/dashboard/components/DashNav/DashNavButton'; import { usePanelLatestData } from './usePanelLatestData'; import { selectors } from '@grafana/e2e-selectors'; interface Props { plugin: PanelPlugin; panel: PanelModel; width: number; dashboard: DashboardModel; onClose: () => void; onFieldConfigsChange: (config: FieldConfigSource) => void; onPanelOptionsChanged: (options: any) => void; onPanelConfigChange: (configKey: string, value: any) => void; } export const OptionsPaneContent: React.FC = ({ plugin, panel, width, onFieldConfigsChange, onPanelOptionsChanged, onPanelConfigChange, onClose, dashboard, }: Props) => { const theme = useTheme(); const styles = getStyles(theme); const [activeTab, setActiveTab] = useState('options'); const [isSearching, setSearchMode] = useState(false); const { data, hasSeries } = usePanelLatestData(panel, { withTransforms: true, withFieldConfig: false }); const renderFieldOptions = useCallback( (plugin: PanelPlugin) => { const fieldConfig = panel.getFieldConfig(); if (!fieldConfig || !hasSeries) { return null; } return ( ); }, [data, plugin, panel, onFieldConfigsChange] ); const renderFieldOverrideOptions = useCallback( (plugin: PanelPlugin) => { const fieldConfig = panel.getFieldConfig(); if (!fieldConfig || !hasSeries) { return null; } return ( ); }, [data, plugin, panel, onFieldConfigsChange] ); // When the panel has no query only show the main tab const showMainTab = activeTab === 'options' || plugin.meta.skipDataQuery; return (
{plugin && (
{showMainTab ? ( ) : ( <> {activeTab === 'defaults' && renderFieldOptions(plugin)} {activeTab === 'overrides' && renderFieldOverrideOptions(plugin)} )}
)}
); }; export const TabsBarContent: React.FC<{ width: number; plugin: PanelPlugin; isSearching: boolean; activeTab: string; styles: OptionsPaneStyles; onClose: () => void; setSearchMode: (mode: boolean) => void; setActiveTab: (tab: string) => void; panel: PanelModel; }> = ({ width, plugin, 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', width: '50%', display: 'flex', }; const transitionStyles: { [str: string]: CSSProperties } = { entered: { width: '100%' }, }; return ( {state => { return (
} ref={elem => elem && elem.focus()} placeholder="Search all options" suffix={ setSearchMode(false)} className={styles.searchRemoveIcon} /> } />
); }}
); } // Show the appropriate tabs let tabs = tabSelections; let active = tabs.find(v => v.value === activeTab)!; // If no field configs hide Fields & Override tab if (plugin.fieldConfigRegistry.isEmpty()) { active = tabSelections[0]; tabs = [active]; } return ( <> {width < 352 ? (