Added tree root dialog to breadcrumbs

This commit is contained in:
Stefan Zermatten
2022-07-24 14:46:27 +02:00
parent f88ffcf0c3
commit be654d5d45
3 changed files with 225 additions and 2 deletions

View File

@@ -0,0 +1,189 @@
<template lang="html">
<dialog-base>
<template #replace-toolbar="{flat}">
<property-toolbar
:model="creature"
:editing="editing"
:flat="flat"
:embedded="embedded"
style="flex-grow: 0;"
@toggle-editing="editing = !editing"
/>
</template>
<template v-if="_id">
<v-fade-transition
mode="out-in"
>
<div v-if="editing">
<creature-properties-tree
style="width: 100%;"
class="mb-2"
organize
:root="{collection: 'creatures', id: _id}"
@length="childrenLength = $event"
@selected="selectSubProperty"
/>
<v-btn
icon
outlined
color="accent"
data-id="insert-creature-property-btn"
@click="addProperty"
>
<v-icon>
mdi-plus
</v-icon>
</v-btn>
</div>
<div v-else>
<creature-properties-tree
style="width: 100%;"
:root="{collection: 'creatures', id: _id}"
@length="childrenLength = $event"
@selected="selectSubProperty"
/>
</div>
</v-fade-transition>
</template>
<div
v-if="!embedded"
slot="actions"
class="layout"
>
<v-spacer />
<v-btn
text
color="accent"
@click="$store.dispatch('popDialogStack')"
>
Close
</v-btn>
</div>
</dialog-base>
</template>
<script lang="js">
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js';
import PropertyToolbar from '/imports/ui/components/propertyToolbar.vue';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
import propertyFormIndex from '/imports/ui/properties/forms/shared/propertyFormIndex.js';
import propertyViewerIndex from '/imports/ui/properties/viewers/shared/propertyViewerIndex.js';
import CreaturePropertiesTree from '/imports/ui/creature/creatureProperties/CreaturePropertiesTree.vue';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
import { getHighestOrder } from '/imports/api/parenting/order.js';
import insertProperty from '/imports/api/creature/creatureProperties/methods/insertProperty.js';
import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js';
let formIndex = {};
for (let key in propertyFormIndex){
formIndex[key + 'Form'] = propertyFormIndex[key];
}
let viewerIndex = {};
for (let key in propertyViewerIndex){
formIndex[key + 'Viewer'] = propertyViewerIndex[key];
}
export default {
components: {
...formIndex,
...viewerIndex,
DialogBase,
PropertyToolbar,
CreaturePropertiesTree,
},
props: {
_id: String,
embedded: Boolean, // This dialog is embedded in a page
startInEditTab: Boolean,
},
data(){ return {
editing: !!this.startInEditTab,
// CurrentId lags behind Id by one tick so that events fired by destroying
// forms keyed to the old ID are applied before the new ID overwrites it
currentId: undefined,
childrenLength: 0,
}},
meteor: {
editPermission(){
try {
assertEditPermission(this.creature, Meteor.userId());
return true;
} catch (e) {
return false;
}
},
},
computed: {
creature(){
return Creatures.findOne(this._id);
},
},
watch: {
_id: {
immediate: true,
handler(newId){
this.$nextTick(() => {
this.currentId = newId;
});
}
},
},
reactiveProvide: {
name: 'context',
include: ['creatureId', 'editPermission'],
},
methods: {
getPropertyName,
selectSubProperty(_id){
this.$store.commit('pushDialogStack', {
component: 'creature-property-dialog',
elementId: `tree-node-${_id}`,
data: {
_id,
startInEditTab: this.editing,
},
});
},
addProperty(){
let parentPropertyId = this._id;
this.$store.commit('pushDialogStack', {
component: 'add-creature-property-dialog',
elementId: 'insert-creature-property-btn',
data: {
parentDoc: this.creature,
creatureId: this._id,
},
callback(result){
if (!result) return;
let parentRef = {
id: parentPropertyId,
collection: 'creatures',
};
let order = getHighestOrder({
collection: CreatureProperties,
ancestorId: parentRef.id,
}) + 0.5;
if (Array.isArray(result)){
let nodeIds = result;
let id = insertPropertyFromLibraryNode.call({nodeIds, parentRef, order});
return `tree-node-${id}`;
} else {
let creatureProperty = result;
// Get order and parent
creatureProperty.order = order;
// Insert the property
let id = insertProperty.call({creatureProperty, parentRef});
return `tree-node-${id}`;
}
}
});
},
}
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -3,9 +3,16 @@
class="breadcrumbs layout align-center wrap"
:class="{'no-icons': noIcons}"
>
<a
data-id="breadcrumb-root"
@click="clickRootCreature"
>
<v-icon color="accent">
mdi-account
</v-icon>
</a>
<template v-for="(prop, index) in props">
<v-icon
v-if="index !== 0"
:key="index"
>
mdi-chevron-right
@@ -60,7 +67,7 @@
},
methods: {
click(id){
let store = this.$store;
const store = this.$store;
// Check if there is a dialog open for this doc already
let dialogFound;
let dialogsToPop = 0;
@@ -84,6 +91,31 @@
});
}
},
clickRootCreature() {
const store = this.$store;
// Check if there is a dialog open for this doc already
let dialogFound;
let dialogsToPop = 0;
store.state.dialogStack.dialogs.forEach(dialog => {
if (dialog.component === 'creature-root-dialog'){
dialogFound = true;
dialogsToPop = 0;
} else {
dialogsToPop += 1;
}
});
if (dialogFound){
// Pop dialogs until we get to it
store.dispatch('popDialogStacks', dialogsToPop);
} else {
// Otherwise open it as a new dialog
store.commit('pushDialogStack', {
component: 'creature-root-dialog',
elementId: 'breadcrumb-root',
data: {_id: this.model.ancestors[0].id},
});
}
}
}
}
</script>

View File

@@ -6,6 +6,7 @@ const CreatureFormDialog = () => import('/imports/ui/creature/CreatureFormDialog
const CreaturePropertyCreationDialog = () => import('/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue');
const CreaturePropertyDialog = () => import('/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue');
const CreaturePropertyFromLibraryDialog = () => import('/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue');
const CreatureRootDialog = () => import('/imports/ui/creature/character/CreatureRootDialog.vue');
const DeleteConfirmationDialog = () => import('/imports/ui/dialogStack/DeleteConfirmationDialog.vue');
const DeleteUserAccountDialog = () => import('/imports/ui/user/DeleteUserAccountDialog.vue');
const ExperienceInsertDialog = () => import( '/imports/ui/creature/experiences/ExperienceInsertDialog.vue');
@@ -36,6 +37,7 @@ export default {
CreaturePropertyCreationDialog,
CreaturePropertyDialog,
CreaturePropertyFromLibraryDialog,
CreatureRootDialog,
DeleteConfirmationDialog,
DeleteUserAccountDialog,
ExperienceInsertDialog,