Show fields inside groups correctly in display templates for relational interfaces (#13187)

* added a tree with the groups filtered out for rendering the display templates

* don't walk the tree unnecessarily

* fix for groups after nested relations as often seen in M2M

* moved the tree function to utils and updated references

* [WIP] writing tests for the flatten-field-groups utility

* tests for the flatten-field-groups utility
This commit is contained in:
Brainslug
2022-06-07 21:46:21 +02:00
committed by GitHub
parent 694c664401
commit e5466a1e12
3 changed files with 149 additions and 2 deletions

View File

@@ -29,11 +29,12 @@
</template>
<script lang="ts">
import { defineComponent, toRefs, ref, watch, onMounted, onUnmounted, PropType } from 'vue';
import { defineComponent, toRefs, ref, watch, onMounted, onUnmounted, PropType, computed } from 'vue';
import FieldListItem from './field-list-item.vue';
import { FieldTree } from './types';
import { Field, Relation } from '@directus/shared/types';
import { useFieldTree } from '@/composables/use-field-tree';
import { flattenFieldGroups } from '@/utils/flatten-field-groups';
export default defineComponent({
components: { FieldListItem },
@@ -78,6 +79,10 @@ export default defineComponent({
watch(() => props.modelValue, setContent, { immediate: true });
const grouplessTree = computed(() => {
return flattenFieldGroups(treeList.value);
});
onMounted(() => {
if (contentEl.value) {
contentEl.value.addEventListener('selectstart', onSelect);
@@ -279,7 +284,7 @@ export default defineComponent({
loadFieldRelations(fieldPath.slice(0, i).join('.'));
}
const field = findTree(treeList.value, fieldPath);
const field = findTree(grouplessTree.value, fieldPath);
if (!field) return '';

View File

@@ -0,0 +1,20 @@
import { FieldNode } from '@/composables/use-field-tree';
/**
* Returns the given tree without FieldNodes that have the "group" flag set.
*/
export function flattenFieldGroups(tree: FieldNode[]): FieldNode[] {
function flattenGroups(list: FieldNode[]): FieldNode[] {
return list.flatMap((item: FieldNode) => {
if (Array.isArray(item.children) && item.children.length > 0) {
if (item.group === true) {
return flattenGroups(item.children);
} else {
item.children = flattenGroups(item.children);
}
}
return item;
});
}
return flattenGroups(tree);
}

View File

@@ -0,0 +1,122 @@
import { flattenFieldGroups } from '../../src/utils/flatten-field-groups';
import { FieldNode } from '@/composables/use-field-tree';
describe('utils/flatten-field-groups', () => {
it('Returns the original tree when no groups are present', () => {
const TreeWithoutGroups: FieldNode[] = [
{ name: 'ID', field: 'id', collection: 'test', key: 'id', path: 'id', type: 'integer' },
{ name: 'Test Field', field: 'test', collection: 'test', key: 'test', path: 'test', type: 'string' },
];
expect(flattenFieldGroups(TreeWithoutGroups)).toEqual(TreeWithoutGroups);
});
it('Returns a tree without groups', () => {
const TreeWithGroups: FieldNode[] = [
{ name: 'ID', field: 'id', collection: 'test', key: 'id', path: 'id', type: 'integer' },
{
name: 'Group',
field: 'group',
collection: 'test',
key: '',
path: 'group',
group: true,
type: 'alias',
children: [
{
name: 'Nested Field',
field: 'nested_field',
collection: 'test',
key: 'nested_field',
path: 'group.nested_field',
type: 'string',
},
],
},
];
const TreeWithoutGroups: FieldNode[] = [
{ name: 'ID', field: 'id', collection: 'test', key: 'id', path: 'id', type: 'integer' },
{
name: 'Nested Field',
field: 'nested_field',
collection: 'test',
key: 'nested_field',
path: 'group.nested_field',
type: 'string',
},
];
expect(flattenFieldGroups(TreeWithGroups)).toEqual(TreeWithoutGroups);
});
it('Returns a tree without deeply nested groups', () => {
const TreeWithNestedGroups: FieldNode[] = [
{ name: 'ID', field: 'id', collection: 'test', key: 'id', path: 'id', type: 'integer' },
{
name: 'Group',
field: 'group1',
collection: 'test',
key: '',
path: 'group1',
group: true,
type: 'alias',
children: [
{
name: 'Group',
field: 'group2',
collection: 'test',
key: '',
path: 'group2',
group: true,
type: 'alias',
children: [
{
name: 'Nested Field 1',
field: 'nested_field_1',
collection: 'test',
key: 'nested_field',
path: 'group.nested_field_1',
type: 'string',
},
{
name: 'Group',
field: 'group3',
collection: 'test',
key: '',
path: 'group3',
group: true,
type: 'alias',
children: [
{
name: 'Nested Field 2',
field: 'nested_field_2',
collection: 'test',
key: 'nested_field',
path: 'group.nested_field_2',
type: 'string',
},
],
},
],
},
],
},
];
const TreeWithoutGroups: FieldNode[] = [
{ name: 'ID', field: 'id', collection: 'test', key: 'id', path: 'id', type: 'integer' },
{
name: 'Nested Field 1',
field: 'nested_field_1',
collection: 'test',
key: 'nested_field',
path: 'group.nested_field_1',
type: 'string',
},
{
name: 'Nested Field 2',
field: 'nested_field_2',
collection: 'test',
key: 'nested_field',
path: 'group.nested_field_2',
type: 'string',
},
];
expect(flattenFieldGroups(TreeWithNestedGroups)).toEqual(TreeWithoutGroups);
});
});