Added simple feature UI components and insertion dialog

This commit is contained in:
Stefan Zermatten
2019-02-25 15:38:57 +02:00
parent e5ff116208
commit b7a4a3d3fa
23 changed files with 579 additions and 93 deletions

View File

@@ -9,16 +9,15 @@
@change="change"
:debounce-time="0"
/>
<div slot="actions">
<v-spacer/>
<v-btn
flat
:disabled="!valid"
@click="$store.dispatch('popDialogStack', attribute)"
>
Insert Attribute
</v-btn>
</div>
<v-spacer slot="actions"/>
<v-btn
flat
slot="actions"
:disabled="!valid"
@click="$store.dispatch('popDialogStack', attribute)"
>
Insert Attribute
</v-btn>
</dialog-base>
</template>
@@ -26,7 +25,6 @@
import AttributeEdit from '/imports/ui/components/AttributeEdit.vue';
import Attributes from '/imports/api/creature/properties/Attributes.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import { Tracker } from 'meteor/tracker';
export default {
components: {

View File

@@ -49,7 +49,6 @@
/>
<smart-select
label="Reset"
append-icon="arrow_drop_down"
clearable
:items="resetOptions"
:value="attribute.reset"

View File

@@ -0,0 +1,51 @@
<template lang="html">
<column-layout>
<div
v-for="(feature, index) in features"
:key="index"
>
<feature-card
v-bind="feature"
/>
</div>
</column-layout>
</template>
<script>
import ColumnLayout from '/imports/ui/components/ColumnLayout.vue';
import FeatureCard from '/imports/ui/components/FeatureCard.vue';
export default {
dontWrap: true,
components: {
ColumnLayout,
FeatureCard,
},
data(){return {
features: [
{
name: 'Feature 1',
enabled: true,
alwaysEnabled: true,
description: `
blah blah, with
spacing
`,
color: '#f44336',
}, {
name: 'Feature 2',
enabled: false,
alwaysEnabled: false,
description: `Short Description`,
uses: 5,
used: 2,
},
],
}},
}
</script>
<style lang="css' scoped>
</style>

View File

@@ -0,0 +1,60 @@
<template lang="html">
<toolbar-card :color="color" @click="$emit('click')">
<span slot="toolbar">
{{name}}
</span>
<v-spacer slot="toolbar"/>
<v-checkbox
hide-details
class="shrink"
v-if="!alwaysEnabled"
:value="enabled"
@change="enabled => $emit('change', {enabled})"
slot="toolbar"
/>
<v-card-text>
{{description}}
</v-card-text>
<v-card-actions v-if="uses">
<v-spacer/>
<v-btn
flat
:disabled="uses - used <= 0"
@click="$emit('used')"
>
Use
</v-btn>
<v-btn
flat
:disabled="!used"
@click="$emit('reset')"
>
Reset
</v-btn>
</v-card-actions>
</toolbar-card>
</template>
<script>
import ToolbarCard from '/imports/ui/components/ToolbarCard.vue';
export default {
props: {
charId: String,
name: String,
description: String,
uses: Number,
used: Number,
reset: String,
color: String,
enabled: Boolean,
alwaysEnabled: Boolean,
},
components: {
ToolbarCard,
},
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,78 @@
<template lang="html">
<dialog-base>
<div slot="toolbar">
New Feature
</div>
<feature-edit
:feature="feature"
:errors="errors"
@change="change"
:debounce-time="0"
/>
<v-spacer slot="actions"/>
<v-btn
flat
slot="actions"
:disabled="!valid"
@click="$store.dispatch('popDialogStack', feature)"
>
Insert Feature
</v-btn>
</dialog-base>
</template>
<script>
import FeatureEdit from '/imports/ui/components/FeatureEdit.vue';
import Features from '/imports/api/creature/properties/Features.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
export default {
components: {
FeatureEdit,
DialogBase,
},
data(){ return {
feature: {
name: 'New Feature',
description: null,
uses: null,
used: 0,
reset: null,
enabled: true,
alwaysEnabled: true,
color: '#9E9E9E',
},
valid: true,
}},
methods: {
change(update, ack){
for (key in update){
this.feature[key] = update[key];
}
if (ack) ack();
},
},
created(){
this.validationContext = Features.simpleSchema().newContext();
},
computed: {
errors(){
this.valid = true;
let cleanAtt = this.validationContext.clean(this.feature)
this.validationContext.validate(cleanAtt, {keys: [
'name', 'description', 'uses', 'used', 'reset', 'enabled',
'alwaysEnabled', 'color',
]});
let errors = {};
this.validationContext.validationErrors().forEach(error => {
if (this.valid) this.valid = false;
errors[error.name] = Features.simpleSchema().messageForError(error);
});
return errors;
},
},
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,113 @@
<template lang="html">
<div>
<text-field
label="Name"
:value="feature.name"
@change="(name, ack) => $emit('change', {name}, ack)"
:error-messages="errors.name"
:debounce-time="debounceTime"
/>
<text-field
label="Used"
type="number"
:value="feature.used"
@change="(used, ack) => $emit('change', {used}, ack)"
:error-messages="errors.used"
:debounce-time="debounceTime"
/>
<text-field
label="Uses"
:value="feature.uses"
@change="(uses, ack) => $emit('change', {uses}, ack)"
:error-messages="errors.uses"
:debounce-time="debounceTime"
/>
<smart-select
label="Reset"
clearable
:items="resetOptions"
:value="feature.reset"
:error-messages="errors.reset"
:menu-props="{auto: true, lazy: true}"
@change="(reset, ack) => $emit('change', {reset}, ack)"
:debounce-time="debounceTime"
/>
<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="Description"
:value="feature.description"
:error-messages="errors.description"
@change="(description, ack) => $emit('change', {description}, ack)"
:debounce-time="debounceTime"
/>
</div>
</template>
<script>
export default {
props: {
feature: {
type: Object,
default: () => ({}),
},
errors: {
type: Object,
default: () => ({}),
},
debounceTime: Number,
},
data(){ return{
resetOptions: [
{
text: 'Short rest',
value: 'shortRest',
}, {
text: 'Long rest',
value: 'longRest',
}
],
enabledOptions: [
{
text: 'Always enabled',
value: 'always',
}, {
text: 'Enabled',
value: 'enabled',
}, {
text: 'Disabled',
value: 'disabled',
}
],
}},
computed: {
enabledStatus(){
if (!this.feature) return;
if (this.feature.alwaysEnabled) return 'always';
if (this.feature.enabled) return 'enabled';
return 'disabled';
},
},
methods: {
changeEnabled(value, ack){
if (value === 'always'){
this.$emit('change', {enabled: true, alwaysEnabled: true}, ack);
} else if (value === 'enabled'){
this.$emit('change', {enabled: true, alwaysEnabled: false}, ack);
} else if (value === 'disabled'){
this.$emit('change', {enabled: false, alwaysEnabled: false}, ack);
}
}
}
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,38 @@
<template lang="html">
<v-card>
<v-toolbar
flat
style="transform: none;"
@click="$emit('click')"
:color="color"
:dark="isDark"
>
<slot name="toolbar"/>
</v-toolbar>
<div>
<slot/>
</div>
</v-card>
</template>
<script>
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
export default {
props: {
color: {
type: String,
default(){
return this.$vuetify.theme.secondary;
},
},
},
computed: {
isDark(){
return isDarkColor(this.color);
}
}
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -4,6 +4,7 @@
:loading="loading"
:error-messages="errors"
:value="safeValue"
:auto-grow="autoGrow"
@input="input"
@focus="focused = true"
@blur="focused = false"
@@ -15,5 +16,11 @@
export default {
mixins: [SmartInput],
props: {
autoGrow: {
type: Boolean,
default: true,
},
},
};
</script>