mirror of
https://github.com/directus/directus.git
synced 2026-01-30 12:08:14 -05:00
Various changes and fixes
This commit is contained in:
@@ -18,19 +18,21 @@ export function useCollection(collection: Ref<string>) {
|
||||
const primaryKeyField = computed(() => {
|
||||
// Every collection has a primary key; rules of the land
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return fields.value?.find((field) => field.collection === collection.value && field.primary_key === true)!;
|
||||
return fields.value?.find(
|
||||
(field) => field.collection === collection.value && field.database.is_primary_key === true
|
||||
)!;
|
||||
});
|
||||
|
||||
const userCreatedField = computed(() => {
|
||||
return fields.value?.find((field) => field.type === 'user_created') || null;
|
||||
return fields.value?.find((field) => field.system?.special === 'user_created') || null;
|
||||
});
|
||||
|
||||
const statusField = computed(() => {
|
||||
return fields.value?.find((field) => field.type === 'status') || null;
|
||||
return fields.value?.find((field) => field.system?.special === 'status') || null;
|
||||
});
|
||||
|
||||
const sortField = computed(() => {
|
||||
return fields.value?.find((field) => field.type === 'sort') || null;
|
||||
return fields.value?.find((field) => field.system?.special === 'sort') || null;
|
||||
});
|
||||
|
||||
type Status = {
|
||||
@@ -48,7 +50,7 @@ export function useCollection(collection: Ref<string>) {
|
||||
const softDeleteStatus = computed<string | null>(() => {
|
||||
if (statusField.value === null) return null;
|
||||
|
||||
const statuses = Object.values(statusField.value?.options?.status_mapping || {});
|
||||
const statuses = Object.values(statusField.value?.system?.options?.status_mapping || {});
|
||||
return (
|
||||
(statuses.find((status) => (status as Status).soft_delete === true) as Status | undefined)?.value || null
|
||||
);
|
||||
|
||||
@@ -12,7 +12,10 @@ export default function useFieldTree(collection: Ref<string>) {
|
||||
const tree = computed<FieldTree[]>(() => {
|
||||
return fieldsStore
|
||||
.getFieldsForCollection(collection.value)
|
||||
.filter((field: Field) => field.hidden_browse === false && field.type.toLowerCase() !== 'alias')
|
||||
.filter(
|
||||
(field: Field) =>
|
||||
field.system?.hidden_browse === false && field.system?.special?.toLowerCase() !== 'alias'
|
||||
)
|
||||
.map((field: Field) => parseField(field, []));
|
||||
|
||||
function parseField(field: Field, parents: Field[]) {
|
||||
@@ -40,7 +43,9 @@ export default function useFieldTree(collection: Ref<string>) {
|
||||
return fieldsStore
|
||||
.getFieldsForCollection(relatedCollection)
|
||||
.filter(
|
||||
(field: Field) => field.hidden_browse === false && field.type.toLowerCase() !== 'alias'
|
||||
(field: Field) =>
|
||||
field.system?.hidden_browse === false &&
|
||||
field.system?.special?.toLowerCase() !== 'alias'
|
||||
);
|
||||
})
|
||||
.flat()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import { computed, Ref } from '@vue/composition-api';
|
||||
import { isEmpty } from '@/utils/is-empty';
|
||||
import getDefaultInterfaceForType from '@/utils/get-default-interface-for-type';
|
||||
@@ -14,37 +16,36 @@ export default function useFormFields(fields: Ref<Field[]>) {
|
||||
*
|
||||
* This can be optimized by combining a bunch of these maps and filters
|
||||
*/
|
||||
|
||||
// Filter out the fields that are marked hidden on detail
|
||||
formFields = formFields.filter((field) => {
|
||||
const hiddenDetail = field.hidden_detail;
|
||||
const hiddenDetail = field.system?.hidden_detail;
|
||||
if (isEmpty(hiddenDetail)) return true;
|
||||
return hiddenDetail === false;
|
||||
});
|
||||
|
||||
// Sort the fields on the sort column value
|
||||
formFields = formFields.sort((a, b) => {
|
||||
if (a.sort == b.sort) return 0;
|
||||
if (a.sort === null || a.sort === undefined) return 1;
|
||||
if (b.sort === null || b.sort === undefined) return -1;
|
||||
return a.sort > b.sort ? 1 : -1;
|
||||
if (a.system!.sort == b.system!.sort) return 0;
|
||||
if (a.system!.sort === null || a.system!.sort === undefined) return 1;
|
||||
if (b.system!.sort === null || b.system!.sort === undefined) return -1;
|
||||
return a.system!.sort > b.system!.sort ? 1 : -1;
|
||||
});
|
||||
|
||||
// Make sure all form fields have a width associated with it
|
||||
formFields = formFields.map((field) => {
|
||||
if (!field.width) {
|
||||
field.width = 'full';
|
||||
if (!field.system!.width) {
|
||||
field.system!.width = 'full';
|
||||
}
|
||||
|
||||
return field;
|
||||
});
|
||||
|
||||
formFields = formFields.map((field) => {
|
||||
const interfaceUsed = interfaces.find((int) => int.id === field.interface);
|
||||
const interfaceUsed = interfaces.find((int) => int.id === field.system!.interface);
|
||||
const interfaceExists = interfaceUsed !== undefined;
|
||||
|
||||
if (interfaceExists === false) {
|
||||
field.interface = getDefaultInterfaceForType(field.type);
|
||||
field.system!.interface = getDefaultInterfaceForType(field.system!.type);
|
||||
}
|
||||
|
||||
if (interfaceUsed?.hideLabel === true) {
|
||||
@@ -63,11 +64,11 @@ export default function useFormFields(fields: Ref<Field[]>) {
|
||||
formFields = formFields.map((field, index, formFields) => {
|
||||
if (index === 0) return field;
|
||||
|
||||
if (field.width === 'half') {
|
||||
if (field.system!.width === 'half') {
|
||||
const prevField = formFields[index - 1];
|
||||
|
||||
if (prevField.width === 'half') {
|
||||
field.width = 'half-right';
|
||||
if (prevField.system!.width === 'half') {
|
||||
field.system!.width = 'half-right';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ export default defineComponent({
|
||||
const { info, primaryKeyField, fields: fieldsInCollection, sortField } = useCollection(collection);
|
||||
|
||||
const availableFields = computed(() =>
|
||||
fieldsInCollection.value.filter(({ hidden_browse }) => hidden_browse === false)
|
||||
fieldsInCollection.value.filter((field) => field.system?.hidden_browse === false)
|
||||
);
|
||||
|
||||
const { sort, limit, page, fields, fieldsWithRelational } = useItemOptions();
|
||||
|
||||
@@ -14,11 +14,11 @@ export function defineModule(config: ModuleDefineParam | ((context: ModuleContex
|
||||
if (options.routes !== undefined) {
|
||||
options.routes = options.routes.map((route) => {
|
||||
if (route.path) {
|
||||
route.path = `/:project/${options.id}${route.path}`;
|
||||
route.path = `/${options.id}${route.path}`;
|
||||
}
|
||||
|
||||
if (route.redirect) {
|
||||
route.redirect = `/:project/${options.id}${route.redirect}`;
|
||||
route.redirect = `/${options.id}${route.redirect}`;
|
||||
}
|
||||
|
||||
return route;
|
||||
|
||||
@@ -10,7 +10,7 @@ const moduleRoutes = modules
|
||||
replaceRoutes((routes) => insertBeforeProjectWildcard(routes, moduleRoutes));
|
||||
|
||||
export function insertBeforeProjectWildcard(currentRoutes: RouteConfig[], routesToBeAdded: RouteConfig[]) {
|
||||
// Find the index of the /:project/* route, so we can insert the module routes right above that
|
||||
const wildcardIndex = currentRoutes.findIndex((route) => route.path === '/:project/*');
|
||||
// Find the index of the /* route, so we can insert the module routes right above that
|
||||
const wildcardIndex = currentRoutes.findIndex((route) => route.path === '/*');
|
||||
return [...currentRoutes.slice(0, wildcardIndex), ...routesToBeAdded, ...currentRoutes.slice(wildcardIndex)];
|
||||
}
|
||||
|
||||
@@ -8,37 +8,57 @@ import formatTitle from '@directus/format-title';
|
||||
import notify from '@/utils/notify';
|
||||
import useRelationsStore from '@/stores/relations';
|
||||
import { Relation } from '@/stores/relations/types';
|
||||
import getLocalType from '@/utils/get-local-type';
|
||||
|
||||
const fakeFilesField: Field = {
|
||||
id: -1,
|
||||
collection: 'directus_files',
|
||||
field: '$file',
|
||||
database: null,
|
||||
name: i18n.t('file'),
|
||||
datatype: null,
|
||||
type: 'file',
|
||||
unique: false,
|
||||
primary_key: false,
|
||||
default_value: null,
|
||||
auto_increment: false,
|
||||
note: null,
|
||||
signed: false,
|
||||
sort: 0,
|
||||
interface: null,
|
||||
options: null,
|
||||
display: 'file',
|
||||
display_options: null,
|
||||
hidden_detail: true,
|
||||
hidden_browse: false,
|
||||
locked: true,
|
||||
required: false,
|
||||
translation: null,
|
||||
readonly: true,
|
||||
width: 'full',
|
||||
validation: null,
|
||||
group: null,
|
||||
length: null,
|
||||
type: 'integer',
|
||||
system: {
|
||||
id: -1,
|
||||
collection: 'directus_files',
|
||||
field: '$file',
|
||||
sort: null,
|
||||
special: null,
|
||||
interface: null,
|
||||
options: null,
|
||||
display: 'file',
|
||||
display_options: null,
|
||||
hidden_detail: true,
|
||||
hidden_browse: false,
|
||||
locked: true,
|
||||
required: false,
|
||||
translation: null,
|
||||
readonly: true,
|
||||
width: 'full',
|
||||
group: null,
|
||||
},
|
||||
};
|
||||
|
||||
function getSystemDefault(collection: string, field: string): Field['system'] {
|
||||
return {
|
||||
id: -1,
|
||||
collection,
|
||||
field,
|
||||
group: null,
|
||||
hidden_browse: false,
|
||||
hidden_detail: false,
|
||||
interface: null,
|
||||
display: null,
|
||||
display_options: null,
|
||||
locked: false,
|
||||
options: null,
|
||||
readonly: false,
|
||||
required: false,
|
||||
sort: null,
|
||||
special: null,
|
||||
translation: null,
|
||||
width: 'full',
|
||||
};
|
||||
}
|
||||
|
||||
export const useFieldsStore = createStore({
|
||||
id: 'fieldsStore',
|
||||
state: () => ({
|
||||
@@ -62,17 +82,20 @@ export const useFieldsStore = createStore({
|
||||
* is a fake m2o to itself.
|
||||
*/
|
||||
|
||||
this.state.fields = [...fields.map(this.addTranslationsForField), fakeFilesField];
|
||||
this.state.fields = [...fields.map(this.parseField), fakeFilesField];
|
||||
},
|
||||
async dehydrate() {
|
||||
this.reset();
|
||||
},
|
||||
addTranslationsForField(field: Field) {
|
||||
parseField(field: FieldRaw): Field {
|
||||
let name: string | VueI18n.TranslateResult;
|
||||
|
||||
if (notEmpty(field.translation) && field.translation.length > 0) {
|
||||
for (let i = 0; i < field.translation.length; i++) {
|
||||
const { locale, translation } = field.translation[i];
|
||||
const type = field.database === null ? 'alias' : getLocalType(field.database.type);
|
||||
const system = field.system === null ? getSystemDefault(field.collection, field.field) : field.system;
|
||||
|
||||
if (notEmpty(system.translation) && system.translation.length > 0) {
|
||||
for (let i = 0; i < system.translation.length; i++) {
|
||||
const { locale, translation } = system.translation[i];
|
||||
|
||||
i18n.mergeLocaleMessage(locale, {
|
||||
fields: {
|
||||
@@ -89,6 +112,8 @@ export const useFieldsStore = createStore({
|
||||
return {
|
||||
...field,
|
||||
name,
|
||||
type,
|
||||
system,
|
||||
};
|
||||
},
|
||||
async createField(collectionKey: string, newField: Field) {
|
||||
@@ -247,7 +272,7 @@ export const useFieldsStore = createStore({
|
||||
/** @NOTE it's safe to assume every collection has a primary key */
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const primaryKeyField = this.state.fields.find(
|
||||
(field) => field.collection === collection && field.primary_key === true
|
||||
(field) => field.collection === collection && field.database?.is_primary_key === true
|
||||
);
|
||||
|
||||
return primaryKeyField;
|
||||
|
||||
@@ -7,98 +7,72 @@ type Translation = {
|
||||
|
||||
export type Width = 'half' | 'half-left' | 'half-right' | 'full' | 'fill';
|
||||
|
||||
export type Type =
|
||||
export type LocalType =
|
||||
| 'alias'
|
||||
| 'array'
|
||||
| 'boolean'
|
||||
| 'bigInteger'
|
||||
| 'binary'
|
||||
| 'datetime'
|
||||
| 'binary'
|
||||
| 'boolean'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'file'
|
||||
| 'files'
|
||||
| 'hash'
|
||||
| 'group'
|
||||
| 'integer'
|
||||
| 'datetime'
|
||||
| 'decimal'
|
||||
| 'json'
|
||||
| 'lang'
|
||||
| 'm2o'
|
||||
| 'o2m'
|
||||
| 'm2m'
|
||||
| 'slug'
|
||||
| 'sort'
|
||||
| 'status'
|
||||
| 'float'
|
||||
| 'integer'
|
||||
| 'string'
|
||||
| 'translation'
|
||||
| 'uuid'
|
||||
| 'datetime_created'
|
||||
| 'datetime_updated'
|
||||
| 'user_created'
|
||||
| 'user_updated'
|
||||
| 'user';
|
||||
| 'text'
|
||||
| 'time'
|
||||
| 'timestamp'
|
||||
| 'unknown';
|
||||
|
||||
export const types: Type[] = [
|
||||
'alias',
|
||||
'array',
|
||||
'boolean',
|
||||
'binary',
|
||||
'datetime',
|
||||
'date',
|
||||
'time',
|
||||
'file',
|
||||
'files',
|
||||
'hash',
|
||||
'group',
|
||||
'integer',
|
||||
'decimal',
|
||||
'json',
|
||||
'lang',
|
||||
'm2o',
|
||||
'o2m',
|
||||
'm2m',
|
||||
'slug',
|
||||
'sort',
|
||||
'status',
|
||||
'string',
|
||||
'translation',
|
||||
'uuid',
|
||||
'datetime_created',
|
||||
'datetime_updated',
|
||||
'user_created',
|
||||
'user_updated',
|
||||
'user',
|
||||
];
|
||||
export type DatabaseColumn = {
|
||||
/** @todo import this from knex-schema-inspector when that's launched */
|
||||
name: string;
|
||||
table: string;
|
||||
type: string;
|
||||
default_value: any | null;
|
||||
max_length: number | null;
|
||||
is_nullable: boolean;
|
||||
is_primary_key: boolean;
|
||||
has_auto_increment: boolean;
|
||||
foreign_key_column: string | null;
|
||||
foreign_key_table: string | null;
|
||||
comment: string | null;
|
||||
|
||||
export interface FieldRaw {
|
||||
// Postgres Only
|
||||
schema?: string;
|
||||
foreign_key_schema?: string | null;
|
||||
};
|
||||
|
||||
export type SystemField = {
|
||||
id: number;
|
||||
collection: string;
|
||||
field: string;
|
||||
datatype: string | null;
|
||||
unique: boolean;
|
||||
primary_key: boolean;
|
||||
auto_increment: boolean;
|
||||
default_value: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
note: string | TranslateResult | null;
|
||||
signed: boolean;
|
||||
type: Type;
|
||||
sort: null | number;
|
||||
interface: string | null;
|
||||
options: null | { [key: string]: any }; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
display: string | null;
|
||||
display_options: null | { [key: string]: any }; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
hidden_detail: boolean;
|
||||
hidden_browse: boolean;
|
||||
required: boolean;
|
||||
locked: boolean;
|
||||
translation: null | Translation[];
|
||||
readonly: boolean;
|
||||
width: null | Width;
|
||||
validation: string | null;
|
||||
group: number | null;
|
||||
length: string | number | null;
|
||||
hidden_browse: boolean;
|
||||
hidden_detail: boolean;
|
||||
locked: boolean;
|
||||
interface: string | null;
|
||||
display: string | null;
|
||||
options: null | Record<string, any>;
|
||||
display_options: null | Record<string, any>;
|
||||
readonly: boolean;
|
||||
required: boolean;
|
||||
sort: number | null;
|
||||
special: string | null;
|
||||
translation: null | Translation[];
|
||||
width: Width | null;
|
||||
};
|
||||
|
||||
export interface FieldRaw {
|
||||
collection: string;
|
||||
field: string;
|
||||
|
||||
database: DatabaseColumn | null;
|
||||
system: SystemField | null;
|
||||
}
|
||||
|
||||
export interface Field extends FieldRaw {
|
||||
name: string | TranslateResult;
|
||||
type: LocalType;
|
||||
system: SystemField;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ export default function adjustFieldsForDisplays(fields: readonly string[], paren
|
||||
const field: Field = fieldsStore.getField(parentCollection, fieldKey);
|
||||
|
||||
if (!field) return fieldKey;
|
||||
if (field.display === null) return fieldKey;
|
||||
if (field.system?.display === null) return fieldKey;
|
||||
|
||||
const display = displays.find((d) => d.id === field.display);
|
||||
const display = displays.find((d) => d.id === field.system?.display);
|
||||
|
||||
if (!display) return fieldKey;
|
||||
if (!display?.fields) return fieldKey;
|
||||
@@ -23,7 +23,7 @@ export default function adjustFieldsForDisplays(fields: readonly string[], paren
|
||||
|
||||
if (typeof display.fields === 'function') {
|
||||
return display
|
||||
.fields(field.display_options, {
|
||||
.fields(field.system?.display_options, {
|
||||
collection: field.collection,
|
||||
field: field.field,
|
||||
type: field.type,
|
||||
|
||||
87
src/utils/get-local-type/get-local-type.ts
Normal file
87
src/utils/get-local-type/get-local-type.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { LocalType } from '@/stores/fields/types';
|
||||
|
||||
/**
|
||||
* Typemap graciously provided by @gpetrov
|
||||
*/
|
||||
const localTypeMap: Record<string, { type: LocalType; useTz?: boolean }> = {
|
||||
// Shared
|
||||
boolean: { type: 'boolean' },
|
||||
tinyint: { type: 'boolean' },
|
||||
smallint: { type: 'integer' },
|
||||
mediumint: { type: 'integer' },
|
||||
int: { type: 'integer' },
|
||||
integer: { type: 'integer' },
|
||||
serial: { type: 'integer' },
|
||||
bigint: { type: 'bigInteger' },
|
||||
bigserial: { type: 'bigInteger' },
|
||||
clob: { type: 'text' },
|
||||
tinytext: { type: 'text' },
|
||||
mediumtext: { type: 'text' },
|
||||
longtext: { type: 'text' },
|
||||
text: { type: 'text' },
|
||||
varchar: { type: 'string' },
|
||||
longvarchar: { type: 'string' },
|
||||
varchar2: { type: 'string' },
|
||||
nvarchar: { type: 'string' },
|
||||
image: { type: 'binary' },
|
||||
ntext: { type: 'text' },
|
||||
char: { type: 'string' },
|
||||
date: { type: 'date' },
|
||||
datetime: { type: 'datetime' },
|
||||
timestamp: { type: 'timestamp' },
|
||||
time: { type: 'time' },
|
||||
float: { type: 'float' },
|
||||
double: { type: 'float' },
|
||||
'double precision': { type: 'float' },
|
||||
real: { type: 'float' },
|
||||
decimal: { type: 'decimal' },
|
||||
numeric: { type: 'integer' },
|
||||
|
||||
// MySQL
|
||||
string: { type: 'text' },
|
||||
year: { type: 'integer' },
|
||||
blob: { type: 'binary' },
|
||||
mediumblob: { type: 'binary' },
|
||||
|
||||
// MS SQL
|
||||
bit: { type: 'boolean' },
|
||||
smallmoney: { type: 'float' },
|
||||
money: { type: 'float' },
|
||||
datetimeoffset: { type: 'datetime', useTz: true },
|
||||
datetime2: { type: 'datetime' },
|
||||
smalldatetime: { type: 'datetime' },
|
||||
nchar: { type: 'text' },
|
||||
binary: { type: 'binary' },
|
||||
varbinary: { type: 'binary' },
|
||||
|
||||
// Postgres
|
||||
int2: { type: 'integer' },
|
||||
serial4: { type: 'integer' },
|
||||
int4: { type: 'integer' },
|
||||
serial8: { type: 'integer' },
|
||||
int8: { type: 'integer' },
|
||||
bool: { type: 'boolean' },
|
||||
'character varying': { type: 'string' },
|
||||
character: { type: 'string' },
|
||||
interval: { type: 'string' },
|
||||
_varchar: { type: 'string' },
|
||||
bpchar: { type: 'string' },
|
||||
timestamptz: { type: 'timestamp' },
|
||||
'timestamp with time zone': { type: 'timestamp', useTz: true },
|
||||
'timestamp without thime zone': { type: 'timestamp' },
|
||||
timetz: { type: 'time' },
|
||||
'time with time zone': { type: 'time', useTz: true },
|
||||
'time without time zone': { type: 'time' },
|
||||
float4: { type: 'float' },
|
||||
float8: { type: 'float' },
|
||||
};
|
||||
|
||||
export default function getLocalType(databaseType: string) {
|
||||
const type = localTypeMap[databaseType];
|
||||
|
||||
if (type) {
|
||||
return type.type;
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
4
src/utils/get-local-type/index.ts
Normal file
4
src/utils/get-local-type/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import getLocalType from './get-local-type';
|
||||
|
||||
export { getLocalType };
|
||||
export default getLocalType;
|
||||
@@ -72,7 +72,10 @@ export default defineComponent({
|
||||
const fieldTree = computed<FieldTree[]>(() => {
|
||||
return fieldsStore
|
||||
.getFieldsForCollection(props.collection)
|
||||
.filter((field: Field) => field.hidden_browse === false && field.type.toLowerCase() !== 'alias')
|
||||
.filter(
|
||||
(field: Field) =>
|
||||
field.system?.hidden_browse !== true && field.system?.special?.toLowerCase() !== 'alias'
|
||||
)
|
||||
.map((field: Field) => parseField(field, []));
|
||||
|
||||
function parseField(field: Field, parents: Field[]) {
|
||||
@@ -101,7 +104,8 @@ export default defineComponent({
|
||||
.getFieldsForCollection(relatedCollection)
|
||||
.filter(
|
||||
(field: Field) =>
|
||||
field.hidden_browse === false && field.type.toLowerCase() !== 'alias'
|
||||
field.system?.hidden_browse !== true &&
|
||||
field.system?.special?.toLowerCase() !== 'alias'
|
||||
);
|
||||
})
|
||||
.flat()
|
||||
|
||||
@@ -64,9 +64,9 @@ export default defineComponent({
|
||||
if (value === undefined) return '???';
|
||||
|
||||
// If no display is configured, we can render the raw value
|
||||
if (field.display === null) return value;
|
||||
if (field.system?.display === null) return value;
|
||||
|
||||
const displayInfo = displays.find((display) => display.id === field.display);
|
||||
const displayInfo = displays.find((display) => display.id === field.system?.display);
|
||||
|
||||
// If used display doesn't exist in the current project, return raw value
|
||||
if (!displayInfo) return value;
|
||||
@@ -74,16 +74,16 @@ export default defineComponent({
|
||||
// If the display handler is a function, we parse the value and return the result
|
||||
if (typeof displayInfo.handler === 'function') {
|
||||
const handler = displayInfo.handler as Function;
|
||||
return handler(value, field.display_options);
|
||||
return handler(value, field.system?.display_options);
|
||||
}
|
||||
|
||||
return {
|
||||
component: field.display,
|
||||
options: field.display_options,
|
||||
component: field.system?.display,
|
||||
options: field.system?.display_options,
|
||||
value: value,
|
||||
interface: field.interface,
|
||||
interfaceOptions: field.options,
|
||||
type: field.type,
|
||||
interface: field.system?.interface,
|
||||
interfaceOptions: field.system?.options,
|
||||
type: field.system?.special /** @todo check what this is used for */,
|
||||
};
|
||||
})
|
||||
.map((p) => p)
|
||||
|
||||
Reference in New Issue
Block a user