Library nodes can now be edited :D

This commit is contained in:
Stefan Zermatten
2019-08-02 10:47:29 +02:00
parent 3c4f3e26f8
commit 745f4fd353
13 changed files with 110 additions and 80 deletions

View File

@@ -45,21 +45,26 @@ const insertNode = new ValidatedMethod({
}, },
}); });
const updateNode = new ValidatedMethod({ const updateLibraryNode = new ValidatedMethod({
name: 'LibraryNodes.methods.update', name: 'LibraryNodes.methods.set',
validate({_id, update}){ validate({_id, path, value, ack}){
let fields = getModifierFields(update); if (!_id) return false;
return !fields.hasAny([ switch (path[0]){
'type', case 'type':
'order', case 'order':
'parent', case 'parent':
'ancestors', case 'ancestors':
]); return false;
}
}, },
run({_id, update}) { run({_id, path, value, ack}) {
let node = LibraryNodes.findOne(_id); let node = LibraryNodes.findOne(_id);
assertNodeEditPermission(node, this.userId); assertNodeEditPermission(node, this.userId);
return LibraryNodes.update(_id, update); return LibraryNodes.update(_id, {
$set: {[path.join('.')]: value},
}, {
selector: {type: node.type},
}, error => ack && ack(error));
}, },
}); });
@@ -93,4 +98,4 @@ function libraryNodesToTree(ancestorId){
} }
export default LibraryNodes; export default LibraryNodes;
export { LibraryNodeSchema, insertNode, updateNode, libraryNodesToTree }; export { LibraryNodeSchema, insertNode, updateLibraryNode, libraryNodesToTree };

View File

@@ -44,7 +44,7 @@
import ColorPicker from '/imports/ui/components/ColorPicker.Story.vue'; import ColorPicker from '/imports/ui/components/ColorPicker.Story.vue';
import ColumnLayout from "/imports/ui/components/ColumnLayout.Story.vue"; import ColumnLayout from "/imports/ui/components/ColumnLayout.Story.vue";
import DialogStack from '/imports/ui/dialogStack/DialogStack.Story.vue'; import DialogStack from '/imports/ui/dialogStack/DialogStack.Story.vue';
import EffectEditExpansionList from '/imports/ui/properties/effects/EffectEditExpansionList.Story.vue'; import EffectEditExpansionList from '/imports/ui/properties/viewers/shared/effects/EffectEditExpansionList.Story.vue';
import FeatureCard from '/imports/ui/properties/features/FeatureCard.Story.vue'; import FeatureCard from '/imports/ui/properties/features/FeatureCard.Story.vue';
import HealthBar from '/imports/ui/properties/attributes/HealthBar.Story.vue'; import HealthBar from '/imports/ui/properties/attributes/HealthBar.Story.vue';
import HitDiceListTile from '/imports/ui/properties/attributes/HitDiceListTile.Story.vue'; import HitDiceListTile from '/imports/ui/properties/attributes/HitDiceListTile.Story.vue';

View File

