From 27142182d0a11af9fa9b1eae1f0ef86ab738c008 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Wed, 23 Oct 2019 17:04:18 -0700 Subject: [PATCH 01/21] added celltags extension --- dev_mode/imports.css | 1 + dev_mode/package.json | 5 + packages/celltags-extension/README.md | 3 + packages/celltags-extension/package.json | 53 +++++ packages/celltags-extension/src/index.ts | 29 +++ packages/celltags-extension/style/index.css | 1 + packages/celltags-extension/tsconfig.json | 35 ++++ packages/celltags/README.md | 3 + packages/celltags/package.json | 52 +++++ packages/celltags/src/addwidget.ts | 119 +++++++++++ packages/celltags/src/index.ts | 3 + packages/celltags/src/tool.ts | 218 ++++++++++++++++++++ packages/celltags/src/widget.ts | 109 ++++++++++ packages/celltags/static/add-24px.svg | 1 + packages/celltags/static/check-24px.svg | 1 + packages/celltags/style/base.css | 66 ++++++ packages/celltags/style/index.css | 12 ++ packages/celltags/tsconfig.json | 35 ++++ packages/metapackage/package.json | 2 + packages/metapackage/tsconfig.json | 6 + 20 files changed, 754 insertions(+) create mode 100644 packages/celltags-extension/README.md create mode 100644 packages/celltags-extension/package.json create mode 100644 packages/celltags-extension/src/index.ts create mode 100644 packages/celltags-extension/style/index.css create mode 100644 packages/celltags-extension/tsconfig.json create mode 100644 packages/celltags/README.md create mode 100644 packages/celltags/package.json create mode 100644 packages/celltags/src/addwidget.ts create mode 100644 packages/celltags/src/index.ts create mode 100644 packages/celltags/src/tool.ts create mode 100644 packages/celltags/src/widget.ts create mode 100644 packages/celltags/static/add-24px.svg create mode 100644 packages/celltags/static/check-24px.svg create mode 100644 packages/celltags/style/base.css create mode 100644 packages/celltags/style/index.css create mode 100644 packages/celltags/tsconfig.json diff --git a/dev_mode/imports.css b/dev_mode/imports.css index f73e03847429..944d9544df5e 100644 --- a/dev_mode/imports.css +++ b/dev_mode/imports.css @@ -2,6 +2,7 @@ /* It was generated by @jupyterlab/buildutils in Build.ensureAssets() */ @import url('~@jupyterlab/application-extension/style/index.css'); @import url('~@jupyterlab/apputils-extension/style/index.css'); +@import url('~@jupyterlab/celltags-extension/style/index.css'); @import url('~@jupyterlab/codemirror-extension/style/index.css'); @import url('~@jupyterlab/completer-extension/style/index.css'); @import url('~@jupyterlab/console-extension/style/index.css'); diff --git a/dev_mode/package.json b/dev_mode/package.json index 65ee7546d3b7..23551a777b87 100644 --- a/dev_mode/package.json +++ b/dev_mode/package.json @@ -19,6 +19,7 @@ "@jupyterlab/application": "~2.0.0-alpha.4", "@jupyterlab/application-extension": "~2.0.0-alpha.4", "@jupyterlab/apputils-extension": "~2.0.0-alpha.4", + "@jupyterlab/celltags-extension": "~0.1.0", "@jupyterlab/codemirror-extension": "~2.0.0-alpha.4", "@jupyterlab/completer-extension": "~2.0.0-alpha.4", "@jupyterlab/console-extension": "~2.0.0-alpha.4", @@ -93,6 +94,7 @@ "@jupyterlab/apputils-extension": "~2.0.0-alpha.4", "@jupyterlab/attachments": "~2.0.0-alpha.4", "@jupyterlab/cells": "~2.0.0-alpha.4", + "@jupyterlab/celltags": "~0.1.0", "@jupyterlab/codeeditor": "~2.0.0-alpha.4", "@jupyterlab/codemirror": "~2.0.0-alpha.4", "@jupyterlab/codemirror-extension": "~2.0.0-alpha.4", @@ -189,6 +191,7 @@ "extensions": { "@jupyterlab/application-extension": "", "@jupyterlab/apputils-extension": "", + "@jupyterlab/celltags-extension": "", "@jupyterlab/codemirror-extension": "", "@jupyterlab/completer-extension": "", "@jupyterlab/console-extension": "", @@ -277,6 +280,8 @@ "@jupyterlab/apputils-extension": "../packages/apputils-extension", "@jupyterlab/attachments": "../packages/attachments", "@jupyterlab/cells": "../packages/cells", + "@jupyterlab/celltags": "../packages/celltags", + "@jupyterlab/celltags-extension": "../packages/celltags-extension", "@jupyterlab/codeeditor": "../packages/codeeditor", "@jupyterlab/codemirror": "../packages/codemirror", "@jupyterlab/codemirror-extension": "../packages/codemirror-extension", diff --git a/packages/celltags-extension/README.md b/packages/celltags-extension/README.md new file mode 100644 index 000000000000..2d45e2131d85 --- /dev/null +++ b/packages/celltags-extension/README.md @@ -0,0 +1,3 @@ +# celltags + +A refactor of jupyterlab-celltags intended to be merged into core. diff --git a/packages/celltags-extension/package.json b/packages/celltags-extension/package.json new file mode 100644 index 000000000000..a8884c1e5cd7 --- /dev/null +++ b/packages/celltags-extension/package.json @@ -0,0 +1,53 @@ +{ + "name": "@jupyterlab/celltags-extension", + "version": "0.1.0", + "description": "An extension for manipulating tags in cell metadata", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/my_name/myextension", + "bugs": { + "url": "https://github.com/my_name/myextension/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/my_name/myextension.git" + }, + "license": "BSD-3-Clause", + "author": "Markelle Kelly", + "files": [ + "lib/*.{d.ts,js}", + "style/*.css" + ], + "sideEffects": [ + "style/*.css" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "directories": { + "lib": "lib/" + }, + "scripts": { + "build": "tsc", + "clean": "rimraf lib && rimraf tsconfig.tsbuildinfo", + "prepare": "npm run clean && npm run build", + "prepublishOnly": "npm run build", + "watch": "tsc -b --watch" + }, + "dependencies": { + "@jupyterlab/application": "^2.0.0-alpha.1", + "@jupyterlab/celltags": "^0.1.0", + "@jupyterlab/notebook": "^2.0.0-alpha.1", + "@types/node": "^12.0.2" + }, + "devDependencies": { + "rimraf": "~2.6.2", + "typescript": "~3.5.1" + }, + "jupyterlab": { + "extension": true + } +} diff --git a/packages/celltags-extension/src/index.ts b/packages/celltags-extension/src/index.ts new file mode 100644 index 000000000000..f581d36b02c5 --- /dev/null +++ b/packages/celltags-extension/src/index.ts @@ -0,0 +1,29 @@ +import { + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; + +import { INotebookTools, INotebookTracker } from '@jupyterlab/notebook'; + +import { TagTool } from '@jupyterlab/celltags'; + +function activate( + app: JupyterFrontEnd, + tools: INotebookTools, + tracker: INotebookTracker +) { + const tool = new TagTool(tracker, app); + tools.addItem({ tool: tool, rank: 1.7 }); +} + +/** + * Initialization data for the celltags extension. + */ +const celltags: JupyterFrontEndPlugin = { + id: 'celltags', + autoStart: true, + requires: [INotebookTools, INotebookTracker], + activate: activate +}; + +export default celltags; diff --git a/packages/celltags-extension/style/index.css b/packages/celltags-extension/style/index.css new file mode 100644 index 000000000000..23f21ce84b0b --- /dev/null +++ b/packages/celltags-extension/style/index.css @@ -0,0 +1 @@ +@import url('~@jupyterlab/celltags/style/index.css'); diff --git a/packages/celltags-extension/tsconfig.json b/packages/celltags-extension/tsconfig.json new file mode 100644 index 000000000000..a68cc31546ae --- /dev/null +++ b/packages/celltags-extension/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "composite": true, + "declaration": true, + "esModuleInterop": true, + "incremental": true, + "jsx": "react", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "preserveWatchOutput": true, + "resolveJsonModule": true, + "outDir": "lib", + "rootDir": "src", + "strict": true, + "strictNullChecks": false, + "target": "es2017", + "types": ["node"] + }, + "include": ["src/*"], + "references": [ + { + "path": "../application" + }, + { + "path": "../celltags" + }, + { + "path": "../notebook" + } + ] +} diff --git a/packages/celltags/README.md b/packages/celltags/README.md new file mode 100644 index 000000000000..2d45e2131d85 --- /dev/null +++ b/packages/celltags/README.md @@ -0,0 +1,3 @@ +# celltags + +A refactor of jupyterlab-celltags intended to be merged into core. diff --git a/packages/celltags/package.json b/packages/celltags/package.json new file mode 100644 index 000000000000..0151391aff7f --- /dev/null +++ b/packages/celltags/package.json @@ -0,0 +1,52 @@ +{ + "name": "@jupyterlab/celltags", + "version": "0.1.0", + "description": "An extension for manipulating tags in cell metadata", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/my_name/myextension", + "bugs": { + "url": "https://github.com/my_name/myextension/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/my_name/myextension.git" + }, + "license": "BSD-3-Clause", + "author": "Markelle Kelly", + "files": [ + "lib/*.{d.ts,js}", + "style/*.css", + "static/*.svg" + ], + "sideEffects": [ + "style/*.css" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "directories": { + "lib": "lib/" + }, + "scripts": { + "build": "tsc -b", + "clean": "rimraf lib", + "prepare": "npm run clean && npm run build", + "prepublishOnly": "npm run build", + "watch": "tsc -b --watch" + }, + "dependencies": { + "@jupyterlab/application": "^2.0.0-alpha.1", + "@jupyterlab/cells": "^2.0.0-alpha.1", + "@jupyterlab/notebook": "^2.0.0-alpha.1", + "@phosphor/widgets": "^1.9.0", + "@types/node": "^12.0.2" + }, + "devDependencies": { + "rimraf": "~2.6.2", + "typescript": "~3.5.1" + } +} diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts new file mode 100644 index 000000000000..003bae4b0bf6 --- /dev/null +++ b/packages/celltags/src/addwidget.ts @@ -0,0 +1,119 @@ +import { Widget } from '@phosphor/widgets'; + +import { TagTool } from './tool'; + +/** + * A widget which hosts a cell tags area. + */ +export class AddWidget extends Widget { + /** + * Construct a new tag widget. + */ + constructor() { + super(); + this.addClass('tag'); + this.editing = false; + this.buildTag(); + } + + buildTag() { + let text = document.createElement('input'); + text.value = 'Add Tag'; + text.contentEditable = 'true'; + text.className = 'add-tag'; + text.style.width = '49px'; + let tag = document.createElement('div'); + tag.className = 'tag-holder'; + tag.appendChild(text); + let img = document.createElement('span'); + img.className = 'add-icon'; + this.addClass('unapplied-tag'); + tag.appendChild(img); + this.node.appendChild(tag); + } + + onAfterAttach() { + this.node.addEventListener('mousedown', this); + this.node.addEventListener('mouseover', this); + this.node.addEventListener('mouseout', this); + this.node.addEventListener('keypress', this); + this.node.addEventListener('focusout', this); + } + + onBeforeDetach() { + this.node.removeEventListener('mousedown', this); + this.node.removeEventListener('mouseover', this); + this.node.removeEventListener('mouseout', this); + this.node.removeEventListener('keypress', this); + this.node.removeEventListener('focusout', this); + } + + handleEvent(event: Event): void { + switch (event.type) { + case 'mousedown': + this._evtClick(event as MouseEvent); + break; + case 'mouseover': + this._evtHover(event as MouseEvent); + break; + case 'mouseout': + this._evtOffHover(event as MouseEvent); + break; + case 'keypress': + this._evtKeyPress(event as KeyboardEvent); + break; + case 'focusout': + this._evtBlur(); + break; + default: + break; + } + } + + private _evtClick(event: MouseEvent) { + if (!this.editing) { + this.editing = true; + let target = event.target as HTMLInputElement; + target.value = ''; + target.autofocus = true; + } + } + + private _evtHover(event: MouseEvent) { + //(this.node as HTMLElement).classList.add("tag-hover"); + } + + private _evtOffHover(event: MouseEvent) { + //(this.node as HTMLElement).classList.remove("tag-hover"); + } + + private _evtKeyPress(event: KeyboardEvent) { + let inputElement = event.target as HTMLInputElement; + let tmp = document.createElement('span'); + tmp.className = 'tag'; + tmp.innerHTML = inputElement.value; + // set width to the pixel length of the text + document.body.appendChild(tmp); + inputElement.style.width = tmp.getBoundingClientRect().width + 8 + 'px'; + document.body.removeChild(tmp); + // if they hit Enter, add the tag and reset state + if (event.keyCode == 13) { + let value = inputElement.value; + (this.parent as TagTool).addTag(value); + inputElement.blur(); + this._evtBlur(); + } + } + + private _evtBlur() { + if (this.editing) { + this.editing = false; + let target = event.target as HTMLInputElement; + target.value = 'Add Tag'; + target.style.width = '49px'; + } + } + + public parent: TagTool; + private editing: boolean; +} diff --git a/packages/celltags/src/index.ts b/packages/celltags/src/index.ts new file mode 100644 index 000000000000..24f17dcd2283 --- /dev/null +++ b/packages/celltags/src/index.ts @@ -0,0 +1,3 @@ +export * from './addwidget'; +export * from './tool'; +export * from './widget'; diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts new file mode 100644 index 000000000000..df070dc1d720 --- /dev/null +++ b/packages/celltags/src/tool.ts @@ -0,0 +1,218 @@ +import { PanelLayout } from '@phosphor/widgets'; + +import { NotebookTools, INotebookTracker } from '@jupyterlab/notebook'; + +import { Cell } from '@jupyterlab/cells'; + +import { JupyterFrontEnd } from '@jupyterlab/application'; + +import { TagWidget } from './widget'; + +import { AddWidget } from './addwidget'; + +/** + * A Tool for tag operations. + */ +export class TagTool extends NotebookTools.Tool { + /** + * Construct a new tag Tool. + * + * @param tracker - The notebook tracker. + */ + constructor(tracker: INotebookTracker, app: JupyterFrontEnd) { + super(); + app; + this.tracker = tracker; + this.layout = new PanelLayout(); + this.createTagInput(); + } + + createTagInput() { + let layout = this.layout as PanelLayout; + let input = new AddWidget(); + input.id = 'add-tag'; + layout.insertWidget(0, input); + } + + checkApplied(name: string): boolean { + if (this.tracker.activeCell) { + let tags = this.tracker.activeCell.model.metadata.get('tags') as string[]; + if (tags) { + for (let i = 0; i < tags.length; i++) { + if (tags[i] === name) { + return true; + } + } + } + } + return false; + } + + addTag(name: string) { + let cell = this.tracker.activeCell; + let tags = cell.model.metadata.get('tags') as string[]; + let newTags = name.split(/[,\s]+/); + if (tags === undefined) { + tags = []; + } + const toAdd: string[] = []; + for (let i = 0; i < newTags.length; i++) { + if (newTags[i] !== '' && toAdd.indexOf(newTags[i]) < 0) { + toAdd.push(newTags[i]); + } + } + for (let j = 0; j < toAdd.length; j++) { + if (tags.indexOf(toAdd[j]) < 0) { + tags.push(toAdd[j]); + } + } + cell.model.metadata.set('tags', tags); + console.log(this.tracker.activeCell.model.metadata.get('tags')); + this.refreshTags(); + this.loadActiveTags(); + } + + removeTag(name: string) { + let cell = this.tracker.activeCell; + let tags = cell.model.metadata.get('tags') as string[]; + let idx = tags.indexOf(name); + if (idx > -1) { + tags.splice(idx, 1); + } + cell.model.metadata.set('tags', tags); + if (tags.length === 0) { + cell.model.metadata.delete('tags'); + } + this.refreshTags(); + this.loadActiveTags(); + console.log(this.tracker.activeCell.model.metadata.get('tags')); + } + + loadActiveTags() { + let layout = this.layout as PanelLayout; + for (let i = 0; i < layout.widgets.length; i++) { + layout.widgets[i].update(); + } + } + + /** + * Pull from cell metadata all the tags assigned to notebook cells, + */ + pullTags() { + let notebook = this.tracker.currentWidget; + if (this.tracker && this.tracker.currentWidget) { + let cells = notebook.model.cells; + let allTags: string[] = []; + for (var i = 0; i < cells.length; i++) { + let metadata = cells.get(i).metadata; + let tags = metadata.get('tags') as string[]; + if (tags) { + for (var j = 0; j < tags.length; j++) { + let name = tags[j] as string; + if (name !== '') { + if (allTags.indexOf(name) < 0) { + allTags.push(name); + } + } + } + } + } + this.tagList = allTags; + } + } + + refreshTags() { + this.pullTags(); + let layout = this.layout as PanelLayout; + let tags: string[] = this.tagList; + let nWidgets = layout.widgets.length; + for (let i = 0; i < nWidgets - 1; i++) { + let idx = tags.indexOf((layout.widgets[i] as TagWidget).name); + if (idx < 0 && layout.widgets[i].id != 'add-tag') { + layout.widgets[i].dispose(); + } else { + tags.splice(idx, 1); + } + } + for (let i = 0; i < tags.length; i++) { + let widget = new TagWidget(tags[i]); + let idx = layout.widgets.length - 1; + layout.insertWidget(idx, widget); + } + } + + validateTags(cell: Cell) { + let tags = cell.model.metadata.get('tags'); + var results: string[] = []; + var taglist: string[] = []; + if (tags === undefined) { + return; + } + if (typeof tags === 'string') { + taglist.push(tags); + } else { + taglist = tags; + } + for (let i = 0; i < taglist.length; i++) { + if (taglist[i] != '' && typeof taglist[i] === 'string') { + let spl = taglist[i].split(' '); + for (let j = 0; j < spl.length; j++) { + if (spl[j] != '' && results.indexOf(spl[j]) < 0) { + results.push(spl[j]); + } + } + } + } + cell.model.metadata.set('tags', results); + } + + /** + * Handle a change to the active cell. + */ + protected onActiveCellChanged(): void { + this.loadActiveTags(); + } + + /** + * Handle a change to cell selection in the notebook. + */ + protected onSelectionChanged(): void {} + + /** + * Get all tags once available. + */ + protected onAfterShow() { + this.refreshTags(); + this.loadActiveTags(); + } + + /** + * Get all tags once available. + */ + protected onAfterAttach() { + this.tracker.currentWidget.context.ready.then(() => { + this.refreshTags(); + this.loadActiveTags(); + }); + this.tracker.currentChanged.connect(() => { + this.refreshTags(); + this.loadActiveTags(); + }); + this.tracker.currentWidget.model.cells.changed.connect(() => { + this.refreshTags(); + this.loadActiveTags(); + }); + } + + /** + * Handle a change to active cell metadata. + */ + protected onActiveCellMetadataChanged(): void { + this.validateTags(this.tracker.activeCell); + this.refreshTags(); + this.loadActiveTags(); + } + + private tagList: string[] = []; + public tracker: INotebookTracker = null; +} diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts new file mode 100644 index 000000000000..58274e2b4297 --- /dev/null +++ b/packages/celltags/src/widget.ts @@ -0,0 +1,109 @@ +import { Widget } from '@phosphor/widgets'; + +import { TagTool } from './tool'; + +/** + * A widget which hosts a cell tags area. + */ +export class TagWidget extends Widget { + /** + * Construct a new tag widget. + */ + constructor(name: string) { + super(); + this.applied = true; + this.name = name; + this.addClass('tag'); + this.buildTag(); + } + + buildTag() { + let text = document.createElement('span'); + text.textContent = this.name; + text.style.textOverflow = 'ellipsis'; + let tag = document.createElement('div'); + tag.className = 'tag-holder'; + tag.appendChild(text); + let img = document.createElement('span'); + img.className = 'check-icon'; + if (this.applied) { + this.addClass('applied-tag'); + } else { + this.addClass('unapplied-tag'); + img.style.display = 'none'; + } + tag.appendChild(img); + this.node.appendChild(tag); + } + + onAfterAttach() { + this.node.addEventListener('mousedown', this); + this.node.addEventListener('mouseover', this); + this.node.addEventListener('mouseout', this); + } + + onBeforeDetach() { + this.node.removeEventListener('mousedown', this); + this.node.removeEventListener('mouseover', this); + this.node.removeEventListener('mouseout', this); + } + + handleEvent(event: Event): void { + switch (event.type) { + case 'mousedown': + this._evtClick(); + break; + case 'mouseover': + this._evtHover(event as MouseEvent); + break; + case 'mouseout': + this._evtOffHover(event as MouseEvent); + break; + default: + break; + } + } + + onUpdateRequest() { + let applied = this.parent.checkApplied(this.name); + if (applied != this.applied) { + this.toggleApplied(); + } + } + + toggleApplied() { + if (this.applied) { + this.removeClass('applied-tag'); + (this.node.firstChild.lastChild as HTMLSpanElement).style.display = + 'none'; + this.addClass('unapplied-tag'); + } else { + this.removeClass('unapplied-tag'); + (this.node.firstChild.lastChild as HTMLSpanElement).style.display = + 'inline-block'; + this.addClass('applied-tag'); + } + this.applied = !this.applied; + } + + private _evtClick() { + if (this.applied) { + this.parent.removeTag(this.name); + } else { + this.parent.addTag(this.name); + } + this.toggleApplied(); + } + + private _evtHover(event: MouseEvent) { + (this.node as HTMLElement).classList.add('tag-hover'); + } + + private _evtOffHover(event: MouseEvent) { + (this.node as HTMLElement).classList.remove('tag-hover'); + } + + public name: string; + private applied: boolean; + public parent: TagTool; +} diff --git a/packages/celltags/static/add-24px.svg b/packages/celltags/static/add-24px.svg new file mode 100644 index 000000000000..934909653041 --- /dev/null +++ b/packages/celltags/static/add-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/celltags/static/check-24px.svg b/packages/celltags/static/check-24px.svg new file mode 100644 index 000000000000..2453d055cdff --- /dev/null +++ b/packages/celltags/static/check-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/celltags/style/base.css b/packages/celltags/style/base.css new file mode 100644 index 000000000000..bb004435053a --- /dev/null +++ b/packages/celltags/style/base.css @@ -0,0 +1,66 @@ +.tag { + height: 32px; + width: fit-content; + border-radius: 35px; + margin-left: 5px; + margin-right: 5px; + margin-bottom: 10px; + padding: 12px; + font-size: var(--jp-ui-font-size-1); + display: inline-flex; + justify-content: center; + align-items: center; + max-width: calc(100% - 25px); +} + +.unapplied-tag { + background-color: var(--jp-layout-color1); + border: 1px solid var(--jp-ui-font-color2); + color: var(--jp-ui-font-color2); +} + +.applied-tag { + background-color: var(--jp-layout-color2); + border: 1px solid var(--jp-ui-font-color1); + color: var(--jp-ui-font-color1); +} + +.add-tag { + white-space: nowrap; + overflow: hidden; + border: none; + outline: none; + resize: horizontal; + font-size: var(--jp-ui-font-size-1); + color: var(--jp-ui-font-color2); + background-color: var(--jp-layout-color1); +} + +.tag-holder { + display: flex; + justify-content: center; + align-items: center; +} + +.check-icon { + display: inline-block; + height: 18px; + min-width: 18px; + background-image: url('../static/check-24px.svg'); + background-size: 18px; + margin-left: 8px; +} + +.add-icon { + display: inline-block; + height: 18px; + min-width: 15px; + background-image: url('../static/add-24px.svg'); + background-size: 18px; + margin-left: 8px; + fill: var(--jp-ui-font-color2); +} + +.tag-hover { + background-color: var(--jp-layout-color2); +} diff --git a/packages/celltags/style/index.css b/packages/celltags/style/index.css new file mode 100644 index 000000000000..f9d952a05d8c --- /dev/null +++ b/packages/celltags/style/index.css @@ -0,0 +1,12 @@ +/*----------------------------------------------------------------------------- +| Copyright (c) Jupyter Development Team. +| Distributed under the terms of the Modified BSD License. +|----------------------------------------------------------------------------*/ + +/* This file was auto-generated by ensurePackage() in @jupyterlab/buildutils */ +@import url('~@phosphor/widgets/style/index.css'); +@import url('~@jupyterlab/application/style/index.css'); +@import url('~@jupyterlab/cells/style/index.css'); +@import url('~@jupyterlab/notebook/style/index.css'); + +@import url('./base.css'); diff --git a/packages/celltags/tsconfig.json b/packages/celltags/tsconfig.json new file mode 100644 index 000000000000..9ad9346e2d3b --- /dev/null +++ b/packages/celltags/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "composite": true, + "declaration": true, + "esModuleInterop": true, + "incremental": true, + "jsx": "react", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "preserveWatchOutput": true, + "resolveJsonModule": true, + "outDir": "lib", + "rootDir": "src", + "strict": true, + "strictNullChecks": false, + "target": "es2017", + "types": ["node"] + }, + "include": ["src/*"], + "references": [ + { + "path": "../application" + }, + { + "path": "../cells" + }, + { + "path": "../notebook" + } + ] +} diff --git a/packages/metapackage/package.json b/packages/metapackage/package.json index 9a372b06f309..73a69b112944 100644 --- a/packages/metapackage/package.json +++ b/packages/metapackage/package.json @@ -37,6 +37,8 @@ "@jupyterlab/apputils-extension": "^2.0.0-alpha.4", "@jupyterlab/attachments": "^2.0.0-alpha.4", "@jupyterlab/cells": "^2.0.0-alpha.4", + "@jupyterlab/celltags": "^0.1.0", + "@jupyterlab/celltags-extension": "^0.1.0", "@jupyterlab/codeeditor": "^2.0.0-alpha.4", "@jupyterlab/codemirror": "^2.0.0-alpha.4", "@jupyterlab/codemirror-extension": "^2.0.0-alpha.4", diff --git a/packages/metapackage/tsconfig.json b/packages/metapackage/tsconfig.json index 2ada971156cb..66cebeabc8be 100644 --- a/packages/metapackage/tsconfig.json +++ b/packages/metapackage/tsconfig.json @@ -24,6 +24,12 @@ { "path": "../cells" }, + { + "path": "../celltags" + }, + { + "path": "../celltags-extension" + }, { "path": "../codeeditor" }, From aced9fe6dd245438b752cb8ed0e550f9dcc69b75 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Fri, 25 Oct 2019 12:49:29 -0700 Subject: [PATCH 02/21] added header, css fixes --- packages/celltags/src/tool.ts | 4 ++++ packages/celltags/static/add-24px-dark.svg | 7 +++++++ packages/celltags/static/add-24px.svg | 4 +++- packages/celltags/static/check-24px-dark.svg | 3 +++ packages/celltags/style/base.css | 19 ++++++++++++++++--- 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100755 packages/celltags/static/add-24px-dark.svg mode change 100644 => 100755 packages/celltags/static/add-24px.svg create mode 100755 packages/celltags/static/check-24px-dark.svg diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index df070dc1d720..de89fe497694 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -190,6 +190,10 @@ export class TagTool extends NotebookTools.Tool { * Get all tags once available. */ protected onAfterAttach() { + const header = document.createElement('header'); + header.textContent = 'Tags in Notebook'; + header.className = 'tag-header'; + this.parent.node.insertBefore(header, this.node); this.tracker.currentWidget.context.ready.then(() => { this.refreshTags(); this.loadActiveTags(); diff --git a/packages/celltags/static/add-24px-dark.svg b/packages/celltags/static/add-24px-dark.svg new file mode 100755 index 000000000000..ac6d4baa772c --- /dev/null +++ b/packages/celltags/static/add-24px-dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/celltags/static/add-24px.svg b/packages/celltags/static/add-24px.svg old mode 100644 new mode 100755 index 934909653041..881f35256ff4 --- a/packages/celltags/static/add-24px.svg +++ b/packages/celltags/static/add-24px.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/packages/celltags/static/check-24px-dark.svg b/packages/celltags/static/check-24px-dark.svg new file mode 100755 index 000000000000..f3a52eaa8a45 --- /dev/null +++ b/packages/celltags/static/check-24px-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/celltags/style/base.css b/packages/celltags/style/base.css index bb004435053a..0d5464aa0552 100644 --- a/packages/celltags/style/base.css +++ b/packages/celltags/style/base.css @@ -48,19 +48,32 @@ min-width: 18px; background-image: url('../static/check-24px.svg'); background-size: 18px; - margin-left: 8px; + margin-left: 5px; + margin-right: -3px; } .add-icon { display: inline-block; height: 18px; - min-width: 15px; + min-width: 18px; background-image: url('../static/add-24px.svg'); background-size: 18px; - margin-left: 8px; + margin-left: 3px; + margin-right: -5px; fill: var(--jp-ui-font-color2); } .tag-hover { background-color: var(--jp-layout-color2); } + +.tag-header { + border-bottom: var(--jp-border-width) solid var(--jp-border-color2); + flex: 0 0 auto; + font-size: var(--jp-ui-font-size0); + font-weight: 600; + letter-spacing: 1px; + margin: 0px; + padding: 8px 12px; + text-transform: uppercase; +} From 7dc1e6641766b33c33d644ec362cf00f9a19c090 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Fri, 1 Nov 2019 11:26:16 -0700 Subject: [PATCH 03/21] fixed icons & css for dark mode --- packages/celltags-extension/package.json | 1 + packages/celltags-extension/src/index.ts | 11 +++++--- packages/celltags-extension/tsconfig.json | 3 +++ packages/celltags/package.json | 7 +++++- packages/celltags/src/addwidget.ts | 19 +++++++++++--- packages/celltags/src/tool.ts | 29 +++++++++++++++++++--- packages/celltags/src/widget.ts | 19 +++++++++++--- packages/celltags/static/add-24px-dark.svg | 6 +---- packages/celltags/style/base.css | 24 ++++++++++++------ packages/celltags/style/index.css | 2 ++ packages/celltags/tsconfig.json | 6 +++++ 11 files changed, 100 insertions(+), 27 deletions(-) diff --git a/packages/celltags-extension/package.json b/packages/celltags-extension/package.json index a8884c1e5cd7..c5b83761649d 100644 --- a/packages/celltags-extension/package.json +++ b/packages/celltags-extension/package.json @@ -39,6 +39,7 @@ }, "dependencies": { "@jupyterlab/application": "^2.0.0-alpha.1", + "@jupyterlab/apputils": "^2.0.0-alpha.1", "@jupyterlab/celltags": "^0.1.0", "@jupyterlab/notebook": "^2.0.0-alpha.1", "@types/node": "^12.0.2" diff --git a/packages/celltags-extension/src/index.ts b/packages/celltags-extension/src/index.ts index f581d36b02c5..27e8c4376ed1 100644 --- a/packages/celltags-extension/src/index.ts +++ b/packages/celltags-extension/src/index.ts @@ -6,14 +6,19 @@ import { import { INotebookTools, INotebookTracker } from '@jupyterlab/notebook'; import { TagTool } from '@jupyterlab/celltags'; +import { IThemeManager } from '@jupyterlab/apputils'; function activate( app: JupyterFrontEnd, tools: INotebookTools, - tracker: INotebookTracker + tracker: INotebookTracker, + manager: IThemeManager ) { - const tool = new TagTool(tracker, app); + const tool = new TagTool(tracker, app, manager); tools.addItem({ tool: tool, rank: 1.7 }); + manager.themeChanged.connect(() => { + tool.updateTheme(); + }); } /** @@ -22,7 +27,7 @@ function activate( const celltags: JupyterFrontEndPlugin = { id: 'celltags', autoStart: true, - requires: [INotebookTools, INotebookTracker], + requires: [INotebookTools, INotebookTracker, IThemeManager], activate: activate }; diff --git a/packages/celltags-extension/tsconfig.json b/packages/celltags-extension/tsconfig.json index a68cc31546ae..69f2c84a2795 100644 --- a/packages/celltags-extension/tsconfig.json +++ b/packages/celltags-extension/tsconfig.json @@ -25,6 +25,9 @@ { "path": "../application" }, + { + "path": "../apputils" + }, { "path": "../celltags" }, diff --git a/packages/celltags/package.json b/packages/celltags/package.json index 0151391aff7f..b41265b43215 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -40,12 +40,17 @@ }, "dependencies": { "@jupyterlab/application": "^2.0.0-alpha.1", + "@jupyterlab/apputils": "^2.0.0-alpha.1", "@jupyterlab/cells": "^2.0.0-alpha.1", "@jupyterlab/notebook": "^2.0.0-alpha.1", + "@jupyterlab/ui-components": "^2.0.0-alpha.1", "@phosphor/widgets": "^1.9.0", - "@types/node": "^12.0.2" + "@types/node": "^12.0.2", + "react": "~16.8.4", + "react-dom": "~16.8.4" }, "devDependencies": { + "@types/react-dom": "^16.8.4", "rimraf": "~2.6.2", "typescript": "~3.5.1" } diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 003bae4b0bf6..e4387b1e0c26 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -9,14 +9,14 @@ export class AddWidget extends Widget { /** * Construct a new tag widget. */ - constructor() { + constructor(darkTheme: boolean) { super(); this.addClass('tag'); this.editing = false; - this.buildTag(); + this.buildTag(darkTheme); } - buildTag() { + buildTag(theme: boolean) { let text = document.createElement('input'); text.value = 'Add Tag'; text.contentEditable = 'true'; @@ -26,9 +26,11 @@ export class AddWidget extends Widget { tag.className = 'tag-holder'; tag.appendChild(text); let img = document.createElement('span'); - img.className = 'add-icon'; + img.className = theme ? 'add-icon-dark' : 'add-icon'; + img.classList.add('icon'); this.addClass('unapplied-tag'); tag.appendChild(img); + this.img = img; this.node.appendChild(tag); } @@ -114,6 +116,15 @@ export class AddWidget extends Widget { } } + updateTheme() { + let darkTheme = this.parent.getTheme(); + this.img.classList.remove('add-icon-dark'); + this.img.classList.remove('add-icon'); + let add = darkTheme ? 'add-icon-dark' : 'add-icon'; + this.img.classList.add(add); + } + public parent: TagTool; + private img: HTMLSpanElement; private editing: boolean; } diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index de89fe497694..9fb2b9aa62bd 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -9,6 +9,7 @@ import { JupyterFrontEnd } from '@jupyterlab/application'; import { TagWidget } from './widget'; import { AddWidget } from './addwidget'; +import { IThemeManager } from '@jupyterlab/apputils'; /** * A Tool for tag operations. @@ -19,17 +20,22 @@ export class TagTool extends NotebookTools.Tool { * * @param tracker - The notebook tracker. */ - constructor(tracker: INotebookTracker, app: JupyterFrontEnd) { + constructor( + tracker: INotebookTracker, + app: JupyterFrontEnd, + manager: IThemeManager + ) { super(); app; this.tracker = tracker; + this.manager = manager; this.layout = new PanelLayout(); this.createTagInput(); } createTagInput() { let layout = this.layout as PanelLayout; - let input = new AddWidget(); + let input = new AddWidget(this.getTheme()); input.id = 'add-tag'; layout.insertWidget(0, input); } @@ -135,7 +141,7 @@ export class TagTool extends NotebookTools.Tool { } } for (let i = 0; i < tags.length; i++) { - let widget = new TagWidget(tags[i]); + let widget = new TagWidget(tags[i], this.getTheme()); let idx = layout.widgets.length - 1; layout.insertWidget(idx, widget); } @@ -217,6 +223,23 @@ export class TagTool extends NotebookTools.Tool { this.loadActiveTags(); } + getTheme() { + if (this.manager.theme == 'JupyterLab Dark') { + return true; + } + return false; + } + + updateTheme() { + let layout = this.layout as PanelLayout; + let nWidgets = layout.widgets.length; + for (let i = 0; i < nWidgets - 1; i++) { + (layout.widgets[i] as TagWidget).updateTheme(); + } + (layout.widgets[nWidgets - 1] as AddWidget).updateTheme(); + } + private tagList: string[] = []; + private manager: IThemeManager; public tracker: INotebookTracker = null; } diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts index 58274e2b4297..dde99cbfcec9 100644 --- a/packages/celltags/src/widget.ts +++ b/packages/celltags/src/widget.ts @@ -9,15 +9,15 @@ export class TagWidget extends Widget { /** * Construct a new tag widget. */ - constructor(name: string) { + constructor(name: string, darkTheme: boolean) { super(); this.applied = true; this.name = name; this.addClass('tag'); - this.buildTag(); + this.buildTag(darkTheme); } - buildTag() { + buildTag(theme: boolean) { let text = document.createElement('span'); text.textContent = this.name; text.style.textOverflow = 'ellipsis'; @@ -25,7 +25,8 @@ export class TagWidget extends Widget { tag.className = 'tag-holder'; tag.appendChild(text); let img = document.createElement('span'); - img.className = 'check-icon'; + img.className = theme ? 'check-icon-dark' : 'check-icon'; + img.classList.add('icon'); if (this.applied) { this.addClass('applied-tag'); } else { @@ -33,6 +34,7 @@ export class TagWidget extends Widget { img.style.display = 'none'; } tag.appendChild(img); + this.img = img; this.node.appendChild(tag); } @@ -103,7 +105,16 @@ export class TagWidget extends Widget { (this.node as HTMLElement).classList.remove('tag-hover'); } + updateTheme() { + let darkTheme = this.parent.getTheme(); + this.img.classList.remove('check-icon-dark'); + this.img.classList.remove('check-icon-dark'); + let add = darkTheme ? 'check-icon-dark' : 'check-icon'; + this.img.classList.add(add); + } + public name: string; private applied: boolean; + private img: HTMLSpanElement; public parent: TagTool; } diff --git a/packages/celltags/static/add-24px-dark.svg b/packages/celltags/static/add-24px-dark.svg index ac6d4baa772c..0382d06ca057 100755 --- a/packages/celltags/static/add-24px-dark.svg +++ b/packages/celltags/static/add-24px-dark.svg @@ -1,7 +1,3 @@ - - - - - + diff --git a/packages/celltags/style/base.css b/packages/celltags/style/base.css index 0d5464aa0552..208bfef2fffe 100644 --- a/packages/celltags/style/base.css +++ b/packages/celltags/style/base.css @@ -42,25 +42,35 @@ align-items: center; } -.check-icon { +.icon { display: inline-block; height: 18px; min-width: 18px; - background-image: url('../static/check-24px.svg'); background-size: 18px; +} + +.check-icon { + background-image: url('../static/check-24px.svg'); margin-left: 5px; margin-right: -3px; } .add-icon { - display: inline-block; - height: 18px; - min-width: 18px; background-image: url('../static/add-24px.svg'); - background-size: 18px; margin-left: 3px; margin-right: -5px; - fill: var(--jp-ui-font-color2); +} + +.check-icon-dark { + background-image: url('../static/check-24px-dark.svg'); + margin-left: 5px; + margin-right: -3px; +} + +.add-icon-dark { + background-image: url('../static/add-24px-dark.svg'); + margin-left: 3px; + margin-right: -5px; } .tag-hover { diff --git a/packages/celltags/style/index.css b/packages/celltags/style/index.css index f9d952a05d8c..5ae710253293 100644 --- a/packages/celltags/style/index.css +++ b/packages/celltags/style/index.css @@ -5,6 +5,8 @@ /* This file was auto-generated by ensurePackage() in @jupyterlab/buildutils */ @import url('~@phosphor/widgets/style/index.css'); +@import url('~@jupyterlab/ui-components/style/index.css'); +@import url('~@jupyterlab/apputils/style/index.css'); @import url('~@jupyterlab/application/style/index.css'); @import url('~@jupyterlab/cells/style/index.css'); @import url('~@jupyterlab/notebook/style/index.css'); diff --git a/packages/celltags/tsconfig.json b/packages/celltags/tsconfig.json index 9ad9346e2d3b..bdfc7b342e1d 100644 --- a/packages/celltags/tsconfig.json +++ b/packages/celltags/tsconfig.json @@ -25,11 +25,17 @@ { "path": "../application" }, + { + "path": "../apputils" + }, { "path": "../cells" }, { "path": "../notebook" + }, + { + "path": "../ui-components" } ] } From eb6bc41c5c96ab1ac84e0fdcdbf4aab17836fc84 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Mon, 4 Nov 2019 15:23:41 -0800 Subject: [PATCH 04/21] fixed to use defaultIconRegistry --- packages/celltags-extension/src/index.ts | 11 ++--- packages/celltags/package.json | 5 +- packages/celltags/src/addwidget.ts | 47 ++++++------------- packages/celltags/src/tool.ts | 43 +++++------------ packages/celltags/src/widget.ts | 29 ++++++------ packages/celltags/static/add-24px-dark.svg | 3 -- packages/celltags/static/add-24px.svg | 3 -- packages/celltags/static/check-24px-dark.svg | 3 -- packages/celltags/static/check-24px.svg | 1 - packages/celltags/style/base.css | 31 ------------ .../ui-components/src/icon/iconimports.ts | 2 + packages/ui-components/style/deprecated.css | 4 ++ .../style/icons/toolbar/check.svg | 5 ++ 13 files changed, 55 insertions(+), 132 deletions(-) delete mode 100755 packages/celltags/static/add-24px-dark.svg delete mode 100755 packages/celltags/static/add-24px.svg delete mode 100755 packages/celltags/static/check-24px-dark.svg delete mode 100644 packages/celltags/static/check-24px.svg create mode 100644 packages/ui-components/style/icons/toolbar/check.svg diff --git a/packages/celltags-extension/src/index.ts b/packages/celltags-extension/src/index.ts index 27e8c4376ed1..f581d36b02c5 100644 --- a/packages/celltags-extension/src/index.ts +++ b/packages/celltags-extension/src/index.ts @@ -6,19 +6,14 @@ import { import { INotebookTools, INotebookTracker } from '@jupyterlab/notebook'; import { TagTool } from '@jupyterlab/celltags'; -import { IThemeManager } from '@jupyterlab/apputils'; function activate( app: JupyterFrontEnd, tools: INotebookTools, - tracker: INotebookTracker, - manager: IThemeManager + tracker: INotebookTracker ) { - const tool = new TagTool(tracker, app, manager); + const tool = new TagTool(tracker, app); tools.addItem({ tool: tool, rank: 1.7 }); - manager.themeChanged.connect(() => { - tool.updateTheme(); - }); } /** @@ -27,7 +22,7 @@ function activate( const celltags: JupyterFrontEndPlugin = { id: 'celltags', autoStart: true, - requires: [INotebookTools, INotebookTracker, IThemeManager], + requires: [INotebookTools, INotebookTracker], activate: activate }; diff --git a/packages/celltags/package.json b/packages/celltags/package.json index b41265b43215..a45ed466924f 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -45,12 +45,9 @@ "@jupyterlab/notebook": "^2.0.0-alpha.1", "@jupyterlab/ui-components": "^2.0.0-alpha.1", "@phosphor/widgets": "^1.9.0", - "@types/node": "^12.0.2", - "react": "~16.8.4", - "react-dom": "~16.8.4" + "@types/node": "^12.0.2" }, "devDependencies": { - "@types/react-dom": "^16.8.4", "rimraf": "~2.6.2", "typescript": "~3.5.1" } diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index e4387b1e0c26..a65eb2f674d9 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -1,5 +1,7 @@ import { Widget } from '@phosphor/widgets'; +import { defaultIconRegistry } from '@jupyterlab/ui-components'; + import { TagTool } from './tool'; /** @@ -9,14 +11,14 @@ export class AddWidget extends Widget { /** * Construct a new tag widget. */ - constructor(darkTheme: boolean) { + constructor() { super(); this.addClass('tag'); this.editing = false; - this.buildTag(darkTheme); + this.buildTag(); } - buildTag(theme: boolean) { + buildTag() { let text = document.createElement('input'); text.value = 'Add Tag'; text.contentEditable = 'true'; @@ -26,26 +28,28 @@ export class AddWidget extends Widget { tag.className = 'tag-holder'; tag.appendChild(text); let img = document.createElement('span'); - img.className = theme ? 'add-icon-dark' : 'add-icon'; - img.classList.add('icon'); + defaultIconRegistry.icon({ + name: 'add', + container: img, + center: true, + height: '18px', + width: '18px', + marginLeft: '3px', + marginRight: '-5px' + }); this.addClass('unapplied-tag'); tag.appendChild(img); - this.img = img; this.node.appendChild(tag); } onAfterAttach() { this.node.addEventListener('mousedown', this); - this.node.addEventListener('mouseover', this); - this.node.addEventListener('mouseout', this); this.node.addEventListener('keypress', this); this.node.addEventListener('focusout', this); } onBeforeDetach() { this.node.removeEventListener('mousedown', this); - this.node.removeEventListener('mouseover', this); - this.node.removeEventListener('mouseout', this); this.node.removeEventListener('keypress', this); this.node.removeEventListener('focusout', this); } @@ -55,12 +59,6 @@ export class AddWidget extends Widget { case 'mousedown': this._evtClick(event as MouseEvent); break; - case 'mouseover': - this._evtHover(event as MouseEvent); - break; - case 'mouseout': - this._evtOffHover(event as MouseEvent); - break; case 'keypress': this._evtKeyPress(event as KeyboardEvent); break; @@ -81,14 +79,6 @@ export class AddWidget extends Widget { } } - private _evtHover(event: MouseEvent) { - //(this.node as HTMLElement).classList.add("tag-hover"); - } - - private _evtOffHover(event: MouseEvent) { - //(this.node as HTMLElement).classList.remove("tag-hover"); - } - private _evtKeyPress(event: KeyboardEvent) { let inputElement = event.target as HTMLInputElement; let tmp = document.createElement('span'); @@ -116,15 +106,6 @@ export class AddWidget extends Widget { } } - updateTheme() { - let darkTheme = this.parent.getTheme(); - this.img.classList.remove('add-icon-dark'); - this.img.classList.remove('add-icon'); - let add = darkTheme ? 'add-icon-dark' : 'add-icon'; - this.img.classList.add(add); - } - public parent: TagTool; - private img: HTMLSpanElement; private editing: boolean; } diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index 9fb2b9aa62bd..3c0c04aecf4d 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -9,7 +9,6 @@ import { JupyterFrontEnd } from '@jupyterlab/application'; import { TagWidget } from './widget'; import { AddWidget } from './addwidget'; -import { IThemeManager } from '@jupyterlab/apputils'; /** * A Tool for tag operations. @@ -20,22 +19,17 @@ export class TagTool extends NotebookTools.Tool { * * @param tracker - The notebook tracker. */ - constructor( - tracker: INotebookTracker, - app: JupyterFrontEnd, - manager: IThemeManager - ) { + constructor(tracker: INotebookTracker, app: JupyterFrontEnd) { super(); app; this.tracker = tracker; - this.manager = manager; this.layout = new PanelLayout(); this.createTagInput(); } createTagInput() { let layout = this.layout as PanelLayout; - let input = new AddWidget(this.getTheme()); + let input = new AddWidget(); input.id = 'add-tag'; layout.insertWidget(0, input); } @@ -73,9 +67,9 @@ export class TagTool extends NotebookTools.Tool { } } cell.model.metadata.set('tags', tags); - console.log(this.tracker.activeCell.model.metadata.get('tags')); this.refreshTags(); this.loadActiveTags(); + console.log(this.tracker.activeCell.model.metadata.get('tags')); } removeTag(name: string) { @@ -141,7 +135,7 @@ export class TagTool extends NotebookTools.Tool { } } for (let i = 0; i < tags.length; i++) { - let widget = new TagWidget(tags[i], this.getTheme()); + let widget = new TagWidget(tags[i]); let idx = layout.widgets.length - 1; layout.insertWidget(idx, widget); } @@ -196,10 +190,13 @@ export class TagTool extends NotebookTools.Tool { * Get all tags once available. */ protected onAfterAttach() { - const header = document.createElement('header'); - header.textContent = 'Tags in Notebook'; - header.className = 'tag-header'; - this.parent.node.insertBefore(header, this.node); + if (!this.header) { + const header = document.createElement('header'); + header.textContent = 'Tags in Notebook'; + header.className = 'tag-header'; + this.parent.node.insertBefore(header, this.node); + this.header = true; + } this.tracker.currentWidget.context.ready.then(() => { this.refreshTags(); this.loadActiveTags(); @@ -223,23 +220,7 @@ export class TagTool extends NotebookTools.Tool { this.loadActiveTags(); } - getTheme() { - if (this.manager.theme == 'JupyterLab Dark') { - return true; - } - return false; - } - - updateTheme() { - let layout = this.layout as PanelLayout; - let nWidgets = layout.widgets.length; - for (let i = 0; i < nWidgets - 1; i++) { - (layout.widgets[i] as TagWidget).updateTheme(); - } - (layout.widgets[nWidgets - 1] as AddWidget).updateTheme(); - } - private tagList: string[] = []; - private manager: IThemeManager; + private header: boolean = false; public tracker: INotebookTracker = null; } diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts index dde99cbfcec9..1d3f1078f691 100644 --- a/packages/celltags/src/widget.ts +++ b/packages/celltags/src/widget.ts @@ -1,5 +1,7 @@ import { Widget } from '@phosphor/widgets'; +import { defaultIconRegistry } from '@jupyterlab/ui-components'; + import { TagTool } from './tool'; /** @@ -9,15 +11,15 @@ export class TagWidget extends Widget { /** * Construct a new tag widget. */ - constructor(name: string, darkTheme: boolean) { + constructor(name: string) { super(); this.applied = true; this.name = name; this.addClass('tag'); - this.buildTag(darkTheme); + this.buildTag(); } - buildTag(theme: boolean) { + buildTag() { let text = document.createElement('span'); text.textContent = this.name; text.style.textOverflow = 'ellipsis'; @@ -25,8 +27,15 @@ export class TagWidget extends Widget { tag.className = 'tag-holder'; tag.appendChild(text); let img = document.createElement('span'); - img.className = theme ? 'check-icon-dark' : 'check-icon'; - img.classList.add('icon'); + defaultIconRegistry.icon({ + name: 'check', + container: img, + center: true, + height: '18px', + width: '18px', + marginLeft: '5px', + marginRight: '-3px' + }); if (this.applied) { this.addClass('applied-tag'); } else { @@ -34,7 +43,6 @@ export class TagWidget extends Widget { img.style.display = 'none'; } tag.appendChild(img); - this.img = img; this.node.appendChild(tag); } @@ -105,16 +113,7 @@ export class TagWidget extends Widget { (this.node as HTMLElement).classList.remove('tag-hover'); } - updateTheme() { - let darkTheme = this.parent.getTheme(); - this.img.classList.remove('check-icon-dark'); - this.img.classList.remove('check-icon-dark'); - let add = darkTheme ? 'check-icon-dark' : 'check-icon'; - this.img.classList.add(add); - } - public name: string; private applied: boolean; - private img: HTMLSpanElement; public parent: TagTool; } diff --git a/packages/celltags/static/add-24px-dark.svg b/packages/celltags/static/add-24px-dark.svg deleted file mode 100755 index 0382d06ca057..000000000000 --- a/packages/celltags/static/add-24px-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/celltags/static/add-24px.svg b/packages/celltags/static/add-24px.svg deleted file mode 100755 index 881f35256ff4..000000000000 --- a/packages/celltags/static/add-24px.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/celltags/static/check-24px-dark.svg b/packages/celltags/static/check-24px-dark.svg deleted file mode 100755 index f3a52eaa8a45..000000000000 --- a/packages/celltags/static/check-24px-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/celltags/static/check-24px.svg b/packages/celltags/static/check-24px.svg deleted file mode 100644 index 2453d055cdff..000000000000 --- a/packages/celltags/static/check-24px.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/celltags/style/base.css b/packages/celltags/style/base.css index 208bfef2fffe..7935d22b6ae5 100644 --- a/packages/celltags/style/base.css +++ b/packages/celltags/style/base.css @@ -42,37 +42,6 @@ align-items: center; } -.icon { - display: inline-block; - height: 18px; - min-width: 18px; - background-size: 18px; -} - -.check-icon { - background-image: url('../static/check-24px.svg'); - margin-left: 5px; - margin-right: -3px; -} - -.add-icon { - background-image: url('../static/add-24px.svg'); - margin-left: 3px; - margin-right: -5px; -} - -.check-icon-dark { - background-image: url('../static/check-24px-dark.svg'); - margin-left: 5px; - margin-right: -3px; -} - -.add-icon-dark { - background-image: url('../static/add-24px-dark.svg'); - margin-left: 3px; - margin-right: -5px; -} - .tag-hover { background-color: var(--jp-layout-color2); } diff --git a/packages/ui-components/src/icon/iconimports.ts b/packages/ui-components/src/icon/iconimports.ts index ac330e7056c0..f77f056a98c2 100644 --- a/packages/ui-components/src/icon/iconimports.ts +++ b/packages/ui-components/src/icon/iconimports.ts @@ -33,6 +33,7 @@ import notTrustedSvg from '../../style/icons/statusbar/not-trusted.svg'; import terminalSvg from '../../style/icons/statusbar/terminal.svg'; import trustedSvg from '../../style/icons/statusbar/trusted.svg'; import addSvg from '../../style/icons/toolbar/add.svg'; +import checkSvg from '../../style/icons/toolbar/check.svg'; import copySvg from '../../style/icons/toolbar/copy.svg'; import cutSvg from '../../style/icons/toolbar/cut.svg'; import pasteSvg from '../../style/icons/toolbar/paste.svg'; @@ -69,6 +70,7 @@ export namespace IconImports { { name: 'terminal', svg: terminalSvg }, { name: 'trusted', svg: trustedSvg }, { name: 'add', svg: addSvg }, + { name: 'check', svg: checkSvg }, { name: 'copy', svg: copySvg }, { name: 'cut', svg: cutSvg }, { name: 'paste', svg: pasteSvg }, diff --git a/packages/ui-components/style/deprecated.css b/packages/ui-components/style/deprecated.css index d7aab13b71a6..5c1dc7f90a59 100644 --- a/packages/ui-components/style/deprecated.css +++ b/packages/ui-components/style/deprecated.css @@ -37,6 +37,7 @@ --jp-icon-terminal: url('icons/statusbar/terminal.svg'); --jp-icon-trusted: url('icons/statusbar/trusted.svg'); --jp-icon-add: url('icons/toolbar/add.svg'); + --jp-icon-check: url('icons/toolbar/check.svg'); --jp-icon-copy: url('icons/toolbar/copy.svg'); --jp-icon-cut: url('icons/toolbar/cut.svg'); --jp-icon-paste: url('icons/toolbar/paste.svg'); @@ -123,6 +124,9 @@ .jp-AddIcon { background-image: var(--jp-icon-add); } +.jp-CheckIcon { + background-image: var(--jp-icon-check); +} .jp-CopyIcon { background-image: var(--jp-icon-copy); } diff --git a/packages/ui-components/style/icons/toolbar/check.svg b/packages/ui-components/style/icons/toolbar/check.svg new file mode 100644 index 000000000000..60af68f52500 --- /dev/null +++ b/packages/ui-components/style/icons/toolbar/check.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file From aa113c4a5d14f724f49b326301a95fab74e3e462 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Wed, 6 Nov 2019 15:25:20 -0800 Subject: [PATCH 05/21] added docstrings, fixed some function names, updated package.json --- packages/celltags-extension/package.json | 8 ++-- packages/celltags-extension/src/index.ts | 18 ++++--- packages/celltags/package.json | 8 ++-- packages/celltags/src/addwidget.ts | 44 +++++++++++++++-- packages/celltags/src/tool.ts | 39 ++++++++++++++- packages/celltags/src/widget.ts | 48 +++++++++++++++++-- .../style/icons/toolbar/check.svg | 2 +- 7 files changed, 137 insertions(+), 30 deletions(-) diff --git a/packages/celltags-extension/package.json b/packages/celltags-extension/package.json index c5b83761649d..f27d848f7082 100644 --- a/packages/celltags-extension/package.json +++ b/packages/celltags-extension/package.json @@ -7,16 +7,16 @@ "jupyterlab", "jupyterlab-extension" ], - "homepage": "https://github.com/my_name/myextension", + "homepage": "https://github.com/jupyterlab/jupyterlab", "bugs": { - "url": "https://github.com/my_name/myextension/issues" + "url": "https://github.com/jupyterlab/jupyterlab/issues" }, "repository": { "type": "git", - "url": "https://github.com/my_name/myextension.git" + "url": "https://github.com/jupyterlab/jupyterlab.git" }, "license": "BSD-3-Clause", - "author": "Markelle Kelly", + "author": "Project Jupyter", "files": [ "lib/*.{d.ts,js}", "style/*.css" diff --git a/packages/celltags-extension/src/index.ts b/packages/celltags-extension/src/index.ts index f581d36b02c5..abc31963baaf 100644 --- a/packages/celltags-extension/src/index.ts +++ b/packages/celltags-extension/src/index.ts @@ -7,15 +7,6 @@ import { INotebookTools, INotebookTracker } from '@jupyterlab/notebook'; import { TagTool } from '@jupyterlab/celltags'; -function activate( - app: JupyterFrontEnd, - tools: INotebookTools, - tracker: INotebookTracker -) { - const tool = new TagTool(tracker, app); - tools.addItem({ tool: tool, rank: 1.7 }); -} - /** * Initialization data for the celltags extension. */ @@ -23,7 +14,14 @@ const celltags: JupyterFrontEndPlugin = { id: 'celltags', autoStart: true, requires: [INotebookTools, INotebookTracker], - activate: activate + activate: ( + app: JupyterFrontEnd, + tools: INotebookTools, + tracker: INotebookTracker + ) => { + const tool = new TagTool(tracker, app); + tools.addItem({ tool: tool, rank: 1.7 }); + } }; export default celltags; diff --git a/packages/celltags/package.json b/packages/celltags/package.json index a45ed466924f..ebecabef344d 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -7,16 +7,16 @@ "jupyterlab", "jupyterlab-extension" ], - "homepage": "https://github.com/my_name/myextension", + "homepage": "https://github.com/jupyterlab/jupyterlab", "bugs": { - "url": "https://github.com/my_name/myextension/issues" + "url": "https://github.com/jupyterlab/jupyterlab/issues" }, "repository": { "type": "git", - "url": "https://github.com/my_name/myextension.git" + "url": "https://github.com/jupyterlab/jupyterlab.git" }, "license": "BSD-3-Clause", - "author": "Markelle Kelly", + "author": "Project Jupyter", "files": [ "lib/*.{d.ts,js}", "style/*.css", diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index a65eb2f674d9..3f9cec9289cc 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -18,6 +18,9 @@ export class AddWidget extends Widget { this.buildTag(); } + /** + * Create input box with icon and attach to this.node. + */ buildTag() { let text = document.createElement('input'); text.value = 'Add Tag'; @@ -42,35 +45,56 @@ export class AddWidget extends Widget { this.node.appendChild(tag); } + /** + * Handle `after-attach` messages for the widget. + */ onAfterAttach() { this.node.addEventListener('mousedown', this); this.node.addEventListener('keypress', this); this.node.addEventListener('focusout', this); } + /** + * Handle `before-detach` messages for the widget. + */ onBeforeDetach() { this.node.removeEventListener('mousedown', this); this.node.removeEventListener('keypress', this); this.node.removeEventListener('focusout', this); } + /** + * Handle the DOM events for the widget. + * + * @param event - The DOM event sent to the widget. + * + * #### Notes + * This method implements the DOM `EventListener` interface and is + * called in response to events on the dock panel's node. It should + * not be called directly by user code. + */ handleEvent(event: Event): void { switch (event.type) { case 'mousedown': - this._evtClick(event as MouseEvent); + this._evtMouseDown(event as MouseEvent); break; case 'keypress': this._evtKeyPress(event as KeyboardEvent); break; case 'focusout': - this._evtBlur(); + this._evtFocusOut(); break; default: break; } } - private _evtClick(event: MouseEvent) { + /** + * Handle the `'mousedown'` event for the input box. + * + * @param event - The DOM event sent to the widget + */ + private _evtMouseDown(event: MouseEvent) { if (!this.editing) { this.editing = true; let target = event.target as HTMLInputElement; @@ -79,6 +103,11 @@ export class AddWidget extends Widget { } } + /** + * Handle the `'keypress'` event for the input box. + * + * @param event - The DOM event sent to the widget + */ private _evtKeyPress(event: KeyboardEvent) { let inputElement = event.target as HTMLInputElement; let tmp = document.createElement('span'); @@ -93,11 +122,16 @@ export class AddWidget extends Widget { let value = inputElement.value; (this.parent as TagTool).addTag(value); inputElement.blur(); - this._evtBlur(); + this._evtFocusOut(); } } - private _evtBlur() { + /** + * Handle the `'focusout'` event for the input box. + * + * @param event - The DOM event sent to the widget + */ + private _evtFocusOut() { if (this.editing) { this.editing = false; let target = event.target as HTMLInputElement; diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index 3c0c04aecf4d..65ea987f4c05 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -27,6 +27,9 @@ export class TagTool extends NotebookTools.Tool { this.createTagInput(); } + /** + * Add an AddWidget input box to the layout. + */ createTagInput() { let layout = this.layout as PanelLayout; let input = new AddWidget(); @@ -34,6 +37,13 @@ export class TagTool extends NotebookTools.Tool { layout.insertWidget(0, input); } + /** + * Check whether a tag is applied to the current active cell + * + * @param name - The name of the tag. + * + * @returns A boolean representing whether it is applied. + */ checkApplied(name: string): boolean { if (this.tracker.activeCell) { let tags = this.tracker.activeCell.model.metadata.get('tags') as string[]; @@ -48,6 +58,11 @@ export class TagTool extends NotebookTools.Tool { return false; } + /** + * Add a tag to the current active cell. + * + * @param name - The name of the tag. + */ addTag(name: string) { let cell = this.tracker.activeCell; let tags = cell.model.metadata.get('tags') as string[]; @@ -61,6 +76,7 @@ export class TagTool extends NotebookTools.Tool { toAdd.push(newTags[i]); } } + // todo: can this be combined into one for loop? for (let j = 0; j < toAdd.length; j++) { if (tags.indexOf(toAdd[j]) < 0) { tags.push(toAdd[j]); @@ -72,6 +88,11 @@ export class TagTool extends NotebookTools.Tool { console.log(this.tracker.activeCell.model.metadata.get('tags')); } + /** + * Remove a tag from the current active cell. + * + * @param name - The name of the tag. + */ removeTag(name: string) { let cell = this.tracker.activeCell; let tags = cell.model.metadata.get('tags') as string[]; @@ -88,6 +109,10 @@ export class TagTool extends NotebookTools.Tool { console.log(this.tracker.activeCell.model.metadata.get('tags')); } + /** + * Update each tag widget to represent whether it is applied to the current + * active cell. + */ loadActiveTags() { let layout = this.layout as PanelLayout; for (let i = 0; i < layout.widgets.length; i++) { @@ -96,7 +121,8 @@ export class TagTool extends NotebookTools.Tool { } /** - * Pull from cell metadata all the tags assigned to notebook cells, + * Pull from cell metadata all the tags used in the notebook and update the + * stored tag list. */ pullTags() { let notebook = this.tracker.currentWidget; @@ -121,6 +147,10 @@ export class TagTool extends NotebookTools.Tool { } } + /** + * Pull the most recent list of tags and update the tag widgets - dispose if + * the tag no longer exists, and create new widgets for new tags. + */ refreshTags() { this.pullTags(); let layout = this.layout as PanelLayout; @@ -141,6 +171,10 @@ export class TagTool extends NotebookTools.Tool { } } + /** + * Validate the 'tags' of cell metadata, ensuring it is a list of strings and + * that each string doesn't include spaces. + */ validateTags(cell: Cell) { let tags = cell.model.metadata.get('tags'); var results: string[] = []; @@ -187,7 +221,8 @@ export class TagTool extends NotebookTools.Tool { } /** - * Get all tags once available. + * Upon attach, add header if it doesn't already exist and listen for changes + * from the notebook tracker. */ protected onAfterAttach() { if (!this.header) { diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts index 1d3f1078f691..ded1a91abf34 100644 --- a/packages/celltags/src/widget.ts +++ b/packages/celltags/src/widget.ts @@ -19,6 +19,9 @@ export class TagWidget extends Widget { this.buildTag(); } + /** + * Create tag div with icon and attach to this.node. + */ buildTag() { let text = document.createElement('span'); text.textContent = this.name; @@ -46,34 +49,53 @@ export class TagWidget extends Widget { this.node.appendChild(tag); } + /** + * Handle `after-attach` messages for the widget. + */ onAfterAttach() { this.node.addEventListener('mousedown', this); this.node.addEventListener('mouseover', this); this.node.addEventListener('mouseout', this); } + /** + * Handle `before-detach` messages for the widget. + */ onBeforeDetach() { this.node.removeEventListener('mousedown', this); this.node.removeEventListener('mouseover', this); this.node.removeEventListener('mouseout', this); } + /** + * Handle the DOM events for the widget. + * + * @param event - The DOM event sent to the widget. + * + * #### Notes + * This method implements the DOM `EventListener` interface and is + * called in response to events on the dock panel's node. It should + * not be called directly by user code. + */ handleEvent(event: Event): void { switch (event.type) { case 'mousedown': this._evtClick(); break; case 'mouseover': - this._evtHover(event as MouseEvent); + this._evtMouseOver(event as MouseEvent); break; case 'mouseout': - this._evtOffHover(event as MouseEvent); + this._evtMouseOut(event as MouseEvent); break; default: break; } } + /** + * Handle `update-request` messages. Check if applied to current active cell. + */ onUpdateRequest() { let applied = this.parent.checkApplied(this.name); if (applied != this.applied) { @@ -81,6 +103,9 @@ export class TagWidget extends Widget { } } + /** + * Update styling to reflect whether tag is applied to current active cell. + */ toggleApplied() { if (this.applied) { this.removeClass('applied-tag'); @@ -96,6 +121,11 @@ export class TagWidget extends Widget { this.applied = !this.applied; } + /** + * Handle the `'click'` event for the widget. + * + * @param event - The DOM event sent to the widget + */ private _evtClick() { if (this.applied) { this.parent.removeTag(this.name); @@ -105,11 +135,21 @@ export class TagWidget extends Widget { this.toggleApplied(); } - private _evtHover(event: MouseEvent) { + /** + * Handle the `'mouseover'` event for the widget. + * + * @param event - The DOM event sent to the widget + */ + private _evtMouseOver(event: MouseEvent) { (this.node as HTMLElement).classList.add('tag-hover'); } - private _evtOffHover(event: MouseEvent) { + /** + * Handle the `'mouseout'` event for the widget. + * + * @param event - The DOM event sent to the widget + */ + private _evtMouseOut(event: MouseEvent) { (this.node as HTMLElement).classList.remove('tag-hover'); } diff --git a/packages/ui-components/style/icons/toolbar/check.svg b/packages/ui-components/style/icons/toolbar/check.svg index 60af68f52500..5303898a89b7 100644 --- a/packages/ui-components/style/icons/toolbar/check.svg +++ b/packages/ui-components/style/icons/toolbar/check.svg @@ -1,5 +1,5 @@ - \ No newline at end of file From 8fa2b85f74005f57489ca95782956782abe45f03 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Wed, 6 Nov 2019 15:39:23 -0800 Subject: [PATCH 06/21] small fixes --- packages/celltags/src/tool.ts | 11 ++--------- packages/ui-components/style/icons/toolbar/check.svg | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index 65ea987f4c05..b01991c6f4f7 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -70,16 +70,9 @@ export class TagTool extends NotebookTools.Tool { if (tags === undefined) { tags = []; } - const toAdd: string[] = []; for (let i = 0; i < newTags.length; i++) { - if (newTags[i] !== '' && toAdd.indexOf(newTags[i]) < 0) { - toAdd.push(newTags[i]); - } - } - // todo: can this be combined into one for loop? - for (let j = 0; j < toAdd.length; j++) { - if (tags.indexOf(toAdd[j]) < 0) { - tags.push(toAdd[j]); + if (newTags[i] !== '' && tags.indexOf(newTags[i]) < 0) { + tags.push(newTags[i]); } } cell.model.metadata.set('tags', tags); diff --git a/packages/ui-components/style/icons/toolbar/check.svg b/packages/ui-components/style/icons/toolbar/check.svg index 5303898a89b7..60af68f52500 100644 --- a/packages/ui-components/style/icons/toolbar/check.svg +++ b/packages/ui-components/style/icons/toolbar/check.svg @@ -1,5 +1,5 @@ - \ No newline at end of file From 1f09a97bae66349e46b304edc973c54eb511abd4 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Fri, 8 Nov 2019 11:08:57 -0800 Subject: [PATCH 07/21] updated package.json, debugging --- packages/celltags-extension/package.json | 1 - packages/celltags-extension/tsconfig.json | 3 -- packages/celltags/package.json | 1 - packages/celltags/src/tool.ts | 38 +++++++++++++---------- packages/celltags/style/index.css | 1 - packages/celltags/tsconfig.json | 3 -- 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/packages/celltags-extension/package.json b/packages/celltags-extension/package.json index f27d848f7082..36431f7a5cf6 100644 --- a/packages/celltags-extension/package.json +++ b/packages/celltags-extension/package.json @@ -39,7 +39,6 @@ }, "dependencies": { "@jupyterlab/application": "^2.0.0-alpha.1", - "@jupyterlab/apputils": "^2.0.0-alpha.1", "@jupyterlab/celltags": "^0.1.0", "@jupyterlab/notebook": "^2.0.0-alpha.1", "@types/node": "^12.0.2" diff --git a/packages/celltags-extension/tsconfig.json b/packages/celltags-extension/tsconfig.json index 69f2c84a2795..a68cc31546ae 100644 --- a/packages/celltags-extension/tsconfig.json +++ b/packages/celltags-extension/tsconfig.json @@ -25,9 +25,6 @@ { "path": "../application" }, - { - "path": "../apputils" - }, { "path": "../celltags" }, diff --git a/packages/celltags/package.json b/packages/celltags/package.json index ebecabef344d..bf9df994a9e5 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -40,7 +40,6 @@ }, "dependencies": { "@jupyterlab/application": "^2.0.0-alpha.1", - "@jupyterlab/apputils": "^2.0.0-alpha.1", "@jupyterlab/cells": "^2.0.0-alpha.1", "@jupyterlab/notebook": "^2.0.0-alpha.1", "@jupyterlab/ui-components": "^2.0.0-alpha.1", diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index b01991c6f4f7..b4cf4387d69e 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -148,15 +148,19 @@ export class TagTool extends NotebookTools.Tool { this.pullTags(); let layout = this.layout as PanelLayout; let tags: string[] = this.tagList; + let toDispose: TagWidget[] = []; let nWidgets = layout.widgets.length; - for (let i = 0; i < nWidgets - 1; i++) { + for (let i = 0; i < nWidgets; i++) { let idx = tags.indexOf((layout.widgets[i] as TagWidget).name); if (idx < 0 && layout.widgets[i].id != 'add-tag') { - layout.widgets[i].dispose(); + toDispose.push(layout.widgets[i] as TagWidget); } else { tags.splice(idx, 1); } } + for (let i = 0; i < toDispose.length; i++) { + toDispose[i].dispose(); + } for (let i = 0; i < tags.length; i++) { let widget = new TagWidget(tags[i]); let idx = layout.widgets.length - 1; @@ -168,21 +172,11 @@ export class TagTool extends NotebookTools.Tool { * Validate the 'tags' of cell metadata, ensuring it is a list of strings and * that each string doesn't include spaces. */ - validateTags(cell: Cell) { - let tags = cell.model.metadata.get('tags'); + validateTags(cell: Cell, taglist: string[]) { var results: string[] = []; - var taglist: string[] = []; - if (tags === undefined) { - return; - } - if (typeof tags === 'string') { - taglist.push(tags); - } else { - taglist = tags; - } for (let i = 0; i < taglist.length; i++) { if (taglist[i] != '' && typeof taglist[i] === 'string') { - let spl = taglist[i].split(' '); + let spl = taglist[i].split(/[,\s]+/); for (let j = 0; j < spl.length; j++) { if (spl[j] != '' && results.indexOf(spl[j]) < 0) { results.push(spl[j]); @@ -191,6 +185,8 @@ export class TagTool extends NotebookTools.Tool { } } cell.model.metadata.set('tags', results); + this.refreshTags(); + this.loadActiveTags(); } /** @@ -243,9 +239,17 @@ export class TagTool extends NotebookTools.Tool { * Handle a change to active cell metadata. */ protected onActiveCellMetadataChanged(): void { - this.validateTags(this.tracker.activeCell); - this.refreshTags(); - this.loadActiveTags(); + let tags = this.tracker.activeCell.model.metadata.get('tags'); + var taglist: string[] = []; + if (tags === undefined) { + return; + } + if (typeof tags === 'string') { + taglist.push(tags); + } else { + taglist = tags; + } + this.validateTags(this.tracker.activeCell, taglist); } private tagList: string[] = []; diff --git a/packages/celltags/style/index.css b/packages/celltags/style/index.css index 5ae710253293..bc576e569e3d 100644 --- a/packages/celltags/style/index.css +++ b/packages/celltags/style/index.css @@ -6,7 +6,6 @@ /* This file was auto-generated by ensurePackage() in @jupyterlab/buildutils */ @import url('~@phosphor/widgets/style/index.css'); @import url('~@jupyterlab/ui-components/style/index.css'); -@import url('~@jupyterlab/apputils/style/index.css'); @import url('~@jupyterlab/application/style/index.css'); @import url('~@jupyterlab/cells/style/index.css'); @import url('~@jupyterlab/notebook/style/index.css'); diff --git a/packages/celltags/tsconfig.json b/packages/celltags/tsconfig.json index bdfc7b342e1d..d2fd9e21416c 100644 --- a/packages/celltags/tsconfig.json +++ b/packages/celltags/tsconfig.json @@ -25,9 +25,6 @@ { "path": "../application" }, - { - "path": "../apputils" - }, { "path": "../cells" }, From 4f65cb4b6ccfdb1ec0b133708d208cdc94cb794f Mon Sep 17 00:00:00 2001 From: markellekelly Date: Fri, 8 Nov 2019 11:24:56 -0800 Subject: [PATCH 08/21] adjusted to pass linux integrity tests --- packages/celltags/src/addwidget.ts | 2 +- packages/celltags/src/tool.ts | 21 ++++++++------------- packages/celltags/src/widget.ts | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 3f9cec9289cc..a003b497cc10 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -118,7 +118,7 @@ export class AddWidget extends Widget { inputElement.style.width = tmp.getBoundingClientRect().width + 8 + 'px'; document.body.removeChild(tmp); // if they hit Enter, add the tag and reset state - if (event.keyCode == 13) { + if (event.keyCode === 13) { let value = inputElement.value; (this.parent as TagTool).addTag(value); inputElement.blur(); diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index b4cf4387d69e..fe4dec54be88 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -122,11 +122,11 @@ export class TagTool extends NotebookTools.Tool { if (this.tracker && this.tracker.currentWidget) { let cells = notebook.model.cells; let allTags: string[] = []; - for (var i = 0; i < cells.length; i++) { + for (let i = 0; i < cells.length; i++) { let metadata = cells.get(i).metadata; let tags = metadata.get('tags') as string[]; if (tags) { - for (var j = 0; j < tags.length; j++) { + for (let j = 0; j < tags.length; j++) { let name = tags[j] as string; if (name !== '') { if (allTags.indexOf(name) < 0) { @@ -152,7 +152,7 @@ export class TagTool extends NotebookTools.Tool { let nWidgets = layout.widgets.length; for (let i = 0; i < nWidgets; i++) { let idx = tags.indexOf((layout.widgets[i] as TagWidget).name); - if (idx < 0 && layout.widgets[i].id != 'add-tag') { + if (idx < 0 && layout.widgets[i].id !== 'add-tag') { toDispose.push(layout.widgets[i] as TagWidget); } else { tags.splice(idx, 1); @@ -173,12 +173,12 @@ export class TagTool extends NotebookTools.Tool { * that each string doesn't include spaces. */ validateTags(cell: Cell, taglist: string[]) { - var results: string[] = []; + let results: string[] = []; for (let i = 0; i < taglist.length; i++) { - if (taglist[i] != '' && typeof taglist[i] === 'string') { + if (taglist[i] !== '' && typeof taglist[i] === 'string') { let spl = taglist[i].split(/[,\s]+/); for (let j = 0; j < spl.length; j++) { - if (spl[j] != '' && results.indexOf(spl[j]) < 0) { + if (spl[j] !== '' && results.indexOf(spl[j]) < 0) { results.push(spl[j]); } } @@ -196,11 +196,6 @@ export class TagTool extends NotebookTools.Tool { this.loadActiveTags(); } - /** - * Handle a change to cell selection in the notebook. - */ - protected onSelectionChanged(): void {} - /** * Get all tags once available. */ @@ -240,14 +235,14 @@ export class TagTool extends NotebookTools.Tool { */ protected onActiveCellMetadataChanged(): void { let tags = this.tracker.activeCell.model.metadata.get('tags'); - var taglist: string[] = []; + let taglist: string[] = []; if (tags === undefined) { return; } if (typeof tags === 'string') { taglist.push(tags); } else { - taglist = tags; + taglist = tags as string[]; } this.validateTags(this.tracker.activeCell, taglist); } diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts index ded1a91abf34..6bf37306bba4 100644 --- a/packages/celltags/src/widget.ts +++ b/packages/celltags/src/widget.ts @@ -98,7 +98,7 @@ export class TagWidget extends Widget { */ onUpdateRequest() { let applied = this.parent.checkApplied(this.name); - if (applied != this.applied) { + if (applied !== this.applied) { this.toggleApplied(); } } From 5d4b05ebe9fded973aa7d25652313372503d0786 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Mon, 2 Dec 2019 14:17:48 -0800 Subject: [PATCH 09/21] bug fix --- packages/celltags-extension/src/index.ts | 2 +- packages/celltags/src/tool.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/celltags-extension/src/index.ts b/packages/celltags-extension/src/index.ts index abc31963baaf..87da87c5d6b0 100644 --- a/packages/celltags-extension/src/index.ts +++ b/packages/celltags-extension/src/index.ts @@ -20,7 +20,7 @@ const celltags: JupyterFrontEndPlugin = { tracker: INotebookTracker ) => { const tool = new TagTool(tracker, app); - tools.addItem({ tool: tool, rank: 1.7 }); + tools.addItem({ tool: tool, rank: 1.6 }); } }; diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index fe4dec54be88..c04953d3c480 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -154,7 +154,7 @@ export class TagTool extends NotebookTools.Tool { let idx = tags.indexOf((layout.widgets[i] as TagWidget).name); if (idx < 0 && layout.widgets[i].id !== 'add-tag') { toDispose.push(layout.widgets[i] as TagWidget); - } else { + } else if (layout.widgets[i].id !== 'add-tag') { tags.splice(idx, 1); } } From d8c7754dc77cee47cdfbbb8415c2af3a732b5b95 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Mon, 2 Dec 2019 15:50:53 -0800 Subject: [PATCH 10/21] check for tracker.currentwidget --- packages/celltags/src/tool.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index c04953d3c480..2f4311f21f28 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -216,18 +216,20 @@ export class TagTool extends NotebookTools.Tool { this.parent.node.insertBefore(header, this.node); this.header = true; } - this.tracker.currentWidget.context.ready.then(() => { - this.refreshTags(); - this.loadActiveTags(); - }); + if (this.tracker.currentWidget) { + this.tracker.currentWidget.context.ready.then(() => { + this.refreshTags(); + this.loadActiveTags(); + }); + this.tracker.currentWidget.model.cells.changed.connect(() => { + this.refreshTags(); + this.loadActiveTags(); + }); + } this.tracker.currentChanged.connect(() => { this.refreshTags(); this.loadActiveTags(); }); - this.tracker.currentWidget.model.cells.changed.connect(() => { - this.refreshTags(); - this.loadActiveTags(); - }); } /** From 49f2619ad588e15ba6da741825d5560a58517127 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Mon, 2 Dec 2019 16:16:57 -0800 Subject: [PATCH 11/21] prevent text highlighting --- packages/celltags/style/base.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/celltags/style/base.css b/packages/celltags/style/base.css index 7935d22b6ae5..3f5048f78eaf 100644 --- a/packages/celltags/style/base.css +++ b/packages/celltags/style/base.css @@ -11,6 +11,12 @@ justify-content: center; align-items: center; max-width: calc(100% - 25px); + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .unapplied-tag { From 902571e8da3cb4a2972bf03b1d2ebf0d0304be89 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Thu, 5 Dec 2019 11:56:24 -0800 Subject: [PATCH 12/21] Update packages/celltags/package.json Co-Authored-By: Saul Shanabrook --- packages/celltags/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/celltags/package.json b/packages/celltags/package.json index bf9df994a9e5..b73604afd4e9 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -43,7 +43,7 @@ "@jupyterlab/cells": "^2.0.0-alpha.1", "@jupyterlab/notebook": "^2.0.0-alpha.1", "@jupyterlab/ui-components": "^2.0.0-alpha.1", - "@phosphor/widgets": "^1.9.0", + "@lumino/widgets": "^1.9.0", "@types/node": "^12.0.2" }, "devDependencies": { From 21d3f40b9ef5604fc1aa4e08280efaba5b501dbd Mon Sep 17 00:00:00 2001 From: Zsailer Date: Thu, 5 Dec 2019 14:51:00 -0600 Subject: [PATCH 13/21] bump ts version --- packages/celltags-extension/package.json | 2 +- packages/celltags/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/celltags-extension/package.json b/packages/celltags-extension/package.json index 36431f7a5cf6..86d0cccefaa1 100644 --- a/packages/celltags-extension/package.json +++ b/packages/celltags-extension/package.json @@ -45,7 +45,7 @@ }, "devDependencies": { "rimraf": "~2.6.2", - "typescript": "~3.5.1" + "typescript": "~3.7.2" }, "jupyterlab": { "extension": true diff --git a/packages/celltags/package.json b/packages/celltags/package.json index b73604afd4e9..3bf9e601dc2c 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -48,6 +48,6 @@ }, "devDependencies": { "rimraf": "~2.6.2", - "typescript": "~3.5.1" + "typescript": "~3.7.2" } } From 6ad89fa48e3c4e498ea70ec0d23df081d14f5d28 Mon Sep 17 00:00:00 2001 From: Zsailer Date: Thu, 5 Dec 2019 15:19:44 -0600 Subject: [PATCH 14/21] switch phosphor to lumino dependencies --- packages/celltags/src/addwidget.ts | 2 +- packages/celltags/src/tool.ts | 2 +- packages/celltags/src/widget.ts | 2 +- packages/celltags/style/index.css | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index a003b497cc10..436e88ed38f3 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -1,4 +1,4 @@ -import { Widget } from '@phosphor/widgets'; +import { Widget } from '@lumino/widgets'; import { defaultIconRegistry } from '@jupyterlab/ui-components'; diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index 2f4311f21f28..e4e8cf94dcf1 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -1,4 +1,4 @@ -import { PanelLayout } from '@phosphor/widgets'; +import { PanelLayout } from '@lumino/widgets'; import { NotebookTools, INotebookTracker } from '@jupyterlab/notebook'; diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts index 6bf37306bba4..434c12658793 100644 --- a/packages/celltags/src/widget.ts +++ b/packages/celltags/src/widget.ts @@ -1,4 +1,4 @@ -import { Widget } from '@phosphor/widgets'; +import { Widget } from '@lumino/widgets'; import { defaultIconRegistry } from '@jupyterlab/ui-components'; diff --git a/packages/celltags/style/index.css b/packages/celltags/style/index.css index bc576e569e3d..b8a4c6f09b70 100644 --- a/packages/celltags/style/index.css +++ b/packages/celltags/style/index.css @@ -4,7 +4,7 @@ |----------------------------------------------------------------------------*/ /* This file was auto-generated by ensurePackage() in @jupyterlab/buildutils */ -@import url('~@phosphor/widgets/style/index.css'); +@import url('~@lumino/widgets/style/index.css'); @import url('~@jupyterlab/ui-components/style/index.css'); @import url('~@jupyterlab/application/style/index.css'); @import url('~@jupyterlab/cells/style/index.css'); From 0cc08c238dd492c786af5d0d140eabcb4251ddd7 Mon Sep 17 00:00:00 2001 From: markellekelly Date: Thu, 5 Dec 2019 17:44:27 -0800 Subject: [PATCH 15/21] fixed interactions with add widget --- packages/celltags/src/addwidget.ts | 46 ++++++++++++++++-------------- packages/celltags/style/index.css | 1 + 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 436e88ed38f3..449b5a8afbc7 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -27,6 +27,7 @@ export class AddWidget extends Widget { text.contentEditable = 'true'; text.className = 'add-tag'; text.style.width = '49px'; + this.input = text; let tag = document.createElement('div'); tag.className = 'tag-holder'; tag.appendChild(text); @@ -41,6 +42,7 @@ export class AddWidget extends Widget { marginRight: '-5px' }); this.addClass('unapplied-tag'); + //this.button = img; tag.appendChild(img); this.node.appendChild(tag); } @@ -50,8 +52,9 @@ export class AddWidget extends Widget { */ onAfterAttach() { this.node.addEventListener('mousedown', this); - this.node.addEventListener('keypress', this); - this.node.addEventListener('focusout', this); + //this.button.addEventListener('mousedown', this); + this.input.addEventListener('keydown', this); + this.input.addEventListener('blur', this); } /** @@ -59,8 +62,9 @@ export class AddWidget extends Widget { */ onBeforeDetach() { this.node.removeEventListener('mousedown', this); - this.node.removeEventListener('keypress', this); - this.node.removeEventListener('focusout', this); + //this.button.removeEventListener('mousedown', this); + this.input.removeEventListener('keydown', this); + this.input.removeEventListener('blur', this); } /** @@ -78,10 +82,10 @@ export class AddWidget extends Widget { case 'mousedown': this._evtMouseDown(event as MouseEvent); break; - case 'keypress': - this._evtKeyPress(event as KeyboardEvent); + case 'keydown': + this._evtKeyDown(event as KeyboardEvent); break; - case 'focusout': + case 'blur': this._evtFocusOut(); break; default: @@ -97,31 +101,30 @@ export class AddWidget extends Widget { private _evtMouseDown(event: MouseEvent) { if (!this.editing) { this.editing = true; - let target = event.target as HTMLInputElement; - target.value = ''; - target.autofocus = true; + this.input.value = ''; + this.input.focus(); } + event.preventDefault(); } /** - * Handle the `'keypress'` event for the input box. + * Handle the `'keydown'` event for the input box. * * @param event - The DOM event sent to the widget */ - private _evtKeyPress(event: KeyboardEvent) { - let inputElement = event.target as HTMLInputElement; + private _evtKeyDown(event: KeyboardEvent) { let tmp = document.createElement('span'); - tmp.className = 'tag'; - tmp.innerHTML = inputElement.value; + tmp.className = 'add-tag'; + tmp.innerHTML = this.input.value; // set width to the pixel length of the text document.body.appendChild(tmp); - inputElement.style.width = tmp.getBoundingClientRect().width + 8 + 'px'; + this.input.style.width = tmp.getBoundingClientRect().width + 8 + 'px'; document.body.removeChild(tmp); // if they hit Enter, add the tag and reset state if (event.keyCode === 13) { - let value = inputElement.value; + let value = this.input.value; (this.parent as TagTool).addTag(value); - inputElement.blur(); + this.input.blur(); this._evtFocusOut(); } } @@ -134,12 +137,13 @@ export class AddWidget extends Widget { private _evtFocusOut() { if (this.editing) { this.editing = false; - let target = event.target as HTMLInputElement; - target.value = 'Add Tag'; - target.style.width = '49px'; + this.input.value = 'Add Tag'; + this.input.style.width = '49px'; } } public parent: TagTool; private editing: boolean; + //private button: HTMLElement; + private input: HTMLInputElement; } diff --git a/packages/celltags/style/index.css b/packages/celltags/style/index.css index b8a4c6f09b70..3b675404811b 100644 --- a/packages/celltags/style/index.css +++ b/packages/celltags/style/index.css @@ -9,5 +9,6 @@ @import url('~@jupyterlab/application/style/index.css'); @import url('~@jupyterlab/cells/style/index.css'); @import url('~@jupyterlab/notebook/style/index.css'); +@import url('~@phosphor/widgets/style/index.css'); @import url('./base.css'); From 8613b24c3b09ebe7205787eeec2dfd11b5a5c72b Mon Sep 17 00:00:00 2001 From: markellekelly Date: Thu, 5 Dec 2019 17:46:32 -0800 Subject: [PATCH 16/21] css --- packages/celltags/style/index.css | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/celltags/style/index.css b/packages/celltags/style/index.css index 3b675404811b..b8a4c6f09b70 100644 --- a/packages/celltags/style/index.css +++ b/packages/celltags/style/index.css @@ -9,6 +9,5 @@ @import url('~@jupyterlab/application/style/index.css'); @import url('~@jupyterlab/cells/style/index.css'); @import url('~@jupyterlab/notebook/style/index.css'); -@import url('~@phosphor/widgets/style/index.css'); @import url('./base.css'); From 53b6da5a456656766c624fe669075b585033d72e Mon Sep 17 00:00:00 2001 From: markellekelly Date: Thu, 5 Dec 2019 17:52:06 -0800 Subject: [PATCH 17/21] removed comments/small fixes --- packages/celltags/src/addwidget.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 449b5a8afbc7..083254dbe611 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -42,7 +42,6 @@ export class AddWidget extends Widget { marginRight: '-5px' }); this.addClass('unapplied-tag'); - //this.button = img; tag.appendChild(img); this.node.appendChild(tag); } @@ -52,7 +51,6 @@ export class AddWidget extends Widget { */ onAfterAttach() { this.node.addEventListener('mousedown', this); - //this.button.addEventListener('mousedown', this); this.input.addEventListener('keydown', this); this.input.addEventListener('blur', this); } @@ -62,7 +60,6 @@ export class AddWidget extends Widget { */ onBeforeDetach() { this.node.removeEventListener('mousedown', this); - //this.button.removeEventListener('mousedown', this); this.input.removeEventListener('keydown', this); this.input.removeEventListener('blur', this); } @@ -86,7 +83,7 @@ export class AddWidget extends Widget { this._evtKeyDown(event as KeyboardEvent); break; case 'blur': - this._evtFocusOut(); + this._evtBlur(); break; default: break; @@ -125,7 +122,7 @@ export class AddWidget extends Widget { let value = this.input.value; (this.parent as TagTool).addTag(value); this.input.blur(); - this._evtFocusOut(); + this._evtBlur(); } } @@ -134,7 +131,7 @@ export class AddWidget extends Widget { * * @param event - The DOM event sent to the widget */ - private _evtFocusOut() { + private _evtBlur() { if (this.editing) { this.editing = false; this.input.value = 'Add Tag'; @@ -144,6 +141,5 @@ export class AddWidget extends Widget { public parent: TagTool; private editing: boolean; - //private button: HTMLElement; private input: HTMLInputElement; } From 8d9036ac6f1d373d3e4a9f06df1e35ce3f2f025f Mon Sep 17 00:00:00 2001 From: markellekelly Date: Thu, 5 Dec 2019 18:33:49 -0800 Subject: [PATCH 18/21] added functionality to plus button --- packages/celltags/src/addwidget.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 083254dbe611..3b97863c4090 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -100,6 +100,11 @@ export class AddWidget extends Widget { this.editing = true; this.input.value = ''; this.input.focus(); + } else if (event.target !== this.input) { + let value = this.input.value; + (this.parent as TagTool).addTag(value); + this.input.blur(); + this._evtBlur(); } event.preventDefault(); } From 8f57a9167490e228fd20639d1fb6897a028b603b Mon Sep 17 00:00:00 2001 From: markellekelly Date: Fri, 6 Dec 2019 12:02:17 -0800 Subject: [PATCH 19/21] fixed focus problem when changing tabs + removed console logs --- packages/celltags/src/addwidget.ts | 26 ++++++++++++++++++++++---- packages/celltags/src/tool.ts | 2 -- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 3b97863c4090..3088b5afdae1 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -52,6 +52,7 @@ export class AddWidget extends Widget { onAfterAttach() { this.node.addEventListener('mousedown', this); this.input.addEventListener('keydown', this); + this.input.addEventListener('focus', this); this.input.addEventListener('blur', this); } @@ -61,6 +62,7 @@ export class AddWidget extends Widget { onBeforeDetach() { this.node.removeEventListener('mousedown', this); this.input.removeEventListener('keydown', this); + this.input.removeEventListener('focus', this); this.input.removeEventListener('blur', this); } @@ -85,6 +87,9 @@ export class AddWidget extends Widget { case 'blur': this._evtBlur(); break; + case 'focus': + this._evtFocus(); + break; default: break; } @@ -101,14 +106,27 @@ export class AddWidget extends Widget { this.input.value = ''; this.input.focus(); } else if (event.target !== this.input) { - let value = this.input.value; - (this.parent as TagTool).addTag(value); - this.input.blur(); - this._evtBlur(); + if (this.input.value !== '') { + let value = this.input.value; + (this.parent as TagTool).addTag(value); + this.input.blur(); + this._evtBlur(); + } } event.preventDefault(); } + /** + * Handle the `'focus'` event for the input box. + * + * @param event - The DOM event sent to the widget + */ + private _evtFocus() { + if (!this.editing) { + this.input.blur(); + } + } + /** * Handle the `'keydown'` event for the input box. * diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index e4e8cf94dcf1..03ba10778423 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -78,7 +78,6 @@ export class TagTool extends NotebookTools.Tool { cell.model.metadata.set('tags', tags); this.refreshTags(); this.loadActiveTags(); - console.log(this.tracker.activeCell.model.metadata.get('tags')); } /** @@ -99,7 +98,6 @@ export class TagTool extends NotebookTools.Tool { } this.refreshTags(); this.loadActiveTags(); - console.log(this.tracker.activeCell.model.metadata.get('tags')); } /** From 8e59ea7cb696c0f3fa94ddfbae0576ca1dac2c50 Mon Sep 17 00:00:00 2001 From: telamonian Date: Sat, 7 Dec 2019 08:25:49 -0600 Subject: [PATCH 20/21] post rebase integrity in celltags --- packages/celltags-extension/package.json | 4 ++-- packages/celltags/package.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/celltags-extension/package.json b/packages/celltags-extension/package.json index 86d0cccefaa1..e2115030e098 100644 --- a/packages/celltags-extension/package.json +++ b/packages/celltags-extension/package.json @@ -38,9 +38,9 @@ "watch": "tsc -b --watch" }, "dependencies": { - "@jupyterlab/application": "^2.0.0-alpha.1", + "@jupyterlab/application": "^2.0.0-alpha.3", "@jupyterlab/celltags": "^0.1.0", - "@jupyterlab/notebook": "^2.0.0-alpha.1", + "@jupyterlab/notebook": "^2.0.0-alpha.3", "@types/node": "^12.0.2" }, "devDependencies": { diff --git a/packages/celltags/package.json b/packages/celltags/package.json index 3bf9e601dc2c..2fbd75efed97 100644 --- a/packages/celltags/package.json +++ b/packages/celltags/package.json @@ -39,10 +39,10 @@ "watch": "tsc -b --watch" }, "dependencies": { - "@jupyterlab/application": "^2.0.0-alpha.1", - "@jupyterlab/cells": "^2.0.0-alpha.1", - "@jupyterlab/notebook": "^2.0.0-alpha.1", - "@jupyterlab/ui-components": "^2.0.0-alpha.1", + "@jupyterlab/application": "^2.0.0-alpha.3", + "@jupyterlab/cells": "^2.0.0-alpha.3", + "@jupyterlab/notebook": "^2.0.0-alpha.3", + "@jupyterlab/ui-components": "^2.0.0-alpha.3", "@lumino/widgets": "^1.9.0", "@types/node": "^12.0.2" }, From 5067aed922d698663074e113b44ea7119b36662f Mon Sep 17 00:00:00 2001 From: markellekelly Date: Sat, 7 Dec 2019 10:46:12 -0800 Subject: [PATCH 21/21] fixed readmes, final code cleaning --- packages/celltags-extension/README.md | 5 +++-- packages/celltags/README.md | 5 +++-- packages/celltags/src/addwidget.ts | 4 ---- packages/celltags/src/tool.ts | 2 +- packages/celltags/src/widget.ts | 14 ++++---------- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/celltags-extension/README.md b/packages/celltags-extension/README.md index 2d45e2131d85..7a2c75e70730 100644 --- a/packages/celltags-extension/README.md +++ b/packages/celltags-extension/README.md @@ -1,3 +1,4 @@ -# celltags +# @jupyterlab/celltags-extension -A refactor of jupyterlab-celltags intended to be merged into core. +A JupyterLab extension which provides an entry point for +[@jupyterlab/celltags](../celltags). diff --git a/packages/celltags/README.md b/packages/celltags/README.md index 2d45e2131d85..52550c724dd1 100644 --- a/packages/celltags/README.md +++ b/packages/celltags/README.md @@ -1,3 +1,4 @@ -# celltags +# @jupyterlab/celltags -A refactor of jupyterlab-celltags intended to be merged into core. +A JupyterLab package which provides an interface for viewing and manipulating +descriptive tags in notebook cell metadata. diff --git a/packages/celltags/src/addwidget.ts b/packages/celltags/src/addwidget.ts index 3088b5afdae1..a8ae0e6b9dcc 100644 --- a/packages/celltags/src/addwidget.ts +++ b/packages/celltags/src/addwidget.ts @@ -118,8 +118,6 @@ export class AddWidget extends Widget { /** * Handle the `'focus'` event for the input box. - * - * @param event - The DOM event sent to the widget */ private _evtFocus() { if (!this.editing) { @@ -151,8 +149,6 @@ export class AddWidget extends Widget { /** * Handle the `'focusout'` event for the input box. - * - * @param event - The DOM event sent to the widget */ private _evtBlur() { if (this.editing) { diff --git a/packages/celltags/src/tool.ts b/packages/celltags/src/tool.ts index 03ba10778423..d9a797a6d35f 100644 --- a/packages/celltags/src/tool.ts +++ b/packages/celltags/src/tool.ts @@ -247,7 +247,7 @@ export class TagTool extends NotebookTools.Tool { this.validateTags(this.tracker.activeCell, taglist); } + public tracker: INotebookTracker = null; private tagList: string[] = []; private header: boolean = false; - public tracker: INotebookTracker = null; } diff --git a/packages/celltags/src/widget.ts b/packages/celltags/src/widget.ts index 434c12658793..1f8709933c43 100644 --- a/packages/celltags/src/widget.ts +++ b/packages/celltags/src/widget.ts @@ -83,10 +83,10 @@ export class TagWidget extends Widget { this._evtClick(); break; case 'mouseover': - this._evtMouseOver(event as MouseEvent); + this._evtMouseOver(); break; case 'mouseout': - this._evtMouseOut(event as MouseEvent); + this._evtMouseOut(); break; default: break; @@ -123,8 +123,6 @@ export class TagWidget extends Widget { /** * Handle the `'click'` event for the widget. - * - * @param event - The DOM event sent to the widget */ private _evtClick() { if (this.applied) { @@ -137,19 +135,15 @@ export class TagWidget extends Widget { /** * Handle the `'mouseover'` event for the widget. - * - * @param event - The DOM event sent to the widget */ - private _evtMouseOver(event: MouseEvent) { + private _evtMouseOver() { (this.node as HTMLElement).classList.add('tag-hover'); } /** * Handle the `'mouseout'` event for the widget. - * - * @param event - The DOM event sent to the widget */ - private _evtMouseOut(event: MouseEvent) { + private _evtMouseOut() { (this.node as HTMLElement).classList.remove('tag-hover'); }