Added a tree view of the character, fixed the issue it revealed
This commit is contained in:
45
app/imports/api/creature/creatureCollections.js
Normal file
45
app/imports/api/creature/creatureCollections.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import Actions from '/imports/api/creature/properties/Actions.js';
|
||||
import Attacks from '/imports/api/creature/properties/Attacks.js';
|
||||
import Attributes from '/imports/api/creature/properties/Attributes.js';
|
||||
import Buffs from '/imports/api/creature/properties/Buffs.js';
|
||||
import Bundles from '/imports/api/creature/properties/Bundles.js';
|
||||
import Classes from '/imports/api/creature/properties/Classes.js';
|
||||
import Conditions from '/imports/api/creature/properties/Conditions.js';
|
||||
import CustomBuffs from '/imports/api/creature/properties/CustomBuffs.js';
|
||||
import DamageMultipliers from '/imports/api/creature/properties/DamageMultipliers.js';
|
||||
import Effects from '/imports/api/creature/properties/Effects.js';
|
||||
import Experiences from '/imports/api/creature/properties/Experiences.js';
|
||||
import Features from '/imports/api/creature/properties/Features.js';
|
||||
import Notes from '/imports/api/creature/properties/Notes.js';
|
||||
import Proficiencies from '/imports/api/creature/properties/Proficiencies.js';
|
||||
import Skills from '/imports/api/creature/properties/Skills.js';
|
||||
import SpellLists from '/imports/api/creature/properties/SpellLists.js';
|
||||
import Spells from '/imports/api/creature/properties/Spells.js';
|
||||
import Containers from '/imports/api/inventory/Containers.js';
|
||||
import Items from '/imports/api/inventory/Items.js';
|
||||
|
||||
// All theses collections have the field {charId: String}
|
||||
// Collate them here in case we need to do something on all the collections of
|
||||
// a creature
|
||||
|
||||
export default [
|
||||
Actions,
|
||||
Attacks,
|
||||
Attributes,
|
||||
Buffs,
|
||||
Bundles,
|
||||
Classes,
|
||||
Conditions,
|
||||
CustomBuffs,
|
||||
DamageMultipliers,
|
||||
Effects,
|
||||
Experiences,
|
||||
Features,
|
||||
Notes,
|
||||
Proficiencies,
|
||||
Skills,
|
||||
SpellLists,
|
||||
Spells,
|
||||
Containers,
|
||||
Items,
|
||||
];
|
||||
@@ -8,7 +8,7 @@ const setParent = function(charId){
|
||||
group: "default",
|
||||
};
|
||||
return doc => {
|
||||
doc.parent = parent;
|
||||
doc.parent = doc.parent || parent;
|
||||
doc.charId = charId;
|
||||
};
|
||||
};
|
||||
@@ -102,6 +102,7 @@ const getDefaultCharacterDocs = function(charId, {
|
||||
const strippedCls = cls.replace(/\s+/g, '')
|
||||
const classId = Random.id();
|
||||
docs.classes = [{
|
||||
_id: classId,
|
||||
charId,
|
||||
level,
|
||||
name: cls,
|
||||
|
||||
@@ -20,15 +20,16 @@ attributeSchema = schema({
|
||||
// The nice-to-read name
|
||||
name: {
|
||||
type: String,
|
||||
index: 1,
|
||||
},
|
||||
// The technical, lowercase, single-word name used in formulae
|
||||
variableName: {
|
||||
type: String,
|
||||
index: 1,
|
||||
},
|
||||
// Attributes need to store their order to keep the sheet consistent
|
||||
order: {
|
||||
type: SimpleSchema.Integer,
|
||||
// Indexed because we update order in bulk using the current order as a query
|
||||
index: 1,
|
||||
},
|
||||
type: {
|
||||
|
||||
@@ -8,9 +8,28 @@
|
||||
<v-icon>refresh</v-icon>
|
||||
</v-btn>
|
||||
<span>{{character.name}}</span>
|
||||
<v-tabs
|
||||
slot="extension"
|
||||
v-model="tab"
|
||||
centered
|
||||
>
|
||||
<v-tab>
|
||||
Stats
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Tree
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</v-toolbar>
|
||||
<v-content v-if="$subReady.singleCharacter">
|
||||
<stats-tab :char-id="character._id"/>
|
||||
<v-tabs-items v-model="tab">
|
||||
<v-tab-item>
|
||||
<stats-tab :char-id="character._id"/>
|
||||
</v-tab-item>
|
||||
<v-tab-item>
|
||||
<character-tree-view :char-id="character._id"/>
|
||||
</v-tab-item>
|
||||
</v-tabs-items>
|
||||
</v-content>
|
||||
<v-content v-else>
|
||||
<v-progress-circular indeterminate />
|
||||
@@ -24,6 +43,7 @@
|
||||
import { mapMutations } from "vuex";
|
||||
import theme from '/imports/ui/theme.js';
|
||||
import StatsTab from '/imports/ui/character/StatsTab.vue';
|
||||
import CharacterTreeView from '/imports/ui/character/CharacterTreeView.vue';
|
||||
import { recomputeCreature } from '/imports/api/creature/creatureComputation.js'
|
||||
|
||||
export default {
|
||||
@@ -33,6 +53,7 @@
|
||||
},
|
||||
components: {
|
||||
StatsTab,
|
||||
CharacterTreeView,
|
||||
},
|
||||
watch: {
|
||||
charId(newValue){
|
||||
@@ -41,6 +62,7 @@
|
||||
},
|
||||
data(){return {
|
||||
theme,
|
||||
tab: 1,
|
||||
}},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
|
||||
85
app/imports/ui/character/CharacterTreeView.vue
Normal file
85
app/imports/ui/character/CharacterTreeView.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template lang="html">
|
||||
<v-treeview :items="treeItems">
|
||||
<template slot="label" slot-scope="{ item, open }">
|
||||
<span v-if="item.collection === 'attributes' || item.collection === 'skills'">
|
||||
{{item.name}}: {{item.value}}
|
||||
</span>
|
||||
<span v-else-if="item.collection === 'effects'">
|
||||
{{item.name}}: {{item.stat}} {{item.operation}} {{item.result}}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{item.name}}
|
||||
</span>
|
||||
</template>
|
||||
</v-treeview>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import creatureCollections from '/imports/api/creature/creatureCollections.js';
|
||||
export default {
|
||||
name: 'character-tree-view',
|
||||
props: {
|
||||
charId: String,
|
||||
},
|
||||
computed: {
|
||||
treeItems(){
|
||||
let docsByParent = this.characterDocsByParent;
|
||||
let buildDoc = (oldDoc) => {
|
||||
let doc = {...oldDoc};
|
||||
if (docsByParent[doc._id]){
|
||||
doc.children = [];
|
||||
for (let group in docsByParent[doc._id]){
|
||||
if (group === 'ungrouped'){
|
||||
doc.children.push(...docsByParent[doc._id][group].map(buildDoc))
|
||||
} else {
|
||||
doc.children.push({
|
||||
name: group,
|
||||
type: 'group',
|
||||
children: docsByParent[doc._id][group].map(buildDoc),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
return buildDoc({
|
||||
_id: 'unparented',
|
||||
}).children;
|
||||
},
|
||||
},
|
||||
meteor: {
|
||||
characterDocsByParent(){
|
||||
let parentIndex = {unparented: {}};
|
||||
for (collection of creatureCollections){
|
||||
collection.find({
|
||||
charId: this.charId
|
||||
}, {
|
||||
sort: {order: 1}
|
||||
}).forEach(doc => {
|
||||
doc.collection = collection._name;
|
||||
let parentId = doc.parent && doc.parent.id;
|
||||
let parentGroup = (doc.parent && doc.parent.group) || 'ungrouped'
|
||||
if (parentId && parentId !== this.charId){
|
||||
if (!parentIndex[parentId]){
|
||||
parentIndex[parentId] = {};
|
||||
}
|
||||
if (!parentIndex[parentId][parentGroup]){
|
||||
parentIndex[parentId][parentGroup] = [];
|
||||
}
|
||||
parentIndex[parentId][parentGroup].push(doc);
|
||||
} else {
|
||||
if (!parentIndex.unparented[parentGroup]){
|
||||
parentIndex.unparented[parentGroup] = [];
|
||||
}
|
||||
parentIndex.unparented[parentGroup].push(doc);
|
||||
}
|
||||
});
|
||||
}
|
||||
return parentIndex;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user