mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	Allow marking code (JavaScript) notes for execution after application loads, closes #19
This commit is contained in:
		| @@ -203,3 +203,11 @@ window.onerror = function (msg, url, lineNo, columnNo, error) { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| $("#logout-button").toggle(!isElectron()); | $("#logout-button").toggle(!isElectron()); | ||||||
|  |  | ||||||
|  | $(document).ready(() => { | ||||||
|  |     server.get("script/startup").then(scripts => { | ||||||
|  |         for (const script of scripts) { | ||||||
|  |             executeScript(script); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | }); | ||||||
| @@ -214,14 +214,14 @@ const noteEditor = (function() { | |||||||
|         return currentNote ? currentNote.detail.type : null; |         return currentNote ? currentNote.detail.type : null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async function executeScript() { |     async function executeCurrentNote() { | ||||||
|         if (getCurrentNoteType() === 'code') { |         if (getCurrentNoteType() === 'code') { | ||||||
|             // make sure note is saved so we load latest changes |             // make sure note is saved so we load latest changes | ||||||
|             await saveNoteIfChanged(); |             await saveNoteIfChanged(); | ||||||
|  |  | ||||||
|             const subTreeScripts = await server.get('script/subtree/' + getCurrentNoteId()); |             const script = await server.get('script/subtree/' + getCurrentNoteId()); | ||||||
|  |  | ||||||
|             eval("(async function() {" + subTreeScripts + "})()"); |             executeScript(script); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -263,7 +263,7 @@ const noteEditor = (function() { | |||||||
|         noteDetailEl.attr("tabindex", 2); |         noteDetailEl.attr("tabindex", 2); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     $(document).bind('keydown', "ctrl+return", executeScript); |     $(document).bind('keydown', "ctrl+return", executeCurrentNote); | ||||||
|  |  | ||||||
|     setInterval(saveNoteIfChanged, 5000); |     setInterval(saveNoteIfChanged, 5000); | ||||||
|  |  | ||||||
| @@ -281,6 +281,6 @@ const noteEditor = (function() { | |||||||
|         newNoteCreated, |         newNoteCreated, | ||||||
|         getEditor, |         getEditor, | ||||||
|         focus, |         focus, | ||||||
|         executeScript |         executeCurrentNote | ||||||
|     }; |     }; | ||||||
| })(); | })(); | ||||||
| @@ -114,3 +114,7 @@ async function stopWatch(what, func) { | |||||||
|  |  | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function executeScript(script) { | ||||||
|  |     eval("(async function() {" + script + "})()"); | ||||||
|  | } | ||||||
| @@ -8,6 +8,7 @@ const log = require('../../services/log'); | |||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const notes = require('../../services/notes'); | const notes = require('../../services/notes'); | ||||||
| const protected_session = require('../../services/protected_session'); | const protected_session = require('../../services/protected_session'); | ||||||
|  | const attributes = require('../../services/attributes'); | ||||||
|  |  | ||||||
| router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { | router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||||
|     log.info('Executing script: ' + req.body.script); |     log.info('Executing script: ' + req.body.script); | ||||||
| @@ -19,6 +20,18 @@ router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { | |||||||
|     res.send(ret); |     res.send(ret); | ||||||
| })); | })); | ||||||
|  |  | ||||||
|  | router.get('/startup', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||||
|  |     const noteIds = await attributes.getNoteIdsWithAttribute("run_on_startup"); | ||||||
|  |  | ||||||
|  |     const scripts = []; | ||||||
|  |  | ||||||
|  |     for (const noteId of noteIds) { | ||||||
|  |         scripts.push(await getNoteWithSubtreeScript(noteId, req)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     res.send(scripts); | ||||||
|  | })); | ||||||
|  |  | ||||||
| router.get('/subtree/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { | router.get('/subtree/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||||
|     const noteId = req.params.noteId; |     const noteId = req.params.noteId; | ||||||
|  |  | ||||||
| @@ -29,6 +42,14 @@ router.get('/subtree/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => | |||||||
|     res.send(subTreeScripts + noteScript); |     res.send(subTreeScripts + noteScript); | ||||||
| })); | })); | ||||||
|  |  | ||||||
|  | async function getNoteWithSubtreeScript(noteId, req) { | ||||||
|  |     const noteScript = (await notes.getNoteById(noteId, req)).note_text; | ||||||
|  |  | ||||||
|  |     const subTreeScripts = await getSubTreeScripts(noteId, [noteId], req); | ||||||
|  |  | ||||||
|  |     return subTreeScripts + noteScript; | ||||||
|  | } | ||||||
|  |  | ||||||
| async function getSubTreeScripts(parentId, includedNoteIds, dataKey) { | async function getSubTreeScripts(parentId, includedNoteIds, dataKey) { | ||||||
|     const children = await sql.getAll(`SELECT notes.note_id, notes.note_title, notes.note_text, notes.is_protected  |     const children = await sql.getAll(`SELECT notes.note_id, notes.note_title, notes.note_text, notes.is_protected  | ||||||
|                                      FROM notes JOIN notes_tree USING(note_id) |                                      FROM notes JOIN notes_tree USING(note_id) | ||||||
|   | |||||||
| @@ -9,10 +9,15 @@ async function getNoteAttributeMap(noteId) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function getNoteIdWithAttribute(name, value) { | async function getNoteIdWithAttribute(name, value) { | ||||||
|     return await sql.getFirstValue(`SELECT notes.note_id FROM notes JOIN attributes USING(note_id)  |     return await sql.getFirstValue(`SELECT DISTINCT notes.note_id FROM notes JOIN attributes USING(note_id)  | ||||||
|           WHERE notes.is_deleted = 0 AND attributes.name = ? AND attributes.value = ?`, [name, value]); |           WHERE notes.is_deleted = 0 AND attributes.name = ? AND attributes.value = ?`, [name, value]); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function getNoteIdsWithAttribute(name) { | ||||||
|  |     return await sql.getFirstColumn(`SELECT DISTINCT notes.note_id FROM notes JOIN attributes USING(note_id)  | ||||||
|  |           WHERE notes.is_deleted = 0 AND attributes.name = ?`, [name]); | ||||||
|  | } | ||||||
|  |  | ||||||
| async function createAttribute(noteId, name, value = null, sourceId = null) { | async function createAttribute(noteId, name, value = null, sourceId = null) { | ||||||
|     const now = utils.nowDate(); |     const now = utils.nowDate(); | ||||||
|     const attributeId = utils.newAttributeId(); |     const attributeId = utils.newAttributeId(); | ||||||
| @@ -32,5 +37,6 @@ async function createAttribute(noteId, name, value = null, sourceId = null) { | |||||||
| module.exports = { | module.exports = { | ||||||
|     getNoteAttributeMap, |     getNoteAttributeMap, | ||||||
|     getNoteIdWithAttribute, |     getNoteIdWithAttribute, | ||||||
|  |     getNoteIdsWithAttribute, | ||||||
|     createAttribute |     createAttribute | ||||||
| }; | }; | ||||||
| @@ -98,7 +98,7 @@ | |||||||
|           <button class="btn btn-sm" |           <button class="btn btn-sm" | ||||||
|                   style="display: none; margin-right: 10px" |                   style="display: none; margin-right: 10px" | ||||||
|                   id="execute-script-button" |                   id="execute-script-button" | ||||||
|                   onclick="noteEditor.executeScript()">Execute <kbd>Ctrl+Enter</kbd></button> |                   onclick="noteEditor.executeCurrentNote()">Execute <kbd>Ctrl+Enter</kbd></button> | ||||||
|  |  | ||||||
|           <div class="dropdown" id="note-type"> |           <div class="dropdown" id="note-type"> | ||||||
|             <button id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm"> |             <button id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm"> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user