mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
added new label "sorted" which will keep children notes alphabetically sorted, fixes #82
This commit is contained in:
parent
9452fc236b
commit
2d24bf81dd
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user