Migrate to a monorepo structure (#2909)
This commit is contained in:
@ -0,0 +1,41 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType';
|
||||
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
|
||||
import { FieldMetadataItem } from '../types/FieldMetadataItem';
|
||||
|
||||
import { parseFieldType } from './parseFieldType';
|
||||
|
||||
export const formatFieldMetadataItemAsColumnDefinition = ({
|
||||
position,
|
||||
field,
|
||||
objectMetadataItem,
|
||||
}: {
|
||||
position: number;
|
||||
field: FieldMetadataItem;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}): ColumnDefinition<FieldMetadata> => {
|
||||
const relationObjectMetadataItem =
|
||||
field.toRelationMetadata?.fromObjectMetadata;
|
||||
|
||||
return {
|
||||
position,
|
||||
fieldMetadataId: field.id,
|
||||
label: field.label,
|
||||
size: 100,
|
||||
type: parseFieldType(field.type),
|
||||
metadata: {
|
||||
fieldName: field.name,
|
||||
placeHolder: field.label,
|
||||
relationType: parseFieldRelationType(field),
|
||||
relationObjectMetadataNameSingular:
|
||||
relationObjectMetadataItem?.nameSingular ?? '',
|
||||
relationObjectMetadataNamePlural:
|
||||
relationObjectMetadataItem?.namePlural ?? '',
|
||||
objectMetadataNameSingular: objectMetadataItem.nameSingular ?? '',
|
||||
},
|
||||
iconName: field.icon ?? 'Icon123',
|
||||
isVisible: true,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
import toCamelCase from 'lodash.camelcase';
|
||||
import toSnakeCase from 'lodash.snakecase';
|
||||
|
||||
import { Field } from '~/generated-metadata/graphql';
|
||||
|
||||
import { FieldMetadataOption } from '../types/FieldMetadataOption';
|
||||
|
||||
const getOptionValueFromLabel = (label: string) =>
|
||||
toSnakeCase(label.trim()).toUpperCase();
|
||||
|
||||
export const formatFieldMetadataItemInput = (
|
||||
input: Pick<Field, 'label' | 'icon' | 'description' | 'defaultValue'> & {
|
||||
options?: FieldMetadataOption[];
|
||||
},
|
||||
) => {
|
||||
const defaultOption = input.options?.find((option) => option.isDefault);
|
||||
|
||||
return {
|
||||
defaultValue: defaultOption
|
||||
? getOptionValueFromLabel(defaultOption.label)
|
||||
: undefined,
|
||||
description: input.description?.trim() ?? null,
|
||||
icon: input.icon,
|
||||
label: input.label.trim(),
|
||||
name: toCamelCase(input.label.trim()),
|
||||
options: input.options?.map((option, index) => ({
|
||||
color: option.color,
|
||||
id: option.id,
|
||||
label: option.label.trim(),
|
||||
position: index,
|
||||
value: getOptionValueFromLabel(option.label),
|
||||
})),
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,71 @@
|
||||
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||
|
||||
export const formatFieldMetadataItemsAsFilterDefinitions = ({
|
||||
fields,
|
||||
}: {
|
||||
fields: Array<ObjectMetadataItem['fields'][0]>;
|
||||
}): FilterDefinition[] =>
|
||||
fields.reduce((acc, field) => {
|
||||
if (
|
||||
![
|
||||
FieldMetadataType.DateTime,
|
||||
FieldMetadataType.Text,
|
||||
FieldMetadataType.Email,
|
||||
FieldMetadataType.Number,
|
||||
FieldMetadataType.Link,
|
||||
FieldMetadataType.FullName,
|
||||
FieldMetadataType.Relation,
|
||||
FieldMetadataType.Currency,
|
||||
].includes(field.type)
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
// Todo: remove once Rating fieldtype is implemented
|
||||
if (field.name === 'probability') {
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (field.type === FieldMetadataType.Relation) {
|
||||
if (field.fromRelationMetadata) {
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
|
||||
return [...acc, formatFieldMetadataItemAsFilterDefinition({ field })];
|
||||
}, [] as FilterDefinition[]);
|
||||
|
||||
const formatFieldMetadataItemAsFilterDefinition = ({
|
||||
field,
|
||||
}: {
|
||||
field: ObjectMetadataItem['fields'][0];
|
||||
}): FilterDefinition => ({
|
||||
fieldMetadataId: field.id,
|
||||
label: field.label,
|
||||
iconName: field.icon ?? 'Icon123',
|
||||
relationObjectMetadataNamePlural:
|
||||
field.toRelationMetadata?.fromObjectMetadata.namePlural,
|
||||
relationObjectMetadataNameSingular:
|
||||
field.toRelationMetadata?.fromObjectMetadata.nameSingular,
|
||||
type:
|
||||
field.type === FieldMetadataType.DateTime
|
||||
? 'DATE_TIME'
|
||||
: field.type === FieldMetadataType.Link
|
||||
? 'LINK'
|
||||
: field.type === FieldMetadataType.FullName
|
||||
? 'FULL_NAME'
|
||||
: field.type === FieldMetadataType.Number
|
||||
? 'NUMBER'
|
||||
: field.type === FieldMetadataType.Currency
|
||||
? 'CURRENCY'
|
||||
: field.type === FieldMetadataType.Email
|
||||
? 'TEXT'
|
||||
: field.type === FieldMetadataType.Phone
|
||||
? 'TEXT'
|
||||
: field.type === FieldMetadataType.Relation
|
||||
? 'RELATION'
|
||||
: 'TEXT',
|
||||
});
|
||||
@ -0,0 +1,31 @@
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||
|
||||
export const formatFieldMetadataItemsAsSortDefinitions = ({
|
||||
fields,
|
||||
}: {
|
||||
fields: Array<ObjectMetadataItem['fields'][0]>;
|
||||
}): SortDefinition[] =>
|
||||
fields.reduce((acc, field) => {
|
||||
if (
|
||||
![
|
||||
FieldMetadataType.DateTime,
|
||||
FieldMetadataType.Number,
|
||||
FieldMetadataType.Text,
|
||||
FieldMetadataType.Boolean,
|
||||
].includes(field.type)
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
fieldMetadataId: field.id,
|
||||
label: field.label,
|
||||
iconName: field.icon ?? 'Icon123',
|
||||
},
|
||||
];
|
||||
}, [] as SortDefinition[]);
|
||||
@ -0,0 +1,17 @@
|
||||
import toCamelCase from 'lodash.camelcase';
|
||||
|
||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||
|
||||
export const formatObjectMetadataItemInput = (
|
||||
input: Pick<
|
||||
ObjectMetadataItem,
|
||||
'labelPlural' | 'labelSingular' | 'icon' | 'description'
|
||||
>,
|
||||
) => ({
|
||||
description: input.description?.trim() ?? null,
|
||||
icon: input.icon,
|
||||
labelPlural: input.labelPlural.trim(),
|
||||
labelSingular: input.labelSingular.trim(),
|
||||
namePlural: toCamelCase(input.labelPlural.trim()),
|
||||
nameSingular: toCamelCase(input.labelSingular.trim()),
|
||||
});
|
||||
@ -0,0 +1,59 @@
|
||||
import { RelationType } from '@/settings/data-model/types/RelationType';
|
||||
import {
|
||||
CreateRelationInput,
|
||||
Field,
|
||||
RelationMetadataType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
import { formatFieldMetadataItemInput } from './formatFieldMetadataItemInput';
|
||||
|
||||
export type FormatRelationMetadataInputParams = {
|
||||
relationType: RelationType;
|
||||
field: Pick<Field, 'label' | 'icon' | 'description'>;
|
||||
objectMetadataId: string;
|
||||
connect: {
|
||||
field: Pick<Field, 'label' | 'icon'>;
|
||||
objectMetadataId: string;
|
||||
};
|
||||
};
|
||||
|
||||
export const formatRelationMetadataInput = (
|
||||
input: FormatRelationMetadataInputParams,
|
||||
): CreateRelationInput => {
|
||||
// /!\ MANY_TO_ONE does not exist on backend.
|
||||
// => Transform into ONE_TO_MANY and invert "from" and "to" data.
|
||||
const isManyToOne = input.relationType === 'MANY_TO_ONE';
|
||||
const relationType = isManyToOne
|
||||
? RelationMetadataType.OneToMany
|
||||
: (input.relationType as RelationMetadataType);
|
||||
const { field: fromField, objectMetadataId: fromObjectMetadataId } =
|
||||
isManyToOne ? input.connect : input;
|
||||
const { field: toField, objectMetadataId: toObjectMetadataId } = isManyToOne
|
||||
? input
|
||||
: input.connect;
|
||||
|
||||
const {
|
||||
description,
|
||||
icon: fromIcon,
|
||||
label: fromLabel,
|
||||
name: fromName,
|
||||
} = formatFieldMetadataItemInput(fromField);
|
||||
const {
|
||||
icon: toIcon,
|
||||
label: toLabel,
|
||||
name: toName,
|
||||
} = formatFieldMetadataItemInput(toField);
|
||||
|
||||
return {
|
||||
description,
|
||||
fromIcon,
|
||||
fromLabel,
|
||||
fromName,
|
||||
fromObjectMetadataId,
|
||||
relationType,
|
||||
toIcon,
|
||||
toLabel,
|
||||
toName,
|
||||
toObjectMetadataId,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
import toKebabCase from 'lodash.kebabcase';
|
||||
|
||||
import { Field } from '~/generated-metadata/graphql';
|
||||
|
||||
export const getFieldSlug = (metadataField: Pick<Field, 'label'>) =>
|
||||
toKebabCase(metadataField.label);
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
||||
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const getObjectOrderByField = (
|
||||
objectMetadataItem: ObjectMetadataItem,
|
||||
orderBy: OrderBy,
|
||||
): OrderByField => {
|
||||
const labelIdentifierFieldMetadata = objectMetadataItem.fields.find(
|
||||
(field) =>
|
||||
field.id === objectMetadataItem.labelIdentifierFieldMetadataId ||
|
||||
field.name === 'name',
|
||||
);
|
||||
|
||||
if (labelIdentifierFieldMetadata) {
|
||||
switch (labelIdentifierFieldMetadata.type) {
|
||||
case FieldMetadataType.FullName:
|
||||
return {
|
||||
[labelIdentifierFieldMetadata.name]: {
|
||||
firstName: orderBy,
|
||||
lastName: orderBy,
|
||||
},
|
||||
};
|
||||
default:
|
||||
return {
|
||||
[labelIdentifierFieldMetadata.name]: orderBy,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
createdAt: orderBy,
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
import toKebabCase from 'lodash.kebabcase';
|
||||
|
||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||
|
||||
export const getObjectSlug = (
|
||||
objectMetadataItem: Pick<ObjectMetadataItem, 'labelPlural'>,
|
||||
) => toKebabCase(objectMetadataItem.labelPlural);
|
||||
@ -0,0 +1,17 @@
|
||||
import { ObjectMetadataItemsQuery } from '~/generated-metadata/graphql';
|
||||
|
||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||
|
||||
export const mapPaginatedObjectMetadataItemsToObjectMetadataItems = ({
|
||||
pagedObjectMetadataItems,
|
||||
}: {
|
||||
pagedObjectMetadataItems: ObjectMetadataItemsQuery | undefined;
|
||||
}) => {
|
||||
const formattedObjects: ObjectMetadataItem[] =
|
||||
pagedObjectMetadataItems?.objects.edges.map((object) => ({
|
||||
...object.node,
|
||||
fields: object.node.fields.edges.map((field) => field.node),
|
||||
})) ?? [];
|
||||
|
||||
return formattedObjects;
|
||||
};
|
||||
@ -0,0 +1,51 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { FieldDefinitionRelationType } from '@/object-record/field/types/FieldDefinition';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationMetadataType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const parseFieldRelationType = (
|
||||
field: FieldMetadataItem | undefined,
|
||||
): FieldDefinitionRelationType | undefined => {
|
||||
if (!field || field.type !== FieldMetadataType.Relation) return;
|
||||
|
||||
const config: Record<
|
||||
RelationMetadataType,
|
||||
{ from: FieldDefinitionRelationType; to: FieldDefinitionRelationType }
|
||||
> = {
|
||||
[RelationMetadataType.ManyToMany]: {
|
||||
from: 'FROM_MANY_OBJECTS',
|
||||
to: 'TO_MANY_OBJECTS',
|
||||
},
|
||||
[RelationMetadataType.OneToMany]: {
|
||||
from: 'FROM_MANY_OBJECTS',
|
||||
to: 'TO_ONE_OBJECT',
|
||||
},
|
||||
[RelationMetadataType.OneToOne]: {
|
||||
from: 'FROM_ONE_OBJECT',
|
||||
to: 'TO_ONE_OBJECT',
|
||||
},
|
||||
};
|
||||
|
||||
if (
|
||||
isDefined(field.fromRelationMetadata) &&
|
||||
field.fromRelationMetadata.relationType in config
|
||||
) {
|
||||
return config[field.fromRelationMetadata.relationType].from;
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(field.toRelationMetadata) &&
|
||||
field.toRelationMetadata.relationType in config
|
||||
) {
|
||||
return config[field.toRelationMetadata.relationType].to;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Cannot determine field relation type for field : ${JSON.stringify(
|
||||
field,
|
||||
)}.`,
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
import { FieldType } from '@/object-record/field/types/FieldType';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const parseFieldType = (fieldType: FieldMetadataType): FieldType => {
|
||||
if (fieldType === FieldMetadataType.Link) {
|
||||
return 'LINK';
|
||||
}
|
||||
|
||||
if (fieldType === FieldMetadataType.Currency) {
|
||||
return 'CURRENCY';
|
||||
}
|
||||
|
||||
return fieldType as FieldType;
|
||||
};
|
||||
@ -0,0 +1,4 @@
|
||||
const metadataLabelValidationPattern = /^[a-zA-Z][a-zA-Z0-9 ]*$/;
|
||||
|
||||
export const validateMetadataLabel = (value: string) =>
|
||||
!!value.match(metadataLabelValidationPattern);
|
||||
Reference in New Issue
Block a user