Allow marking code (JavaScript) notes for execution after application loads, closes #19

This commit is contained in:
azivner 2018-01-25 23:49:03 -05:00
parent a42fd9b090
commit 9f3d46ddb1
6 changed files with 47 additions and 8 deletions

View File

@ -202,4 +202,12 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
return false; return false;
}; };
$("#logout-button").toggle(!isElectron()); $("#logout-button").toggle(!isElectron());
$(document).ready(() => {
server.get("script/startup").then(scripts => {
for (const script of scripts) {
executeScript(script);
}
});
});

View File

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

View File

@ -113,4 +113,8 @@ async function stopWatch(what, func) {
console.log(`${what} took ${tookMs}ms`); console.log(`${what} took ${tookMs}ms`);
return ret; return ret;
}
function executeScript(script) {
eval("(async function() {" + script + "})()");
} }

View File

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

View File

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

View File

@ -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">