Form overhaul: roll -> trigger

roll, savingThrow, skill, slot, slotfiller, spell, spellList,
toggle, trigger
This commit is contained in:
Stefan Zermatten
2023-05-17 11:32:39 +02:00
parent 4c34986fb7
commit 0a3ea7672f
12 changed files with 443 additions and 814 deletions

View File

@@ -203,7 +203,7 @@ const updateLibraryNode = new ValidatedMethod({
}, },
mixins: [RateLimiterMixin], mixins: [RateLimiterMixin],
rateLimit: { rateLimit: {
numRequests: 5, numRequests: 15,
timeInterval: 5000, timeInterval: 5000,
}, },
run({ _id, path, value }) { run({ _id, path, value }) {

View File

@@ -22,6 +22,12 @@
height="42" height="42"
v-on="(value == option.value) ? {} : { click() { click(option.value) } }" v-on="(value == option.value) ? {} : { click() { click(option.value) } }"
> >
<v-icon
v-if="option.icon"
left
>
{{ option.icon }}
</v-icon>
{{ option.name }} {{ option.name }}
</v-btn> </v-btn>
</v-btn-toggle> </v-btn-toggle>

View File

@@ -83,19 +83,6 @@ import propertyFormMixin from '/imports/client/ui/properties/forms/shared/proper
export default { export default {
mixins: [propertyFormMixin], mixins: [propertyFormMixin],
data() {
return {
targetOptions: [
{
text: 'Self',
value: 'self',
}, {
text: 'Target',
value: 'target',
},
],
}
},
} }
</script> </script>

View File

@@ -1,17 +1,6 @@
<template lang="html"> <template lang="html">
<div class="roll-form"> <div class="roll-form">
<v-row dense> <v-row dense>
<v-col
cols="12"
md="6"
>
<text-field
label="Name"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
</v-col>
<v-col <v-col
cols="12" cols="12"
md="6" md="6"
@@ -25,48 +14,30 @@
@change="change('variableName', ...arguments)" @change="change('variableName', ...arguments)"
/> />
</v-col> </v-col>
</v-row> <v-col
<computed-field cols="12"
label="Roll" md="6"
hint="The calculation that will be evaluated when the roll is triggered by an action. The result will be saved as the variable name in the context of the roll."
:model="model.roll"
:error-messages="errors.roll"
@change="({path, value, ack}) =>
$emit('change', {path: ['roll', ...path], value, ack})"
/>
<form-sections>
<form-section
v-if="$slots.children"
name="Children"
> >
<slot name="children" /> <computed-field
</form-section> label="Roll"
hint="The calculation that will be evaluated when the roll is triggered by an action. The result will be saved as the variable name in the context of the roll."
<form-section name="Advanced"> :model="model.roll"
<v-row dense> :error-messages="errors.roll"
<v-col @change="({path, value, ack}) =>
cols="12" $emit('change', {path: ['roll', ...path], value, ack})"
sm="6" />
md="4" </v-col>
> </v-row>
<smart-switch <form-sections>
label="Don't show in log" <form-section name="Log">
:value="model.silent" <smart-switch
:error-messages="errors.silent" label="Don't show in log"
@change="change('silent', ...arguments)" :value="model.silent"
/> :error-messages="errors.silent"
</v-col> @change="change('silent', ...arguments)"
</v-row>
<smart-combobox
label="Tags"
multiple
chips
deletable-chips
hint="Used to let slots find this property in a library, should otherwise be left blank"
:value="model.tags"
@change="change('tags', ...arguments)"
/> />
</form-section> </form-section>
<slot />
</form-sections> </form-sections>
</div> </div>
</template> </template>

View File

@@ -1,25 +1,13 @@
<template lang="html"> <template lang="html">
<div class="saving-throw-form"> <div class="saving-throw-form">
<v-row dense> <v-row dense>
<v-col
cols="12"
md="6"
>
<text-field
ref="focusFirst"
label="Name"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
</v-col>
<v-col <v-col
cols="12" cols="12"
md="6" md="6"
> >
<computed-field <computed-field
label="DC" label="DC"
hint="A calculation of the DC that the target of an action needs to save against in order to succeed. If the saving throw is lower than the DC, the children of this property will be activated." hint="Saving throw DC"
:model="model.dc" :model="model.dc"
:error-messages="errors.dc" :error-messages="errors.dc"
@change="({path, value, ack}) => @change="({path, value, ack}) =>
@@ -43,41 +31,29 @@
cols="12" cols="12"
md="6" md="6"
> >
<smart-select <smart-toggle
label="Target" label="Target creature"
:hint="targetOptionHint"
:items="targetOptions"
:value="model.target" :value="model.target"
:options="[
{name: 'Action Target', value: 'target'},
{name: 'Self', value: 'self'},
]"
:error-messages="errors.target" :error-messages="errors.target"
:menu-props="{auto: true, lazy: true}"
@change="change('target', ...arguments)" @change="change('target', ...arguments)"
/> />
</v-col> </v-col>
</v-row> </v-row>
<smart-combobox <form-sections>
label="Tags" <form-section name="Log">
class="mr-2" <smart-switch
multiple label="Don't show in log"
chips :value="model.silent"
deletable-chips :error-messages="errors.silent"
hint="Used to let slots find this property in a library, should otherwise be left blank" @change="change('silent', ...arguments)"
:value="model.tags" />
:error-messages="errors.tags" </form-section>
@change="change('tags', ...arguments)" <slot />
/> </form-sections>
<smart-switch
label="Don't show in log"
:value="model.silent"
:error-messages="errors.silent"
@change="change('silent', ...arguments)"
/>
<form-section
v-if="$slots.children"
name="Children"
standalone
>
<slot name="children" />
</form-section>
</div> </div>
</template> </template>
@@ -87,25 +63,5 @@ import propertyFormMixin from '/imports/client/ui/properties/forms/shared/proper
export default { export default {
mixins: [saveListMixin, propertyFormMixin], mixins: [saveListMixin, propertyFormMixin],
computed: {
targetOptions() {
return [
{
text: 'Self',
value: 'self',
}, {
text: 'Target',
value: 'target',
},
];
},
targetOptionHint() {
let hints = {
self: 'The save will be applied to the character taking the action',
target: 'The save will be applied to the targets of the action',
};
return hints[this.model.target];
}
},
}; };
</script> </script>

View File

@@ -1,42 +1,49 @@
<template lang="html"> <template lang="html">
<div class="skill-form"> <div class="skill-form">
<div class="layout wrap"> <v-row dense>
<text-field <v-col
ref="focusFirst" cols="12"
label="Name" md="6"
:value="model.name" >
:error-messages="errors.name" <text-field
@change="change('name', ...arguments)" label="Variable name"
/> :value="model.variableName"
<text-field style="flex-basis: 300px;"
label="Variable name" hint="Use this name in formulae to reference this skill"
:value="model.variableName" :error-messages="errors.variableName"
style="flex-basis: 300px;" @change="change('variableName', ...arguments)"
hint="Use this name in formulae to reference this skill" />
:error-messages="errors.variableName" </v-col>
@change="change('variableName', ...arguments)" <v-col
/> cols="12"
<smart-combobox md="6"
label="Ability" >
:value="model.ability" <smart-combobox
style="flex-basis: 300px;" label="Ability"
hint="Which ability is this skill based off of" :value="model.ability"
:items="abilityScoreList" style="flex-basis: 300px;"
:error-messages="errors.ability" hint="Which ability is this skill based off of"
@change="change('ability', ...arguments)" :items="abilityScoreList"
/> :error-messages="errors.ability"
</div> @change="change('ability', ...arguments)"
<smart-select />
label="Type" </v-col>
clearable <v-col
:items="skillTypes" cols="12"
:value="model.skillType" md="6"
:error-messages="errors.skillType" >
:menu-props="{auto: true, lazy: true}" <smart-select
:hint="skillTypeHints[model.skillType]" label="Type"
@change="change('skillType', ...arguments)" clearable
/> :items="skillTypes"
:value="model.skillType"
:error-messages="errors.skillType"
:menu-props="{auto: true, lazy: true}"
:hint="skillTypeHints[model.skillType]"
@change="change('skillType', ...arguments)"
/>
</v-col>
</v-row>
<inline-computation-field <inline-computation-field
label="Description" label="Description"
:model="model.description" :model="model.description"
@@ -46,39 +53,33 @@
/> />
<form-sections> <form-sections>
<form-section <form-section name="Base Values">
v-if="$slots.children" <v-row dense>
name="Children" <v-col
> cols="12"
<slot name="children" /> md="6"
</form-section> >
<proficiency-select
<form-section name="Advanced"> label="Base Proficiency"
<smart-combobox :value="model.baseProficiency"
label="Tags" :error-messages="errors.baseProficiency"
multiple @change="change('baseProficiency', ...arguments)"
chips />
deletable-chips </v-col>
:value="model.tags" <v-col
@change="change('tags', ...arguments)" cols="12"
/> md="6"
<div class="layout justify-center"> >
<computed-field <computed-field
label="Base Value" label="Base Value"
hint="This is the value of the skill before effects are applied" hint="This is the value of the skill before effects are applied"
:model="model.baseValue" :model="model.baseValue"
:error-messages="errors.baseValue" :error-messages="errors.baseValue"
@change="({path, value, ack}) => @change="({path, value, ack}) =>
$emit('change', {path: ['baseValue', ...path], value, ack})" $emit('change', {path: ['baseValue', ...path], value, ack})"
/> />
<proficiency-select </v-col>
style="flex-basis: 300px;" </v-row>
label="Base Proficiency"
:value="model.baseProficiency"
:error-messages="errors.baseProficiency"
@change="change('baseProficiency', ...arguments)"
/>
</div>
</form-section> </form-section>
</form-sections> </form-sections>
</div> </div>

View File

@@ -1,114 +1,23 @@
<template lang="html"> <template lang="html">
<div class="slot-filler-form"> <div class="slot-filler-form">
<v-row
dense
align="start"
>
<v-col
cols="12"
sm="9"
md="10"
>
<text-field
ref="focusFirst"
label="Name"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
</v-col>
<v-col
cols="12"
sm="3"
md="2"
>
<icon-picker
:value="model.icon"
:error-messages="errors.icon"
height="56"
width="100%"
button-style="margin-bottom: 30px;"
@change="change('icon', ...arguments)"
/>
</v-col>
</v-row>
<text-area <text-area
label="Description" label="Description"
:value="model.description" :value="model.description"
:error-messages="errors.description" :error-messages="errors.description"
@change="change('description', ...arguments)" @change="change('description', ...arguments)"
/> />
<form-sections
<text-field v-if="$slots.default"
label="Picture URL"
hint="A link to an image representing this property"
:value="model.picture"
:error-messages="errors.picture"
@change="change('picture', ...arguments)"
/>
<smart-select
label="Type"
style="flex-basis: 300px;"
clearable
hint="The property type that this slot filler pretends to be when being searched for by a slot"
:items="slotTypes"
:value="model.slotFillerType"
:error-messages="errors.slotFillerType"
@change="change('slotFillerType', ...arguments)"
/>
<text-field
label="Quantity"
type="number"
min="0"
hint="How many properties this counts as when filling a slot"
:value="model.slotQuantityFilled"
:error-messages="errors.slotQuantityFilled"
@change="change('slotQuantityFilled', ...arguments)"
/>
<text-field
v-if="context.isLibraryForm"
label="Condition"
hint="A caclulation to determine if this can be added to the character"
placeholder="Always active"
:value="model.slotFillerCondition"
:error-messages="errors.slotFillerCondition"
@change="change('slotFillerCondition', ...arguments)"
/>
<smart-combobox
label="Tags"
multiple
chips
deletable-chips
hint="Used to let slots find this slot filler in a library"
:value="model.tags"
:error-messages="errors.tags"
@change="change('tags', ...arguments)"
/>
<form-section
v-if="$slots.children"
name="Children"
standalone
> >
<slot name="children" /> <slot />
</form-section> </form-sections>
</div> </div>
</template> </template>
<script lang="js"> <script lang="js">
import propertyFormMixin from '/imports/client/ui/properties/forms/shared/propertyFormMixin.js'; import propertyFormMixin from '/imports/client/ui/properties/forms/shared/propertyFormMixin.js';
import PROPERTIES from '/imports/constants/PROPERTIES.js';
export default { export default {
mixins: [propertyFormMixin], mixins: [propertyFormMixin],
inject: {
context: { default: {} }
},
data() {
let slotTypes = [];
for (let key in PROPERTIES) {
slotTypes.push({ text: PROPERTIES[key].name, value: key });
}
return { slotTypes };
},
}; };
</script> </script>

View File

@@ -1,155 +1,97 @@
<template lang="html"> <template lang="html">
<div class="slot-form"> <div class="slot-form">
<v-row <v-row dense>
v-if="model.type === 'class'" <v-col cols="12">
dense <smart-select
> label="Type"
<v-col clearable
cols="12" hint="What property type is needed to fill this slot"
md="6" placeholder="Any type"
> persistent-placeholder
<text-field :items="slotTypes"
ref="focusFirst" :value="model.slotType"
label="Name" :error-messages="errors.slotType"
:value="model.name" @change="change('slotType', ...arguments)"
:error-messages="errors.name" />
@change="change('name', ...arguments)" </v-col>
<v-col cols="12">
<tag-targeting
:model="model"
:errors="errors"
tag-field="slotTags"
tag-hint="Find library properties that have all of these tags"
or-hint="Also library properties that have all of these tags instead"
not-hint="Ignore library properties that have any of these tags"
@change="e => $emit('change', e)"
@push="e => $emit('push', e)"
@pull="e => $emit('pull', e)"
/> />
</v-col> </v-col>
<v-col <v-col
cols="12" cols="12"
md="6" md="6"
> >
<text-field <computed-field
label="Variable name" label="Quantity"
:value="model.variableName" hint="How many matching properties must be used to fill this slot"
hint="Use this name in calculations to reference this attribute" placeholder="unlimited"
:error-messages="errors.variableName" persistent-placeholder
@change="change('variableName', ...arguments)" :model="model.quantityExpected"
:error-messages="errors.quantityExpected"
@change="({path, value, ack}) =>
$emit('change', {path: ['quantityExpected', ...path], value, ack})"
/> />
</v-col> </v-col>
</v-row> <v-col
<text-field cols="12"
v-else md="6"
ref="focusFirst"
label="Name"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
<smart-select
v-if="model.type !== 'class'"
label="Type"
style="flex-basis: 300px;"
clearable
hint="What property type is needed to fill this slot"
:items="slotTypes"
:value="model.slotType"
:error-messages="errors.slotType"
@change="change('slotType', ...arguments)"
/>
<v-layout align-center>
<v-btn
icon
style="margin-top: -30px;"
class="mr-2"
:loading="addExtraTagsLoading"
:disabled="extraTagsFull"
@click="addExtraTags"
> >
<v-icon> <computed-field
mdi-plus label="Condition"
</v-icon> hint="A caclulation to determine if this slot should be active"
</v-btn> placeholder="Always active"
<smart-combobox persistent-placeholder
label="Tags Required" :model="model.slotCondition"
hint="The slot must be filled with a property which has all the listed tags" :error-messages="errors.slotCondition"
multiple @change="({path, value, ack}) =>
chips $emit('change', {path: ['slotCondition', ...path], value, ack})"
deletable-chips />
:value="model.slotTags" </v-col>
:error-messages="errors.slotTags" <v-col
@change="change('slotTags', ...arguments)" cols="12"
/> md="6"
</v-layout>
<v-slide-x-transition group>
<div
v-for="(extras, i) in model.extraTags"
:key="extras._id"
class="extra-tags layout align-center justify-space-between"
style="transition: all 0.3s !important;"
> >
<smart-select <smart-select
label="Operation" v-if="model.type !== 'class'"
style="width: 90px; flex-grow: 0;" label="Unique"
:items="extraTagOperations" style="flex-basis: 300px;"
:value="extras.operation" clearable
:error-messages="errors.extraTags && errors.extraTags[i]" hint="Do the properties that fill this slot need to be unique?"
@change="change(['extraTags', i, 'operation'], ...arguments)" placeholder="Allow duplicate values"
persistent-placeholder
:items="uniqueOptions"
:value="model.unique"
:error-messages="errors.unique"
@change="change('unique', ...arguments)"
/> />
<smart-combobox </v-col>
label="Tags" <v-col
:hint="extras.operation === 'OR' ? 'The slot can be filled with a property that has all of these tags instead' : 'The slot cannot be filled with a property that has any of these tags'" cols="12"
class="mx-2" md="6"
multiple
chips
deletable-chips
:value="extras.tags"
@change="change(['extraTags', i, 'tags'], ...arguments)"
/>
<v-btn
icon
style="margin-top: -30px;"
@click="$emit('pull', {path: ['extraTags', i]})"
>
<v-icon>mdi-delete</v-icon>
</v-btn>
</div>
</v-slide-x-transition>
<computed-field
label="Quantity"
hint="How many matching properties must be used to fill this slot, 0 is unlimited"
:model="model.quantityExpected"
:error-messages="errors.quantityExpected"
@change="({path, value, ack}) =>
$emit('change', {path: ['quantityExpected', ...path], value, ack})"
/>
<computed-field
label="Condition"
hint="A caclulation to determine if this slot should be active"
placeholder="Always active"
:model="model.slotCondition"
:error-messages="errors.slotCondition"
@change="({path, value, ack}) =>
$emit('change', {path: ['slotCondition', ...path], value, ack})"
/>
<smart-select
v-if="model.type !== 'class'"
label="Unique"
style="flex-basis: 300px;"
clearable
hint="Do the properties that fill this slot need to be unique?"
:items="uniqueOptions"
:value="model.unique"
:error-messages="errors.unique"
@change="change('unique', ...arguments)"
/>
<v-layout justify-center>
<v-btn
v-if="context.isLibraryForm"
color="accent"
class="ma-2 mb-4"
data-id="test-slot-button"
@click="testSlot"
> >
Test Slot <v-layout justify-center>
</v-btn> <v-btn
</v-layout> v-if="context.isLibraryForm"
color="accent"
class="ma-2 mb-4"
data-id="test-slot-button"
@click="testSlot"
>
Test Slot
</v-btn>
</v-layout>
</v-col>
</v-row>
<inline-computation-field <inline-computation-field
label="Description" label="Description"
:model="model.description" :model="model.description"
@@ -166,35 +108,37 @@
<slot name="children" /> <slot name="children" />
</form-section> </form-section>
<form-section name="Advanced"> <form-section name="Behavior">
<div class="layout wrap justify-space-between"> <v-row dense>
<smart-switch <v-col
label="Hide when full" cols="12"
style="width: 200px; flex-grow: 0;" md="6"
class="mx-2" >
:value="model.hideWhenFull" <smart-switch
:error-messages="errors.hideWhenFull" label="Hide when full"
@change="change('hideWhenFull', ...arguments)" style="width: 200px; flex-grow: 0;"
/> class="mx-2"
<smart-switch :value="model.hideWhenFull"
label="Ignored" :error-messages="errors.hideWhenFull"
style="width: 200px; flex-grow: 0;" @change="change('hideWhenFull', ...arguments)"
class="mx-2" />
:value="model.ignored" </v-col>
:error-messages="errors.ignored" <v-col
@change="change('ignored', ...arguments)" cols="12"
/> md="6"
</div> >
<smart-combobox <smart-switch
label="Tags" label="Ignored"
hint="This slot's own tags which will be used to fill other slots" style="width: 200px; flex-grow: 0;"
multiple class="mx-2"
chips :value="model.ignored"
deletable-chips :error-messages="errors.ignored"
:value="model.tags" @change="change('ignored', ...arguments)"
@change="change('tags', ...arguments)" />
/> </v-col>
</v-row>
</form-section> </form-section>
<slot />
</form-sections> </form-sections>
</div> </div>
</template> </template>
@@ -203,19 +147,17 @@
import propertyFormMixin from '/imports/client/ui/properties/forms/shared/propertyFormMixin.js'; import propertyFormMixin from '/imports/client/ui/properties/forms/shared/propertyFormMixin.js';
import FormSection from '/imports/client/ui/properties/forms/shared/FormSection.vue'; import FormSection from '/imports/client/ui/properties/forms/shared/FormSection.vue';
import PROPERTIES from '/imports/constants/PROPERTIES.js'; import PROPERTIES from '/imports/constants/PROPERTIES.js';
import { SlotSchema } from '/imports/api/properties/Slots.js'; import TagTargeting from '/imports/client/ui/properties/forms/shared/TagTargeting.vue';
export default { export default {
components: { components: {
FormSection, FormSection,
TagTargeting,
}, },
mixins: [propertyFormMixin], mixins: [propertyFormMixin],
inject: { inject: {
context: { default: {} } context: { default: {} }
}, },
props: {
classForm: Boolean,
},
data() { data() {
let slotTypes = []; let slotTypes = [];
for (let key in PROPERTIES) { for (let key in PROPERTIES) {
@@ -223,8 +165,6 @@ export default {
} }
return { return {
slotTypes, slotTypes,
addExtraTagsLoading: false,
extraTagOperations: ['OR', 'NOT'],
uniqueOptions: [{ uniqueOptions: [{
text: 'Each property inside this slot should be unique', text: 'Each property inside this slot should be unique',
value: 'uniqueInSlot', value: 'uniqueInSlot',
@@ -234,29 +174,7 @@ export default {
}], }],
}; };
}, },
computed: {
extraTagsFull() {
if (!this.model.extraTags) return false;
let maxCount = SlotSchema.get('extraTags', 'maxCount');
return this.model.extraTags.length >= maxCount;
}
},
methods: { methods: {
acknowledgeAddResult() {
this.addExtraTagsLoading = false;
},
addExtraTags() {
this.addExtraTagsLoading = true;
this.$emit('push', {
path: ['extraTags'],
value: {
_id: Random.id(),
operation: 'OR',
tags: [],
},
ack: this.acknowledgeAddResult,
});
},
testSlot() { testSlot() {
if (!this.context.isLibraryForm) return; if (!this.context.isLibraryForm) return;
this.$store.commit('pushDialogStack', { this.$store.commit('pushDialogStack', {

View File

@@ -1,17 +1,5 @@
<template lang="html"> <template lang="html">
<div class="spell-form"> <div class="spell-form">
<v-row
justify="center"
class="mb-3"
>
<v-col cols="12">
<icon-color-menu
:model="model"
:errors="errors"
@change="e => $emit('change', e)"
/>
</v-col>
</v-row>
<v-row dense> <v-row dense>
<v-col <v-col
cols="12" cols="12"
@@ -19,6 +7,7 @@
md="4" md="4"
> >
<smart-switch <smart-switch
class="ml-2"
label="Always prepared" label="Always prepared"
:value="model.alwaysPrepared" :value="model.alwaysPrepared"
:error-messages="errors.alwaysPrepared" :error-messages="errors.alwaysPrepared"
@@ -32,6 +21,7 @@
md="4" md="4"
> >
<smart-switch <smart-switch
class="ml-2"
label="Prepared" label="Prepared"
:value="model.prepared" :value="model.prepared"
:error-messages="errors.prepared" :error-messages="errors.prepared"
@@ -45,6 +35,7 @@
md="4" md="4"
> >
<smart-switch <smart-switch
class="ml-2"
label="Cast without spell slots" label="Cast without spell slots"
:value="model.castWithoutSpellSlots" :value="model.castWithoutSpellSlots"
:error-messages="errors.castWithoutSpellSlots" :error-messages="errors.castWithoutSpellSlots"
@@ -53,18 +44,6 @@
</v-col> </v-col>
</v-row> </v-row>
<v-row dense> <v-row dense>
<v-col
cols="12"
md="6"
>
<text-field
ref="focusFirst"
label="Name"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
</v-col>
<v-col <v-col
cols="12" cols="12"
md="6" md="6"
@@ -189,12 +168,15 @@
cols="12" cols="12"
md="6" md="6"
> >
<smart-select <smart-toggle
label="Target" label="Target creature"
:items="targetOptions"
:value="model.target" :value="model.target"
:options="[
{name: 'Single Target', value: 'singleTarget'},
{name: 'Multiple Targets', value: 'multipleTargets'},
{name: 'Self', value: 'self'},
]"
:error-messages="errors.target" :error-messages="errors.target"
:menu-props="{auto: true, lazy: true}"
@change="change('target', ...arguments)" @change="change('target', ...arguments)"
/> />
</v-col> </v-col>
@@ -205,6 +187,7 @@
<v-slide-x-transition mode="out-in"> <v-slide-x-transition mode="out-in">
<v-switch <v-switch
v-if="!isAttack" v-if="!isAttack"
class="ml-4"
label="Attack roll" label="Attack roll"
:value="attackSwitch" :value="attackSwitch"
@change="e => attackSwitch = e" @change="e => attackSwitch = e"
@@ -218,7 +201,18 @@
:error-messages="errors.attackRoll" :error-messages="errors.attackRoll"
@change="({path, value, ack}) => @change="({path, value, ack}) =>
$emit('change', {path: ['attackRoll', ...path], value, ack})" $emit('change', {path: ['attackRoll', ...path], value, ack})"
/> >
<template #prepend>
<v-btn
:disabled="!!(model.attackRoll && model.attackRoll.calculation)"
icon
style="margin-top: -12px;"
@click="attackSwitch = false"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</template>
</computed-field>
</v-slide-x-transition> </v-slide-x-transition>
</v-col> </v-col>
</v-row> </v-row>
@@ -285,25 +279,7 @@
@change="change('reset', ...arguments)" @change="change('reset', ...arguments)"
/> />
</form-section> </form-section>
<slot />
<form-section
v-if="$slots.children"
name="Children"
>
<slot name="children" />
</form-section>
<form-section name="Advanced">
<smart-combobox
label="Tags"
multiple
chips
deletable-chips
hint="Used to let slots find this property in a library, should otherwise be left blank"
:value="model.tags"
@change="change('tags', ...arguments)"
/>
</form-section>
</form-sections> </form-sections>
</div> </div>
</template> </template>
@@ -311,7 +287,6 @@
<script lang="js"> <script lang="js">
import FormSection, { FormSections } from '/imports/client/ui/properties/forms/shared/FormSection.vue'; import FormSection, { FormSections } from '/imports/client/ui/properties/forms/shared/FormSection.vue';
import propertyFormMixin from '/imports/client/ui/properties/forms/shared/propertyFormMixin.js'; import propertyFormMixin from '/imports/client/ui/properties/forms/shared/propertyFormMixin.js';
import IconColorMenu from '/imports/client/ui/properties/forms/shared/IconColorMenu.vue';
import ResourcesForm from '/imports/client/ui/properties/forms/ResourcesForm.vue'; import ResourcesForm from '/imports/client/ui/properties/forms/ResourcesForm.vue';
import ResetSelector from '/imports/client/ui/components/ResetSelector.vue'; import ResetSelector from '/imports/client/ui/components/ResetSelector.vue';
@@ -319,7 +294,6 @@ export default {
components: { components: {
FormSections, FormSections,
FormSection, FormSection,
IconColorMenu,
ResourcesForm, ResourcesForm,
ResetSelector, ResetSelector,
}, },
@@ -386,18 +360,6 @@ export default {
value: 9, value: 9,
}, },
], ],
targetOptions: [
{
text: 'Self',
value: 'self',
}, {
text: 'Single target',
value: 'singleTarget',
}, {
text: 'Multiple targets',
value: 'multipleTargets',
},
],
attackSwitch: false, attackSwitch: false,
}; };
}, },

View File

@@ -1,14 +1,59 @@
<template lang="html"> <template lang="html">
<div class="attribute-form"> <div class="spell-list-form">
<div class="layout wrap"> <v-row dense>
<text-field <v-col
ref="focusFirst" cols="12"
label="Name" md="6"
:value="model.name" >
:error-messages="errors.name" <computed-field
@change="change('name', ...arguments)" label="Maximum prepared spells"
/> hint="How many spells can be prepared"
</div> :model="model.maxPrepared"
:error-messages="errors.maxPrepared"
@change="({path, value, ack}) =>
$emit('change', {path: ['maxPrepared', ...path], value, ack})"
/>
</v-col>
<v-col
cols="12"
md="6"
>
<smart-combobox
label="Spellcasting ability"
:value="model.ability"
hint="Which ability is used to cast spells in this spell list"
:items="abilityScoreList"
:error-messages="errors.ability"
@change="changeAbility"
/>
</v-col>
<v-col
cols="12"
md="6"
>
<computed-field
label="Spell save DC"
hint="The spell save DC of spells in this list"
:model="model.dc"
:error-messages="errors.dc"
@change="({path, value, ack}) =>
$emit('change', {path: ['dc', ...path], value, ack})"
/>
</v-col>
<v-col
cols="12"
md="6"
>
<computed-field
label="Attack roll bonus"
hint="The attack roll bonus of spell attacks made by spells in this list"
:model="model.attackRollBonus"
:error-messages="errors.attackRollBonus"
@change="({path, value, ack}) =>
$emit('change', {path: ['attackRollBonus', ...path], value, ack})"
/>
</v-col>
</v-row>
<inline-computation-field <inline-computation-field
label="Description" label="Description"
@@ -18,59 +63,11 @@
$emit('change', {path: ['description', ...path], value, ack})" $emit('change', {path: ['description', ...path], value, ack})"
/> />
<computed-field <form-sections
label="Maximum prepared spells" v-if="$slots.default"
hint="How many spells can be prepared"
:model="model.maxPrepared"
:error-messages="errors.maxPrepared"
@change="({path, value, ack}) =>
$emit('change', {path: ['maxPrepared', ...path], value, ack})"
/>
<smart-combobox
label="Spellcasting ability"
:value="model.ability"
hint="Which ability is used to cast spells in this spell list"
:items="abilityScoreList"
:error-messages="errors.ability"
@change="changeAbility"
/>
<computed-field
label="Spell save DC"
hint="The spell save DC of spells in this list"
:model="model.dc"
:error-messages="errors.dc"
@change="({path, value, ack}) =>
$emit('change', {path: ['dc', ...path], value, ack})"
/>
<computed-field
label="Attack roll bonus"
hint="The attack roll bonus of spell attacks made by spells in this list"
:model="model.attackRollBonus"
:error-messages="errors.attackRollBonus"
@change="({path, value, ack}) =>
$emit('change', {path: ['attackRollBonus', ...path], value, ack})"
/>
<smart-combobox
label="Tags"
multiple
chips
deletable-chips
hint="Used to let slots find this property in a library, should otherwise be left blank"
:value="model.tags"
@change="change('tags', ...arguments)"
/>
<form-section
v-if="$slots.children"
name="Children"
standalone
> >
<slot name="children" /> <slot />
</form-section> </form-sections>
</div> </div>
</template> </template>
@@ -95,8 +92,9 @@ export default {
const attackRollBonus = this.model.attackRollBonus?.calculation; const attackRollBonus = this.model.attackRollBonus?.calculation;
if ( if (
!attackRollBonus || value &&
attackRollBonus === `proficiencyBonus + ${oldValue}.modifier` (!attackRollBonus ||
attackRollBonus === `proficiencyBonus + ${oldValue}.modifier`)
) { ) {
this.$emit('change', { this.$emit('change', {
path: ['attackRollBonus', 'calculation'], path: ['attackRollBonus', 'calculation'],
@@ -106,8 +104,9 @@ export default {
const dc = this.model.dc?.calculation; const dc = this.model.dc?.calculation;
if ( if (
!dc || value &&
dc === `8 + proficiencyBonus + ${oldValue}.modifier` (!dc ||
dc === `8 + proficiencyBonus + ${oldValue}.modifier`)
) { ) {
this.$emit('change', { this.$emit('change', {
path: ['dc', 'calculation'], path: ['dc', 'calculation'],
@@ -118,6 +117,3 @@ export default {
} }
}; };
</script> </script>
<style lang="css" scoped>
</style>

View File

@@ -1,18 +1,6 @@
<template lang="html"> <template lang="html">
<div class="feature-form"> <div class="toggle-form">
<v-row dense> <v-row dense>
<v-col
cols="12"
md="6"
>
<text-field
ref="focusFirst"
label="Name"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
</v-col>
<v-col <v-col
cols="12" cols="12"
md="6" md="6"
@@ -25,71 +13,57 @@
@change="change('variableName', ...arguments)" @change="change('variableName', ...arguments)"
/> />
</v-col> </v-col>
<v-col <v-col
cols="12" cols="12"
md="6" md="6"
> >
<smart-checkbox <smart-toggle
label="Show on character sheet" label="Active"
:value="model.showUI" :value="radioSelection"
:error-messages="errors.showUI" :options="[
@change="change('showUI', ...arguments)" {name: 'Enabled', value: 'enabled'},
{name: 'Disabled', value: 'disabled'},
{name: 'Calculated', value: 'calculated'},
]"
:error-messages="errors.enabled"
@change="radioChange"
/> />
</v-col> </v-col>
<v-expand-transition>
<v-col <v-col
cols="12" v-show="radioSelection === 'calculated'"
md="6" cols="12"
> >
<v-layout column> <computed-field
<v-radio-group label="Condition"
:value="radioSelection" hint="When this calculation returns a value that isn't false or zero the children will be active"
@change="radioChange" :model="model.condition"
> :error-messages="errors.condition"
<v-radio @change="({path, value, ack}) =>
value="enabled" $emit('change', {path: ['condition', ...path], value, ack})"
label="Enabled" />
/> </v-col>
<v-radio </v-expand-transition>
value="disabled"
label="Disabled"
/>
<v-radio
value="calculated"
label="Calculated"
/>
</v-radio-group>
</v-layout>
</v-col>
</v-row> </v-row>
<v-fade-transition>
<computed-field
v-show="radioSelection === 'calculated'"
label="Condition"
hint="When this calculation returns a value that isn't false or zero the children will be active"
:model="model.condition"
:error-messages="errors.condition"
@change="({path, value, ack}) =>
$emit('change', {path: ['condition', ...path], value, ack})"
/>
</v-fade-transition>
<smart-combobox
label="Tags"
multiple
chips
deletable-chips
hint="Used to let slots find this property in a library, should otherwise be left blank"
:value="model.tags"
@change="change('tags', ...arguments)"
/>
<form-section <form-sections>
v-if="$slots.children" <form-section name="Behavior">
name="Children" <v-col
standalone cols="12"
> md="6"
<slot name="children" /> >
</form-section> <smart-switch
class="ml-2"
label="Show on character sheet"
:value="model.showUI"
:error-messages="errors.showUI"
@change="change('showUI', ...arguments)"
/>
</v-col>
</form-section>
<slot />
</form-sections>
</div> </div>
</template> </template>
@@ -110,16 +84,16 @@ export default {
} }
}, },
methods: { methods: {
radioChange(value) { radioChange(value, ack) {
if (value === 'enabled') { if (value === 'enabled') {
this.$emit('change', { path: ['enabled'], value: true }); this.$emit('change', { path: ['enabled'], value: true, ack });
this.$emit('change', { path: ['disabled'], value: false }); this.$emit('change', { path: ['disabled'], value: false, ack });
} else if (value === 'disabled') { } else if (value === 'disabled') {
this.$emit('change', { path: ['disabled'], value: true }); this.$emit('change', { path: ['disabled'], value: true, ack });
this.$emit('change', { path: ['enabled'], value: false }); this.$emit('change', { path: ['enabled'], value: false, ack });
} else if (value === 'calculated') { } else if (value === 'calculated') {
this.$emit('change', { path: ['disabled'], value: false }); this.$emit('change', { path: ['disabled'], value: false, ack });
this.$emit('change', { path: ['enabled'], value: false }); this.$emit('change', { path: ['enabled'], value: false, ack });
} }
} }
} }

View File

@@ -1,117 +1,79 @@
<template lang="html"> <template lang="html">
<div class="trigger-form"> <div class="trigger-form">
<text-field <v-row dense>
ref="focusFirst" <v-col
label="Name" cols="12"
:value="model.name" md="6"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
<smart-select
label="Timing"
style="flex-basis: 300px;"
hint="When this trigger will fire"
:items="timingOptions"
:value="model.timing"
:error-messages="errors.timing"
@change="change('timing', ...arguments)"
/>
<smart-select
label="Event"
style="flex-basis: 300px;"
hint="What causes this trigger to fire"
:items="eventOptions"
:value="model.event"
:error-messages="errors.event"
@change="change('event', ...arguments)"
/>
<smart-select
v-if="model.event === 'doActionProperty' || model.event === 'receiveActionProperty'"
label="Event Type"
style="flex-basis: 300px;"
hint="Which action event causes this trigger to fire"
:items="actionPropertyTypeOptions"
:value="model.actionPropertyType"
:error-messages="errors.actionPropertyType"
@change="change('actionPropertyType', ...arguments)"
/>
<v-layout
v-show="showTags"
align-center
>
<v-btn
icon
style="margin-top: -30px;"
class="mr-2"
:loading="addExtraTagsLoading"
:disabled="extraTagsFull"
@click="addExtraTags"
>
<v-icon>
mdi-plus
</v-icon>
</v-btn>
<smart-combobox
label="Tags Required"
hint="The trigger will be fired by a property which has all the listed tags"
multiple
chips
deletable-chips
:value="model.targetTags"
:error-messages="errors.targetTags"
@change="change('targetTags', ...arguments)"
/>
</v-layout>
<v-slide-x-transition
v-show="showTags"
group
>
<div
v-for="(extras, i) in model.extraTags"
:key="extras._id"
class="extra-tags layout align-center justify-space-between"
> >
<smart-select <smart-select
label="Operation" label="Timing"
style="width: 90px; flex-grow: 0;" style="flex-basis: 300px;"
:items="extraTagOperations" hint="When this trigger will fire"
:value="extras.operation" :items="timingOptions"
:error-messages="errors.extraTags && errors.extraTags[i]" :value="model.timing"
@change="change(['extraTags', i, 'operation'], ...arguments)" :error-messages="errors.timing"
@change="change('timing', ...arguments)"
/> />
<smart-combobox </v-col>
label="Tags" <v-col
:hint="extras.operation === 'OR' ? 'The trigger can be fired by a property that has all of these tags instead' : 'The trigger won\'t be fired by a property that has any of these tags'" cols="12"
class="mx-2" md="6"
multiple >
chips <smart-select
deletable-chips label="Event"
:value="extras.tags" style="flex-basis: 300px;"
@change="change(['extraTags', i, 'tags'], ...arguments)" hint="What causes this trigger to fire"
:items="eventOptions"
:value="model.event"
:error-messages="errors.event"
@change="change('event', ...arguments)"
/> />
<v-btn </v-col>
icon <v-col
style="margin-top: -30px;" cols="12"
@click="$emit('pull', {path: ['extraTags', i]})" md="6"
>
<computed-field
label="Condition"
hint="A calculation to determine if this trigger should fire"
placeholder="Always active"
persistent-placeholder
:model="model.condition"
:error-messages="errors.condition"
@change="({path, value, ack}) =>
$emit('change', {path: ['condition', ...path], value, ack})"
/>
</v-col>
<v-expand-transition>
<v-col
v-if="model.event === 'doActionProperty' || model.event === 'receiveActionProperty'"
cols="12"
md="6"
> >
<v-icon>mdi-delete</v-icon> <smart-select
</v-btn> label="Event Type"
</div> style="flex-basis: 300px;"
</v-slide-x-transition> hint="Which action event causes this trigger to fire"
:items="actionPropertyTypeOptions"
<computed-field :value="model.actionPropertyType"
label="Condition" :error-messages="errors.actionPropertyType"
hint="A caclulation to determine if this trigger should fire" @change="change('actionPropertyType', ...arguments)"
placeholder="Always active" />
:model="model.condition" </v-col>
:error-messages="errors.condition" </v-expand-transition>
@change="({path, value, ack}) => <v-col cols="12">
$emit('change', {path: ['condition', ...path], value, ack})" <tag-targeting
/> :model="model"
:errors="errors"
@change="e => $emit('change', e)"
@push="e => $emit('push', e)"
@pull="e => $emit('pull', e)"
/>
</v-col>
</v-row>
<inline-computation-field <inline-computation-field
class="mt-6"
label="Description" label="Description"
hint="The rest of the description that doesn't fit in the summary goes here" hint="The rest of the description that doesn't fit in the summary goes here"
:model="model.description" :model="model.description"
@@ -122,24 +84,8 @@
<form-sections> <form-sections>
<form-section <form-section
v-if="$slots.children" name="Log"
name="Children"
> >
<slot name="children" />
</form-section>
<form-section
name="Advanced"
>
<smart-combobox
label="Tags"
hint="This trigger's own tags"
multiple
chips
deletable-chips
:value="model.tags"
@change="change('tags', ...arguments)"
/>
<smart-switch <smart-switch
label="Don't show in log" label="Don't show in log"
:value="model.silent" :value="model.silent"
@@ -147,6 +93,7 @@
@change="change('silent', ...arguments)" @change="change('silent', ...arguments)"
/> />
</form-section> </form-section>
<slot />
</form-sections> </form-sections>
</div> </div>
</template> </template>
@@ -157,10 +104,12 @@ import FormSection from '/imports/client/ui/properties/forms/shared/FormSection.
import { import {
TriggerSchema, eventOptions, timingOptions, actionPropertyTypeOptions TriggerSchema, eventOptions, timingOptions, actionPropertyTypeOptions
} from '/imports/api/properties/Triggers.js'; } from '/imports/api/properties/Triggers.js';
import TagTargeting from '/imports/client/ui/properties/forms/shared/TagTargeting.vue';
export default { export default {
components: { components: {
FormSection, FormSection,
TagTargeting,
}, },
mixins: [propertyFormMixin], mixins: [propertyFormMixin],
inject: { inject: {