Assign sort number when creating field(s) (#18877)

Co-authored-by: Jan Arends <jan.arends@mailbox.org>
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
This commit is contained in:
Azri Kahar
2023-06-28 21:47:15 +08:00
committed by GitHub
parent 43e6038cb0
commit c80fa6d6b9
3 changed files with 40 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
'@directus/api': patch
---
Implemented sort number for fields in collections on creation to ensure order is always retained

View File

@@ -4,7 +4,7 @@ import type { Accountability, FieldMeta, RawField, SchemaOverview } from '@direc
import { addFieldFlag } from '@directus/utils';
import type Keyv from 'keyv';
import type { Knex } from 'knex';
import { chunk, omit } from 'lodash-es';
import { chunk, groupBy, merge, omit } from 'lodash-es';
import { clearSystemCache, getCache } from '../cache.js';
import { ALIAS_TYPES } from '../constants.js';
import type { Helpers } from '../database/helpers/index.js';
@@ -145,7 +145,30 @@ export class CollectionsService {
const fieldPayloads = payload.fields!.filter((field) => field.meta).map((field) => field.meta) as FieldMeta[];
await fieldItemsService.createMany(fieldPayloads, {
// Sort new fields that does not have any group defined, in ascending order.
// Lodash merge is used so that the "sort" can be overridden if defined.
let sortedFieldPayloads = fieldPayloads
.filter((field) => field?.group === undefined || field?.group === null)
.map((field, index) => merge({ sort: index + 1 }, field));
// Sort remaining new fields with group defined, if any, in ascending order.
// sortedFieldPayloads will be less than fieldPayloads if it filtered out any fields with group defined.
if (sortedFieldPayloads.length < fieldPayloads.length) {
const fieldsWithGroups = groupBy(
fieldPayloads.filter((field) => field?.group),
(field) => field?.group
);
// The sort order is restarted from 1 for fields in each group and appended to sortedFieldPayloads.
// Lodash merge is used so that the "sort" can be overridden if defined.
for (const [_group, fields] of Object.entries(fieldsWithGroups)) {
sortedFieldPayloads = sortedFieldPayloads.concat(
fields.map((field, index) => merge({ sort: index + 1 }, field))
);
}
}
await fieldItemsService.createMany(sortedFieldPayloads, {
bypassEmitAction: (params) =>
opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
bypassLimits: true,

View File

@@ -5,7 +5,7 @@ import type { Accountability, Field, FieldMeta, RawField, SchemaOverview, Type }
import { addFieldFlag, toArray } from '@directus/utils';
import type Keyv from 'keyv';
import type { Knex } from 'knex';
import { isEqual, isNil } from 'lodash-es';
import { isEqual, isNil, merge } from 'lodash-es';
import { clearSystemCache, getCache } from '../cache.js';
import { ALIAS_TYPES } from '../constants.js';
import { translateDatabaseError } from '../database/errors/translate.js';
@@ -308,9 +308,17 @@ export class FieldsService {
}
if (hookAdjustedField.meta) {
const existingSortRecord: Record<'max', number | null> | undefined = await trx
.from('directus_fields')
.where(hookAdjustedField.meta?.group ? { collection, group: hookAdjustedField.meta.group } : { collection })
.max('sort', { as: 'max' })
.first();
const newSortValue: number = existingSortRecord?.max ? existingSortRecord.max + 1 : 1;
await itemsService.createOne(
{
...hookAdjustedField.meta,
...merge({ sort: newSortValue }, hookAdjustedField.meta),
collection: collection,
field: hookAdjustedField.field,
},