diff --git a/app/src/components/v-field-select/v-field-select.vue b/app/src/components/v-field-select/v-field-select.vue index 77701171c4..bf22fba451 100644 --- a/app/src/components/v-field-select/v-field-select.vue +++ b/app/src/components/v-field-select/v-field-select.vue @@ -26,7 +26,7 @@ {{ field.name || formatTitle(field.field) }} , inject?: { fields: Field[]; relations: Relation[] }) { const fieldsStore = useFieldsStore(); const relationsStore = useRelationsStore(); - const tree = computed(() => { - return [...fieldsStore.getFieldsForCollection(collection.value), ...(inject?.fields || [])] + const tree = computed(() => parseLevel(collection.value, null)); + + return { tree }; + + function parseLevel(collection: string, parentPath: string | null, level = 0) { + const fieldsInLevel = cloneDeep(fieldsStore.getFieldsForCollection(collection)) .filter((field: Field) => { const shown = field.meta?.special?.includes('alias') !== true && field.meta?.special?.includes('no-data') !== true; return shown; }) - .map((field: Field) => parseField(field, [])); - - function parseField(field: Field, parents: Field[]) { - const fieldInfo: FieldTree = { - field: field.field, + .map((field: Field) => ({ name: field.name, - }; + field: field.field, + key: parentPath ? `${parentPath}.${field.field}` : field.field, + })); - if (parents.length === 2) { - return fieldInfo; + if (level >= 3) return fieldsInLevel; + + for (const field of fieldsInLevel) { + const relations = relationsStore.getRelationsForField(collection, field.field); + const relation = relations.find( + (relation: Relation) => + (relation.many_collection === collection && relation.many_field === field.field) || + (relation.one_collection === collection && relation.one_field === field.field) + ); + if (!relation) continue; + const relationType = getRelationType({ relation, collection, field: field.field }); + + if (relationType === 'm2o') { + field.children = parseLevel( + relation.one_collection, + parentPath ? `${parentPath}.${field.field}` : field.field, + level + 1 + ); } - - const relations = [ - ...relationsStore.getRelationsForField(field.collection, field.field), - ...(inject?.relations || []).filter( - (relation) => - (relation.many_collection === field.collection && relation.many_field === field.field) || - (relation.one_collection === field.collection && relation.one_field === field.field) - ), - ]; - - if (relations.length > 0) { - const relatedFields = relations - .map((relation: Relation) => { - const relatedCollection = - relation.many_collection === field.collection - ? relation.one_collection - : relation.many_collection; - - if (relation.junction_field === field.field) return []; - - return fieldsStore.getFieldsForCollection(relatedCollection).filter((field: Field) => { - const shown = - field.meta?.special?.includes('alias') !== true && - field.meta?.special?.includes('no-data') !== true; - return shown; - }); - }) - .flat() - .map((childField: Field) => parseField(childField, [...parents, field])); - - fieldInfo.children = relatedFields; - } - - return fieldInfo; } - }); - return { tree }; + return fieldsInLevel; + } + + // const tree = computed(() => { + // return [...fieldsStore.getFieldsForCollection(collection.value), ...(inject?.fields || [])] + // .filter((field: Field) => { + // const shown = + // field.meta?.special?.includes('alias') !== true && + // field.meta?.special?.includes('no-data') !== true; + // return shown; + // }) + // .map((field: Field) => parseField(field, [])); + + // function parseField(field: Field, parents: Field[]) { + // const fieldInfo: FieldTree = { + // field: field.field, + // name: field.name, + // }; + + // if (parents.length === 2) { + // return fieldInfo; + // } + + // const relations = [ + // ...relationsStore.getRelationsForField(field.collection, field.field), + // ...(inject?.relations || []).filter( + // (relation) => + // (relation.many_collection === field.collection && relation.many_field === field.field) || + // (relation.one_collection === field.collection && relation.one_field === field.field) + // ), + // ]; + + // if (relations.length > 0) { + // const relatedFields = relations + // .map((relation: Relation) => { + // const relatedCollection = + // relation.many_collection === field.collection + // ? relation.one_collection + // : relation.many_collection; + + // if (relation.junction_field === field.field) return []; + + // return fieldsStore.getFieldsForCollection(relatedCollection).filter((field: Field) => { + // const shown = + // field.meta?.special?.includes('alias') !== true && + // field.meta?.special?.includes('no-data') !== true; + // return shown; + // }); + // }) + // .flat() + // .map((childField: Field) => parseField(childField, [...parents, field])); + + // fieldInfo.children = relatedFields; + // } + + // return fieldInfo; + // } + // }); + + // return { tree }; } diff --git a/app/src/types/relations.ts b/app/src/types/relations.ts index 6858915df0..861c95b678 100644 --- a/app/src/types/relations.ts +++ b/app/src/types/relations.ts @@ -7,4 +7,6 @@ export type Relation = { one_field: null | string; one_primary: string; junction_field: null | string; + one_collection_field: null | string; + one_allowed_collections: null | string[]; }; diff --git a/app/src/utils/get-relation-type.ts b/app/src/utils/get-relation-type.ts new file mode 100644 index 0000000000..25f56ad479 --- /dev/null +++ b/app/src/utils/get-relation-type.ts @@ -0,0 +1,30 @@ +import { Relation } from '@/types'; + +export function getRelationType(getRelationOptions: { + relation: Relation; + collection: string | null; + field: string; +}): 'm2o' | 'o2m' | 'm2a' | null { + const { relation, collection, field } = getRelationOptions; + + if (!relation) return null; + + if ( + relation.many_collection === collection && + relation.many_field === field && + relation.one_collection_field && + relation.one_allowed_collections + ) { + return 'm2a'; + } + + if (relation.many_collection === collection && relation.many_field === field) { + return 'm2o'; + } + + if (relation.one_collection === collection && relation.one_field === field) { + return 'o2m'; + } + + return null; +}