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 2177d2f663..c794009767 100644
--- a/app/src/components/v-field-select/v-field-select.vue
+++ b/app/src/components/v-field-select/v-field-select.vue
@@ -1,15 +1,16 @@
-
+
{{ field.name }}
{
- const fields: FieldTree[] = [];
- const stack: FieldTree[] = tree.value;
-
- while (stack.length > 0) {
- const field = stack.shift();
- if (field === undefined) continue;
- fields.push(field);
- if (field.children === undefined) continue;
- stack.push(...field.children);
- }
- return fields;
- });
-
- const activeFields = computed({
+ const selectedFields = computed({
get() {
- const list = _value.value.map((field) => fieldsInCollection.value.find((f) => f.field === field));
- const filteredList: Field[] = [];
- list.forEach((field) => {
- if (field !== undefined) filteredList.push(field);
- });
-
- return filteredList;
+ return props.value.map((field) => ({
+ field,
+ name: findTree(tree.value, field.split('.'))?.name as string,
+ }));
},
- set(newVal: Field[]) {
+ set(newVal: { field: string; name: string }[]) {
_value.value = newVal.map((field) => field.field);
},
});
const selectableFields = computed(() => {
- return fieldsInCollection.value.filter((field) => _value.value.includes(field.field) === false);
+ return filterTree(tree.value, (field, prefix) => props.value.includes(prefix + field.field) === false);
});
- return { tree, menuActive, addField, activeFields, removeField, selectableFields, hideDragImage };
+ return { menuActive, addField, removeField, selectableFields, selectedFields, hideDragImage, tree };
+
+ function findTree(tree: FieldTree[] | undefined, fieldSections: string[]): FieldTree | undefined {
+ if (tree === undefined) return undefined;
+
+ const fieldObject = tree.find((f) => f.field === fieldSections[0]);
+
+ if (fieldObject === undefined) return undefined;
+ if (fieldSections.length === 1) return fieldObject;
+ return findTree(fieldObject.children, fieldSections.slice(1));
+ }
+
+ function filterTree(
+ tree: FieldTree[] | undefined,
+ f: (field: FieldTree, prefix: string) => boolean,
+ prefix = ''
+ ) {
+ if (tree === undefined) return undefined;
+
+ const newTree: FieldTree[] = [];
+ tree.forEach((field) => {
+ if (f(field, prefix)) {
+ newTree.push({
+ field: field.field,
+ name: field.name,
+ children: filterTree(field.children, f, prefix + field.field + '.'),
+ });
+ }
+ });
+ return newTree.length === 0 ? undefined : newTree;
+ }
function removeField(field: string) {
_value.value = _value.value.filter((f) => f !== field);
@@ -126,7 +140,7 @@ export default defineComponent({
function addField(field: string) {
const newArray = _value.value;
newArray.push(field);
- _value.value = newArray;
+ _value.value = [...new Set(newArray)];
}
},
});
diff --git a/app/src/composables/use-field-tree/use-field-tree.ts b/app/src/composables/use-field-tree/use-field-tree.ts
index 63c17f1fc8..6c6c7c79c8 100644
--- a/app/src/composables/use-field-tree/use-field-tree.ts
+++ b/app/src/composables/use-field-tree/use-field-tree.ts
@@ -3,7 +3,7 @@ import { FieldTree } from './types';
import { useFieldsStore, useRelationsStore } from '@/stores/';
import { Field, Relation } from '@/types';
-export default function useFieldTree(collection: Ref) {
+export default function useFieldTree(collection: Ref, showHidden = false) {
const fieldsStore = useFieldsStore();
const relationsStore = useRelationsStore();
@@ -12,7 +12,8 @@ export default function useFieldTree(collection: Ref) {
.getFieldsForCollection(collection.value)
.filter(
(field: Field) =>
- field.meta?.hidden === false && (field.meta?.special || []).includes('alias') === false
+ showHidden ||
+ (field.meta?.hidden === false && (field.meta?.special || []).includes('alias') === false)
)
.map((field: Field) => parseField(field, []));
diff --git a/app/src/interfaces/many-to-many/options.vue b/app/src/interfaces/many-to-many/options.vue
index dfec9fd9a8..c23eef6076 100644
--- a/app/src/interfaces/many-to-many/options.vue
+++ b/app/src/interfaces/many-to-many/options.vue
@@ -12,6 +12,7 @@
import { Field } from '@/types';
import { defineComponent, PropType, computed } from '@vue/composition-api';
import { useRelationsStore } from '@/stores/';
+import { Relation } from '@/types';
export default defineComponent({
props: {
@@ -31,27 +32,26 @@ export default defineComponent({
get() {
return props.value?.fields;
},
- set(newTemplate: string) {
+ set(newFields: string) {
emit('input', {
...(props.value || {}),
- fields: newTemplate,
+ fields: newFields,
});
},
});
const collection = computed(() => {
if (props.fieldData.field == null || props.fieldData.meta?.collection == null) return null;
- const junction = relationsStore.getRelationsForField(
- props.fieldData.meta.collection,
- props.fieldData.field
- )?.[0];
- const relationData = relationsStore.getRelationsForField(
- junction.many_collection,
- junction.junction_field
- )?.[0];
+ const collection = props.fieldData.meta.collection;
+ const field = props.fieldData.field;
- return relationData.one_collection;
+ const relations: Relation[] = relationsStore.getRelationsForField(collection, field);
+
+ const junction = relations.find((r) => r.one_collection === collection && r.one_field === field);
+ if (junction === undefined) return null;
+
+ return junction.many_collection;
});
return { fields, collection };
diff --git a/app/src/interfaces/one-to-many/options.vue b/app/src/interfaces/one-to-many/options.vue
index bf6b800e1c..1ac74395b9 100644
--- a/app/src/interfaces/one-to-many/options.vue
+++ b/app/src/interfaces/one-to-many/options.vue
@@ -11,7 +11,7 @@