From f37f47ce5b2896531df3f552c361a23ffbb1d8c0 Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 3 Nov 2023 01:11:47 +0100 Subject: [PATCH] fixes to stable sorting --- src/becca/entities/bnote.js | 6 +++--- src/etapi/notes.js | 2 +- src/public/app/entities/fnote.js | 4 ++-- .../widgets/attribute_widgets/attribute_editor.js | 2 +- src/public/app/widgets/basic_widget.js | 8 ++++---- src/public/app/widgets/note_tree.js | 15 +++++++++------ .../ribbon_widgets/inherited_attribute_list.js | 2 +- .../widgets/ribbon_widgets/promoted_attributes.js | 2 +- src/services/import/zip.js | 2 +- 9 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js index 260a208d63..98829b58f5 100644 --- a/src/becca/entities/bnote.js +++ b/src/becca/entities/bnote.js @@ -91,7 +91,7 @@ class BNote extends AbstractBeccaEntity { this.utcDateCreated = utcDateCreated || dateUtils.utcNowDateTime(); /** @type {string} */ this.utcDateModified = utcDateModified; - /** + /** * set during the deletion operation, before it is completed (removed from becca completely) * @type {boolean} */ @@ -756,7 +756,7 @@ class BNote extends AbstractBeccaEntity { } else if (a.parentNote?.isHiddenCompletely()) { return 1; } else { - return -1; + return 0; } }); @@ -776,7 +776,7 @@ class BNote extends AbstractBeccaEntity { const aBranch = becca.getBranchFromChildAndParent(a.noteId, this.noteId); const bBranch = becca.getBranchFromChildAndParent(b.noteId, this.noteId); - return aBranch?.notePosition < bBranch?.notePosition ? -1 : 1; + return (aBranch?.notePosition - bBranch?.notePosition) || 0; }); } diff --git a/src/etapi/notes.js b/src/etapi/notes.js index 00c6adbb89..dcd0c6504e 100644 --- a/src/etapi/notes.js +++ b/src/etapi/notes.js @@ -163,7 +163,7 @@ function register(router) { zipImportService.importZip(taskContext, req.body, note).then(importedNote => { res.status(201).json({ note: mappers.mapNoteToPojo(importedNote), - branch: mappers.mapBranchToPojo(importedNote.getBranches()[0]), + branch: mappers.mapBranchToPojo(importedNote.getParentBranches()[0]), }); }); // we need better error handling here, async errors won't be properly processed. }); diff --git a/src/public/app/entities/fnote.js b/src/public/app/entities/fnote.js index f8715b369d..fc53d56c08 100644 --- a/src/public/app/entities/fnote.js +++ b/src/public/app/entities/fnote.js @@ -130,7 +130,7 @@ class FNote { branchIdPos[branchId] = this.froca.getBranch(branchId).notePosition; } - this.children.sort((a, b) => branchIdPos[this.childToBranch[a]] < branchIdPos[this.childToBranch[b]] ? -1 : 1); + this.children.sort((a, b) => branchIdPos[this.childToBranch[a]] - branchIdPos[this.childToBranch[b]]); } /** @returns {boolean} */ @@ -228,7 +228,7 @@ class FNote { return 1; } - return -1; + return 0; }); } diff --git a/src/public/app/widgets/attribute_widgets/attribute_editor.js b/src/public/app/widgets/attribute_widgets/attribute_editor.js index 225ba1f384..70b81fd569 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_editor.js +++ b/src/public/app/widgets/attribute_widgets/attribute_editor.js @@ -473,7 +473,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { async renderOwnedAttributes(ownedAttributes, saved) { // attrs are not resorted if position changes after the initial load - ownedAttributes.sort((a, b) => a.position < b.position ? -1 : 1); + ownedAttributes.sort((a, b) => a.position - b.position); let htmlAttrs = (await attributeRenderer.renderAttributes(ownedAttributes, true)).html(); diff --git a/src/public/app/widgets/basic_widget.js b/src/public/app/widgets/basic_widget.js index 25145c38f1..1c1896abf3 100644 --- a/src/public/app/widgets/basic_widget.js +++ b/src/public/app/widgets/basic_widget.js @@ -3,7 +3,7 @@ import Component from "../components/component.js"; /** * This is the base widget for all other widgets. - * + * * For information on using widgets, see the tutorial {@tutorial widget_basics}. */ class BasicWidget extends Component { @@ -33,7 +33,7 @@ class BasicWidget extends Component { } } - this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1); + this.children.sort((a, b) => a.position - b.position); return this; } @@ -72,7 +72,7 @@ class BasicWidget extends Component { /** * Accepts a string of CSS to add with the widget. - * @param {string} block + * @param {string} block * @returns {this} for chaining */ cssBlock(block) { @@ -124,7 +124,7 @@ class BasicWidget extends Component { /** * Method used for rendering the widget. - * + * * Your class should override this method. * @returns {JQuery} Your widget. */ diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index 20d064a80c..24c0d7a7a6 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -1147,7 +1147,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { let parentsOfAddedNodes = []; const allBranchRows = loadResults.getBranchRows(); - // TODO: this flag is suspicious - why does it matter that all branches in a particular update are deleted? const allBranchesDeleted = allBranchRows.every(branchRow => !!branchRow.isDeleted); for (const branchRow of allBranchRows) { @@ -1190,12 +1189,16 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { continue; } - const found = (parentNode.getChildren() || []).find(child => child.data.noteId === branchRow.noteId); - if (!found) { + const note = await froca.getNote(branchRow.noteId); + const frocaBranch = froca.getBranch(branchRow.branchId); + const foundNode = (parentNode.getChildren() || []).find(child => child.data.noteId === branchRow.noteId); + if (foundNode) { + // the branch already exists in the tree + if (branchRow.isExpanded !== foundNode.isExpanded()) { + noteIdsToReload.add(frocaBranch.noteId); + } + } else { // make sure it's loaded - const note = await froca.getNote(branchRow.noteId); - const frocaBranch = froca.getBranch(branchRow.branchId); - // we're forcing lazy since it's not clear if the whole required subtree is in froca parentNode.addChildren([this.prepareNode(frocaBranch, true)]); diff --git a/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js index 1af39a972e..78d9496262 100644 --- a/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js +++ b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js @@ -96,7 +96,7 @@ export default class InheritedAttributesWidget extends NoteContextAwareWidget { attrs.sort((a, b) => { if (a.noteId === b.noteId) { - return a.position < b.position ? -1 : 1; + return a.position - b.position; } else { // inherited attributes should stay grouped: https://github.com/zadam/trilium/issues/3761 return a.noteId < b.noteId ? -1 : 1; diff --git a/src/public/app/widgets/ribbon_widgets/promoted_attributes.js b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js index b3299844a9..ae34550fa9 100644 --- a/src/public/app/widgets/ribbon_widgets/promoted_attributes.js +++ b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js @@ -83,7 +83,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget { // attrs are not resorted if position changes after the initial load // promoted attrs are sorted primarily by order of definitions, but with multi-valued promoted attrs // the order of attributes is important as well - ownedAttributes.sort((a, b) => a.position < b.position ? -1 : 1); + ownedAttributes.sort((a, b) => a.position - b.position); if (promotedDefAttrs.length === 0) { this.toggleInt(false); diff --git a/src/services/import/zip.js b/src/services/import/zip.js index 9103d22f9d..64e3ff2d06 100644 --- a/src/services/import/zip.js +++ b/src/services/import/zip.js @@ -20,7 +20,7 @@ const markdownService = require("./markdown"); * @param {TaskContext} taskContext * @param {Buffer} fileBuffer * @param {BNote} importRootNote - * @returns {Promise<*>} + * @returns {Promise} */ async function importZip(taskContext, fileBuffer, importRootNote) { /** @type {Object.} maps from original noteId (in ZIP file) to newly generated noteId */