Notes/src/services/special_notes.js

287 lines
8.5 KiB
JavaScript
Raw Normal View History

const attributeService = require("./attributes");
const dateNoteService = require("./date_notes");
const becca = require("../becca/becca");
const noteService = require("./notes");
const cls = require("./cls");
const dateUtils = require("./date_utils");
const log = require("./log");
2022-12-07 12:46:41 +01:00
const hiddenSubtreeService = require("./hidden_subtree");
2022-12-21 16:11:00 +01:00
const searchService = require("./search/services/search");
const SearchContext = require("./search/search_context");
const {LBTPL_NOTE_LAUNCHER, LBTPL_CUSTOM_WIDGET, LBTPL_SPACER, LBTPL_SCRIPT} = require("./hidden_subtree");
2022-11-28 23:39:23 +01:00
function getInboxNote(date) {
const hoistedNote = getHoistedNote();
let inbox;
if (!hoistedNote.isRoot()) {
inbox = hoistedNote.searchNoteInSubtree('#hoistedInbox');
if (!inbox) {
inbox = hoistedNote.searchNoteInSubtree('#inbox');
}
if (!inbox) {
inbox = hoistedNote;
}
}
else {
inbox = attributeService.getNoteWithLabel('inbox')
2022-01-10 17:09:20 +01:00
|| dateNoteService.getDayNote(date);
}
return inbox;
}
function createSqlConsole() {
const {note} = noteService.createNewNote({
2022-12-21 16:11:00 +01:00
parentNoteId: getMonthlyParentNoteId('_sqlConsole'),
title: 'SQL Console',
content: "SELECT title, isDeleted, isProtected FROM notes WHERE noteId = ''\n\n\n\n",
type: 'code',
mime: 'text/x-sqlite;schema=trilium'
});
2022-12-21 16:11:00 +01:00
note.setLabel('_sqlConsole', dateUtils.localNowDate());
2022-11-25 15:29:57 +01:00
note.setLabel('iconClass', 'bx bx-data');
2022-12-14 10:29:14 +01:00
note.setLabel('keepCurrentHoisting');
return note;
}
function saveSqlConsole(sqlConsoleNoteId) {
const sqlConsoleNote = becca.getNote(sqlConsoleNoteId);
const today = dateUtils.localNowDate();
const sqlConsoleHome =
attributeService.getNoteWithLabel('sqlConsoleHome')
2022-01-10 17:09:20 +01:00
|| dateNoteService.getDayNote(today);
const result = sqlConsoleNote.cloneTo(sqlConsoleHome.noteId);
for (const parentBranch of sqlConsoleNote.getParentBranches()) {
2022-12-21 16:11:00 +01:00
if (parentBranch.parentNote.hasAncestor('_hidden')) {
parentBranch.markAsDeleted();
}
}
return result;
}
function createSearchNote(searchString, ancestorNoteId) {
const {note} = noteService.createNewNote({
2022-12-21 16:11:00 +01:00
parentNoteId: getMonthlyParentNoteId('_search'),
title: `Search: ${searchString}`,
content: "",
type: 'search',
mime: 'application/json'
});
note.setLabel('searchString', searchString);
2022-12-14 10:29:14 +01:00
note.setLabel('keepCurrentHoisting');
if (ancestorNoteId) {
note.setRelation('ancestor', ancestorNoteId);
}
return note;
}
function getSearchHome() {
const hoistedNote = getHoistedNote();
if (!hoistedNote.isRoot()) {
return hoistedNote.searchNoteInSubtree('#hoistedSearchHome')
|| hoistedNote.searchNoteInSubtree('#searchHome')
|| hoistedNote;
} else {
const today = dateUtils.localNowDate();
return hoistedNote.searchNoteInSubtree('#searchHome')
2022-01-10 17:09:20 +01:00
|| dateNoteService.getDayNote(today);
}
}
function saveSearchNote(searchNoteId) {
const searchNote = becca.getNote(searchNoteId);
const searchHome = getSearchHome();
const result = searchNote.cloneTo(searchHome.noteId);
for (const parentBranch of searchNote.getParentBranches()) {
2022-12-21 16:11:00 +01:00
if (parentBranch.parentNote.hasAncestor('_hidden')) {
parentBranch.markAsDeleted();
}
}
return result;
}
2022-12-15 16:38:05 +01:00
function getMonthlyParentNoteId(rootNoteId) {
const month = dateUtils.localNowDate().substring(0, 7);
const labelName = `${rootNoteId}MonthNote`;
let monthNote = searchService.findFirstNoteWithQuery(`#${labelName}="${month}"`,
new SearchContext({ancestorNoteId: rootNoteId}));
if (!monthNote) {
monthNote = noteService.createNewNote({
parentNoteId: rootNoteId,
title: month,
content: '',
isProtected: false,
type: 'book'
}).note
monthNote.addLabel(labelName, month);
}
return monthNote.noteId;
}
function getHoistedNote() {
return becca.getNote(cls.getHoistedNoteId());
}
2022-12-22 14:57:00 +01:00
function createScriptLauncher(parentNoteId, forceId = null) {
const note = noteService.createNewNote({
2022-12-22 14:57:00 +01:00
noteId: forceId,
branchId: forceId,
title: "Script Launcher",
type: 'launcher',
content: '',
parentNoteId: parentNoteId
}).note;
2022-12-21 16:11:00 +01:00
note.addRelation('template', LBTPL_SCRIPT);
return note;
}
2022-12-22 14:57:00 +01:00
function createLauncher({parentNoteId, launcherType, id}) {
2022-08-07 15:34:59 +02:00
let note;
2022-12-01 10:16:57 +01:00
if (launcherType === 'note') {
2022-08-07 15:34:59 +02:00
note = noteService.createNewNote({
2022-12-22 14:57:00 +01:00
noteId: id,
branchId: id,
2022-12-07 12:46:41 +01:00
title: "Note Launcher",
2022-12-01 10:16:57 +01:00
type: 'launcher',
2022-08-07 15:34:59 +02:00
content: '',
parentNoteId: parentNoteId
}).note;
2022-11-29 16:16:57 +01:00
2022-12-21 16:11:00 +01:00
note.addRelation('template', LBTPL_NOTE_LAUNCHER);
2022-12-01 10:16:57 +01:00
} else if (launcherType === 'script') {
2022-12-22 14:57:00 +01:00
note = createScriptLauncher(parentNoteId, id);
2022-12-01 10:16:57 +01:00
} else if (launcherType === 'customWidget') {
2022-08-07 15:34:59 +02:00
note = noteService.createNewNote({
2022-12-22 14:57:00 +01:00
noteId: id,
branchId: id,
2022-12-07 12:46:41 +01:00
title: "Widget Launcher",
2022-12-01 10:16:57 +01:00
type: 'launcher',
2022-08-07 15:34:59 +02:00
content: '',
parentNoteId: parentNoteId
}).note;
2022-12-21 16:11:00 +01:00
note.addRelation('template', LBTPL_CUSTOM_WIDGET);
2022-12-01 10:16:57 +01:00
} else if (launcherType === 'spacer') {
2022-08-07 15:34:59 +02:00
note = noteService.createNewNote({
2022-12-22 14:57:00 +01:00
noteId: id,
branchId: id,
2022-08-07 15:34:59 +02:00
title: "Spacer",
2022-12-01 10:16:57 +01:00
type: 'launcher',
2022-08-07 15:34:59 +02:00
content: '',
parentNoteId: parentNoteId
}).note;
2022-08-07 13:23:03 +02:00
2022-12-21 16:11:00 +01:00
note.addRelation('template', LBTPL_SPACER);
2022-08-07 15:34:59 +02:00
} else {
2022-12-07 12:46:41 +01:00
throw new Error(`Unrecognized launcher type '${launcherType}'`);
2022-08-07 13:23:03 +02:00
}
2022-08-07 15:34:59 +02:00
return {
success: true,
note
};
2022-08-07 13:23:03 +02:00
}
2022-12-01 10:16:57 +01:00
function resetLauncher(noteId) {
2022-12-06 23:48:44 +01:00
const note = becca.getNote(noteId);
2022-11-25 15:29:57 +01:00
2022-12-06 23:48:44 +01:00
if (note.isLauncherConfig()) {
2022-11-25 15:29:57 +01:00
if (note) {
2022-12-21 16:11:00 +01:00
if (noteId === '_lbRoot') {
2022-11-25 15:29:57 +01:00
// deleting hoisted notes are not allowed, so we just reset the children
for (const childNote of note.getChildNotes()) {
childNote.deleteNote();
}
} else {
note.deleteNote();
}
} else {
log.info(`Note ${noteId} has not been found and cannot be reset.`);
}
} else {
2022-12-01 10:16:57 +01:00
log.info(`Note ${noteId} is not a resettable launcher note.`);
2022-11-25 15:29:57 +01:00
}
2022-12-07 12:46:41 +01:00
hiddenSubtreeService.checkHiddenSubtree();
2022-11-25 15:29:57 +01:00
}
/**
* This exists to ease transition into the new launchbar, but it's not meant to be a permanent functionality.
* Previously, the launchbar was fixed and the only way to add buttons was through this API, so a lot of buttons have been
* created just to fill this user hole.
*
* Another use case would be for script-packages (of which only few exists) which could this way register automatically
2022-12-18 20:29:17 +01:00
* into the launchbar. For such use cases this might be a usable replacement, but it should look a bit differently:
* - launcher should be added into the available shortcuts, not visible. Part of the reasoning is that adding them to visible
* could mess up the layout - e.g. the sync status being below.
*/
function createOrUpdateScriptLauncherFromApi(opts) {
2022-12-22 14:57:00 +01:00
if (opts.id && !/^[a-z0-9]+$/i.test(opts.id)) {
throw new Error(`Launcher ID can be alphanumeric only, '${opts.id}' given`);
}
const launcherId = opts.id || (`tb_${opts.title.toLowerCase().replace(/[^[a-z0-9]/gi, "")}`);
if (!opts.title) {
throw new Error("Title is mandatory property to create or update a launcher.");
}
const launcherNote = becca.getNote(launcherId)
2022-12-21 16:11:00 +01:00
|| createScriptLauncher('_lbVisibleLaunchers', launcherId);
launcherNote.title = opts.title;
launcherNote.setContent(`(${opts.action})()`);
launcherNote.setLabel('scriptInLauncherContent'); // there's no target note, the script is in the launcher's content
launcherNote.mime = 'application/javascript;env=frontend';
launcherNote.save();
if (opts.shortcut) {
launcherNote.setLabel('keyboardShortcut', opts.shortcut);
} else {
launcherNote.removeLabel('keyboardShortcut');
}
if (opts.icon) {
launcherNote.setLabel('iconClass', `bx bx-${opts.icon}`);
} else {
launcherNote.removeLabel('iconClass');
}
return launcherNote;
}
module.exports = {
getInboxNote,
createSqlConsole,
saveSqlConsole,
createSearchNote,
saveSearchNote,
2022-12-01 10:16:57 +01:00
createLauncher,
resetLauncher,
createOrUpdateScriptLauncherFromApi
};