mirror of https://github.com/grafana/grafana.git
161 lines
5.4 KiB
TypeScript
161 lines
5.4 KiB
TypeScript
import { css, cx } from '@emotion/css';
|
|
import { useMemo } from 'react';
|
|
|
|
import { GrafanaTheme2, textUtil } from '@grafana/data';
|
|
import { sceneGraph, VizPanel } from '@grafana/scenes';
|
|
import { useStyles2, Text, Icon, Stack, Tooltip } from '@grafana/ui';
|
|
import { t } from 'app/core/internationalization';
|
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
|
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
|
|
|
import {
|
|
PanelBackgroundSwitch,
|
|
PanelDescriptionTextArea,
|
|
PanelFrameTitleInput,
|
|
} from '../panel-edit/getPanelFrameOptions';
|
|
import { BulkActionElement } from '../scene/types/BulkActionElement';
|
|
import { isDashboardLayoutItem } from '../scene/types/DashboardLayoutItem';
|
|
import { EditableDashboardElement, EditableDashboardElementInfo } from '../scene/types/EditableDashboardElement';
|
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
|
import { getEditPanelUrl } from '../utils/urlBuilders';
|
|
import { getDashboardSceneFor, getPanelIdForVizPanel } from '../utils/utils';
|
|
|
|
import { MultiSelectedVizPanelsEditableElement } from './MultiSelectedVizPanelsEditableElement';
|
|
|
|
export class VizPanelEditableElement implements EditableDashboardElement, BulkActionElement {
|
|
public readonly isEditableDashboardElement = true;
|
|
public readonly typeName = 'Panel';
|
|
|
|
public constructor(public panel: VizPanel) {}
|
|
|
|
public getEditableElementInfo(): EditableDashboardElementInfo {
|
|
return {
|
|
typeName: t('dashboard.edit-pane.elements.panel', 'Panel'),
|
|
icon: 'chart-line',
|
|
instanceName: sceneGraph.interpolate(this.panel, this.panel.state.title, undefined, 'text'),
|
|
};
|
|
}
|
|
|
|
public useEditPaneOptions(): OptionsPaneCategoryDescriptor[] {
|
|
const panel = this.panel;
|
|
const layoutElement = panel.parent!;
|
|
|
|
const panelOptions = useMemo(() => {
|
|
return new OptionsPaneCategoryDescriptor({ title: '', id: 'panel-options' })
|
|
.addItem(
|
|
new OptionsPaneItemDescriptor({
|
|
title: '',
|
|
render: () => <OpenPanelEditViz panel={this.panel} />,
|
|
})
|
|
)
|
|
.addItem(
|
|
new OptionsPaneItemDescriptor({
|
|
title: t('dashboard.viz-panel.options.title-option', 'Title'),
|
|
value: panel.state.title,
|
|
popularRank: 1,
|
|
render: () => <PanelFrameTitleInput panel={panel} />,
|
|
})
|
|
)
|
|
.addItem(
|
|
new OptionsPaneItemDescriptor({
|
|
title: t('dashboard.viz-panel.options.description', 'Description'),
|
|
value: panel.state.description,
|
|
render: () => <PanelDescriptionTextArea panel={panel} />,
|
|
})
|
|
)
|
|
.addItem(
|
|
new OptionsPaneItemDescriptor({
|
|
title: t('dashboard.viz-panel.options.transparent-background', 'Transparent background'),
|
|
render: () => <PanelBackgroundSwitch panel={panel} />,
|
|
})
|
|
);
|
|
}, [panel]);
|
|
|
|
const layoutCategories = useMemo(
|
|
() => (isDashboardLayoutItem(layoutElement) && layoutElement.getOptions ? layoutElement.getOptions() : []),
|
|
[layoutElement]
|
|
);
|
|
|
|
return [panelOptions, ...layoutCategories];
|
|
}
|
|
|
|
public onDelete() {
|
|
const layout = dashboardSceneGraph.getLayoutManagerFor(this.panel);
|
|
layout.removePanel?.(this.panel);
|
|
}
|
|
|
|
public onDuplicate() {
|
|
const layout = dashboardSceneGraph.getLayoutManagerFor(this.panel);
|
|
layout.duplicatePanel?.(this.panel);
|
|
}
|
|
|
|
public onCopy() {
|
|
const dashboard = getDashboardSceneFor(this.panel);
|
|
dashboard.copyPanel(this.panel);
|
|
}
|
|
|
|
public createMultiSelectedElement(items: VizPanelEditableElement[]) {
|
|
return new MultiSelectedVizPanelsEditableElement(items);
|
|
}
|
|
}
|
|
|
|
type OpenPanelEditVizProps = {
|
|
panel: VizPanel;
|
|
};
|
|
|
|
const OpenPanelEditViz = ({ panel }: OpenPanelEditVizProps) => {
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const plugin = panel.getPlugin();
|
|
const imgSrc = plugin?.meta.info.logos.small;
|
|
|
|
return (
|
|
<Stack alignItems="center" width="100%">
|
|
{plugin ? (
|
|
<Tooltip content={t('dashboard.viz-panel.options.open-edit', 'Open panel editor')}>
|
|
<a
|
|
href={textUtil.sanitizeUrl(getEditPanelUrl(getPanelIdForVizPanel(panel)))}
|
|
className={cx(styles.pluginDescriptionWrapper)}
|
|
>
|
|
<img
|
|
className={styles.panelVizImg}
|
|
src={imgSrc}
|
|
alt={t('dashboard.viz-panel.options.plugin-type-image', 'Image of plugin type')}
|
|
/>
|
|
<Text truncate>{plugin.meta.name}</Text>
|
|
<Icon className={styles.panelVizIcon} name="sliders-v-alt" />
|
|
</a>
|
|
</Tooltip>
|
|
) : null}
|
|
</Stack>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
|
pluginDescriptionWrapper: css({
|
|
display: 'flex',
|
|
flexWrap: 'nowrap',
|
|
alignItems: 'center',
|
|
columnGap: theme.spacing(1),
|
|
rowGap: theme.spacing(0.5),
|
|
minHeight: theme.spacing(4),
|
|
backgroundColor: theme.colors.secondary.main,
|
|
border: `1px solid ${theme.colors.secondary.border}`,
|
|
borderRadius: theme.shape.radius.default,
|
|
paddingInline: theme.spacing(1),
|
|
paddingBlock: theme.spacing(0.5),
|
|
flexGrow: 1,
|
|
'&:hover': {
|
|
backgroundColor: theme.colors.secondary.shade,
|
|
},
|
|
}),
|
|
panelVizImg: css({
|
|
width: '16px',
|
|
height: '16px',
|
|
marginRight: theme.spacing(1),
|
|
}),
|
|
panelVizIcon: css({
|
|
marginLeft: 'auto',
|
|
}),
|
|
});
|