mirror of https://github.com/grafana/grafana
DashboardScene: Refactor body property to be layout manager interface (#93738)
* Began layout refactor * fixing tests * Progress * Progress * Progress * Progress * Progress * Progress * finally no errors * Remove unused interface * Remove unused interface * fixed tests * Update * Update * Fixes to keyboard shortcuts and solo route * fix lint issuespull/93911/head
parent
7e94d05d39
commit
1941ae21d7
@ -0,0 +1,281 @@ |
|||||||
|
import { SceneGridItemLike, SceneGridLayout, SceneGridRow, SceneQueryRunner, VizPanel } from '@grafana/scenes'; |
||||||
|
|
||||||
|
import { findVizPanelByKey } from '../../utils/utils'; |
||||||
|
import { DashboardGridItem } from '../DashboardGridItem'; |
||||||
|
|
||||||
|
import { DefaultGridLayoutManager } from './DefaultGridLayoutManager'; |
||||||
|
|
||||||
|
describe('DefaultGridLayoutManager', () => { |
||||||
|
describe('getVizPanels', () => { |
||||||
|
it('Should return all panels', () => { |
||||||
|
const { manager } = setup(); |
||||||
|
const vizPanels = manager.getVizPanels(); |
||||||
|
|
||||||
|
expect(vizPanels.length).toBe(4); |
||||||
|
expect(vizPanels[0].state.title).toBe('Panel A'); |
||||||
|
expect(vizPanels[1].state.title).toBe('Panel B'); |
||||||
|
expect(vizPanels[2].state.title).toBe('Panel C'); |
||||||
|
expect(vizPanels[3].state.title).toBe('Panel D'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should return an empty array when scene has no panels', () => { |
||||||
|
const { manager } = setup({ gridItems: [] }); |
||||||
|
const vizPanels = manager.getVizPanels(); |
||||||
|
expect(vizPanels.length).toBe(0); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('getNextPanelId', () => { |
||||||
|
it('should get next panel id in a simple 3 panel layout', () => { |
||||||
|
const { manager } = setup(); |
||||||
|
const id = manager.getNextPanelId(); |
||||||
|
|
||||||
|
expect(id).toBe(4); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should return 1 if no panels are found', () => { |
||||||
|
const { manager } = setup({ gridItems: [] }); |
||||||
|
const id = manager.getNextPanelId(); |
||||||
|
|
||||||
|
expect(id).toBe(1); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('addPanel', () => { |
||||||
|
it('Should add a new panel', () => { |
||||||
|
const { manager } = setup(); |
||||||
|
|
||||||
|
const vizPanel = new VizPanel({ |
||||||
|
title: 'Panel Title', |
||||||
|
key: 'panel-55', |
||||||
|
pluginId: 'timeseries', |
||||||
|
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }), |
||||||
|
}); |
||||||
|
|
||||||
|
manager.addPanel(vizPanel); |
||||||
|
|
||||||
|
const panel = findVizPanelByKey(manager, 'panel-55')!; |
||||||
|
const gridItem = panel.parent as DashboardGridItem; |
||||||
|
|
||||||
|
expect(panel).toBeDefined(); |
||||||
|
expect(gridItem.state.y).toBe(0); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('addNewRow', () => { |
||||||
|
it('Should create and add a new row to the dashboard', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const row = manager.addNewRow(); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(2); |
||||||
|
expect(row.state.key).toBe('panel-4'); |
||||||
|
expect(row.state.children[0].state.key).toBe('griditem-1'); |
||||||
|
expect(row.state.children[1].state.key).toBe('griditem-2'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should create a row and add all panels in the dashboard under it', () => { |
||||||
|
const { manager, grid } = setup({ |
||||||
|
gridItems: [ |
||||||
|
new DashboardGridItem({ |
||||||
|
key: 'griditem-1', |
||||||
|
x: 0, |
||||||
|
body: new VizPanel({ |
||||||
|
title: 'Panel A', |
||||||
|
key: 'panel-1', |
||||||
|
pluginId: 'table', |
||||||
|
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }), |
||||||
|
}), |
||||||
|
}), |
||||||
|
new DashboardGridItem({ |
||||||
|
key: 'griditem-2', |
||||||
|
body: new VizPanel({ |
||||||
|
title: 'Panel B', |
||||||
|
key: 'panel-2', |
||||||
|
pluginId: 'table', |
||||||
|
}), |
||||||
|
}), |
||||||
|
], |
||||||
|
}); |
||||||
|
|
||||||
|
const row = manager.addNewRow(); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(1); |
||||||
|
expect(row.state.children.length).toBe(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should create and add two new rows, but the second has no children', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const row1 = manager.addNewRow(); |
||||||
|
const row2 = manager.addNewRow(); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(3); |
||||||
|
expect(row1.state.children.length).toBe(2); |
||||||
|
expect(row2.state.children.length).toBe(0); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should create an empty row when nothing else in dashboard', () => { |
||||||
|
const { manager, grid } = setup({ gridItems: [] }); |
||||||
|
const row = manager.addNewRow(); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(1); |
||||||
|
expect(row.state.children.length).toBe(0); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('Remove row', () => { |
||||||
|
it('Should remove a row and move its children to the grid layout', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const row = grid.state.children[2] as SceneGridRow; |
||||||
|
|
||||||
|
manager.removeRow(row); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(4); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should remove a row and its children', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const row = grid.state.children[2] as SceneGridRow; |
||||||
|
|
||||||
|
manager.removeRow(row, true); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should remove an empty row from the layout', () => { |
||||||
|
const row = new SceneGridRow({ key: 'panel-1' }); |
||||||
|
const { manager, grid } = setup({ gridItems: [row] }); |
||||||
|
|
||||||
|
manager.removeRow(row); |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(0); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('removePanel', () => { |
||||||
|
it('Should remove grid item', () => { |
||||||
|
const { manager } = setup(); |
||||||
|
const panel = findVizPanelByKey(manager, 'panel-1')!; |
||||||
|
manager.removePanel(panel); |
||||||
|
|
||||||
|
expect(findVizPanelByKey(manager, 'panel-1')).toBeNull(); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should remove a grid item within a row', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const vizPanel = findVizPanelByKey(manager, 'panel-within-row1')!; |
||||||
|
|
||||||
|
manager.removePanel(vizPanel); |
||||||
|
|
||||||
|
const gridRow = grid.state.children[2] as SceneGridRow; |
||||||
|
expect(gridRow.state.children.length).toBe(1); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('duplicatePanel', () => { |
||||||
|
it('Should duplicate a panel', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const vizPanel = findVizPanelByKey(manager, 'panel-1')!; |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(3); |
||||||
|
|
||||||
|
manager.duplicatePanel(vizPanel); |
||||||
|
|
||||||
|
const newGridItem = grid.state.children[3]; |
||||||
|
|
||||||
|
expect(grid.state.children.length).toBe(4); |
||||||
|
expect(newGridItem.state.key).toBe('grid-item-4'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should maintain size of duplicated panel', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
|
||||||
|
const gItem = grid.state.children[0] as DashboardGridItem; |
||||||
|
gItem.setState({ height: 1 }); |
||||||
|
|
||||||
|
const vizPanel = gItem.state.body; |
||||||
|
manager.duplicatePanel(vizPanel); |
||||||
|
|
||||||
|
const newGridItem = grid.state.children[grid.state.children.length - 1] as DashboardGridItem; |
||||||
|
|
||||||
|
expect(newGridItem.state.height).toBe(1); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should duplicate a repeated panel', () => { |
||||||
|
const { manager, grid } = setup(); |
||||||
|
const gItem = grid.state.children[0] as DashboardGridItem; |
||||||
|
gItem.setState({ variableName: 'server', repeatDirection: 'v', maxPerRow: 100 }); |
||||||
|
const vizPanel = gItem.state.body; |
||||||
|
manager.duplicatePanel(vizPanel as VizPanel); |
||||||
|
|
||||||
|
const newGridItem = grid.state.children[grid.state.children.length - 1] as DashboardGridItem; |
||||||
|
|
||||||
|
expect(newGridItem.state.variableName).toBe('server'); |
||||||
|
expect(newGridItem.state.repeatDirection).toBe('v'); |
||||||
|
expect(newGridItem.state.maxPerRow).toBe(100); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should duplicate a panel in a row', () => { |
||||||
|
const { manager } = setup(); |
||||||
|
const vizPanel = findVizPanelByKey(manager, 'panel-within-row1')!; |
||||||
|
const gridRow = vizPanel.parent?.parent as SceneGridRow; |
||||||
|
|
||||||
|
expect(gridRow.state.children.length).toBe(2); |
||||||
|
|
||||||
|
manager.duplicatePanel(vizPanel); |
||||||
|
|
||||||
|
expect(gridRow.state.children.length).toBe(3); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
interface TestOptions { |
||||||
|
gridItems: SceneGridItemLike[]; |
||||||
|
} |
||||||
|
|
||||||
|
function setup(options?: TestOptions) { |
||||||
|
const gridItems = options?.gridItems ?? [ |
||||||
|
new DashboardGridItem({ |
||||||
|
key: 'griditem-1', |
||||||
|
x: 0, |
||||||
|
body: new VizPanel({ |
||||||
|
title: 'Panel A', |
||||||
|
key: 'panel-1', |
||||||
|
pluginId: 'table', |
||||||
|
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }), |
||||||
|
}), |
||||||
|
}), |
||||||
|
new DashboardGridItem({ |
||||||
|
key: 'griditem-2', |
||||||
|
body: new VizPanel({ |
||||||
|
title: 'Panel B', |
||||||
|
key: 'panel-2', |
||||||
|
pluginId: 'table', |
||||||
|
}), |
||||||
|
}), |
||||||
|
new SceneGridRow({ |
||||||
|
key: 'panel-3', |
||||||
|
title: 'row', |
||||||
|
children: [ |
||||||
|
new DashboardGridItem({ |
||||||
|
body: new VizPanel({ |
||||||
|
title: 'Panel C', |
||||||
|
key: 'panel-within-row1', |
||||||
|
pluginId: 'table', |
||||||
|
}), |
||||||
|
}), |
||||||
|
new DashboardGridItem({ |
||||||
|
body: new VizPanel({ |
||||||
|
title: 'Panel D', |
||||||
|
key: 'panel-within-row2', |
||||||
|
pluginId: 'table', |
||||||
|
}), |
||||||
|
}), |
||||||
|
], |
||||||
|
}), |
||||||
|
]; |
||||||
|
|
||||||
|
const grid = new SceneGridLayout({ children: gridItems }); |
||||||
|
const manager = new DefaultGridLayoutManager({ grid: grid }); |
||||||
|
|
||||||
|
return { manager, grid }; |
||||||
|
} |
@ -0,0 +1,355 @@ |
|||||||
|
import { |
||||||
|
SceneObjectState, |
||||||
|
SceneGridLayout, |
||||||
|
SceneObjectBase, |
||||||
|
SceneGridRow, |
||||||
|
VizPanel, |
||||||
|
sceneGraph, |
||||||
|
sceneUtils, |
||||||
|
SceneComponentProps, |
||||||
|
} from '@grafana/scenes'; |
||||||
|
import { GRID_COLUMN_COUNT } from 'app/core/constants'; |
||||||
|
|
||||||
|
import { |
||||||
|
forceRenderChildren, |
||||||
|
getPanelIdForVizPanel, |
||||||
|
NEW_PANEL_HEIGHT, |
||||||
|
NEW_PANEL_WIDTH, |
||||||
|
getVizPanelKeyForPanelId, |
||||||
|
} from '../../utils/utils'; |
||||||
|
import { DashboardGridItem } from '../DashboardGridItem'; |
||||||
|
import { RowRepeaterBehavior } from '../RowRepeaterBehavior'; |
||||||
|
import { RowActions } from '../row-actions/RowActions'; |
||||||
|
import { DashboardLayoutManager } from '../types'; |
||||||
|
|
||||||
|
interface DefaultGridLayoutManagerState extends SceneObjectState { |
||||||
|
grid: SceneGridLayout; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* State manager for the default grid layout |
||||||
|
*/ |
||||||
|
export class DefaultGridLayoutManager |
||||||
|
extends SceneObjectBase<DefaultGridLayoutManagerState> |
||||||
|
implements DashboardLayoutManager |
||||||
|
{ |
||||||
|
public editModeChanged(isEditing: boolean): void { |
||||||
|
this.state.grid.setState({ isDraggable: isEditing, isResizable: isEditing }); |
||||||
|
forceRenderChildren(this.state.grid, true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes the first panel |
||||||
|
*/ |
||||||
|
public cleanUpStateFromExplore(): void { |
||||||
|
this.state.grid.setState({ |
||||||
|
children: this.state.grid.state.children.slice(1), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public addPanel(vizPanel: VizPanel): void { |
||||||
|
const panelId = getPanelIdForVizPanel(vizPanel); |
||||||
|
const newGridItem = new DashboardGridItem({ |
||||||
|
height: NEW_PANEL_HEIGHT, |
||||||
|
width: NEW_PANEL_WIDTH, |
||||||
|
x: 0, |
||||||
|
y: 0, |
||||||
|
body: vizPanel, |
||||||
|
key: `grid-item-${panelId}`, |
||||||
|
}); |
||||||
|
|
||||||
|
this.state.grid.setState({ |
||||||
|
children: [newGridItem, ...this.state.grid.state.children], |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds a new emtpy row |
||||||
|
*/ |
||||||
|
public addNewRow(): SceneGridRow { |
||||||
|
const id = this.getNextPanelId(); |
||||||
|
const row = new SceneGridRow({ |
||||||
|
key: getVizPanelKeyForPanelId(id), |
||||||
|
title: 'Row title', |
||||||
|
actions: new RowActions({}), |
||||||
|
y: 0, |
||||||
|
}); |
||||||
|
|
||||||
|
const sceneGridLayout = this.state.grid; |
||||||
|
|
||||||
|
// find all panels until the first row and put them into the newly created row. If there are no other rows,
|
||||||
|
// add all panels to the row. If there are no panels just create an empty row
|
||||||
|
const indexTillNextRow = sceneGridLayout.state.children.findIndex((child) => child instanceof SceneGridRow); |
||||||
|
const rowChildren = sceneGridLayout.state.children |
||||||
|
.splice(0, indexTillNextRow === -1 ? sceneGridLayout.state.children.length : indexTillNextRow) |
||||||
|
.map((child) => child.clone()); |
||||||
|
|
||||||
|
if (rowChildren) { |
||||||
|
row.setState({ children: rowChildren }); |
||||||
|
} |
||||||
|
|
||||||
|
sceneGridLayout.setState({ children: [row, ...sceneGridLayout.state.children] }); |
||||||
|
|
||||||
|
return row; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes a row |
||||||
|
* @param row |
||||||
|
* @param removePanels |
||||||
|
*/ |
||||||
|
public removeRow(row: SceneGridRow, removePanels = false) { |
||||||
|
const sceneGridLayout = this.state.grid; |
||||||
|
|
||||||
|
const children = sceneGridLayout.state.children.filter((child) => child.state.key !== row.state.key); |
||||||
|
|
||||||
|
if (!removePanels) { |
||||||
|
const rowChildren = row.state.children.map((child) => child.clone()); |
||||||
|
const indexOfRow = sceneGridLayout.state.children.findIndex((child) => child.state.key === row.state.key); |
||||||
|
|
||||||
|
children.splice(indexOfRow, 0, ...rowChildren); |
||||||
|
} |
||||||
|
|
||||||
|
sceneGridLayout.setState({ children }); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes a panel |
||||||
|
*/ |
||||||
|
public removePanel(panel: VizPanel) { |
||||||
|
const gridItem = panel.parent!; |
||||||
|
|
||||||
|
if (!(gridItem instanceof DashboardGridItem)) { |
||||||
|
throw new Error('Trying to remove panel that is not inside a DashboardGridItem'); |
||||||
|
} |
||||||
|
|
||||||
|
const layout = this.state.grid; |
||||||
|
|
||||||
|
let row: SceneGridRow | undefined; |
||||||
|
|
||||||
|
try { |
||||||
|
row = sceneGraph.getAncestor(gridItem, SceneGridRow); |
||||||
|
} catch { |
||||||
|
row = undefined; |
||||||
|
} |
||||||
|
|
||||||
|
if (row) { |
||||||
|
row.setState({ children: row.state.children.filter((child) => child !== gridItem) }); |
||||||
|
layout.forceRender(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
this.state.grid.setState({ |
||||||
|
children: layout.state.children.filter((child) => child !== gridItem), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public duplicatePanel(vizPanel: VizPanel): void { |
||||||
|
const gridItem = vizPanel.parent; |
||||||
|
if (!(gridItem instanceof DashboardGridItem)) { |
||||||
|
console.error('Trying to duplicate a panel that is not inside a DashboardGridItem'); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
let panelState; |
||||||
|
let panelData; |
||||||
|
let newGridItem; |
||||||
|
|
||||||
|
const newPanelId = this.getNextPanelId(); |
||||||
|
const grid = this.state.grid; |
||||||
|
|
||||||
|
if (gridItem instanceof DashboardGridItem) { |
||||||
|
panelState = sceneUtils.cloneSceneObjectState(gridItem.state.body.state); |
||||||
|
panelData = sceneGraph.getData(gridItem.state.body).clone(); |
||||||
|
} else { |
||||||
|
panelState = sceneUtils.cloneSceneObjectState(vizPanel.state); |
||||||
|
panelData = sceneGraph.getData(vizPanel).clone(); |
||||||
|
} |
||||||
|
|
||||||
|
// when we duplicate a panel we don't want to clone the alert state
|
||||||
|
delete panelData.state.data?.alertState; |
||||||
|
|
||||||
|
newGridItem = new DashboardGridItem({ |
||||||
|
x: gridItem.state.x, |
||||||
|
y: gridItem.state.y, |
||||||
|
height: gridItem.state.height, |
||||||
|
width: gridItem.state.width, |
||||||
|
variableName: gridItem.state.variableName, |
||||||
|
repeatDirection: gridItem.state.repeatDirection, |
||||||
|
maxPerRow: gridItem.state.maxPerRow, |
||||||
|
key: `grid-item-${newPanelId}`, |
||||||
|
body: new VizPanel({ ...panelState, $data: panelData, key: getVizPanelKeyForPanelId(newPanelId) }), |
||||||
|
}); |
||||||
|
|
||||||
|
if (gridItem.parent instanceof SceneGridRow) { |
||||||
|
const row = gridItem.parent; |
||||||
|
|
||||||
|
row.setState({ children: [...row.state.children, newGridItem] }); |
||||||
|
|
||||||
|
grid.forceRender(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
grid.setState({ children: [...grid.state.children, newGridItem] }); |
||||||
|
} |
||||||
|
|
||||||
|
public getVizPanels(): VizPanel[] { |
||||||
|
const panels: VizPanel[] = []; |
||||||
|
|
||||||
|
this.state.grid.forEachChild((child) => { |
||||||
|
if (!(child instanceof DashboardGridItem) && !(child instanceof SceneGridRow)) { |
||||||
|
throw new Error('Child is not a DashboardGridItem or SceneGridRow, invalid scene'); |
||||||
|
} |
||||||
|
|
||||||
|
if (child instanceof DashboardGridItem) { |
||||||
|
if (child.state.body instanceof VizPanel) { |
||||||
|
panels.push(child.state.body); |
||||||
|
} |
||||||
|
} else if (child instanceof SceneGridRow) { |
||||||
|
child.forEachChild((child) => { |
||||||
|
if (child instanceof DashboardGridItem) { |
||||||
|
if (child.state.body instanceof VizPanel) { |
||||||
|
panels.push(child.state.body); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
return panels; |
||||||
|
} |
||||||
|
|
||||||
|
public getNextPanelId(): number { |
||||||
|
let max = 0; |
||||||
|
|
||||||
|
for (const child of this.state.grid.state.children) { |
||||||
|
if (child instanceof DashboardGridItem) { |
||||||
|
const vizPanel = child.state.body; |
||||||
|
|
||||||
|
if (vizPanel) { |
||||||
|
const panelId = getPanelIdForVizPanel(vizPanel); |
||||||
|
|
||||||
|
if (panelId > max) { |
||||||
|
max = panelId; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (child instanceof SceneGridRow) { |
||||||
|
//rows follow the same key pattern --- e.g.: `panel-6`
|
||||||
|
const panelId = getPanelIdForVizPanel(child); |
||||||
|
|
||||||
|
if (panelId > max) { |
||||||
|
max = panelId; |
||||||
|
} |
||||||
|
|
||||||
|
for (const rowChild of child.state.children) { |
||||||
|
if (rowChild instanceof DashboardGridItem) { |
||||||
|
const vizPanel = rowChild.state.body; |
||||||
|
|
||||||
|
if (vizPanel) { |
||||||
|
const panelId = getPanelIdForVizPanel(vizPanel); |
||||||
|
|
||||||
|
if (panelId > max) { |
||||||
|
max = panelId; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return max + 1; |
||||||
|
} |
||||||
|
|
||||||
|
public collapseAllRows() { |
||||||
|
this.state.grid.state.children.forEach((child) => { |
||||||
|
if (!(child instanceof SceneGridRow)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!child.state.isCollapsed) { |
||||||
|
this.state.grid.toggleRow(child); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public expandAllRows() { |
||||||
|
this.state.grid.state.children.forEach((child) => { |
||||||
|
if (!(child instanceof SceneGridRow)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (child.state.isCollapsed) { |
||||||
|
this.state.grid.toggleRow(child); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
activateRepeaters(): void { |
||||||
|
this.state.grid.forEachChild((child) => { |
||||||
|
if (child instanceof DashboardGridItem && !child.isActive) { |
||||||
|
child.activate(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (child instanceof SceneGridRow && child.state.$behaviors) { |
||||||
|
for (const behavior of child.state.$behaviors) { |
||||||
|
if (behavior instanceof RowRepeaterBehavior && !child.isActive) { |
||||||
|
child.activate(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
child.state.children.forEach((child) => { |
||||||
|
if (child instanceof DashboardGridItem && !child.isActive) { |
||||||
|
child.activate(); |
||||||
|
return; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* For simple test grids |
||||||
|
* @param panels |
||||||
|
*/ |
||||||
|
public static fromVizPanels(panels: VizPanel[] = []): DefaultGridLayoutManager { |
||||||
|
const children: DashboardGridItem[] = []; |
||||||
|
const panelHeight = 10; |
||||||
|
const panelWidth = GRID_COLUMN_COUNT / 3; |
||||||
|
let currentY = 0; |
||||||
|
let currentX = 0; |
||||||
|
|
||||||
|
for (let panel of panels) { |
||||||
|
children.push( |
||||||
|
new DashboardGridItem({ |
||||||
|
key: `griditem-${getPanelIdForVizPanel(panel)}`, |
||||||
|
x: currentX, |
||||||
|
y: currentY, |
||||||
|
width: panelWidth, |
||||||
|
height: panelHeight, |
||||||
|
body: panel, |
||||||
|
}) |
||||||
|
); |
||||||
|
|
||||||
|
currentX += panelWidth; |
||||||
|
|
||||||
|
if (currentX + panelWidth >= GRID_COLUMN_COUNT) { |
||||||
|
currentX = 0; |
||||||
|
currentY += panelHeight; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return new DefaultGridLayoutManager({ |
||||||
|
grid: new SceneGridLayout({ |
||||||
|
children: children, |
||||||
|
isDraggable: false, |
||||||
|
isResizable: false, |
||||||
|
}), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public static Component = ({ model }: SceneComponentProps<DefaultGridLayoutManager>) => { |
||||||
|
return <model.state.grid.Component model={model.state.grid} />; |
||||||
|
}; |
||||||
|
} |
Loading…
Reference in new issue