Library node editing now includes editing sub-documents and soft removal

This commit is contained in:
Stefan Zermatten
2019-08-02 12:35:59 +02:00
parent 745f4fd353
commit 0b184c4e85
8 changed files with 109 additions and 41 deletions

View File

@@ -3,7 +3,8 @@ import ChildSchema from '/imports/api/parenting/ChildSchema.js';
import librarySchemas from '/imports/api/library/librarySchemas.js';
import Libraries from '/imports/api/library/Libraries.js';
import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js';
import getModifierFields from '/imports/api/getModifierFields.js';
import { softRemove } from '/imports/api/parenting/softRemove.js';
import SoftRemovableSchema from '/imports/api/parenting/SoftRemovableSchema.js';
let LibraryNodes = new Mongo.Collection('libraryNodes');
@@ -16,9 +17,10 @@ let LibraryNodeSchema = new SimpleSchema({
for (let key in librarySchemas){
let schema = new SimpleSchema({});
schema.extend(librarySchemas[key]);
schema.extend(LibraryNodeSchema);
schema.extend(librarySchemas[key]);
schema.extend(ChildSchema);
schema.extend(SoftRemovableSchema);
LibraryNodes.attachSchema(schema, {
selector: {type: key}
});
@@ -46,9 +48,10 @@ const insertNode = new ValidatedMethod({
});
const updateLibraryNode = new ValidatedMethod({
name: 'LibraryNodes.methods.set',
name: 'LibraryNodes.methods.update',
validate({_id, path, value, ack}){
if (!_id) return false;
// We cannot change these with a simple update
switch (path[0]){
case 'type':
case 'order':
@@ -57,23 +60,65 @@ const updateLibraryNode = new ValidatedMethod({
return false;
}
},
run({_id, path, value, ack}) {
run({_id, path, value}) {
let node = LibraryNodes.findOne(_id);
assertNodeEditPermission(node, this.userId);
return LibraryNodes.update(_id, {
$set: {[path.join('.')]: value},
}, {
selector: {type: node.type},
}, error => ack && ack(error));
});
},
});
const pushToLibraryNode = new ValidatedMethod({
name: 'LibraryNodes.methods.push',
validate: null,
run({_id, path, value}){
let node = LibraryNodes.findOne(_id);
assertNodeEditPermission(node, this.userId);
return LibraryNodes.update(_id, {
$push: {[path.join('.')]: value},
}, {
selector: {type: node.type},
});
}
});
const pullFromLibraryNode = new ValidatedMethod({
name: 'LibraryNodes.methods.pull',
validate: null,
run({_id, path, itemId}){
let node = LibraryNodes.findOne(_id);
assertNodeEditPermission(node, this.userId);
return LibraryNodes.update(_id, {
$pull: {[path.join('.')]: {_id: itemId}},
}, {
selector: {type: node.type},
getAutoValues: false,
});
}
});
const softRemoveLibraryNode = new ValidatedMethod({
name: 'LibraryNodes.methods.softRemove',
validate: new SimpleSchema({
_id: SimpleSchema.RegEx.Id
}).validator(),
run({_id}){
let node = LibraryNodes.findOne(_id);
assertNodeEditPermission(node, this.userId);
softRemove({_id, collection: LibraryNodes});
}
});
function libraryNodesToTree(ancestorId){
// Store a dict of all the nodes
let nodeIndex = {};
let nodeList = [];
LibraryNodes.find({
'ancestors.id': ancestorId
'ancestors.id': ancestorId,
removed: {$ne: true},
}, {
sort: {order: 1}
}).forEach( node => {
@@ -98,4 +143,12 @@ function libraryNodesToTree(ancestorId){
}
export default LibraryNodes;
export { LibraryNodeSchema, insertNode, updateLibraryNode, libraryNodesToTree };
export {
LibraryNodeSchema,
insertNode,
updateLibraryNode,
pullFromLibraryNode,
pushToLibraryNode,
softRemoveLibraryNode,
libraryNodesToTree,
};

View File

@@ -32,6 +32,7 @@ export function fetchDescendants({ collection, ancestorId, filter = {}, options}
export function updateDescendants({collection, ancestorId, filter = {}, modifier, options={}}){
filter["ancestors.id"] = ancestorId;
options.multi = true;
options.selector = {type: 'any'};
collection.update(filter, modifier, options);
}

View File

@@ -1,20 +1,29 @@
import getCollectionByName from '/imports/api/parenting/getCollectionByName.js';
import updateDescendants from '/imports/api/parenting/parenting.js';
import { updateDescendants } from '/imports/api/parenting/parenting.js';
// 1 + n database hits
export function softRemove({_id, collection}){
let removalDate = new Date();
if (typeof collection === 'string') {
collection = getCollectionByName(collection);
}
// Remove this document
collection = getCollectionByName(collection);
collection.update(_id, {$set: {
removed: true,
removedAt: removalDate,
}, $unset: {
removedWith: 1,
}});
collection.update(
_id, {
$set: {
removed: true,
removedAt: removalDate,
},
$unset: {
removedWith: 1,
}
}, {
selector: {type: 'any'},
},
);
// Remove all the descendants that have not yet been removed, and set them to be
// removed with this document
updateDescendants({
collection,
ancestorId: _id,
filter: {removed: {$ne: true}},
modifier: {$set: {

View File

@@ -5,9 +5,6 @@ let BuffSchema = new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoValue(){
if (!this.isSet) return Random.id();
}
},
name: {
type: String,

View File

@@ -12,8 +12,9 @@
</template>
<component
v-if="model"
:is="model.type"
class="library-node-form"
stored
:is="model.type"
:model="model"
@change="change"
@push="push"
@@ -32,18 +33,18 @@
</template>
<script>
import LibraryNodes, { updateLibraryNode } from '/imports/api/library/LibraryNodes.js';
import LibraryNodes, {
updateLibraryNode,
pushToLibraryNode,
pullFromLibraryNode,
softRemoveLibraryNode,
} from '/imports/api/library/LibraryNodes.js';
import librarySchemas from '/imports/api/library/librarySchemas.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
import PropertyIcon from '/imports/ui/components/properties/PropertyIcon.vue';
import propertyFormIndex from '/imports/ui/properties/forms/shared/propertyFormIndex.js';
let todo = ({ack}) => {
console.warn('not implemented');
ack && ack();
};
let libraryNodePull = libraryNodePush = libraryNodeRemove = todo;
import { get } from 'lodash';
export default {
components: {
@@ -62,16 +63,28 @@
methods: {
getPropertyName,
change({path, value, ack}){
updateLibraryNode.call({_id: this._id, path, value, ack});
updateLibraryNode.call({_id: this._id, path, value}, (error, result) =>{
console.log({error, result});
ack && ack(error);
});
},
push({path, value, ack}){
libraryNodePush({_id: this._id, path}, e => ack(e));
pushToLibraryNode.call({_id: this._id, path, value}, (error, result) =>{
console.log({error, result});
ack && ack(error);
});
},
pull({path, ack}){
libraryNodePull({_id: this._id, path}, e => ack(e));
let itemId = get(this.model, path)._id;
path.pop();
pullFromLibraryNode.call({_id: this._id, path, itemId}, (error, result) =>{
console.log({error, result});
ack && ack(error);
});
},
remove(){
libraryNodeRemove({_id: this._id});
softRemoveLibraryNode.call({_id: this._id});
this.$store.dispatch('popDialogStack');
},
}
};

View File

@@ -55,16 +55,7 @@ export default {
model.type = newType;
this.model = model;
},
model(newModel){
console.log('model changed');
console.log(newModel);
},
},
methods: {
insert(){
console.log(this.model);
}
}
}
</script>

View File

@@ -109,7 +109,10 @@
return Libraries.findOne(this.$route.params.id);
},
selectedNode(){
return LibraryNodes.findOne(this.selected);
return LibraryNodes.findOne({
_id: this.selected,
removed: {$ne: true}
});
}
}
};

View File

@@ -3,6 +3,7 @@
* inputs, and sends update events when valid data model changes must occur
*/
import { get, toPath } from 'lodash';
function resolvePath(model, path){
let arrayPath = toPath(path);
if (arrayPath.length === 1){