diff --git a/app/imports/api/creature/Creatures.js b/app/imports/api/creature/Creatures.js index 625f8f07..92f031f7 100644 --- a/app/imports/api/creature/Creatures.js +++ b/app/imports/api/creature/Creatures.js @@ -1,10 +1,11 @@ import SimpleSchema from 'simpl-schema'; -import deathSaveSchema from "/imports/api/properties/subSchemas/DeathSavesSchema.js" -import ColorSchema from "/imports/api/properties/subSchemas/ColorSchema.js"; +import deathSaveSchema from '/imports/api/properties/subSchemas/DeathSavesSchema.js' +import ColorSchema from '/imports/api/properties/subSchemas/ColorSchema.js'; import SharingSchema from '/imports/api/sharing/SharingSchema.js'; +import {assertEditPermission, assertOwnership} from '/imports/api/sharing/sharingPermissions.js'; //set up the collection for creatures -Creatures = new Mongo.Collection("creatures"); +Creatures = new Mongo.Collection('creatures'); let CreatureSettingsSchema = new SimpleSchema({ //slowed down by carrying too much? @@ -28,25 +29,25 @@ let CreatureSchema = new SimpleSchema({ // Strings name: { type: String, - defaultValue: "", + defaultValue: '', optional: true, }, urlName: { type: String, optional: true, autoValue: function() { - return getSlug(this.field("name").value, {maintainCase: true}) || "-"; + return getSlug(this.field('name').value, {maintainCase: true}) || '-'; }, }, alignment: { type: String, optional: true }, - gender: { + gender: { type: String, optional: true }, - picture: { + picture: { type: String, optional: true }, @@ -70,8 +71,8 @@ let CreatureSchema = new SimpleSchema({ }, type: { type: String, - defaultValue: "pc", - allowedValues: ["pc", "npc", "monster"], + defaultValue: 'pc', + allowedValues: ['pc', 'npc', 'monster'], }, variables: { type: Object, @@ -93,14 +94,14 @@ Creatures.attachSchema(CreatureSchema); const insertCreature = new ValidatedMethod({ - name: "Creatures.methods.insertCreature", + name: 'Creatures.methods.insertCreature', validate: null, run() { if (!this.userId) { - throw new Meteor.Error("Creatures.methods.insert.denied", - "You need to be logged in to insert a creature"); + throw new Meteor.Error('Creatures.methods.insert.denied', + 'You need to be logged in to insert a creature'); } // Create the creature document @@ -114,15 +115,36 @@ const insertCreature = new ValidatedMethod({ }); const removeCreature = new ValidatedMethod({ - name: 'Creature.methods.remove', + name: 'Creatures.methods.remove', validate: null, run({charId}) { - assertCreatureEditPermission(charId, this.userId); + let creature = Creatures.findOne(_id); + assertOwnership(creature, this.userId); let _id = CreatureProperties.insert(creatureProperty); let property = CreatureProperties.findOne(_id); recomputeCreatures(property); }, }); +const updateCreature = new ValidatedMethod({ + name: 'Creatures.methods.update', + validate({_id, path, value, ack}){ + if (!_id) return false; + // Allowed fields + let allowedFields = ['name', 'alignment', 'gender', 'picture', 'settings']; + if (!allowedFields.includes(path[0])){ + throw new Meteor.Error('Creatures.methods.update.denied', + 'This field can\'t be updated using this method'); + } + }, + run({_id, path, value}) { + let creature = Creatures.findOne(_id); + assertEditPermission(creature, this.userId); + Creatures.update(_id, { + $set: {[path.join('.')]: value}, + }); + }, +}); + export default Creatures; -export { CreatureSchema, insertCreature, removeCreature }; +export { CreatureSchema, insertCreature, removeCreature, updateCreature }; diff --git a/app/imports/ui/creature/CreatureForm.vue b/app/imports/ui/creature/CreatureForm.vue new file mode 100644 index 00000000..bc6e8b7c --- /dev/null +++ b/app/imports/ui/creature/CreatureForm.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/app/imports/ui/creature/CreatureFormDialog.vue b/app/imports/ui/creature/CreatureFormDialog.vue new file mode 100644 index 00000000..b2ea5d65 --- /dev/null +++ b/app/imports/ui/creature/CreatureFormDialog.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/app/imports/ui/creature/character/CharacterSheet.vue b/app/imports/ui/creature/character/CharacterSheet.vue index d3c88f60..88740513 100644 --- a/app/imports/ui/creature/character/CharacterSheet.vue +++ b/app/imports/ui/creature/character/CharacterSheet.vue @@ -4,10 +4,14 @@ menu - + refresh {{character.name}} + + + more + edit @@ -116,7 +116,7 @@ creatureProperty.parent = {collection: "creatures", id: that.creatureId}; creatureProperty.ancestors = [ {collection: "creatures", id: that.creatureId}]; setDocToLastOrder({collection: CreatureProperties, doc: creatureProperty}); - let creaturePropertyId = insertProperty.call(creatureProperty); + let creaturePropertyId = insertProperty.call({creatureProperty}); return creaturePropertyId; } }); diff --git a/app/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue b/app/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue index c2f5e085..efc00057 100644 --- a/app/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue +++ b/app/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue @@ -105,13 +105,13 @@ export default { change({path, value, ack}){ updateProperty.call({_id: this._id, path, value}, (error, result) =>{ console.log({error, result}); - ack && ack(error); + ack && ack(error && error.reason || error); }); }, push({path, value, ack}){ pushToProperty.call({_id: this._id, path, value}, (error, result) =>{ console.log({error, result}); - ack && ack(error); + ack && ack(error && error.reason || error); }); }, pull({path, ack}){ @@ -119,7 +119,7 @@ export default { path.pop(); pullFromProperty.call({_id: this._id, path, itemId}, (error, result) =>{ console.log({error, result}); - ack && ack(error); + ack && ack(error && error.reason || error); }); }, remove(){ diff --git a/app/imports/ui/dialogStack/DialogComponentIndex.js b/app/imports/ui/dialogStack/DialogComponentIndex.js index 5f119bd1..f70e8e7a 100644 --- a/app/imports/ui/dialogStack/DialogComponentIndex.js +++ b/app/imports/ui/dialogStack/DialogComponentIndex.js @@ -1,6 +1,7 @@ import AttributeDialog from '/imports/ui/properties/attributes/AttributeDialog.vue'; import AttributeDialogContainer from '/imports/ui/properties/attributes/AttributeDialogContainer.vue'; import AttributeCreationDialog from '/imports/ui/properties/attributes/AttributeCreationDialog.vue'; +import CreatureFormDialog from '/imports/ui/creature/CreatureFormDialog.vue'; import CreaturePropertyCreationDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue'; import CreaturePropertyDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue' import CreaturePropertyFromLibraryDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue' @@ -15,6 +16,7 @@ export default { AttributeDialog, AttributeDialogContainer, AttributeCreationDialog, + CreatureFormDialog, CreaturePropertyCreationDialog, CreaturePropertyDialog, CreaturePropertyFromLibraryDialog, diff --git a/app/imports/ui/library/LibraryNodeEditDialog.vue b/app/imports/ui/library/LibraryNodeEditDialog.vue index 8b57150a..9f72169a 100644 --- a/app/imports/ui/library/LibraryNodeEditDialog.vue +++ b/app/imports/ui/library/LibraryNodeEditDialog.vue @@ -64,13 +64,13 @@ change({path, value, ack}){ updateLibraryNode.call({_id: this._id, path, value}, (error, result) =>{ console.log({error, result}); - ack && ack(error); + ack && ack(error && error.reason || error); }); }, push({path, value, ack}){ pushToLibraryNode.call({_id: this._id, path, value}, (error, result) =>{ console.log({error, result}); - ack && ack(error); + ack && ack(error && error.reason || error); }); }, pull({path, ack}){ @@ -78,7 +78,7 @@ path.pop(); pullFromLibraryNode.call({_id: this._id, path, itemId}, (error, result) =>{ console.log({error, result}); - ack && ack(error); + ack && ack(error && error.reason || error); }); }, remove(){