diff --git a/src/public/app/services/entrypoints.js b/src/public/app/services/entrypoints.js index 42e4f79ee9..cd05a515ce 100644 --- a/src/public/app/services/entrypoints.js +++ b/src/public/app/services/entrypoints.js @@ -66,7 +66,6 @@ export default class Entrypoints extends Component { const inboxNote = await dateNoteService.getInboxNote(); const {note} = await server.post(`notes/${inboxNote.noteId}/children?target=into`, { - title: 'new note', content: '', type: 'text', isProtected: inboxNote.isProtected && protectedSessionHolder.isProtectedSessionAvailable() diff --git a/src/public/app/services/note_create.js b/src/public/app/services/note_create.js index f1bbc2e35e..0132f438af 100644 --- a/src/public/app/services/note_create.js +++ b/src/public/app/services/note_create.js @@ -28,8 +28,6 @@ async function createNote(parentNotePath, options = {}) { [options.title, options.content] = parseSelectedHtml(window.cutToNote.getSelectedHtml()); } - const newNoteName = options.title || "new note"; - const parentNoteId = treeService.getNoteIdFromNotePath(parentNotePath); if (options.type === 'mermaid' && !options.content) { @@ -41,7 +39,7 @@ async function createNote(parentNotePath, options = {}) { } const {note, branch} = await server.post(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId || ""}`, { - title: newNoteName, + title: options.title, content: options.content || "", isProtected: options.isProtected, type: options.type, diff --git a/src/public/app/widgets/attribute_widgets/attribute_detail.js b/src/public/app/widgets/attribute_widgets/attribute_detail.js index 01c6b80a2e..85eef7c795 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_detail.js +++ b/src/public/app/widgets/attribute_widgets/attribute_detail.js @@ -219,6 +219,15 @@ const ATTR_HELP = { "shareDisallowRobotIndexing": `will forbid robot indexing of this note via X-Robots-Tag: noindex header`, "displayRelations": "comma delimited names of relations which should be displayed. All other ones will be hidden.", "hideRelations": "comma delimited names of relations which should be hidden. All other ones will be displayed.", + "titleTemplate": `default title of notes created as children of this note. The value is evaluated as JavaScript string + and thus can be enriched with dynamic content via the injected now and parentNote variables. Examples: + + + + See wiki with details, API docs for parentNote and now for details.` }, "relation": { "runOnNoteCreation": "executes when note is created on backend", diff --git a/src/services/builtin_attributes.js b/src/services/builtin_attributes.js index 51243aa0b8..31093ff068 100644 --- a/src/services/builtin_attributes.js +++ b/src/services/builtin_attributes.js @@ -50,6 +50,7 @@ module.exports = [ { type: 'label', name: 'shareDisallowRobotIndexing' }, { type: 'label', name: 'displayRelations' }, { type: 'label', name: 'hideRelations' }, + { type: 'label', name: 'titleTemplate' }, // relation names { type: 'relation', name: 'internalLink' }, diff --git a/src/services/notes.js b/src/services/notes.js index 9accb08d8b..067bf45960 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -17,7 +17,7 @@ const becca = require('../becca/becca'); const Branch = require('../becca/entities/branch'); const Note = require('../becca/entities/note'); const Attribute = require('../becca/entities/attribute'); -const TaskContext = require("./task_context.js"); +const dayjs = require("dayjs"); function getNewNotePosition(parentNoteId) { const note = becca.notes[parentNoteId]; @@ -79,6 +79,28 @@ function copyChildAttributes(parentNote, childNote) { } } +function getNewNoteTitle(parentNote) { + let title = "new note"; + + const titleTemplate = parentNote.getLabelValue('titleTemplate'); + + if (titleTemplate !== null) { + try { + const now = dayjs(cls.getLocalNowDateTime() || new Date()); + + // "officially" injected values: + // - now + // - parentNote + + title = eval('`' + titleTemplate + '`'); + } catch (e) { + log.error(`Title template of note '${parentNote.noteId}' failed with: ${e.message}`); + } + } + + return title; +} + /** * Following object properties are mandatory: * - {string} parentNoteId @@ -104,8 +126,7 @@ function createNewNote(params) { } if (params.title === null || params.title === undefined) { - // empty title is allowed since it's possible to create such in the UI - throw new Error(`Note title must be set`); + params.title = getNewNoteTitle(parentNote); } if (params.content === null || params.content === undefined) {