loading of custom widgets

This commit is contained in:
zadam 2019-08-17 11:28:36 +02:00
parent 53c4bb8a94
commit fd9b79e115
7 changed files with 63 additions and 12 deletions

View file

@ -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<Note[]>}
*/
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<Attribute[]>} all note's relation definitions including inherited ones

View file

@ -196,12 +196,27 @@ class NoteShort {
/**
* @param {string} name
* @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found)
* @returns {Promise<NoteShort>|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<NoteShort[]>}
*/
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;
}
/**

View file

@ -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) {

View file

@ -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.
*

View file

@ -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}`);
}
}
}

View file

@ -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}`);

View file

@ -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(', ') + `));
`;