Trees can now be freely re-arranged :D
This commit is contained in:
@@ -51,7 +51,7 @@ export function getHighestOrder({collection, parentId}){
|
||||
fields: {order: 1},
|
||||
sort: {order: -1},
|
||||
});
|
||||
return (highestOrderedDoc && highestOrderedDoc.order) || 0;
|
||||
return highestOrderedDoc ? highestOrderedDoc.order : -1;
|
||||
}
|
||||
|
||||
export function setDocToLastOrder({collection, doc}){
|
||||
@@ -61,7 +61,7 @@ export function setDocToLastOrder({collection, doc}){
|
||||
}) + 1;
|
||||
}
|
||||
|
||||
export function updateOrder({docRef, order}){
|
||||
export function updateDocOrder({docRef, order}){
|
||||
let doc = fetchDocByRef(docRef, {fields: {
|
||||
order: 1,
|
||||
parent: 1,
|
||||
@@ -71,8 +71,7 @@ export function updateOrder({docRef, order}){
|
||||
if (currentOrder === order){
|
||||
return;
|
||||
} else {
|
||||
// Move the document to its new order
|
||||
collection.update(doc._id, {$set: {order}}, {selector: {type: 'any'}});
|
||||
// First move the documents that are in the way
|
||||
let inBetweenSelector, increment;
|
||||
if (order > currentOrder){
|
||||
// Move in-between docs backward
|
||||
@@ -98,9 +97,37 @@ export function updateOrder({docRef, order}){
|
||||
multi: true,
|
||||
selector: {type: 'any'},
|
||||
});
|
||||
// Then move the document itself
|
||||
collection.update(doc._id, {$set: {order}}, {selector: {type: 'any'}});
|
||||
}
|
||||
}
|
||||
|
||||
export function removedDocAtOrder({collection, doc}){
|
||||
// Decrement the order of all docs after the removed doc
|
||||
collection.update({
|
||||
'parent.id': doc.parent.id,
|
||||
order: {$gt: doc.order},
|
||||
}, {
|
||||
$inc: {order: -1},
|
||||
}, {
|
||||
multi: true,
|
||||
selector: {type: 'any'},
|
||||
});
|
||||
}
|
||||
|
||||
export function insertedDocAtOrder({collection, parentId, order}){
|
||||
// Decrement the order of all docs after the removed doc
|
||||
collection.update({
|
||||
'parent.id': parentId,
|
||||
order: {$gte: order},
|
||||
}, {
|
||||
$inc: {order: 1},
|
||||
}, {
|
||||
multi: true,
|
||||
selector: {type: 'any'},
|
||||
});
|
||||
}
|
||||
|
||||
export function reorderDocs({collection, parentId}){
|
||||
let bulkWrite = [];
|
||||
collection.find({
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import { updateParent } from '/imports/api/parenting/parenting.js';
|
||||
import { updateOrder } from '/imports/api/parenting/order.js';
|
||||
import { insertedDocAtOrder, removedDocAtOrder, updateDocOrder } 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';
|
||||
import getCollectionByName from '/imports/api/parenting/getCollectionByName.js';
|
||||
|
||||
const organizeDoc = new ValidatedMethod({
|
||||
name: 'organize.methods.organizeDoc',
|
||||
@@ -17,14 +18,21 @@ const organizeDoc = new ValidatedMethod({
|
||||
}).validator(),
|
||||
run({docRef, parentRef, order}) {
|
||||
let doc = fetchDocByRef(docRef);
|
||||
|
||||
let collection = getCollectionByName(docRef.collection);
|
||||
// The user must be able to edit both the doc and its parent to move it
|
||||
// successfully
|
||||
assertDocEditPermission(doc, this.userId);
|
||||
let parent = fetchDocByRef(parentRef);
|
||||
assertDocEditPermission(parent, this.userId);
|
||||
|
||||
// Reorder the documents in the doc's old parent
|
||||
removedDocAtOrder({collection, doc});
|
||||
// Reorder the docs in the destination parent
|
||||
insertedDocAtOrder({collection, parentId: parentRef.id, order});
|
||||
// Change the doc's parent
|
||||
updateParent({docRef, parentRef});
|
||||
updateOrder({docRef, order})
|
||||
// Change the doc's order
|
||||
collection.update(doc._id, {$set: {order}}, {selector: {type: 'any'}});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -40,7 +48,7 @@ const reorderDoc = new ValidatedMethod({
|
||||
run({docRef, order}) {
|
||||
let doc = fetchDocByRef(docRef);
|
||||
assertDocEditPermission(doc, this.userId);
|
||||
updateOrder({docRef, order})
|
||||
updateDocOrder({docRef, order})
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@ export function forEachDescendant({collection, ancestorId, filter = {}, options}
|
||||
|
||||
// 1 database read
|
||||
export function getAncestry({parentRef, inheritedFields = {}}){
|
||||
// Ancestry must include ancestors
|
||||
inheritedFields.ancestors = 1;
|
||||
|
||||
let parentDoc = fetchDocByRef(parentRef, {fields: inheritedFields});
|
||||
let parent = { ...parentRef};
|
||||
for (let field in inheritedFields){
|
||||
@@ -66,24 +63,30 @@ export function updateParent({docRef, parentRef}){
|
||||
parent: 1,
|
||||
ancestors: 1,
|
||||
}});
|
||||
let updateOptions = { selector: {type: 'any'} };
|
||||
|
||||
// Skip if we aren't changing the parent id
|
||||
if (oldDoc.parent.id === parentRef.id) return;
|
||||
|
||||
// update the document's parenting
|
||||
let {parent, ancestors} = getAncestry({parentRef});
|
||||
collection.update(docRef.id, {$set: {parent, ancestors}});
|
||||
collection.update(docRef.id, {
|
||||
$set: {parent, ancestors}
|
||||
}, updateOptions);
|
||||
|
||||
// Remove the old ancestors from the descendants
|
||||
updateDescendants({
|
||||
collection,
|
||||
ancestorId: docRef.id,
|
||||
modifier: {$pullAll: {
|
||||
ancestors: oldDoc.ancestors,
|
||||
}},
|
||||
options: updateOptions,
|
||||
});
|
||||
|
||||
// Add the new ancestors to the descendants
|
||||
updateDescendants({
|
||||
collection,
|
||||
ancestorId: docRef.id,
|
||||
modifier: {$push: {
|
||||
ancestors: {
|
||||
@@ -91,6 +94,7 @@ export function updateParent({docRef, parentRef}){
|
||||
$position: 0,
|
||||
},
|
||||
}},
|
||||
options: updateOptions,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ let AttributeSchema = new SimpleSchema({
|
||||
defaultValue: 'newAttribute',
|
||||
},
|
||||
// How it is displayed and computed is determined by type
|
||||
type: {
|
||||
attributeType: {
|
||||
type: String,
|
||||
allowedValues: [
|
||||
'ability', //Strength, Dex, Con, etc.
|
||||
|
||||
@@ -45,7 +45,11 @@ export function assertEditPermission(doc, userId) {
|
||||
|
||||
function getRoot(doc){
|
||||
assertdocExists(doc);
|
||||
return fetchDocByRef(doc.ancestors && doc.ancestors.length && doc.ancestors[0] || doc);
|
||||
if (doc.ancestors && doc.ancestors.length && doc.ancestors[0]){
|
||||
return fetchDocByRef(doc.ancestors[0]);
|
||||
} else {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template lang="html">
|
||||
<div :class="!hasChildren ? 'empty' : null">
|
||||
<div :class="!hasChildren ? 'empty' : null" :data-id="node._id">
|
||||
<div class="layout row align-center">
|
||||
<v-btn
|
||||
small icon
|
||||
@@ -9,9 +9,10 @@
|
||||
>
|
||||
<v-icon v-if="hasChildren || organize">chevron_right</v-icon>
|
||||
</v-btn>
|
||||
<v-icon class="handle mr-2" v-if="organize">reorder</v-icon>
|
||||
<v-icon class="handle mr-2" v-if="organize" :disabled="expanded">reorder</v-icon>
|
||||
<div>
|
||||
<span class="mr-2 subheading">{{node && node.order}}</span>
|
||||
<span class="mr-2 caption">{{node && node.order}}</span>
|
||||
<span class="mr-2 caption">({{node && node.type}})</span>
|
||||
{{node && node.name}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,7 +22,7 @@
|
||||
:node="node"
|
||||
:children="computedChildren"
|
||||
:group="group"
|
||||
:show-empty="organize"
|
||||
:organize="organize"
|
||||
@reordered="e => $emit('reordered', e)"
|
||||
@reorganized="e => $emit('reorganized', e)"
|
||||
/>
|
||||
@@ -95,4 +96,7 @@
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
.v-icon--disabled {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
:value="children"
|
||||
class="drag-area layout column"
|
||||
@change="change"
|
||||
@start="start"
|
||||
:group="group"
|
||||
:animation="200"
|
||||
ghost-class="ghost"
|
||||
@@ -67,6 +68,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
start(){
|
||||
console.log({start: arguments})
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
<smart-select
|
||||
label="Type"
|
||||
:items="attributeTypes"
|
||||
:value="model.type"
|
||||
:error-messages="errors.type"
|
||||
:value="model.attributeType"
|
||||
:error-messages="errors.attributeType"
|
||||
:menu-props="{auto: true, lazy: true}"
|
||||
@change="(value, ack) => $emit('change', {path: ['type'], value, ack})"
|
||||
:hint="attributeTypeHints[model.type]"
|
||||
@change="(value, ack) => $emit('change', {path: ['attributeType'], value, ack})"
|
||||
:hint="attributeTypeHints[model.attributeType]"
|
||||
:debounce-time="debounceTime"
|
||||
/>
|
||||
<form-section name="Advanced" standalone>
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
let parentRef;
|
||||
if (parent){
|
||||
parentRef = {
|
||||
id: this.libraryId,
|
||||
collection: 'libraries',
|
||||
id: parent._id,
|
||||
collection: 'libraryNodes',
|
||||
};
|
||||
} else {
|
||||
parentRef = {
|
||||
id: parent._id,
|
||||
collection: 'libraryNodes',
|
||||
id: this.libraryId,
|
||||
collection: 'libraries',
|
||||
};
|
||||
}
|
||||
organizeDoc.call({
|
||||
|
||||
Reference in New Issue
Block a user