Started working on getting creature property insertion working

This commit is contained in:
Stefan Zermatten
2019-09-27 11:06:33 +02:00
parent 73f193460d
commit f4d613a20b
22 changed files with 437 additions and 282 deletions

View File

@@ -1,16 +1,15 @@
import SimpleSchema from 'simpl-schema';
import ChildSchema from '/imports/api/parenting/ChildSchema.js';
import propertySchemas from '/imports/api/properties/propertySchemas.js';
import Libraries from '/imports/api/library/Libraries.js';
import Creature from '/imports/api/creature/Creatures.js';
import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js';
import getModifierFields from '/imports/api/getModifierFields.js';
import propertySchemasIndex from '/imports/api/properties/propertySchemasIndex.js';
let CreatureProperties = new Mongo.Collection('creatureProperties');
let CreaturePropertySchema = new SimpleSchema({
type: {
type: String,
allowedValues: Object.keys(propertySchemas),
allowedValues: Object.keys(propertySchemasIndex),
},
charId: {
type: String,
@@ -20,9 +19,9 @@ let CreaturePropertySchema = new SimpleSchema({
},
});
for (let key in propertySchemas){
for (let key in propertySchemasIndex){
let schema = new SimpleSchema({});
schema.extend(propertySchemas[key]);
schema.extend(propertySchemasIndex[key]);
schema.extend(CreaturePropertySchema);
schema.extend(ChildSchema);
CreatureProperties.attachSchema(schema, {
@@ -30,6 +29,28 @@ for (let key in propertySchemas){
});
}
function getCreature(property){
if (!property) throw new Meteor.Error('No property provided');
let creature = Creatures.findOne(property.ancestors[0].id);
if (!creature) throw new Meteor.Error('Creature does not exist');
return creature;
}
function assertPropertyEditPermission(property, userId){
let creature = getCreature(property);
return assertEditPermission(creature, userId);
}
const insertProperty = new ValidatedMethod({
name: 'CreatureProperties.methods.insert',
validate: null,
run(creatureProperty) {
assertPropertyEditPermission(creatureProperty, this.userId);
return CreatureProperties.insert(creatureProperty);
},
});
/*
const adjustAttribute = new ValidatedMethod({
name: 'Attributes.methods.adjust',
mixins: [
@@ -73,6 +94,7 @@ const adjustAttribute = new ValidatedMethod({
}
},
});
*/
export default CreatureProperties;
export { CreaturePropertySchema};
export { CreaturePropertySchema, insertProperty };

View File

@@ -50,38 +50,10 @@ let CreatureSchema = new SimpleSchema({
type: String,
optional: true
},
race: {
type: String,
optional: true
},
picture: {
type: String,
optional: true
},
description: {
type: String,
optional: true
},
personality: {
type: String,
optional: true
},
ideals: {
type: String,
optional: true
},
bonds: {
type: String,
optional: true
},
flaws: {
type: String,
optional: true
},
backstory: {
type: String,
optional: true
},
// Mechanics
deathSave: {
@@ -105,8 +77,6 @@ let CreatureSchema = new SimpleSchema({
defaultValue: "pc",
allowedValues: ["pc", "npc", "monster"],
},
// Computed
variables: {
type: Object,
blackbox: true,

View File

@@ -1,6 +1,6 @@
import SimpleSchema from 'simpl-schema';
import ChildSchema from '/imports/api/parenting/ChildSchema.js';
import librarySchemas from '/imports/api/library/librarySchemas.js';
import propertySchemasIndex from '/imports/api/properties/propertySchemasIndex.js';
import Libraries from '/imports/api/library/Libraries.js';
import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js';
import { softRemove } from '/imports/api/parenting/softRemove.js';
@@ -11,14 +11,14 @@ let LibraryNodes = new Mongo.Collection('libraryNodes');
let LibraryNodeSchema = new SimpleSchema({
type: {
type: String,
allowedValues: Object.keys(librarySchemas),
allowedValues: Object.keys(propertySchemasIndex),
},
});
for (let key in librarySchemas){
for (let key in propertySchemasIndex){
let schema = new SimpleSchema({});
schema.extend(LibraryNodeSchema);
schema.extend(librarySchemas[key]);
schema.extend(propertySchemasIndex[key]);
schema.extend(ChildSchema);
schema.extend(SoftRemovableSchema);
LibraryNodes.attachSchema(schema, {
@@ -112,36 +112,6 @@ const softRemoveLibraryNode = new ValidatedMethod({
}
});
function libraryNodesToTree(ancestorId){
// Store a dict of all the nodes
let nodeIndex = {};
let nodeList = [];
LibraryNodes.find({
'ancestors.id': ancestorId,
removed: {$ne: true},
}, {
sort: {order: 1}
}).forEach( node => {
let treeNode = {
node: node,
children: [],
};
nodeIndex[node._id] = treeNode;
nodeList.push(treeNode);
});
// Create a forest of trees
let forest = [];
// Either the node is a child of another node, or in the forest as a root
nodeList.forEach(node => {
if (nodeIndex[node.node.parent.id]){
nodeIndex[node.node.parent.id].children.push(node);
} else {
forest.push(node);
}
});
return forest;
}
export default LibraryNodes;
export {
LibraryNodeSchema,

View File

@@ -165,3 +165,33 @@ export function getName(doc){
if (ancestors[i].name) return ancestors[i].name;
}
}
export function nodesToTree({collection, ancestorId}){
// Store a dict of all the nodes
let nodeIndex = {};
let nodeList = [];
collection.find({
'ancestors.id': ancestorId,
removed: {$ne: true},
}, {
sort: {order: 1}
}).forEach( node => {
let treeNode = {
node: node,
children: [],
};
nodeIndex[node._id] = treeNode;
nodeList.push(treeNode);
});
// Create a forest of trees
let forest = [];
// Either the node is a child of another node, or in the forest as a root
nodeList.forEach(node => {
if (nodeIndex[node.node.parent.id]){
nodeIndex[node.node.parent.id].children.push(node);
} else {
forest.push(node);
}
});
return forest;
}

View File

@@ -1,43 +0,0 @@
import { ActionSchema } from '/imports/api/properties/Actions.js';
import { AttackSchema } from '/imports/api/properties/Attacks.js';
import { AttributeSchema } from '/imports/api/properties/Attributes.js';
import { StoredBuffSchema } from '/imports/api/properties/Buffs.js';
import { ClassLevelSchema } from '/imports/api/properties/ClassLevels.js';
import { DamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers.js';
import { EffectSchema } from '/imports/api/properties/Effects.js';
import { ExperienceSchema } from '/imports/api/properties/Experiences.js';
import { FeatureSchema } from '/imports/api/properties/Features.js';
import { FolderSchema } from '/imports/api/properties/Folders.js';
import { NoteSchema } from '/imports/api/properties/Notes.js';
import { ProficiencySchema } from '/imports/api/properties/Proficiencies.js';
import { RollSchema } from '/imports/api/properties/Rolls.js';
import { SavingThrowSchema } from '/imports/api/properties/SavingThrows.js';
import { SkillSchema } from '/imports/api/properties/Skills.js';
import { SpellListSchema } from '/imports/api/properties/SpellLists.js';
import { SpellSchema } from '/imports/api/properties/Spells.js';
import { ContainerSchema } from '/imports/api/properties/Containers.js';
import { ItemSchema } from '/imports/api/properties/Items.js';
const propertySchemas = {
action: ActionSchema,
attack: AttackSchema,
attribute: AttributeSchema,
buff: StoredBuffSchema,
classLevel: ClassLevelSchema,
damageMultiplier: DamageMultiplierSchema,
effect: EffectSchema,
experience: ExperienceSchema,
feature: FeatureSchema,
folder: FolderSchema,
note: NoteSchema,
proficiency: ProficiencySchema,
roll: RollSchema,
savingThrow: SavingThrowSchema,
skill: SkillSchema,
spellList: SpellListSchema,
spell: SpellSchema,
container: ContainerSchema,
item: ItemSchema,
};
export default propertySchemas;

View File

@@ -19,7 +19,7 @@ import { SpellSchema } from '/imports/api/properties/Spells.js';
import { ContainerSchema } from '/imports/api/properties/Containers.js';
import { ItemSchema } from '/imports/api/properties/Items.js';
const librarySchemas = {
const propertySchemasIndex = {
action: ActionSchema,
attack: AttackSchema,
attribute: AttributeSchema,
@@ -42,4 +42,4 @@ const librarySchemas = {
any: new SimpleSchema({}),
};
export default librarySchemas;
export default propertySchemasIndex;

View File

@@ -1,7 +1,7 @@
import Creatures from "/imports/api/creature/Creatures.js";
import creatureCollections from '/imports/api/creature/creatureCollections.js';
import Creatures from '/imports/api/creature/Creatures.js';
import CreatureProperties from '/imports/api/creature/CreatureProperties.js';
Meteor.publish("singleCharacter", function(charId){
Meteor.publish('singleCharacter', function(charId){
userId = this.userId;
var char = Creatures.findOne({
_id: charId,
@@ -9,15 +9,15 @@ Meteor.publish("singleCharacter", function(charId){
{readers: userId},
{writers: userId},
{owner: userId},
{"settings.viewPermission": "public"},
{'settings.viewPermission': 'public'},
],
});
if (char){
return [
Creatures.find({_id: charId}),
...creatureCollections.map(
collection => collection.find({charId})
)
CreatureProperties.find({
'ancestors.id': charId,
}),
];
} else {
return [];
@@ -25,8 +25,8 @@ Meteor.publish("singleCharacter", function(charId){
});
DDPRateLimiter.addRule({
name: "singleCharacter",
type: "subscription",
name: 'singleCharacter',
type: 'subscription',
userId: null,
connectionId(){ return true; },
}, 8, 10000, function(reply, ruleInput){
@@ -35,7 +35,7 @@ DDPRateLimiter.addRule({
}
});
Meteor.publish("singleCharacterName", function(charId){
Meteor.publish('singleCharacterName', function(charId){
userId = this.userId;
return Creatures.find({
_id: charId,
@@ -43,9 +43,9 @@ Meteor.publish("singleCharacterName", function(charId){
{readers: userId},
{writers: userId},
{owner: userId},
{"settings.viewPermission": "public"},
{'settings.viewPermission': 'public'},
],
}, {
fields:{"name": 1}
fields:{'name': 1}
});
});

View File

@@ -0,0 +1,81 @@
<template lang="html">
<v-card-text style="width: initial; max-width: 100%; min-width: 320px;">
<tree-node-list
v-if="creatureChildren"
:children="creatureChildren"
:group="creature && creature._id"
:organize="organize"
:selected-node-id="selectedNodeId"
@selected="e => $emit('selected', e)"
@reordered="reordered"
@reorganized="reorganized"
/>
</v-card-text>
</template>
<script>
import Creatures from '/imports/api/creature/Creatures.js';
import CreatureProperties from '/imports/api/creature/CreatureProperties.js';
import { nodesToTree } from '/imports/api/parenting/parenting.js'
import TreeNodeList from '/imports/ui/components/tree/TreeNodeList.vue';
import { organizeDoc, reorderDoc } from '/imports/api/parenting/organizeMethods.js';
export default {
components: {
TreeNodeList,
},
props: {
creatureId: String,
organize: Boolean,
selectedNodeId: String,
},
meteor: {
$subscribe: {
'creature': [this.creatureId],
},
creature(){
return Creatures.findOne(this.creatureId);
},
creatureChildren(){
if (!this.creature) return;
return nodesToTree({collection: CreatureProperties, ancestorId: this.creatureId});
},
},
methods: {
reordered({doc, newIndex}){
reorderDoc.call({
docRef: {
id: doc._id,
collection: 'creatureProperties',
},
order: newIndex,
});
},
reorganized({doc, parent, newIndex}){
let parentRef;
if (parent){
parentRef = {
id: parent._id,
collection: 'creatureProperties',
};
} else {
parentRef = {
id: this.creatureId,
collection: 'creatures',
};
}
organizeDoc.call({
docRef: {
id: doc._id,
collection: 'creatureProperties',
},
parentRef,
order: newIndex,
});
},
},
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -13,12 +13,6 @@
v-model="tab"
centered
>
<v-tab>
Stats
</v-tab>
<v-tab>
Features
</v-tab>
<v-tab>
Tree
</v-tab>
@@ -26,14 +20,8 @@
</v-toolbar>
<v-content v-if="$subReady.singleCharacter">
<v-tabs-items v-model="tab">
<v-tab-item>
<stats-tab :char-id="character._id"/>
</v-tab-item>
<v-tab-item>
<features-tab :char-id="character._id"/>
</v-tab-item>
<v-tab-item>
<character-tree-view :char-id="character._id"/>
<tree-tab :character-id="creatureId"/>
</v-tab-item>
</v-tabs-items>
</v-content>
@@ -48,20 +36,16 @@
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
import { mapMutations } from "vuex";
import { theme } from '/imports/ui/theme.js';
import StatsTab from '/imports/ui/creature/character/StatsTab.vue';
import FeaturesTab from '/imports/ui/creature/character/FeaturesTab.vue';
import CharacterTreeView from '/imports/ui/creature/character/CharacterTreeView.vue';
import TreeTab from '/imports/ui/creature/character/TreeTab.vue';
import { recomputeCreature } from '/imports/api/creature/creatureComputation.js'
export default {
props: {
showMenuButton: Boolean,
charId: String,
creatureId: String,
},
components: {
StatsTab,
FeaturesTab,
CharacterTreeView,
TreeTab,
},
data(){return {
theme,
@@ -71,19 +55,19 @@
...mapMutations([
"toggleDrawer",
]),
recompute(charId){
recomputeCreature.call({charId});
recompute(creatureId){
recomputeCreature.call({creatureId});
},
isDarkColor,
},
meteor: {
$subscribe: {
'singleCharacter'(){
return [this.charId];
return [this.creatureId];
},
},
character(){
return Creatures.findOne(this.charId) || {};
return Creatures.findOne(this.creatureId) || {};
},
},
}

View File

@@ -1,86 +0,0 @@
<template lang="html">
<v-treeview :items="treeItems" transition>
<template slot="label" slot-scope="{ item, open }">
<em>{{item.collection}}</em>:
<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>

View File

@@ -0,0 +1,109 @@
<template lang="html">
<div class="tree-tab">
<v-card class="ma-4 layout row" data-id="creature-tree-card">
<div>
<v-toolbar dense flat>
<v-spacer/>
<v-switch
label="Organize"
class="mx-3"
v-model="organize"
style="flex-grow: 0; height: 32px;"
/>
</v-toolbar>
<creature-tree-container
:creature-id="creatureId"
:organize="organize"
@selected="e => selected = e"
:selected-node-id="selected"
/>
</div>
<v-divider vertical/>
<div style="width: 100%; background-color: inherit;" data-id="selected-node-card">
<v-toolbar dense flat>
<property-icon :type="selectedProperty && selectedProperty.type" class="mr-2"/>
<div class="title">
{{getPropertyName(selectedProperty && selectedProperty.type)}}
</div>
<v-spacer/>
<v-btn flat icon @click="editCreatureProperty" v-if="selectedProperty">
<v-icon>create</v-icon>
</v-btn>
</v-toolbar>
<v-card-text>
<property-viewer :model="selectedProperty"/>
</v-card-text>
</div>
</v-card>
<v-btn fixed fab bottom right
color="primary"
@click="insertCreatureProperty"
data-id="insert-creature-property-fab"
>
<v-icon>add</v-icon>
</v-btn>
</div>
</template>
<script>
import CreatureTreeContainer from '/imports/ui/creature/CreatureTreeContainer.vue';
import CreatureProperties, { insertProperty } from '/imports/api/creature/CreatureProperties.js';
import PropertyViewer from '/imports/ui/properties/PropertyViewer.vue';
import { setDocToLastOrder } from '/imports/api/parenting/order.js';
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
export default {
components: {
CreatureTreeContainer,
PropertyViewer,
PropertyIcon,
},
data(){ return {
organize: false,
selected: undefined,
};},
props: {
creatureId: {
type: String,
},
},
methods: {
insertCreatureProperty(){
let that = this;
this.$store.commit('pushDialogStack', {
component: 'creature-property-creation-dialog',
elementId: 'insert-creature-property-fab',
callback(creatureProperty){
if (!creatureProperty) return;
creatureProperty.parent = {collection: "creatures", id: that.creatureId};
creatureProperty.ancestors = [ {collection: "creatures", id: that.creatureId}];
setDocToLastOrder({collection: CreatureProperties, doc: creatureProperty});
let creaturePropertyId = insertProperty.call(creatureProperty);
return creaturePropertyId;
}
});
},
editCreatureProperty(){
let that = this;
this.$store.commit('pushDialogStack', {
component: 'library-node-edit-dialog',
elementId: 'selected-node-card',
data: {_id: this.selected},
});
},
getPropertyName,
},
meteor: {
selectedProperty(){
return CreatureProperties.findOne({
_id: this.selected,
removed: {$ne: true}
});
}
}
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,31 @@
<template lang="html">
<selectable-property-dialog v-model="type">
<creature-property-insert-form
:type="type"
:property-name="getPropertyName(type)"
@back="type = undefined"
/>
</selectable-property-dialog>
</template>
<script>
import SelectablePropertyDialog from '/imports/ui/properties/components/SelectablePropertyDialog.vue';
import CreaturePropertyInsertForm from '/imports/ui/creature/creatureProperties/CreaturePropertyInsertForm.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
export default {
data() { return {
type: undefined,
};},
components: {
SelectablePropertyDialog,
CreaturePropertyInsertForm,
},
methods: {
getPropertyName,
},
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,64 @@
<template lang="html">
<dialog-base :override-back-button="() => $emit('back')">
<div slot="toolbar">Add {{propertyName}}</div>
<component
v-if="type"
stored
:is="type"
class="creature-property-form"
:model="model"
:errors="errors"
@change="change"
@push="push"
@pull="pull"
/>
<div
slot="actions"
class="layout row justify-end"
>
<v-btn
flat
:disabled="!valid"
@click="$store.dispatch('popDialogStack', model)"
>Insert</v-btn>
</div>
</dialog-base>
</template>
<script>
import propertySchemasIndex from '/imports/api/properties/propertySchemasIndex.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import propertyFormIndex from '/imports/ui/properties/forms/shared/propertyFormIndex.js';
import schemaFormMixin from '/imports/ui/properties/forms/shared/schemaFormMixin.js';
export default {
components: {
...propertyFormIndex,
DialogBase,
},
mixins: [schemaFormMixin],
data(){return {
model: {
type: this.type,
},
schema: undefined,
validationContext: undefined,
};},
props: {
propertyName: String,
type: String,
},
watch: {
type(newType){
if (!newType) return;
this.schema = propertySchemasIndex[newType];
this.validationContext = this.schema.newContext();
let model = this.schema.clean({});
model.type = newType;
this.model = model;
},
},
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,6 +1,7 @@
import AttributeDialog from '/imports/ui/properties/attributes/AttributeDialog.vue';
import AttributeDialogContainer from '/imports/ui/properties/attributes/AttributeDialogContainer.vue';
import AttributeCreationDialog from '/imports/ui/properties/attributes/AttributeCreationDialog.vue';
import CreaturePropertyCreationDialog from '/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue';
import FeatureCreationDialog from '/imports/ui/properties/features/FeatureCreationDialog.vue';
import FeatureDialogContainer from '/imports/ui/properties/features/FeatureDialogContainer.vue';
import LibraryCreationDialog from '/imports/ui/library/LibraryCreationDialog.vue';
@@ -12,6 +13,7 @@ export default {
AttributeDialog,
AttributeDialogContainer,
AttributeCreationDialog,
CreaturePropertyCreationDialog,
FeatureCreationDialog,
FeatureDialogContainer,
LibraryCreationDialog,

View File

@@ -15,7 +15,8 @@
<script>
import Libraries from '/imports/api/library/Libraries.js';
import LibraryNodes, { libraryNodesToTree } from '/imports/api/library/LibraryNodes.js';
import LibraryNodes from '/imports/api/library/LibraryNodes.js';
import { nodesToTree } from '/imports/api/parenting/parenting.js'
import TreeNodeList from '/imports/ui/components/tree/TreeNodeList.vue';
import { organizeDoc, reorderDoc } from '/imports/api/parenting/organizeMethods.js';
@@ -37,7 +38,7 @@
},
libraryChildren(){
if (!this.library) return;
return libraryNodesToTree(this.library._id);
return nodesToTree({collection: LibraryNodes, ancestorId: this.library._id});
},
},
methods: {

View File

@@ -1,57 +1,31 @@
<template lang="html">
<transition-group name="slide">
<dialog-base v-show="step == 1" class="step-1" key="left">
<div slot="toolbar">Add Library Content</div>
<property-selector @select="setType"/>
</dialog-base>
<selectable-property-dialog v-model="type">
<library-node-insert-form
v-show="step == 2"
class="step-2"
key="right"
:type="type"
:property-name="getPropertyName(type)"
@back="step = 1"
@back="type = undefined"
/>
</transition-group>
</selectable-property-dialog>
</template>
<script>
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import PropertySelector from '/imports/ui/properties/PropertySelector.vue';
import SelectablePropertyDialog from '/imports/ui/properties/components/SelectablePropertyDialog.vue';
import LibraryNodeInsertForm from '/imports/ui/library/LibraryNodeInsertForm.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
export default {
data() { return {
type: undefined,
step: 1,
};},
components: {
DialogBase,
PropertySelector,
SelectablePropertyDialog,
LibraryNodeInsertForm,
},
methods: {
setType(property){
this.type = property;
this.step = 2;
},
getPropertyName,
},
};
</script>
<style lang="css" scoped>
.slide-enter-active, .slide-leave-active {
transition: transform .3s ease;
}
.slide-enter-active.step-1, .slide-leave-active.step-1{
position: absolute;
}
.slide-enter.step-1, .slide-leave-to.step-1 {
transform: translateX(-100%);
}
.slide-enter.step-2, .slide-leave-to.step-2 {
transform: translateX(100%);
}
</style>

View File

@@ -39,7 +39,6 @@
pullFromLibraryNode,
softRemoveLibraryNode,
} from '/imports/api/library/LibraryNodes.js';
import librarySchemas from '/imports/api/library/librarySchemas.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';

View File

@@ -26,10 +26,11 @@
</template>
<script>
import librarySchemas from '/imports/api/library/librarySchemas.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import propertyFormIndex from '/imports/ui/properties/forms/shared/propertyFormIndex.js';
import schemaFormMixin from '/imports/ui/properties/forms/shared/schemaFormMixin.js';
import propertySchemasIndex from '/imports/api/properties/propertySchemasIndex.js';
export default {
components: {
...propertyFormIndex,
@@ -49,7 +50,8 @@ export default {
},
watch: {
type(newType){
this.schema = librarySchemas[newType];
if (!newType) return;
this.schema = propertySchemasIndex[newType];
this.validationContext = this.schema.newContext();
let model = this.schema.clean({});
model.type = newType;

View File

@@ -82,7 +82,6 @@
const characterTransform = function(char){
char.url = `\/character\/${char._id}\/${char.urlName || "-"}`;
char.color = getColorClass(char.color);
char.initial = char.name[0] || "?";
return char;
};

View File

@@ -1,5 +1,5 @@
<template>
<character-sheet show-menu-button :char-id="$route.params.id" />
<character-sheet show-menu-button :creature-id="$route.params.id" />
</template>
<script>

View File

@@ -0,0 +1,48 @@
<template lang="html">
<transition-group name="slide">
<dialog-base v-show="!value" class="step-1" key="left">
<div slot="toolbar">Add Library Content</div>
<property-selector @select="property => $emit('input', property)"/>
</dialog-base>
<div
v-show="value"
class="step-2"
style="height: 100%;"
key="right"
>
<slot/>
</div>
</transition-group>
</template>
<script>
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import PropertySelector from '/imports/ui/properties/PropertySelector.vue';
export default {
props: {
value: {
type: String,
},
},
components: {
DialogBase,
PropertySelector,
},
};
</script>
<style lang="css" scoped>
.slide-enter-active, .slide-leave-active {
transition: transform .3s ease;
}
.slide-enter-active.step-1, .slide-leave-active.step-1{
position: absolute;
}
.slide-enter.step-1, .slide-leave-to.step-1 {
transform: translateX(-100%);
}
.slide-enter.step-2, .slide-leave-to.step-2 {
transform: translateX(100%);
}
</style>

View File

@@ -31,8 +31,7 @@ RouterFactory.configure(factory => {
component: Home,
},{
path: '/characterList',
//component: CharacterList,
component: NotImplemented,
component: CharacterList,
},{
path: '/library',
component: Libraries,
@@ -41,12 +40,11 @@ RouterFactory.configure(factory => {
component: Library,
},{
path: '/character/:id/:urlName',
//component: CharacterSheetPage,
component: NotImplemented,
component: CharacterSheetPage,
//component: NotImplemented,
},{
path: '/character/:id',
//component: CharacterSheetPage,
component: NotImplemented,
component: CharacterSheetPage,
},{
path: '/sign-in',
component: SignIn,