Libraries can now be deleted
This commit is contained in:
@@ -116,21 +116,9 @@ const insertCreature = new ValidatedMethod({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeCreature = new ValidatedMethod({
|
|
||||||
name: 'Creatures.methods.remove',
|
|
||||||
validate: null,
|
|
||||||
run({charId}) {
|
|
||||||
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({
|
const updateCreature = new ValidatedMethod({
|
||||||
name: 'Creatures.methods.update',
|
name: 'Creatures.methods.update',
|
||||||
validate({_id, path, value, ack}){
|
validate({_id, path, value}){
|
||||||
if (!_id) return false;
|
if (!_id) return false;
|
||||||
// Allowed fields
|
// Allowed fields
|
||||||
let allowedFields = ['name', 'alignment', 'gender', 'picture', 'settings'];
|
let allowedFields = ['name', 'alignment', 'gender', 'picture', 'settings'];
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import SimpleSchema from 'simpl-schema';
|
import SimpleSchema from 'simpl-schema';
|
||||||
import SharingSchema from '/imports/api/sharing/SharingSchema.js';
|
import SharingSchema from '/imports/api/sharing/SharingSchema.js';
|
||||||
import simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js';
|
import simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js';
|
||||||
|
import { assertEditPermission, assertOwnership } from '/imports/api/sharing/sharingPermissions.js';
|
||||||
|
import LibraryNodes from '/imports/api/library/LibraryNodes.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Libraries are trees of library nodes where each node represents a character
|
* Libraries are trees of library nodes where each node represents a character
|
||||||
@@ -41,6 +43,24 @@ const insertLibrary = new ValidatedMethod({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updateLibraryName = new ValidatedMethod({
|
||||||
|
name: 'Libraries.methods.updateName',
|
||||||
|
validate: new SimpleSchema({
|
||||||
|
_id: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.id
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
}).validator(),
|
||||||
|
run({_id, name}){
|
||||||
|
let library = Libraries.findOne(_id);
|
||||||
|
assertEditPermission(library, this.userId);
|
||||||
|
Libraries.update(_id, {$set: {name}});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const setLibraryDefault = new ValidatedMethod({
|
const setLibraryDefault = new ValidatedMethod({
|
||||||
name: 'Libraries.methods.makeLibraryDefault',
|
name: 'Libraries.methods.makeLibraryDefault',
|
||||||
validate: new SimpleSchema({
|
validate: new SimpleSchema({
|
||||||
@@ -60,4 +80,22 @@ const setLibraryDefault = new ValidatedMethod({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export { LibrarySchema, insertLibrary, setLibraryDefault };
|
const removeLibrary = new ValidatedMethod({
|
||||||
|
name: 'Libraries.methods.remove',
|
||||||
|
validate: new SimpleSchema({
|
||||||
|
_id: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.id
|
||||||
|
},
|
||||||
|
}).validator(),
|
||||||
|
run({_id}){
|
||||||
|
let library = Libraries.findOne(_id);
|
||||||
|
console.log({library, _id});
|
||||||
|
assertOwnership(library, this.userId);
|
||||||
|
Libraries.remove(_id);
|
||||||
|
this.unblock();
|
||||||
|
LibraryNodes.remove({'ancestors.id': _id});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export { LibrarySchema, insertLibrary, setLibraryDefault, updateLibraryName, removeLibrary };
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ function assertIdValid(userId){
|
|||||||
|
|
||||||
function assertdocExists(doc){
|
function assertdocExists(doc){
|
||||||
if (!doc){
|
if (!doc){
|
||||||
throw new Meteor.Error("Edit permission denied",
|
throw new Meteor.Error("Permission denied",
|
||||||
`No such document exists`);
|
`No such document exists`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Creatures from '/imports/api/creature/Creatures.js';
|
import Creatures from '/imports/api/creature/Creatures.js';
|
||||||
|
import removeCreature from '/imports/api/creature/removeCreature.js';
|
||||||
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
|
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
|
||||||
import { mapMutations } from "vuex";
|
import { mapMutations } from "vuex";
|
||||||
import { theme } from '/imports/ui/theme.js';
|
import { theme } from '/imports/ui/theme.js';
|
||||||
@@ -121,12 +122,24 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteCharacter(){
|
deleteCharacter(){
|
||||||
|
let that = this;
|
||||||
this.$store.commit('pushDialogStack', {
|
this.$store.commit('pushDialogStack', {
|
||||||
component: 'character-delete-dialog',
|
component: 'delete-confirmation-dialog',
|
||||||
elementId: 'creature-menu',
|
elementId: 'creature-menu',
|
||||||
data: {
|
data: {
|
||||||
id: this.creatureId,
|
name: this.character.name,
|
||||||
|
typeName: 'Character'
|
||||||
},
|
},
|
||||||
|
callback(confirmation){
|
||||||
|
if(!confirmation) return;
|
||||||
|
removeCreature.call({charId: that.creatureId}, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
} else {
|
||||||
|
that.$router.push('/characterList');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
isDarkColor,
|
isDarkColor,
|
||||||
|
|||||||
54
app/imports/ui/dialogStack/DeleteConfirmationDialog.vue
Normal file
54
app/imports/ui/dialogStack/DeleteConfirmationDialog.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template lang="html">
|
||||||
|
<dialog-base>
|
||||||
|
<div slot="toolbar">
|
||||||
|
Delete {{typeName}}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p v-if="name">
|
||||||
|
Type "{{name}}" to permanenetly delete
|
||||||
|
</p>
|
||||||
|
<v-text-field v-if="name" v-model="inputName"/>
|
||||||
|
<div class="layout row justify-center">
|
||||||
|
<v-btn
|
||||||
|
v-show="nameMatch"
|
||||||
|
class="primary"
|
||||||
|
@click="$store.dispatch('popDialogStack', true);"
|
||||||
|
>Delete forever</v-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<v-spacer slot="actions"/>
|
||||||
|
<v-btn
|
||||||
|
slot="actions"
|
||||||
|
flat
|
||||||
|
@click="$store.dispatch('popDialogStack')"
|
||||||
|
>Cancel</v-btn>
|
||||||
|
</dialog-base>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
DialogBase,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
typeName: String,
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
data(){return {
|
||||||
|
inputName: undefined,
|
||||||
|
}},
|
||||||
|
computed: {
|
||||||
|
nameMatch(){
|
||||||
|
if (!this.name) return true;
|
||||||
|
let uppername = this.name.toUpperCase();
|
||||||
|
let upperInputName = this.inputName && this.inputName.toUpperCase();
|
||||||
|
return uppername === upperInputName;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
</style>
|
||||||
@@ -2,13 +2,14 @@ import AttributeDialog from '/imports/ui/properties/attributes/AttributeDialog.v
|
|||||||
import AttributeDialogContainer from '/imports/ui/properties/attributes/AttributeDialogContainer.vue';
|
import AttributeDialogContainer from '/imports/ui/properties/attributes/AttributeDialogContainer.vue';
|
||||||
import AttributeCreationDialog from '/imports/ui/properties/attributes/AttributeCreationDialog.vue';
|
import AttributeCreationDialog from '/imports/ui/properties/attributes/AttributeCreationDialog.vue';
|
||||||
import CreatureFormDialog from '/imports/ui/creature/CreatureFormDialog.vue';
|
import CreatureFormDialog from '/imports/ui/creature/CreatureFormDialog.vue';
|
||||||
import CharacterDeleteDialog from '/imports/ui/creature/character/CharacterDeleteDialog.vue';
|
|
||||||
import CreaturePropertyCreationDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue';
|
import CreaturePropertyCreationDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue';
|
||||||
import CreaturePropertyDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue'
|
import CreaturePropertyDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue'
|
||||||
import CreaturePropertyFromLibraryDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue'
|
import CreaturePropertyFromLibraryDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue'
|
||||||
|
import DeleteConfirmationDialog from '/imports/ui/dialogStack/DeleteConfirmationDialog.vue';
|
||||||
import FeatureCreationDialog from '/imports/ui/properties/features/FeatureCreationDialog.vue';
|
import FeatureCreationDialog from '/imports/ui/properties/features/FeatureCreationDialog.vue';
|
||||||
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 LibraryEditDialog from '/imports/ui/library/LibraryEditDialog.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 LibraryNodeEditDialog from '/imports/ui/library/LibraryNodeEditDialog.vue';
|
||||||
import ShareDialog from '/imports/ui/sharing/ShareDialog.vue';
|
import ShareDialog from '/imports/ui/sharing/ShareDialog.vue';
|
||||||
@@ -19,13 +20,14 @@ export default {
|
|||||||
AttributeDialogContainer,
|
AttributeDialogContainer,
|
||||||
AttributeCreationDialog,
|
AttributeCreationDialog,
|
||||||
CreatureFormDialog,
|
CreatureFormDialog,
|
||||||
CharacterDeleteDialog,
|
|
||||||
CreaturePropertyCreationDialog,
|
CreaturePropertyCreationDialog,
|
||||||
CreaturePropertyDialog,
|
CreaturePropertyDialog,
|
||||||
CreaturePropertyFromLibraryDialog,
|
CreaturePropertyFromLibraryDialog,
|
||||||
|
DeleteConfirmationDialog,
|
||||||
FeatureCreationDialog,
|
FeatureCreationDialog,
|
||||||
FeatureDialogContainer,
|
FeatureDialogContainer,
|
||||||
LibraryCreationDialog,
|
LibraryCreationDialog,
|
||||||
|
LibraryEditDialog,
|
||||||
LibraryNodeCreationDialog,
|
LibraryNodeCreationDialog,
|
||||||
LibraryNodeEditDialog,
|
LibraryNodeEditDialog,
|
||||||
ShareDialog,
|
ShareDialog,
|
||||||
|
|||||||
@@ -27,10 +27,8 @@
|
|||||||
:selected-node-id="selectedNodeId"
|
:selected-node-id="selectedNodeId"
|
||||||
/>
|
/>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer/>
|
|
||||||
<v-btn
|
<v-btn
|
||||||
flat
|
flat small
|
||||||
color="primary"
|
|
||||||
style="background-color: inherit; margin-top: 0;"
|
style="background-color: inherit; margin-top: 0;"
|
||||||
@click="insertLibraryNode(library._id)"
|
@click="insertLibraryNode(library._id)"
|
||||||
:data-id="`insert-node-${library._id}`"
|
:data-id="`insert-node-${library._id}`"
|
||||||
@@ -38,6 +36,12 @@
|
|||||||
<v-icon>add</v-icon>
|
<v-icon>add</v-icon>
|
||||||
New property
|
New property
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
<v-spacer/>
|
||||||
|
<v-btn flat small icon
|
||||||
|
@click="editLibrary(library._id)"
|
||||||
|
>
|
||||||
|
<v-icon>create</v-icon>
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-expansion-panel-content>
|
</v-expansion-panel-content>
|
||||||
@@ -97,6 +101,13 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
editLibrary(_id){
|
||||||
|
this.$store.commit('pushDialogStack', {
|
||||||
|
component: 'library-edit-dialog',
|
||||||
|
elementId: _id,
|
||||||
|
data: {_id},
|
||||||
|
});
|
||||||
|
},
|
||||||
insertLibraryNode(libraryId){
|
insertLibraryNode(libraryId){
|
||||||
this.$store.commit('pushDialogStack', {
|
this.$store.commit('pushDialogStack', {
|
||||||
component: 'library-node-creation-dialog',
|
component: 'library-node-creation-dialog',
|
||||||
@@ -111,7 +122,12 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
watch: {
|
||||||
|
expandedLibrary(value){
|
||||||
|
console.log(value)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
76
app/imports/ui/library/LibraryEditDialog.vue
Normal file
76
app/imports/ui/library/LibraryEditDialog.vue
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<template lang="html">
|
||||||
|
<dialog-base>
|
||||||
|
<template slot="toolbar">
|
||||||
|
<div>
|
||||||
|
{{model && model.name}}
|
||||||
|
</div>
|
||||||
|
<v-spacer/>
|
||||||
|
<v-btn flat icon @click="remove">
|
||||||
|
<v-icon>delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<template v-if="model">
|
||||||
|
<text-field label="name" :value="model.name" @change="updateName"/>
|
||||||
|
</template>
|
||||||
|
<template slot="actions">
|
||||||
|
<v-spacer/>
|
||||||
|
<v-btn
|
||||||
|
flat
|
||||||
|
@click="$store.dispatch('popDialogStack')"
|
||||||
|
data-id="delete-library-button"
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</dialog-base>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
|
||||||
|
import Libraries, { updateLibraryName, removeLibrary } from '/imports/api/library/Libraries.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
DialogBase,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
_id: String,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateName(value, ack){
|
||||||
|
updateLibraryName.call({_id: this._id, name: value}, (error, result) =>{
|
||||||
|
ack(error && error.reason || error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
remove(){
|
||||||
|
let that = this;
|
||||||
|
this.$store.commit('pushDialogStack', {
|
||||||
|
component: 'delete-confirmation-dialog',
|
||||||
|
elementId: 'delete-library-button',
|
||||||
|
data: {
|
||||||
|
name: this.model.name,
|
||||||
|
typeName: 'Library'
|
||||||
|
},
|
||||||
|
callback(confirmation){
|
||||||
|
if(!confirmation) return;
|
||||||
|
removeLibrary.call({_id: that._id}, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
} else {
|
||||||
|
that.$store.dispatch('popDialogStack')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
meteor: {
|
||||||
|
model(){
|
||||||
|
return Libraries.findOne(this._id);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user