diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx index 891ffe9e780..64d7f7f97e0 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx @@ -1,6 +1,8 @@ +import { css } from '@emotion/css'; import React from 'react'; import { Unsubscribable } from 'rxjs'; +import { GrafanaTheme2 } from '@grafana/data'; import { SceneComponentProps, SceneObjectBase, @@ -9,7 +11,7 @@ import { SceneObjectUrlValues, VizPanel, } from '@grafana/scenes'; -import { Tab, TabContent, TabsBar } from '@grafana/ui'; +import { Tab, TabContent, TabsBar, useStyles2 } from '@grafana/ui'; import { shouldShowAlertingTab } from 'app/features/dashboard/components/PanelEditor/state/selectors'; import { VizPanelManager } from '../VizPanelManager'; @@ -132,6 +134,7 @@ export class PanelDataPane extends SceneObjectBase { function PanelDataPaneRendered({ model }: SceneComponentProps) { const { tab, tabs } = model.useState(); + const styles = useStyles2(getStyles); if (!tabs) { return; @@ -155,7 +158,19 @@ function PanelDataPaneRendered({ model }: SceneComponentProps) { ); })} - {currentTab && } + {currentTab && } ); } + +function getStyles(theme: GrafanaTheme2) { + return { + tabContent: css({ + padding: theme.spacing(2), + border: `1px solid ${theme.colors.border.weak}`, + borderLeft: 'none', + borderBottom: 'none', + borderTopRightRadius: theme.shape.radius.default, + }), + }; +} diff --git a/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx b/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx index 1f16cbdf45e..61f4c955407 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx @@ -25,7 +25,6 @@ import { PanelDataPane } from './PanelDataPane/PanelDataPane'; import { PanelEditorRenderer } from './PanelEditorRenderer'; import { PanelEditorUrlSync } from './PanelEditorUrlSync'; import { PanelOptionsPane } from './PanelOptionsPane'; -import { PanelVizTypePicker } from './PanelVizTypePicker'; import { VizPanelManager } from './VizPanelManager'; export interface PanelEditorState extends SceneObjectState { @@ -153,9 +152,9 @@ export function buildPanelEditScene(dashboard: DashboardScene, panel: VizPanel): body: new PanelDataPane(vizPanelMgr), }), }), - secondary: new SceneFlexLayout({ - direction: 'column', - children: [new PanelOptionsPane(vizPanelMgr), new PanelVizTypePicker(vizPanelMgr)], + secondary: new SceneFlexItem({ + body: new PanelOptionsPane(vizPanelMgr), + width: '100%', }), }), }); diff --git a/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx b/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx index 109b3db72de..681930cd583 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx @@ -68,7 +68,6 @@ function getStyles(theme: GrafanaTheme2) { label: 'canvas-content', display: 'flex', flexDirection: 'column', - padding: theme.spacing(0, 2), flexBasis: '100%', flexGrow: 1, minHeight: 0, diff --git a/public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx b/public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx index e76751a1414..f0c6399545a 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx @@ -1,10 +1,13 @@ import { css } from '@emotion/css'; -import React from 'react'; +import React, { useMemo, useState } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; +import { selectors } from '@grafana/e2e-selectors'; import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; -import { Field, Input, useStyles2 } from '@grafana/ui'; +import { ButtonGroup, FilterInput, RadioButtonGroup, ToolbarButton, useStyles2 } from '@grafana/ui'; +import { getAllPanelPluginMeta } from 'app/features/panel/state/util'; +import { PanelVizTypePicker } from './PanelVizTypePicker'; import { VizPanelManager } from './VizPanelManager'; export interface PanelOptionsPaneState extends SceneObjectState {} @@ -21,14 +24,41 @@ export class PanelOptionsPane extends SceneObjectBase { static Component = ({ model }: SceneComponentProps) => { const { panelManager } = model; const { panel } = panelManager.state; - const { title } = panel.useState(); + const { pluginId } = panel.useState(); const styles = useStyles2(getStyles); + const [isVizPickerOpen, setVizPickerOpen] = useState(true); return ( -
- - panel.setState({ title: evt.currentTarget.value })} /> - +
+ {!isVizPickerOpen && ( + { + setVizPickerOpen(true); + }} + /> + )} +
+ {isVizPickerOpen && ( + setVizPickerOpen(false)} /> + )} + {!isVizPickerOpen && ( + <> + {}} /> + + {/* + Placeholder + */} + + )} +
); }; @@ -39,7 +69,80 @@ function getStyles(theme: GrafanaTheme2) { box: css({ display: 'flex', flexDirection: 'column', - padding: theme.spacing(2), + flexGrow: '1', + padding: theme.spacing(1), + background: theme.colors.background.primary, + border: `1px solid ${theme.colors.border.weak}`, + gap: theme.spacing(1), + }), + wrapper: css({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + flexGrow: '1', + }), + }; +} + +export const VisualizationButton = ({ pluginId, onClick }: { pluginId: string; onClick: () => void }) => { + // const dispatch = useDispatch(); + // const plugin = useSelector(getPanelPluginWithFallback(panel.type)); + // const isPanelOptionsVisible = useSelector((state) => state.panelEditor.ui.isPanelOptionsVisible); + // const isVizPickerOpen = useSelector((state) => state.panelEditor.isVizPickerOpen); + + // const onToggleOpen = () => { + // dispatch(toggleVizPicker(!isVizPickerOpen)); + // }; + + // const onToggleOptionsPane = () => { + // dispatch(updatePanelEditorUIState({ isPanelOptionsVisible: !isPanelOptionsVisible })); + // }; + + // if (!plugin) { + // return null; + // } + + const styles = useStyles2(getVizButtonStyles); + const pluginMeta = useMemo(() => getAllPanelPluginMeta().filter((p) => p.id === pluginId)[0], [pluginId]); + + return ( +
+ + + {pluginMeta.name} + + {/* */} + +
+ ); +}; + +function getVizButtonStyles(theme: GrafanaTheme2) { + return { + wrapper: css({ + display: 'flex', + flexDirection: 'column', + paddingRight: theme.spacing(2), + }), + vizButton: css({ + textAlign: 'left', }), }; } diff --git a/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx b/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx index 0899d3df1e2..9ae03114a1a 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import React, { useState } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; +import { SceneObjectState } from '@grafana/scenes'; import { CustomScrollbar, FilterInput, useStyles2 } from '@grafana/ui'; import { VizTypePicker } from 'app/features/panel/components/VizTypePicker/VizTypePicker'; @@ -10,38 +10,49 @@ import { VizPanelManager } from './VizPanelManager'; export interface PanelVizTypePickerState extends SceneObjectState {} -export class PanelVizTypePicker extends SceneObjectBase { - public constructor(public panelManager: VizPanelManager) { - super({}); - } +export function PanelVizTypePicker({ + panelManager, + onChange, +}: { + panelManager: VizPanelManager; + onChange: () => void; +}) { + const { panel } = panelManager.useState(); + const styles = useStyles2(getStyles); + const [searchQuery, setSearchQuery] = useState(''); - static Component = ({ model }: SceneComponentProps) => { - const { panelManager } = model; - const { panel } = panelManager.useState(); - const styles = useStyles2(getStyles); - const [searchQuery, setSearchQuery] = useState(''); - - return ( - -
- - { - panelManager.changePluginType(options.pluginId); - }} - /> -
+ return ( +
+ + + { + panelManager.changePluginType(options.pluginId); + onChange(); + }} + /> - ); - }; +
+ ); } const getStyles = (theme: GrafanaTheme2) => ({ wrapper: css({ display: 'flex', flexDirection: 'column', + flexGrow: 1, + height: '100%', gap: theme.spacing(1), }), + filter: css({ + minHeight: theme.spacing(4), + }), });