mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Refactor types for dynamic dashboards (#100064)
This commit is contained in:
parent
bea62aa615
commit
f51571db5d
@ -3435,10 +3435,6 @@ exports[`better eslint`] = {
|
|||||||
"public/app/features/dashboard-scene/scene/UnlinkModal.tsx:5381": [
|
"public/app/features/dashboard-scene/scene/UnlinkModal.tsx:5381": [
|
||||||
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
|
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard-scene/scene/types.ts:5381": [
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
|
||||||
],
|
|
||||||
"public/app/features/dashboard-scene/serialization/angularMigration.test.ts:5381": [
|
"public/app/features/dashboard-scene/serialization/angularMigration.test.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||||
],
|
],
|
||||||
|
@ -176,7 +176,7 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla
|
|||||||
|
|
||||||
{openOverlay && (
|
{openOverlay && (
|
||||||
<Resizable className={cx(styles.fixed, styles.container)} defaultSize={{ height: '100%', width: '20vw' }}>
|
<Resizable className={cx(styles.fixed, styles.container)} defaultSize={{ height: '100%', width: '20vw' }}>
|
||||||
<ElementEditPane element={editableElement} key={editableElement.getTypeName()} />
|
<ElementEditPane element={editableElement} key={editableElement.typeName} />
|
||||||
</Resizable>
|
</Resizable>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -185,7 +185,7 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper} ref={paneRef}>
|
<div className={styles.wrapper} ref={paneRef}>
|
||||||
<ElementEditPane element={editableElement} key={editableElement.getTypeName()} />
|
<ElementEditPane element={editableElement} key={editableElement.typeName} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,11 @@ import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/Pan
|
|||||||
|
|
||||||
import { DashboardScene } from '../scene/DashboardScene';
|
import { DashboardScene } from '../scene/DashboardScene';
|
||||||
import { useLayoutCategory } from '../scene/layouts-shared/DashboardLayoutSelector';
|
import { useLayoutCategory } from '../scene/layouts-shared/DashboardLayoutSelector';
|
||||||
import { EditableDashboardElement } from '../scene/types';
|
import { EditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
||||||
|
|
||||||
export class DashboardEditableElement implements EditableDashboardElement {
|
export class DashboardEditableElement implements EditableDashboardElement {
|
||||||
public isEditableDashboardElement: true = true;
|
public readonly isEditableDashboardElement = true;
|
||||||
|
public readonly typeName = 'Dashboard';
|
||||||
|
|
||||||
public constructor(private dashboard: DashboardScene) {}
|
public constructor(private dashboard: DashboardScene) {}
|
||||||
|
|
||||||
@ -47,10 +48,6 @@ export class DashboardEditableElement implements EditableDashboardElement {
|
|||||||
|
|
||||||
return [dashboardOptions, layoutCategory];
|
return [dashboardOptions, layoutCategory];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTypeName(): string {
|
|
||||||
return 'Dashboard';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DashboardTitleInput({ dashboard }: { dashboard: DashboardScene }) {
|
export function DashboardTitleInput({ dashboard }: { dashboard: DashboardScene }) {
|
||||||
|
@ -4,7 +4,8 @@ import { GrafanaTheme2 } from '@grafana/data';
|
|||||||
import { Stack, useStyles2 } from '@grafana/ui';
|
import { Stack, useStyles2 } from '@grafana/ui';
|
||||||
import { OptionsPaneCategory } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategory';
|
import { OptionsPaneCategory } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategory';
|
||||||
|
|
||||||
import { EditableDashboardElement, MultiSelectedEditableDashboardElement } from '../scene/types';
|
import { EditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
||||||
|
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
element: EditableDashboardElement | MultiSelectedEditableDashboardElement;
|
element: EditableDashboardElement | MultiSelectedEditableDashboardElement;
|
||||||
@ -19,7 +20,7 @@ export function ElementEditPane({ element }: Props) {
|
|||||||
{element.renderActions && (
|
{element.renderActions && (
|
||||||
<OptionsPaneCategory
|
<OptionsPaneCategory
|
||||||
id="selected-item"
|
id="selected-item"
|
||||||
title={element.getTypeName()}
|
title={element.typeName}
|
||||||
isOpenDefault={true}
|
isOpenDefault={true}
|
||||||
className={styles.noBorderTop}
|
className={styles.noBorderTop}
|
||||||
>
|
>
|
||||||
|
@ -2,12 +2,9 @@ import { SceneObject, SceneObjectRef, VizPanel } from '@grafana/scenes';
|
|||||||
import { ElementSelectionContextItem } from '@grafana/ui';
|
import { ElementSelectionContextItem } from '@grafana/ui';
|
||||||
|
|
||||||
import { DashboardScene } from '../scene/DashboardScene';
|
import { DashboardScene } from '../scene/DashboardScene';
|
||||||
import {
|
import { isBulkActionElement } from '../scene/types/BulkActionElement';
|
||||||
EditableDashboardElement,
|
import { EditableDashboardElement, isEditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
||||||
isBulkActionElement,
|
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
||||||
isEditableDashboardElement,
|
|
||||||
MultiSelectedEditableDashboardElement,
|
|
||||||
} from '../scene/types';
|
|
||||||
|
|
||||||
import { DashboardEditableElement } from './DashboardEditableElement';
|
import { DashboardEditableElement } from './DashboardEditableElement';
|
||||||
import { MultiSelectedObjectsEditableElement } from './MultiSelectedObjectsEditableElement';
|
import { MultiSelectedObjectsEditableElement } from './MultiSelectedObjectsEditableElement';
|
||||||
|
@ -3,10 +3,13 @@ import { ReactNode } from 'react';
|
|||||||
import { Stack, Text, Button } from '@grafana/ui';
|
import { Stack, Text, Button } from '@grafana/ui';
|
||||||
import { Trans } from 'app/core/internationalization';
|
import { Trans } from 'app/core/internationalization';
|
||||||
|
|
||||||
import { BulkActionElement, MultiSelectedEditableDashboardElement } from '../scene/types';
|
import { BulkActionElement } from '../scene/types/BulkActionElement';
|
||||||
|
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
||||||
|
|
||||||
export class MultiSelectedObjectsEditableElement implements MultiSelectedEditableDashboardElement {
|
export class MultiSelectedObjectsEditableElement implements MultiSelectedEditableDashboardElement {
|
||||||
public isMultiSelectedEditableDashboardElement: true = true;
|
public readonly isMultiSelectedEditableDashboardElement = true;
|
||||||
|
public readonly typeName = 'Objects';
|
||||||
|
|
||||||
private items?: BulkActionElement[];
|
private items?: BulkActionElement[];
|
||||||
|
|
||||||
constructor(items: BulkActionElement[]) {
|
constructor(items: BulkActionElement[]) {
|
||||||
@ -19,10 +22,6 @@ export class MultiSelectedObjectsEditableElement implements MultiSelectedEditabl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public getTypeName(): string {
|
|
||||||
return 'Objects';
|
|
||||||
}
|
|
||||||
|
|
||||||
renderActions(): ReactNode {
|
renderActions(): ReactNode {
|
||||||
return (
|
return (
|
||||||
<Stack direction="column">
|
<Stack direction="column">
|
||||||
|
@ -5,11 +5,12 @@ import { Button, Stack, Text } from '@grafana/ui';
|
|||||||
import { Trans } from 'app/core/internationalization';
|
import { Trans } from 'app/core/internationalization';
|
||||||
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
|
|
||||||
import { MultiSelectedEditableDashboardElement } from '../scene/types';
|
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
||||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||||
|
|
||||||
export class MultiSelectedVizPanelsEditableElement implements MultiSelectedEditableDashboardElement {
|
export class MultiSelectedVizPanelsEditableElement implements MultiSelectedEditableDashboardElement {
|
||||||
public isMultiSelectedEditableDashboardElement: true = true;
|
public readonly isMultiSelectedEditableDashboardElement = true;
|
||||||
|
public readonly typeName = 'Panels';
|
||||||
|
|
||||||
private items?: VizPanel[];
|
private items?: VizPanel[];
|
||||||
|
|
||||||
@ -34,10 +35,6 @@ export class MultiSelectedVizPanelsEditableElement implements MultiSelectedEdita
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public getTypeName(): string {
|
|
||||||
return 'Panels';
|
|
||||||
}
|
|
||||||
|
|
||||||
renderActions(): ReactNode {
|
renderActions(): ReactNode {
|
||||||
return (
|
return (
|
||||||
<Stack direction="column">
|
<Stack direction="column">
|
||||||
|
@ -12,11 +12,14 @@ import {
|
|||||||
PanelDescriptionTextArea,
|
PanelDescriptionTextArea,
|
||||||
PanelFrameTitleInput,
|
PanelFrameTitleInput,
|
||||||
} from '../panel-edit/getPanelFrameOptions';
|
} from '../panel-edit/getPanelFrameOptions';
|
||||||
import { BulkActionElement, EditableDashboardElement, isDashboardLayoutItem } from '../scene/types';
|
import { BulkActionElement } from '../scene/types/BulkActionElement';
|
||||||
|
import { isDashboardLayoutItem } from '../scene/types/DashboardLayoutItem';
|
||||||
|
import { EditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
||||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||||
|
|
||||||
export class VizPanelEditableElement implements EditableDashboardElement, BulkActionElement {
|
export class VizPanelEditableElement implements EditableDashboardElement, BulkActionElement {
|
||||||
public isEditableDashboardElement: true = true;
|
public readonly isEditableDashboardElement = true;
|
||||||
|
public readonly typeName = 'Panel';
|
||||||
|
|
||||||
public constructor(private panel: VizPanel) {}
|
public constructor(private panel: VizPanel) {}
|
||||||
|
|
||||||
@ -96,10 +99,6 @@ export class VizPanelEditableElement implements EditableDashboardElement, BulkAc
|
|||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTypeName(): string {
|
|
||||||
return 'Panel';
|
|
||||||
}
|
|
||||||
|
|
||||||
public onDelete = () => {
|
public onDelete = () => {
|
||||||
const layout = dashboardSceneGraph.getLayoutManagerFor(this.panel);
|
const layout = dashboardSceneGraph.getLayoutManagerFor(this.panel);
|
||||||
layout.removePanel(this.panel);
|
layout.removePanel(this.panel);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { EditableDashboardElement, MultiSelectedEditableDashboardElement } from '../scene/types';
|
import { EditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
||||||
|
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
||||||
|
|
||||||
import { ElementSelection } from './ElementSelection';
|
import { ElementSelection } from './ElementSelection';
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import { saveLibPanel } from 'app/features/library-panels/state/api';
|
|||||||
|
|
||||||
import { DashboardSceneChangeTracker } from '../saving/DashboardSceneChangeTracker';
|
import { DashboardSceneChangeTracker } from '../saving/DashboardSceneChangeTracker';
|
||||||
import { getPanelChanges } from '../saving/getDashboardChanges';
|
import { getPanelChanges } from '../saving/getDashboardChanges';
|
||||||
import { DashboardLayoutItem, isDashboardLayoutItem } from '../scene/types';
|
import { DashboardLayoutItem, isDashboardLayoutItem } from '../scene/types/DashboardLayoutItem';
|
||||||
import { vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
|
import { vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
|
||||||
import {
|
import {
|
||||||
activateSceneObjectAndParentTree,
|
activateSceneObjectAndParentTree,
|
||||||
|
@ -10,7 +10,7 @@ import { getPanelLinksVariableSuggestions } from 'app/features/panel/panellinks/
|
|||||||
|
|
||||||
import { VizPanelLinks } from '../scene/PanelLinks';
|
import { VizPanelLinks } from '../scene/PanelLinks';
|
||||||
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
||||||
import { isDashboardLayoutItem } from '../scene/types';
|
import { isDashboardLayoutItem } from '../scene/types/DashboardLayoutItem';
|
||||||
import { vizPanelToPanel, transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
|
import { vizPanelToPanel, transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
|
||||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||||
import { getDashboardSceneFor } from '../utils/utils';
|
import { getDashboardSceneFor } from '../utils/utils';
|
||||||
|
@ -71,7 +71,7 @@ import { isUsingAngularDatasourcePlugin, isUsingAngularPanelPlugin } from './ang
|
|||||||
import { setupKeyboardShortcuts } from './keyboardShortcuts';
|
import { setupKeyboardShortcuts } from './keyboardShortcuts';
|
||||||
import { DashboardGridItem } from './layout-default/DashboardGridItem';
|
import { DashboardGridItem } from './layout-default/DashboardGridItem';
|
||||||
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
||||||
import { DashboardLayoutManager } from './types';
|
import { DashboardLayoutManager } from './types/DashboardLayoutManager';
|
||||||
|
|
||||||
export const PERSISTED_PROPS = ['title', 'description', 'tags', 'editable', 'graphTooltip', 'links', 'meta', 'preload'];
|
export const PERSISTED_PROPS = ['title', 'description', 'tags', 'editable', 'graphTooltip', 'links', 'meta', 'preload'];
|
||||||
export const PANEL_SEARCH_VAR = 'systemPanelFilterVar';
|
export const PANEL_SEARCH_VAR = 'systemPanelFilterVar';
|
||||||
@ -258,7 +258,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
this.setState({ isEditing: true, showHiddenElements: true });
|
this.setState({ isEditing: true, showHiddenElements: true });
|
||||||
|
|
||||||
// Propagate change edit mode change to children
|
// Propagate change edit mode change to children
|
||||||
this.state.body.editModeChanged(true);
|
this.state.body.editModeChanged?.(true);
|
||||||
|
|
||||||
// Propagate edit mode to scopes
|
// Propagate edit mode to scopes
|
||||||
this._scopesFacade?.enterReadOnly();
|
this._scopesFacade?.enterReadOnly();
|
||||||
@ -349,7 +349,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable grid dragging
|
// Disable grid dragging
|
||||||
this.state.body.editModeChanged(false);
|
this.state.body.editModeChanged?.(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public canDiscard() {
|
public canDiscard() {
|
||||||
|
@ -8,7 +8,7 @@ import { getCloneKey } from '../utils/clone';
|
|||||||
import { DashboardScene } from './DashboardScene';
|
import { DashboardScene } from './DashboardScene';
|
||||||
import { DashboardGridItem } from './layout-default/DashboardGridItem';
|
import { DashboardGridItem } from './layout-default/DashboardGridItem';
|
||||||
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
||||||
import { DashboardRepeatsProcessedEvent } from './types';
|
import { DashboardRepeatsProcessedEvent } from './types/DashboardRepeatsProcessedEvent';
|
||||||
|
|
||||||
describe('DashboardSceneUrlSync', () => {
|
describe('DashboardSceneUrlSync', () => {
|
||||||
describe('Given a standard scene', () => {
|
describe('Given a standard scene', () => {
|
||||||
|
@ -19,7 +19,7 @@ import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
|||||||
import { LibraryPanelBehavior } from './LibraryPanelBehavior';
|
import { LibraryPanelBehavior } from './LibraryPanelBehavior';
|
||||||
import { ViewPanelScene } from './ViewPanelScene';
|
import { ViewPanelScene } from './ViewPanelScene';
|
||||||
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
||||||
import { DashboardRepeatsProcessedEvent } from './types';
|
import { DashboardRepeatsProcessedEvent } from './types/DashboardRepeatsProcessedEvent';
|
||||||
|
|
||||||
export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||||
private _eventSub?: Unsubscribable;
|
private _eventSub?: Unsubscribable;
|
||||||
|
@ -25,7 +25,8 @@ import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components
|
|||||||
|
|
||||||
import { getCloneKey } from '../../utils/clone';
|
import { getCloneKey } from '../../utils/clone';
|
||||||
import { getMultiVariableValues, getQueryRunnerFor } from '../../utils/utils';
|
import { getMultiVariableValues, getQueryRunnerFor } from '../../utils/utils';
|
||||||
import { DashboardLayoutItem, DashboardRepeatsProcessedEvent } from '../types';
|
import { DashboardLayoutItem } from '../types/DashboardLayoutItem';
|
||||||
|
import { DashboardRepeatsProcessedEvent } from '../types/DashboardRepeatsProcessedEvent';
|
||||||
|
|
||||||
import { getDashboardGridItemOptions } from './DashboardGridItemEditor';
|
import { getDashboardGridItemOptions } from './DashboardGridItemEditor';
|
||||||
|
|
||||||
@ -47,6 +48,8 @@ export class DashboardGridItem
|
|||||||
private _prevRepeatValues?: VariableValueSingle[];
|
private _prevRepeatValues?: VariableValueSingle[];
|
||||||
protected _variableDependency = new DashboardGridItemVariableDependencyHandler(this);
|
protected _variableDependency = new DashboardGridItemVariableDependencyHandler(this);
|
||||||
|
|
||||||
|
public readonly isDashboardLayoutItem = true;
|
||||||
|
|
||||||
public constructor(state: DashboardGridItemState) {
|
public constructor(state: DashboardGridItemState) {
|
||||||
super(state);
|
super(state);
|
||||||
|
|
||||||
@ -188,11 +191,6 @@ export class DashboardGridItem
|
|||||||
this.setState(stateUpdate);
|
this.setState(stateUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DashboardLayoutItem interface start
|
|
||||||
*/
|
|
||||||
public isDashboardLayoutItem: true = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns options for panel edit
|
* Returns options for panel edit
|
||||||
*/
|
*/
|
||||||
|
@ -26,19 +26,19 @@ describe('DefaultGridLayoutManager', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getNextPanelId', () => {
|
describe('getMaxPanelId', () => {
|
||||||
it('should get next panel id in a simple 3 panel layout', () => {
|
it('should get max panel id in a simple 3 panel layout', () => {
|
||||||
const { manager } = setup();
|
const { manager } = setup();
|
||||||
const id = manager.getNextPanelId();
|
const id = manager.getMaxPanelId();
|
||||||
|
|
||||||
expect(id).toBe(4);
|
expect(id).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 1 if no panels are found', () => {
|
it('should return 0 if no panels are found', () => {
|
||||||
const { manager } = setup({ gridItems: [] });
|
const { manager } = setup({ gridItems: [] });
|
||||||
const id = manager.getNextPanelId();
|
const id = manager.getMaxPanelId();
|
||||||
|
|
||||||
expect(id).toBe(1);
|
expect(id).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
getGridItemKeyForPanelId,
|
getGridItemKeyForPanelId,
|
||||||
getDashboardSceneFor,
|
getDashboardSceneFor,
|
||||||
} from '../../utils/utils';
|
} from '../../utils/utils';
|
||||||
import { DashboardLayoutManager, LayoutRegistryItem } from '../types';
|
import { DashboardLayoutManager } from '../types/DashboardLayoutManager';
|
||||||
|
|
||||||
import { DashboardGridItem } from './DashboardGridItem';
|
import { DashboardGridItem } from './DashboardGridItem';
|
||||||
import { RowRepeaterBehavior } from './RowRepeaterBehavior';
|
import { RowRepeaterBehavior } from './RowRepeaterBehavior';
|
||||||
@ -39,7 +39,16 @@ export class DefaultGridLayoutManager
|
|||||||
extends SceneObjectBase<DefaultGridLayoutManagerState>
|
extends SceneObjectBase<DefaultGridLayoutManagerState>
|
||||||
implements DashboardLayoutManager
|
implements DashboardLayoutManager
|
||||||
{
|
{
|
||||||
public isDashboardLayoutManager: true = true;
|
public readonly isDashboardLayoutManager = true;
|
||||||
|
|
||||||
|
public static readonly descriptor = {
|
||||||
|
name: 'Default grid',
|
||||||
|
description: 'The default grid layout',
|
||||||
|
id: 'default-grid',
|
||||||
|
createFromLayout: DefaultGridLayoutManager.createFromLayout,
|
||||||
|
};
|
||||||
|
|
||||||
|
public readonly descriptor = DefaultGridLayoutManager.descriptor;
|
||||||
|
|
||||||
public editModeChanged(isEditing: boolean): void {
|
public editModeChanged(isEditing: boolean): void {
|
||||||
const updateResizeAndDragging = () => {
|
const updateResizeAndDragging = () => {
|
||||||
@ -328,10 +337,6 @@ export class DefaultGridLayoutManager
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDescriptor(): LayoutRegistryItem {
|
|
||||||
return DefaultGridLayoutManager.getDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public cloneLayout(ancestorKey: string, isSource: boolean): DashboardLayoutManager {
|
public cloneLayout(ancestorKey: string, isSource: boolean): DashboardLayoutManager {
|
||||||
return this.clone({
|
return this.clone({
|
||||||
grid: this.state.grid.clone({
|
grid: this.state.grid.clone({
|
||||||
@ -402,15 +407,6 @@ export class DefaultGridLayoutManager
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDescriptor(): LayoutRegistryItem {
|
|
||||||
return {
|
|
||||||
name: 'Default grid',
|
|
||||||
description: 'The default grid layout',
|
|
||||||
id: 'default-grid',
|
|
||||||
createFromLayout: DefaultGridLayoutManager.createFromLayout,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle switching to the manual grid layout from other layouts
|
* Handle switching to the manual grid layout from other layouts
|
||||||
* @param currentLayout
|
* @param currentLayout
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
isClonedKey,
|
isClonedKey,
|
||||||
} from '../../utils/clone';
|
} from '../../utils/clone';
|
||||||
import { getMultiVariableValues } from '../../utils/utils';
|
import { getMultiVariableValues } from '../../utils/utils';
|
||||||
import { DashboardRepeatsProcessedEvent } from '../types';
|
import { DashboardRepeatsProcessedEvent } from '../types/DashboardRepeatsProcessedEvent';
|
||||||
|
|
||||||
import { DashboardGridItem } from './DashboardGridItem';
|
import { DashboardGridItem } from './DashboardGridItem';
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { Switch, useStyles2 } from '@grafana/ui';
|
|||||||
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
||||||
|
|
||||||
import { DashboardLayoutItem } from '../types';
|
import { DashboardLayoutItem } from '../types/DashboardLayoutItem';
|
||||||
|
|
||||||
export interface ResponsiveGridItemState extends SceneObjectState {
|
export interface ResponsiveGridItemState extends SceneObjectState {
|
||||||
body: VizPanel;
|
body: VizPanel;
|
||||||
@ -14,6 +14,8 @@ export interface ResponsiveGridItemState extends SceneObjectState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ResponsiveGridItem extends SceneObjectBase<ResponsiveGridItemState> implements DashboardLayoutItem {
|
export class ResponsiveGridItem extends SceneObjectBase<ResponsiveGridItemState> implements DashboardLayoutItem {
|
||||||
|
public readonly isDashboardLayoutItem = true;
|
||||||
|
|
||||||
public constructor(state: ResponsiveGridItemState) {
|
public constructor(state: ResponsiveGridItemState) {
|
||||||
super(state);
|
super(state);
|
||||||
this.addActivationHandler(() => this._activationHandler());
|
this.addActivationHandler(() => this._activationHandler());
|
||||||
@ -29,11 +31,6 @@ export class ResponsiveGridItem extends SceneObjectBase<ResponsiveGridItemState>
|
|||||||
this.setState({ hideWhenNoData: !this.state.hideWhenNoData });
|
this.setState({ hideWhenNoData: !this.state.hideWhenNoData });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DashboardLayoutElement interface
|
|
||||||
*/
|
|
||||||
public isDashboardLayoutItem: true = true;
|
|
||||||
|
|
||||||
public getOptions?(): OptionsPaneCategoryDescriptor {
|
public getOptions?(): OptionsPaneCategoryDescriptor {
|
||||||
const model = this;
|
const model = this;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/Pan
|
|||||||
|
|
||||||
import { getDashboardSceneFor, getPanelIdForVizPanel, getVizPanelKeyForPanelId } from '../../utils/utils';
|
import { getDashboardSceneFor, getPanelIdForVizPanel, getVizPanelKeyForPanelId } from '../../utils/utils';
|
||||||
import { RowsLayoutManager } from '../layout-rows/RowsLayoutManager';
|
import { RowsLayoutManager } from '../layout-rows/RowsLayoutManager';
|
||||||
import { DashboardLayoutManager, LayoutRegistryItem } from '../types';
|
import { DashboardLayoutManager } from '../types/DashboardLayoutManager';
|
||||||
|
|
||||||
import { ResponsiveGridItem } from './ResponsiveGridItem';
|
import { ResponsiveGridItem } from './ResponsiveGridItem';
|
||||||
|
|
||||||
@ -17,7 +17,16 @@ export class ResponsiveGridLayoutManager
|
|||||||
extends SceneObjectBase<ResponsiveGridLayoutManagerState>
|
extends SceneObjectBase<ResponsiveGridLayoutManagerState>
|
||||||
implements DashboardLayoutManager
|
implements DashboardLayoutManager
|
||||||
{
|
{
|
||||||
public isDashboardLayoutManager: true = true;
|
public readonly isDashboardLayoutManager = true;
|
||||||
|
|
||||||
|
public static readonly descriptor = {
|
||||||
|
name: 'Responsive grid',
|
||||||
|
description: 'CSS layout that adjusts to the available space',
|
||||||
|
id: 'responsive-grid',
|
||||||
|
createFromLayout: ResponsiveGridLayoutManager.createFromLayout,
|
||||||
|
};
|
||||||
|
|
||||||
|
public readonly descriptor = ResponsiveGridLayoutManager.descriptor;
|
||||||
|
|
||||||
public editModeChanged(isEditing: boolean): void {}
|
public editModeChanged(isEditing: boolean): void {}
|
||||||
|
|
||||||
@ -83,19 +92,6 @@ export class ResponsiveGridLayoutManager
|
|||||||
return getOptions(this);
|
return getOptions(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDescriptor(): LayoutRegistryItem {
|
|
||||||
return ResponsiveGridLayoutManager.getDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getDescriptor(): LayoutRegistryItem {
|
|
||||||
return {
|
|
||||||
name: 'Responsive grid',
|
|
||||||
description: 'CSS layout that adjusts to the available space',
|
|
||||||
id: 'responsive-grid',
|
|
||||||
createFromLayout: ResponsiveGridLayoutManager.createFromLayout,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static createEmpty() {
|
public static createEmpty() {
|
||||||
return new ResponsiveGridLayoutManager({
|
return new ResponsiveGridLayoutManager({
|
||||||
layout: new SceneCSSGridLayout({
|
layout: new SceneCSSGridLayout({
|
||||||
@ -123,10 +119,6 @@ export class ResponsiveGridLayoutManager
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toSaveModel?() {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
activateRepeaters?(): void {
|
activateRepeaters?(): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,13 @@ import { t, Trans } from 'app/core/internationalization';
|
|||||||
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
||||||
|
|
||||||
import { MultiSelectedEditableDashboardElement } from '../types';
|
import { MultiSelectedEditableDashboardElement } from '../types/MultiSelectedEditableDashboardElement';
|
||||||
|
|
||||||
import { RowItem } from './RowItem';
|
import { RowItem } from './RowItem';
|
||||||
|
|
||||||
export class MultiSelectedRowItemsElement implements MultiSelectedEditableDashboardElement {
|
export class MultiSelectedRowItemsElement implements MultiSelectedEditableDashboardElement {
|
||||||
public isMultiSelectedEditableDashboardElement: true = true;
|
public readonly isMultiSelectedEditableDashboardElement = true;
|
||||||
|
public readonly typeName = 'Rows';
|
||||||
|
|
||||||
private items?: RowItem[];
|
private items?: RowItem[];
|
||||||
|
|
||||||
@ -44,10 +45,6 @@ export class MultiSelectedRowItemsElement implements MultiSelectedEditableDashbo
|
|||||||
return [rowOptions];
|
return [rowOptions];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTypeName(): string {
|
|
||||||
return 'Rows';
|
|
||||||
}
|
|
||||||
|
|
||||||
public onDelete = () => {
|
public onDelete = () => {
|
||||||
for (const item of this.items || []) {
|
for (const item of this.items || []) {
|
||||||
item.onDelete();
|
item.onDelete();
|
||||||
|
@ -33,7 +33,10 @@ import { isClonedKey } from '../../utils/clone';
|
|||||||
import { getDashboardSceneFor, getDefaultVizPanel, getQueryRunnerFor } from '../../utils/utils';
|
import { getDashboardSceneFor, getDefaultVizPanel, getQueryRunnerFor } from '../../utils/utils';
|
||||||
import { DashboardScene } from '../DashboardScene';
|
import { DashboardScene } from '../DashboardScene';
|
||||||
import { useLayoutCategory } from '../layouts-shared/DashboardLayoutSelector';
|
import { useLayoutCategory } from '../layouts-shared/DashboardLayoutSelector';
|
||||||
import { BulkActionElement, DashboardLayoutManager, EditableDashboardElement, LayoutParent } from '../types';
|
import { BulkActionElement } from '../types/BulkActionElement';
|
||||||
|
import { DashboardLayoutManager } from '../types/DashboardLayoutManager';
|
||||||
|
import { EditableDashboardElement } from '../types/EditableDashboardElement';
|
||||||
|
import { LayoutParent } from '../types/LayoutParent';
|
||||||
|
|
||||||
import { MultiSelectedRowItemsElement } from './MultiSelectedRowItemsElement';
|
import { MultiSelectedRowItemsElement } from './MultiSelectedRowItemsElement';
|
||||||
import { RowItemRepeaterBehavior } from './RowItemRepeaterBehavior';
|
import { RowItemRepeaterBehavior } from './RowItemRepeaterBehavior';
|
||||||
@ -55,7 +58,8 @@ export class RowItem
|
|||||||
statePaths: ['title'],
|
statePaths: ['title'],
|
||||||
});
|
});
|
||||||
|
|
||||||
public isEditableDashboardElement: true = true;
|
public readonly isEditableDashboardElement = true;
|
||||||
|
public readonly typeName = 'Row';
|
||||||
|
|
||||||
public useEditPaneOptions(): OptionsPaneCategoryDescriptor[] {
|
public useEditPaneOptions(): OptionsPaneCategoryDescriptor[] {
|
||||||
const row = this;
|
const row = this;
|
||||||
@ -107,10 +111,6 @@ export class RowItem
|
|||||||
return [rowOptions, rowRepeatOptions, layoutOptions];
|
return [rowOptions, rowRepeatOptions, layoutOptions];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTypeName(): string {
|
|
||||||
return 'Row';
|
|
||||||
}
|
|
||||||
|
|
||||||
public createMultiSelectedElement(items: SceneObject[]) {
|
public createMultiSelectedElement(items: SceneObject[]) {
|
||||||
return new MultiSelectedRowItemsElement(items);
|
return new MultiSelectedRowItemsElement(items);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
|
|
||||||
import { isClonedKeyOf, getCloneKey } from '../../utils/clone';
|
import { isClonedKeyOf, getCloneKey } from '../../utils/clone';
|
||||||
import { getMultiVariableValues } from '../../utils/utils';
|
import { getMultiVariableValues } from '../../utils/utils';
|
||||||
import { DashboardRepeatsProcessedEvent } from '../types';
|
import { DashboardRepeatsProcessedEvent } from '../types/DashboardRepeatsProcessedEvent';
|
||||||
|
|
||||||
import { RowItem } from './RowItem';
|
import { RowItem } from './RowItem';
|
||||||
import { RowsLayoutManager } from './RowsLayoutManager';
|
import { RowsLayoutManager } from './RowsLayoutManager';
|
||||||
|
@ -18,7 +18,7 @@ import { DashboardGridItem } from '../layout-default/DashboardGridItem';
|
|||||||
import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager';
|
||||||
import { RowRepeaterBehavior } from '../layout-default/RowRepeaterBehavior';
|
import { RowRepeaterBehavior } from '../layout-default/RowRepeaterBehavior';
|
||||||
import { ResponsiveGridLayoutManager } from '../layout-responsive-grid/ResponsiveGridLayoutManager';
|
import { ResponsiveGridLayoutManager } from '../layout-responsive-grid/ResponsiveGridLayoutManager';
|
||||||
import { DashboardLayoutManager, LayoutRegistryItem } from '../types';
|
import { DashboardLayoutManager } from '../types/DashboardLayoutManager';
|
||||||
|
|
||||||
import { RowItem } from './RowItem';
|
import { RowItem } from './RowItem';
|
||||||
import { RowItemRepeaterBehavior } from './RowItemRepeaterBehavior';
|
import { RowItemRepeaterBehavior } from './RowItemRepeaterBehavior';
|
||||||
@ -28,7 +28,16 @@ interface RowsLayoutManagerState extends SceneObjectState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RowsLayoutManager extends SceneObjectBase<RowsLayoutManagerState> implements DashboardLayoutManager {
|
export class RowsLayoutManager extends SceneObjectBase<RowsLayoutManagerState> implements DashboardLayoutManager {
|
||||||
public isDashboardLayoutManager: true = true;
|
public readonly isDashboardLayoutManager = true;
|
||||||
|
|
||||||
|
public static readonly descriptor = {
|
||||||
|
name: 'Rows',
|
||||||
|
description: 'Rows layout',
|
||||||
|
id: 'rows-layout',
|
||||||
|
createFromLayout: RowsLayoutManager.createFromLayout,
|
||||||
|
};
|
||||||
|
|
||||||
|
public readonly descriptor = RowsLayoutManager.descriptor;
|
||||||
|
|
||||||
public editModeChanged(isEditing: boolean): void {}
|
public editModeChanged(isEditing: boolean): void {}
|
||||||
|
|
||||||
@ -113,23 +122,10 @@ export class RowsLayoutManager extends SceneObjectBase<RowsLayoutManagerState> i
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDescriptor(): LayoutRegistryItem {
|
|
||||||
return RowsLayoutManager.getDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSelectedObject() {
|
public getSelectedObject() {
|
||||||
return sceneGraph.getAncestor(this, DashboardScene).state.editPane.state.selection?.getFirstObject();
|
return sceneGraph.getAncestor(this, DashboardScene).state.editPane.state.selection?.getFirstObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDescriptor(): LayoutRegistryItem {
|
|
||||||
return {
|
|
||||||
name: 'Rows',
|
|
||||||
description: 'Rows layout',
|
|
||||||
id: 'rows-layout',
|
|
||||||
createFromLayout: RowsLayoutManager.createFromLayout,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static createEmpty() {
|
public static createEmpty() {
|
||||||
return new RowsLayoutManager({ rows: [] });
|
return new RowsLayoutManager({ rows: [] });
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import { Select } from '@grafana/ui';
|
|||||||
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
||||||
|
|
||||||
import { DashboardLayoutManager, isLayoutParent, LayoutRegistryItem } from '../types';
|
import { DashboardLayoutManager } from '../types/DashboardLayoutManager';
|
||||||
|
import { isLayoutParent } from '../types/LayoutParent';
|
||||||
|
import { LayoutRegistryItem } from '../types/LayoutRegistryItem';
|
||||||
|
|
||||||
import { layoutRegistry } from './layoutRegistry';
|
import { layoutRegistry } from './layoutRegistry';
|
||||||
import { findParentLayout } from './utils';
|
import { findParentLayout } from './utils';
|
||||||
@ -16,7 +18,7 @@ export interface Props {
|
|||||||
export function DashboardLayoutSelector({ layoutManager }: Props) {
|
export function DashboardLayoutSelector({ layoutManager }: Props) {
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
const parentLayout = findParentLayout(layoutManager);
|
const parentLayout = findParentLayout(layoutManager);
|
||||||
const parentLayoutId = parentLayout?.getDescriptor().id;
|
const parentLayoutId = parentLayout?.descriptor.id;
|
||||||
|
|
||||||
return layoutRegistry
|
return layoutRegistry
|
||||||
.list()
|
.list()
|
||||||
@ -27,7 +29,7 @@ export function DashboardLayoutSelector({ layoutManager }: Props) {
|
|||||||
}));
|
}));
|
||||||
}, [layoutManager]);
|
}, [layoutManager]);
|
||||||
|
|
||||||
const currentLayoutId = layoutManager.getDescriptor().id;
|
const currentLayoutId = layoutManager.descriptor.id;
|
||||||
const currentOption = options.find((option) => option.value.id === currentLayoutId);
|
const currentOption = options.find((option) => option.value.id === currentLayoutId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,12 +3,8 @@ import { Registry } from '@grafana/data';
|
|||||||
import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager';
|
||||||
import { ResponsiveGridLayoutManager } from '../layout-responsive-grid/ResponsiveGridLayoutManager';
|
import { ResponsiveGridLayoutManager } from '../layout-responsive-grid/ResponsiveGridLayoutManager';
|
||||||
import { RowsLayoutManager } from '../layout-rows/RowsLayoutManager';
|
import { RowsLayoutManager } from '../layout-rows/RowsLayoutManager';
|
||||||
import { LayoutRegistryItem } from '../types';
|
import { LayoutRegistryItem } from '../types/LayoutRegistryItem';
|
||||||
|
|
||||||
export const layoutRegistry: Registry<LayoutRegistryItem> = new Registry<LayoutRegistryItem>(() => {
|
export const layoutRegistry: Registry<LayoutRegistryItem> = new Registry<LayoutRegistryItem>(() => {
|
||||||
return [
|
return [DefaultGridLayoutManager.descriptor, ResponsiveGridLayoutManager.descriptor, RowsLayoutManager.descriptor];
|
||||||
DefaultGridLayoutManager.getDescriptor(),
|
|
||||||
ResponsiveGridLayoutManager.getDescriptor(),
|
|
||||||
RowsLayoutManager.getDescriptor(),
|
|
||||||
];
|
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { SceneObject } from '@grafana/scenes';
|
import { SceneObject } from '@grafana/scenes';
|
||||||
|
|
||||||
import { DashboardLayoutManager, isDashboardLayoutManager } from '../types';
|
import { DashboardLayoutManager, isDashboardLayoutManager } from '../types/DashboardLayoutManager';
|
||||||
|
|
||||||
export function findParentLayout(sceneObject: SceneObject): DashboardLayoutManager | null {
|
export function findParentLayout(sceneObject: SceneObject): DashboardLayoutManager | null {
|
||||||
let parent = sceneObject.parent;
|
let parent = sceneObject.parent;
|
||||||
|
@ -1,207 +0,0 @@
|
|||||||
import { BusEventWithPayload, RegistryItem } from '@grafana/data';
|
|
||||||
import { SceneObject, VizPanel } from '@grafana/scenes';
|
|
||||||
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
|
||||||
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A scene object that usually wraps an underlying layout
|
|
||||||
* Dealing with all the state management and editing of the layout
|
|
||||||
*/
|
|
||||||
export interface DashboardLayoutManager extends SceneObject {
|
|
||||||
/** Marks it as a DashboardLayoutManager */
|
|
||||||
isDashboardLayoutManager: true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the layout manager that the edit mode has changed
|
|
||||||
* @param isEditing
|
|
||||||
*/
|
|
||||||
editModeChanged(isEditing: boolean): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an element / panel
|
|
||||||
* @param element
|
|
||||||
*/
|
|
||||||
removePanel(panel: VizPanel): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a copy of an existing element and adds it to the layout
|
|
||||||
* @param element
|
|
||||||
*/
|
|
||||||
duplicatePanel(panel: VizPanel): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new panel to the layout
|
|
||||||
*/
|
|
||||||
addPanel(panel: VizPanel): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add row
|
|
||||||
*/
|
|
||||||
addNewRow(): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getVizPanels
|
|
||||||
*/
|
|
||||||
getVizPanels(): VizPanel[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn into a save model
|
|
||||||
* @param saveModel
|
|
||||||
*/
|
|
||||||
toSaveModel?(): any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For dynamic panels that need to be viewed in isolation (SoloRoute)
|
|
||||||
*/
|
|
||||||
activateRepeaters?(): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the layout descriptor (which has the name and id)
|
|
||||||
*/
|
|
||||||
getDescriptor(): LayoutRegistryItem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders options and layout actions
|
|
||||||
*/
|
|
||||||
getOptions?(): OptionsPaneItemDescriptor[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a clone of the layout manager given an ancestor key
|
|
||||||
* @param ancestorKey
|
|
||||||
* @param isSource
|
|
||||||
*/
|
|
||||||
cloneLayout?(ancestorKey: string, isSource: boolean): DashboardLayoutManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the highest panel id in the layout
|
|
||||||
*/
|
|
||||||
getMaxPanelId(): number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isDashboardLayoutManager(obj: SceneObject): obj is DashboardLayoutManager {
|
|
||||||
return 'isDashboardLayoutManager' in obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The layout descriptor used when selecting / switching layouts
|
|
||||||
*/
|
|
||||||
export interface LayoutRegistryItem extends RegistryItem {
|
|
||||||
/**
|
|
||||||
* When switching between layouts
|
|
||||||
* @param currentLayout
|
|
||||||
*/
|
|
||||||
createFromLayout(currentLayout: DashboardLayoutManager): DashboardLayoutManager;
|
|
||||||
/**
|
|
||||||
* Create from persisted state
|
|
||||||
* @param saveModel
|
|
||||||
*/
|
|
||||||
createFromSaveModel?(saveModel: any): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface is needed to support layouts existing on different levels of the scene (DashboardScene and inside the TabsLayoutManager)
|
|
||||||
*/
|
|
||||||
export interface LayoutParent extends SceneObject {
|
|
||||||
switchLayout(newLayout: DashboardLayoutManager): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isLayoutParent(obj: SceneObject): obj is LayoutParent {
|
|
||||||
return 'switchLayout' in obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction to handle editing of different layout elements (wrappers for VizPanels and other objects)
|
|
||||||
* Also useful to when rendering / viewing an element outside it's layout scope
|
|
||||||
*/
|
|
||||||
export interface DashboardLayoutItem extends SceneObject {
|
|
||||||
/**
|
|
||||||
* Marks this object as a layout item
|
|
||||||
*/
|
|
||||||
isDashboardLayoutItem: true;
|
|
||||||
/**
|
|
||||||
* Return layout item options (like repeat, repeat direction, etc for the default DashboardGridItem)
|
|
||||||
*/
|
|
||||||
getOptions?(): OptionsPaneCategoryDescriptor;
|
|
||||||
/**
|
|
||||||
* When going into panel edit
|
|
||||||
**/
|
|
||||||
editingStarted?(): void;
|
|
||||||
/**
|
|
||||||
* When coming out of panel edit
|
|
||||||
*/
|
|
||||||
editingCompleted?(withChanges: boolean): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isDashboardLayoutItem(obj: SceneObject): obj is DashboardLayoutItem {
|
|
||||||
return 'isDashboardLayoutItem' in obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DashboardRepeatsProcessedEventPayload {
|
|
||||||
source: SceneObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DashboardRepeatsProcessedEvent extends BusEventWithPayload<DashboardRepeatsProcessedEventPayload> {
|
|
||||||
public static type = 'dashboard-repeats-processed';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for elements that have options
|
|
||||||
*/
|
|
||||||
export interface EditableDashboardElement {
|
|
||||||
/**
|
|
||||||
* Marks this object as an element that can be selected and edited directly on the canvas
|
|
||||||
*/
|
|
||||||
isEditableDashboardElement: true;
|
|
||||||
/**
|
|
||||||
* Hook that returns edit pane options
|
|
||||||
*/
|
|
||||||
useEditPaneOptions(): OptionsPaneCategoryDescriptor[];
|
|
||||||
/**
|
|
||||||
* Get the type name of the element
|
|
||||||
*/
|
|
||||||
getTypeName(): string;
|
|
||||||
/**
|
|
||||||
* Panel Actions
|
|
||||||
**/
|
|
||||||
renderActions?(): React.ReactNode;
|
|
||||||
/**
|
|
||||||
* creates a new multi-selection element from a list of selected items
|
|
||||||
*/
|
|
||||||
createMultiSelectedElement?(items: SceneObject[]): MultiSelectedEditableDashboardElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isEditableDashboardElement(obj: object): obj is EditableDashboardElement {
|
|
||||||
return 'isEditableDashboardElement' in obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MultiSelectedEditableDashboardElement {
|
|
||||||
/**
|
|
||||||
* Marks this object as an element that can be selected and edited directly on the canvas
|
|
||||||
*/
|
|
||||||
isMultiSelectedEditableDashboardElement: true;
|
|
||||||
/**
|
|
||||||
* Get the type name of the element
|
|
||||||
*/
|
|
||||||
getTypeName(): string;
|
|
||||||
/**
|
|
||||||
* Hook that returns edit pane options
|
|
||||||
*/
|
|
||||||
useEditPaneOptions?(): OptionsPaneCategoryDescriptor[];
|
|
||||||
/**
|
|
||||||
* Panel Actions
|
|
||||||
**/
|
|
||||||
renderActions?(): React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isMultiSelectedEditableDashboardElement(obj: object): obj is MultiSelectedEditableDashboardElement {
|
|
||||||
return 'isMultiSelectedEditableDashboardElement' in obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BulkActionElement {
|
|
||||||
onDelete(): void;
|
|
||||||
onCopy?(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isBulkActionElement(obj: object): obj is BulkActionElement {
|
|
||||||
return 'onDelete' in obj;
|
|
||||||
}
|
|
@ -0,0 +1,8 @@
|
|||||||
|
export interface BulkActionElement {
|
||||||
|
onDelete(): void;
|
||||||
|
onCopy?(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBulkActionElement(obj: object): obj is BulkActionElement {
|
||||||
|
return 'onDelete' in obj;
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
import { SceneObject } from '@grafana/scenes';
|
||||||
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction to handle editing of different layout elements (wrappers for VizPanels and other objects)
|
||||||
|
* Also useful to when rendering / viewing an element outside it's layout scope
|
||||||
|
*/
|
||||||
|
export interface DashboardLayoutItem extends SceneObject {
|
||||||
|
/**
|
||||||
|
* Marks this object as a layout item
|
||||||
|
*/
|
||||||
|
isDashboardLayoutItem: true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return layout item options (like repeat, repeat direction, etc. for the default DashboardGridItem)
|
||||||
|
*/
|
||||||
|
getOptions?(): OptionsPaneCategoryDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When going into panel edit
|
||||||
|
**/
|
||||||
|
editingStarted?(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When coming out of panel edit
|
||||||
|
*/
|
||||||
|
editingCompleted?(withChanges: boolean): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDashboardLayoutItem(obj: SceneObject): obj is DashboardLayoutItem {
|
||||||
|
return 'isDashboardLayoutItem' in obj;
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
import { SceneObject, VizPanel } from '@grafana/scenes';
|
||||||
|
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
||||||
|
|
||||||
|
import { LayoutRegistryItem } from './LayoutRegistryItem';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scene object that usually wraps an underlying layout
|
||||||
|
* Dealing with all the state management and editing of the layout
|
||||||
|
*/
|
||||||
|
export interface DashboardLayoutManager<S = {}> extends SceneObject {
|
||||||
|
/** Marks it as a DashboardLayoutManager */
|
||||||
|
isDashboardLayoutManager: true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The layout descriptor (which has the name and id)
|
||||||
|
*/
|
||||||
|
descriptor: Readonly<LayoutRegistryItem>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new panel to the layout
|
||||||
|
*/
|
||||||
|
addPanel(panel: VizPanel): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an element / panel
|
||||||
|
* @param panel
|
||||||
|
*/
|
||||||
|
removePanel(panel: VizPanel): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of an existing element and adds it to the layout
|
||||||
|
* @param panel
|
||||||
|
*/
|
||||||
|
duplicatePanel(panel: VizPanel): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getVizPanels
|
||||||
|
*/
|
||||||
|
getVizPanels(): VizPanel[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the highest panel id in the layout
|
||||||
|
*/
|
||||||
|
getMaxPanelId(): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add row
|
||||||
|
*/
|
||||||
|
addNewRow(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the layout manager that the edit mode has changed
|
||||||
|
* @param isEditing
|
||||||
|
*/
|
||||||
|
editModeChanged?(isEditing: boolean): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn into a save model
|
||||||
|
*/
|
||||||
|
toSaveModel?(): S;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For dynamic panels that need to be viewed in isolation (SoloRoute)
|
||||||
|
*/
|
||||||
|
activateRepeaters?(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders options and layout actions
|
||||||
|
*/
|
||||||
|
getOptions?(): OptionsPaneItemDescriptor[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of the layout manager given an ancestor key
|
||||||
|
* @param ancestorKey
|
||||||
|
* @param isSource
|
||||||
|
*/
|
||||||
|
cloneLayout?(ancestorKey: string, isSource: boolean): DashboardLayoutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDashboardLayoutManager(obj: SceneObject): obj is DashboardLayoutManager {
|
||||||
|
return 'isDashboardLayoutManager' in obj;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { BusEventWithPayload } from '@grafana/data';
|
||||||
|
import { SceneObject } from '@grafana/scenes';
|
||||||
|
|
||||||
|
export interface DashboardRepeatsProcessedEventPayload {
|
||||||
|
source: SceneObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DashboardRepeatsProcessedEvent extends BusEventWithPayload<DashboardRepeatsProcessedEventPayload> {
|
||||||
|
public static type = 'dashboard-repeats-processed';
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { SceneObject } from '@grafana/scenes';
|
||||||
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
|
|
||||||
|
import { MultiSelectedEditableDashboardElement } from './MultiSelectedEditableDashboardElement';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for elements that have options
|
||||||
|
*/
|
||||||
|
export interface EditableDashboardElement {
|
||||||
|
/**
|
||||||
|
* Marks this object as an element that can be selected and edited directly on the canvas
|
||||||
|
*/
|
||||||
|
isEditableDashboardElement: true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type name of the element
|
||||||
|
*/
|
||||||
|
typeName: Readonly<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook that returns edit pane options
|
||||||
|
*/
|
||||||
|
useEditPaneOptions(): OptionsPaneCategoryDescriptor[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel Actions
|
||||||
|
**/
|
||||||
|
renderActions?(): ReactNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates a new multi-selection element from a list of selected items
|
||||||
|
*/
|
||||||
|
createMultiSelectedElement?(items: SceneObject[]): MultiSelectedEditableDashboardElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isEditableDashboardElement(obj: object): obj is EditableDashboardElement {
|
||||||
|
return 'isEditableDashboardElement' in obj;
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { SceneObject } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { DashboardLayoutManager } from './DashboardLayoutManager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is needed to support layouts existing on different levels of the scene (DashboardScene and inside the TabsLayoutManager)
|
||||||
|
*/
|
||||||
|
export interface LayoutParent extends SceneObject {
|
||||||
|
switchLayout(newLayout: DashboardLayoutManager): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isLayoutParent(obj: SceneObject): obj is LayoutParent {
|
||||||
|
return 'switchLayout' in obj;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import { RegistryItem } from '@grafana/data';
|
||||||
|
|
||||||
|
import { DashboardLayoutManager } from './DashboardLayoutManager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The layout descriptor used when selecting / switching layouts
|
||||||
|
*/
|
||||||
|
export interface LayoutRegistryItem<S = {}> extends RegistryItem {
|
||||||
|
/**
|
||||||
|
* When switching between layouts
|
||||||
|
* @param currentLayout
|
||||||
|
*/
|
||||||
|
createFromLayout(currentLayout: DashboardLayoutManager): DashboardLayoutManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create from persisted state
|
||||||
|
* @param saveModel
|
||||||
|
*/
|
||||||
|
createFromSaveModel?(saveModel: S): void;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
|
|
||||||
|
export interface MultiSelectedEditableDashboardElement {
|
||||||
|
/**
|
||||||
|
* Marks this object as an element that can be selected and edited directly on the canvas
|
||||||
|
*/
|
||||||
|
isMultiSelectedEditableDashboardElement: true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type name of the element
|
||||||
|
*/
|
||||||
|
typeName: Readonly<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook that returns edit pane options
|
||||||
|
*/
|
||||||
|
useEditPaneOptions?(): OptionsPaneCategoryDescriptor[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel Actions
|
||||||
|
**/
|
||||||
|
renderActions?(): ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isMultiSelectedEditableDashboardElement(obj: object): obj is MultiSelectedEditableDashboardElement {
|
||||||
|
return 'isMultiSelectedEditableDashboardElement' in obj;
|
||||||
|
}
|
@ -33,7 +33,7 @@ import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSou
|
|||||||
|
|
||||||
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
||||||
import { DefaultGridLayoutManager } from '../scene/layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from '../scene/layout-default/DefaultGridLayoutManager';
|
||||||
import { DashboardLayoutManager } from '../scene/types';
|
import { DashboardLayoutManager } from '../scene/types/DashboardLayoutManager';
|
||||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||||
import { getQueryRunnerFor } from '../utils/utils';
|
import { getQueryRunnerFor } from '../utils/utils';
|
||||||
import { validateVariable, validateVizPanel } from '../v2schema/test-helpers';
|
import { validateVariable, validateVizPanel } from '../v2schema/test-helpers';
|
||||||
|
@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
|
|||||||
import { VizPanel, UrlSyncManager } from '@grafana/scenes';
|
import { VizPanel, UrlSyncManager } from '@grafana/scenes';
|
||||||
|
|
||||||
import { DashboardScene } from '../scene/DashboardScene';
|
import { DashboardScene } from '../scene/DashboardScene';
|
||||||
import { DashboardRepeatsProcessedEvent } from '../scene/types';
|
import { DashboardRepeatsProcessedEvent } from '../scene/types/DashboardRepeatsProcessedEvent';
|
||||||
import { containsCloneKey } from '../utils/clone';
|
import { containsCloneKey } from '../utils/clone';
|
||||||
import { findVizPanelByKey } from '../utils/utils';
|
import { findVizPanelByKey } from '../utils/utils';
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import { LibraryPanelBehavior } from '../scene/LibraryPanelBehavior';
|
|||||||
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
|
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
|
||||||
import { panelMenuBehavior } from '../scene/PanelMenuBehavior';
|
import { panelMenuBehavior } from '../scene/PanelMenuBehavior';
|
||||||
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
|
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
|
||||||
import { DashboardLayoutManager, isDashboardLayoutManager } from '../scene/types';
|
import { DashboardLayoutManager, isDashboardLayoutManager } from '../scene/types/DashboardLayoutManager';
|
||||||
|
|
||||||
import { getLastKeyFromClone, getOriginalKey } from './clone';
|
import { getLastKeyFromClone, getOriginalKey } from './clone';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user