Skip to content

Commit 8f349be

Browse files
committed
started new metadata schema
1 parent c78a3fb commit 8f349be

File tree

7 files changed

+221
-56
lines changed

7 files changed

+221
-56
lines changed

src/dashboard.tsx

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ import { DashboardLayout } from './layout';
2929

3030
import { DashboardWidget } from './widget';
3131

32-
import { WidgetPosition, Widgetstore } from './widgetstore';
32+
import { Widgetstore, WidgetInfo } from './widgetstore';
3333

3434
import {
3535
addCellId,
3636
addNotebookId,
3737
getNotebookById,
3838
getCellId,
39-
updateMetadata
39+
getMetadata,
40+
addMetadataView
4041
} from './utils';
4142

4243
import {
@@ -54,6 +55,8 @@ import { HTMLSelect } from '@jupyterlab/ui-components';
5455

5556
import { UUID } from '@lumino/coreutils';
5657

58+
import * as dbformat from './dbformat';
59+
5760
// HTML element classes
5861

5962
export const DASHBOARD_CLASS = 'pr-JupyterDashboard';
@@ -182,8 +185,8 @@ export class Dashboard extends Widget {
182185
const pos = { left, top, width, height };
183186

184187
if (oldDashboard === this) {
185-
// dragging in same dashboard.ono
186-
this.updateWidget(widget, pos);
188+
// dragging in same dashboard.
189+
this.updateWidget(widget, { pos });
187190
} else {
188191
// dragging between dashboards
189192
const info: Widgetstore.WidgetInfo = {
@@ -284,9 +287,9 @@ export class Dashboard extends Widget {
284287

285288
updateWidget(
286289
widget: DashboardWidget,
287-
pos: Widgetstore.WidgetPosition
290+
newInfo: Partial<WidgetInfo>
288291
): boolean {
289-
return (this.layout as DashboardLayout).updateWidget(widget, pos);
292+
return (this.layout as DashboardLayout).updateWidget(widget, newInfo);
290293
}
291294

292295
/**
@@ -364,7 +367,7 @@ export class Dashboard extends Widget {
364367
return (this.layout as DashboardLayout).createWidget(info, fit);
365368
}
366369

367-
saveToNotebookMetadata(): void {
370+
saveToNotebookMetadata(name: string = 'default'): void {
368371
// Get a list of all notebookIds used in the dashboard.
369372
const widgets = toArray(this.model.widgetstore.getWidgets());
370373

@@ -380,22 +383,64 @@ export class Dashboard extends Widget {
380383
const notebookTracker = this.model.notebookTracker;
381384
const notebook = getNotebookById(notebookId, notebookTracker);
382385

383-
updateMetadata(notebook, { hasDashboard: true });
386+
const oldDashboardMetadata = getMetadata(notebook);
387+
let dashboardId: string;
388+
389+
if ((oldDashboardMetadata as Object).hasOwnProperty('views')) {
390+
const dashboardIds = Object.keys(oldDashboardMetadata.views);
391+
if (dashboardIds.length != 1) {
392+
throw new Error(
393+
'Multiple dashboards are embedded--currently only a single embedded dashboard is supported.'
394+
);
395+
}
396+
dashboardId = dashboardIds[0];
397+
} else {
398+
dashboardId = UUID.uuid4();
399+
}
400+
401+
const cellWidth = (this.layout as DashboardLayout).tileSize;
402+
// Only square dimensions are currently supported.
403+
const cellHeight = cellWidth;
404+
405+
const dashboardView = {
406+
name,
407+
cellWidth,
408+
cellHeight,
409+
dashboardWidth: this.model.width,
410+
dashboardHeight: this.model.height
411+
};
412+
addMetadataView(notebook, dashboardId, dashboardView);
384413

385414
const cells = notebook.content.widgets;
386415

387-
const widgetMap = new Map<string, WidgetPosition>(
388-
widgets.map(widget => [widget.cellId, widget.pos])
416+
const widgetMap = new Map<string, WidgetInfo>(
417+
widgets.map(widget => [widget.cellId, widget])
389418
);
390419

391420
each(cells, cell => {
392421
const cellId = getCellId(cell);
393-
const pos = widgetMap.get(cellId);
394-
if (pos != null) {
395-
updateMetadata(cell, { pos, hidden: false });
396-
} else {
397-
updateMetadata(cell, { hidden: true });
422+
const info = widgetMap.get(cellId);
423+
let view: Partial<dbformat.ICellView> = { hidden: true };
424+
425+
if (info != null) {
426+
let { pos, snapToGrid } = info;
427+
let { left, top, width, height } = pos;
428+
let adjustedPos = !snapToGrid ? pos : {
429+
left: left / cellWidth,
430+
top: top / cellHeight,
431+
width: width / cellWidth,
432+
height: height / cellHeight
433+
};
434+
435+
view = {
436+
hidden: false,
437+
name,
438+
pos: adjustedPos,
439+
snapToGrid: snapToGrid
440+
};
398441
}
442+
443+
addMetadataView(cell, dashboardId, view);
399444
});
400445

401446
notebook.context.save();

src/dbformat.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { PartialJSONObject } from '@lumino/coreutils';
22

3+
import { WidgetPosition } from './widgetstore';
4+
35
export const DASHBOARD_VERSION = 1;
46

57
/**
@@ -55,3 +57,29 @@ export interface IOutputInfo extends PartialJSONObject {
5557
height: number;
5658
};
5759
}
60+
61+
export interface ICellView {
62+
name: string;
63+
pos: WidgetPosition,
64+
hidden: boolean,
65+
snapToGrid: boolean,
66+
}
67+
68+
export interface ICellMetadataFormat {
69+
id: string;
70+
views: { [id: string]: ICellView }
71+
}
72+
73+
export interface IDashboardView {
74+
name: string;
75+
cellWidth: number;
76+
cellHeight: number;
77+
dashboardWidth: number;
78+
dashboardHeight: number;
79+
}
80+
81+
82+
export interface INBMetadataFormat {
83+
id: string;
84+
views: { [id: string]: IDashboardView }
85+
}

src/index.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,23 @@ function addCommands(
591591
execute: args => {
592592
const notebook = notebookTracker.currentWidget;
593593
const notebookMetadata = getMetadata(notebook);
594+
if (!('views' in notebookMetadata)) {
595+
throw new Error('No views in notebook');
596+
}
594597
const notebookId = notebookMetadata.id;
598+
let dashboardId: string;
599+
if (args.id != null) {
600+
dashboardId = args.id as string;
601+
if (!(notebookMetadata.views as Object).hasOwnProperty(dashboardId)) {
602+
throw new Error(`Dashboard id ${dashboardId} doesn't exist in notebook ${notebookId}`);
603+
}
604+
} else {
605+
dashboardId = Object.keys(notebookMetadata.views)[0]
606+
}
607+
608+
const dashboardView = notebookMetadata.views[dashboardId];
609+
const { cellHeight, cellWidth, dashboardHeight, dashboardWidth } = dashboardView;
610+
595611
const cells = notebook.content.widgets;
596612

597613
const widgetstore = new Widgetstore({ id: 0, notebookTracker });
@@ -600,12 +616,23 @@ function addCommands(
600616

601617
for (const cell of cells) {
602618
const metadata = getMetadata(cell);
603-
if (metadata !== undefined && !metadata.hidden) {
619+
if (metadata !== undefined && !metadata.views[dashboardId].hidden) {
620+
let { pos, snapToGrid } = metadata.views[dashboardId];
621+
let { left, top, width, height } = pos;
622+
623+
let adjustedPos = !snapToGrid ? pos : {
624+
left: left * cellWidth,
625+
top: top * cellHeight,
626+
width: width * cellWidth,
627+
height: height * cellHeight
628+
};
629+
604630
const widgetInfo: WidgetInfo = {
605631
widgetId: DashboardWidget.createDashboardWidgetId(),
606632
notebookId,
607633
cellId: metadata.id,
608-
pos: metadata.pos
634+
snapToGrid,
635+
pos: adjustedPos
609636
};
610637
widgetstore.addWidget(widgetInfo);
611638
}
@@ -623,6 +650,10 @@ function addCommands(
623650
model
624651
});
625652

653+
dashboard.model.width = dashboardWidth;
654+
dashboard.model.height = dashboardHeight;
655+
(dashboard.layout as DashboardLayout).setTileSize(cellHeight);
656+
626657
dashboard.updateLayoutFromWidgetstore();
627658
dashboard.model.mode = 'present';
628659

@@ -631,8 +662,8 @@ function addCommands(
631662
isEnabled: args => {
632663
const notebook = notebookTracker.currentWidget;
633664
const metadata = getMetadata(notebook);
634-
if (metadata !== undefined && metadata.hasDashboard !== undefined) {
635-
return metadata.hasDashboard;
665+
if (metadata !== undefined) {
666+
return true
636667
}
637668
return false;
638669
}

src/layout.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { MessageLoop, Message } from '@lumino/messaging';
88

99
import { DashboardWidget } from './widget';
1010

11-
import { Widgetstore, WidgetSchema, WidgetPosition } from './widgetstore';
11+
import { Widgetstore, WidgetSchema, WidgetInfo, WidgetPosition } from './widgetstore';
1212

1313
import { WidgetTracker } from '@jupyterlab/apputils';
1414

@@ -240,12 +240,12 @@ export class DashboardLayout extends Layout {
240240
}
241241
this.attachWidget(widget);
242242

243-
const { id, notebookId, cellId } = widget;
243+
const { id, notebookId, cellId, snapToGrid } = widget;
244244

245245
const ignore = !this._signalChanges;
246246

247247
widget.ready.connect(() => {
248-
this._updateWidget(widget, widget.pos, false);
248+
this._updateWidget(widget, { pos: widget.pos }, false);
249249
this.fixOverlaps(widget);
250250
this._outputTracker.add(widget);
251251

@@ -255,6 +255,7 @@ export class DashboardLayout extends Layout {
255255
widgetId: id,
256256
notebookId,
257257
cellId,
258+
snapToGrid,
258259
ignore
259260
};
260261

@@ -275,14 +276,14 @@ export class DashboardLayout extends Layout {
275276
*/
276277
updateWidget(
277278
widget: DashboardWidget,
278-
pos: Widgetstore.WidgetPosition
279+
newInfo: Partial<WidgetInfo>
279280
): boolean {
280281
const wasInBatch = this.inBatch;
281282
if (!wasInBatch) {
282283
this.startBatch();
283284
}
284285

285-
const success = this._updateWidgetHelper(widget, pos);
286+
const success = this._updateWidgetHelper(widget, newInfo);
286287

287288
if (!wasInBatch) {
288289
this.endBatch();
@@ -308,14 +309,15 @@ export class DashboardLayout extends Layout {
308309
*/
309310
private _updateWidgetHelper(
310311
widget: DashboardWidget,
311-
pos: Widgetstore.WidgetPosition,
312+
newInfo: Partial<WidgetInfo>,
312313
fixOverlaps = true
313314
): boolean {
314-
const success = this._updateWidget(widget, pos, fixOverlaps);
315+
const success = this._updateWidget(widget, newInfo, fixOverlaps);
315316
if (success) {
316317
const change: IDashboardChange = {
317-
type: 'move',
318+
type: 'update',
318319
widgetId: widget.id,
320+
snapToGrid: widget.snapToGrid,
319321
pos: widget.pos
320322
};
321323
this.signalChange(change);
@@ -341,7 +343,7 @@ export class DashboardLayout extends Layout {
341343
*/
342344
private _updateWidget(
343345
widget: DashboardWidget,
344-
pos: Widgetstore.WidgetPosition,
346+
newInfo: Partial<WidgetInfo>,
345347
fixOverlaps = true
346348
): boolean {
347349
// Get the item from the map.
@@ -352,7 +354,12 @@ export class DashboardLayout extends Layout {
352354
return false;
353355
}
354356

355-
let { left, top, width, height } = pos;
357+
// Just changing snap-to-grid status.
358+
if (newInfo.pos == null) {
359+
return true
360+
}
361+
362+
let { left, top, width, height } = newInfo.pos;
356363

357364
// Constrain the widget to the dashboard dimensions.
358365
if (this._width !== 0 && left + width > this._width) {
@@ -499,7 +506,7 @@ export class DashboardLayout extends Layout {
499506
}
500507

501508
// Widget was moved or resized; update.
502-
this.updateWidget(item.widget as DashboardWidget, pos);
509+
this.updateWidget(item.widget as DashboardWidget, { pos });
503510
}
504511
}
505512

@@ -627,7 +634,7 @@ export class DashboardLayout extends Layout {
627634
this._expandCanvas(type, widthDiff);
628635
}
629636

630-
this._updateWidget(widget, newPos);
637+
this._updateWidget(widget, { pos: newPos });
631638
}
632639

633640
/**
@@ -682,7 +689,7 @@ export class DashboardLayout extends Layout {
682689
const widget = _widget as DashboardWidget;
683690
const pos = widget.pos;
684691
pos.left += amount;
685-
this._updateWidgetHelper(widget, pos);
692+
this._updateWidgetHelper(widget, { pos });
686693
});
687694
break;
688695
case 'right':
@@ -694,7 +701,7 @@ export class DashboardLayout extends Layout {
694701
const widget = _widget as DashboardWidget;
695702
const pos = widget.pos;
696703
pos.top += amount;
697-
this._updateWidgetHelper(widget, pos);
704+
this._updateWidgetHelper(widget, { pos });
698705
});
699706
break;
700707
case 'down':
@@ -878,7 +885,7 @@ export class DashboardLayout extends Layout {
878885
this.startBatch();
879886
each(this, _widget => {
880887
const widget = _widget as DashboardWidget;
881-
this.updateWidget(widget, widget.pos);
888+
this.updateWidget(widget, { pos: widget.pos });
882889
});
883890
this.endBatch();
884891
}
@@ -1016,7 +1023,7 @@ export namespace DashboardLayout {
10161023
/**
10171024
* A type for dashboard changes emitted by the changed signal.
10181025
*/
1019-
export type DashboardChangeType = 'add' | 'remove' | 'move';
1026+
export type DashboardChangeType = 'add' | 'remove' | 'update';
10201027

10211028
/**
10221029
* An interface describing a change that occurs to the dashboard.
@@ -1037,6 +1044,8 @@ export interface IDashboardChange {
10371044

10381045
cellId?: string;
10391046

1047+
snapToGrid?: boolean;
1048+
10401049
ignore?: boolean;
10411050
}
10421051

0 commit comments

Comments
 (0)