mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
#125, basic infrastructure for scripts attached to notes via relations
This commit is contained in:
parent
ededc063df
commit
170d317589
@ -1,8 +1,14 @@
|
|||||||
import ScriptContext from "./script_context.js";
|
import ScriptContext from "./script_context.js";
|
||||||
import server from "./server.js";
|
import server from "./server.js";
|
||||||
|
|
||||||
async function executeBundle(bundle) {
|
async function getAndExecuteBundle(noteId, targetNote = null) {
|
||||||
const apiContext = ScriptContext(bundle.note, bundle.allNotes);
|
const bundle = await server.get('script/bundle/' + noteId);
|
||||||
|
|
||||||
|
await executeBundle(bundle, targetNote);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function executeBundle(bundle, targetNote) {
|
||||||
|
const apiContext = ScriptContext(bundle.note, bundle.allNotes, targetNote);
|
||||||
|
|
||||||
return await (function () {
|
return await (function () {
|
||||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||||
@ -19,5 +25,6 @@ async function executeStartupBundles() {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
executeBundle,
|
executeBundle,
|
||||||
|
getAndExecuteBundle,
|
||||||
executeStartupBundles
|
executeStartupBundles
|
||||||
}
|
}
|
@ -15,6 +15,7 @@ import noteDetailText from './note_detail_text.js';
|
|||||||
import noteDetailFile from './note_detail_file.js';
|
import noteDetailFile from './note_detail_file.js';
|
||||||
import noteDetailSearch from './note_detail_search.js';
|
import noteDetailSearch from './note_detail_search.js';
|
||||||
import noteDetailRender from './note_detail_render.js';
|
import noteDetailRender from './note_detail_render.js';
|
||||||
|
import bundleService from "./bundle.js";
|
||||||
|
|
||||||
const $noteTitle = $("#note-title");
|
const $noteTitle = $("#note-title");
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ const $labelListInner = $("#label-list-inner");
|
|||||||
const $relationList = $("#relation-list");
|
const $relationList = $("#relation-list");
|
||||||
const $relationListInner = $("#relation-list-inner");
|
const $relationListInner = $("#relation-list-inner");
|
||||||
const $childrenOverview = $("#children-overview");
|
const $childrenOverview = $("#children-overview");
|
||||||
|
const $scriptArea = $("#note-detail-script-area");
|
||||||
|
|
||||||
let currentNote = null;
|
let currentNote = null;
|
||||||
|
|
||||||
@ -144,6 +146,8 @@ async function handleProtectedSession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadNoteDetail(noteId) {
|
async function loadNoteDetail(noteId) {
|
||||||
|
$scriptArea.html('');
|
||||||
|
|
||||||
currentNote = await loadNote(noteId);
|
currentNote = await loadNote(noteId);
|
||||||
|
|
||||||
if (isNewNoteCreated) {
|
if (isNewNoteCreated) {
|
||||||
@ -183,10 +187,15 @@ async function loadNoteDetail(noteId) {
|
|||||||
|
|
||||||
const labels = await loadLabelList();
|
const labels = await loadLabelList();
|
||||||
|
|
||||||
loadRelationList(); // no need to wait
|
|
||||||
|
|
||||||
const hideChildrenOverview = labels.some(label => label.name === 'hideChildrenOverview');
|
const hideChildrenOverview = labels.some(label => label.name === 'hideChildrenOverview');
|
||||||
await showChildrenOverview(hideChildrenOverview);
|
await showChildrenOverview(hideChildrenOverview);
|
||||||
|
|
||||||
|
const relations = await loadRelationList();
|
||||||
|
const relationsToRun = relations.filter(relation => relation.name === 'runOnNoteView');
|
||||||
|
|
||||||
|
for (const relationToRun of relationsToRun) {
|
||||||
|
await bundleService.getAndExecuteBundle(relationToRun.targetNoteId, getCurrentNote());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showChildrenOverview(hideChildrenOverview) {
|
async function showChildrenOverview(hideChildrenOverview) {
|
||||||
|
@ -2,8 +2,9 @@ import treeService from './tree.js';
|
|||||||
import server from './server.js';
|
import server from './server.js';
|
||||||
import utils from './utils.js';
|
import utils from './utils.js';
|
||||||
import infoService from './info.js';
|
import infoService from './info.js';
|
||||||
|
import linkService from './link.js';
|
||||||
|
|
||||||
function ScriptApi(startNote, currentNote) {
|
function ScriptApi(startNote, currentNote, targetNote = null) {
|
||||||
const $pluginButtons = $("#plugin-buttons");
|
const $pluginButtons = $("#plugin-buttons");
|
||||||
|
|
||||||
async function activateNote(notePath) {
|
async function activateNote(notePath) {
|
||||||
@ -42,7 +43,8 @@ function ScriptApi(startNote, currentNote) {
|
|||||||
script: script,
|
script: script,
|
||||||
params: prepareParams(params),
|
params: prepareParams(params),
|
||||||
startNoteId: startNote.noteId,
|
startNoteId: startNote.noteId,
|
||||||
currentNoteId: currentNote.noteId
|
currentNoteId: currentNote.noteId,
|
||||||
|
targetNoteId: targetNote ? targetNote.noteId : null
|
||||||
});
|
});
|
||||||
|
|
||||||
return ret.executionResult;
|
return ret.executionResult;
|
||||||
@ -51,6 +53,7 @@ function ScriptApi(startNote, currentNote) {
|
|||||||
return {
|
return {
|
||||||
startNote: startNote,
|
startNote: startNote,
|
||||||
currentNote: currentNote,
|
currentNote: currentNote,
|
||||||
|
targetNote: targetNote,
|
||||||
addButtonToToolbar,
|
addButtonToToolbar,
|
||||||
activateNote,
|
activateNote,
|
||||||
getInstanceName: () => window.glob.instanceName,
|
getInstanceName: () => window.glob.instanceName,
|
||||||
@ -59,7 +62,8 @@ function ScriptApi(startNote, currentNote) {
|
|||||||
parseDate: utils.parseDate,
|
parseDate: utils.parseDate,
|
||||||
showMessage: infoService.showMessage,
|
showMessage: infoService.showMessage,
|
||||||
showError: infoService.showError,
|
showError: infoService.showError,
|
||||||
reloadTree: treeService.reload
|
reloadTree: treeService.reload,
|
||||||
|
createNoteLink: linkService.createNoteLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import ScriptApi from './script_api.js';
|
import ScriptApi from './script_api.js';
|
||||||
import utils from './utils.js';
|
import utils from './utils.js';
|
||||||
|
|
||||||
function ScriptContext(startNote, allNotes) {
|
function ScriptContext(startNote, allNotes, targetNote = null) {
|
||||||
const modules = {};
|
const modules = {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modules: modules,
|
modules: modules,
|
||||||
notes: utils.toObject(allNotes, note => [note.noteId, note]),
|
notes: utils.toObject(allNotes, note => [note.noteId, note]),
|
||||||
apis: utils.toObject(allNotes, note => [note.noteId, ScriptApi(startNote, note)]),
|
apis: utils.toObject(allNotes, note => [note.noteId, ScriptApi(startNote, note, targetNote)]),
|
||||||
require: moduleNoteIds => {
|
require: moduleNoteIds => {
|
||||||
return moduleName => {
|
return moduleName => {
|
||||||
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
||||||
|
@ -5,7 +5,8 @@ const scriptService = require('../../services/script');
|
|||||||
const repository = require('../../services/repository');
|
const repository = require('../../services/repository');
|
||||||
|
|
||||||
async function exec(req) {
|
async function exec(req) {
|
||||||
const result = await scriptService.executeScript(req.body.script, req.body.params, req.body.startNoteId, req.body.currentNoteId);
|
const result = await scriptService.executeScript(req.body.script, req.body.params, req.body.startNoteId,
|
||||||
|
req.body.currentNoteId, req.body.targetNoteId);
|
||||||
|
|
||||||
return { executionResult: result };
|
return { executionResult: result };
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ async function executeNote(note) {
|
|||||||
await executeBundle(bundle);
|
await executeBundle(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function executeBundle(bundle, startNote) {
|
async function executeBundle(bundle, startNote, targetNote = null) {
|
||||||
if (!startNote) {
|
if (!startNote) {
|
||||||
// this is the default case, the only exception is when we want to preserve frontend startNote
|
// this is the default case, the only exception is when we want to preserve frontend startNote
|
||||||
startNote = bundle.note;
|
startNote = bundle.note;
|
||||||
@ -23,7 +23,7 @@ async function executeBundle(bundle, startNote) {
|
|||||||
// last \r\n is necessary if script contains line comment on its last line
|
// last \r\n is necessary if script contains line comment on its last line
|
||||||
const script = "async function() {\r\n" + bundle.script + "\r\n}";
|
const script = "async function() {\r\n" + bundle.script + "\r\n}";
|
||||||
|
|
||||||
const ctx = new ScriptContext(startNote, bundle.allNotes);
|
const ctx = new ScriptContext(startNote, bundle.allNotes, targetNote);
|
||||||
|
|
||||||
if (await bundle.note.hasLabel('manualTransactionHandling')) {
|
if (await bundle.note.hasLabel('manualTransactionHandling')) {
|
||||||
return await execute(ctx, script, '');
|
return await execute(ctx, script, '');
|
||||||
@ -37,9 +37,10 @@ async function executeBundle(bundle, startNote) {
|
|||||||
* This method preserves frontend startNode - that's why we start execution from currentNote and override
|
* This method preserves frontend startNode - that's why we start execution from currentNote and override
|
||||||
* bundle's startNote.
|
* bundle's startNote.
|
||||||
*/
|
*/
|
||||||
async function executeScript(script, params, startNoteId, currentNoteId) {
|
async function executeScript(script, params, startNoteId, currentNoteId, targetNoteId) {
|
||||||
const startNote = await repository.getNote(startNoteId);
|
const startNote = await repository.getNote(startNoteId);
|
||||||
const currentNote = await repository.getNote(currentNoteId);
|
const currentNote = await repository.getNote(currentNoteId);
|
||||||
|
const targetNote = await repository.getNote(targetNoteId);
|
||||||
|
|
||||||
currentNote.content = `return await (${script}\r\n)(${getParams(params)})`;
|
currentNote.content = `return await (${script}\r\n)(${getParams(params)})`;
|
||||||
currentNote.type = 'code';
|
currentNote.type = 'code';
|
||||||
@ -47,7 +48,7 @@ async function executeScript(script, params, startNoteId, currentNoteId) {
|
|||||||
|
|
||||||
const bundle = await getScriptBundle(currentNote);
|
const bundle = await getScriptBundle(currentNote);
|
||||||
|
|
||||||
return await executeBundle(bundle, startNote);
|
return await executeBundle(bundle, startNote, targetNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function execute(ctx, script, paramsStr) {
|
async function execute(ctx, script, paramsStr) {
|
||||||
|
@ -9,10 +9,10 @@ const config = require('./config');
|
|||||||
const repository = require('./repository');
|
const repository = require('./repository');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
function ScriptContext(startNote, allNotes) {
|
function ScriptContext(startNote, allNotes, targetNote = null) {
|
||||||
this.modules = {};
|
this.modules = {};
|
||||||
this.notes = utils.toObject(allNotes, note => [note.noteId, note]);
|
this.notes = utils.toObject(allNotes, note => [note.noteId, note]);
|
||||||
this.apis = utils.toObject(allNotes, note => [note.noteId, new ScriptApi(startNote, note)]);
|
this.apis = utils.toObject(allNotes, note => [note.noteId, new ScriptApi(startNote, note, targetNote)]);
|
||||||
this.require = moduleNoteIds => {
|
this.require = moduleNoteIds => {
|
||||||
return moduleName => {
|
return moduleName => {
|
||||||
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
||||||
@ -27,9 +27,10 @@ function ScriptContext(startNote, allNotes) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScriptApi(startNote, currentNote) {
|
function ScriptApi(startNote, currentNote, targetNote) {
|
||||||
this.startNote = startNote;
|
this.startNote = startNote;
|
||||||
this.currentNote = currentNote;
|
this.currentNote = currentNote;
|
||||||
|
this.targetNote = targetNote;
|
||||||
|
|
||||||
this.axios = axios;
|
this.axios = axios;
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ function ScriptApi(startNote, currentNote) {
|
|||||||
this.getNote = repository.getNote;
|
this.getNote = repository.getNote;
|
||||||
this.getBranch = repository.getBranch;
|
this.getBranch = repository.getBranch;
|
||||||
this.getLabel = repository.getLabel;
|
this.getLabel = repository.getLabel;
|
||||||
|
this.getRelation = repository.getRelation;
|
||||||
this.getImage = repository.getImage;
|
this.getImage = repository.getImage;
|
||||||
this.getEntity = repository.getEntity;
|
this.getEntity = repository.getEntity;
|
||||||
this.getEntities = repository.getEntities;
|
this.getEntities = repository.getEntities;
|
||||||
|
@ -180,6 +180,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="note-detail-wrapper">
|
<div id="note-detail-wrapper">
|
||||||
|
<div id="note-detail-script-area"></div>
|
||||||
|
|
||||||
<div id="note-detail-component-wrapper">
|
<div id="note-detail-component-wrapper">
|
||||||
<div id="note-detail-text" class="note-detail-component" tabindex="2"></div>
|
<div id="note-detail-text" class="note-detail-component" tabindex="2"></div>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user