From 4fcae9b3f9bdeb5bc69676df1cc58e8beb3db6bf Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 25 Sep 2019 14:37:54 +0200 Subject: [PATCH] Fixed a bug where moving documents around deleted docs breaks the ordering --- app/imports/api/parenting/order.js | 48 +++++++++++++++++-- app/imports/api/parenting/organizeMethods.js | 4 +- .../ui/components/tree/TreeNodeList.vue | 2 +- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/app/imports/api/parenting/order.js b/app/imports/api/parenting/order.js index 32172c59..cab63b09 100644 --- a/app/imports/api/parenting/order.js +++ b/app/imports/api/parenting/order.js @@ -61,6 +61,8 @@ export function setDocToLastOrder({collection, doc}){ }) + 1; } +// update the order of a doc, and shift the siblings around to suit the new +// order export function updateDocOrder({docRef, order}){ let doc = fetchDocByRef(docRef, {fields: { order: 1, @@ -116,7 +118,7 @@ export function removedDocAtOrder({collection, doc}){ } export function insertedDocAtOrder({collection, parentId, order}){ - // Decrement the order of all docs after the removed doc + // Increment the order of all docs after the inserted doc collection.update({ 'parent.id': parentId, order: {$gte: order}, @@ -128,6 +130,46 @@ export function insertedDocAtOrder({collection, parentId, order}){ }); } +// Update the order a single doc and re-order the entire sibling list +// with the change +export function safeUpdateDocOrder({docRef, order}){ + let collection = getCollectionByName(docRef.collection); + let movedDoc = fetchDocByRef(docRef, {fields: { + parent: 1, name: 1 + }}); + let parentId = movedDoc.parent.id; + let bulkWrite = []; + let docs = collection.find({ + 'parent.id': parentId, + '_id': {$ne: movedDoc._id}, + }, { + fields: {order: 1, name: 1}, + sort: {order: 1} + }).fetch(); + docs.splice(order, 0, movedDoc); + docs.forEach((doc, index) => { + if (doc.order !== index){ + bulkWrite.push({ + updateOne: { + filter: {_id: doc._id}, + update: {$set: {order: index}}, + }, + }); + } + }); + if (Meteor.isServer){ + collection.rawCollection().bulkWrite(bulkWrite); + } else { + bulkWrite.forEach(op => { + collection.update( + op.updateOne.filter, + op.updateOne.update, + {selector: {type: 'any'}} + ); + }); + } +}; + export function reorderDocs({collection, parentId}){ let bulkWrite = []; collection.find({ @@ -137,7 +179,7 @@ export function reorderDocs({collection, parentId}){ sort: {order: 1} }).forEach((doc, index) => { if (doc.order !== index){ - bulkwrite.push({ + bulkWrite.push({ updateOne : { filter: {_id: doc._id}, update: {$set: {order: index}}, @@ -149,7 +191,7 @@ export function reorderDocs({collection, parentId}){ collection.rawCollection().bulkWrite(bulkWrite); } else { bulkWrite.forEach(op => { - collection.update(op.filter, op.update); + collection.update(op.updateOne.filter, op.updateOne.update); }); } } diff --git a/app/imports/api/parenting/organizeMethods.js b/app/imports/api/parenting/organizeMethods.js index 3f9120e2..bce2f889 100644 --- a/app/imports/api/parenting/organizeMethods.js +++ b/app/imports/api/parenting/organizeMethods.js @@ -1,6 +1,6 @@ import SimpleSchema from 'simpl-schema'; import { updateParent } from '/imports/api/parenting/parenting.js'; -import { insertedDocAtOrder, removedDocAtOrder, updateDocOrder } from '/imports/api/parenting/order.js'; +import { insertedDocAtOrder, removedDocAtOrder, safeUpdateDocOrder } from '/imports/api/parenting/order.js'; import { RefSchema } from '/imports/api/parenting/ChildSchema.js'; import { assertDocEditPermission } from '/imports/api/sharing/sharingPermissions.js'; import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js'; @@ -48,7 +48,7 @@ const reorderDoc = new ValidatedMethod({ run({docRef, order}) { let doc = fetchDocByRef(docRef); assertDocEditPermission(doc, this.userId); - updateDocOrder({docRef, order}) + safeUpdateDocOrder({docRef, order}) }, }); diff --git a/app/imports/ui/components/tree/TreeNodeList.vue b/app/imports/ui/components/tree/TreeNodeList.vue index b0fbddd5..93ab46e5 100644 --- a/app/imports/ui/components/tree/TreeNodeList.vue +++ b/app/imports/ui/components/tree/TreeNodeList.vue @@ -64,8 +64,8 @@ methods: { change({added, moved}){ let event = moved || added; + let newIndex = this.children[event.newIndex].node.order; if (event){ - let newIndex = event.newIndex; let doc = event.element.node; if (moved){ this.$emit('reordered', {doc, newIndex});