mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	added new label "sorted" which will keep children notes alphabetically sorted, fixes #82
This commit is contained in:
		| @@ -11,6 +11,7 @@ const os = require('os'); | |||||||
| const sessionSecret = require('./services/session_secret'); | const sessionSecret = require('./services/session_secret'); | ||||||
| const cls = require('./services/cls'); | const cls = require('./services/cls'); | ||||||
| require('./entities/entity_constructor'); | require('./entities/entity_constructor'); | ||||||
|  | require('./services/handlers'); | ||||||
|  |  | ||||||
| const app = express(); | const app = express(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,6 +30,10 @@ class Note extends Entity { | |||||||
|         catch(e) {} |         catch(e) {} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     isRoot() { | ||||||
|  |         return this.noteId === 'root'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     isJson() { |     isJson() { | ||||||
|         return this.mime === "application/json"; |         return this.mime === "application/json"; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import infoService from "./info.js"; | |||||||
|  |  | ||||||
| const $outstandingSyncsCount = $("#outstanding-syncs-count"); | const $outstandingSyncsCount = $("#outstanding-syncs-count"); | ||||||
|  |  | ||||||
|  | const syncMessageHandlers = []; | ||||||
| const messageHandlers = []; | const messageHandlers = []; | ||||||
|  |  | ||||||
| let ws; | let ws; | ||||||
| @@ -25,9 +26,17 @@ function subscribeToMessages(messageHandler) { | |||||||
|     messageHandlers.push(messageHandler); |     messageHandlers.push(messageHandler); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function subscribeToSyncMessages(messageHandler) { | ||||||
|  |     syncMessageHandlers.push(messageHandler); | ||||||
|  | } | ||||||
|  |  | ||||||
| function handleMessage(event) { | function handleMessage(event) { | ||||||
|     const message = JSON.parse(event.data); |     const message = JSON.parse(event.data); | ||||||
|  |  | ||||||
|  |     for (const messageHandler of messageHandlers) { | ||||||
|  |         messageHandler(message); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (message.type === 'sync') { |     if (message.type === 'sync') { | ||||||
|         lastPingTs = new Date().getTime(); |         lastPingTs = new Date().getTime(); | ||||||
|  |  | ||||||
| @@ -39,8 +48,8 @@ function handleMessage(event) { | |||||||
|  |  | ||||||
|         const syncData = message.data.filter(sync => sync.sourceId !== glob.sourceId); |         const syncData = message.data.filter(sync => sync.sourceId !== glob.sourceId); | ||||||
|  |  | ||||||
|         for (const messageHandler of messageHandlers) { |         for (const syncMessageHandler of syncMessageHandlers) { | ||||||
|             messageHandler(syncData); |             syncMessageHandler(syncData); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         $outstandingSyncsCount.html(message.outstandingSyncs); |         $outstandingSyncsCount.html(message.outstandingSyncs); | ||||||
| @@ -104,5 +113,6 @@ setTimeout(() => { | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     logError, |     logError, | ||||||
|     subscribeToMessages |     subscribeToMessages, | ||||||
|  |     subscribeToSyncMessages | ||||||
| }; | }; | ||||||
| @@ -276,7 +276,7 @@ function focus() { | |||||||
|     getComponent(note.type).focus(); |     getComponent(note.type).focus(); | ||||||
| } | } | ||||||
|  |  | ||||||
| messagingService.subscribeToMessages(syncData => { | messagingService.subscribeToSyncMessages(syncData => { | ||||||
|     if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === getCurrentNoteId())) { |     if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === getCurrentNoteId())) { | ||||||
|         infoService.showMessage('Reloading note because of background changes'); |         infoService.showMessage('Reloading note because of background changes'); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -505,7 +505,13 @@ async function showTree() { | |||||||
|     initFancyTree(tree); |     initFancyTree(tree); | ||||||
| } | } | ||||||
|  |  | ||||||
| messagingService.subscribeToMessages(syncData => { | messagingService.subscribeToMessages(message => { | ||||||
|  |    if (message.type === 'refresh-tree') { | ||||||
|  |        reload(); | ||||||
|  |    } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | messagingService.subscribeToSyncMessages(syncData => { | ||||||
|     if (syncData.some(sync => sync.entityName === 'branches') |     if (syncData.some(sync => sync.entityName === 'branches') | ||||||
|         || syncData.some(sync => sync.entityName === 'notes')) { |         || syncData.some(sync => sync.entityName === 'notes')) { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ async function getRootCalendarNote() { | |||||||
|         })).note; |         })).note; | ||||||
|  |  | ||||||
|         await labelService.createLabel(rootNote.noteId, CALENDAR_ROOT_LABEL); |         await labelService.createLabel(rootNote.noteId, CALENDAR_ROOT_LABEL); | ||||||
|  |         await labelService.createLabel(rootNote.noteId, 'sorted'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return rootNote; |     return rootNote; | ||||||
| @@ -60,6 +61,7 @@ async function getYearNote(dateTimeStr, rootNote) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         await labelService.createLabel(yearNote.noteId, YEAR_LABEL, yearStr); |         await labelService.createLabel(yearNote.noteId, YEAR_LABEL, yearStr); | ||||||
|  |         await labelService.createLabel(yearNote.noteId, 'sorted'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return yearNote; |     return yearNote; | ||||||
| @@ -85,6 +87,7 @@ async function getMonthNote(dateTimeStr, rootNote) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         await labelService.createLabel(monthNote.noteId, MONTH_LABEL, monthStr); |         await labelService.createLabel(monthNote.noteId, MONTH_LABEL, monthStr); | ||||||
|  |         await labelService.createLabel(monthNote.noteId, 'sorted'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return monthNote; |     return monthNote; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | const NOTE_TITLE_CHANGED = "NOTE_TITLE_CHANGED"; | ||||||
| const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION"; | const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION"; | ||||||
| const ENTITY_CHANGED = "ENTITY_CHANGED"; | const ENTITY_CHANGED = "ENTITY_CHANGED"; | ||||||
|  |  | ||||||
| @@ -19,10 +20,22 @@ function emit(eventType, data) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function syncEmit(eventType, data) { | ||||||
|  |     const listeners = eventListeners[eventType]; | ||||||
|  |  | ||||||
|  |     if (listeners) { | ||||||
|  |         for (const listener of listeners) { | ||||||
|  |             await listener(data); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     subscribe, |     subscribe, | ||||||
|     emit, |     emit, | ||||||
|  |     syncEmit, | ||||||
|     // event types: |     // event types: | ||||||
|  |     NOTE_TITLE_CHANGED, | ||||||
|     ENTER_PROTECTED_SESSION, |     ENTER_PROTECTED_SESSION, | ||||||
|     ENTITY_CHANGED |     ENTITY_CHANGED | ||||||
| }; | }; | ||||||
							
								
								
									
										27
									
								
								src/services/handlers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/services/handlers.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | const eventService = require('./events'); | ||||||
|  | const scriptService = require('./script'); | ||||||
|  | const relationService = require('./relations'); | ||||||
|  | const treeService = require('./tree'); | ||||||
|  | const messagingService = require('./messaging'); | ||||||
|  |  | ||||||
|  | eventService.subscribe(eventService.NOTE_TITLE_CHANGED, async note => { | ||||||
|  |     const relations = await relationService.getEffectiveRelations(note.noteId, 'runOnNoteTitleChange'); | ||||||
|  |  | ||||||
|  |     for (const relation of relations) { | ||||||
|  |         const scriptNote = await relation.getTargetNote(); | ||||||
|  |  | ||||||
|  |         await scriptService.executeNote(scriptNote, scriptNote, note); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!note.isRoot()) { | ||||||
|  |         const parents = await note.getParentNotes(); | ||||||
|  |  | ||||||
|  |         for (const parent of parents) { | ||||||
|  |             if (await parent.hasLabel("sorted")) { | ||||||
|  |                 await treeService.sortNotesAlphabetically(parent.noteId); | ||||||
|  |  | ||||||
|  |                 messagingService.sendMessageToAllClients({ type: 'refresh-tree' }); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }); | ||||||
| @@ -3,6 +3,7 @@ const optionService = require('./options'); | |||||||
| const dateUtils = require('./date_utils'); | const dateUtils = require('./date_utils'); | ||||||
| const syncTableService = require('./sync_table'); | const syncTableService = require('./sync_table'); | ||||||
| const labelService = require('./labels'); | const labelService = require('./labels'); | ||||||
|  | const eventService = require('./events'); | ||||||
| const repository = require('./repository'); | const repository = require('./repository'); | ||||||
| const Note = require('../entities/note'); | const Note = require('../entities/note'); | ||||||
| const NoteImage = require('../entities/note_image'); | const NoteImage = require('../entities/note_image'); | ||||||
| @@ -34,6 +35,10 @@ async function getNewNotePosition(parentNoteId, noteData) { | |||||||
|     return newNotePos; |     return newNotePos; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function triggerNoteTitleChanged(note) { | ||||||
|  |     await eventService.emit(eventService.NOTE_TITLE_CHANGED, note); | ||||||
|  | } | ||||||
|  |  | ||||||
| async function createNewNote(parentNoteId, noteData) { | async function createNewNote(parentNoteId, noteData) { | ||||||
|     const newNotePos = await getNewNotePosition(parentNoteId, noteData); |     const newNotePos = await getNewNotePosition(parentNoteId, noteData); | ||||||
|  |  | ||||||
| @@ -60,6 +65,8 @@ async function createNewNote(parentNoteId, noteData) { | |||||||
|         isExpanded: 0 |         isExpanded: 0 | ||||||
|     }).save(); |     }).save(); | ||||||
|  |  | ||||||
|  |     await triggerNoteTitleChanged(note); | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|         note, |         note, | ||||||
|         branch |         branch | ||||||
| @@ -92,6 +99,8 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {}) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     await triggerNoteTitleChanged(note); | ||||||
|  |  | ||||||
|     return {note, branch}; |     return {note, branch}; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -200,11 +209,17 @@ async function updateNote(noteId, noteUpdates) { | |||||||
|  |  | ||||||
|     await saveNoteRevision(note); |     await saveNoteRevision(note); | ||||||
|  |  | ||||||
|  |     const noteTitleChanged = note.title !== noteUpdates.title; | ||||||
|  |  | ||||||
|     note.title = noteUpdates.title; |     note.title = noteUpdates.title; | ||||||
|     note.setContent(noteUpdates.content); |     note.setContent(noteUpdates.content); | ||||||
|     note.isProtected = noteUpdates.isProtected; |     note.isProtected = noteUpdates.isProtected; | ||||||
|     await note.save(); |     await note.save(); | ||||||
|  |  | ||||||
|  |     if (noteTitleChanged) { | ||||||
|  |         await triggerNoteTitleChanged(note); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     await saveNoteImages(note); |     await saveNoteImages(note); | ||||||
|  |  | ||||||
|     await protectNoteRevisions(note); |     await protectNoteRevisions(note); | ||||||
|   | |||||||
| @@ -4,7 +4,8 @@ const repository = require('./repository'); | |||||||
| const Relation = require('../entities/relation'); | const Relation = require('../entities/relation'); | ||||||
|  |  | ||||||
| const BUILTIN_RELATIONS = [ | const BUILTIN_RELATIONS = [ | ||||||
|     'runOnNoteView' |     'runOnNoteView', | ||||||
|  |     'runOnNoteTitleChange' | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| async function getNotesWithRelation(name, targetNoteId) { | async function getNotesWithRelation(name, targetNoteId) { | ||||||
| @@ -36,8 +37,8 @@ async function createRelation(sourceNoteId, name, targetNoteId) { | |||||||
|     }).save(); |     }).save(); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function getEffectiveRelations(noteId) { | async function getEffectiveRelations(noteId, relationName) { | ||||||
|     return await repository.getEntities(` |     const relations = await repository.getEntities(` | ||||||
|         WITH RECURSIVE tree(noteId) AS ( |         WITH RECURSIVE tree(noteId) AS ( | ||||||
|         SELECT ? |         SELECT ? | ||||||
|             UNION |             UNION | ||||||
| @@ -48,6 +49,13 @@ async function getEffectiveRelations(noteId) { | |||||||
|         ) |         ) | ||||||
|         SELECT relations.* FROM relations JOIN tree ON relations.sourceNoteId = tree.noteId  |         SELECT relations.* FROM relations JOIN tree ON relations.sourceNoteId = tree.noteId  | ||||||
|         WHERE relations.isDeleted = 0 AND (relations.isInheritable = 1 OR relations.sourceNoteId = ?)`, [noteId, noteId]); |         WHERE relations.isDeleted = 0 AND (relations.isInheritable = 1 OR relations.sourceNoteId = ?)`, [noteId, noteId]); | ||||||
|  |  | ||||||
|  |     if (relationName) { | ||||||
|  |         return relations.filter(relation => relation.name === relationName); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         return relations; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   | |||||||
| @@ -4,14 +4,14 @@ const repository = require('./repository'); | |||||||
| const cls = require('./cls'); | const cls = require('./cls'); | ||||||
| const sourceIdService = require('./source_id'); | const sourceIdService = require('./source_id'); | ||||||
|  |  | ||||||
| async function executeNote(note) { | async function executeNote(note, targetNote) { | ||||||
|     if (!note.isJavaScript()) { |     if (!note.isJavaScript()) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const bundle = await getScriptBundle(note); |     const bundle = await getScriptBundle(note); | ||||||
|  |  | ||||||
|     await executeBundle(bundle); |     await executeBundle(bundle, note, targetNote); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function executeBundle(bundle, startNote, targetNote = null) { | async function executeBundle(bundle, startNote, targetNote = null) { | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ const utils = require('./utils'); | |||||||
| const dateUtils = require('./date_utils'); | const dateUtils = require('./date_utils'); | ||||||
| const labelService = require('./labels'); | const labelService = require('./labels'); | ||||||
| const dateNoteService = require('./date_notes'); | const dateNoteService = require('./date_notes'); | ||||||
|  | const treeService = require('./tree'); | ||||||
| const config = require('./config'); | const config = require('./config'); | ||||||
| const repository = require('./repository'); | const repository = require('./repository'); | ||||||
| const axios = require('axios'); | const axios = require('axios'); | ||||||
| @@ -61,6 +62,8 @@ function ScriptApi(startNote, currentNote, targetNote) { | |||||||
|     this.getRootCalendarNote = dateNoteService.getRootCalendarNote; |     this.getRootCalendarNote = dateNoteService.getRootCalendarNote; | ||||||
|     this.getDateNote = dateNoteService.getDateNote; |     this.getDateNote = dateNoteService.getDateNote; | ||||||
|  |  | ||||||
|  |     this.sortNotesAlphabetically = treeService.sortNotesAlphabetically; | ||||||
|  |  | ||||||
|     this.transactional = sql.transactional; |     this.transactional = sql.transactional; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user