mirror of
https://github.com/directus/directus.git
synced 2026-01-25 06:47:57 -05:00
Allow auto generate in m2m
This commit is contained in:
@@ -4,45 +4,108 @@
|
||||
<div class="grid">
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('this_collection') }}</div>
|
||||
<v-input disabled :value="collection" />
|
||||
<v-input disabled :value="relations[0].one_collection" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('junction_collection') }}</div>
|
||||
<v-select
|
||||
:items="collectionItems"
|
||||
v-model="junctionCollection"
|
||||
:placeholder="$t('select_one')"
|
||||
:disabled="isExisting"
|
||||
allow-other
|
||||
/>
|
||||
<v-input v-model="junctionCollection" :placeholder="$t('collection')" :disabled="isExisting" db-safe>
|
||||
<template #append>
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="box" @click="toggle" v-tooltip="$t('select_existing')" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in collectionItems"
|
||||
:key="item.value"
|
||||
:active="relations[0].many_collection === item.value"
|
||||
@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>
|
||||
<div class="field">
|
||||
<div class="type-label">{{ $t('related_collection') }}</div>
|
||||
<v-select
|
||||
:disabled="type === 'files' || isExisting"
|
||||
:items="collectionItems"
|
||||
v-model="relations[1].one_collection"
|
||||
:placeholder="$t('select_one')"
|
||||
/>
|
||||
<v-input v-model="relations[1].one_collection" :placeholder="$t('collection')" :disabled="type === 'files' || isExisting" db-safe>
|
||||
<template #append>
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="box" @click="toggle" v-tooltip="$t('select_existing')" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in collectionItems"
|
||||
:key="item.value"
|
||||
:active="relations[1].one_collection === item.value"
|
||||
@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 disabled :value="relations[0].one_primary" />
|
||||
<v-select
|
||||
:disabled="!junctionCollection || isExisting"
|
||||
:items="junctionFields"
|
||||
v-model="relations[0].many_field"
|
||||
:placeholder="$t('select_one')"
|
||||
/>
|
||||
<v-input v-model="relations[0].many_field" :placeholder="$t('foreign_key')" :disabled="isExisting" db-safe>
|
||||
<template #append v-if="junctionCollectionExists">
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="box" @click="toggle" v-tooltip="$t('select_existing')" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in junctionFields"
|
||||
:key="item.value"
|
||||
:active="relations[0].many_field === item.value"
|
||||
@click="relations[0].many_field = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
<div class="spacer" />
|
||||
<div class="spacer" />
|
||||
<v-select
|
||||
:disabled="!junctionCollection || isExisting"
|
||||
:items="junctionFields"
|
||||
v-model="relations[1].many_field"
|
||||
:placeholder="$t('select_one')"
|
||||
/>
|
||||
<v-input disabled :value="relations[1].one_primary" />
|
||||
<v-icon name="arrow_forward" />
|
||||
<v-icon name="arrow_backward" />
|
||||
<v-input v-model="relations[1].many_field" :placeholder="$t('foreign_key')" :disabled="isExisting" db-safe>
|
||||
<template #append v-if="junctionCollectionExists">
|
||||
<v-menu show-arrow placement="bottom-end">
|
||||
<template #activator="{ toggle }">
|
||||
<v-icon name="box" @click="toggle" v-tooltip="$t('select_existing')" />
|
||||
</template>
|
||||
|
||||
<v-list dense class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in junctionFields"
|
||||
:key="item.value"
|
||||
:active="relations[1].many_field === item.value"
|
||||
@click="relations[1].many_field = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
<v-input db-safe :disabled="relatedCollectionExists" v-model="relations[1].one_primary" :placeholder="$t('primary_key')" />
|
||||
<v-icon class="arrow" name="arrow_forward" />
|
||||
<v-icon class="arrow" name="arrow_backward" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -104,6 +167,14 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
|
||||
const junctionCollectionExists = computed(() => {
|
||||
return collectionsStore.getCollection(junctionCollection.value) !== null;
|
||||
});
|
||||
|
||||
const relatedCollectionExists = computed(() => {
|
||||
return collectionsStore.getCollection(state.relations[1].one_collection) !== null;
|
||||
});
|
||||
|
||||
const junctionFields = computed(() => {
|
||||
if (!junctionCollection.value) return [];
|
||||
|
||||
@@ -117,7 +188,7 @@ export default defineComponent({
|
||||
}));
|
||||
});
|
||||
|
||||
return { relations: state.relations, collectionItems, junctionCollection, junctionFields };
|
||||
return { relations: state.relations, collectionItems, junctionCollection, junctionFields, junctionCollectionExists, relatedCollectionExists };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -133,11 +204,12 @@ export default defineComponent({
|
||||
gap: 20px;
|
||||
margin-top: 48px;
|
||||
|
||||
.v-icon {
|
||||
.v-icon.arrow {
|
||||
--v-icon-color: var(--foreground-subdued);
|
||||
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
pointer-events: none;
|
||||
|
||||
&:first-of-type {
|
||||
bottom: 85px;
|
||||
|
||||
@@ -12,6 +12,7 @@ import { getInterfaces } from '@/interfaces';
|
||||
import { getDisplays } from '@/displays';
|
||||
import { InterfaceConfig } from '@/interfaces/types';
|
||||
import { DisplayConfig } from '@/displays/types';
|
||||
import { Field } from '@/types';
|
||||
|
||||
const fieldsStore = useFieldsStore();
|
||||
const relationsStore = useRelationsStore();
|
||||
@@ -160,7 +161,7 @@ function initLocalStore(
|
||||
has_auto_increment: true,
|
||||
},
|
||||
system: {
|
||||
interface: 'text-input',
|
||||
hidden: true,
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -238,7 +239,7 @@ function initLocalStore(
|
||||
has_auto_increment: true,
|
||||
},
|
||||
system: {
|
||||
interface: 'text-input',
|
||||
hidden: true,
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -315,6 +316,69 @@ function initLocalStore(
|
||||
delete state.fieldData.schema;
|
||||
delete state.fieldData.type;
|
||||
|
||||
const syncNewCollectionsM2M = throttle((
|
||||
[junctionCollection, manyCurrent, manyRelated, relatedCollection],
|
||||
[oldJunctionCollection, oldManyCurrent, oldManyRelated, oldRelatedCollection]
|
||||
) => {
|
||||
state.newCollections = state.newCollections.filter((col: any) => [junctionCollection, relatedCollection, oldJunctionCollection, oldRelatedCollection].includes(col.collection) === false);
|
||||
state.newFields = state.newFields
|
||||
.filter((field: Partial<Field>) => [manyCurrent, manyRelated, relatedCollection, oldManyCurrent, oldManyRelated, oldRelatedCollection].includes(field.field) === false);
|
||||
|
||||
if (collectionExists(junctionCollection) === false) {
|
||||
state.newCollections.push({
|
||||
collection: junctionCollection,
|
||||
fields: [
|
||||
{
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyCurrent) === false) {
|
||||
state.newFields.push({
|
||||
collection: junctionCollection,
|
||||
field: manyCurrent,
|
||||
type: fieldsStore.getPrimaryKeyFieldForCollection(junctionCollection)?.type,
|
||||
schema: {},
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyRelated) === false) {
|
||||
state.newFields.push({
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
type: collectionExists(relatedCollection) ? fieldsStore.getPrimaryKeyFieldForCollection(relatedCollection)?.type : 'integer',
|
||||
schema: {},
|
||||
});
|
||||
}
|
||||
|
||||
if (collectionExists(relatedCollection) === false) {
|
||||
state.newCollections.push({
|
||||
collection: relatedCollection,
|
||||
fields: [
|
||||
{
|
||||
field: state.relations[1].one_primary,
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}, 50);
|
||||
|
||||
if (!isExisting) {
|
||||
state.fieldData.meta.special = 'm2m';
|
||||
|
||||
@@ -348,9 +412,11 @@ function initLocalStore(
|
||||
watch(
|
||||
() => state.relations[0].many_collection,
|
||||
() => {
|
||||
const pkField = fieldsStore.getPrimaryKeyFieldForCollection(state.relations[0].many_collection)?.field;
|
||||
state.relations[0].many_primary = pkField;
|
||||
state.relations[1].many_primary = pkField;
|
||||
if (collectionExists(state.relations[0].many_collection)) {
|
||||
const pkField = fieldsStore.getPrimaryKeyFieldForCollection(state.relations[0].many_collection)?.field;
|
||||
state.relations[0].many_primary = pkField;
|
||||
state.relations[1].many_primary = pkField;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -371,11 +437,23 @@ function initLocalStore(
|
||||
watch(
|
||||
() => state.relations[1].one_collection,
|
||||
() => {
|
||||
state.relations[1].one_primary = fieldsStore.getPrimaryKeyFieldForCollection(
|
||||
state.relations[1].one_collection
|
||||
)?.field;
|
||||
if (collectionExists(state.relations[1].one_collection)) {
|
||||
state.relations[1].one_primary = fieldsStore.getPrimaryKeyFieldForCollection(
|
||||
state.relations[1].one_collection
|
||||
)?.field;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
[
|
||||
() => state.relations[0].many_collection,
|
||||
() => state.relations[0].many_field,
|
||||
() => state.relations[1].many_field,
|
||||
() => state.relations[1].one_collection,
|
||||
],
|
||||
syncNewCollectionsM2M
|
||||
)
|
||||
}
|
||||
|
||||
if (type === 'presentation') {
|
||||
@@ -420,7 +498,7 @@ function initLocalStore(
|
||||
}
|
||||
|
||||
function fieldExists(collection: string, field: string) {
|
||||
return fieldsStore.getField(collection, field) !== null;
|
||||
return collectionExists(collection) && fieldsStore.getField(collection, field) !== null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user