Skip to content

Commit f44a33c

Browse files
committed
preliminary single metadata dashboard work (EXPERIMENTAL)
1 parent cdd0cc7 commit f44a33c

File tree

8 files changed

+256
-74
lines changed

8 files changed

+256
-74
lines changed

src/commands.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ export namespace CommandIDs {
1919
export const startFullscreen = 'dashboard:start-fullscreen';
2020
export const createNew = 'dashboard:create-new';
2121
export const setTileSize = 'dashboard:set-tile-size';
22+
export const saveToMetadata = 'dashboard:save-to-metadata';
23+
export const openFromMetadata = 'dashboard:open-from-metadata';
2224
}

src/dashboard.tsx

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { NotebookPanel } from '@jupyterlab/notebook';
22

33
import { CodeCell, MarkdownCell, Cell } from '@jupyterlab/cells';
44

5+
import { filter, map, toArray, ArrayExt } from '@lumino/algorithm';
6+
57
import * as React from 'react';
68

79
import {
@@ -10,6 +12,7 @@ import {
1012
IWidgetTracker,
1113
Toolbar,
1214
ReactWidget,
15+
// MainAreaWidget,
1316
} from '@jupyterlab/apputils';
1417

1518
import { CommandRegistry } from '@lumino/commands';
@@ -28,7 +31,7 @@ import { DashboardWidget } from './widget';
2831

2932
import { Widgetstore } from './widgetstore';
3033

31-
import { addCellId, addNotebookId } from './utils';
34+
import { addCellId, addNotebookId, getNotebookById, getCellId, updateMetadata } from './utils';
3235

3336
import {
3437
DocumentWidget,
@@ -70,9 +73,11 @@ export class Dashboard extends Widget {
7073
constructor(options: Dashboard.IOptions) {
7174
super(options);
7275

73-
const { outputTracker, model, context } = options;
76+
const { outputTracker, model } = options;
7477
this._model = model;
75-
this._context = context;
78+
if (options.context !== undefined) {
79+
this._context = options.context;
80+
}
7681
const { widgetstore, mode } = model;
7782

7883
this.layout = new DashboardLayout({
@@ -349,6 +354,55 @@ export class Dashboard extends Widget {
349354
return (this.layout as DashboardLayout).createWidget(info, fit);
350355
}
351356

357+
saveToNotebookMetadata() {
358+
// Get a list of all notebookIds used in the dashboard.
359+
const widgets = toArray(
360+
filter(
361+
this.model.widgetstore.getWidgets(),
362+
(widget) => widget.widgetId && !widget.removed
363+
)
364+
);
365+
366+
const notebookIds = toArray(
367+
map(
368+
widgets,
369+
(record) => record.notebookId
370+
)
371+
);
372+
373+
if (!notebookIds.every((v) => v === notebookIds[0])) {
374+
console.log(notebookIds);
375+
throw new Error('Only single notebook dashboards can be saved to metadata.');
376+
}
377+
378+
const notebookId = notebookIds[0];
379+
const notebookTracker = this.model.notebookTracker;
380+
const notebook = getNotebookById(notebookId, notebookTracker);
381+
updateMetadata(notebook, { hasDashboard: true });
382+
383+
const cells = notebook.content.widgets;
384+
385+
for (let widget of widgets) {
386+
let { pos, cellId } = widget;
387+
388+
let cell = ArrayExt.findFirstValue(
389+
cells,
390+
(cell) => getCellId(cell) === cellId
391+
);
392+
393+
// let output = find(
394+
// this.layout,
395+
// (widget) => widget.id === widgetId
396+
// );
397+
398+
if (cell !== undefined) {
399+
updateMetadata(cell, { pos });
400+
}
401+
}
402+
403+
notebook.context.save();
404+
}
405+
352406
get model(): IDashboardModel {
353407
return this._model;
354408
}
@@ -394,15 +448,28 @@ export namespace Dashboard {
394448

395449
model: IDashboardModel;
396450

397-
context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
451+
context?: DocumentRegistry.IContext<DocumentRegistry.IModel>;
398452
}
399453
}
400454

455+
// export class SingleNotebookDashboard extends MainAreaWidget {
456+
// constructor(options: SingleNotebookDashboard.IOptions) {
457+
458+
// }
459+
// }
460+
461+
// export namespace SingleNotebookDashboard {
462+
// export interface IOptions {
463+
464+
// }
465+
// }
466+
401467
export class DashboardDocument extends DocumentWidget<Dashboard> {
402468
constructor(options: DashboardDocument.IOptions) {
403469
let { content, reveal } = options;
404470
const { context, commandRegistry } = options;
405471
const model = context.model as DashboardModel;
472+
model.path = context.path;
406473
content = content || new Dashboard({ ...options, model, context });
407474
reveal = Promise.all([reveal, context.ready]);
408475
super({
@@ -473,7 +540,7 @@ export namespace DashboardDocument {
473540
name?: string;
474541

475542
/**
476-
* Dashboard canvas width (default is 1280).
543+
* Optional widgetstore to restore from.
477544
*/
478545
store?: Widgetstore;
479546

src/drag.ts

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ export class Drag implements IDisposable {
137137
this.proposedAction = options.proposedAction || 'copy';
138138
this.supportedActions = options.supportedActions || 'all';
139139
this.source = options.source || null;
140-
this._widgetX = options.widgetX || 0;
141-
this._widgetY = options.widgetY || 0;
140+
this._dragAdjustX = options.dragAdjustX || 0;
141+
this._dragAdjustY = options.dragAdjustY || 0;
142142
}
143143

144144
/**
@@ -228,8 +228,8 @@ export class Drag implements IDisposable {
228228
return this._promise;
229229
}
230230

231-
this._deltaX = this._widgetX - clientX;
232-
this._deltaY = this._widgetY - clientY;
231+
this._dragOffsetX = this._dragAdjustX - clientX;
232+
this._dragOffsetY = this._dragAdjustY - clientY;
233233

234234
// Install the document listeners for the drag object.
235235
this._addListeners();
@@ -295,7 +295,7 @@ export class Drag implements IDisposable {
295295

296296
// Move the drag image to the specified client position. This is
297297
// performed *after* dispatching to prevent unnecessary reflows.
298-
this._moveDragImage(event.clientX, event.clientY);
298+
this.moveDragImage(event.clientX, event.clientY);
299299
}
300300

301301
/**
@@ -416,8 +416,8 @@ export class Drag implements IDisposable {
416416

417417
// Find the current indicated element at the given position.
418418
const currElems = document.elementsFromPoint(
419-
event.clientX + this._deltaX,
420-
event.clientY + this._deltaY
419+
event.clientX + this._dragOffsetX,
420+
event.clientY + this._dragOffsetY
421421
);
422422

423423
let currElem = currElems.find((elem) =>
@@ -470,8 +470,8 @@ export class Drag implements IDisposable {
470470
const style = this.dragImage.style;
471471
style.pointerEvents = 'none';
472472
style.position = 'fixed';
473-
style.top = `${clientY + this._deltaY}px`;
474-
style.left = `${clientX + this._deltaX}px`;
473+
style.top = `${clientY + this._dragOffsetY}px`;
474+
style.left = `${clientX + this._dragOffsetX}px`;
475475
document.body.appendChild(this.dragImage);
476476
}
477477

@@ -480,13 +480,13 @@ export class Drag implements IDisposable {
480480
*
481481
* This is a no-op if there is no drag image element.
482482
*/
483-
private _moveDragImage(clientX: number, clientY: number): void {
483+
protected moveDragImage(clientX: number, clientY: number): void {
484484
if (!this.dragImage) {
485485
return;
486486
}
487487
const style = this.dragImage.style;
488-
style.top = `${clientY + this._deltaY}px`;
489-
style.left = `${clientX + this._deltaX}px`;
488+
style.top = `${clientY + this.dragOffsetY}px`;
489+
style.left = `${clientX + this.dragOffsetX}px`;
490490
}
491491

492492
/**
@@ -607,12 +607,12 @@ export class Drag implements IDisposable {
607607
requestAnimationFrame(this._onScrollFrame);
608608
};
609609

610-
get deltaX(): number {
611-
return this._deltaX;
610+
get dragOffsetX(): number {
611+
return this._dragOffsetX;
612612
}
613613

614-
get deltaY(): number {
615-
return this._deltaY;
614+
get dragOffsetY(): number {
615+
return this._dragOffsetY;
616616
}
617617

618618
private _disposed = false;
@@ -623,10 +623,10 @@ export class Drag implements IDisposable {
623623
private _promise: Promise<DropAction> | null = null;
624624
private _scrollTarget: Private.IScrollTarget | null = null;
625625
private _resolve: ((value: DropAction) => void) | null = null;
626-
private _widgetX: number;
627-
private _widgetY: number;
628-
private _deltaX: number;
629-
private _deltaY: number;
626+
private _dragAdjustX: number;
627+
private _dragAdjustY: number;
628+
private _dragOffsetX: number;
629+
private _dragOffsetY: number;
630630
}
631631

632632
/**
@@ -702,14 +702,14 @@ export namespace Drag {
702702
*
703703
* The default value is 0.
704704
*/
705-
widgetX?: number;
705+
dragAdjustX?: number;
706706

707707
/**
708708
* How many pixels to offset the drag/image in the y direction.
709709
*
710710
* The default value is 0.
711711
*/
712-
widgetY?: number;
712+
dragAdjustY?: number;
713713
}
714714

715715
/**
@@ -842,8 +842,8 @@ namespace Private {
842842
drag: Drag
843843
): IScrollTarget | null {
844844
// Look up the client mouse position.
845-
const x = event.clientX + drag.deltaX;
846-
const y = event.clientY + drag.deltaY;
845+
const x = event.clientX + drag.dragOffsetX;
846+
const y = event.clientY + drag.dragOffsetY;
847847

848848
// Get the element under the mouse.
849849
let element: Element | null = document.elementFromPoint(x, y);
@@ -1199,10 +1199,10 @@ namespace Private {
11991199
true,
12001200
window,
12011201
0,
1202-
event.screenX + drag.deltaX,
1203-
event.screenY + drag.deltaY,
1204-
event.clientX + drag.deltaX,
1205-
event.clientY + drag.deltaY,
1202+
event.screenX + drag.dragOffsetX,
1203+
event.screenY + drag.dragOffsetY,
1204+
event.clientX + drag.dragOffsetX,
1205+
event.clientY + drag.dragOffsetY,
12061206
event.ctrlKey,
12071207
event.altKey,
12081208
event.shiftKey,

0 commit comments

Comments
 (0)