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,
optional: true,
},
summary: {
type: String,
optional: true,
},
description: {
type: String,
optional: true,

View File

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

View File

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

View File

@@ -16,25 +16,27 @@
:class="{
'error--text': insufficient,
'clickable': context.editPermission,
'left-pad': leftPad,
}"
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
v-if="model.itemIcon"
class="mr-2"
:shape="model.itemIcon.shape"
: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
class="text-no-wrap text-truncate flex"
>
@@ -86,6 +88,7 @@ export default {
type: Object,
required: true,
},
leftPad: Boolean,
},
computed: {
insufficient(){
@@ -105,4 +108,7 @@ export default {
.theme--dark .clickable:hover {
background: hsla(0,0%,100%,.08);
}
.left-pad {
padding-left: 44px;
}
</style>

View File

@@ -23,8 +23,16 @@
:error-messages="errors.rollBonus"
@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
label="Description"
hint="The rest of the description that doesn't fit in the summary goes here"
:value="model.description"
:error-messages="errors.description"
@change="change('description', ...arguments)"

View File

@@ -1,49 +1,115 @@
<template lang="html">
<div class="action-viewer">
<div class="layout row wrap align-center">
<div>
<div class="action-sub-title layout row align-center justify-space-between wrap mb-3">
<property-tags
:tags="model.tags"
no-margin
class="mx-2"
/>
<div
v-if="!attack"
class="mx-2"
>
{{ model.actionType }}
</div>
<div class="flex">
<property-tags :tags="model.tags" />
</div>
<div v-if="model.usesResult">
{{ model.usesResult - (model.usesUsed) }}/{{ model.usesResult }}
</div>
<div class="layout row align-center justify-space-around">
<v-btn
flat
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
v-if="attack"
class="layout row justify-center align-center ma-3"
>
<div class="headline mr-2">
{{ rollBonus }}
</div>
<em>
to hit
</em>
</div>
<div
v-if="reset"
class="my-2"
>
{{ reset }}
</div>
<property-description
v-if="model.description"
:value="model.description"
<attribute-consumed-view
v-for="attributeConsumed in model.resources.attributesConsumed"
:key="attributeConsumed._id"
class="action-child"
:model="attributeConsumed"
style="padding-left: 44px;"
/>
<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>
</template>
<script>
import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.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 {
components: {
AttributeConsumedView,
ItemConsumedView,
},
mixins: [propertyViewerMixin],
props: {
attack: Boolean,
},
inject: {
context: {
default: {},
},
},
data(){return {
doActionLoading: false,
}},
computed: {
reset(){
let reset = this.model.reset
@@ -55,11 +121,50 @@ export default {
return undefined;
},
rollBonus(){
if (!this.attack) return;
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>
<style lang="css" scoped>
.action-sub-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.action-child {
height: 40px;
}
</style>

View File

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

View File

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

View File

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