Overhauled action detail view

This commit is contained in:
Stefan Zermatten
2020-06-16 13:51:58 +02:00
parent ecba587253
commit e1bfb173ab
9 changed files with 208 additions and 72 deletions

View File

@@ -13,6 +13,10 @@ let ActionSchema = new SimpleSchema({
type: String, type: String,
optional: true, optional: true,
}, },
summary: {
type: String,
optional: true,
},
description: { description: {
type: String, type: String,
optional: true, optional: true,

View File

@@ -35,7 +35,7 @@
</p> </p>
</v-fade-transition> </v-fade-transition>
<template v-if="!editing && !embedded"> <template v-if="!editing && !embedded">
<v-divider /> <v-divider class="my-2" />
<creature-properties-tree <creature-properties-tree
v-if="!editing" v-if="!editing"
:root="{collection: 'creatureProperties', id: model._id}" :root="{collection: 'creatureProperties', id: model._id}"

View File

@@ -1,6 +1,5 @@
<template lang="html"> <template lang="html">
<v-card <v-card
ref="card"
class="action-card" class="action-card"
:class="cardClasses" :class="cardClasses"
:elevation="hovering ? 8 : undefined" :elevation="hovering ? 8 : undefined"
@@ -14,7 +13,7 @@
style="margin-left: -4px; font-size: 18px;" style="margin-left: -4px; font-size: 18px;"
color="primary" color="primary"
:loading="doActionLoading" :loading="doActionLoading"
:disabled="model.insufficientResources" :disabled="model.insufficientResources || !context.editPermission"
@click.stop="doAction" @click.stop="doAction"
> >
<template v-if="attack && !rollBonusTooLong"> <template v-if="attack && !rollBonusTooLong">
@@ -35,7 +34,7 @@
<div <div
class="action-title my-1" class="action-title my-1"
> >
{{ model.name }} {{ model.name || propertyName }}
</div> </div>
<div class="action-sub-title layout row align-center"> <div class="action-sub-title layout row align-center">
<div class="flex"> <div class="flex">
@@ -48,26 +47,35 @@
</div> </div>
</div> </div>
<div class="px-3 pb-3"> <div class="px-3 pb-3">
<attribute-consumed-view <template
v-for="attributeConsumed in model.resources.attributesConsumed" v-if="model.resources.attributesConsumed.length ||
:key="attributeConsumed._id" model.resources.itemsConsumed.length"
class="action-child" >
:model="attributeConsumed" <attribute-consumed-view
/> v-for="attributeConsumed in model.resources.attributesConsumed"
<item-consumed-view :key="attributeConsumed._id"
v-for="itemConsumed in model.resources.itemsConsumed" class="action-child"
:key="itemConsumed._id" :model="attributeConsumed"
class="action-child" />
:model="itemConsumed" <item-consumed-view
:action="model" v-for="itemConsumed in model.resources.itemsConsumed"
/> :key="itemConsumed._id"
<v-divider class="action-child"
v-if=" :model="itemConsumed"
model.resources.attributesConsumed.length || :action="model"
model.resources.itemsConsumed.length />
" <v-divider
class="my-2" v-if="model.summary || children.length"
/> class="my-2"
/>
</template>
<template v-if="model.summary">
<property-description :value="model.summary" />
<v-divider
v-if="children.length"
class="my-2"
/>
</template>
<tree-node-view <tree-node-view
v-for="child in children" v-for="child in children"
:key="child._id" :key="child._id"
@@ -79,18 +87,21 @@
</template> </template>
<script> <script>
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import doAction from '/imports/api/creature/actions/doAction.js'; import doAction from '/imports/api/creature/actions/doAction.js';
import getActiveProperties from '/imports/api/creature/getActiveProperties.js'; import getActiveProperties from '/imports/api/creature/getActiveProperties.js';
import TreeNodeView from '/imports/ui/properties/treeNodeViews/TreeNodeView.vue'; import TreeNodeView from '/imports/ui/properties/treeNodeViews/TreeNodeView.vue';
import AttributeConsumedView from '/imports/ui/properties/components/actions/AttributeConsumedView.vue'; import AttributeConsumedView from '/imports/ui/properties/components/actions/AttributeConsumedView.vue';
import ItemConsumedView from '/imports/ui/properties/components/actions/ItemConsumedView.vue'; import ItemConsumedView from '/imports/ui/properties/components/actions/ItemConsumedView.vue';
import PropertyDescription from '/imports/ui/properties/viewers/shared/PropertyDescription.vue';
export default { export default {
components: { components: {
TreeNodeView, TreeNodeView,
AttributeConsumedView, AttributeConsumedView,
ItemConsumedView, ItemConsumedView,
PropertyDescription,
}, },
inject: { inject: {
context: { context: {
@@ -117,9 +128,6 @@ export default {
hovering: false, hovering: false,
}}, }},
computed: { computed: {
hasClickListener(){
return this.$listeners && this.$listeners.click
},
rollBonus(){ rollBonus(){
if (!this.attack) return; if (!this.attack) return;
return numberToSignedString(this.model.rollBonusResult); return numberToSignedString(this.model.rollBonusResult);
@@ -133,6 +141,9 @@ export default {
usesLeft(){ usesLeft(){
return Math.max(this.model.usesResult - this.model.usesUsed, 0); return Math.max(this.model.usesResult - this.model.usesUsed, 0);
}, },
propertyName(){
return getPropertyName(this.model.type);
},
cardClasses() { cardClasses() {
return { return {
'theme--dark': this.theme.isDark, 'theme--dark': this.theme.isDark,
@@ -201,7 +212,6 @@ export default {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: .3s cubic-bezier(.25,.8,.5,1);
width: 100%; width: 100%;
} }
.action-child { .action-child {
@@ -225,4 +235,7 @@ export default {
.action-card.theme--dark.muted-text .v-icon { .action-card.theme--dark.muted-text .v-icon {
color: hsla(0,0%,100%,.3) !important; color: hsla(0,0%,100%,.3) !important;
} }
.action-card .property-description > p:last-of-type {
margin-bottom: 0;
}
</style> </style>

View File

@@ -16,25 +16,27 @@
:class="{ :class="{
'error--text': insufficient, 'error--text': insufficient,
'clickable': context.editPermission, 'clickable': context.editPermission,
'left-pad': leftPad,
}" }"
v-on="on" v-on="on"
> >
<div
class="mr-2"
style="width: 24px; text-align: center;"
>
<template v-if="model.quantity === 1">
{{ model.available }}
</template>
<template v-else-if="model.quantity !== 0">
{{ model.available }} / {{ model.quantity }}
</template>
</div>
<svg-icon <svg-icon
v-if="model.itemIcon" v-if="model.itemIcon"
class="mr-2"
:shape="model.itemIcon.shape" :shape="model.itemIcon.shape"
:color="model.itemColor" :color="model.itemColor"
/> />
<div
class="mr-2 text-no-wrap"
style="min-width: 24px; text-align: center;"
>
<template v-if="model.quantity !== 0 && insufficient">
{{ model.available }} / {{ model.quantity }}
</template>
<template v-else>
{{ model.available }}
</template>
</div>
<div <div
class="text-no-wrap text-truncate flex" class="text-no-wrap text-truncate flex"
> >
@@ -86,6 +88,7 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
leftPad: Boolean,
}, },
computed: { computed: {
insufficient(){ insufficient(){
@@ -105,4 +108,7 @@ export default {
.theme--dark .clickable:hover { .theme--dark .clickable:hover {
background: hsla(0,0%,100%,.08); background: hsla(0,0%,100%,.08);
} }
.left-pad {
padding-left: 44px;
}
</style> </style>

View File

@@ -23,8 +23,16 @@
:error-messages="errors.rollBonus" :error-messages="errors.rollBonus"
@change="change('rollBonus', ...arguments)" @change="change('rollBonus', ...arguments)"
/> />
<text-area
label="Summary"
hint="This will appear in the action card in the character sheet"
:value="model.summary"
:error-messages="errors.summary"
@change="change('summary', ...arguments)"
/>
<text-area <text-area
label="Description" label="Description"
hint="The rest of the description that doesn't fit in the summary goes here"
:value="model.description" :value="model.description"
:error-messages="errors.description" :error-messages="errors.description"
@change="change('description', ...arguments)" @change="change('description', ...arguments)"

View File

@@ -1,49 +1,115 @@
<template lang="html"> <template lang="html">
<div class="action-viewer"> <div class="action-viewer">
<div class="layout row wrap align-center"> <div class="action-sub-title layout row align-center justify-space-between wrap mb-3">
<div> <property-tags
:tags="model.tags"
no-margin
class="mx-2"
/>
<div
v-if="!attack"
class="mx-2"
>
{{ model.actionType }} {{ model.actionType }}
</div> </div>
<div class="flex"> </div>
<property-tags :tags="model.tags" /> <div class="layout row align-center justify-space-around">
</div> <v-btn
<div v-if="model.usesResult"> flat
{{ model.usesResult - (model.usesUsed) }}/{{ model.usesResult }} outline
style="font-size: 18px;"
class="ma-2"
color="primary"
:icon="!rollBonusTooLong"
:loading="doActionLoading"
:disabled="model.insufficientResources || !context.editPermission"
@click.stop="doAction"
>
<template v-if="attack">
{{ rollBonus }}
</template>
<v-icon v-else>
{{ actionTypeIcon }}
</v-icon>
</v-btn>
<div v-if="model.uses">
<span
class="uses mx-2"
>
{{ usesLeft }}/{{ model.usesResult }} uses
</span>
<span
v-if="reset"
class="mx-2"
>
{{ reset }}
</span>
<v-btn
v-if="context.creature"
outline
color="primary"
:disabled="!model.usesUsed || !context.editPermission"
@click="resetUses"
>
Reset
</v-btn>
</div> </div>
</div> </div>
<div <attribute-consumed-view
v-if="attack" v-for="attributeConsumed in model.resources.attributesConsumed"
class="layout row justify-center align-center ma-3" :key="attributeConsumed._id"
> class="action-child"
<div class="headline mr-2"> :model="attributeConsumed"
{{ rollBonus }} style="padding-left: 44px;"
</div>
<em>
to hit
</em>
</div>
<div
v-if="reset"
class="my-2"
>
{{ reset }}
</div>
<property-description
v-if="model.description"
:value="model.description"
/> />
<item-consumed-view
v-for="itemConsumed in model.resources.itemsConsumed"
:key="itemConsumed._id"
class="action-child"
:model="itemConsumed"
:action="model"
left-pad
/>
<v-divider
v-if="model.summary || model.description"
class="my-3"
/>
<template v-if="model.summary">
<property-description :value="model.summary" />
<v-divider
v-if="model.description"
class="my-3"
/>
</template>
<property-description :value="model.description" />
</div> </div>
</template> </template>
<script> <script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'; import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import doAction from '/imports/api/creature/actions/doAction.js';
import AttributeConsumedView from '/imports/ui/properties/components/actions/AttributeConsumedView.vue';
import ItemConsumedView from '/imports/ui/properties/components/actions/ItemConsumedView.vue';
import { updateProperty } from '/imports/api/creature/CreatureProperties.js';
export default { export default {
components: {
AttributeConsumedView,
ItemConsumedView,
},
mixins: [propertyViewerMixin], mixins: [propertyViewerMixin],
props: { props: {
attack: Boolean, attack: Boolean,
}, },
inject: {
context: {
default: {},
},
},
data(){return {
doActionLoading: false,
}},
computed: { computed: {
reset(){ reset(){
let reset = this.model.reset let reset = this.model.reset
@@ -55,11 +121,50 @@ export default {
return undefined; return undefined;
}, },
rollBonus(){ rollBonus(){
if (!this.attack) return;
return numberToSignedString(this.model.rollBonusResult); return numberToSignedString(this.model.rollBonusResult);
}, },
rollBonusTooLong(){
return this.rollBonus && this.rollBonus.length > 3;
},
totalUses(){
return Math.max(this.model.usesResult, 0);
},
usesLeft(){
return Math.max(this.model.usesResult - this.model.usesUsed, 0);
},
actionTypeIcon() {
return `$vuetify.icons.${this.model.actionType}`;
},
},
methods: {
doAction(){
this.doActionLoading = true;
doAction.call({actionId: this.model._id}, error => {
this.doActionLoading = false;
if (error){
console.error(error);
}
});
},
resetUses(){
updateProperty.call({
_id: this.model._id,
path: ['usesUsed'],
value: 0,
});
},
}, },
} }
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.action-sub-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.action-child {
height: 40px;
}
</style> </style>

View File

@@ -3,10 +3,7 @@
<property-name :value="model.name" /> <property-name :value="model.name" />
<property-description :value="model.summary" /> <property-description :value="model.summary" />
<v-divider class="mt-3 mb-3" /> <v-divider class="mt-3 mb-3" />
<property-description <property-description :value="model.description" />
v-if="model.description"
:value="model.description"
/>
</div> </div>
</template> </template>

View File

@@ -1,5 +1,6 @@
<template lang="html"> <template lang="html">
<computed <computed
v-if="value"
class="property-description" class="property-description"
embedded embedded
:value="value" :value="value"

View File

@@ -1,7 +1,8 @@
<template lang="html"> <template lang="html">
<div <div
v-if="tagString" v-if="tagString"
class="tags ma-3 " class="tags"
:class="{'ma-3': !noMargin}"
> >
{{ tagString }} {{ tagString }}
</div> </div>
@@ -13,7 +14,8 @@ export default {
tags: { tags: {
type: Array, type: Array,
default: () => [], default: () => [],
} },
noMargin: Boolean,
}, },
computed:{ computed:{
tagString(){ tagString(){