improve related values display

This commit is contained in:
Nitwel
2020-10-15 17:04:07 +02:00
parent cbd283d4a0
commit 8857ac54fb
6 changed files with 111 additions and 25 deletions

View File

@@ -5,6 +5,7 @@ import adjustFieldsForDisplays from '@/utils/adjust-fields-for-displays';
import getRelatedCollection from '@/utils/get-related-collection';
import useCollection from '@/composables/use-collection';
import { ref } from '@vue/composition-api';
import options from './options.vue';
type Options = {
template: string;
@@ -16,19 +17,9 @@ export default defineDisplay(({ i18n }) => ({
description: i18n.t('displays.related-values.description'),
icon: 'settings_ethernet',
handler: DisplayRelatedValues,
options: [
/** @todo make this a component so we have dynamic collection for display template component */
{
field: 'template',
name: i18n.t('display_template'),
type: 'string',
meta: {
interface: 'text-input',
width: 'full',
},
},
],
options: options,
types: ['alias', 'string', 'uuid', 'integer', 'bigInteger', 'json'],
localTypes: ['m2m', 'm2o', 'o2m'],
fields: (options: Options, { field, collection }) => {
const relatedCollection = getRelatedCollection(collection, field);
const { primaryKeyField } = useCollection(ref(relatedCollection as string));

View File

@@ -0,0 +1,82 @@
<template>
<v-notice type="warning" v-if="collection === null">
{{ $t('interfaces.one-to-many.no_collection') }}
</v-notice>
<div v-else class="form-grid">
<div class="field full">
<p class="type-label">{{ $t('display_template') }}</p>
<v-field-template :collection="relatedCollection" v-model="template" :depth="2" />
</div>
</div>
</template>
<script lang="ts">
import { Field } from '@/types';
import { defineComponent, PropType, computed } from '@vue/composition-api';
import { useRelationsStore } from '@/stores/';
import { Relation } from '@/types/relations';
export default defineComponent({
props: {
value: {
type: Object as PropType<any | null>,
default: null,
},
fieldData: {
type: Object as PropType<Field>,
default: null,
},
relations: {
type: Array as PropType<Relation[]>,
default: () => [],
},
collection: {
type: String,
default: null,
},
},
setup(props, { emit }) {
const relationsStore = useRelationsStore();
const template = computed({
get() {
return props.value?.template;
},
set(newTemplate: string) {
emit('input', {
...(props.value || {}),
template: newTemplate,
});
},
});
const relatedCollection = computed(() => {
if (!props.fieldData || !props.relations || props.relations.length === 0) return null;
const { field } = props.fieldData;
const m2o = props.relations.find(
(relation) => relation.many_collection === props.collection && relation.many_field === field
);
const o2m = props.relations.find(
(relation) => relation.one_collection === props.collection && relation.one_field === field
);
if (m2o !== undefined) {
return m2o?.one_collection || null;
}
if (o2m !== undefined) {
return o2m?.many_collection || null;
}
});
return { template, relatedCollection };
},
});
</script>
<style lang="scss" scoped>
@import '@/styles/mixins/form-grid';
.form-grid {
@include form-grid;
}
</style>

View File

@@ -1,6 +1,6 @@
import VueI18n from 'vue-i18n';
import { Component } from 'vue';
import { Field, types } from '@/types';
import { Field, localTypes, types } from '@/types';
export type DisplayHandlerFunctionContext = {
type: string;
@@ -30,6 +30,7 @@ export type DisplayConfig = {
handler: DisplayHandlerFunction | Component;
options: null | DeepPartial<Field>[] | Component;
types: readonly typeof types[number][];
localTypes?: readonly typeof localTypes[number][];
fields?: string[] | DisplayFieldsFunction;
};

View File

@@ -22,13 +22,22 @@
v-model="fieldData.meta.display_options"
/>
<component v-model="fieldData" :is="`display-options-${selectedDisplay.id}`" v-else />
<component
v-model="fieldData.meta.display_options"
:collection="collection"
:field-data="fieldData"
:relations="relations"
:new-fields="newFields"
:new-collections="newCollections"
:is="`display-options-${selectedDisplay.id}`"
v-else
/>
</template>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from '@vue/composition-api';
import { defineComponent, computed, toRefs } from '@vue/composition-api';
import { getDisplays } from '@/displays';
import { getInterfaces } from '@/interfaces';
import { FancySelectItem } from '@/components/v-fancy-select/types';
@@ -42,6 +51,10 @@ export default defineComponent({
type: String,
required: true,
},
collection: {
type: String,
required: true,
},
},
setup(props, { emit }) {
const displays = getDisplays();
@@ -95,7 +108,9 @@ export default defineComponent({
return displays.value.find((display) => display.id === state.fieldData.meta.display);
});
return { fieldData: state.fieldData, selectItems, selectedDisplay };
const { fieldData, relations, newCollections, newFields } = toRefs(state);
return { fieldData, selectItems, selectedDisplay, relations, newCollections, newFields };
},
});
</script>

View File

@@ -12,7 +12,7 @@ import { getInterfaces } from '@/interfaces';
import { getDisplays } from '@/displays';
import { InterfaceConfig } from '@/interfaces/types';
import { DisplayConfig } from '@/displays/types';
import { Field } from '@/types';
import { Field, localTypes } from '@/types';
import Vue from 'vue';
const fieldsStore = useFieldsStore();
@@ -25,11 +25,7 @@ let availableDisplays: ComputedRef<DisplayConfig[]>;
export { state, availableInterfaces, availableDisplays, initLocalStore, clearLocalStore };
function initLocalStore(
collection: string,
field: string,
type: 'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m' | 'presentation' | 'translations'
) {
function initLocalStore(collection: string, field: string, type: typeof localTypes[number]) {
const interfaces = getInterfaces();
const displays = getDisplays();
@@ -91,8 +87,8 @@ function initLocalStore(
availableDisplays = computed(() =>
displays.value.filter((display) => {
const matchesType = display.types.includes(state.fieldData?.type || 'alias');
const matchesRelation = true;
return matchesType && matchesRelation;
let matchesLocalType = display.localTypes?.includes(type);
return matchesType && (matchesLocalType === undefined || matchesLocalType);
})
);

View File

@@ -27,6 +27,8 @@ export const types = [
'unknown',
] as const;
export const localTypes = ['standard', 'file', 'files', 'm2o', 'o2m', 'm2m', 'presentation', 'translations'] as const;
export type FieldSchema = {
/** @todo import this from knex-schema-inspector when that's launched */
name: string;
@@ -70,7 +72,6 @@ export interface FieldRaw {
collection: string;
field: string;
type: typeof types[number];
schema: FieldSchema | null;
meta: FieldMeta | null;
}