@@ -5,6 +5,7 @@ import FeatureCreationDialog from '/imports/ui/properties/features/FeatureCreati
import FeatureDialogContainer from '/imports/ui/properties/features/FeatureDialogContainer.vue'; import FeatureDialogContainer from '/imports/ui/properties/features/FeatureDialogContainer.vue';
import LibraryCreationDialog from '/imports/ui/library/LibraryCreationDialog.vue'; import LibraryCreationDialog from '/imports/ui/library/LibraryCreationDialog.vue';
import LibraryNodeCreationDialog from '/imports/ui/library/LibraryNodeCreationDialog.vue'; import LibraryNodeCreationDialog from '/imports/ui/library/LibraryNodeCreationDialog.vue';
import LibraryNodeEditDialog from '/imports/ui/library/LibraryNodeEditDialog.vue';
import SkillDialogContainer from '/imports/ui/properties/skills/SkillDialogContainer.vue'; import SkillDialogContainer from '/imports/ui/properties/skills/SkillDialogContainer.vue';
export default { export default {
@@ -15,5 +16,6 @@ export default {
FeatureDialogContainer, FeatureDialogContainer,
LibraryCreationDialog, LibraryCreationDialog,
LibraryNodeCreationDialog, LibraryNodeCreationDialog,
LibraryNodeEditDialog,
SkillDialogContainer, SkillDialogContainer,
}; };

View File

@@ -1,14 +1,18 @@
<template lang="html"> <template lang="html">
<dialog-base v-show="step == 1" class="step-1" key="left"> <dialog-base>
<template slot="toolbar"> <template slot="toolbar">
<div>Add {{propertyName}}</div> <property-icon :type="model.type" class="mr-2"/>
<div class="title">
{{getPropertyName(model.type)}}
</div>
<v-spacer/>
<v-btn icon flat @click="remove"> <v-btn icon flat @click="remove">
<v-icon>delete</v-icon> <v-icon>delete</v-icon>
</v-btn> </v-btn>
</template> </template>
<component <component
v-if="type" v-if="model"
:is="type" :is="model.type"
class="library-node-form" class="library-node-form"
:model="model" :model="model"
@change="change" @change="change"
@@ -21,7 +25,6 @@
> >
<v-btn <v-btn
flat flat
:disabled="!valid"
@click="$store.dispatch('popDialogStack')" @click="$store.dispatch('popDialogStack')"
>Done</v-btn> >Done</v-btn>
</div> </div>
@@ -29,41 +32,49 @@
</template> </template>
<script> <script>
import librarySchemas from '/imports/api/library/librarySchemas.js'; import LibraryNodes, { updateLibraryNode } from '/imports/api/library/LibraryNodes.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue'; import librarySchemas from '/imports/api/library/librarySchemas.js';
import propertyFormIndex from '/imports/ui/properties/forms/shared/propertyFormIndex.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 = () => console.log('not implemented'); let todo = ({ack}) => {
let libraryNodeSet = libraryNodePull = libraryNodePush = libraryNodeRemove = todo; console.warn('not implemented');
ack && ack();
};
let libraryNodePull = libraryNodePush = libraryNodeRemove = todo;
export default { export default {
components: { components: {
...propertyFormIndex, ...propertyFormIndex,
DialogBase, PropertyIcon,
}, DialogBase,
props: { },
_id: String, props: {
}, _id: String,
meteor: {
model(){
return LibrarNodes.findOne(this._id);
}, },
}, meteor: {
methods: { model(){
change({path, value, ack}){ return LibraryNodes.findOne(this._id);
libraryNodeSet({_id: this._id, path, value}, e => ack(e)); },
}, },
push({path, value, ack}){ methods: {
libraryNodePush({_id: this._id, path}, e => ack(e)); getPropertyName,
}, change({path, value, ack}){
pull({path, ack}){ updateLibraryNode.call({_id: this._id, path, value, ack});
libraryNodePull({_id: this._id, path}, e => ack(e)); },
}, push({path, value, ack}){
remove(){ libraryNodePush({_id: this._id, path}, e => ack(e));
libraryNodeRemove({_id: this._id}); },
}, pull({path, ack}){
} libraryNodePull({_id: this._id, path}, e => ack(e));
}; },
remove(){
libraryNodeRemove({_id: this._id});
},
}
};
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>

View File

