Improved usability and UI for Features. Fixed embedded computations

This commit is contained in:
Thaum Rystra
2020-05-02 17:54:22 +02:00
parent d649fb9d54
commit 48e54c42b4
12 changed files with 157 additions and 93 deletions

View File

@@ -0,0 +1,11 @@
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
// Strings can have computations in bracers like so: {computation}
export default function evalutateStringWithEmbeddedCalculations(string, scope){
if (!string) return string;
// Compute everything inside bracers
return string.replace(/\{([^{}]*)\}/g, function(match, p1){
let {result} = evaluateString(p1, scope);
return result;
});
}

View File

@@ -68,6 +68,6 @@ export function recomputeCreatureById(creatureId){
computeMemo(computationMemo);
writeAlteredProperties(computationMemo);
writeCreatureVariables(computationMemo, creatureId);
if(Meteor.isClient) console.log(computationMemo);
// if(Meteor.isClient) console.log(computationMemo);
return computationMemo;
}

View File

@@ -4,7 +4,11 @@ let FeatureSchema = new SimpleSchema({
name: {
type: String,
},
description: {
summary: {
type: String,
optional: true,
},
description: {
type: String,
optional: true,
},

View File

@@ -2,13 +2,19 @@
lang="html"
functional
>
<div class="column-layout">
<div
class="column-layout"
:class="wideColumns ? 'wide-columns' : ''"
>
<slot />
</div>
</template>
<script>
export default {
props: {
wideColumns: Boolean,
},
};
</script>
@@ -21,6 +27,14 @@ export default {
transform: translateZ(0);
padding: 4px;
}
.column-layout.wide-columns {
column-count: 12;
column-fill: balance;
column-gap: 0;
column-width: 320px;
transform: translateZ(0);
padding: 4px;
}
.column-layout >>> > div {
-webkit-backface-visibility: hidden;
-webkit-transform: translateX(0);

View File

@@ -1,5 +1,10 @@
<template lang="html">
<markdown-text
v-if="embedded"
:markdown="computedValue"
/>
<div
v-else
class="computed"
:class="{
'symbols-are-errors': expectNumber && scope,
@@ -11,9 +16,14 @@
<script>
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
import evalutateStringWithEmbeddedCalculations from '/imports/api/creature/computation/afterComputation/evalutateStringWithEmbeddedCalculations.js';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
export default {
components: {
MarkdownText,
},
props: {
value: {
type: String,
@@ -30,6 +40,9 @@ export default {
signed: {
type: Boolean
},
embedded: {
type: Boolean,
},
},
data(){return {
errors: false,
@@ -49,12 +62,17 @@ export default {
methods: {
recalculate(){
if (!this.value) return;
let {result, errors} = evaluateString(this.value, this.scope);
if (this.signed){
result = numberToSignedString(result);
if (this.embedded){
let result = evalutateStringWithEmbeddedCalculations(this.value, this.scope);
this.computedValue = result;
} else {
let {result, errors} = evaluateString(this.value, this.scope);
if (this.signed){
result = numberToSignedString(result);
}
this.computedValue = result;
this.errors = errors;
}
this.computedValue = result;
this.errors = errors;
}
}
}

View File

@@ -1,46 +1,44 @@
<template lang="html">
<div class="features">
<column-layout>
<div v-for="feature in features" :key="feature._id">
<feature-card
v-bind="feature"
:data-id="feature._id"
@click="featureClicked(feature)"
/>
</div>
</column-layout>
</div>
<div class="features">
<column-layout wide-columns>
<div
v-for="feature in features"
:key="feature._id"
>
<feature-card
:model="feature"
:data-id="feature._id"
@click="featureClicked(feature)"
/>
</div>
</column-layout>
</div>
</template>
<script>
import Creatures from '/imports/api/creature/Creatures.js';
import CreatureProperties from '/imports/api/creature/CreatureProperties.js';
import ColumnLayout from '/imports/ui/components/ColumnLayout.vue';
import FeatureCard from '/imports/ui/properties/components/features/FeatureCard.vue';
import { evaluateComputation, evaluateStringWithVariables } from '/imports/ui/utility/evaluate.js';
export default {
props: {
creatureId: String,
},
components: {
ColumnLayout,
FeatureCard,
},
props: {
creatureId: {
type: String,
required: true,
},
},
meteor: {
features(){
let char = Creatures.findOne(this.creatureId, {fields: {variables: 1}});
if (!char) return [];
let vars = char.variables;
return CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'feature',
removed: {$ne: true},
}, {
sort: {order: 1},
}).map(f => {
f.description = evaluateStringWithVariables(f.description, vars);
return f;
});
},
},

View File

@@ -1,22 +1,31 @@
<template lang="html">
<div class="inventory">
<column-layout>
<div>
<v-card hover @click="showCharacterForm" data-id="creature-summary">
<v-card-title class="title">
{{creature.name}}
</v-card-title>
<v-card-text>
{{creature.alignment}}<br/>
{{creature.gender}}
</v-card-text>
</v-card>
</div>
<div v-for="note in notes">
<note-card :model="note" :key="note._id"/>
</div>
</column-layout>
</div>
<div class="inventory">
<column-layout wide-columns>
<div>
<v-card
hover
data-id="creature-summary"
@click="showCharacterForm"
>
<v-card-title class="title">
{{ creature.name }}
</v-card-title>
<v-card-text>
{{ creature.alignment }}<br>
{{ creature.gender }}
</v-card-text>
</v-card>
</div>
<div
v-for="note in notes"
:key="note._id"
>
<note-card
:model="note"
/>
</div>
</column-layout>
</div>
</template>
<script>
@@ -26,13 +35,13 @@ import ColumnLayout from '/imports/ui/components/ColumnLayout.vue';
import NoteCard from '/imports/ui/properties/components/persona/NoteCard.vue';
export default {
props: {
creatureId: String,
},
components: {
ColumnLayout,
NoteCard,
},
props: {
creatureId: String,
},
meteor: {
notes(){
return CreatureProperties.find({

View File

@@ -1,31 +1,38 @@
<template lang="html">
<toolbar-card :color="color" @click="$emit('click')" :id="_id">
<template slot="toolbar">
<span>
{{name}}
</span>
<v-spacer/>
</template>
<v-card-text v-if="description">
<markdown-text :markdown="description"/>
</v-card-text>
<toolbar-card
:id="model._id"
:color="model.color"
@click="$emit('click')"
>
<template slot="toolbar">
<span>
{{ model.name }}
</span>
<v-spacer />
</template>
<v-card-text v-if="model.summary">
<computed
embedded
:value="model.summary"
/>
</v-card-text>
</toolbar-card>
</template>
<script>
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
import ToolbarCard from '/imports/ui/components/ToolbarCard.vue';
import ComputedForCreature from '/imports/ui/components/computation/ComputedForCreature.vue';
export default {
props: {
_id: String,
name: String,
description: String,
color: String,
},
components: {
MarkdownText,
ToolbarCard,
Computed: ComputedForCreature,
},
props: {
model: {
type: Object,
required: true,
},
},
};
</script>

View File

@@ -7,18 +7,17 @@
:debounce-time="debounceTime"
@change="(value, ack) => $emit('change', {path: ['name'], value, ack})"
/>
<!--
<smart-select
label="Enabled"
:items="enabledOptions"
:value="enabledStatus"
:error-messages="errors.enabled || errors.alwaysEnabled"
:menu-props="{auto: true, lazy: true}"
@change="changeEnabled"
:debounce-time="debounceTime"
/>-->
<text-area
label="Summary"
hint="This will appear in the feature card in the character sheet"
:value="model.summary"
:error-messages="errors.summary"
:debounce-time="debounceTime"
@change="(value, ack) => $emit('change', {path: ['summary'], value, ack})"
/>
<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"
:debounce-time="debounceTime"

View File

@@ -1,11 +1,10 @@
<template lang="html">
<div class="feature-viewer">
<property-name :value="model.name"/>
<div v-if="model.alwaysEnabled" class="caption">
Always enabled
</div>
<property-description :value="model.description"/>
</div>
<div class="feature-viewer">
<property-name :value="model.name" />
<property-description :value="model.summary" />
<v-divider class="mt-3 mb-3" />
<property-description :value="model.description" />
</div>
</template>
<script>

View File

@@ -1,18 +1,20 @@
<template lang="html">
<div>
<markdown-text v-if="value" :markdown="value"/>
</div>
<computed
class="property-description"
embedded
:value="value"
/>
</template>
<script>
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
import ComputedForCreature from '/imports/ui/components/computation/ComputedForCreature.vue';
export default {
components: {
Computed: ComputedForCreature,
},
props: {
value: String,
},
components: {
MarkdownText,
},
}
</script>

View File

@@ -3,6 +3,7 @@ import Creatures from '/imports/api/creature/Creatures.js';
// Computations resolve to numbers
// vars is a dict of variables to substitute
export function evaluateComputation(string, vars){
console.warn('Deprecated, evaluate computation should be done by the computation engine')
if (!string) return string;
// Replace all the string variables with numbers if possible
let substitutedString = string.replace(
@@ -21,6 +22,7 @@ export function evaluateComputation(string, vars){
// Strings can have computations in bracers like so: {computation}
// vars is a dict of variables to substitute
export function evaluateStringWithVariables(string, vars){
console.warn('Deprecated, evaluateStringWithVariables should be done by the computation engine')
if (!string) return string;
// Compute everything inside bracers
return string.replace(/\{([^\{\}]*)\}/g, function(match, p1){
@@ -29,6 +31,7 @@ export function evaluateStringWithVariables(string, vars){
}
export function evaluateStringForCharId(string, charId){
console.warn('Deprecated, evaluateStringForCharId should be done by the computation engine')
let char = Creatures.findOne(charId, {fields: {variables: 1}});
let vars = char ? char.variables : {};
return evaluateStringWithVariables(string, vars);