mirror of
https://github.com/directus/directus.git
synced 2026-01-23 00:28:10 -05:00
Move sortField to relationship setup (#4304)
* Add migration * Add sort field to relation types * Remove sortfield options in favor of relationship * Add sort field configuration to relational setup * Save m2a sortfield on the correct row * Add default sort field to system data
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import Knex from 'knex';
|
||||
|
||||
export async function up(knex: Knex) {
|
||||
await knex.schema.alterTable('directus_relations', (table) => {
|
||||
table.string('sort_field');
|
||||
});
|
||||
|
||||
const fieldsWithSort = await knex
|
||||
.select('collection', 'field', 'options')
|
||||
.from('directus_fields')
|
||||
.whereIn('interface', ['one-to-many', 'm2a-builder', 'many-to-many']);
|
||||
|
||||
for (const field of fieldsWithSort) {
|
||||
const options = typeof field.options === 'string' ? JSON.parse(field.options) : field.options ?? {};
|
||||
|
||||
if ('sortField' in options) {
|
||||
await knex('directus_relations')
|
||||
.update({
|
||||
sort_field: options.sortField,
|
||||
})
|
||||
.where({
|
||||
one_collection: field.collection,
|
||||
one_field: field.field,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex) {
|
||||
await knex.schema.alterTable('directus_relations', (table) => {
|
||||
table.dropColumn('sort_field');
|
||||
});
|
||||
}
|
||||
@@ -8,6 +8,7 @@ defaults:
|
||||
one_field: null
|
||||
one_primary: null
|
||||
junction_field: null
|
||||
sort_field: null
|
||||
|
||||
data:
|
||||
- many_collection: directus_users
|
||||
|
||||
@@ -11,4 +11,7 @@ export type Relation = {
|
||||
|
||||
one_collection_field: string | null;
|
||||
one_allowed_collections: string | null;
|
||||
|
||||
junction_field: string | null;
|
||||
sort_field: string | null;
|
||||
};
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
:disabled="disabled"
|
||||
@update:items="sortItems($event)"
|
||||
@click:row="editItem"
|
||||
:show-manual-sort="sortField !== null"
|
||||
:manual-sort-key="sortField"
|
||||
:show-manual-sort="relationInfo.sortField !== null"
|
||||
:manual-sort-key="relationInfo.sortField"
|
||||
>
|
||||
<template #item.$thumbnail="{ item }">
|
||||
<render-display
|
||||
@@ -104,10 +104,6 @@ export default defineComponent({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
sortField: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
value: {
|
||||
type: Array as PropType<(string | number | Record<string, any>)[] | null>,
|
||||
default: null,
|
||||
@@ -118,23 +114,19 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const { collection, field, value, primaryKey, sortField } = toRefs(props);
|
||||
const { collection, field, value } = toRefs(props);
|
||||
|
||||
const { junction, junctionCollection, relation, relationCollection, relationInfo } = useRelation(collection, field);
|
||||
const { junction, junctionCollection, relation, relationInfo } = useRelation(collection, field);
|
||||
|
||||
function emitter(newVal: any[] | null) {
|
||||
emit('input', newVal);
|
||||
}
|
||||
|
||||
const {
|
||||
deleteItem,
|
||||
getUpdatedItems,
|
||||
getNewItems,
|
||||
getPrimaryKeys,
|
||||
getNewSelectedItems,
|
||||
getJunctionItem,
|
||||
getJunctionFromRelatedId,
|
||||
} = useActions(value, relationInfo, emitter);
|
||||
const { deleteItem, getUpdatedItems, getNewItems, getPrimaryKeys, getNewSelectedItems } = useActions(
|
||||
value,
|
||||
relationInfo,
|
||||
emitter
|
||||
);
|
||||
|
||||
const fields = computed(() => {
|
||||
const { junctionField } = relationInfo.value;
|
||||
@@ -162,7 +154,6 @@ export default defineComponent({
|
||||
const { loading, error, items } = usePreview(
|
||||
value,
|
||||
fields,
|
||||
sortField,
|
||||
relationInfo,
|
||||
getNewSelectedItems,
|
||||
getUpdatedItems,
|
||||
@@ -184,7 +175,7 @@ export default defineComponent({
|
||||
|
||||
const { showUpload, onUpload } = useUpload();
|
||||
|
||||
const { sort, sortItems, sortedItems } = useSort(sortField, fields, items, emitter);
|
||||
const { sort, sortItems, sortedItems } = useSort(relationInfo, fields, items, emitter);
|
||||
|
||||
return {
|
||||
junction,
|
||||
@@ -212,7 +203,7 @@ export default defineComponent({
|
||||
sort,
|
||||
sortItems,
|
||||
sortedItems,
|
||||
downloadItem
|
||||
downloadItem,
|
||||
};
|
||||
|
||||
function downloadItem(item: any) {
|
||||
@@ -255,6 +246,7 @@ export default defineComponent({
|
||||
}
|
||||
.download {
|
||||
--v-icon-color: var(--foreground-subdued);
|
||||
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { defineInterface } from '../define';
|
||||
import InterfaceFiles from './files.vue';
|
||||
import FilesOptions from './options.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'files',
|
||||
@@ -11,6 +10,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
types: ['alias'],
|
||||
groups: ['files'],
|
||||
relational: true,
|
||||
options: FilesOptions,
|
||||
options: [],
|
||||
recommendedDisplays: ['files'],
|
||||
}));
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<v-notice type="warning" v-if="junctionCollection === null">
|
||||
{{ $t('interfaces.one-to-many.no_collection') }}
|
||||
</v-notice>
|
||||
<div v-else class="form-grid">
|
||||
<div class="field half">
|
||||
<p class="type-label">{{ $t('sort_field') }}</p>
|
||||
<interface-field
|
||||
v-model="sortField"
|
||||
:collection="junctionCollection"
|
||||
:type-allow-list="['bigInteger', 'integer']"
|
||||
allowNone
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Field } from '@/types';
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import { useRelationsStore } from '@/stores/';
|
||||
import { Relation, Collection } from '@/types';
|
||||
import { useCollectionsStore } from '@/stores';
|
||||
export default defineComponent({
|
||||
props: {
|
||||
collection: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
fieldData: {
|
||||
type: Object as PropType<Field>,
|
||||
default: null,
|
||||
},
|
||||
relations: {
|
||||
type: Array as PropType<Relation[]>,
|
||||
default: () => [],
|
||||
},
|
||||
value: {
|
||||
type: Object as PropType<any>,
|
||||
default: null,
|
||||
},
|
||||
newCollections: {
|
||||
type: Array as PropType<Collection[]>,
|
||||
default: () => [],
|
||||
},
|
||||
newFields: {
|
||||
type: Array as PropType<Field[]>,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const relationsStore = useRelationsStore();
|
||||
|
||||
const sortField = computed({
|
||||
get() {
|
||||
return props.value?.sortField;
|
||||
},
|
||||
set(newFields: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
sortField: newFields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const junctionCollection = computed(() => {
|
||||
if (!props.fieldData || !props.relations || props.relations.length === 0) return null;
|
||||
const { field } = props.fieldData;
|
||||
const junctionRelation = props.relations.find(
|
||||
(relation) => relation.one_collection === props.collection && relation.one_field === field
|
||||
);
|
||||
return junctionRelation?.many_collection || null;
|
||||
});
|
||||
|
||||
const junctionCollectionExists = computed(() => {
|
||||
return !!collectionsStore.state.collections.find(
|
||||
(collection) => collection.collection === junctionCollection.value
|
||||
);
|
||||
});
|
||||
|
||||
return { sortField, junctionCollection, junctionCollectionExists };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/styles/mixins/form-grid';
|
||||
.form-grid {
|
||||
@include form-grid;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,5 @@
|
||||
import { defineInterface } from '../define';
|
||||
import InterfaceManyToAny from './m2a-builder.vue';
|
||||
import Options from './options.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'm2a-builder',
|
||||
@@ -10,5 +9,5 @@ export default defineInterface(({ i18n }) => ({
|
||||
relational: true,
|
||||
types: ['alias'],
|
||||
groups: ['m2a'],
|
||||
options: Options,
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
handle=".drag-handle"
|
||||
@input="onSort"
|
||||
:set-data="hideDragImage"
|
||||
:disabled="!sortField"
|
||||
:disabled="!o2mRelation.sort_field"
|
||||
>
|
||||
<div
|
||||
class="m2a-row"
|
||||
@@ -18,7 +18,7 @@
|
||||
:key="item.$index"
|
||||
@click="editExisting((value || [])[item.$index])"
|
||||
>
|
||||
<v-icon class="drag-handle" name="drag_handle" @click.stop v-if="sortField" />
|
||||
<v-icon class="drag-handle" name="drag_handle" @click.stop v-if="o2mRelation.sort_field" />
|
||||
<span class="collection">{{ collections[item[anyRelation.one_collection_field]].name }}:</span>
|
||||
<span
|
||||
v-if="typeof item[anyRelation.many_field] === 'number' || typeof item[anyRelation.many_field] === 'string'"
|
||||
@@ -139,10 +139,6 @@ export default defineComponent({
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
required: true,
|
||||
},
|
||||
sortField: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const relationsStore = useRelationsStore();
|
||||
@@ -304,10 +300,16 @@ export default defineComponent({
|
||||
return val;
|
||||
});
|
||||
|
||||
return [
|
||||
...values.filter((val) => val[props.sortField]).sort((a, b) => a[props.sortField] - b[props.sortField]), // sort by sortField if it exists
|
||||
...values.filter((val) => !val[props.sortField]).sort((a, b) => a.$index - b.$index), // sort the rest with $index
|
||||
];
|
||||
if (o2mRelation.value?.sort_field) {
|
||||
return [
|
||||
...values
|
||||
.filter((val) => val[o2mRelation.value.sort_field!])
|
||||
.sort((a, b) => a[o2mRelation.value.sort_field!] - b[o2mRelation.value.sort_field!]), // sort by sort field if it exists
|
||||
...values.filter((val) => !val[o2mRelation.value.sort_field!]).sort((a, b) => a.$index - b.$index), // sort the rest with $index
|
||||
];
|
||||
} else {
|
||||
return [...values.sort((a, b) => a.$index - b.$index)];
|
||||
}
|
||||
});
|
||||
|
||||
return { fetchValues, previewValues, loading, junctionRowMap, relatedItemValues };
|
||||
@@ -378,7 +380,7 @@ export default defineComponent({
|
||||
o2mRelation.value.many_primary,
|
||||
anyRelation.value.many_field,
|
||||
anyRelation.value.one_collection_field!,
|
||||
props.sortField,
|
||||
o2mRelation.value.sort_field,
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -530,8 +532,8 @@ export default defineComponent({
|
||||
},
|
||||
};
|
||||
|
||||
if (props.sortField) {
|
||||
editsAtStart.value[props.sortField] = junctionRow[props.sortField];
|
||||
if (o2mRelation.value.sort_field) {
|
||||
editsAtStart.value[o2mRelation.value.sort_field] = junctionRow[o2mRelation.value.sort_field];
|
||||
}
|
||||
|
||||
relatedPrimaryKey.value = relatedKey || '+';
|
||||
@@ -571,6 +573,8 @@ export default defineComponent({
|
||||
emit(
|
||||
'input',
|
||||
props.value.map((rawValue, index) => {
|
||||
if (!o2mRelation.value.sort_field) return rawValue;
|
||||
|
||||
const sortedItemIndex = sortedItems.findIndex((sortedItem) => {
|
||||
return sortedItem.$index === index;
|
||||
});
|
||||
@@ -578,12 +582,12 @@ export default defineComponent({
|
||||
if (isPlainObject(rawValue)) {
|
||||
return {
|
||||
...rawValue,
|
||||
[props.sortField]: sortedItemIndex + 1,
|
||||
[o2mRelation.value.sort_field]: sortedItemIndex + 1,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
[o2mRelation.value.many_primary]: rawValue,
|
||||
[props.sortField]: sortedItemIndex + 1,
|
||||
[o2mRelation.value.sort_field]: sortedItemIndex + 1,
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<v-notice type="warning" v-if="junctionCollection === null">
|
||||
{{ $t('interfaces.one-to-many.no_collection') }}
|
||||
</v-notice>
|
||||
<div v-else class="form-grid">
|
||||
<div class="field half-space">
|
||||
<p class="type-label">{{ $t('sort_field') }}</p>
|
||||
|
||||
<interface-field
|
||||
v-model="sortField"
|
||||
:collection="junctionCollection"
|
||||
:type-allow-list="['bigInteger', 'integer']"
|
||||
allowNone
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Field } from '@/types';
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import { useRelationsStore } from '@/stores/';
|
||||
import { Relation, Collection } from '@/types';
|
||||
import { useCollectionsStore } from '@/stores';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
collection: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
fieldData: {
|
||||
type: Object as PropType<Field>,
|
||||
default: null,
|
||||
},
|
||||
relations: {
|
||||
type: Array as PropType<Relation[]>,
|
||||
default: () => [],
|
||||
},
|
||||
value: {
|
||||
type: Object as PropType<any>,
|
||||
default: null,
|
||||
},
|
||||
newCollections: {
|
||||
type: Array as PropType<Collection[]>,
|
||||
default: () => [],
|
||||
},
|
||||
newFields: {
|
||||
type: Array as PropType<Field[]>,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const relationsStore = useRelationsStore();
|
||||
|
||||
const sortField = computed({
|
||||
get() {
|
||||
return props.value?.sortField;
|
||||
},
|
||||
set(newFields: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
sortField: newFields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const junctionCollection = computed(() => {
|
||||
if (!props.fieldData || !props.relations || props.relations.length === 0) return null;
|
||||
const { field } = props.fieldData;
|
||||
|
||||
const junctionRelation = props.relations.find(
|
||||
(relation) => relation.one_collection === props.collection && relation.one_field === field
|
||||
);
|
||||
|
||||
return junctionRelation?.many_collection || null;
|
||||
});
|
||||
|
||||
const junctionCollectionExists = computed(() => {
|
||||
return !!collectionsStore.state.collections.find(
|
||||
(collection) => collection.collection === junctionCollection.value
|
||||
);
|
||||
});
|
||||
|
||||
return { sortField, junctionCollection, junctionCollectionExists };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/styles/mixins/form-grid';
|
||||
.form-grid {
|
||||
@include form-grid;
|
||||
}
|
||||
</style>
|
||||
@@ -13,8 +13,8 @@
|
||||
@update:items="sortItems($event)"
|
||||
@click:row="editItem"
|
||||
:disabled="disabled"
|
||||
:show-manual-sort="sortField !== null"
|
||||
:manual-sort-key="sortField"
|
||||
:show-manual-sort="relationInfo.sortField !== null"
|
||||
:manual-sort-key="relationInfo.sortField"
|
||||
>
|
||||
<template v-for="header in tableHeaders" v-slot:[`item.${header.value}`]="{ item }">
|
||||
<render-display
|
||||
@@ -98,10 +98,6 @@ export default defineComponent({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
sortField: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
fields: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
@@ -112,7 +108,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const { value, collection, field, fields, sortField } = toRefs(props);
|
||||
const { value, collection, field, fields } = toRefs(props);
|
||||
|
||||
function emitter(newVal: any[] | null) {
|
||||
emit('input', newVal);
|
||||
@@ -120,20 +116,15 @@ export default defineComponent({
|
||||
|
||||
const { junction, junctionCollection, relation, relationCollection, relationInfo } = useRelation(collection, field);
|
||||
|
||||
const {
|
||||
deleteItem,
|
||||
getUpdatedItems,
|
||||
getNewItems,
|
||||
getPrimaryKeys,
|
||||
getNewSelectedItems,
|
||||
getJunctionItem,
|
||||
getJunctionFromRelatedId,
|
||||
} = useActions(value, relationInfo, emitter);
|
||||
const { deleteItem, getUpdatedItems, getNewItems, getPrimaryKeys, getNewSelectedItems } = useActions(
|
||||
value,
|
||||
relationInfo,
|
||||
emitter
|
||||
);
|
||||
|
||||
const { tableHeaders, items, loading, error } = usePreview(
|
||||
value,
|
||||
fields,
|
||||
sortField,
|
||||
relationInfo,
|
||||
getNewSelectedItems,
|
||||
getUpdatedItems,
|
||||
@@ -153,7 +144,7 @@ export default defineComponent({
|
||||
|
||||
const { stageSelection, selectModalActive, selectionFilters } = useSelection(value, items, relationInfo, emitter);
|
||||
|
||||
const { sort, sortItems, sortedItems } = useSort(sortField, fields, items, emitter);
|
||||
const { sort, sortItems, sortedItems } = useSort(relationInfo, fields, items, emitter);
|
||||
|
||||
return {
|
||||
junction,
|
||||
|
||||
@@ -11,15 +11,6 @@
|
||||
:inject="junctionCollectionExists ? null : { fields: newFields, collections: newCollections, relations }"
|
||||
/>
|
||||
</div>
|
||||
<div class="field half">
|
||||
<p class="type-label">{{ $t('sort_field') }}</p>
|
||||
<interface-field
|
||||
v-model="sortField"
|
||||
:collection="junctionCollection"
|
||||
:type-allow-list="['bigInteger', 'integer']"
|
||||
allowNone
|
||||
></interface-field>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -58,19 +49,6 @@ export default defineComponent({
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const relationsStore = useRelationsStore();
|
||||
|
||||
const sortField = computed({
|
||||
get() {
|
||||
return props.value?.sortField;
|
||||
},
|
||||
set(newFields: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
sortField: newFields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const fields = computed({
|
||||
get() {
|
||||
@@ -99,7 +77,7 @@ export default defineComponent({
|
||||
);
|
||||
});
|
||||
|
||||
return { fields, sortField, junctionCollection, junctionCollectionExists };
|
||||
return { fields, junctionCollection, junctionCollectionExists };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -9,7 +9,6 @@ import { cloneDeep, get } from 'lodash';
|
||||
export default function usePreview(
|
||||
value: Ref<(string | number | Record<string, any>)[] | null>,
|
||||
fields: Ref<string[]>,
|
||||
sortField: Ref<string | null>,
|
||||
relation: Ref<RelationInfo>,
|
||||
getNewSelectedItems: () => Record<string, any>[],
|
||||
getUpdatedItems: () => Record<string, any>[],
|
||||
@@ -159,8 +158,8 @@ export default function usePreview(
|
||||
if (filteredFields.includes(junctionPkField) === false) filteredFields.push(junctionPkField);
|
||||
if (filteredFields.includes(junctionField) === false) filteredFields.push(junctionField);
|
||||
|
||||
if (sortField.value !== null && filteredFields.includes(sortField.value) === false)
|
||||
filteredFields.push(sortField.value);
|
||||
if (relation.value.sortField !== null && filteredFields.includes(relation.value.sortField) === false)
|
||||
filteredFields.push(relation.value.sortField);
|
||||
|
||||
data = await request(junctionCollection, filteredFields, junctionPkField, primaryKeys);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export type RelationInfo = {
|
||||
junctionPkField: string;
|
||||
relationPkField: string;
|
||||
junctionField: string;
|
||||
sortField: string;
|
||||
junctionCollection: string;
|
||||
relationCollection: string;
|
||||
};
|
||||
@@ -50,6 +51,7 @@ export default function useRelation(collection: Ref<string>, field: Ref<string>)
|
||||
junctionPkField: junctionPrimaryKeyField.value.field,
|
||||
relationPkField: relationPrimaryKeyField.value.field,
|
||||
junctionField: junction.value.junction_field as string,
|
||||
sortField: junction.value.sort_field as string,
|
||||
junctionCollection: junctionCollection.value.collection,
|
||||
relationCollection: relationCollection.value.collection,
|
||||
} as RelationInfo;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { Ref, ref, computed } from '@vue/composition-api';
|
||||
import { Sort } from '@/components/v-table/types';
|
||||
import { sortBy } from 'lodash';
|
||||
import { RelationInfo } from './use-relation';
|
||||
|
||||
export default function useSort(
|
||||
sortField: Ref<string | null>,
|
||||
relation: Ref<RelationInfo>,
|
||||
fields: Ref<string[]>,
|
||||
items: Ref<Record<string, any>[]>,
|
||||
emit: (newVal: any[] | null) => void
|
||||
) {
|
||||
const sort = ref<Sort>({ by: sortField.value || fields.value[0], desc: false });
|
||||
const sort = ref<Sort>({ by: relation.value.sortField || fields.value[0], desc: false });
|
||||
|
||||
const sortedItems = computed(() => {
|
||||
const sField = sortField.value;
|
||||
const sField = relation.value.sortField;
|
||||
if (sField === null || sort.value.by !== sField) return null;
|
||||
|
||||
const desc = sort.value.desc;
|
||||
@@ -22,7 +23,7 @@ export default function useSort(
|
||||
return { sort, sortItems, sortedItems };
|
||||
|
||||
function sortItems(newItems: Record<string, any>[]) {
|
||||
const sField = sortField.value;
|
||||
const sField = relation.value.sortField;
|
||||
if (sField === null) return;
|
||||
|
||||
const itemsSorted = newItems.map((item, i) => {
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
@update:items="sortItems($event)"
|
||||
@click:row="editItem"
|
||||
:disabled="disabled"
|
||||
:show-manual-sort="sortField !== null"
|
||||
:manual-sort-key="sortField"
|
||||
:show-manual-sort="relation.sort_field !== null"
|
||||
:manual-sort-key="relation.sort_field"
|
||||
>
|
||||
<template v-for="header in tableHeaders" v-slot:[`item.${header.value}`]="{ item }">
|
||||
<render-display
|
||||
@@ -100,10 +100,6 @@ export default defineComponent({
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
sortField: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -141,16 +137,6 @@ export default defineComponent({
|
||||
get,
|
||||
};
|
||||
|
||||
function getItem(id: string | number) {
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
if (props.value === null) return null;
|
||||
return (
|
||||
props.value.find(
|
||||
(item) => (typeof item === 'object' && pkField in item && item[pkField] === id) || item === id
|
||||
) || null
|
||||
);
|
||||
}
|
||||
|
||||
function getNewItems() {
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
if (props.value === null) return [];
|
||||
@@ -169,12 +155,6 @@ export default defineComponent({
|
||||
>[];
|
||||
}
|
||||
|
||||
function getExistingItems() {
|
||||
if (props.value === null) return [];
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
return props.value.filter((item) => typeof item === 'string' || typeof item === 'number');
|
||||
}
|
||||
|
||||
function getPrimaryKeys() {
|
||||
if (props.value === null) return [];
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
@@ -216,13 +196,13 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function useSort() {
|
||||
const sort = ref<Sort>({ by: props.sortField || props.fields[0], desc: false });
|
||||
const sort = ref<Sort>({ by: relation.value.sort_field || props.fields[0], desc: false });
|
||||
|
||||
function sortItems(newItems: Record<string, any>[]) {
|
||||
if (props.sortField === null) return;
|
||||
if (relation.value.sort_field === null) return;
|
||||
|
||||
const itemsSorted = newItems.map((item, i) => {
|
||||
item[props.sortField] = i;
|
||||
item[relation.value.sort_field] = i;
|
||||
return item;
|
||||
});
|
||||
|
||||
@@ -230,10 +210,10 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const sortedItems = computed(() => {
|
||||
if (props.sortField === null || sort.value.by !== props.sortField) return null;
|
||||
if (relation.value.sort_field === null || sort.value.by !== relation.value.sort_field) return null;
|
||||
|
||||
const desc = sort.value.desc;
|
||||
const sorted = sortBy(items.value, [props.sortField]);
|
||||
const sorted = sortBy(items.value, [relation.value.sort_field]);
|
||||
return desc ? sorted.reverse() : sorted;
|
||||
});
|
||||
|
||||
@@ -267,7 +247,7 @@ export default defineComponent({
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
async (newVal) => {
|
||||
async () => {
|
||||
loading.value = true;
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
|
||||
@@ -277,7 +257,8 @@ export default defineComponent({
|
||||
fields.push(pkField);
|
||||
}
|
||||
|
||||
if (props.sortField !== null && fields.includes(props.sortField) === false) fields.push(props.sortField);
|
||||
if (relation.value.sort_field !== null && fields.includes(relation.value.sort_field) === false)
|
||||
fields.push(relation.value.sort_field);
|
||||
|
||||
try {
|
||||
const endpoint = relatedCollection.value.collection.startsWith('directus_')
|
||||
@@ -385,8 +366,6 @@ export default defineComponent({
|
||||
function stageEdits(edits: any) {
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
|
||||
const hasPrimaryKey = pkField in edits;
|
||||
|
||||
const newValue = (props.value || []).map((item) => {
|
||||
if (typeof item === 'object' && pkField in item && pkField in edits && item[pkField] === edits[pkField]) {
|
||||
return edits;
|
||||
@@ -447,8 +426,6 @@ export default defineComponent({
|
||||
return { stageSelection, selectModalActive, selectionFilters };
|
||||
|
||||
function stageSelection(newSelection: (number | string)[]) {
|
||||
const pkField = relatedPrimaryKeyField.value.field;
|
||||
|
||||
const selection = newSelection.filter((item) => selectedPrimaryKeys.value.includes(item) === false);
|
||||
|
||||
const newVal = [...selection, ...(props.value || [])];
|
||||
|
||||
@@ -11,22 +11,13 @@
|
||||
:inject="relatedCollectionExists ? null : { fields: newFields, collections: newCollections, relations }"
|
||||
/>
|
||||
</div>
|
||||
<div class="field half">
|
||||
<p class="type-label">{{ $t('sort_field') }}</p>
|
||||
<interface-field
|
||||
v-model="sortField"
|
||||
:collection="relatedCollection"
|
||||
:type-allow-list="['bigInteger', 'integer']"
|
||||
allowNone
|
||||
></interface-field>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Field, Relation, Collection } from '@/types';
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import { useRelationsStore, useCollectionsStore } from '@/stores/';
|
||||
import { useCollectionsStore } from '@/stores/';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -57,7 +48,6 @@ export default defineComponent({
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const relationsStore = useRelationsStore();
|
||||
|
||||
const fields = computed({
|
||||
get() {
|
||||
@@ -71,18 +61,6 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
|
||||
const sortField = computed({
|
||||
get() {
|
||||
return props.value?.sortField;
|
||||
},
|
||||
set(newFields: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
sortField: newFields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const relatedCollection = computed(() => {
|
||||
if (!props.fieldData || !props.relations || props.relations.length === 0) return null;
|
||||
const { field } = props.fieldData;
|
||||
@@ -98,7 +76,7 @@ export default defineComponent({
|
||||
);
|
||||
});
|
||||
|
||||
return { fields, sortField, relatedCollection, relatedCollectionExists };
|
||||
return { fields, relatedCollection, relatedCollectionExists };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -90,6 +90,7 @@ field_presentation: Presentation & Aliases
|
||||
field_file: Single File
|
||||
field_files: Multiple Files
|
||||
field_m2o: M2O Relationship
|
||||
field_m2a: M2A Relationship
|
||||
field_o2m: O2M Relationship
|
||||
field_m2m: M2M Relationship
|
||||
field_translations: Translations
|
||||
@@ -367,6 +368,7 @@ collection_created: Collection Created
|
||||
modified_on: Modified On
|
||||
card_size: Card Size
|
||||
sort_field: Sort Field
|
||||
add_sort_field: Add Sort Field
|
||||
sort: Sort
|
||||
status: Status
|
||||
toggle_manual_sorting: Toggle Manual Sorting
|
||||
|
||||
@@ -192,13 +192,47 @@
|
||||
<v-icon class="arrow" name="arrow_backward" />
|
||||
</div>
|
||||
|
||||
<div class="sort-field">
|
||||
<v-divider large :inline-title="false">{{ $t('sort_field') }}</v-divider>
|
||||
|
||||
<v-input
|
||||
:class="{ matches: junctionFieldExists(relations[0].sort_field) }"
|
||||
v-model="relations[0].sort_field"
|
||||
:nullable="false"
|
||||
:placeholder="$t('add_sort_field') + '...'"
|
||||
db-safe
|
||||
>
|
||||
<template #append v-if="junctionCollectionExists">
|
||||
<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 class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in junctionFields"
|
||||
:key="item.value"
|
||||
:active="relations[0].sort_field === item.value"
|
||||
:disabled="item.disabled"
|
||||
@click="relations[0].sort_field = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
</div>
|
||||
|
||||
<v-notice class="generated-data" v-if="generationInfo.length > 0" type="warning">
|
||||
<span>
|
||||
{{ $t('new_data_alert') }}
|
||||
<ul>
|
||||
<li v-for="(data, index) in generationInfo" :key="index">
|
||||
<span class="field-name">{{ data.name }}</span>
|
||||
({{ $t(data.isField ? 'new_field' : 'new_collection') }})
|
||||
({{ $t(data.type === 'field' ? 'new_field' : 'new_collection') }})
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
@@ -207,13 +241,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, ref } from '@vue/composition-api';
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import { orderBy } from 'lodash';
|
||||
import { useCollectionsStore, useFieldsStore } from '@/stores/';
|
||||
import { Field } from '@/types';
|
||||
import i18n from '@/lang';
|
||||
|
||||
import { state } from '../store';
|
||||
import { state, generationInfo } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -230,7 +263,7 @@ export default defineComponent({
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
setup() {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
@@ -290,38 +323,6 @@ export default defineComponent({
|
||||
}));
|
||||
});
|
||||
|
||||
const generationInfo = computed(() => {
|
||||
const message: { name: string; isField: boolean }[] = [];
|
||||
|
||||
if (state.relations[0].many_collection) {
|
||||
if (junctionCollectionExists.value === false)
|
||||
message.push({ name: state.relations[0].many_collection, isField: false });
|
||||
|
||||
if (junctionFieldExists(state.relations[0].many_field) === false && state.relations[0].many_field !== '')
|
||||
message.push({
|
||||
name: state.relations[0].many_collection + '.' + state.relations[0].many_field,
|
||||
isField: true,
|
||||
});
|
||||
|
||||
if (
|
||||
junctionFieldExists(state.relations[1].one_collection_field) === false &&
|
||||
state.relations[1].one_collection_field !== ''
|
||||
)
|
||||
message.push({
|
||||
name: state.relations[0].many_collection + '.' + state.relations[1].one_collection_field,
|
||||
isField: true,
|
||||
});
|
||||
|
||||
if (junctionFieldExists(state.relations[1].many_field) === false && state.relations[1].many_field !== '')
|
||||
message.push({
|
||||
name: state.relations[0].many_collection + '.' + state.relations[1].many_field,
|
||||
isField: true,
|
||||
});
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
|
||||
return {
|
||||
relations: state.relations,
|
||||
autoFill,
|
||||
@@ -353,10 +354,6 @@ export default defineComponent({
|
||||
gap: 12px 28px;
|
||||
margin-top: 48px;
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.v-icon.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
|
||||
@@ -381,6 +378,10 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.type-label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@@ -407,8 +408,8 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.related-collections-preview {
|
||||
grid-row: 2 / span 2;
|
||||
grid-column: 3;
|
||||
grid-row: 2 / span 2;
|
||||
padding: var(--input-padding);
|
||||
overflow: auto;
|
||||
color: var(--foreground-subdued);
|
||||
@@ -421,4 +422,13 @@ export default defineComponent({
|
||||
.one-collection-field {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.sort-field {
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
|
||||
.v-divider {
|
||||
margin-top: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -219,6 +219,40 @@
|
||||
<v-icon name="arrow_forward" class="arrow" />
|
||||
</div>
|
||||
|
||||
<div class="sort-field">
|
||||
<v-divider large :inline-title="false">{{ $t('sort_field') }}</v-divider>
|
||||
|
||||
<v-input
|
||||
:class="{ matches: junctionFieldExists(relations[0].sort_field) }"
|
||||
v-model="relations[0].sort_field"
|
||||
:nullable="false"
|
||||
:placeholder="$t('add_sort_field') + '...'"
|
||||
db-safe
|
||||
>
|
||||
<template #append v-if="junctionCollectionExists">
|
||||
<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 class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in junctionFields"
|
||||
:key="item.value"
|
||||
:active="relations[0].sort_field === item.value"
|
||||
:disabled="item.disabled"
|
||||
@click="relations[0].sort_field = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
</div>
|
||||
|
||||
<v-notice class="generated-data" v-if="generationInfo.length > 0" type="warning">
|
||||
<span>
|
||||
{{ $t('new_data_alert') }}
|
||||
@@ -226,7 +260,7 @@
|
||||
<ul>
|
||||
<li v-for="(data, index) in generationInfo" :key="index">
|
||||
<span class="field-name">{{ data.name }}</span>
|
||||
({{ $t(data.isField ? 'new_field' : 'new_collection') }})
|
||||
({{ $t(data.type === 'field' ? 'new_field' : 'new_collection') }})
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
@@ -235,13 +269,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, ref } from '@vue/composition-api';
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import { orderBy } from 'lodash';
|
||||
import { useCollectionsStore, useFieldsStore } from '@/stores/';
|
||||
import { Field } from '@/types';
|
||||
import i18n from '@/lang';
|
||||
|
||||
import { state } from '../store';
|
||||
import { state, generationInfo } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -324,44 +358,6 @@ export default defineComponent({
|
||||
|
||||
const { hasCorresponding, correspondingField, correspondingLabel } = useCorresponding();
|
||||
|
||||
const generationInfo = computed(() => {
|
||||
const message: { name: string; isField: boolean }[] = [];
|
||||
|
||||
if (state.relations[1].one_collection !== '') {
|
||||
if (relatedCollectionExists.value === false) {
|
||||
message.push({ name: state.relations[1].one_collection, isField: false });
|
||||
|
||||
if (state.relations[1].one_primary !== '')
|
||||
message.push({
|
||||
name: state.relations[1].one_collection + '.' + state.relations[1].one_primary,
|
||||
isField: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (hasCorresponding.value === true && correspondingField.value !== null)
|
||||
message.push({ name: state.relations[1].one_collection + '.' + correspondingField.value, isField: true });
|
||||
}
|
||||
|
||||
if (state.relations[0].many_collection) {
|
||||
if (junctionCollectionExists.value === false)
|
||||
message.push({ name: state.relations[0].many_collection, isField: false });
|
||||
|
||||
if (junctionFieldExists(state.relations[0].many_field) === false && state.relations[0].many_field !== '')
|
||||
message.push({
|
||||
name: state.relations[0].many_collection + '.' + state.relations[0].many_field,
|
||||
isField: true,
|
||||
});
|
||||
|
||||
if (junctionFieldExists(state.relations[1].many_field) === false && state.relations[1].many_field !== '')
|
||||
message.push({
|
||||
name: state.relations[0].many_collection + '.' + state.relations[1].many_field,
|
||||
isField: true,
|
||||
});
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
|
||||
return {
|
||||
relations: state.relations,
|
||||
autoFill,
|
||||
@@ -379,7 +375,7 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
function junctionFieldExists(fieldKey: string) {
|
||||
if (!junctionCollection.value) return false;
|
||||
if (!junctionCollection.value || !fieldKey) return false;
|
||||
return !!fieldsStore.getField(junctionCollection.value, fieldKey);
|
||||
}
|
||||
|
||||
@@ -457,10 +453,6 @@ export default defineComponent({
|
||||
gap: 12px 28px;
|
||||
margin-top: 48px;
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.v-icon.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
|
||||
@@ -480,12 +472,16 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.type-label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.v-divider {
|
||||
margin: 48px 0;
|
||||
margin: 48px 0 24px;
|
||||
}
|
||||
|
||||
.v-list {
|
||||
@@ -497,7 +493,6 @@ export default defineComponent({
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px 32px;
|
||||
margin-top: 48px;
|
||||
|
||||
.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
@@ -525,4 +520,13 @@ export default defineComponent({
|
||||
font-family: var(--family-monospace);
|
||||
}
|
||||
}
|
||||
|
||||
.sort-field {
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
|
||||
.v-divider {
|
||||
margin-top: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<ul>
|
||||
<li v-for="(data, index) in generationInfo" :key="index">
|
||||
<span class="field-name">{{ data.name }}</span>
|
||||
({{ $t(data.isField ? 'new_field' : 'new_collection') }})
|
||||
({{ $t(data.type === 'field' ? 'new_field' : 'new_collection') }})
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
@@ -102,15 +102,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, watch } from '@vue/composition-api';
|
||||
import { Relation } from '@/types';
|
||||
import { Field } from '@/types';
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import { orderBy } from 'lodash';
|
||||
import useSync from '@/composables/use-sync';
|
||||
import { useCollectionsStore, useFieldsStore } from '@/stores';
|
||||
import { useCollectionsStore } from '@/stores';
|
||||
import i18n from '@/lang';
|
||||
|
||||
import { state } from '../store';
|
||||
import { state, generationInfo } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -127,9 +124,8 @@ export default defineComponent({
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
setup() {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
const { availableCollections, systemCollections } = useRelation();
|
||||
const { hasCorresponding, correspondingField, correspondingLabel } = useCorresponding();
|
||||
@@ -138,30 +134,6 @@ export default defineComponent({
|
||||
return !!collectionsStore.getCollection(state.relations[0].one_collection);
|
||||
});
|
||||
|
||||
const generationInfo = computed(() => {
|
||||
const message: { name: string; isField: boolean }[] = [];
|
||||
|
||||
if (relatedCollectionExists.value === false && state.relations[0].one_collection !== '') {
|
||||
message.push({ name: state.relations[0].one_collection, isField: false });
|
||||
|
||||
if (state.relations[0].one_primary !== '')
|
||||
message.push({
|
||||
name: state.relations[0].one_collection + '.' + state.relations[0].one_primary,
|
||||
isField: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
hasCorresponding.value === true &&
|
||||
state.relations[0].one_collection !== '' &&
|
||||
correspondingField.value !== null
|
||||
) {
|
||||
message.push({ name: state.relations[0].one_collection + '.' + correspondingField.value, isField: true });
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
|
||||
return {
|
||||
relations: state.relations,
|
||||
availableCollections,
|
||||
|
||||
@@ -103,6 +103,40 @@
|
||||
<v-icon name="arrow_forward" class="arrow" />
|
||||
</div>
|
||||
|
||||
<div class="sort-field">
|
||||
<v-divider large :inline-title="false">{{ $t('sort_field') }}</v-divider>
|
||||
|
||||
<v-input
|
||||
:class="{ matches: sortFieldExists }"
|
||||
v-model="relations[0].sort_field"
|
||||
:nullable="false"
|
||||
:placeholder="$t('add_sort_field') + '...'"
|
||||
db-safe
|
||||
>
|
||||
<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 class="monospace">
|
||||
<v-list-item
|
||||
v-for="item in fields"
|
||||
:key="item.value"
|
||||
:active="relations[0].sort_field === item.value"
|
||||
:disabled="item.disabled"
|
||||
@click="relations[0].sort_field = item.value"
|
||||
>
|
||||
<v-list-item-content>
|
||||
{{ item.text }}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-input>
|
||||
</div>
|
||||
|
||||
<v-notice class="generated-data" v-if="generationInfo.length > 0" type="warning">
|
||||
<span>
|
||||
{{ $t('new_data_alert') }}
|
||||
@@ -110,7 +144,7 @@
|
||||
<ul>
|
||||
<li v-for="(data, index) in generationInfo" :key="index">
|
||||
<span class="field-name">{{ data.name }}</span>
|
||||
({{ $t(data.isField ? 'new_field' : 'new_collection') }})
|
||||
({{ $t(data.type === 'field' ? 'new_field' : 'new_collection') }})
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
@@ -119,13 +153,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import { Relation, Field } from '@/types';
|
||||
import useSync from '@/composables/use-sync';
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import { Field } from '@/types';
|
||||
import { useFieldsStore, useCollectionsStore } from '@/stores';
|
||||
import { orderBy } from 'lodash';
|
||||
import i18n from '@/lang';
|
||||
import { state } from '../store';
|
||||
import { state, generationInfo } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -142,7 +175,7 @@ export default defineComponent({
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
setup(props) {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
@@ -167,22 +200,9 @@ export default defineComponent({
|
||||
return !!fieldsStore.getField(state.relations[0].many_collection, state.relations[0].many_field);
|
||||
});
|
||||
|
||||
const generationInfo = computed(() => {
|
||||
const message: { name: string; isField: boolean }[] = [];
|
||||
|
||||
if (state.relations[0].many_collection !== '') {
|
||||
if (relatedCollectionExists.value === false)
|
||||
message.push({ name: state.relations[0].many_collection, isField: false });
|
||||
|
||||
if (relatedFieldExists.value === false && state.relations[0].many_field !== '') {
|
||||
message.push({
|
||||
name: state.relations[0].many_collection + '.' + state.relations[0].many_field,
|
||||
isField: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
const sortFieldExists = computed(() => {
|
||||
if (!state?.relations?.[0].many_collection || !state?.relations?.[0].sort_field) return false;
|
||||
return !!fieldsStore.getField(state.relations[0].many_collection, state.relations[0].sort_field);
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -197,6 +217,7 @@ export default defineComponent({
|
||||
relatedCollectionExists,
|
||||
relatedFieldExists,
|
||||
generationInfo,
|
||||
sortFieldExists,
|
||||
};
|
||||
|
||||
function useRelation() {
|
||||
@@ -355,10 +376,6 @@ export default defineComponent({
|
||||
gap: 12px 32px;
|
||||
margin-top: 48px;
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.v-icon.arrow {
|
||||
--v-icon-color: var(--primary);
|
||||
|
||||
@@ -369,6 +386,10 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.v-input.matches {
|
||||
--v-input-color: var(--primary);
|
||||
}
|
||||
|
||||
.v-list {
|
||||
--v-list-item-content-font-family: var(--family-monospace);
|
||||
}
|
||||
@@ -414,4 +435,13 @@ export default defineComponent({
|
||||
font-family: var(--family-monospace);
|
||||
}
|
||||
}
|
||||
|
||||
.sort-field {
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
|
||||
.v-divider {
|
||||
margin-top: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,11 +19,17 @@ const fieldsStore = useFieldsStore();
|
||||
const relationsStore = useRelationsStore();
|
||||
const collectionsStore = useCollectionsStore();
|
||||
|
||||
type GenerationInfo = {
|
||||
name: string;
|
||||
type: 'collection' | 'field';
|
||||
};
|
||||
|
||||
let state: any;
|
||||
let availableInterfaces: ComputedRef<InterfaceConfig[]>;
|
||||
let availableDisplays: ComputedRef<DisplayConfig[]>;
|
||||
let generationInfo: ComputedRef<GenerationInfo[]>;
|
||||
|
||||
export { state, availableInterfaces, availableDisplays, initLocalStore, clearLocalStore };
|
||||
export { state, availableInterfaces, availableDisplays, generationInfo, initLocalStore, clearLocalStore };
|
||||
|
||||
function initLocalStore(collection: string, field: string, type: typeof localTypes[number]) {
|
||||
const interfaces = getInterfaces();
|
||||
@@ -85,6 +91,28 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
.sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||
});
|
||||
|
||||
generationInfo = computed(() => {
|
||||
return [
|
||||
...state.newCollections.map((newCollection: any) => ({
|
||||
name: newCollection.collection,
|
||||
type: 'collection',
|
||||
})),
|
||||
...state.newCollections
|
||||
.map((newCollection: any) =>
|
||||
newCollection.fields.map((field: any) => ({ ...field, collection: newCollection.collection }))
|
||||
)
|
||||
.flat()
|
||||
.map((newField: any) => ({
|
||||
name: `${newField.collection}.${newField.field}`,
|
||||
type: 'field',
|
||||
})),
|
||||
...state.newFields.map((newField: any) => ({
|
||||
name: `${newField.collection}.${newField.field}`,
|
||||
type: 'field',
|
||||
})),
|
||||
];
|
||||
});
|
||||
|
||||
const isExisting = field !== '+';
|
||||
|
||||
if (isExisting) {
|
||||
@@ -231,59 +259,58 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
delete state.fieldData.schema;
|
||||
state.fieldData.type = null;
|
||||
|
||||
const syncNewCollectionsO2M = throttle(() => {
|
||||
const collectionName = state.relations[0].many_collection;
|
||||
const fieldName = state.relations[0].many_field;
|
||||
const syncNewCollectionsO2M = throttle(([collectionName, fieldName, sortField]) => {
|
||||
state.newCollections = state.newCollections.filter((col: any) => ['related'].includes(col.$type) === false);
|
||||
|
||||
if (collectionExists(collectionName)) {
|
||||
state.newCollections = [];
|
||||
} else {
|
||||
state.newCollections = [
|
||||
{
|
||||
collection: collectionName,
|
||||
fields: [
|
||||
{
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
is_primary_key: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
state.newFields = state.newFields.filter(
|
||||
(field: Partial<Field> & { $type: string }) => ['manyRelated', 'sort'].includes(field.$type) === false
|
||||
);
|
||||
|
||||
if (collectionExists(collectionName) === false) {
|
||||
state.newCollections.push({
|
||||
$type: 'related',
|
||||
collection: collectionName,
|
||||
fields: [
|
||||
{
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
is_primary_key: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
state.relations[0].many_primary = 'id';
|
||||
}
|
||||
|
||||
if (collectionExists(collectionName)) {
|
||||
if (fieldExists(collectionName, fieldName)) {
|
||||
state.newFields = [];
|
||||
} else {
|
||||
state.newFields = [
|
||||
{
|
||||
$type: 'manyRelated',
|
||||
collection: collectionName,
|
||||
field: fieldName,
|
||||
type: fieldsStore.getPrimaryKeyFieldForCollection(collection)?.type,
|
||||
schema: {},
|
||||
},
|
||||
];
|
||||
}
|
||||
} else {
|
||||
state.newFields = [
|
||||
{
|
||||
$type: 'manyRelated',
|
||||
collection: collectionName,
|
||||
field: fieldName,
|
||||
type: 'integer',
|
||||
schema: {},
|
||||
if (fieldExists(collectionName, fieldName) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: collectionName,
|
||||
field: fieldName,
|
||||
type: collectionExists(collectionName)
|
||||
? fieldsStore.getPrimaryKeyFieldForCollection(collectionName)?.type
|
||||
: 'integer',
|
||||
schema: {},
|
||||
});
|
||||
}
|
||||
|
||||
if (sortField && fieldExists(collectionName, sortField) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'sort',
|
||||
collection: collectionName,
|
||||
field: sortField,
|
||||
type: 'integer',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
}, 50);
|
||||
|
||||
@@ -321,134 +348,41 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
}
|
||||
);
|
||||
|
||||
watch([() => state.relations[0].many_collection, () => state.relations[0].many_field], syncNewCollectionsO2M);
|
||||
watch(
|
||||
[
|
||||
() => state.relations[0].many_collection,
|
||||
() => state.relations[0].many_field,
|
||||
() => state.relations[0].sort_field,
|
||||
],
|
||||
syncNewCollectionsO2M
|
||||
);
|
||||
}
|
||||
|
||||
function useM2M() {
|
||||
delete state.fieldData.schema;
|
||||
state.fieldData.type = null;
|
||||
|
||||
const syncNewCollectionsM2M = throttle(([junctionCollection, manyCurrent, manyRelated, relatedCollection]) => {
|
||||
state.newCollections = state.newCollections.filter(
|
||||
(col: any) => ['junction', 'related'].includes(col.$type) === false
|
||||
);
|
||||
state.newFields = state.newFields.filter(
|
||||
(field: Partial<Field> & { $type: string }) => ['manyCurrent', 'manyRelated'].includes(field.$type) === false
|
||||
);
|
||||
const syncNewCollectionsM2M = throttle(
|
||||
([junctionCollection, manyCurrent, manyRelated, relatedCollection, sortField]) => {
|
||||
state.newCollections = state.newCollections.filter(
|
||||
(col: any) => ['junction', 'related'].includes(col.$type) === false
|
||||
);
|
||||
state.newFields = state.newFields.filter(
|
||||
(field: Partial<Field> & { $type: string }) =>
|
||||
['manyCurrent', 'manyRelated', 'sort'].includes(field.$type) === false
|
||||
);
|
||||
|
||||
if (collectionExists(junctionCollection) === false) {
|
||||
state.newCollections.push({
|
||||
$type: 'junction',
|
||||
collection: junctionCollection,
|
||||
meta: {
|
||||
hidden: true,
|
||||
icon: 'import_export',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
state.relations[0].many_primary = 'id';
|
||||
state.relations[1].many_primary = 'id';
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyCurrent) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyCurrent',
|
||||
collection: junctionCollection,
|
||||
field: manyCurrent,
|
||||
type: fieldsStore.getPrimaryKeyFieldForCollection(collection)!.type,
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyRelated) === false) {
|
||||
if (type === 'translations') {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
type: collectionExists(relatedCollection)
|
||||
? fieldsStore.getPrimaryKeyFieldForCollection(relatedCollection)?.type
|
||||
: 'string',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
type: collectionExists(relatedCollection)
|
||||
? fieldsStore.getPrimaryKeyFieldForCollection(relatedCollection)?.type
|
||||
: 'integer',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (collectionExists(relatedCollection) === false) {
|
||||
if (type === 'translations') {
|
||||
if (collectionExists(junctionCollection) === false) {
|
||||
state.newCollections.push({
|
||||
$type: 'related',
|
||||
collection: relatedCollection,
|
||||
$type: 'junction',
|
||||
collection: junctionCollection,
|
||||
meta: {
|
||||
icon: 'translate',
|
||||
hidden: true,
|
||||
icon: 'import_export',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
field: state.relations[1].one_primary,
|
||||
type: 'string',
|
||||
schema: {
|
||||
is_primary_key: true,
|
||||
},
|
||||
meta: {
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
iconLeft: 'vpn_key',
|
||||
},
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
type: 'string',
|
||||
schema: {},
|
||||
meta: {
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
iconLeft: 'translate',
|
||||
},
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} else {
|
||||
state.newCollections.push({
|
||||
$type: 'related',
|
||||
collection: relatedCollection,
|
||||
fields: [
|
||||
{
|
||||
field: state.relations[1].one_primary,
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
@@ -459,48 +393,165 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'translations') {
|
||||
if (collectionExists(relatedCollection) === false) {
|
||||
state.newRows = {
|
||||
[relatedCollection]: [
|
||||
{
|
||||
code: 'en-US',
|
||||
name: 'English',
|
||||
},
|
||||
{
|
||||
code: 'de-DE',
|
||||
name: 'German',
|
||||
},
|
||||
{
|
||||
code: 'fr-FR',
|
||||
name: 'French',
|
||||
},
|
||||
{
|
||||
code: 'ru-RU',
|
||||
name: 'Russian',
|
||||
},
|
||||
{
|
||||
code: 'es-ES',
|
||||
name: 'Spanish',
|
||||
},
|
||||
{
|
||||
code: 'it-IT',
|
||||
name: 'Italian',
|
||||
},
|
||||
{
|
||||
code: 'pt-BR',
|
||||
name: 'Portuguese',
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
state.newRows = {};
|
||||
state.relations[0].many_primary = 'id';
|
||||
state.relations[1].many_primary = 'id';
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
|
||||
if (fieldExists(junctionCollection, manyCurrent) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyCurrent',
|
||||
collection: junctionCollection,
|
||||
field: manyCurrent,
|
||||
type: fieldsStore.getPrimaryKeyFieldForCollection(collection)!.type,
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyRelated) === false) {
|
||||
if (type === 'translations') {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
type: collectionExists(relatedCollection)
|
||||
? fieldsStore.getPrimaryKeyFieldForCollection(relatedCollection)?.type
|
||||
: 'string',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
type: collectionExists(relatedCollection)
|
||||
? fieldsStore.getPrimaryKeyFieldForCollection(relatedCollection)?.type
|
||||
: 'integer',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (collectionExists(relatedCollection) === false) {
|
||||
if (type === 'translations') {
|
||||
state.newCollections.push({
|
||||
$type: 'related',
|
||||
collection: relatedCollection,
|
||||
meta: {
|
||||
icon: 'translate',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
field: state.relations[1].one_primary,
|
||||
type: 'string',
|
||||
schema: {
|
||||
is_primary_key: true,
|
||||
},
|
||||
meta: {
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
iconLeft: 'vpn_key',
|
||||
},
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
type: 'string',
|
||||
schema: {},
|
||||
meta: {
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
iconLeft: 'translate',
|
||||
},
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} else {
|
||||
state.newCollections.push({
|
||||
$type: 'related',
|
||||
collection: relatedCollection,
|
||||
fields: [
|
||||
{
|
||||
field: state.relations[1].one_primary,
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'translations') {
|
||||
if (collectionExists(relatedCollection) === false) {
|
||||
state.newRows = {
|
||||
[relatedCollection]: [
|
||||
{
|
||||
code: 'en-US',
|
||||
name: 'English',
|
||||
},
|
||||
{
|
||||
code: 'de-DE',
|
||||
name: 'German',
|
||||
},
|
||||
{
|
||||
code: 'fr-FR',
|
||||
name: 'French',
|
||||
},
|
||||
{
|
||||
code: 'ru-RU',
|
||||
name: 'Russian',
|
||||
},
|
||||
{
|
||||
code: 'es-ES',
|
||||
name: 'Spanish',
|
||||
},
|
||||
{
|
||||
code: 'it-IT',
|
||||
name: 'Italian',
|
||||
},
|
||||
{
|
||||
code: 'pt-BR',
|
||||
name: 'Portuguese',
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
state.newRows = {};
|
||||
}
|
||||
}
|
||||
|
||||
if (sortField && fieldExists(junctionCollection, sortField) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'sort',
|
||||
collection: junctionCollection,
|
||||
field: sortField,
|
||||
type: 'integer',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
50
|
||||
);
|
||||
|
||||
if (!isExisting) {
|
||||
state.fieldData.meta.special = [type];
|
||||
@@ -567,6 +618,7 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
() => state.relations[0].many_field,
|
||||
() => state.relations[1].many_field,
|
||||
() => state.relations[1].one_collection,
|
||||
() => state.relations[0].sort_field,
|
||||
],
|
||||
syncNewCollectionsM2M
|
||||
);
|
||||
@@ -691,83 +743,99 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
delete state.fieldData.schema;
|
||||
state.fieldData.type = null;
|
||||
|
||||
const syncNewCollectionsM2A = throttle(([junctionCollection, manyCurrent, manyRelated, oneCollectionField]) => {
|
||||
state.newCollections = state.newCollections.filter(
|
||||
(col: any) => ['junction', 'related'].includes(col.$type) === false
|
||||
);
|
||||
const syncNewCollectionsM2A = throttle(
|
||||
([junctionCollection, manyCurrent, manyRelated, oneCollectionField, sortField]) => {
|
||||
state.newCollections = state.newCollections.filter(
|
||||
(col: any) => ['junction', 'related'].includes(col.$type) === false
|
||||
);
|
||||
|
||||
state.newFields = state.newFields.filter(
|
||||
(field: Partial<Field> & { $type: string }) =>
|
||||
['manyCurrent', 'manyRelated', 'collectionField'].includes(field.$type) === false
|
||||
);
|
||||
state.newFields = state.newFields.filter(
|
||||
(field: Partial<Field> & { $type: string }) =>
|
||||
['manyCurrent', 'manyRelated', 'collectionField', 'sort'].includes(field.$type) === false
|
||||
);
|
||||
|
||||
if (collectionExists(junctionCollection) === false) {
|
||||
state.newCollections.push({
|
||||
$type: 'junction',
|
||||
collection: junctionCollection,
|
||||
meta: {
|
||||
hidden: true,
|
||||
icon: 'import_export',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
if (collectionExists(junctionCollection) === false) {
|
||||
state.newCollections.push({
|
||||
$type: 'junction',
|
||||
collection: junctionCollection,
|
||||
meta: {
|
||||
hidden: true,
|
||||
icon: 'import_export',
|
||||
},
|
||||
],
|
||||
});
|
||||
fields: [
|
||||
{
|
||||
field: 'id',
|
||||
type: 'integer',
|
||||
schema: {
|
||||
has_auto_increment: true,
|
||||
},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
state.relations[0].many_primary = 'id';
|
||||
state.relations[1].many_primary = 'id';
|
||||
}
|
||||
state.relations[0].many_primary = 'id';
|
||||
state.relations[1].many_primary = 'id';
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyCurrent) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyCurrent',
|
||||
collection: junctionCollection,
|
||||
field: manyCurrent,
|
||||
type: fieldsStore.getPrimaryKeyFieldForCollection(collection)!.type,
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (fieldExists(junctionCollection, manyCurrent) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyCurrent',
|
||||
collection: junctionCollection,
|
||||
field: manyCurrent,
|
||||
type: fieldsStore.getPrimaryKeyFieldForCollection(collection)!.type,
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, manyRelated) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
// We'll have to save the foreign key as a string, as that's the only way to safely
|
||||
// be able to store the PK of multiple typed collections
|
||||
type: 'string',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (fieldExists(junctionCollection, manyRelated) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'manyRelated',
|
||||
collection: junctionCollection,
|
||||
field: manyRelated,
|
||||
// We'll have to save the foreign key as a string, as that's the only way to safely
|
||||
// be able to store the PK of multiple typed collections
|
||||
type: 'string',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldExists(junctionCollection, oneCollectionField) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'collectionField',
|
||||
collection: junctionCollection,
|
||||
field: oneCollectionField,
|
||||
type: 'string', // directus_collections.collection is a string
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, 50);
|
||||
if (fieldExists(junctionCollection, oneCollectionField) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'collectionField',
|
||||
collection: junctionCollection,
|
||||
field: oneCollectionField,
|
||||
type: 'string', // directus_collections.collection is a string
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (sortField && fieldExists(junctionCollection, sortField) === false) {
|
||||
state.newFields.push({
|
||||
$type: 'sort',
|
||||
collection: junctionCollection,
|
||||
field: sortField,
|
||||
type: 'integer',
|
||||
schema: {},
|
||||
meta: {
|
||||
hidden: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
50
|
||||
);
|
||||
|
||||
if (!isExisting) {
|
||||
state.fieldData.meta.special = [type];
|
||||
@@ -825,6 +893,7 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
() => state.relations[0].many_field,
|
||||
() => state.relations[1].many_field,
|
||||
() => state.relations[1].one_collection_field,
|
||||
() => state.relations[0].sort_field,
|
||||
],
|
||||
syncNewCollectionsM2A
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@ export type Relation = {
|
||||
one_field: null | string;
|
||||
one_primary: string;
|
||||
junction_field: null | string;
|
||||
sort_field: null | string;
|
||||
one_collection_field: null | string;
|
||||
one_allowed_collections: null | string[];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user