From fd9b79e1152b65e9baf6803e21576730ecc2c69b Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 17 Aug 2019 11:28:36 +0200 Subject: [PATCH] loading of custom widgets --- src/entities/note.js | 15 +++++++++++ src/public/javascripts/entities/note_short.js | 21 +++++++++++++--- src/public/javascripts/services/bundle.js | 2 +- .../services/frontend_script_api.js | 8 ++++-- src/public/javascripts/services/sidebar.js | 25 +++++++++++++++---- .../javascripts/services/tab_context.js | 3 ++- src/services/script.js | 1 + 7 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/entities/note.js b/src/entities/note.js index 6b938158f..860888929 100644 --- a/src/entities/note.js +++ b/src/entities/note.js @@ -248,6 +248,21 @@ class Note extends Entity { return (await this.getAttributes(name)).filter(attr => attr.type === RELATION); } + /** + * @param {string} [name] - relation name to filter + * @returns {Promise} + */ + async getRelationTargets(name) { + const relations = await this.getRelations(name); + const targets = []; + + for (const relation of relations) { + targets.push(await relation.getTargetNote()); + } + + return targets; + } + /** * @param {string} [name] - relation name to filter * @returns {Promise} all note's relation definitions including inherited ones diff --git a/src/public/javascripts/entities/note_short.js b/src/public/javascripts/entities/note_short.js index bdb53af31..2c983bd67 100644 --- a/src/public/javascripts/entities/note_short.js +++ b/src/public/javascripts/entities/note_short.js @@ -196,12 +196,27 @@ class NoteShort { /** * @param {string} name - * @returns {Promise|null} target note of the relation or null (if target is empty or note was not found) + * @returns {Promise|null} target note of the relation or null (if target is empty or note was not found) */ async getRelationTarget(name) { - const relation = await this.getRelation(name); + const targets = await this.getRelationTargets(name); - return relation ? await repository.getNote(relation.value) : null; + return targets.length > 0 ? targets[0] : null; + } + + /** + * @param {string} [name] - relation name to filter + * @returns {Promise} + */ + async getRelationTargets(name) { + const relations = await this.getRelations(name); + const targets = []; + + for (const relation of relations) { + targets.push(await this.treeCache.getNote(relation.value)); + } + + return targets; } /** diff --git a/src/public/javascripts/services/bundle.js b/src/public/javascripts/services/bundle.js index 13b01910d..796c10e6e 100644 --- a/src/public/javascripts/services/bundle.js +++ b/src/public/javascripts/services/bundle.js @@ -5,7 +5,7 @@ import infoService from "./info.js"; async function getAndExecuteBundle(noteId, originEntity = null) { const bundle = await server.get('script/bundle/' + noteId); - await executeBundle(bundle, originEntity); + return await executeBundle(bundle, originEntity); } async function executeBundle(bundle, originEntity, tabContext) { diff --git a/src/public/javascripts/services/frontend_script_api.js b/src/public/javascripts/services/frontend_script_api.js index ff83baab1..13d29f20d 100644 --- a/src/public/javascripts/services/frontend_script_api.js +++ b/src/public/javascripts/services/frontend_script_api.js @@ -7,8 +7,9 @@ import treeCache from './tree_cache.js'; import noteDetailService from './note_detail.js'; import noteTypeService from './note_type.js'; import noteTooltipService from './note_tooltip.js'; -import protectedSessionService from'./protected_session.js'; -import dateNotesService from'./date_notes.js'; +import protectedSessionService from './protected_session.js'; +import dateNotesService from './date_notes.js'; +import StandardWidget from '../widgets/standard_widget.js'; /** * This is the main frontend API interface for scripts. It's published in the local "api" object. @@ -32,6 +33,9 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte /** @property {TabContext|null} - experimental! */ this.tabContext = tabContext; + /** @property {StandardWidget} */ + this.StandardWidget = StandardWidget; + /** * Activates note in the tree and in the note detail. * diff --git a/src/public/javascripts/services/sidebar.js b/src/public/javascripts/services/sidebar.js index ed0f416e9..bb8436203 100644 --- a/src/public/javascripts/services/sidebar.js +++ b/src/public/javascripts/services/sidebar.js @@ -2,6 +2,8 @@ import NoteInfoWidget from "../widgets/note_info.js"; import LinkMapWidget from "../widgets/link_map.js"; import NoteRevisionsWidget from "../widgets/note_revisions.js"; import AttributesWidget from "../widgets/attributes.js"; +import bundleService from "./bundle.js"; +import messagingService from "./messaging.js"; class Sidebar { /** @@ -9,6 +11,7 @@ class Sidebar { * @param {object} state */ constructor(ctx, state = {}) { + /** @property {TabContext} */ this.ctx = ctx; this.state = state; this.widgets = []; @@ -51,15 +54,27 @@ class Sidebar { const widgetClasses = [AttributesWidget, LinkMapWidget, NoteRevisionsWidget, NoteInfoWidget]; + const widgetRelations = await this.ctx.note.getRelations('widget'); + + for (const widgetRelation of widgetRelations) { + const widgetClass = await bundleService.getAndExecuteBundle(widgetRelation.value, this.ctx.note); + + widgetClasses.push(widgetClass); + } + for (const widgetClass of widgetClasses) { const state = (this.state.widgets || []).find(s => s.name === widgetClass.name); - const widget = new widgetClass(this.ctx, state); - this.widgets.push(widget); + try { + const widget = new widgetClass(this.ctx, state); + await widget.renderBody(); - widget.renderBody(); // let it run in parallel - - this.$widgetContainer.append(widget.getWidgetElement()); + this.widgets.push(widget); + this.$widgetContainer.append(widget.getWidgetElement()); + } + catch (e) { + messagingService.logError(`Error while loading widget ${widgetClass.name}: ${e.message}`); + } } } diff --git a/src/public/javascripts/services/tab_context.js b/src/public/javascripts/services/tab_context.js index 31879f093..1afeb1361 100644 --- a/src/public/javascripts/services/tab_context.js +++ b/src/public/javascripts/services/tab_context.js @@ -106,6 +106,7 @@ class TabContext { setNote(note, notePath) { this.noteId = note.noteId; this.notePath = notePath; + /** @property {NoteFull} */ this.note = note; this.tabRow.updateTab(this.$tab[0], {title: note.title}); @@ -136,7 +137,7 @@ class TabContext { this.showPaths(); if (this.sidebar) { - this.sidebar.noteLoaded(); + this.sidebar.noteLoaded(); // load async } console.debug(`Switched tab ${this.tabId} to ${this.noteId}`); diff --git a/src/services/script.js b/src/services/script.js index 91872b00a..85c02aef5 100644 --- a/src/services/script.js +++ b/src/services/script.js @@ -161,6 +161,7 @@ ${await note.getContent()}; } catch (e) { throw new Error("Load of script note \\"${note.title}\\" (${note.noteId}) failed with: " + e.message); } if (!module.exports) module.exports = {}; for (const exportKey in exports) module.exports[exportKey] = exports[exportKey]; +return module.exports; }).call({}, {}, apiContext.modules['${note.noteId}'], apiContext.require(${JSON.stringify(moduleNoteIds)}), apiContext.apis['${note.noteId}']` + (modules.length > 0 ? ', ' : '') + modules.map(mod => `apiContext.modules['${mod.noteId}'].exports`).join(', ') + `)); `;