add natural sort for notes, introduce new label #sortNatural

This commit is contained in:
Nriver 2023-03-10 14:35:36 +08:00
parent 6b4800d2d6
commit d3ec9f022c
5 changed files with 31 additions and 10 deletions

View file

@ -65,6 +65,17 @@ const TPL = `<div class="sort-child-notes-dialog modal mx-auto" tabindex="-1" ro
sort folders at the top sort folders at the top
</label> </label>
</div> </div>
<br />
<h5>Natural Sort</h5>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="sort-natural" value="1">
sort by alphanumeric order
</label>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="submit" class="btn btn-primary">Sort <kbd>enter</kbd></button> <button type="submit" class="btn btn-primary">Sort <kbd>enter</kbd></button>
@ -83,8 +94,9 @@ export default class SortChildNotesDialog extends BasicWidget {
const sortBy = this.$form.find("input[name='sort-by']:checked").val(); const sortBy = this.$form.find("input[name='sort-by']:checked").val();
const sortDirection = this.$form.find("input[name='sort-direction']:checked").val(); const sortDirection = this.$form.find("input[name='sort-direction']:checked").val();
const foldersFirst = this.$form.find("input[name='sort-folders-first']").is(":checked"); const foldersFirst = this.$form.find("input[name='sort-folders-first']").is(":checked");
const sortNatural = this.$form.find("input[name='sort-natural']").is(":checked");
await server.put(`notes/${this.parentNoteId}/sort-children`, {sortBy, sortDirection, foldersFirst}); await server.put(`notes/${this.parentNoteId}/sort-children`, {sortBy, sortDirection, foldersFirst, sortNatural});
utils.closeActiveDialog(); utils.closeActiveDialog();
}); });

View file

@ -94,13 +94,13 @@ function undeleteNote(req) {
function sortChildNotes(req) { function sortChildNotes(req) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const {sortBy, sortDirection, foldersFirst} = req.body; const {sortBy, sortDirection, foldersFirst, sortNatural} = req.body;
log.info(`Sorting '${noteId}' children with ${sortBy} ${sortDirection}, foldersFirst=${foldersFirst}`); log.info(`Sorting '${noteId}' children with ${sortBy} ${sortDirection}, foldersFirst=${foldersFirst}, sortNatural=${sortNatural}`);
const reverse = sortDirection === 'desc'; const reverse = sortDirection === 'desc';
treeService.sortNotes(noteId, sortBy, reverse, foldersFirst); treeService.sortNotes(noteId, sortBy, reverse, foldersFirst, sortNatural);
} }
function protectNote(req) { function protectNote(req) {

View file

@ -42,6 +42,7 @@ module.exports = [
{ type: 'label', name: 'sorted' }, { type: 'label', name: 'sorted' },
{ type: 'label', name: 'sortDirection' }, { type: 'label', name: 'sortDirection' },
{ type: 'label', name: 'sortFoldersFirst' }, { type: 'label', name: 'sortFoldersFirst' },
{ type: 'label', name: 'sortNatural' },
{ type: 'label', name: 'top' }, { type: 'label', name: 'top' },
{ type: 'label', name: 'fullContentWidth' }, { type: 'label', name: 'fullContentWidth' },
{ type: 'label', name: 'shareHiddenFromTree' }, { type: 'label', name: 'shareHiddenFromTree' },

View file

@ -46,7 +46,7 @@ eventService.subscribe([ eventService.ENTITY_CHANGED, eventService.ENTITY_DELETE
if (entityName === 'attributes') { if (entityName === 'attributes') {
runAttachedRelations(entity.getNote(), 'runOnAttributeChange', entity); runAttachedRelations(entity.getNote(), 'runOnAttributeChange', entity);
if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst'].includes(entity.name)) { if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural'].includes(entity.name)) {
handleSortedAttribute(entity); handleSortedAttribute(entity);
} else if (entity.type === 'label') { } else if (entity.type === 'label') {
handleMaybeSortingLabel(entity); handleMaybeSortingLabel(entity);
@ -101,7 +101,7 @@ eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) =>
noteService.duplicateSubtreeWithoutRoot(templateNote.noteId, note.noteId); noteService.duplicateSubtreeWithoutRoot(templateNote.noteId, note.noteId);
} }
} }
else if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst'].includes(entity.name)) { else if (entity.type === 'label' && ['sorted', 'sortDirection', 'sortFoldersFirst', 'sortNatural'].includes(entity.name)) {
handleSortedAttribute(entity); handleSortedAttribute(entity);
} }
else if (entity.type === 'label') { else if (entity.type === 'label') {

View file

@ -123,7 +123,7 @@ function loadSubtreeNoteIds(parentNoteId, subtreeNoteIds) {
} }
} }
function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, foldersFirst = false) { function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, foldersFirst = false, sortNatural = false) {
if (!customSortBy) { if (!customSortBy) {
customSortBy = 'title'; customSortBy = 'title';
} }
@ -153,7 +153,14 @@ function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, folder
} }
function compare(a, b) { function compare(a, b) {
return b === null || b === undefined || a < b ? -1 : 1; if (!sortNatural){
// 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'});
}
} }
const topAEl = fetchValue(a, 'top'); const topAEl = fetchValue(a, 'top');
@ -224,8 +231,9 @@ function sortNotesIfNeeded(parentNoteId) {
const sortReversed = parentNote.getLabelValue('sortDirection')?.toLowerCase() === "desc"; const sortReversed = parentNote.getLabelValue('sortDirection')?.toLowerCase() === "desc";
const sortFoldersFirstLabel = parentNote.getLabel('sortFoldersFirst'); const sortFoldersFirstLabel = parentNote.getLabel('sortFoldersFirst');
const sortFoldersFirst = sortFoldersFirstLabel && sortFoldersFirstLabel.value.toLowerCase() !== "false"; const sortFoldersFirst = sortFoldersFirstLabel && sortFoldersFirstLabel.value.toLowerCase() !== "false";
const sortNaturalLabel = parentNote.getLabel('sortNatural');
sortNotes(parentNoteId, sortedLabel.value, sortReversed, sortFoldersFirst); const sortNatural = sortNaturalLabel && sortNaturalLabel.value.toLowerCase() !== "false";
sortNotes(parentNoteId, sortedLabel.value, sortReversed, sortFoldersFirst, sortNatural);
} }
/** /**