Improved property viewers, added some new ones

This commit is contained in:
Stefan Zermatten
2019-08-06 13:16:46 +02:00
parent b70634f5de
commit 45c84e28a3
33 changed files with 379 additions and 197 deletions

View File

@@ -1,5 +1,5 @@
import SimpleSchema from 'simpl-schema';
import { EffectSchema } from '/imports/api/properties/Effects.js';
import { StoredEffectSchema } from '/imports/api/properties/Effects.js';
let BuffSchema = new SimpleSchema({
name: {
@@ -25,7 +25,7 @@ let StoredBuffSchema = new SimpleSchema({
defaultValue: [],
},
'effects.$': {
type: EffectSchema,
type: StoredEffectSchema,
},
target: {
type: String,

View File

@@ -5,13 +5,6 @@ import SimpleSchema from 'simpl-schema';
* that modify their final value or presentation in some way
*/
let EffectSchema = new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoValue(){
if (!this.isSet) return Random.id();
}
},
name: {
type: String,
optional: true,
@@ -43,6 +36,16 @@ let EffectSchema = new SimpleSchema({
},
});
const StoredEffectSchema = new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoValue(){
if (!this.isSet) return Random.id();
}
},
}).extend(EffectSchema);
const ComputedEffectSchema = new SimpleSchema({
// The computed result of the effect
result: {
@@ -51,4 +54,4 @@ const ComputedEffectSchema = new SimpleSchema({
},
}).extend(EffectSchema);
export { EffectSchema, ComputedEffectSchema };
export { EffectSchema, StoredEffectSchema, ComputedEffectSchema };

View File

@@ -20,7 +20,7 @@ let SkillSchema = new SimpleSchema({
optional: true,
},
// What type of skill is this
type: {
skillType: {
type: String,
allowedValues: [
"skill",
@@ -43,6 +43,11 @@ let SkillSchema = new SimpleSchema({
type: Number,
optional: true,
},
// Description of what the skill is used for
description: {
type: String,
optional: true,
},
});

View File

@@ -63,7 +63,7 @@
* the tree view shows off the full character structure, and where each part of
* character comes from.
**/
import PropertyIcon from '/imports/ui/components/properties/PropertyIcon.vue';
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';
export default {
name: 'tree-node',
beforeCreate() {

View File

@@ -42,7 +42,7 @@
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/components/properties/PropertyIcon.vue';
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';
import propertyFormIndex from '/imports/ui/properties/forms/shared/propertyFormIndex.js';
import { get } from 'lodash';

View File

@@ -59,7 +59,7 @@
import LibraryNodes, { insertNode } from '/imports/api/library/LibraryNodes.js';
import Libraries from '/imports/api/library/Libraries.js';
import { setDocToLastOrder } from '/imports/api/parenting/order.js';
import PropertyIcon from '/imports/ui/components/properties/PropertyIcon.vue';
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
export default {

View File

@@ -0,0 +1,18 @@
<template lang="html">
<v-icon>{{icon}}</v-icon>
</template>
<script>
import { getPropertyIcon } from '/imports/constants/PROPERTIES.js';
export default {
props: {
type: String,
},
computed: {
icon(){
return getPropertyIcon(this.type);
},
},
}
</script>

View File

@@ -24,5 +24,5 @@ export default {
}
</script>
<style lang="css" scoped>
<style lang="css">
</style>

View File

@@ -0,0 +1,25 @@
<template lang="html">
<v-icon v-if="value !== undefined">{{displayedIcon}}</v-icon>
</template>
<script>
export default {
props: {
value: Number,
},
computed: {
displayedIcon(){
let value = this.value;
if (value == 0.5){
return 'brightness_2';
} else if (value == 1) {
return 'brightness_1'
} else if (value == 2){
return 'album'
} else {
return 'radio_button_unchecked';
}
}
}
}
</script>

View File

@@ -1,28 +1,19 @@
<template lang="html">
<property-insert-dialog
documentType="Feature"
:doc="feature"
:schema="schema"
:errors.sync="errors"
>
<feature-form
:feature="feature"
@update="update"
:debounce-time="0"
:errors="errors"
/>
</property-insert-dialog>
</template>
<script>
import FeatureForm from '/imports/ui/properties/forms/FeatureForm.vue';
import Features, { FeatureSchema } from '/imports/api/properties/Features.js';
import PropertyInsertDialog from '/imports/ui/components/properties/PropertyInsertDialog.vue';
export default {
components: {
FeatureForm,
PropertyInsertDialog,
},
data(){ return {
feature: {

View File

@@ -1,5 +1,4 @@
<template lang="html">
<property-dialog :doc="feature" collection="features" @remove="$emit('remove')">
<div>
<markdown-text :markdown="feature.computedDescription || feature.description"/>
<!--
@@ -7,19 +6,16 @@
:parent="feature"
/>
-->
<feature-form slot="form" :feature="feature" @update="(update, ack) => $emit('update', update, ack)"/>
</div>
<feature-form slot="form" :feature="feature" @update="(update, ack) => $emit('update', update, ack)"/>
</property-dialog>
</template>
<script>
import PropertyDialog from '/imports/ui/components/properties/PropertyDialog.vue';
import FeatureForm from '/imports/ui/properties/forms/FeatureForm.vue';
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
export default {
components: {
PropertyDialog,
FeatureForm,
MarkdownText,
},

View File

@@ -30,10 +30,17 @@
<smart-select
label="Type"
:items="skillTypes"
:value="model.type"
:error-messages="errors.type"
:value="model.skillType"
:error-messages="errors.skillType"
:menu-props="{auto: true, lazy: true}"
@change="(value, ack) => $emit('change', {path: ['type'], value, ack})"
@change="(value, ack) => $emit('change', {path: ['skillType'], value, ack})"
:debounce-time="debounceTime"
/>
<text-area
label="Description"
:value="model.description"
:error-messages="errors.description"
@change="(value, ack) => $emit('change', {path: ['description'], value, ack})"
:debounce-time="debounceTime"
/>
<form-section name="Advanced" standalone>

View File

@@ -11,40 +11,31 @@
<div v-if="model.mod !== undefined">
{{numberToSignedString(model.mod)}}
</div>
<h1 class="display-1">
{{model.name}}
</h1>
<p class="my-2">
<code>{{model.variableName}}</code>
</p>
<property-name :value="model.name"/>
<property-variable-name :value="model.variableName"/>
<p v-if="reset">
{{reset}}
</p>
<effect-viewer
class="mb-3"
operation="base"
:model="{result: model.baseValue, name: model.attributeType, operation: 'base'}"
:model="{
result: model.baseValue,
operation: 'base'
}"
/>
<p v-if="model.description">
{{model.description}}
</p>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import EffectViewer from '/imports/ui/properties/viewers/EffectViewer.vue';
export default {
mixins: [propertyViewerMixin],
components: {
EffectViewer,
},
props: {
model: {
type: Object,
required: true,
},
},
methods: {
numberToSignedString,
},

View File

@@ -8,37 +8,38 @@
{{model.value}}
</div>
</div>
<h1 class="display-1">
{{model.name}}
</h1>
<effect-viewer
class="mb-3"
operation="base"
v-for="effect in model.effects"
:model="effect"
/>
<div v-if="model.duration">
{{model.duration}}
<property-name :value="model.name"/>
<property-field name="Duration" :value="model.duration"/>
<div>
<div class="subheading">
Effects
</div>
<div
class="layout row center mb-2 ml-2"
v-for="effect in model.effects"
>
<property-icon type="effect" class="mr-2"/>
<effect-viewer
operation="base"
:model="effect"
/>
</div>
</div>
<p v-if="model.description">
{{model.description}}
</p>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import EffectViewer from '/imports/ui/properties/viewers/EffectViewer.vue';
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';
export default {
mixins: [propertyViewerMixin],
components: {
EffectViewer,
},
props: {
model: {
type: Object,
required: true,
},
PropertyIcon,
},
methods: {
numberToSignedString,

View File

@@ -1,14 +1,16 @@
<template lang="html">
<div class="class-level-viewer">
<h1 class="display-1">
{{model.name}}
<div>
<span class="name headline">
{{model.name}}
</span>
<span
class="display-2"
v-if="model.level"
>
{{model.level}}
</span>
</h1>
</div>
<p class="my-2">
<code>{{model.variableName}}</code>
</p>
@@ -19,13 +21,10 @@
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
},
}
mixins: [propertyViewerMixin],
}
</script>

View File

@@ -1,34 +1,22 @@
<template lang="html">
<div class="container-viewer">
<h1 class="display-1">
{{model.name}}
</h1>
<property-name :value="model.name"/>
<div v-if="!model.carried" class="caption">
Not carried
</div>
<div v-if="model.contentsWeightless" class="caption">
Contents are weightless
</div>
<div>
Weight: {{model.weight}} lbs
</div>
<div>
Value: {{model.value}} gp
</div>
<p v-if="model.description">
{{model.description}}
</p>
<property-field name="Weight" :value="`${model.weight} lbs`"/>
<property-field name="Value" :value="`${model.value} gp`"/>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
},
},
mixins: [propertyViewerMixin],
}
</script>

View File

@@ -1,8 +1,6 @@
<template lang="html">
<div>
<h1 class="display-1">
{{model.name}}
</h1>
<property-name :value="model.name"/>
<div>
{{model.damageType}} {{operation}}
</div>
@@ -10,13 +8,9 @@
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
}
},
mixins: [propertyViewerMixin],
computed: {
operation(){
switch (this.model.value){

View File

@@ -1,46 +1,39 @@
<template lang="html">
<v-list-tile
class="effect-list-tile"
:class="{disabled: !model.enabled}"
:data-id="model._id"
>
<v-layout row align-center class="net-effect">
<v-icon class="icon">{{getEffectIcon(model.operation, model.result)}}</v-icon>
<div class="value display-1 pr-2" v-if="showValue(model.operation) && model.result !== undefined">
{{getValue(model.operation, model.result)}}
<div class="effect-viewer">
<property-name :value="model.name" v-if="model.name"/>
<div class="layout row center wrap">
<div class="headline mr-2 my-0" v-if="model.stat">
{{model.stat}}
</div>
<div class="calculation body-2 pr-2" v-else>
{{model.operation === 'conditional' ? model.calculation : ''}}
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-icon v-on="on" class="mr-2" style="cursor: default;">{{effectIcon}}</v-icon>
</template>
<span>{{operation}}</span>
</v-tooltip>
<div v-if="showValue" class="headline">
{{displayedValue}}
</div>
</v-layout>
<v-list-tile-content>
<v-list-tile-title class="stat" v-if="model.showStatName">
{{model.statName}}
</v-list-tile-title>
<v-list-tile-title class="name" v-else>
{{model.name}}
</v-list-tile-title>
<v-list-tile-sub-title class="operation">
{{getOperation(model.operation)}}
</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</div>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import getEffectIcon from '/imports/ui/utility/getEffectIcon.js';
export default {
props: {
model: {
type: Object,
required: true,
mixins: [propertyViewerMixin],
computed: {
resolvedValue(){
return this.model.result !== undefined ? this.model.result : +this.model.calculation;
},
},
methods: {
getEffectIcon,
getOperation(op, value){
switch(op) {
effectIcon(){
let value = this.resolvedValue;
return getEffectIcon(this.model.operation, value);
},
operation(){
switch(this.model.operation) {
case 'base': return 'Base value';
case 'add': return 'Add';
case 'mul': return 'Multiply';
@@ -53,8 +46,8 @@
case 'conditional': return 'Conditional benefit' ;
}
},
showValue(op){
switch(op) {
showValue(){
switch(this.model.operation) {
case 'base': return true;
case 'add': return true;
case 'mul': return true;
@@ -67,8 +60,9 @@
case 'conditional': return false;
}
},
getValue(op, value){
switch(op) {
displayedValue(){
let value = this.resolvedValue;
switch(this.model.operation) {
case 'base': return value;
case 'add': return Math.abs(value);
case 'mul': return value;

View File

@@ -1,12 +1,10 @@
<template lang="html">
<div class="experience-viewer">
<h1 class="display-1" v-if="model.value">
<div class="display-1" v-if="model.value">
{{model.value}} XP
</h1>
</div>
<div class="headline layout row mb-3">
<div>
{{model.name}}
</div>
<property-name :value="model.name"/>
<v-spacer/>
<div>
{{model.worldDate}}
@@ -22,13 +20,9 @@
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
},
},
mixins: [propertyViewerMixin],
}
</script>

View File

@@ -1,25 +1,17 @@
<template lang="html">
<div class="feature-viewer">
<h1 class="display-1">
{{model.name}}
</h1>
<property-name :value="model.name"/>
<div v-if="model.alwaysEnabled" class="caption">
Always enabled
</div>
<p v-if="model.description">
{{model.description}}
</p>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
},
},
mixins: [propertyViewerMixin],
}
</script>

View File

@@ -1,19 +1,13 @@
<template lang="html">
<div class="folder-viewer">
<h1 class="display-1">
{{model.name}}
</h1>
<property-name :value="model.name"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
},
},
mixins: [propertyViewerMixin],
}
</script>

View File

@@ -0,0 +1,20 @@
<template lang="html">
<div class="item-viewer">
<property-name :value="model.name"/>
<property-field name="Plural name" :value="model.plural"/>
<property-field name="Quantity" :value="model.quantity"/>
<property-field name="Weight" :value="`${model.weight} lbs`"/>
<property-field name="Value" :value="`${model.value} gp`"/>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
mixins: [propertyViewerMixin],
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,22 +1,14 @@
<template lang="html">
<div class="note-viewer">
<h1 class="display-1">
{{model.name}}
</h1>
<p v-if="model.description">
{{model.description}}
</p>
<property-name :value="model.name"/>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
props: {
model: {
type: Object,
required: true,
},
},
mixins: [propertyViewerMixin],
}
</script>

View File

@@ -0,0 +1,34 @@
<template lang="html">
<div class="proficiency-viewer">
<div class="headline layout row">
{{model.skill}}
<proficiency-icon :value="model.value" class="ml-3 mr-1"/>
<div>
{{proficiencyText}}
</div>
</div>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js';
import ProficiencyIcon from '/imports/ui/properties/components/ProficiencyIcon.vue';
export default {
mixins: [propertyViewerMixin],
components: {
ProficiencyIcon,
},
computed: {
proficiencyText(){
switch (this.model.value){
case 0.5: return "Half proficiency bonus";
case 1: return "Proficient";
case 2: return "Double proficiency bonus";
}
}
}
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,21 @@
<template lang="html">
<div class="skill-viewer">
<property-name :value="model.name"/>
<property-variable-name :value="model.variableName"/>
<property-field name="Ability" :value="model.ability"/>
<property-field name="Type" :value="model.skillType"/>
<property-field name="Base value" :value="model.baseValue"/>
<property-field name="Base proficiency" :value="model.baseProficiency"/>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js';
export default {
mixins: [propertyViewerMixin],
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,18 @@
<template lang="html">
<div class="spell-list-viewer">
<property-name :value="model.name"/>
<property-variable-name :value="model.variableName"/>
<property-field name="Maximum prepared spells" :value="model.maxPrepared"/>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
mixins: [propertyViewerMixin],
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,20 @@
<template lang="html">
<div class="spell-viewer">
<property-name :value="model.name"/>
<property-field name="Casting time" :value="model.castingTime"/>
<property-field name="Range" :value="model.range"/>
<property-field name="Duration" :value="model.duration"/>
<property-field name="Level" :value="`${model.level} ${model.school}`"/>
<property-description :value="model.description"/>
</div>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'
export default {
mixins: [propertyViewerMixin],
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,13 @@
<template lang="html">
<p v-if="value" class="mt-3">
{{value}}
</p>
</template>
<script>
export default {
props: {
value: String,
},
}
</script>

View File

@@ -0,0 +1,22 @@
<template lang="html">
<div v-if="value !== undefined">
<div class="caption">
{{name}}
</div>
<p class="ml-2 subheading">
{{value}}
</p>
</div>
</template>
<script>
export default {
props: {
name: String,
value: [String, Number],
}
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,13 @@
<template lang="html">
<div class="name headline mb-2">
{{value}}
</div>
</template>
<script>
export default {
props: {
value: String,
}
}
</script>

View File

@@ -0,0 +1,16 @@
<template lang="html">
<div v-if="value" class="mb-3">
<code>{{value}}</code>
</div>
</template>
<script>
export default {
props: {
value: String,
}
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -8,13 +8,13 @@ import EffectViewer from '/imports/ui/properties/viewers/EffectViewer.vue';
import ExperienceViewer from '/imports/ui/properties/viewers/ExperienceViewer.vue';
import FeatureViewer from '/imports/ui/properties/viewers/FeatureViewer.vue';
import FolderViewer from '/imports/ui/properties/viewers/FolderViewer.vue';
//import ItemViewer from '/imports/ui/properties/viewers/ItemViewer.vue';
import ItemViewer from '/imports/ui/properties/viewers/ItemViewer.vue';
import NoteViewer from '/imports/ui/properties/viewers/NoteViewer.vue';
//import ProficiencyViewer from '/imports/ui/properties/viewers/ProficiencyViewer.vue';
import ProficiencyViewer from '/imports/ui/properties/viewers/ProficiencyViewer.vue';
//import RollViewer from '/imports/ui/properties/viewers/RollViewer.vue';
//import SkillViewer from '/imports/ui/properties/viewers/SkillViewer.vue';
//import SpellListViewer from '/imports/ui/properties/viewers/SpellListViewer.vue';
//import SpellViewer from '/imports/ui/properties/viewers/SpellViewer.vue';
import SkillViewer from '/imports/ui/properties/viewers/SkillViewer.vue';
import SpellListViewer from '/imports/ui/properties/viewers/SpellListViewer.vue';
import SpellViewer from '/imports/ui/properties/viewers/SpellViewer.vue';
export default {
// action: ActionViewer,
@@ -27,11 +27,11 @@ export default {
effect: EffectViewer,
feature: FeatureViewer,
folder: FolderViewer,
// item: ItemViewer,
item: ItemViewer,
note: NoteViewer,
// proficiency: ProficiencyViewer,
proficiency: ProficiencyViewer,
// roll: RollViewer,
// skill: SkillViewer,
// spellList: SpellListViewer,
// spell: SpellViewer,
skill: SkillViewer,
spellList: SpellListViewer,
spell: SpellViewer,
};

View File

@@ -0,0 +1,21 @@
import PropertyName from '/imports/ui/properties/viewers/shared/PropertyName.vue';
import PropertyVariableName from '/imports/ui/properties/viewers/shared/PropertyVariableName.vue';
import PropertyField from '/imports/ui/properties/viewers/shared/PropertyField.vue';
import PropertyDescription from '/imports/ui/properties/viewers/shared/PropertyDescription.vue';
const propertyViewerMixin = {
components: {
PropertyName,
PropertyVariableName,
PropertyField,
PropertyDescription,
},
props: {
model: {
type: Object,
required: true,
},
},
};
export default propertyViewerMixin;