diff --git a/public/javascripts/context_menu.js b/public/javascripts/context_menu.js index 2f3e1ac17..0f1864c60 100644 --- a/public/javascripts/context_menu.js +++ b/public/javascripts/context_menu.js @@ -90,7 +90,9 @@ const contextMenu = (function() { {title: "Paste after", cmd: "pasteAfter", uiIcon: "ui-icon-clipboard"}, {title: "----"}, {title: "Collapse sub-tree Alt+-", cmd: "collapse-sub-tree", uiIcon: "ui-icon-minus"}, - {title: "Force note sync", cmd: "force-note-sync", uiIcon: "ui-icon-refresh"} + {title: "Force note sync", cmd: "force-note-sync", uiIcon: "ui-icon-refresh"}, + {title: "Sort alphabetically", cmd: "sort-alphabetically", uiIcon: " ui-icon-arrowthick-2-n-s"} + ], beforeOpen: (event, ui) => { const node = $.ui.fancytree.getNode(ui.target); @@ -147,6 +149,9 @@ const contextMenu = (function() { else if (ui.cmd === "force-note-sync") { forceNoteSync(node.data.note_id); } + else if (ui.cmd === "sort-alphabetically") { + noteTree.sortAlphabetically(node.data.note_id); + } else { messaging.logError("Unknown command: " + ui.cmd); } diff --git a/public/javascripts/note_tree.js b/public/javascripts/note_tree.js index 84862a094..0a80a4caf 100644 --- a/public/javascripts/note_tree.js +++ b/public/javascripts/note_tree.js @@ -769,6 +769,12 @@ const noteTree = (function() { showMessage("Created!"); } + async function sortAlphabetically(noteId) { + await server.put('notes/' + noteId + '/sort'); + + await reload(); + } + $(document).bind('keydown', 'ctrl+o', e => { console.log("pressed O"); @@ -842,6 +848,7 @@ const noteTree = (function() { getNotePathTitle, removeParentChildRelation, setParentChildRelation, - getSelectedNodes + getSelectedNodes, + sortAlphabetically }; })(); \ No newline at end of file diff --git a/routes/api/notes.js b/routes/api/notes.js index 8ef47052e..93dec96a7 100644 --- a/routes/api/notes.js +++ b/routes/api/notes.js @@ -8,6 +8,7 @@ const notes = require('../../services/notes'); const log = require('../../services/log'); const protected_session = require('../../services/protected_session'); const data_encryption = require('../../services/data_encryption'); +const sync_table = require('../../services/sync_table'); const wrap = require('express-promise-wrap').wrap; router.get('/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { @@ -79,4 +80,36 @@ router.get('/', auth.checkApiAuth, wrap(async (req, res, next) => { res.send(noteIdList); })); +router.put('/:noteId/sort', auth.checkApiAuth, wrap(async (req, res, next) => { + const noteId = req.params.noteId; + const sourceId = req.headers.source_id; + const dataKey = protected_session.getDataKey(req); + + await sql.doInTransaction(async () => { + const notes = await sql.getAll(`SELECT note_tree_id, note_id, note_title, is_protected + FROM notes JOIN notes_tree USING(note_id) WHERE parent_note_id = ?`, [noteId]); + + for (const note of notes) { + if (note.is_protected) { + note.note_title = data_encryption.decryptString(dataKey, data_encryption.noteTitleIv(note.note_id), note.note_title); + } + } + + notes.sort((a, b) => a.note_title.toLowerCase() < b.note_title.toLowerCase() ? -1 : 1); + + let position = 1; + + for (const note of notes) { + await sql.execute("UPDATE notes_tree SET note_position = ? WHERE note_tree_id = ?", + [position, note.note_tree_id]); + + position++; + } + + await sync_table.addNoteReorderingSync(noteId, sourceId); + }); + + res.send({}); +})); + module.exports = router; \ No newline at end of file