Skip to content

Commit 9f40508

Browse files
committed
Changed panel placement system. Now the panels attempt to find blank space in 3 directions around the panel they're cloned from, failing that, they take the space directly below their origin and push down all panels that conflict
1 parent 0c2c545 commit 9f40508

File tree

3 files changed

+69
-36
lines changed

3 files changed

+69
-36
lines changed

src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@ import { DashboardPanelState } from '../types';
2222
import { createPanelState } from './create_panel_state';
2323
import { EmbeddableInput } from '../../../embeddable_plugin';
2424
import { CONTACT_CARD_EMBEDDABLE } from '../../../embeddable_plugin_test_samples';
25-
import { IPanelPlacementArgs } from './dashboard_panel_placement';
2625

2726
interface TestInput extends EmbeddableInput {
2827
test: string;
2928
}
3029
const panels: { [key: string]: DashboardPanelState } = {};
3130

3231
test('createPanelState adds a new panel state in 0,0 position', () => {
33-
const panelState = createPanelState<TestInput, IPanelPlacementArgs>(
32+
const panelState = createPanelState<TestInput>(
3433
{
3534
type: CONTACT_CARD_EMBEDDABLE,
3635
explicitInput: { test: 'hi', id: '123' },
@@ -49,7 +48,7 @@ test('createPanelState adds a new panel state in 0,0 position', () => {
4948
});
5049

5150
test('createPanelState adds a second new panel state', () => {
52-
const panelState = createPanelState<TestInput, IPanelPlacementArgs>(
51+
const panelState = createPanelState<TestInput>(
5352
{ type: CONTACT_CARD_EMBEDDABLE, explicitInput: { test: 'bye', id: '456' } },
5453
panels
5554
);
@@ -63,7 +62,7 @@ test('createPanelState adds a second new panel state', () => {
6362
});
6463

6564
test('createPanelState adds a third new panel state', () => {
66-
const panelState = createPanelState<TestInput, IPanelPlacementArgs>(
65+
const panelState = createPanelState<TestInput>(
6766
{
6867
type: CONTACT_CARD_EMBEDDABLE,
6968
explicitInput: { test: 'bye', id: '789' },
@@ -80,7 +79,7 @@ test('createPanelState adds a third new panel state', () => {
8079

8180
test('createPanelState adds a new panel state in the top most position', () => {
8281
delete panels['456'];
83-
const panelState = createPanelState<TestInput, IPanelPlacementArgs>(
82+
const panelState = createPanelState<TestInput>(
8483
{
8584
type: CONTACT_CARD_EMBEDDABLE,
8685
explicitInput: { test: 'bye', id: '987' },

src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
*/
3333
export function createPanelState<
3434
TEmbeddableInput extends EmbeddableInput,
35-
TPlacementMethodArgs extends IPanelPlacementArgs
35+
TPlacementMethodArgs extends IPanelPlacementArgs = IPanelPlacementArgs
3636
>(
3737
panelState: PanelState<TEmbeddableInput>,
3838
currentPanels: { [key: string]: DashboardPanelState },

src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,55 +102,89 @@ export function findTopLeftMostOpenSpace({
102102
return { x: 0, y: maxY, w: width, h: height };
103103
}
104104

105+
interface IplacementDirection {
106+
grid: Omit<GridData, 'i'>;
107+
fits: boolean;
108+
}
109+
105110
export function placePanelBeside({
106111
width,
107112
height,
108113
currentPanels,
109114
placeBesideId,
110115
}: IPanelPlacementBesideArgs): Omit<GridData, 'i'> {
111-
const finalPanels = _.cloneDeep(currentPanels);
116+
// const clonedPanels = _.cloneDeep(currentPanels);
112117
if (!placeBesideId) {
113118
throw new Error('Place beside method called without placeBesideId');
114119
}
115-
const panelToPlaceBeside = finalPanels[placeBesideId];
120+
const panelToPlaceBeside = currentPanels[placeBesideId];
116121
if (!panelToPlaceBeside) {
117122
throw new PanelNotFoundError();
118123
}
119-
120-
const duplicatedPanelGrid = {} as GridData;
121-
duplicatedPanelGrid.x = panelToPlaceBeside.gridData.x + panelToPlaceBeside.gridData.w;
122-
duplicatedPanelGrid.y = panelToPlaceBeside.gridData.y;
123-
duplicatedPanelGrid.w = width;
124-
duplicatedPanelGrid.h = height;
125-
126-
// Adjust flow of dashboard if necessary
124+
const beside = panelToPlaceBeside.gridData;
127125
const otherPanels: GridData[] = [];
128-
_.forOwn(finalPanels, (panel: DashboardPanelState) => {
129-
if (panel.savedObjectId !== panelToPlaceBeside.savedObjectId) {
130-
otherPanels.push(panel.gridData);
131-
}
132-
});
133-
134-
const intersection = otherPanels.some((currentPanelGrid: GridData) => {
135-
return (
136-
duplicatedPanelGrid.x + duplicatedPanelGrid.w > currentPanelGrid.x &&
137-
duplicatedPanelGrid.x < currentPanelGrid.x + currentPanelGrid.w &&
138-
duplicatedPanelGrid.y < currentPanelGrid.y + currentPanelGrid.h &&
139-
duplicatedPanelGrid.y + duplicatedPanelGrid.h > currentPanelGrid.y
140-
);
126+
_.forOwn(currentPanels, (panel: DashboardPanelState, key: string | undefined) => {
127+
otherPanels.push(panel.gridData);
141128
});
142129

143-
// if any other panel intersects with the newly duplicated panel, move all panels in the same 'row' to the right by the amount of the duplciated panel's width
144-
if (intersection) {
130+
const possiblePlacementDirections: IplacementDirection[] = [
131+
{ grid: { x: beside.x + beside.w, y: beside.y, w: width, h: height }, fits: true }, // right
132+
{ grid: { x: beside.x - width, y: beside.y, w: width, h: height }, fits: true }, // left
133+
{ grid: { x: beside.x, y: beside.y + beside.h, w: width, h: height }, fits: true }, // bottom
134+
];
135+
136+
for (const direction of possiblePlacementDirections) {
137+
if (
138+
direction.grid.x >= 0 &&
139+
direction.grid.x + direction.grid.w <= DASHBOARD_GRID_COLUMN_COUNT &&
140+
direction.grid.y >= 0
141+
) {
142+
const intersection = otherPanels.some((currentPanelGrid: GridData) => {
143+
return (
144+
direction.grid.x + direction.grid.w > currentPanelGrid.x &&
145+
direction.grid.x < currentPanelGrid.x + currentPanelGrid.w &&
146+
direction.grid.y < currentPanelGrid.y + currentPanelGrid.h &&
147+
direction.grid.y + direction.grid.h > currentPanelGrid.y
148+
);
149+
});
150+
if (!intersection) {
151+
return direction.grid;
152+
}
153+
} else {
154+
direction.fits = false;
155+
}
156+
}
157+
// if we get here that means there is no blank space around the panel we are placing beside. This means it's time to mess up the dashboard's groove. Fun!
158+
const [rightPlacement, , bottomPlacement] = possiblePlacementDirections;
159+
if (rightPlacement.fits) {
145160
otherPanels.forEach((currentPanelGrid: GridData) => {
146161
if (
147-
currentPanelGrid.x >= duplicatedPanelGrid.x &&
148-
duplicatedPanelGrid.y <= currentPanelGrid.y + currentPanelGrid.h &&
149-
duplicatedPanelGrid.y + duplicatedPanelGrid.h >= currentPanelGrid.y
162+
currentPanelGrid.x >= rightPlacement.grid.x &&
163+
rightPlacement.grid.y < currentPanelGrid.y + currentPanelGrid.h &&
164+
rightPlacement.grid.y + rightPlacement.grid.h > currentPanelGrid.y
150165
) {
151-
currentPanelGrid.x += duplicatedPanelGrid.w;
166+
const movedPanel = _.cloneDeep(currentPanels[currentPanelGrid.i]);
167+
if (movedPanel.gridData.x + rightPlacement.grid.w > DASHBOARD_GRID_COLUMN_COUNT) {
168+
movedPanel.gridData.y = movedPanel.gridData.y + rightPlacement.grid.h;
169+
} else {
170+
movedPanel.gridData.x = movedPanel.gridData.x + rightPlacement.grid.w;
171+
}
172+
currentPanels[currentPanelGrid.i] = movedPanel;
152173
}
153174
});
175+
return rightPlacement.grid;
176+
}
177+
for (const currentPanelGrid of otherPanels) {
178+
if (
179+
bottomPlacement.grid.x + bottomPlacement.grid.w > currentPanelGrid.x &&
180+
bottomPlacement.grid.x < currentPanelGrid.x + currentPanelGrid.w &&
181+
bottomPlacement.grid.y < currentPanelGrid.y + currentPanelGrid.h &&
182+
bottomPlacement.grid.y + bottomPlacement.grid.h > currentPanelGrid.y
183+
) {
184+
const movedPanel = _.cloneDeep(currentPanels[currentPanelGrid.i]);
185+
movedPanel.gridData.y = movedPanel.gridData.y + bottomPlacement.grid.h;
186+
currentPanels[currentPanelGrid.i] = movedPanel;
187+
}
154188
}
155-
return duplicatedPanelGrid;
189+
return bottomPlacement.grid;
156190
}

0 commit comments

Comments
 (0)