From 9757da2caea1c57d4ee07bb7d2759c17f5e4830b Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 27 Jun 2019 16:52:28 +0200 Subject: [PATCH] Started work on library node insert forms --- app/imports/api/library/LibraryNodes.js | 15 +++++- app/imports/server/publications/library.js | 1 + .../ui/components/forms/schemaFormMixin.js | 30 ++++++++++++ .../ui/components/global/SmartInputMixin.js | 4 +- .../properties/PropertySelector.vue | 47 +++++++++++++++++++ .../attributes/AttributeCreationDialog.vue | 6 +-- app/imports/ui/dialogStack/DialogBase.vue | 13 ++++- .../ui/dialogStack/DialogComponentIndex.js | 2 + .../ui/library/LibraryNodeCreationDialog.vue | 42 +++++++++++++++++ app/imports/ui/pages/Library.vue | 21 +++++++++ 10 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 app/imports/ui/components/forms/schemaFormMixin.js create mode 100644 app/imports/ui/components/properties/PropertySelector.vue create mode 100644 app/imports/ui/library/LibraryNodeCreationDialog.vue diff --git a/app/imports/api/library/LibraryNodes.js b/app/imports/api/library/LibraryNodes.js index 37426c1c..197131db 100644 --- a/app/imports/api/library/LibraryNodes.js +++ b/app/imports/api/library/LibraryNodes.js @@ -5,6 +5,7 @@ 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 simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js'; let LibraryNodes = new Mongo.Collection('libraryNodes'); @@ -62,6 +63,18 @@ function assertNodeEditPermission(node, userId){ return assertEditPermission(lib, userId); } +const insertNode = new ValidatedMethod({ + name: 'LibraryNodes.methods.insert', + mixins: [ + simpleSchemaMixin, + ], + schema: LibraryNodeSchema, + run(libraryNode) { + assertNodeEditPermission(libraryNode, this.userId); + return LibraryNodes.insert(libraryNode); + }, +}); + const updateNode = new ValidatedMethod({ name: 'LibraryNodes.methods.update', validate({_id, update}){ @@ -101,4 +114,4 @@ function libraryNodesToTree(ancestorId){ } export default LibraryNodes; -export { LibraryNodeSchema, updateNode }; +export { LibraryNodeSchema, insertNode, updateNode }; diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js index 0e9219d9..18d6394f 100644 --- a/app/imports/server/publications/library.js +++ b/app/imports/server/publications/library.js @@ -46,6 +46,7 @@ Meteor.publish('library', function(libraryId){ const user = Meteor.user(); const userId = user && user._id; if (!userId) return []; + const subs = user && user.subscribedLibraries || []; let libraryCursor = Libraries.find({ _id: libraryId, $or: [ diff --git a/app/imports/ui/components/forms/schemaFormMixin.js b/app/imports/ui/components/forms/schemaFormMixin.js new file mode 100644 index 00000000..d8dabe3f --- /dev/null +++ b/app/imports/ui/components/forms/schemaFormMixin.js @@ -0,0 +1,30 @@ +/** + * Forms that take in a schema and a model of the current data, manages smart + * inputs, and sends update events when valid data model changes must occur + */ +export default function schemaFormMixin(schema){ + return { + data(){ return { + valid: true, + };}, + created(){ + this.validationContext = schema.newContext(); + }, + computed: { + errors(){ + this.valid = true; + if (!this.model){ + throw new Error("this.model must be set"); + } + let cleanModel = this.validationContext.clean(this.model); + this.validationContext.validate(cleanModel); + let errors = {}; + this.validationContext.validationErrors().forEach(error => { + if (this.valid) this.valid = false; + errors[error.name] = Attributes.simpleSchema().messageForError(error); + }); + return errors; + }, + }, + }; +} diff --git a/app/imports/ui/components/global/SmartInputMixin.js b/app/imports/ui/components/global/SmartInputMixin.js index d0574f0d..5e643881 100644 --- a/app/imports/ui/components/global/SmartInputMixin.js +++ b/app/imports/ui/components/global/SmartInputMixin.js @@ -79,11 +79,11 @@ export default { this.$emit('change', val, this.acknowledgeChange); }, hasChangeListener(){ - return this.$listeners && this.$listeners.change + return this.$listeners && this.$listeners.change; }, forceSafeValueUpdate(){ // hack to force the value to update on the child component - this.safeValue = null + this.safeValue = null; this.$nextTick(() => this.safeValue = this.value); }, }, diff --git a/app/imports/ui/components/properties/PropertySelector.vue b/app/imports/ui/components/properties/PropertySelector.vue new file mode 100644 index 00000000..4087d06a --- /dev/null +++ b/app/imports/ui/components/properties/PropertySelector.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/app/imports/ui/creature/properties/attributes/AttributeCreationDialog.vue b/app/imports/ui/creature/properties/attributes/AttributeCreationDialog.vue index 1dfcc7ff..07ba3aad 100644 --- a/app/imports/ui/creature/properties/attributes/AttributeCreationDialog.vue +++ b/app/imports/ui/creature/properties/attributes/AttributeCreationDialog.vue @@ -44,6 +44,9 @@ }, valid: true, }}, + created(){ + this.validationContext = Attributes.simpleSchema().newContext(); + }, methods: { change(update, ack){ for (key in update){ @@ -58,9 +61,6 @@ if (ack) ack(); }, }, - created(){ - this.validationContext = Attributes.simpleSchema().newContext(); - }, computed: { errors(){ this.valid = true; diff --git a/app/imports/ui/dialogStack/DialogBase.vue b/app/imports/ui/dialogStack/DialogBase.vue index 8a42574c..ff219374 100644 --- a/app/imports/ui/dialogStack/DialogBase.vue +++ b/app/imports/ui/dialogStack/DialogBase.vue @@ -1,10 +1,10 @@