From 9f3d46ddb17130b484218000d4048768fcb03e5f Mon Sep 17 00:00:00 2001 From: azivner Date: Thu, 25 Jan 2018 23:49:03 -0500 Subject: [PATCH] Allow marking code (JavaScript) notes for execution after application loads, closes #19 --- public/javascripts/init.js | 10 +++++++++- public/javascripts/note_editor.js | 10 +++++----- public/javascripts/utils.js | 4 ++++ routes/api/script.js | 21 +++++++++++++++++++++ services/attributes.js | 8 +++++++- views/index.ejs | 2 +- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/public/javascripts/init.js b/public/javascripts/init.js index 2d8934b5e..a76de2a28 100644 --- a/public/javascripts/init.js +++ b/public/javascripts/init.js @@ -202,4 +202,12 @@ window.onerror = function (msg, url, lineNo, columnNo, error) { return false; }; -$("#logout-button").toggle(!isElectron()); \ No newline at end of file +$("#logout-button").toggle(!isElectron()); + +$(document).ready(() => { + server.get("script/startup").then(scripts => { + for (const script of scripts) { + executeScript(script); + } + }); +}); \ No newline at end of file diff --git a/public/javascripts/note_editor.js b/public/javascripts/note_editor.js index a278ade4c..f8baf6efb 100644 --- a/public/javascripts/note_editor.js +++ b/public/javascripts/note_editor.js @@ -214,14 +214,14 @@ const noteEditor = (function() { return currentNote ? currentNote.detail.type : null; } - async function executeScript() { + async function executeCurrentNote() { if (getCurrentNoteType() === 'code') { // make sure note is saved so we load latest changes 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); }); - $(document).bind('keydown', "ctrl+return", executeScript); + $(document).bind('keydown', "ctrl+return", executeCurrentNote); setInterval(saveNoteIfChanged, 5000); @@ -281,6 +281,6 @@ const noteEditor = (function() { newNoteCreated, getEditor, focus, - executeScript + executeCurrentNote }; })(); \ No newline at end of file diff --git a/public/javascripts/utils.js b/public/javascripts/utils.js index 5347ec53b..e5ff83f88 100644 --- a/public/javascripts/utils.js +++ b/public/javascripts/utils.js @@ -113,4 +113,8 @@ async function stopWatch(what, func) { console.log(`${what} took ${tookMs}ms`); return ret; +} + +function executeScript(script) { + eval("(async function() {" + script + "})()"); } \ No newline at end of file diff --git a/routes/api/script.js b/routes/api/script.js index c0c5f1bd1..9bdded223 100644 --- a/routes/api/script.js +++ b/routes/api/script.js @@ -8,6 +8,7 @@ const log = require('../../services/log'); const sql = require('../../services/sql'); const notes = require('../../services/notes'); const protected_session = require('../../services/protected_session'); +const attributes = require('../../services/attributes'); router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { log.info('Executing script: ' + req.body.script); @@ -19,6 +20,18 @@ router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { 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) => { const noteId = req.params.noteId; @@ -29,6 +42,14 @@ router.get('/subtree/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => 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) { 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) diff --git a/services/attributes.js b/services/attributes.js index 73297baca..1f1eac455 100644 --- a/services/attributes.js +++ b/services/attributes.js @@ -9,10 +9,15 @@ async function getNoteAttributeMap(noteId) { } 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]); } +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) { const now = utils.nowDate(); const attributeId = utils.newAttributeId(); @@ -32,5 +37,6 @@ async function createAttribute(noteId, name, value = null, sourceId = null) { module.exports = { getNoteAttributeMap, getNoteIdWithAttribute, + getNoteIdsWithAttribute, createAttribute }; \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index def22fa5b..573769696 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -98,7 +98,7 @@ + onclick="noteEditor.executeCurrentNote()">Execute Ctrl+Enter