From d3ec9f022c6aecaa95caa2cc5691bc6235c50f01 Mon Sep 17 00:00:00 2001 From: Nriver <6752679+Nriver@users.noreply.github.com> Date: Fri, 10 Mar 2023 14:35:36 +0800 Subject: [PATCH 1/2] add natural sort for notes, introduce new label #sortNatural --- .../app/widgets/dialogs/sort_child_notes.js | 14 +++++++++++++- src/routes/api/notes.js | 6 +++--- src/services/builtin_attributes.js | 1 + src/services/handlers.js | 4 ++-- src/services/tree.js | 16 ++++++++++++---- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/public/app/widgets/dialogs/sort_child_notes.js b/src/public/app/widgets/dialogs/sort_child_notes.js index 65440efe4..ccb12544a 100644 --- a/src/public/app/widgets/dialogs/sort_child_notes.js +++ b/src/public/app/widgets/dialogs/sort_child_notes.js @@ -65,6 +65,17 @@ const TPL = ` + +
+ +
Natural Sort
+ +
+ +
@@ -95,8 +104,9 @@ export default class SortChildNotesDialog extends BasicWidget { const sortDirection = this.$form.find("input[name='sort-direction']:checked").val(); const foldersFirst = this.$form.find("input[name='sort-folders-first']").is(":checked"); const sortNatural = this.$form.find("input[name='sort-natural']").is(":checked"); + const sortLocale = this.$form.find("input[name='sort-locale']").val(); - await server.put(`notes/${this.parentNoteId}/sort-children`, {sortBy, sortDirection, foldersFirst, sortNatural}); + await server.put(`notes/${this.parentNoteId}/sort-children`, {sortBy, sortDirection, foldersFirst, sortNatural, sortLocale}); utils.closeActiveDialog(); }); diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js index e019ddb8b..8ce603f37 100644 --- a/src/routes/api/notes.js +++ b/src/routes/api/notes.js @@ -94,13 +94,13 @@ function undeleteNote(req) { function sortChildNotes(req) { const noteId = req.params.noteId; - const {sortBy, sortDirection, foldersFirst, sortNatural} = req.body; + const {sortBy, sortDirection, foldersFirst, sortNatural, sortLocale} = req.body; - log.info(`Sorting '${noteId}' children with ${sortBy} ${sortDirection}, foldersFirst=${foldersFirst}, sortNatural=${sortNatural}`); + log.info(`Sorting '${noteId}' children with ${sortBy} ${sortDirection}, foldersFirst=${foldersFirst}, sortNatural=${sortNatural}, sortLocale=${sortLocale}`); const reverse = sortDirection === 'desc'; - treeService.sortNotes(noteId, sortBy, reverse, foldersFirst, sortNatural); + treeService.sortNotes(noteId, sortBy, reverse, foldersFirst, sortNatural, sortLocale); } function protectNote(req) { diff --git a/src/services/builtin_attributes.js b/src/services/builtin_attributes.js index b05ef66e5..6ab9b8a52 100644 --- a/src/services/builtin_attributes.js +++ b/src/services/builtin_attributes.js @@ -43,6 +43,7 @@ module.exports = [ { type: 'label', name: 'sortDirection' }, { type: 'label', name: 'sortFoldersFirst' }, { type: 'label', name: 'sortNatural' }, + { type: 'label', name: 'sortLocale' }, { type: 'label', name: 'top' }, { type: 'label', name: 'fullContentWidth' }, { type: 'label', name: 'shareHiddenFromTree' }, diff --git a/src/services/handlers.js b/src/services/handlers.js index e0902d8bc..75f5563b3 100644 --- a/src/services/handlers.js +++ b/src/services/handlers.js @@ -46,7 +46,7 @@ eventService.subscribe([ eventService.ENTITY_CHANGED, eventService.ENTITY_DELETE if (entityName === 'attributes') { runAttachedRelations(entity.getNote(), 'runOnAttributeChange', entity); - if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural'].includes(entity.name)) { + if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale'].includes(entity.name)) { handleSortedAttribute(entity); } else if (entity.type === 'label') { handleMaybeSortingLabel(entity); @@ -101,7 +101,7 @@ eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => noteService.duplicateSubtreeWithoutRoot(templateNote.noteId, note.noteId); } } - else if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural'].includes(entity.name)) { + else if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural', 'sortLocale'].includes(entity.name)) { handleSortedAttribute(entity); } else if (entity.type === 'label') { diff --git a/src/services/tree.js b/src/services/tree.js index bf537c985..1038e8772 100644 --- a/src/services/tree.js +++ b/src/services/tree.js @@ -123,11 +123,16 @@ function loadSubtreeNoteIds(parentNoteId, subtreeNoteIds) { } } -function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, foldersFirst = false, sortNatural = false) { +function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, foldersFirst = false, sortNatural = false, sortLocale) { if (!customSortBy) { customSortBy = 'title'; } + if (!sortLocale) { + // sortLocale can not be empty string or null value, default value must be set to undefined. + sortLocale = undefined; + } + sql.transactional(() => { const notes = becca.getNote(parentNoteId).getChildNotes(); @@ -157,8 +162,8 @@ function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, folder // alphabetical sort return b === null || b === undefined || a < b ? -1 : 1; } else { - // alphanumeric sort, or natural sort - return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'}); + // natural sort + return a.localeCompare(b, sortLocale, {numeric: true, sensitivity: 'base'}); } } @@ -233,7 +238,9 @@ function sortNotesIfNeeded(parentNoteId) { const sortFoldersFirst = sortFoldersFirstLabel && sortFoldersFirstLabel.value.toLowerCase() !== "false"; const sortNaturalLabel = parentNote.getLabel('sortNatural'); const sortNatural = sortNaturalLabel && sortNaturalLabel.value.toLowerCase() !== "false"; - sortNotes(parentNoteId, sortedLabel.value, sortReversed, sortFoldersFirst, sortNatural); + const sortLocale = parentNote.getLabelValue('sortLocale'); + + sortNotes(parentNoteId, sortedLabel.value, sortReversed, sortFoldersFirst, sortNatural, sortLocale); } /**