diff --git a/notes/!!!meta.json b/notes/!!!meta.json new file mode 100644 index 0000000..863f4dc --- /dev/null +++ b/notes/!!!meta.json @@ -0,0 +1,511 @@ +{ + "formatVersion": 1, + "appVersion": "0.46.9", + "files": [ + { + "isClone": false, + "noteId": "vP5DkrdHVvv0", + "notePath": [ + "vP5DkrdHVvv0" + ], + "title": "Implementation", + "notePosition": 50, + "prefix": null, + "isExpanded": 1, + "type": "text", + "mime": "text/html", + "attributes": [], + "format": "html", + "dirFileName": "Implementation", + "children": [ + { + "isClone": false, + "noteId": "dDCKmKnFWfrk", + "notePath": [ + "vP5DkrdHVvv0", + "dDCKmKnFWfrk" + ], + "title": "attribute changed", + "notePosition": 0, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=backend", + "attributes": [], + "dataFileName": "attribute changed.js", + "dirFileName": "attribute changed", + "children": [ + { + "isClone": false, + "noteId": "Xv1GdWl4UvVO", + "notePath": [ + "vP5DkrdHVvv0", + "dDCKmKnFWfrk", + "Xv1GdWl4UvVO" + ], + "title": "reconcileAssignments", + "notePosition": 0, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=backend", + "attributes": [], + "dataFileName": "reconcileAssignments.js" + } + ] + }, + { + "isClone": false, + "noteId": "1d9ya4XfzQP2", + "notePath": [ + "vP5DkrdHVvv0", + "1d9ya4XfzQP2" + ], + "title": "button", + "notePosition": 10, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=frontend", + "attributes": [ + { + "type": "label", + "name": "run", + "value": "frontendStartup", + "isInheritable": false, + "position": 0 + } + ], + "dataFileName": "button.js" + }, + { + "isClone": false, + "noteId": "hvYOnJwamlAm", + "notePath": [ + "vP5DkrdHVvv0", + "hvYOnJwamlAm" + ], + "title": "CSS", + "notePosition": 20, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "text/css", + "attributes": [ + { + "type": "label", + "name": "appCss", + "value": "", + "isInheritable": false, + "position": 0 + } + ], + "dataFileName": "CSS.css" + }, + { + "isClone": false, + "noteId": "wYT6EyWoF0Qg", + "notePath": [ + "vP5DkrdHVvv0", + "wYT6EyWoF0Qg" + ], + "title": "task template", + "notePosition": 30, + "prefix": null, + "isExpanded": 0, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "label", + "name": "label:tag", + "value": "promoted,multi,text", + "isInheritable": false, + "position": 10 + }, + { + "type": "label", + "name": "cssClass", + "value": "todo", + "isInheritable": false, + "position": 20 + }, + { + "type": "label", + "name": "label:location", + "value": "promoted,single,text", + "isInheritable": false, + "position": 30 + }, + { + "type": "label", + "name": "label:todoDate", + "value": "promoted,single,date", + "isInheritable": false, + "position": 40 + }, + { + "type": "label", + "name": "label:todoTime", + "value": "promoted,single,text", + "isInheritable": false, + "position": 50 + }, + { + "type": "label", + "name": "label:doneDate", + "value": "promoted,single,date", + "isInheritable": false, + "position": 60 + }, + { + "type": "label", + "name": "label:canceled", + "value": "promoted,single,boolean", + "isInheritable": false, + "position": 70 + } + ], + "format": "html", + "dataFileName": "task template.html" + }, + { + "isClone": false, + "noteId": "zzJx2J4CLv9y", + "notePath": [ + "vP5DkrdHVvv0", + "zzJx2J4CLv9y" + ], + "title": "new_reminder handler", + "notePosition": 40, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=backend", + "attributes": [ + { + "type": "label", + "name": "customRequestHandler", + "value": "new_reminder", + "isInheritable": false, + "position": 20 + }, + { + "type": "relation", + "name": "targetTemplate", + "value": "LBDjD6rGxw6I", + "isInheritable": false, + "position": 10 + } + ], + "dataFileName": "new_reminder handler.js" + }, + { + "isClone": false, + "noteId": "UNuCNmOMROgz", + "notePath": [ + "vP5DkrdHVvv0", + "UNuCNmOMROgz" + ], + "title": "task_alerts handler", + "notePosition": 50, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=backend", + "attributes": [ + { + "type": "label", + "name": "customRequestHandler", + "value": "task_alerts", + "isInheritable": false, + "position": 10 + }, + { + "type": "relation", + "name": "targetTemplate", + "value": "wYT6EyWoF0Qg", + "isInheritable": false, + "position": 20 + }, + { + "type": "relation", + "name": "targetTemplateReminder", + "value": "LBDjD6rGxw6I", + "isInheritable": false, + "position": 30 + }, + { + "type": "relation", + "name": "targetTemplateReminderDaily", + "value": "7Wzjk70ySoKm", + "isInheritable": false, + "position": 40 + } + ], + "dataFileName": "task_alerts handler.js" + }, + { + "isClone": false, + "noteId": "LBDjD6rGxw6I", + "notePath": [ + "vP5DkrdHVvv0", + "LBDjD6rGxw6I" + ], + "title": "reminder template", + "notePosition": 60, + "prefix": null, + "isExpanded": 0, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "relation", + "name": "template", + "value": "wYT6EyWoF0Qg", + "isInheritable": false, + "position": 10 + }, + { + "type": "label", + "name": "reminder", + "value": "true", + "isInheritable": true, + "position": 20 + }, + { + "type": "label", + "name": "iconClass", + "value": "bx bx-alarm", + "isInheritable": true, + "position": 30 + }, + { + "type": "label", + "name": "cssClass", + "value": "reminder", + "isInheritable": false, + "position": 40 + } + ], + "format": "html", + "dataFileName": "reminder template.html" + }, + { + "isClone": false, + "noteId": "7Wzjk70ySoKm", + "notePath": [ + "vP5DkrdHVvv0", + "7Wzjk70ySoKm" + ], + "title": "daily reminder template", + "notePosition": 61, + "prefix": null, + "isExpanded": 0, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "label", + "name": "iconClass", + "value": "bx bx-alarm", + "isInheritable": true, + "position": 10 + }, + { + "type": "label", + "name": "cssClass", + "value": "reminder", + "isInheritable": false, + "position": 20 + }, + { + "type": "label", + "name": "label:todoTime", + "value": "promoted,single,text", + "isInheritable": false, + "position": 30 + }, + { + "type": "label", + "name": "reminder", + "value": "true", + "isInheritable": true, + "position": 40 + } + ], + "format": "html", + "dataFileName": "daily reminder template.html" + }, + { + "isClone": false, + "noteId": "XE5kBjusNVkY", + "notePath": [ + "vP5DkrdHVvv0", + "XE5kBjusNVkY" + ], + "title": "attribute sync button", + "notePosition": 80, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=frontend", + "attributes": [ + { + "type": "label", + "name": "run", + "value": "frontendStartup", + "isInheritable": false, + "position": 10 + } + ], + "dataFileName": "attribute sync button.js", + "dirFileName": "attribute sync button", + "children": [ + { + "isClone": true, + "noteId": "Xv1GdWl4UvVO", + "notePath": [ + "vP5DkrdHVvv0", + "XE5kBjusNVkY", + "Xv1GdWl4UvVO" + ], + "title": "reconcileAssignments", + "prefix": "", + "dataFileName": "reconcileAssignments.clone.html", + "type": "text", + "format": "html" + } + ] + }, + { + "isClone": false, + "noteId": "X5pzYZriILAz", + "notePath": [ + "vP5DkrdHVvv0", + "X5pzYZriILAz" + ], + "title": "event template", + "notePosition": 90, + "prefix": null, + "isExpanded": 0, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "label", + "name": "label:location", + "value": "promoted,single,text", + "isInheritable": false, + "position": 10 + }, + { + "type": "label", + "name": "label:startTime", + "value": "promoted,single,text", + "isInheritable": false, + "position": 20 + }, + { + "type": "label", + "name": "label:endTime", + "value": "promoted,single,text", + "isInheritable": false, + "position": 30 + }, + { + "type": "label", + "name": "iconClass", + "value": "bx bx-calendar-event", + "isInheritable": true, + "position": 40 + }, + { + "type": "label", + "name": "label:uid", + "value": "single,text", + "isInheritable": false, + "position": 50 + } + ], + "format": "html", + "dataFileName": "event template.html" + }, + { + "isClone": false, + "noteId": "Qfv3H8TfLqzA", + "notePath": [ + "vP5DkrdHVvv0", + "Qfv3H8TfLqzA" + ], + "title": "new_event handler", + "notePosition": 100, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=backend", + "attributes": [ + { + "type": "label", + "name": "customRequestHandler", + "value": "new_event", + "isInheritable": false, + "position": 10 + }, + { + "type": "relation", + "name": "targetTemplate", + "value": "X5pzYZriILAz", + "isInheritable": false, + "position": 20 + } + ], + "dataFileName": "new_event handler.js" + }, + { + "isClone": false, + "noteId": "rvu9Tix6GYYx", + "notePath": [ + "vP5DkrdHVvv0", + "rvu9Tix6GYYx" + ], + "title": "event_alerts handler", + "notePosition": 110, + "prefix": null, + "isExpanded": 0, + "type": "code", + "mime": "application/javascript;env=backend", + "attributes": [ + { + "type": "label", + "name": "customRequestHandler", + "value": "event_alerts", + "isInheritable": false, + "position": 20 + }, + { + "type": "relation", + "name": "targetTemplateEvent", + "value": "X5pzYZriILAz", + "isInheritable": false, + "position": 10 + } + ], + "dataFileName": "event_alerts handler.js" + } + ] + }, + { + "noImport": true, + "dataFileName": "navigation.html" + }, + { + "noImport": true, + "dataFileName": "index.html" + }, + { + "noImport": true, + "dataFileName": "style.css" + } + ] +} \ No newline at end of file diff --git a/notes/Implementation/CSS.css b/notes/Implementation/CSS.css new file mode 100644 index 0000000..4d4b43b --- /dev/null +++ b/notes/Implementation/CSS.css @@ -0,0 +1,7 @@ +span.fancytree-node.todo .fancytree-title { + color: red !important; +} + +span.fancytree-node.done .fancytree-title { + color: green !important; +} \ No newline at end of file diff --git a/notes/Implementation/attribute changed.js b/notes/Implementation/attribute changed.js new file mode 100644 index 0000000..a734304 --- /dev/null +++ b/notes/Implementation/attribute changed.js @@ -0,0 +1,48 @@ +if (!["task", "location", "tag", "todoDate", "doneDate"].includes(api.originEntity.name)) { + return; +} + +const note = await api.originEntity.getNote(); + +const attributes = await note.getAttributes(); + +if (attributes.filter(attr => attr.type === 'label' && attr.name === 'reminder').map(attr => attr.value).length() > 0) { + api.log("ignoring"); + return; +} + +const todoDate = await note.getLabelValue('todoDate'); +const doneDate = await note.getLabelValue('doneDate'); +const canceled = !!(await note.getLabelValue('canceled')); +const isTaskDone = !!doneDate; + +const canceledRootNote = await api.getNoteWithLabel('taskDoneRoot'); +await api.toggleNoteInParent(canceled, note.noteId, canceledRootNote.noteId); + +const doneRootNote = await api.getNoteWithLabel('taskDoneRoot'); +await api.toggleNoteInParent(isTaskDone && !canceled, note.noteId, doneRootNote.noteId); + +const todoRootNote = await api.getNoteWithLabel('taskTodoRoot'); +await api.toggleNoteInParent(!isTaskDone && !canceled, note.noteId, todoRootNote.noteId); + +const location = await note.getLabelValue('location'); +const locationRootNote = await api.getNoteWithLabel('taskLocationRoot'); + +await reconcileAssignments(note, locationRootNote, location ? [location] : [], 'taskLocationNote', isTaskDone); + +const tags = attributes.filter(attr => attr.type === 'label' && attr.name === 'tag').map(attr => attr.value); +const tagRootNote = await api.getNoteWithLabel('taskTagRoot'); + +await reconcileAssignments(note, tagRootNote, tags, 'taskTagNote', isTaskDone); + +await note.toggleLabel(isTaskDone || canceled, "cssClass", "done"); + +const doneTargetNoteId = isTaskDone ? (await api.getDateNote(doneDate)).noteId : null; +await api.setNoteToParent(note.noteId, 'DONE', doneTargetNoteId); + +await note.toggleLabel(!isTaskDone && !canceled, "cssClass", "todo"); + +const todoTargetNoteId = (!isTaskDone && !canceled && todoDate) ? (await api.getDateNote(todoDate)).noteId : null; +await api.setNoteToParent(note.noteId, 'TODO', todoTargetNoteId); + +api.refreshTree(); \ No newline at end of file diff --git a/notes/Implementation/attribute changed/reconcileAssignments.js b/notes/Implementation/attribute changed/reconcileAssignments.js new file mode 100644 index 0000000..310f219 --- /dev/null +++ b/notes/Implementation/attribute changed/reconcileAssignments.js @@ -0,0 +1,25 @@ +module.exports = async function(note, categoryRootNote, assignedCategories, labelName, isTaskDone) { + const found = {}; + + for (const categoryNote of await categoryRootNote.getChildNotes()) { + const label = await categoryNote.getLabel(labelName); + + if (label) { + found[label.value] = !isTaskDone && assignedCategories.includes(label.value); + + await api.toggleNoteInParent(found[label.value], note.noteId, categoryNote.noteId); + } + } + + if (!isTaskDone) { + for (const assignedCategory of assignedCategories) { + if (!found[assignedCategory]) { + const categoryNote = (await api.createNote(categoryRootNote.noteId, assignedCategory, "", { + attributes: [ { type: "label", name: labelName, value: assignedCategory } ] + })).note; + + await api.ensureNoteIsPresentInParent(note.noteId, categoryNote.noteId); + } + } + } +} \ No newline at end of file diff --git a/notes/Implementation/attribute sync button.js b/notes/Implementation/attribute sync button.js new file mode 100644 index 0000000..807d4a7 --- /dev/null +++ b/notes/Implementation/attribute sync button.js @@ -0,0 +1,44 @@ +api.addButtonToToolbar({ + title: 'Sync task', + icon: 'sync', + action: async () => { + await api.runOnBackend(async (noteId) => { +const note = await api.getNote(noteId); +const attributes = await note.getAttributes(); +const todoDate = await note.getLabelValue('todoDate'); +const doneDate = await note.getLabelValue('doneDate'); +const canceled = !!(await note.getLabelValue('canceled')); +api.log(canceled); +const isTaskDone = !!doneDate; + +const canceledRootNote = await api.getNoteWithLabel('taskCanceledRoot'); +await api.toggleNoteInParent(canceled, note.noteId, canceledRootNote.noteId); + +const doneRootNote = await api.getNoteWithLabel('taskDoneRoot'); +await api.toggleNoteInParent(isTaskDone && !canceled, note.noteId, doneRootNote.noteId); + +const todoRootNote = await api.getNoteWithLabel('taskTodoRoot'); +await api.toggleNoteInParent(!isTaskDone && !canceled, note.noteId, todoRootNote.noteId); + +const location = await note.getLabelValue('location'); +const locationRootNote = await api.getNoteWithLabel('taskLocationRoot'); + +await reconcileAssignments(note, locationRootNote, location ? [location] : [], 'taskLocationNote', isTaskDone); + +const tags = attributes.filter(attr => attr.type === 'label' && attr.name === 'tag').map(attr => attr.value); +const tagRootNote = await api.getNoteWithLabel('taskTagRoot'); + +await reconcileAssignments(note, tagRootNote, tags, 'taskTagNote', isTaskDone); + +await note.toggleLabel(isTaskDone || canceled, "cssClass", "done"); + +const doneTargetNoteId = (isTaskDone && !canceled) ? (await api.getDateNote(doneDate)).noteId : null; +await api.setNoteToParent(note.noteId, 'DONE', doneTargetNoteId); + +await note.toggleLabel(!isTaskDone && !canceled, "cssClass", "todo"); + +const todoTargetNoteId = ((!isTaskDone || canceled) && todoDate) ? (await api.getDateNote(todoDate)).noteId : null; +await api.setNoteToParent(note.noteId, 'TODO', todoTargetNoteId); + }, [api.getActiveTabNote().noteId]); + } +}); \ No newline at end of file diff --git a/notes/Implementation/attribute sync button/reconcileAssignments.clone.html b/notes/Implementation/attribute sync button/reconcileAssignments.clone.html new file mode 100644 index 0000000..f0e986b --- /dev/null +++ b/notes/Implementation/attribute sync button/reconcileAssignments.clone.html @@ -0,0 +1,16 @@ + + + + + + + + + + +

reconcileAssignments

+ +

This is a clone of a note. Go to its primary location.

+ + + \ No newline at end of file diff --git a/notes/Implementation/button.js b/notes/Implementation/button.js new file mode 100644 index 0000000..e81217d --- /dev/null +++ b/notes/Implementation/button.js @@ -0,0 +1,19 @@ +api.addButtonToToolbar({ + title: 'New task', + icon: 'check', + shortcut: 'alt+n', + action: async () => { + // creating notes is backend (server) responsibility so we need to pass + // the control there + const taskNoteId = await api.runOnServer(async () => { + const todoRootNote = await api.getNoteWithLabel('taskTodoRoot'); + const resp = await api.createTextNote(todoRootNote.noteId, 'new task', ''); + + return resp.note.noteId; + }); + + await api.waitUntilSynced(); + // we got an ID of newly created note and we want to immediatelly display it + await api.activateNewNote(taskNoteId); + } +}); \ No newline at end of file diff --git a/notes/Implementation/daily reminder template.html b/notes/Implementation/daily reminder template.html new file mode 100644 index 0000000..85f51e1 --- /dev/null +++ b/notes/Implementation/daily reminder template.html @@ -0,0 +1,15 @@ + + + + + + + + + + +

daily reminder template

+ + + + \ No newline at end of file diff --git a/notes/Implementation/event template.html b/notes/Implementation/event template.html new file mode 100644 index 0000000..368700d --- /dev/null +++ b/notes/Implementation/event template.html @@ -0,0 +1,15 @@ + + + + + + + + + + +

event template

+ + + + \ No newline at end of file diff --git a/event_alerts.js b/notes/Implementation/event_alerts handler.js similarity index 55% rename from event_alerts.js rename to notes/Implementation/event_alerts handler.js index d90e406..a7cbd6f 100644 --- a/event_alerts.js +++ b/notes/Implementation/event_alerts handler.js @@ -1,11 +1,3 @@ -// Create as JS Backend note and add these attributes: -// ~targetTemplateEvent=@event template (this note is described below) -// #customRequestHandler=event_alerts -// Create another note (event template) with this promoted attributes: -// startTime -// Optionally add: -// endTime, location - const {req, res} = api; const targetTemplate = await api.currentNote.getRelationValue("targetTemplateEvent"); @@ -21,4 +13,4 @@ for (const event of events) { }); } -res.send(eventsData); +res.send(eventsData); \ No newline at end of file diff --git a/notes/Implementation/new_event handler.js b/notes/Implementation/new_event handler.js new file mode 100644 index 0000000..80c9901 --- /dev/null +++ b/notes/Implementation/new_event handler.js @@ -0,0 +1,54 @@ +function formatTime(startTime) { + return startTime.getFullYear().toString() + "-" + (startTime.getMonth() + 1).toString().padStart(2, "0") + "-" + startTime.getDate().toString().padStart(2, "0") + "T" + startTime.getHours().toString().padStart(2, "0") + ":" + startTime.getMinutes().toString().padStart(2, "0") + ":" + startTime.getSeconds().toString().padStart(2, "0"); +} + +const {req, res} = api; + +const uid = req.body["uid"]; +const name = req.body["name"]; +const summary = req.body["summary"]; +const location = req.body["location"]; +const fileName = req.body["fileName"]; +const fileData = req.body["fileData"]; +const startTime = new Date(req.body["startTime"]); +const endTime = new Date(req.body["endTime"]); + +const year = startTime.getFullYear(); +var month = startTime.getMonth() + 1; +var day = startTime.getDate(); + +if (month < 10) { + month = '0' + month; +} +if (day < 10) { + day = '0' + day; +} + +const eventDateStr = year + "-" + month + "-" + day; +const dayNote = await api.getDateNote(eventDateStr); + +const targetTemplate = await api.currentNote.getRelationValue('targetTemplate'); +const options = { + "parentNoteId": dayNote.noteId, + "title": name, + "content": summary, + "type": "text" +}; +const resp = await api.createNewNote(options); +const note = resp.note; +await note.setAttribute("relation", "template", targetTemplate); +await note.setAttribute("label", "uid", uid); +await note.setAttribute("label", "location", location); +const startTimeStr = formatTime(startTime); +await note.setAttribute("label", "startTime", startTimeStr); +await note.setAttribute("label", "endTime", formatTime(endTime)); +const fileOptions = { + "parentNoteId": note.noteId, + "title": fileName, + "content": fileData, + "type": "file", + "mime": "text/calendar" +}; +await api.createNewNote(fileOptions); + +res.sendStatus(200); diff --git a/new_reminder.js b/notes/Implementation/new_reminder handler.js similarity index 81% rename from new_reminder.js rename to notes/Implementation/new_reminder handler.js index ba46259..add3dbd 100644 --- a/new_reminder.js +++ b/notes/Implementation/new_reminder handler.js @@ -1,12 +1,3 @@ -// Create as JS Backend note with these attributes: -// ~targetTemplate=@reminder template -// #customRequestHandler=new_reminder -// Create a new note (reminder template) with these promoted attributes: -// todoDate: date -// todoTime: text -// doneDate: date -// reminder = true - Date.prototype.addHours = function(h) { this.setTime(this.getTime() + (h*60*60*1000)); return this; @@ -46,6 +37,8 @@ if (day < 10) { const todayDateStr = year + "-" + month + "-" + day; const todayNote = await api.getDateNote(todayDateStr); +//const templateNoteId = 'LBDjD6rGxw6I'; +//const templateNote = await api.getNote('LBDjD6rGxw6I'); const targetTemplate = await api.currentNote.getAttributeValue('relation', 'targetTemplate'); const resp = await api.createNote( todayNote.noteId, diff --git a/notes/Implementation/reminder template.html b/notes/Implementation/reminder template.html new file mode 100644 index 0000000..f34e589 --- /dev/null +++ b/notes/Implementation/reminder template.html @@ -0,0 +1,15 @@ + + + + + + + + + + +

reminder template

+ + + + \ No newline at end of file diff --git a/notes/Implementation/task template.html b/notes/Implementation/task template.html new file mode 100644 index 0000000..7ed37c9 --- /dev/null +++ b/notes/Implementation/task template.html @@ -0,0 +1,15 @@ + + + + + + + + + + +

task template

+ + + + \ No newline at end of file diff --git a/notes/Implementation/task_alerts handler.js b/notes/Implementation/task_alerts handler.js new file mode 100644 index 0000000..85d91c8 --- /dev/null +++ b/notes/Implementation/task_alerts handler.js @@ -0,0 +1,56 @@ +const {req, res} = api; + +const today = new Date().toISOString().substr(0, 10); + +const targetTemplate = await api.currentNote.getRelationValue('targetTemplate'); +const tasks = await api.getNotesWithLabel("template", targetTemplate); + +let tasksData = []; + +for (const task of tasks) { + const todoDate = task.getAttribute("label", "todoDate"); + if (!todoDate || todoDate["value"] < today) { + continue; + } + tasksData.push({ + attributes: await task.getAttributes(), + ...task + }); +} + +const targetTemplateReminder = await api.currentNote.getRelationValue('targetTemplateReminder'); +const reminders = await api.getNotesWithLabel("template", targetTemplateReminder); +for (const task of reminders) { + const todoDate = task.getAttribute("label", "todoDate"); + if (!todoDate || todoDate["value"] < today) { + continue; + } + tasksData.push({ + attributes: await task.getAttributes(), + ...task + }); +} + +const targetTemplateReminderDaily = await api.currentNote.getRelationValue('targetTemplateReminderDaily'); +const remindersDaily = await api.getNotesWithLabel("template", targetTemplateReminderDaily); +for (const task of remindersDaily) { + const attributes = await task.getAttributes(); + attributes.push({ + "type": "label", + "name": "todoDate", + "value": today, + // API compliance + "attributeId": "", + "noteId": "", + "position": 0, + "utcDateModified": "2021-04-23 08:20:14.295Z", + "isDeleted": false, + "isInheritable": false + }); + tasksData.push({ + attributes: attributes, + ...task + }); +} + +res.send(tasksData); diff --git a/notes/index.html b/notes/index.html new file mode 100644 index 0000000..a3ecbc3 --- /dev/null +++ b/notes/index.html @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/notes/navigation.html b/notes/navigation.html new file mode 100644 index 0000000..f5a878e --- /dev/null +++ b/notes/navigation.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/notes/style.css b/notes/style.css new file mode 100644 index 0000000..2ff1779 --- /dev/null +++ b/notes/style.css @@ -0,0 +1,339 @@ +/* !!!!!! TRILIUM CUSTOM CHANGES !!!!!! */ + +.printed-content .ck-widget__selection-handle, .printed-content .ck-widget__type-around { /* gets rid of triangles: https://github.com/zadam/trilium/issues/1129 */ + display: none; +} + +/* + * CKEditor 5 (v24.0.0) content styles. + * Generated on Thu, 10 Dec 2020 08:15:26 GMT. + * For more information, check out https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/content-styles.html + */ + +:root { + --ck-color-mention-background: hsla(341, 100%, 30%, 0.1); + --ck-color-mention-text: hsl(341, 100%, 30%); + --ck-highlight-marker-blue: hsl(201, 97%, 72%); + --ck-highlight-marker-green: hsl(120, 93%, 68%); + --ck-highlight-marker-pink: hsl(345, 96%, 73%); + --ck-highlight-marker-yellow: hsl(60, 97%, 73%); + --ck-highlight-pen-green: hsl(112, 100%, 27%); + --ck-highlight-pen-red: hsl(0, 85%, 49%); + --ck-image-style-spacing: 1.5em; + --ck-todo-list-checkmark-size: 16px; +} + +/* ckeditor5-image/theme/imageresize.css */ +.ck-content .image.image_resized { + max-width: 100%; + display: block; + box-sizing: border-box; +} +/* ckeditor5-image/theme/imageresize.css */ +.ck-content .image.image_resized img { + width: 100%; +} +/* ckeditor5-image/theme/imageresize.css */ +.ck-content .image.image_resized > figcaption { + display: block; +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-side { + float: right; + margin-left: var(--ck-image-style-spacing); + max-width: 50%; +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-align-left { + float: left; + margin-right: var(--ck-image-style-spacing); +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-align-center { + margin-left: auto; + margin-right: auto; +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-align-right { + float: right; + margin-left: var(--ck-image-style-spacing); +} +/* ckeditor5-image/theme/image.css */ +.ck-content .image { + display: table; + clear: both; + text-align: center; + margin: 1em auto; +} +/* ckeditor5-image/theme/image.css */ +.ck-content .image img { + display: block; + margin: 0 auto; + max-width: 100%; + min-width: 50px; +} +/* ckeditor5-image/theme/imagecaption.css */ +.ck-content .image > figcaption { + display: table-caption; + caption-side: bottom; + word-break: break-word; + color: hsl(0, 0%, 20%); + background-color: hsl(0, 0%, 97%); + padding: .6em; + font-size: .75em; + outline-offset: -1px; +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-yellow { + background-color: var(--ck-highlight-marker-yellow); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-green { + background-color: var(--ck-highlight-marker-green); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-pink { + background-color: var(--ck-highlight-marker-pink); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-blue { + background-color: var(--ck-highlight-marker-blue); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .pen-red { + color: var(--ck-highlight-pen-red); + background-color: transparent; +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .pen-green { + color: var(--ck-highlight-pen-green); + background-color: transparent; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-tiny { + font-size: .7em; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-small { + font-size: .85em; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-big { + font-size: 1.4em; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-huge { + font-size: 1.8em; +} +/* ckeditor5-block-quote/theme/blockquote.css */ +.ck-content blockquote { + overflow: hidden; + padding-right: 1.5em; + padding-left: 1.5em; + margin-left: 0; + margin-right: 0; + font-style: italic; + border-left: solid 5px hsl(0, 0%, 80%); +} +/* ckeditor5-block-quote/theme/blockquote.css */ +.ck-content[dir="rtl"] blockquote { + border-left: 0; + border-right: solid 5px hsl(0, 0%, 80%); +} +/* ckeditor5-basic-styles/theme/code.css */ +.ck-content code { + background-color: hsla(0, 0%, 78%, 0.3); + padding: .15em; + border-radius: 2px; +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table { + margin: 1em auto; + display: table; +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table table { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + height: 100%; + border: 1px double hsl(0, 0%, 70%); +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table table td, +.ck-content .table table th { + min-width: 2em; + padding: .4em; + border: 1px solid hsl(0, 0%, 75%); +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table table th { + font-weight: bold; + background: hsla(0, 0%, 0%, 5%); +} +/* ckeditor5-table/theme/table.css */ +.ck-content[dir="rtl"] .table th { + text-align: right; +} +/* ckeditor5-table/theme/table.css */ +.ck-content[dir="ltr"] .table th { + text-align: left; +} +/* ckeditor5-page-break/theme/pagebreak.css */ +.ck-content .page-break { + position: relative; + clear: both; + padding: 5px 0; + display: flex; + align-items: center; + justify-content: center; +} +/* ckeditor5-page-break/theme/pagebreak.css */ +.ck-content .page-break::after { + content: ''; + position: absolute; + border-bottom: 2px dashed hsl(0, 0%, 77%); + width: 100%; +} +/* ckeditor5-page-break/theme/pagebreak.css */ +.ck-content .page-break__label { + position: relative; + z-index: 1; + padding: .3em .6em; + display: block; + text-transform: uppercase; + border: 1px solid hsl(0, 0%, 77%); + border-radius: 2px; + font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif; + font-size: 0.75em; + font-weight: bold; + color: hsl(0, 0%, 20%); + background: hsl(0, 0%, 100%); + box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +/* ckeditor5-media-embed/theme/mediaembed.css */ +.ck-content .media { + clear: both; + margin: 1em 0; + display: block; + min-width: 15em; +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list { + list-style: none; +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list li { + margin-bottom: 5px; +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list li .todo-list { + margin-top: 5px; +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list .todo-list__label > input { + -webkit-appearance: none; + display: inline-block; + position: relative; + width: var(--ck-todo-list-checkmark-size); + height: var(--ck-todo-list-checkmark-size); + vertical-align: middle; + border: 0; + left: -25px; + margin-right: -15px; + right: 0; + margin-left: 0; +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list .todo-list__label > input::before { + display: block; + position: absolute; + box-sizing: border-box; + content: ''; + width: 100%; + height: 100%; + border: 1px solid hsl(0, 0%, 20%); + border-radius: 2px; + transition: 250ms ease-in-out box-shadow, 250ms ease-in-out background, 250ms ease-in-out border; +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list .todo-list__label > input::after { + display: block; + position: absolute; + box-sizing: content-box; + pointer-events: none; + content: ''; + left: calc( var(--ck-todo-list-checkmark-size) / 3 ); + top: calc( var(--ck-todo-list-checkmark-size) / 5.3 ); + width: calc( var(--ck-todo-list-checkmark-size) / 5.3 ); + height: calc( var(--ck-todo-list-checkmark-size) / 2.6 ); + border-style: solid; + border-color: transparent; + border-width: 0 calc( var(--ck-todo-list-checkmark-size) / 8 ) calc( var(--ck-todo-list-checkmark-size) / 8 ) 0; + transform: rotate(45deg); +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list .todo-list__label > input[checked]::before { + background: hsl(126, 64%, 41%); + border-color: hsl(126, 64%, 41%); +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list .todo-list__label > input[checked]::after { + border-color: hsl(0, 0%, 100%); +} +/* ckeditor5-list/theme/todolist.css */ +.ck-content .todo-list .todo-list__label .todo-list__label__description { + vertical-align: middle; +} +/* ckeditor5-html-embed/theme/htmlembed.css */ +.ck-content .raw-html-embed { + margin: 1em auto; + min-width: 15em; + font-style: normal; +} +/* ckeditor5-horizontal-line/theme/horizontalline.css */ +.ck-content hr { + margin: 15px 0; + height: 4px; + background: hsl(0, 0%, 87%); + border: 0; +} +/* ckeditor5-code-block/theme/codeblock.css */ +.ck-content pre { + padding: 1em; + color: hsl(0, 0%, 20.8%); + background: hsla(0, 0%, 78%, 0.3); + border: 1px solid hsl(0, 0%, 77%); + border-radius: 2px; + text-align: left; + direction: ltr; + tab-size: 4; + white-space: pre-wrap; + font-style: normal; + min-width: 200px; +} +/* ckeditor5-code-block/theme/codeblock.css */ +.ck-content pre code { + background: unset; + padding: 0; + border-radius: 0; +} +/* ckeditor5-mention/theme/mention.css */ +.ck-content .mention { + background: var(--ck-color-mention-background); + color: var(--ck-color-mention-text); +} +@media print { + /* ckeditor5-page-break/theme/pagebreak.css */ + .ck-content .page-break { + padding: 0; + } + /* ckeditor5-page-break/theme/pagebreak.css */ + .ck-content .page-break::after { + display: none; + } +} diff --git a/task_alerts.js b/task_alerts.js deleted file mode 100644 index 04218ea..0000000 --- a/task_alerts.js +++ /dev/null @@ -1,29 +0,0 @@ -// Create as JS Backend note with attributes: -// ~targetTemplate=@task template (included in Trilium task manager) -// #customRequestHandler=task_alerts -// ~targetTemplateReminder=@reminder template (see new_reminder.js) - -const {req, res} = api; - -const targetTemplate = await api.currentNote.getRelationValue('targetTemplate'); -const tasks = await api.getNotesWithLabel("template", targetTemplate); - -let tasksData = []; - -for (const task of tasks) { - tasksData.push({ - attributes: await task.getAttributes(), - ...task - }); -} - -const targetTemplateReminder = await api.currentNote.getRelationValue('targetTemplateReminder'); -const reminders = await api.getNotesWithLabel("template", targetTemplateReminder); -for (const task of reminders) { - tasksData.push({ - attributes: await task.getAttributes(), - ...task - }); -} - -res.send(tasksData);