Skip to content

Commit 8712188

Browse files
committed
metadata dashboard improvements
1 parent 931f5b3 commit 8712188

File tree

6 files changed

+90
-104
lines changed

6 files changed

+90
-104
lines changed

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module.exports = {
2929
{ avoidEscape: true, allowTemplateLiterals: false }
3030
],
3131
curly: ['error', 'all'],
32-
eqeqeq: 'error',
32+
eqeqeq: ['error', 'smart'],
3333
'prefer-arrow-callback': 'error'
3434
}
3535
};

src/dashboard.tsx

Lines changed: 40 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { NotebookPanel } from '@jupyterlab/notebook';
22

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

5-
import { filter, map, toArray, ArrayExt } from '@lumino/algorithm';
5+
import { map, toArray, each } from '@lumino/algorithm';
66

77
import * as React from 'react';
88

@@ -29,9 +29,15 @@ import { DashboardLayout } from './layout';
2929

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

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

34-
import { addCellId, addNotebookId, getNotebookById, getCellId, updateMetadata } from './utils';
34+
import {
35+
addCellId,
36+
addNotebookId,
37+
getNotebookById,
38+
getCellId,
39+
updateMetadata,
40+
} from './utils';
3541

3642
import {
3743
DocumentWidget,
@@ -46,17 +52,19 @@ import { CommandIDs } from './commands';
4652

4753
import { HTMLSelect } from '@jupyterlab/ui-components';
4854

55+
import { UUID } from '@lumino/coreutils';
56+
4957
// HTML element classes
5058

51-
const DASHBOARD_CLASS = 'pr-JupyterDashboard';
59+
export const DASHBOARD_CLASS = 'pr-JupyterDashboard';
5260

53-
const DROP_TARGET_CLASS = 'pr-DropTarget';
61+
export const DROP_TARGET_CLASS = 'pr-DropTarget';
5462

55-
const TOOLBAR_MODE_SWITCHER_CLASS = 'pr-ToolbarModeSwitcher';
63+
export const TOOLBAR_MODE_SWITCHER_CLASS = 'pr-ToolbarModeSwitcher';
5664

57-
const TOOLBAR_SELECT_CLASS = 'pr-ToolbarSelector';
65+
export const TOOLBAR_SELECT_CLASS = 'pr-ToolbarSelector';
5866

59-
const TOOLBAR_CLASS = 'pr-DashboardToolbar';
67+
export const TOOLBAR_CLASS = 'pr-DashboardToolbar';
6068

6169
export const IDashboardTracker = new Token<IDashboardTracker>(
6270
'jupyterlab-interactive-dashboard-editor'
@@ -73,6 +81,8 @@ export class Dashboard extends Widget {
7381
constructor(options: Dashboard.IOptions) {
7482
super(options);
7583

84+
this.id = UUID.uuid4();
85+
7686
const { outputTracker, model } = options;
7787
this._model = model;
7888
if (options.context !== undefined) {
@@ -243,7 +253,7 @@ export class Dashboard extends Widget {
243253

244254
private _evtScroll(_event: Event): void {
245255
const model = this.model;
246-
256+
247257
if (model.scrollMode !== 'infinite') {
248258
return;
249259
}
@@ -354,51 +364,39 @@ export class Dashboard extends Widget {
354364
return (this.layout as DashboardLayout).createWidget(info, fit);
355365
}
356366

357-
saveToNotebookMetadata() {
367+
saveToNotebookMetadata(): void {
358368
// 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-
);
369+
const widgets = toArray(this.model.widgetstore.getWidgets());
365370

366-
const notebookIds = toArray(
367-
map(
368-
widgets,
369-
(record) => record.notebookId
370-
)
371-
);
371+
const notebookIds = toArray(map(widgets, (record) => record.notebookId));
372372

373373
if (!notebookIds.every((v) => v === notebookIds[0])) {
374-
console.log(notebookIds);
375-
throw new Error('Only single notebook dashboards can be saved to metadata.');
374+
throw new Error(
375+
'Only single notebook dashboards can be saved to metadata.'
376+
);
376377
}
377378

378379
const notebookId = notebookIds[0];
379380
const notebookTracker = this.model.notebookTracker;
380381
const notebook = getNotebookById(notebookId, notebookTracker);
382+
381383
updateMetadata(notebook, { hasDashboard: true });
382384

383385
const cells = notebook.content.widgets;
384386

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-
// );
387+
const widgetMap = new Map<string, WidgetPosition>(
388+
widgets.map((widget) => [widget.cellId, widget.pos])
389+
);
397390

398-
if (cell !== undefined) {
399-
updateMetadata(cell, { pos });
391+
each(cells, (cell) => {
392+
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 });
400398
}
401-
}
399+
});
402400

403401
notebook.context.save();
404402
}
@@ -452,18 +450,6 @@ export namespace Dashboard {
452450
}
453451
}
454452

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-
467453
export class DashboardDocument extends DocumentWidget<Dashboard> {
468454
constructor(options: DashboardDocument.IOptions) {
469455
let { content, reveal } = options;
@@ -483,7 +469,7 @@ export class DashboardDocument extends DocumentWidget<Dashboard> {
483469
this.toolbar.addClass(TOOLBAR_CLASS);
484470

485471
const commands = commandRegistry;
486-
const { save, undo, redo, cut, copy, paste, runOutput } = CommandIDs;
472+
const { save, undo, redo, cut, copy, paste } = CommandIDs;
487473

488474
const args = { toolbar: true, dashboardId: content.id };
489475

@@ -505,15 +491,13 @@ export class DashboardDocument extends DocumentWidget<Dashboard> {
505491
paste,
506492
'Paste outputs from the clipboard'
507493
);
508-
const runButton = makeToolbarButton(runOutput, 'Run the selected outputs');
509494

510495
this.toolbar.addItem(save, saveButton);
511496
this.toolbar.addItem(undo, undoButton);
512497
this.toolbar.addItem(redo, redoButton);
513498
this.toolbar.addItem(cut, cutButton);
514499
this.toolbar.addItem(copy, copyButton);
515500
this.toolbar.addItem(paste, pasteButton);
516-
this.toolbar.addItem(runOutput, runButton);
517501
this.toolbar.addItem('spacer', Toolbar.createSpacerItem());
518502
this.toolbar.addItem(
519503
'switchMode',
@@ -589,9 +573,9 @@ export namespace DashboardDocument {
589573
value={value}
590574
aria-label={'Mode'}
591575
>
592-
<option value='present'>Present</option>
576+
<option value="present">Present</option>
593577
{/* <option value="free-edit">Free Layout</option> */}
594-
<option value='grid-edit'>Edit</option>
578+
<option value="grid-edit">Edit</option>
595579
</HTMLSelect>
596580
);
597581
}

src/index.ts

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { IDocumentManager } from '@jupyterlab/docmanager';
2727

2828
import { IMainMenu } from '@jupyterlab/mainmenu';
2929

30-
import { Widget } from '@lumino/widgets';
30+
import { Widget, Menu } from '@lumino/widgets';
3131

3232
import { DocumentRegistry } from '@jupyterlab/docregistry';
3333

@@ -49,7 +49,7 @@ import {
4949

5050
import { CommandIDs } from './commands';
5151

52-
import { ReadonlyJSONObject, UUID } from '@lumino/coreutils';
52+
import { ReadonlyJSONObject } from '@lumino/coreutils';
5353

5454
import { DashboardLayout } from './layout';
5555

@@ -69,7 +69,6 @@ const extension: JupyterFrontEndPlugin<IDashboardTracker> = {
6969
docManager: IDocumentManager,
7070
launcher: ILauncher
7171
): IDashboardTracker => {
72-
7372
// Tracker for Dashboard
7473
const dashboardTracker = new DashboardTracker({ namespace: 'dashboards' });
7574

@@ -172,22 +171,26 @@ const extension: JupyterFrontEndPlugin<IDashboardTracker> = {
172171
rank: 5,
173172
});
174173

175-
app.contextMenu.addItem({
174+
const experimentalMenu = new Menu({ commands: app.commands });
175+
experimentalMenu.title.label = 'Experimental';
176+
177+
experimentalMenu.addItem({
176178
command: CommandIDs.saveToMetadata,
177-
selector: '.pr-JupyterDashboard',
178-
rank: 6,
179179
});
180180

181-
app.contextMenu.addItem({
181+
experimentalMenu.addItem({
182182
command: CommandIDs.toggleInfiniteScroll,
183-
selector: '.pr-JupyterDashboard',
184-
rank: 7,
185183
});
186184

187-
app.contextMenu.addItem({
185+
experimentalMenu.addItem({
188186
command: CommandIDs.trimDashboard,
187+
});
188+
189+
app.contextMenu.addItem({
190+
type: 'submenu',
191+
submenu: experimentalMenu,
189192
selector: '.pr-JupyterDashboard',
190-
rank: 8,
193+
rank: 6,
191194
});
192195

193196
app.contextMenu.addItem({
@@ -217,7 +220,7 @@ const extension: JupyterFrontEndPlugin<IDashboardTracker> = {
217220
app.contextMenu.addItem({
218221
command: CommandIDs.openFromMetadata,
219222
selector: '.jp-Notebook',
220-
rank: 16
223+
rank: 16,
221224
});
222225

223226
// Add commands to key bindings
@@ -543,7 +546,7 @@ function addCommands(
543546
execute: (args) => {
544547
const dashboard = dashboardTracker.currentWidget;
545548
dashboard.saveToNotebookMetadata();
546-
}
549+
},
547550
});
548551

549552
commands.addCommand(CommandIDs.createNew, {
@@ -591,18 +594,18 @@ function addCommands(
591594
const notebookId = notebookMetadata.id;
592595
const cells = notebook.content.widgets;
593596

594-
let widgetstore = new Widgetstore({ id: 0, notebookTracker });
597+
const widgetstore = new Widgetstore({ id: 0, notebookTracker });
595598

596599
widgetstore.startBatch();
597600

598-
for (let cell of cells) {
599-
let metadata = getMetadata(cell);
600-
if (metadata !== undefined && metadata.pos !== undefined) {
601-
let widgetInfo: WidgetInfo = {
601+
for (const cell of cells) {
602+
const metadata = getMetadata(cell);
603+
if (metadata !== undefined && !metadata.hidden) {
604+
const widgetInfo: WidgetInfo = {
602605
widgetId: DashboardWidget.createDashboardWidgetId(),
603606
notebookId,
604607
cellId: metadata.id,
605-
pos: metadata.pos
608+
pos: metadata.pos,
606609
};
607610
widgetstore.addWidget(widgetInfo);
608611
}
@@ -617,10 +620,9 @@ function addCommands(
617620

618621
const dashboard = new Dashboard({
619622
outputTracker,
620-
model
623+
model,
621624
});
622625

623-
dashboard.id = UUID.uuid4();
624626
dashboard.updateLayoutFromWidgetstore();
625627
dashboard.model.mode = 'present';
626628

@@ -633,7 +635,7 @@ function addCommands(
633635
return metadata.hasDashboard;
634636
}
635637
return false;
636-
}
638+
},
637639
});
638640

639641
commands.addCommand(CommandIDs.toggleWidgetMode, {
@@ -649,28 +651,29 @@ function addCommands(
649651
} else if (widget.mode === 'free-edit') {
650652
widget.mode = 'grid-edit';
651653
}
652-
}
654+
},
653655
});
654656

655657
commands.addCommand(CommandIDs.toggleInfiniteScroll, {
656658
label: 'Infinite Scroll',
657-
isToggled: (args) => dashboardTracker.currentWidget?.model.scrollMode === 'infinite',
659+
isToggled: (args) =>
660+
dashboardTracker.currentWidget?.model.scrollMode === 'infinite',
658661
execute: (args) => {
659662
const dashboard = dashboardTracker.currentWidget;
660663
if (dashboard.model.scrollMode === 'infinite') {
661664
dashboard.model.scrollMode = 'constrained';
662665
} else {
663666
dashboard.model.scrollMode = 'infinite';
664667
}
665-
}
668+
},
666669
});
667670

668671
commands.addCommand(CommandIDs.trimDashboard, {
669672
label: 'Trim Dashboard',
670673
execute: (args) => {
671674
const dashboard = dashboardTracker.currentWidget;
672675
(dashboard.layout as DashboardLayout).trimDashboard();
673-
}
676+
},
674677
});
675678
}
676679

0 commit comments

Comments
 (0)