mirror of
https://github.com/directus/directus.git
synced 2026-01-26 18:08:15 -05:00
Add translations field type
This commit is contained in:
@@ -6,6 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('translations'),
|
||||
icon: 'replay',
|
||||
types: ['alias'],
|
||||
relationship: 'translations',
|
||||
component: InterfaceTranslations,
|
||||
options: [
|
||||
/** @todo add custom options component */
|
||||
|
||||
@@ -10,7 +10,7 @@ export type InterfaceConfig = {
|
||||
component: Component;
|
||||
options: DeepPartial<Field>[] | Component;
|
||||
types: typeof types[number][];
|
||||
relationship?: null | 'm2o' | 'o2m' | 'm2m';
|
||||
relationship?: null | 'm2o' | 'o2m' | 'm2m' | 'translations';
|
||||
hideLabel?: boolean;
|
||||
hideLoader?: boolean;
|
||||
system?: boolean;
|
||||
|
||||
@@ -153,6 +153,8 @@
|
||||
"field_m2o": "M2O Relationship",
|
||||
"field_o2m": "O2M Relationship",
|
||||
"field_m2m": "M2M Relationship",
|
||||
"field_translations": "Translations",
|
||||
"languages": "Languages",
|
||||
|
||||
"reset_page_preferences": "Reset Page Preferences",
|
||||
|
||||
@@ -185,6 +187,8 @@
|
||||
"configure_m2o": "Configure your Many-to-One Relationship...",
|
||||
"configure_o2m": "Configure your One-to-Many Relationship...",
|
||||
"configure_m2m": "Configure your Many-to-Many Relationship...",
|
||||
"configure_translations": "Configure your Translations...",
|
||||
"configure_languages": "Configure your Languages...",
|
||||
|
||||
"add_m2o_to_collection": "Add Many-to-One to \"{collection}\"",
|
||||
"add_o2m_to_collection": "Add One-to-Many to \"{collection}\"",
|
||||
@@ -297,6 +301,8 @@
|
||||
"item_in": "Item {primaryKey} in {collection} | Items {primaryKey} in {collection}",
|
||||
"this_collection": "This Collection",
|
||||
"related_collection": "Related Collection",
|
||||
"translations_collection": "Translations Collection",
|
||||
"languages_collection": "Languages Collection",
|
||||
|
||||
"related_values": "Related Values",
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="type-title">{{ $t('configure_languages') }}</h2>
|
||||
<div class="grid">
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('translations_collection') }}</div>
|
||||
<v-input disabled :value="relations[1].many_collection" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('languages_collection') }}</div>
|
||||
<v-input :class="{ matches: languagesCollectionExists }" db-safe key="languages-collection" v-model="relations[1].one_collection" :disabled="isExisting" :placeholder="$t('collection') + '...'">
|
||||
<template #append>
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="list_alt" @click="toggle" v-tooltip="$t('select_existing')" :disabled="isExisting" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in items"
|
||||
:key="item.value"
|
||||
:active="relations[1].one_collection === item.value"
|
||||
:disabled="item.disabled"
|
||||
@click="relations[1].one_collection = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
</div>
|
||||
<v-input :value="relations[1].many_field" :placeholder="$t('foreign_key') + '...'"/>
|
||||
<v-input db-safe :disabled="languagesCollectionExists" v-model="relations[1].one_primary" :placeholder="$t('primary_key') + '...'" />
|
||||
<v-icon class="arrow" name="arrow_back" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, watch } from '@vue/composition-api';
|
||||
import { Relation } from '@/types';
|
||||
import { Field } from '@/types';
|
||||
import { orderBy } from 'lodash';
|
||||
import useSync from '@/composables/use-sync';
|
||||
import { useCollectionsStore, useFieldsStore } from '@/stores';
|
||||
import i18n from '@/lang';
|
||||
|
||||
import { state } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
collection: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isExisting: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
const { items } = useRelation();
|
||||
|
||||
const languagesCollectionExists = computed(() => {
|
||||
return !!collectionsStore.getCollection(state.relations[1].one_collection);
|
||||
});
|
||||
|
||||
return {
|
||||
relations: state.relations,
|
||||
items,
|
||||
fieldData: state.fieldData,
|
||||
languagesCollectionExists,
|
||||
};
|
||||
|
||||
function useRelation() {
|
||||
const availableCollections = computed(() => {
|
||||
return orderBy(
|
||||
collectionsStore.state.collections.filter((collection) => {
|
||||
return collection.collection.startsWith('directus_') === false;
|
||||
}),
|
||||
['collection'],
|
||||
['asc']
|
||||
);
|
||||
});
|
||||
|
||||
const items = computed(() =>
|
||||
availableCollections.value.map((collection) => ({
|
||||
text: collection.collection,
|
||||
value: collection.collection,
|
||||
}))
|
||||
);
|
||||
|
||||
return { items };
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid {
|
||||
--v-select-font-family: var(--family-monospace);
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px 32px;
|
||||
margin-top: 48px;
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
|
||||
position: absolute;
|
||||
bottom: 14px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.v-list {
|
||||
--v-list-item-content-font-family: var(--family-monospace);
|
||||
}
|
||||
|
||||
.v-divider {
|
||||
margin: 48px 0;
|
||||
}
|
||||
|
||||
.type-label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -39,7 +39,6 @@
|
||||
<v-input v-model="fieldData.meta.note" :placeholder="$t('add_note')" />
|
||||
</div>
|
||||
|
||||
<!-- @todo base default value field type on selected type -->
|
||||
<div class="field full" v-if="fieldData.schema">
|
||||
<div class="label type-label">{{ $t('default_value') }}</div>
|
||||
<v-input
|
||||
@@ -228,7 +227,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const typeDisabled = computed(() => {
|
||||
return ['file', 'files', 'o2m', 'm2m', 'm2o'].includes(props.type);
|
||||
return ['file', 'files', 'o2m', 'm2m', 'm2o', 'translations'].includes(props.type);
|
||||
});
|
||||
|
||||
const typePlaceholder = computed(() => {
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="type-title">{{ $t('configure_translations') }}</h2>
|
||||
<div class="grid">
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('this_collection') }}</div>
|
||||
<v-input disabled :value="collection" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('translations_collection') }}</div>
|
||||
<v-input
|
||||
db-safe
|
||||
:placeholder="$t('collection') + '...'"
|
||||
v-model="relations[0].many_collection"
|
||||
:disabled="isExisting"
|
||||
:class="{ matches: translationsCollectionExists }"
|
||||
>
|
||||
<template #append>
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="list_alt" @click="toggle" v-tooltip="$t('select_existing')" :disabled="isExisting" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in items"
|
||||
:key="item.value"
|
||||
:active="relations[0].many_collection === item.value"
|
||||
:disabled="item.disabled"
|
||||
@click="relations[0].many_collection = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
</div>
|
||||
<v-input disabled :value="currentCollectionPrimaryKey.field" />
|
||||
<v-input
|
||||
db-safe
|
||||
v-model="relations[0].many_field"
|
||||
:disabled="isExisting"
|
||||
:placeholder="$t('foreign_key') + '...'"
|
||||
:class="{ matches: translationsFieldExists }"
|
||||
>
|
||||
<template #append v-if="fields && fields.length > 0">
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="list_alt" @click="toggle" v-tooltip="$t('select_existing')" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="field in fields"
|
||||
:key="field.value"
|
||||
:active="relations[0].many_field === field.value"
|
||||
@click="relations[0].many_field = field.value"
|
||||
:disabled="field.disabled"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ field.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
<v-icon class="arrow" name="arrow_forward" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import { Relation, Field } from '@/types';
|
||||
import useSync from '@/composables/use-sync';
|
||||
import { useFieldsStore, useCollectionsStore } from '@/stores';
|
||||
import { orderBy } from 'lodash';
|
||||
import i18n from '@/lang';
|
||||
|
||||
import { state } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
collection: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isExisting: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
const { items, fields, currentCollectionPrimaryKey, collectionMany } = useRelation();
|
||||
|
||||
const translationsCollectionExists = computed(() => {
|
||||
return collectionsStore.state.collections.find((col) => col.collection === state.relations?.[0].many_collection);
|
||||
});
|
||||
|
||||
const translationsFieldExists = computed(() => {
|
||||
if (!state?.relations?.[0].many_collection || !state?.relations?.[0].many_field) return false;
|
||||
return !!fieldsStore.getField(state.relations[0].many_collection, state.relations[0].many_field);
|
||||
});
|
||||
|
||||
return { relations: state.relations, items, fields, currentCollectionPrimaryKey, collectionMany, translationsCollectionExists, translationsFieldExists };
|
||||
|
||||
function useRelation() {
|
||||
const availableCollections = computed(() => {
|
||||
return orderBy(
|
||||
collectionsStore.state.collections.filter((collection) => {
|
||||
return (
|
||||
collection.collection.startsWith('directus_') === false &&
|
||||
collection.collection !== props.collection
|
||||
);
|
||||
}),
|
||||
['collection'],
|
||||
['asc']
|
||||
);
|
||||
});
|
||||
|
||||
const items = computed(() =>
|
||||
availableCollections.value.map((collection) => ({
|
||||
text: collection.collection,
|
||||
value: collection.collection,
|
||||
}))
|
||||
);
|
||||
|
||||
const currentCollectionPrimaryKey = computed(() =>
|
||||
fieldsStore.getPrimaryKeyFieldForCollection(props.collection)
|
||||
);
|
||||
|
||||
const fields = computed(() => {
|
||||
if (!state.relations[0].many_collection) return [];
|
||||
|
||||
return fieldsStore.state.fields
|
||||
.filter((field) => field.collection === state.relations[0].many_collection)
|
||||
.map((field) => ({
|
||||
text: field.field,
|
||||
value: field.field,
|
||||
disabled:
|
||||
!field.schema ||
|
||||
field.schema?.is_primary_key ||
|
||||
field.type !== currentCollectionPrimaryKey.value.type,
|
||||
}));
|
||||
});
|
||||
|
||||
const collectionMany = computed({
|
||||
get() {
|
||||
return state.relations[0].many_collection!;
|
||||
},
|
||||
set(collection: string) {
|
||||
state.relations[0].many_collection = collection;
|
||||
state.relations[0].many_field = '';
|
||||
},
|
||||
});
|
||||
|
||||
return { availableCollections, items, fields, currentCollectionPrimaryKey, collectionMany };
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid {
|
||||
--v-select-font-family: var(--family-monospace);
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px 32px;
|
||||
margin-top: 48px;
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.v-icon.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
|
||||
position: absolute;
|
||||
bottom: 14px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.v-list {
|
||||
--v-list-item-content-font-family: var(--family-monospace);
|
||||
}
|
||||
|
||||
.type-label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.v-divider {
|
||||
margin: 48px 0;
|
||||
}
|
||||
|
||||
.corresponding {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px 32px;
|
||||
margin-top: 48px;
|
||||
|
||||
.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
|
||||
position: absolute;
|
||||
bottom: 14px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -27,6 +27,20 @@
|
||||
:type="localType"
|
||||
/>
|
||||
|
||||
<setup-translations
|
||||
v-if="currentTab[0] === 'translations'"
|
||||
:is-existing="field !== '+'"
|
||||
:collection="collection"
|
||||
:type="localType"
|
||||
/>
|
||||
|
||||
<setup-languages
|
||||
v-if="currentTab[0] === 'languages'"
|
||||
:is-existing="field !== '+'"
|
||||
:collection="collection"
|
||||
:type="localType"
|
||||
/>
|
||||
|
||||
<setup-interface
|
||||
v-if="currentTab[0] === 'interface'"
|
||||
:is-existing="field !== '+'"
|
||||
@@ -61,6 +75,8 @@ import SetupTabs from './components/tabs.vue';
|
||||
import SetupActions from './components/actions.vue';
|
||||
import SetupSchema from './components/schema.vue';
|
||||
import SetupRelationship from './components/relationship.vue';
|
||||
import SetupTranslations from './components/translations.vue';
|
||||
import SetupLanguages from './components/languages.vue';
|
||||
import SetupInterface from './components/interface.vue';
|
||||
import SetupDisplay from './components/display.vue';
|
||||
import { i18n } from '@/lang';
|
||||
@@ -81,6 +97,8 @@ export default defineComponent({
|
||||
SetupActions,
|
||||
SetupSchema,
|
||||
SetupRelationship,
|
||||
SetupTranslations,
|
||||
SetupLanguages,
|
||||
SetupInterface,
|
||||
SetupDisplay,
|
||||
},
|
||||
@@ -94,7 +112,7 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m' | 'presentation'>,
|
||||
type: String as PropType<'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m' | 'presentation' | 'translations'>,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
@@ -116,7 +134,7 @@ export default defineComponent({
|
||||
const localType = computed(() => {
|
||||
if (props.field === '+') return props.type;
|
||||
|
||||
let type: 'standard' | 'file' | 'files' | 'o2m' | 'm2m' | 'm2o' | 'presentation' = 'standard';
|
||||
let type: 'standard' | 'file' | 'files' | 'o2m' | 'm2m' | 'm2o' | 'presentation' | 'translations' = 'standard';
|
||||
type = getLocalTypeForField(props.collection, props.field);
|
||||
|
||||
return type;
|
||||
@@ -173,6 +191,21 @@ export default defineComponent({
|
||||
});
|
||||
}
|
||||
|
||||
if (localType.value === 'translations') {
|
||||
tabs.splice(1, 0, ...[
|
||||
{
|
||||
text: i18n.t('translations'),
|
||||
value: 'translations',
|
||||
disabled: translationsDisabled(),
|
||||
},
|
||||
{
|
||||
text: i18n.t('languages'),
|
||||
value: 'languages',
|
||||
disabled: languagesDisabled(),
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
return tabs;
|
||||
});
|
||||
|
||||
@@ -181,10 +214,20 @@ export default defineComponent({
|
||||
return { tabs, currentTab };
|
||||
|
||||
function relationshipDisabled() {
|
||||
return (
|
||||
isEmpty(state.fieldData.field) ||
|
||||
(['o2m', 'm2m', 'files', 'm2o'].includes(localType.value) === false &&
|
||||
isEmpty(state.fieldData.type))
|
||||
return isEmpty(state.fieldData.field);
|
||||
}
|
||||
|
||||
function translationsDisabled() {
|
||||
return isEmpty(state.fieldData.field);
|
||||
}
|
||||
|
||||
function languagesDisabled() {
|
||||
return isEmpty(state.fieldData.field) || (
|
||||
state.relations.length === 0 ||
|
||||
isEmpty(state.relations[0].many_collection) ||
|
||||
isEmpty(state.relations[0].many_field) ||
|
||||
isEmpty(state.relations[0].one_collection) ||
|
||||
isEmpty(state.relations[0].one_primary)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -199,7 +242,7 @@ export default defineComponent({
|
||||
);
|
||||
}
|
||||
|
||||
if (['m2m', 'files'].includes(localType.value)) {
|
||||
if (['m2m', 'files', 'translations'].includes(localType.value)) {
|
||||
return (
|
||||
state.relations.length !== 2 ||
|
||||
isEmpty(state.relations[0].many_collection) ||
|
||||
@@ -294,11 +337,14 @@ export default defineComponent({
|
||||
function getLocalTypeForField(
|
||||
collection: string,
|
||||
field: string
|
||||
): 'standard' | 'file' | 'files' | 'o2m' | 'm2m' | 'm2o' {
|
||||
): 'standard' | 'file' | 'files' | 'o2m' | 'm2m' | 'm2o' | 'presentation' | 'translations' {
|
||||
const fieldInfo = fieldsStore.getField(collection, field);
|
||||
const relations = relationsStore.getRelationsForField(collection, field);
|
||||
|
||||
if (relations.length === 0) return 'standard';
|
||||
if (relations.length === 0) {
|
||||
if (fieldInfo.type === 'alias') return 'presentation';
|
||||
return 'standard';
|
||||
}
|
||||
|
||||
if (relations.length === 1) {
|
||||
const relation = relations[0];
|
||||
|
||||
@@ -27,7 +27,7 @@ export { state, availableInterfaces, availableDisplays, initLocalStore, clearLoc
|
||||
function initLocalStore(
|
||||
collection: string,
|
||||
field: string,
|
||||
type: 'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m' | 'presentation'
|
||||
type: 'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m' | 'presentation' | 'translations'
|
||||
) {
|
||||
const interfaces = getInterfaces();
|
||||
const displays = getDisplays();
|
||||
@@ -75,6 +75,8 @@ function initLocalStore(
|
||||
matchesRelation = inter.relationship === 'm2o';
|
||||
} else if (type === 'files') {
|
||||
matchesRelation = inter.relationship === 'm2m';
|
||||
} else if (type === 'translations') {
|
||||
matchesRelation = inter.relationship === 'translations';
|
||||
} else {
|
||||
matchesRelation = inter.relationship === type;
|
||||
}
|
||||
@@ -277,8 +279,6 @@ function initLocalStore(
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
console.log(state.newFields);
|
||||
}, 50);
|
||||
|
||||
if (!isExisting) {
|
||||
@@ -321,7 +321,7 @@ function initLocalStore(
|
||||
)
|
||||
}
|
||||
|
||||
if (type === 'm2m' || type === 'files') {
|
||||
if (type === 'm2m' || type === 'files' || type === 'translations') {
|
||||
delete state.fieldData.schema;
|
||||
delete state.fieldData.type;
|
||||
|
||||
@@ -424,26 +424,6 @@ function initLocalStore(
|
||||
];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => state.fieldData.field,
|
||||
() => {
|
||||
state.relations[0].one_field = state.fieldData.field;
|
||||
|
||||
if (collectionExists(state.fieldData.field)) {
|
||||
state.relations[0].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[0].many_field = `${state.relations[0].one_collection}_${state.relations[0].one_primary}`;
|
||||
state.relations[1].one_collection = state.fieldData.field;
|
||||
state.relations[1].one_primary = fieldsStore.getPrimaryKeyFieldForCollection(collection)?.field;
|
||||
state.relations[1].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_${state.relations[1].one_primary}`;
|
||||
|
||||
if (state.relations[0].many_field === state.relations[1].many_field) {
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_related_${state.relations[1].one_primary}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => state.relations[0].many_collection,
|
||||
() => {
|
||||
@@ -490,34 +470,75 @@ function initLocalStore(
|
||||
syncNewCollectionsM2M
|
||||
)
|
||||
|
||||
let stop: WatchStopHandle;
|
||||
watch(
|
||||
() => state.fieldData.field,
|
||||
() => {
|
||||
state.relations[0].one_field = state.fieldData.field;
|
||||
|
||||
watch(() => state.autoFillJunctionRelation, (startWatching) => {
|
||||
if (startWatching) {
|
||||
stop = watch([() => state.relations[1].one_collection, () => state.relations[1].one_primary], ([newRelatedCollection, newRelatedPrimary]: string[]) => {
|
||||
if (newRelatedCollection) {
|
||||
state.relations[0].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[1].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[0].many_field = `${state.relations[0].one_collection}_${state.relations[0].one_primary}`;
|
||||
}
|
||||
|
||||
if (newRelatedPrimary) {
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_${state.relations[1].one_primary}`;
|
||||
}
|
||||
if (collectionExists(state.fieldData.field) && type !== 'translations') {
|
||||
state.relations[0].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[0].many_field = `${state.relations[0].one_collection}_${state.relations[0].one_primary}`;
|
||||
state.relations[1].one_collection = state.fieldData.field;
|
||||
state.relations[1].one_primary = fieldsStore.getPrimaryKeyFieldForCollection(collection)?.field;
|
||||
state.relations[1].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_${state.relations[1].one_primary}`;
|
||||
|
||||
if (state.relations[0].many_field === state.relations[1].many_field) {
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_related_${state.relations[1].one_primary}`;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
stop?.();
|
||||
}
|
||||
}
|
||||
}, { immediate: true });
|
||||
);
|
||||
|
||||
if (type !== 'translations') {
|
||||
let stop: WatchStopHandle;
|
||||
|
||||
watch(() => state.autoFillJunctionRelation, (startWatching) => {
|
||||
if (startWatching) {
|
||||
stop = watch([() => state.relations[1].one_collection, () => state.relations[1].one_primary], ([newRelatedCollection, newRelatedPrimary]: string[]) => {
|
||||
if (newRelatedCollection) {
|
||||
state.relations[0].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[1].many_collection = `${state.relations[0].one_collection}_${state.relations[1].one_collection}`;
|
||||
state.relations[0].many_field = `${state.relations[0].one_collection}_${state.relations[0].one_primary}`;
|
||||
}
|
||||
|
||||
if (newRelatedPrimary) {
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_${state.relations[1].one_primary}`;
|
||||
}
|
||||
|
||||
if (state.relations[0].many_field === state.relations[1].many_field) {
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_related_${state.relations[1].one_primary}`;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
stop?.();
|
||||
}
|
||||
}, { immediate: true });
|
||||
}
|
||||
|
||||
if (type === 'translations') {
|
||||
watch(() => state.relations[0].many_collection, (newManyCollection: string) => {
|
||||
state.relations[1].many_collection = newManyCollection;
|
||||
}, { immediate: true });
|
||||
|
||||
state.relations[0].many_collection = `${collection}_translations`;
|
||||
state.relations[0].many_field = `${collection}_${fieldsStore.getPrimaryKeyFieldForCollection(collection)?.field}`;
|
||||
state.relations[1].one_collection = 'languages';
|
||||
|
||||
if (collectionExists('languages')) {
|
||||
state.relations[1].one_primary = fieldsStore.getPrimaryKeyFieldForCollection('languages')?.field;
|
||||
} else {
|
||||
state.relations[1].one_primary = 'id';
|
||||
}
|
||||
|
||||
state.relations[1].many_field = `${state.relations[1].one_collection}_${state.relations[1].one_primary}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'presentation') {
|
||||
delete state.fieldData.schema;
|
||||
delete state.fieldData.type;
|
||||
|
||||
state.fieldData.meta.special = 'alias';
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,14 @@ export default defineComponent({
|
||||
icon: 'import_export',
|
||||
text: i18n.t('m2m_relationship'),
|
||||
},
|
||||
{
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
type: 'translations',
|
||||
icon: 'translate',
|
||||
text: i18n.t('translations')
|
||||
}
|
||||
]);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user