mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Scenes/PanelEdit: Fix some styles and flesh out the skeleton (#80366)
This commit is contained in:
parent
6796e66fb8
commit
5640f25213
@ -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…
Reference in New Issue
Block a user