Scenes/PanelEdit: Fix some styles and flesh out the skeleton (#80366)

pull/80619/head
kay delaney 1 year ago committed by GitHub
parent 6796e66fb8
commit 5640f25213
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx
  2. 7
      public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx
  3. 1
      public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx
  4. 119
      public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx
  5. 61
      public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.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<PanelDataPaneState> {
function PanelDataPaneRendered({ model }: SceneComponentProps<PanelDataPane>) {
const { tab, tabs } = model.useState();
const styles = useStyles2(getStyles);
if (!tabs) {
return;
@ -155,7 +158,19 @@ function PanelDataPaneRendered({ model }: SceneComponentProps<PanelDataPane>) {
);
})}
</TabsBar>
<TabContent>{currentTab && <currentTab.Component model={currentTab} />}</TabContent>
<TabContent className={styles.tabContent}>{currentTab && <currentTab.Component model={currentTab} />}</TabContent>
</div>
);
}
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,
}),
};
}

@ -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%',
}),
}),
});

@ -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,

@ -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<PanelOptionsPaneState> {
static Component = ({ model }: SceneComponentProps<PanelOptionsPane>) => {
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 (
<div className={styles.box}>
<Field label="Title">
<Input value={title} onChange={(evt) => panel.setState({ title: evt.currentTarget.value })} />
</Field>
<div className={styles.wrapper}>
{!isVizPickerOpen && (
<VisualizationButton
pluginId={pluginId}
onClick={() => {
setVizPickerOpen(true);
}}
/>
)}
<div className={styles.box}>
{isVizPickerOpen && (
<PanelVizTypePicker panelManager={panelManager} onChange={() => setVizPickerOpen(false)} />
)}
{!isVizPickerOpen && (
<>
<FilterInput value={''} placeholder="Search options" onChange={() => {}} />
<RadioButtonGroup
options={[
{ label: 'All', value: 'All' },
{ label: 'Overrides', value: 'Overrides' },
]}
value={'All'}
fullWidth
></RadioButtonGroup>
{/* <OptionsPaneCategory id="test" title="Panel options">
Placeholder
</OptionsPaneCategory> */}
</>
)}
</div>
</div>
);
};
@ -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 (
<div className={styles.wrapper}>
<ButtonGroup>
<ToolbarButton
className={styles.vizButton}
tooltip="Click to change visualization"
imgSrc={pluginMeta.info.logos.small}
// isOpen={isVizPickerOpen}
onClick={onClick}
data-testid={selectors.components.PanelEditor.toggleVizPicker}
aria-label="Change Visualization"
variant="canvas"
fullWidth
>
{pluginMeta.name}
</ToolbarButton>
{/* <ToolbarButton
tooltip={isPanelOptionsVisible ? 'Close options pane' : 'Show options pane'}
icon={isPanelOptionsVisible ? 'angle-right' : 'angle-left'}
onClick={onToggleOptionsPane}
variant="canvas"
data-testid={selectors.components.PanelEditor.toggleVizOptions}
aria-label={isPanelOptionsVisible ? 'Close options pane' : 'Show options pane'}
/> */}
</ButtonGroup>
</div>
);
};
function getVizButtonStyles(theme: GrafanaTheme2) {
return {
wrapper: css({
display: 'flex',
flexDirection: 'column',
paddingRight: theme.spacing(2),
}),
vizButton: css({
textAlign: 'left',
}),
};
}

@ -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<PanelVizTypePickerState> {
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<PanelVizTypePicker>) => {
const { panelManager } = model;
const { panel } = panelManager.useState();
const styles = useStyles2(getStyles);
const [searchQuery, setSearchQuery] = useState('');
return (
<CustomScrollbar autoHeightMin="100%">
<div className={styles.wrapper}>
<FilterInput value={searchQuery} onChange={setSearchQuery} autoFocus={true} placeholder="Search for..." />
<VizTypePicker
pluginId={panel.state.pluginId}
searchQuery={searchQuery}
onChange={(options) => {
panelManager.changePluginType(options.pluginId);
}}
/>
</div>
return (
<div className={styles.wrapper}>
<FilterInput
className={styles.filter}
value={searchQuery}
onChange={setSearchQuery}
autoFocus={true}
placeholder="Search for..."
/>
<CustomScrollbar>
<VizTypePicker
pluginId={panel.state.pluginId}
searchQuery={searchQuery}
onChange={(options) => {
panelManager.changePluginType(options.pluginId);
onChange();
}}
/>
</CustomScrollbar>
);
};
</div>
);
}
const getStyles = (theme: GrafanaTheme2) => ({
wrapper: css({
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
height: '100%',
gap: theme.spacing(1),
}),
filter: css({
minHeight: theme.spacing(4),
}),
});

Loading…
Cancel
Save