Worked on universal property form

This commit is contained in:
Stefan Zermatten
2023-04-03 16:35:29 +02:00
parent b9588c83b1
commit 53e88af93a
11 changed files with 192 additions and 95 deletions

View File

@@ -7,16 +7,18 @@
>
<template #activator="{ on }">
<v-btn
:outlined="!!label"
:icon="!label"
:tile="!label"
:min-width="label && 108"
:height="height"
:width="width"
:disabled="context.editPermission === false"
v-on="on"
>
{{ label }}
<v-icon
:right="!!label"
:color="label && value"
:color="value"
>
mdi-format-paint
</v-icon>
@@ -137,7 +139,15 @@
label: {
type: String,
default: undefined,
}
},
height: {
type: Number,
default: undefined,
},
width: {
type: Number,
default: undefined,
},
},
data(){ return {
colors: [

View File

@@ -5,26 +5,32 @@
transition="slide-y-transition"
min-width="290px"
style="overflow-y: auto;"
left
>
<template #activator="{ on }">
<v-btn
:loading="loading"
outlined
:min-width="108"
v-bind="$attrs"
:outlined="!!label"
:icon="!label"
:tile="!label"
:min-width="label && 108"
:height="height"
:width="width"
:style="buttonStyle"
:disabled="context.editPermission === false"
v-bind="$attrs"
v-on="on"
>
{{ label }}
<svg-icon
v-if="safeValue && safeValue.shape"
right
class="ml-2"
:class="{'ml-2': !!label}"
:shape="safeValue.shape"
/>
<v-icon
v-else
right
:right="!!label"
>
mdi-select-search
</v-icon>
@@ -87,15 +93,26 @@ export default {
SvgIcon,
},
mixins: [SmartInput],
inject: {
context: { default: {} }
},
props: {
label: {
type: String,
default: 'Icon',
default: undefined,
},
buttonStyle: {
type: String,
default: undefined,
},
height: {
type: Number,
default: undefined,
},
width: {
type: Number,
default: undefined,
},
},
data() {
return {

View File

@@ -29,11 +29,6 @@
style="flex-shrink: 0;"
>
<v-spacer />
<color-picker
v-if="$listeners && $listeners['color-changed']"
:value="model.color"
@input="colorChanged"
/>
<v-menu
v-if="$listeners && (
$listeners.move ||

View File

@@ -10,7 +10,6 @@
@duplicate="duplicate"
@remove="remove"
@toggle-editing="editing = !editing"
@color-changed="value => change({path: ['color'], value})"
/>
</template>
<template v-if="model">
@@ -32,37 +31,16 @@
mode="out-in"
>
<div v-if="editing">
<component
:is="model.type + 'Form'"
<property-form
:key="_id"
class="creature-property-form"
:model="model"
:embedded="embedded"
@change="change"
@push="push"
@pull="pull"
>
<template #children>
<creature-properties-tree
style="width: 100%;"
class="mb-2"
organize
:root="{collection: 'creatureProperties', id: model._id}"
@length="childrenLength = $event"
@selected="selectSubProperty"
/>
<v-btn
icon
outlined
color="accent"
data-id="insert-creature-property-btn"
@click="addProperty"
>
<v-icon>
mdi-plus
</v-icon>
</v-btn>
</template>
</component>
@add-child="addProperty"
/>
</div>
<div v-else>
<component
@@ -123,6 +101,7 @@ import DialogBase from '/imports/client/ui/dialogStack/DialogBase.vue';
import { getPropertyName } from '/imports/constants/PROPERTIES.js';
import PropertyIcon from '/imports/client/ui/properties/shared/PropertyIcon.vue';
import propertyFormIndex from '/imports/client/ui/properties/forms/shared/propertyFormIndex.js';
import PropertyForm from '/imports/client/ui/properties/PropertyForm.vue';
import propertyViewerIndex from '/imports/client/ui/properties/viewers/shared/propertyViewerIndex.js';
import CreaturePropertiesTree from '/imports/client/ui/creature/creatureProperties/CreaturePropertiesTree.vue';
import getPropertyTitle from '/imports/client/ui/properties/shared/getPropertyTitle.js';
@@ -150,6 +129,7 @@ export default {
components: {
...formIndex,
...viewerIndex,
PropertyForm,
PropertyIcon,
DialogBase,
PropertyToolbar,

View File

@@ -3,30 +3,24 @@
<v-row>
<v-col
cols="12"
md="6"
>
<icon-color-menu
:model="model"
:errors="errors"
@change="$emit('change', ...arguments)"
/>
</v-col>
<v-col
cols="12"
md="6"
class="d-flex flex-wrap-reverse justify-end"
style="gap: 8px"
>
<text-field
ref="focusFirst"
label="Name"
style="flex-basis: 320px;"
:value="model.name"
:error-messages="errors.name"
@change="change('name', ...arguments)"
/>
<icon-color-menu
:model="model"
@change="$emit('change', $event)"
/>
</v-col>
</v-row>
<component
:is="model.type + 'Form'"
:key="_id"
:is="model.type"
class="creature-property-form"
:model="model"
@change="$emit('change', ...arguments)"
@@ -34,24 +28,6 @@
@pull="$emit('pull', ...arguments)"
/>
<v-divider inset />
<v-row
v-show="!embedded && childrenLength"
class="mt-1"
dense
>
<property-field
name="Child properties"
:cols="{cols: 12}"
>
<creature-properties-tree
style="width: 100%;"
organize
:root="{collection: 'creatureProperties', id: model._id}"
@length="childrenLength = $event"
@selected="selectSubProperty"
/>
</property-field>
</v-row>
<v-row>
<v-col
cols="12"
@@ -68,6 +44,52 @@
/>
</v-col>
</v-row>
<v-row
class="mt-1"
dense
>
<v-col
cols="12"
class="d-flex flex-wrap-reverse justify-end"
style="gap: 8px"
>
<outlined-input
name="Child properties"
style="width: 100%"
class="pa-2"
>
<creature-properties-tree
style="width: 100%;"
organize
:root="{collection: 'creatureProperties', id: model._id}"
@selected="selectSubProperty"
/>
<v-btn
v-for="suggestion in suggestedChildren"
:key="suggestion.type"
text
tile
color="accent"
data-id="insert-creature-property-btn"
@click="$emit('add-child')"
>
<v-icon left>
mdi-plus
</v-icon>
{{ suggestion.details.name }}
</v-btn>
<v-btn
text
tile
color="accent"
data-id="insert-creature-property-btn"
@click="$emit('add-child')"
>
...Other
</v-btn>
</outlined-input>
</v-col>
</v-row>
</div>
</template>
@@ -79,6 +101,11 @@
import ComputedField from '/imports/client/ui/properties/forms/shared/ComputedField.vue';
import InlineComputationField from '/imports/client/ui/properties/forms/shared/InlineComputationField.vue';
import FormSection, { FormSections } from '/imports/client/ui/properties/forms/shared/FormSection.vue';
import propertyFormIndex from '/imports/client/ui/properties/forms/shared/propertyFormIndex.js';
import IconColorMenu from '/imports/client/ui/properties/forms/shared/IconColorMenu.vue';
import CreaturePropertiesTree from '/imports/client/ui/creature/creatureProperties/CreaturePropertiesTree.vue';
import OutlinedInput from '/imports/client/ui/properties/viewers/shared/OutlinedInput.vue';
import { getSuggestedChildren } from '/imports/constants/PROPERTIES.js';
export default {
components: {
@@ -86,15 +113,22 @@ export default {
InlineComputationField,
FormSection,
FormSections,
IconColorMenu,
CreaturePropertiesTree,
OutlinedInput,
...propertyFormIndex,
},
props: {
model: {
type: [Object, Array],
default: () => ({}),
},
errors: {
type: Object,
default: () => ({}),
embedded: Boolean, // This dialog is embedded in a page
},
computed: {
suggestedChildren() {
if (!this.model?.type) return;
return getSuggestedChildren(this.model.type);
},
},
methods: {

View File

@@ -1,6 +1,9 @@
<template lang="html">
<v-card
:hover="hasClickListener"
:color="model.color"
:dark="model.color && isDark"
:light="model.color && !isDark"
@click="click"
@mouseover="hasClickListener ? hovering = true : undefined"
@mouseleave="hasClickListener ? hovering = false : undefined"
@@ -13,6 +16,7 @@
<script lang="js">
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
import AttributeCardContent from '/imports/client/ui/properties/components/attributes/AttributeCardContent.vue';
import isDarkColor from '/imports/client/ui/utility/isDarkColor.js';
export default {
components: {
@@ -33,6 +37,10 @@
hasClickListener(){
return this.$listeners && !!this.$listeners.click
},
isDark() {
if (!this.model.color) return;
return isDarkColor(this.model.color);
},
},
methods: {
click(e){

View File

@@ -2,6 +2,9 @@
<v-card
class="resource-card"
:class="hover ? 'elevation-8': ''"
:color="model.color"
:dark="model.color && isDark"
:light="model.color && !isDark"
>
<resource-card-content
:model="model"
@@ -18,6 +21,7 @@
<script lang="js">
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
import ResourceCardContent from '/imports/client/ui/properties/components/attributes/ResourceCardContent.vue';
import isDarkColor from '/imports/client/ui/utility/isDarkColor.js';
export default {
components: {
@@ -38,6 +42,12 @@ export default {
hover: false,
}
},
computed: {
isDark() {
if (!this.model.color) return;
return isDarkColor(this.model.color);
},
}
};
</script>

View File

@@ -1,31 +1,40 @@
<template lang="html">
<div
class="d-flex justify-center flex-wrap"
class="d-flex flex-wrap align-start"
>
<div class="mx-1">
<color-picker
label="Color"
:value="model.color"
@input="value =>$emit('change', {path: ['color'], value})"
/>
</div>
<div class="mx-1">
<outlined-input
name="Icon"
class="mb-4"
>
<icon-picker
label="Icon"
:value="model.icon"
:error-messages="errors.icon"
:width="54"
:height="54"
@change="(value, ack) =>$emit('change', {path: ['icon'], value, ack})"
/>
</div>
</outlined-input>
<outlined-input
name="Color"
class="mb-4 ml-2"
>
<color-picker
:value="model.color"
:width="54"
:height="54"
@input="value =>$emit('change', {path: ['color'], value})"
/>
</outlined-input>
</div>
</template>
<script lang="js">
import PropertyIcon from '/imports/client/ui/properties/shared/PropertyIcon.vue';
import ColorPicker from '/imports/client/ui/components/ColorPicker.vue';
import OutlinedInput from '/imports/client/ui/properties/viewers/shared/OutlinedInput.vue';
export default {
components: {
OutlinedInput,
PropertyIcon,
ColorPicker,
},
@@ -34,10 +43,6 @@
type: Object,
required: true,
},
errors: {
type: Object,
required: true,
},
},
}
</script>

View File

@@ -0,0 +1,28 @@
<template>
<v-sheet
outlined
rounded
style="position: relative;"
@click="$emit('click', $event)"
>
<v-sheet
v-if="name"
class="text-caption px-1 ml-2 name"
style="top: 0; left: 0; margin-top: -10px; position: absolute;"
>
{{ name }}
</v-sheet>
<slot />
</v-sheet>
</template>
<script lang="js">
export default {
props: {
name: {
type: String,
default: undefined,
}
}
}
</script>

View File

@@ -209,14 +209,25 @@ const PROPERTIES = Object.freeze({
export default PROPERTIES;
export function getPropertyName(type){
export function getPropertyName(type) {
return type && PROPERTIES[type] && PROPERTIES[type].name;
}
export function getPropertyIcon(type){
export function getPropertyIcon(type) {
return type && PROPERTIES[type] && PROPERTIES[type].icon;
}
export function getSuggestedChildren(type) {
const suggestions = [];
for (const key in PROPERTIES) {
const prop = PROPERTIES[key];
if (prop.suggestedParents.includes(type)) {
suggestions.push({ type: key, details: prop });
}
}
return suggestions;
}
const propsByDocsPath = new Map();
for (const key in PROPERTIES) {

View File

@@ -19,8 +19,7 @@
"allowJs": true
},
"vueCompilerOptions": {
"target": 2.7,
// "target": 2, // For Vue version <= 2.6.14
"target": 2 // For Vue version <= 2.6.14
},
"exclude": [
"node_modules",