@@ -7,7 +7,7 @@
{{library && library.name || 'Library'}} {{library && library.name || 'Library'}}
<v-spacer/> <v-spacer/>
</template> </template>
<v-card class="ma-4 layout row"> <v-card class="ma-4 layout row" data-id="library-card">
<div> <div>
<v-toolbar dense flat> <v-toolbar dense flat>
<v-spacer/> <v-spacer/>
@@ -19,21 +19,21 @@
/> />
</v-toolbar> </v-toolbar>
<library-contents-container <library-contents-container
:library-id="$route.params.id" :library-id="$route.params.id"
:organize="organize" :organize="organize"
@selected="e => selected = e" @selected="e => selected = e"
:selected-node-id="selected" :selected-node-id="selected"
/> />
</div> </div>
<v-divider vertical/> <v-divider vertical/>
<div style="width: 100%;"> <div style="width: 100%; background-color: inherit;" data-id="selected-node-card">
<v-toolbar dense flat> <v-toolbar dense flat>
<property-icon :type="selectedNode && selectedNode.type" class="mr-2"/> <property-icon :type="selectedNode && selectedNode.type" class="mr-2"/>
<div class="title"> <div class="title">
{{getPropertyName(selectedNode && selectedNode.type)}} {{getPropertyName(selectedNode && selectedNode.type)}}
</div> </div>
<v-spacer/> <v-spacer/>
<v-btn flat icon> <v-btn flat icon @click="editLibraryNode" v-if="selectedNode">
<v-icon>create</v-icon> <v-icon>create</v-icon>
</v-btn> </v-btn>
</v-toolbar> </v-toolbar>
@@ -84,12 +84,19 @@
libraryNode.parent = {collection: "libraries", id: that.library._id}; libraryNode.parent = {collection: "libraries", id: that.library._id};
libraryNode.ancestors = [ {collection: "libraries", id: that.library._id}]; libraryNode.ancestors = [ {collection: "libraries", id: that.library._id}];
setDocToLastOrder({collection: LibraryNodes, doc: libraryNode}); setDocToLastOrder({collection: LibraryNodes, doc: libraryNode});
console.log(libraryNode);
let libraryNodeId = insertNode.call(libraryNode); let libraryNodeId = insertNode.call(libraryNode);
return libraryNodeId; return libraryNodeId;
} }
}); });
}, },
editLibraryNode(){
let that = this;
this.$store.commit('pushDialogStack', {
component: 'library-node-edit-dialog',
elementId: 'selected-node-card',
data: {_id: this.selected},
});
},
getPropertyName, getPropertyName,
}, },
meteor: { meteor: {

View File

@@ -35,7 +35,7 @@
<script> <script>
import DialogBase from "/imports/ui/dialogStack/DialogBase.vue"; import DialogBase from "/imports/ui/dialogStack/DialogBase.vue";
import EffectChildList from '/imports/ui/properties/effects/EffectChildList.vue'; import EffectChildList from '/imports/ui/properties/viewers/shared/effects/EffectChildList.vue';
import AttributeForm from '/imports/ui/properties/forms/AttributeForm.vue'; import AttributeForm from '/imports/ui/properties/forms/AttributeForm.vue';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';

View File

@@ -27,7 +27,7 @@
</template> </template>
<script> <script>
import EffectChildList from '/imports/ui/properties/effects/EffectChildList.vue'; import EffectChildList from '/imports/ui/properties/viewers/shared/effects/EffectChildList.vue';
import DialogBase from "/imports/ui/dialogStack/DialogBase.vue"; import DialogBase from "/imports/ui/dialogStack/DialogBase.vue";
import SkillEdit from '/imports/ui/properties/skills/SkillEdit.vue'; import SkillEdit from '/imports/ui/properties/skills/SkillEdit.vue';
import SkillProficiencyList from '/imports/ui/properties/skills/SkillProficiencyList.vue'; import SkillProficiencyList from '/imports/ui/properties/skills/SkillProficiencyList.vue';

View File

@@ -11,24 +11,21 @@
<div v-if="model.mod !== undefined"> <div v-if="model.mod !== undefined">
{{numberToSignedString(model.mod)}} {{numberToSignedString(model.mod)}}
</div> </div>
<div class="title"> <h1 class="display-1">
{{model.name}} {{model.name}}
</div> </h1>
<div> <p class="my-2">
<code>{{model.variableName}}</code> <code>{{model.variableName}}</code>
</div> </p>
<div> <p v-if="reset">
{{model.attributeType}}
</div>
<div>
Base value: {{model.baseValue}}
</div>
<div v-if="reset">
{{reset}} {{reset}}
</div> </p>
<div v-if="model.resetMultiplier"> <effect-list-tile
Reset multiplier: {{model.resetMultiplier}} class="mb-3"
</div> operation="base"
:result="model.baseValue"
:name="model.attributeType"
/>
<p v-if="model.description"> <p v-if="model.description">
{{model.description}} {{model.description}}
</p> </p>
@@ -37,8 +34,12 @@
<script> <script>
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import EffectListTile from '/imports/ui/properties/viewers/shared/effects/EffectListTile.vue';
export default { export default {
components: {
EffectListTile,
},
props: { props: {
model: Object, model: Object,
required: true, required: true,
@@ -50,9 +51,13 @@
reset(){ reset(){
let reset = this.model.reset let reset = this.model.reset
if (reset === 'shortRest'){ if (reset === 'shortRest'){
return 'Reset on a short rest'; return `Reset${
this.model.resetMultiplier && ' x' + this.model.resetMultiplier
} on a short rest`;
} else if (reset === 'longRest'){ } else if (reset === 'longRest'){
return 'Reset on a long rest'; return `Reset${
this.model.resetMultiplier && ' x' + this.model.resetMultiplier
} on a long rest`;
} }
} }
} }

View File

@@ -11,7 +11,7 @@
</template> </template>
<script> <script>
import EffectListTile from '/imports/ui/properties/effects/EffectListTile.vue'; import EffectListTile from '/imports/ui/properties/viewers/shared/effects/EffectListTile.vue';
import sortEffects from '/imports/ui/utility/sortEffects.js'; import sortEffects from '/imports/ui/utility/sortEffects.js';
export default { export default {

View File

@@ -7,7 +7,7 @@
</template> </template>
<script> <script>
import EffectEditExpansionList from '/imports/ui/properties/effects/EffectEditExpansionList.vue'; import EffectEditExpansionList from '/imports/ui/properties/viewers/shared/effects/EffectEditExpansionList.vue';
export default { export default {
data(){ return { data(){ return {
effects: [ effects: [

View File

@@ -25,7 +25,7 @@
<script> <script>
import EffectForm from '/imports/ui/properties/forms/EffectForm.vue'; import EffectForm from '/imports/ui/properties/forms/EffectForm.vue';
import EffectListTile from '/imports/ui/properties/effects/EffectListTile.vue'; import EffectListTile from '/imports/ui/properties/viewers/shared/effects/EffectListTile.vue';
export default { export default {
props: { props: {
effects: Array, effects: Array,