feat: refactor schema builder and resolver builder (#2215)

* feat: wip refactor schema builder

* feat: wip store types and first queries generation

* feat: refactor schema-builder and resolver-builder

* fix: clean & small type fix

* fix: avoid breaking change

* fix: remove util from pg-graphql classes

* fix: required default fields

* Refactor frontend accordingly

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Jérémy M 2023-11-03 17:16:37 +01:00 committed by GitHub
parent aba3fd454b
commit 1ed4965a95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
216 changed files with 3215 additions and 2028 deletions

View File

@ -174,7 +174,7 @@ export type CreateFieldInput = {
label: Scalars['String']['input'];
name: Scalars['String']['input'];
objectId: Scalars['String']['input'];
type: Scalars['String']['input'];
type: FieldMetadataType;
};
export type CreateObjectInput = {
@ -424,10 +424,24 @@ export type FieldDeleteResponse = {
name?: Maybe<Scalars['String']['output']>;
/** @deprecated Use label name instead */
placeholder?: Maybe<Scalars['String']['output']>;
type?: Maybe<Scalars['String']['output']>;
type?: Maybe<FieldMetadataType>;
updatedAt?: Maybe<Scalars['DateTime']['output']>;
};
/** Type of the field */
export enum FieldMetadataType {
Boolean = 'BOOLEAN',
Date = 'DATE',
Email = 'EMAIL',
Enum = 'ENUM',
Money = 'MONEY',
Number = 'NUMBER',
Phone = 'PHONE',
Text = 'TEXT',
Url = 'URL',
Uuid = 'UUID'
}
export type Mutation = {
__typename?: 'Mutation';
createOneField: Field;
@ -764,7 +778,7 @@ export type Field = {
name: Scalars['String']['output'];
/** @deprecated Use label name instead */
placeholder?: Maybe<Scalars['String']['output']>;
type: Scalars['String']['output'];
type: FieldMetadataType;
updatedAt: Scalars['DateTime']['output'];
};
@ -818,7 +832,7 @@ export type CreateOneMetadataFieldMutationVariables = Exact<{
}>;
export type CreateOneMetadataFieldMutation = { __typename?: 'Mutation', createOneField: { __typename?: 'field', id: string, type: string, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } };
export type CreateOneMetadataFieldMutation = { __typename?: 'Mutation', createOneField: { __typename?: 'field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } };
export type UpdateOneMetadataFieldMutationVariables = Exact<{
idToUpdate: Scalars['ID']['input'];
@ -826,7 +840,7 @@ export type UpdateOneMetadataFieldMutationVariables = Exact<{
}>;
export type UpdateOneMetadataFieldMutation = { __typename?: 'Mutation', updateOneField: { __typename?: 'field', id: string, type: string, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } };
export type UpdateOneMetadataFieldMutation = { __typename?: 'Mutation', updateOneField: { __typename?: 'field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } };
export type UpdateOneObjectMetadataItemMutationVariables = Exact<{
idToUpdate: Scalars['ID']['input'];
@ -848,12 +862,12 @@ export type DeleteOneMetadataFieldMutationVariables = Exact<{
}>;
export type DeleteOneMetadataFieldMutation = { __typename?: 'Mutation', deleteOneField: { __typename?: 'FieldDeleteResponse', id?: string | null, type?: string | null, name?: string | null, label?: string | null, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isNullable?: boolean | null, createdAt?: any | null, updatedAt?: any | null } };
export type DeleteOneMetadataFieldMutation = { __typename?: 'Mutation', deleteOneField: { __typename?: 'FieldDeleteResponse', id?: string | null, type?: FieldMetadataType | null, name?: string | null, label?: string | null, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isNullable?: boolean | null, createdAt?: any | null, updatedAt?: any | null } };
export type ObjectMetadataItemsQueryVariables = Exact<{ [key: string]: never; }>;
export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', totalCount: number, edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: string, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any, fields: { __typename?: 'ObjectFieldsConnection', totalCount: number, edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: string, type: string, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } };
export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', totalCount: number, edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: string, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any, fields: { __typename?: 'ObjectFieldsConnection', totalCount: number, edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } };
export const CreateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<CreateOneObjectMetadataItemMutation, CreateOneObjectMetadataItemMutationVariables>;

View File

@ -1309,10 +1309,24 @@ export type FieldDeleteResponse = {
name?: Maybe<Scalars['String']>;
/** @deprecated Use label name instead */
placeholder?: Maybe<Scalars['String']>;
type?: Maybe<Scalars['String']>;
type?: Maybe<FieldMetadataType>;
updatedAt?: Maybe<Scalars['DateTime']>;
};
/** Type of the field */
export enum FieldMetadataType {
Boolean = 'BOOLEAN',
Date = 'DATE',
Email = 'EMAIL',
Enum = 'ENUM',
Money = 'MONEY',
Number = 'NUMBER',
Phone = 'PHONE',
Text = 'TEXT',
Url = 'URL',
Uuid = 'UUID'
}
export enum FileFolder {
Attachment = 'Attachment',
PersonPicture = 'PersonPicture',
@ -1377,7 +1391,6 @@ export type Mutation = {
createOneApiKey: ApiKeyToken;
createOneComment: Comment;
createOneCompany: Company;
createOneField: Field;
createOneObject: Object;
createOnePerson: Person;
createOnePipelineProgress: PipelineProgress;
@ -1389,7 +1402,6 @@ export type Mutation = {
deleteManyCompany: AffectedRows;
deleteManyPerson: AffectedRows;
deleteManyPipelineProgress: AffectedRows;
deleteOneField: FieldDeleteResponse;
deleteOneObject: ObjectDeleteResponse;
deleteOnePipelineStage: PipelineStage;
deleteOneWebHook: WebHook;
@ -1402,7 +1414,6 @@ export type Mutation = {
updateOneActivity: Activity;
updateOneCompany?: Maybe<Company>;
updateOneFavorites: Favorite;
updateOneField: Field;
updateOneObject: Object;
updateOnePerson?: Maybe<Person>;
updateOnePipelineProgress?: Maybe<PipelineProgress>;
@ -2393,8 +2404,6 @@ export type Query = {
clientConfig: ClientConfig;
currentUser: User;
currentWorkspace: Workspace;
field: Field;
fields: FieldConnection;
findFavorites: Array<Favorite>;
findManyActivities: Array<Activity>;
findManyApiKey: Array<ApiKey>;
@ -3093,7 +3102,7 @@ export type Field = {
name: Scalars['String'];
/** @deprecated Use label name instead */
placeholder?: Maybe<Scalars['String']>;
type: Scalars['String'];
type: FieldMetadataType;
updatedAt: Scalars['DateTime'];
};

View File

@ -26,7 +26,7 @@ export const ActivityAssigneeEditableField = ({
fieldId: 'assignee',
label: 'Assignee',
Icon: IconUserCircle,
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'assignee',
relationType: Entity.User,

View File

@ -24,7 +24,7 @@ export const ActivityEditorDateField = ({
fieldId: 'activityDueAt',
label: 'Due date',
Icon: IconCalendar,
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'dueAt',
},

View File

@ -23,7 +23,7 @@ export const useCurrentUserTaskCount = () => {
displayValue: currentUser.displayName,
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
definition: {
type: 'entity',
type: 'ENTITY',
},
})
: {}),

View File

@ -33,7 +33,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconBuildingSkyscraper,
size: 180,
position: 0,
type: 'chip',
type: 'CHIP',
metadata: {
urlFieldName: 'domainName',
contentFieldName: 'name',
@ -50,7 +50,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconLink,
size: 100,
position: 1,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'domainName',
placeHolder: 'example.com',
@ -65,7 +65,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconUserCircle,
size: 150,
position: 2,
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'accountOwner',
relationType: Entity.User,
@ -87,7 +87,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconCalendarEvent,
size: 150,
position: 3,
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'createdAt',
},
@ -100,7 +100,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconUsers,
size: 150,
position: 4,
type: 'number',
type: 'NUMBER',
metadata: {
fieldName: 'employees',
isPositive: true,
@ -115,7 +115,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconBrandLinkedin,
size: 170,
position: 5,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'linkedinUrl',
placeHolder: 'LinkedIn URL',
@ -129,7 +129,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconMap,
size: 170,
position: 6,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'address',
placeHolder: 'Address', // Hack: Fake character to prevent password-manager from filling the field
@ -143,7 +143,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconTarget,
size: 150,
position: 7,
type: 'boolean',
type: 'BOOLEAN',
metadata: {
fieldName: 'idealCustomerProfile',
},
@ -157,7 +157,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconMoneybag,
size: 150,
position: 8,
type: 'moneyAmount',
type: 'MONEY_AMOUNT',
metadata: {
fieldName: 'annualRecurringRevenue',
placeHolder: 'ARR',
@ -171,7 +171,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
Icon: IconBrandX,
size: 150,
position: 9,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'xUrl',
placeHolder: 'X',
@ -189,7 +189,7 @@ export const suppliersAvailableColumnDefinitions: ColumnDefinition<FieldMetadata
Icon: IconBuildingSkyscraper,
size: 180,
position: 0,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'name',
placeHolder: 'Company Name',
@ -204,7 +204,7 @@ export const suppliersAvailableColumnDefinitions: ColumnDefinition<FieldMetadata
Icon: IconBuildingSkyscraper,
size: 180,
position: 0,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'city',
placeHolder: 'Company Name',

View File

@ -2,6 +2,7 @@ import { ApolloClient, useMutation } from '@apollo/client';
import { getOperationName } from '@apollo/client/utilities';
import { FieldType } from '@/ui/object/field/types/FieldType';
import { FieldMetadataType } from '~/generated/graphql';
import {
CreateOneMetadataFieldMutation,
CreateOneMetadataFieldMutationVariables,
@ -12,10 +13,12 @@ import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
import { useApolloMetadataClient } from './useApolloMetadataClient';
type CreateOneMetadataFieldArgs =
CreateOneMetadataFieldMutationVariables['input']['field'] & {
type: FieldType;
};
type CreateOneMetadataFieldArgs = Omit<
CreateOneMetadataFieldMutationVariables['input']['field'],
'type'
> & {
type: FieldType;
};
export const useCreateOneMetadataField = () => {
const apolloMetadataClient = useApolloMetadataClient();
@ -33,6 +36,7 @@ export const useCreateOneMetadataField = () => {
input: {
field: {
...input,
type: input.type as FieldMetadataType, // Todo improve typing once we have aligned backend and frontend
},
},
},

View File

@ -1,44 +0,0 @@
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
import { useCreateOneMetadataField } from './useCreateOneMetadataField';
import { useCreateOneObjectMetadataItem } from './useCreateOneObjectMetadataItem';
export const useSeedCustomObjectsTemp = () => {
const { createOneObjectMetadataItem } = useCreateOneObjectMetadataItem();
const { createOneMetadataField } = useCreateOneMetadataField();
return async () => {
const { data: createdObjectMetadataItem, errors } =
await createOneObjectMetadataItem({
labelPlural: 'Suppliers',
labelSingular: 'Supplier',
nameSingular: 'supplier',
namePlural: 'suppliers',
description: 'Suppliers',
icon: 'IconBuilding',
});
if (!isNonEmptyArray(errors)) {
const supplierObjectId =
createdObjectMetadataItem?.createOneObject?.id ?? '';
await createOneMetadataField({
objectId: supplierObjectId,
name: 'name',
type: 'text',
description: 'Name',
label: 'Name',
icon: 'IconBuilding',
});
await createOneMetadataField({
objectId: supplierObjectId,
label: 'City',
name: 'city',
type: 'text',
description: 'City',
icon: 'IconMap',
});
}
};
};

View File

@ -12,5 +12,5 @@ export const formatMetadataFieldAsFilterDefinition = ({
fieldId: field.id,
label: field.label,
Icon: icons[field.icon ?? 'Icon123'],
type: 'text',
type: 'TEXT',
});

View File

@ -13,7 +13,7 @@ export const generateCreateOneObjectMutation = ({
return gql`
mutation CreateOne${capitalizedObjectName}($input: ${capitalizedObjectName}CreateInput!) {
createOne${capitalizedObjectName}(data: $input) {
create${capitalizedObjectName}(data: $input) {
id
}
}

View File

@ -13,7 +13,7 @@ export const generateDeleteOneObjectMutation = ({
return gql`
mutation DeleteOne${capitalizedObjectName}($idToDelete: ID!) {
deleteOne${capitalizedObjectName}(id: $idToDelete) {
delete${capitalizedObjectName}(id: $idToDelete) {
id
}
}

View File

@ -18,7 +18,7 @@ export const generateFindManyCustomObjectsQuery = ({
objectMetadataItem.nameSingular,
)}FilterInput, $orderBy: ${capitalize(
objectMetadataItem.nameSingular,
)}OrderBy) {
)}OrderByInput) {
${objectMetadataItem.namePlural}(filter: $filter, orderBy: $orderBy){
edges {
node {

View File

@ -13,7 +13,7 @@ export const generateUpdateOneObjectMutation = ({
return gql`
mutation UpdateOne${capitalizedObjectName}($idToUpdate: ID!, $input: ${capitalizedObjectName}UpdateInput!) {
updateOne${capitalizedObjectName}(id: $idToUpdate, data: $input) {
update${capitalizedObjectName}(id: $idToUpdate, data: $input) {
id
}
}

View File

@ -7,20 +7,20 @@ export const mapFieldMetadataToGraphQLQuery = (field: Field) => {
const fieldIsSimpleValue = (
[
'text',
'phone',
'date',
'email',
'number',
'boolean',
'date',
'TEXT',
'PHONE',
'DATE',
'EMAIL',
'NUMBER',
'BOOLEAN',
'DATE',
] as FieldType[]
).includes(fieldType);
const fieldIsURL = fieldType === 'url' || fieldType === 'urlV2';
const fieldIsURL = fieldType === 'URL' || fieldType === 'URL_V2';
const fieldIsMoneyAmount =
fieldType === 'money' || fieldType === 'moneyAmountV2';
fieldType === 'MONEY' || fieldType === 'MONEY_AMOUNT_V2';
if (fieldIsSimpleValue) {
return field.name;

View File

@ -2,11 +2,11 @@ import { FieldType } from '@/ui/object/field/types/FieldType';
export const parseFieldType = (fieldType: string): FieldType => {
if (fieldType === 'url') {
return 'urlV2';
return 'URL_V2';
}
if (fieldType === 'money') {
return 'moneyAmountV2';
return 'MONEY_AMOUNT_V2';
}
return fieldType as FieldType;

View File

@ -32,7 +32,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconUser,
size: 210,
position: 0,
type: 'double-text-chip',
type: 'DOUBLE_TEXT_CHIP',
metadata: {
firstValueFieldName: 'firstName',
secondValueFieldName: 'lastName',
@ -49,7 +49,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
label: 'Email',
Icon: IconMail,
size: 150,
type: 'email',
type: 'EMAIL',
position: 1,
metadata: {
fieldName: 'email',
@ -63,7 +63,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconBuildingSkyscraper,
size: 150,
position: 2,
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'company',
relationType: Entity.Company,
@ -83,7 +83,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconPhone,
size: 150,
position: 3,
type: 'phone',
type: 'PHONE',
metadata: {
fieldName: 'phone',
placeHolder: 'Phone', // Hack: Fake character to prevent password-manager from filling the field
@ -96,7 +96,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconCalendarEvent,
size: 150,
position: 4,
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'createdAt',
},
@ -108,7 +108,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconMap,
size: 150,
position: 5,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'city',
placeHolder: 'City', // Hack: Fake character to prevent password-manager from filling the field
@ -121,7 +121,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconBriefcase,
size: 150,
position: 6,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'jobTitle',
placeHolder: 'Job title',
@ -134,7 +134,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconBrandLinkedin,
size: 150,
position: 7,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'linkedinUrl',
placeHolder: 'LinkedIn',
@ -147,7 +147,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
Icon: IconBrandX,
size: 150,
position: 8,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'xUrl',
placeHolder: 'X',

View File

@ -22,7 +22,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[
label: 'Close Date',
Icon: IconCalendarEvent,
position: 0,
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'closeDate',
},
@ -36,7 +36,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[
label: 'Amount',
Icon: IconCurrencyDollar,
position: 1,
type: 'number',
type: 'NUMBER',
metadata: {
fieldName: 'amount',
placeHolder: '0',
@ -50,7 +50,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[
label: 'Probability',
Icon: IconProgressCheck,
position: 2,
type: 'probability',
type: 'PROBABILITY',
metadata: {
fieldName: 'probability',
},
@ -64,7 +64,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[
label: 'Point of Contact',
Icon: IconUser,
position: 3,
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'pointOfContact',
relationType: Entity.Person,

View File

@ -12,7 +12,7 @@ type SettingsObjectFieldTypeSelectSectionProps = {
};
// TODO: remove "relation" type for now, add it back when the backend is ready.
const { relation: _, ...dataTypesWithoutRelation } = dataTypes;
const { RELATION: _, ...dataTypesWithoutRelation } = dataTypes;
export const SettingsObjectFieldTypeSelectSection = ({
disabled,

View File

@ -9,7 +9,7 @@ const meta: Meta<typeof SettingsObjectFieldTypeSelectSection> = {
title: 'Modules/Settings/DataModel/SettingsObjectFieldTypeSelectSection',
component: SettingsObjectFieldTypeSelectSection,
decorators: [ComponentDecorator],
args: { type: 'number' },
args: { type: 'NUMBER' },
};
export default meta;

View File

@ -13,9 +13,9 @@ export const dataTypes: Record<
MetadataFieldDataType,
{ label: string; Icon: IconComponent }
> = {
number: { label: 'Number', Icon: IconNumbers },
text: { label: 'Text', Icon: IconTextSize },
url: { label: 'Link', Icon: IconLink },
boolean: { label: 'True/False', Icon: IconCheck },
relation: { label: 'Relation', Icon: IconPlug },
NUMBER: { label: 'Number', Icon: IconNumbers },
TEXT: { label: 'Text', Icon: IconTextSize },
URL: { label: 'Link', Icon: IconLink },
BOOLEAN: { label: 'True/False', Icon: IconCheck },
RELATION: { label: 'Relation', Icon: IconPlug },
};

View File

@ -15,7 +15,7 @@ const StyledDataType = styled.div<{ value: MetadataFieldDataType }>`
padding: 0 ${({ theme }) => theme.spacing(2)};
${({ theme, value }) =>
value === 'relation'
value === 'RELATION'
? css`
border-color: ${theme.color.purple20};
color: ${theme.color.purple};

View File

@ -39,10 +39,10 @@ export const SettingsObjectFieldItemTableRow = ({
// TODO: parse with zod and merge types with FieldType (create a subset of FieldType for example)
const fieldDataTypeIsSupported = [
'text',
'number',
'boolean',
'url',
'TEXT',
'NUMBER',
'BOOLEAN',
'URL',
].includes(fieldItem.type);
if (!fieldDataTypeIsSupported) {

View File

@ -1,6 +1,6 @@
export type MetadataFieldDataType =
| 'boolean'
| 'number'
| 'relation'
| 'text'
| 'url';
| 'BOOLEAN'
| 'NUMBER'
| 'RELATION'
| 'TEXT'
| 'URL';

View File

@ -33,7 +33,7 @@ const DateFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'date',
label: 'Date',
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'Date',
},

View File

@ -40,7 +40,7 @@ const DoubleTextFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'double-text',
label: 'Double-Text',
type: 'double-text',
type: 'DOUBLE_TEXT',
metadata: {
firstValueFieldName: 'First-text',
firstValuePlaceholder: 'First-text',

View File

@ -32,7 +32,7 @@ const EmailFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'email',
label: 'Email',
type: 'email',
type: 'EMAIL',
metadata: {
fieldName: 'Email',
placeHolder: 'Email',

View File

@ -34,7 +34,7 @@ const MoneyFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'money',
label: 'Money',
type: 'moneyAmount',
type: 'MONEY_AMOUNT',
metadata: {
fieldName: 'Amount',
placeHolder: 'Amount',

View File

@ -34,7 +34,7 @@ const NumberFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'number',
label: 'Number',
type: 'number',
type: 'NUMBER',
metadata: {
fieldName: 'Number',
placeHolder: 'Number',

View File

@ -32,7 +32,7 @@ const PhoneFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'phone',
label: 'Phone',
type: 'phone',
type: 'PHONE',
metadata: {
fieldName: 'Phone',
placeHolder: 'Phone',

View File

@ -34,7 +34,7 @@ const TextFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'text',
label: 'Text',
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'Text',
placeHolder: 'Text',

View File

@ -32,7 +32,7 @@ const URLFieldDisplayWithContext = ({
fieldDefinition={{
fieldId: 'URL',
label: 'URL',
type: 'url',
type: 'URL',
metadata: {
fieldName: 'URL',
placeHolder: 'URL',

View File

@ -9,7 +9,7 @@ import { isFieldBoolean } from '../../types/guards/isFieldBoolean';
export const useBooleanField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('boolean', isFieldBoolean, fieldDefinition);
assertFieldMetadata('BOOLEAN', isFieldBoolean, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -10,7 +10,7 @@ import { isFieldChip } from '../../types/guards/isFieldChip';
export const useChipField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('chip', isFieldChip, fieldDefinition);
assertFieldMetadata('CHIP', isFieldChip, fieldDefinition);
const contentFieldName = fieldDefinition.metadata.contentFieldName;
const avatarUrlFieldName = fieldDefinition.metadata.urlFieldName;

View File

@ -9,7 +9,7 @@ import { isFieldDate } from '../../types/guards/isFieldDate';
export const useDateField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('date', isFieldDate, fieldDefinition);
assertFieldMetadata('DATE', isFieldDate, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -11,7 +11,7 @@ export const useDoubleTextChipField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata(
'double-text-chip',
'DOUBLE_TEXT_CHIP',
isFieldDoubleTextChip,
fieldDefinition,
);

View File

@ -10,7 +10,7 @@ import { isFieldDoubleText } from '../../types/guards/isFieldDoubleText';
export const useDoubleTextField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('double-text', isFieldDoubleText, fieldDefinition);
assertFieldMetadata('DOUBLE_TEXT', isFieldDoubleText, fieldDefinition);
const [firstValue, setFirstValue] = useRecoilState<string>(
entityFieldsFamilySelector({

View File

@ -10,7 +10,7 @@ import { isFieldEmail } from '../../types/guards/isFieldEmail';
export const useEmailField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('email', isFieldEmail, fieldDefinition);
assertFieldMetadata('EMAIL', isFieldEmail, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -13,7 +13,7 @@ import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmount
export const useMoneyAmountV2Field = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('moneyAmountV2', isFieldMoneyAmountV2, fieldDefinition);
assertFieldMetadata('MONEY_AMOUNT_V2', isFieldMoneyAmountV2, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -16,7 +16,7 @@ import { isFieldMoney } from '../../types/guards/isFieldMoney';
export const useMoneyField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('moneyAmount', isFieldMoney, fieldDefinition);
assertFieldMetadata('MONEY_AMOUNT', isFieldMoney, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -16,7 +16,7 @@ import { isFieldNumber } from '../../types/guards/isFieldNumber';
export const useNumberField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('number', isFieldNumber, fieldDefinition);
assertFieldMetadata('NUMBER', isFieldNumber, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -12,7 +12,7 @@ import { isFieldPhone } from '../../types/guards/isFieldPhone';
export const usePhoneField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('phone', isFieldPhone, fieldDefinition);
assertFieldMetadata('PHONE', isFieldPhone, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -9,7 +9,7 @@ import { isFieldProbability } from '../../types/guards/isFieldProbability';
export const useProbabilityField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('probability', isFieldProbability, fieldDefinition);
assertFieldMetadata('PROBABILITY', isFieldProbability, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -11,7 +11,7 @@ import { isFieldRelation } from '../../types/guards/isFieldRelation';
export const useRelationField = () => {
const { entityId, fieldDefinition } = useContext(FieldContext);
assertFieldMetadata('relation', isFieldRelation, fieldDefinition);
assertFieldMetadata('RELATION', isFieldRelation, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -10,7 +10,7 @@ import { isFieldText } from '../../types/guards/isFieldText';
export const useTextField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('text', isFieldText, fieldDefinition);
assertFieldMetadata('TEXT', isFieldText, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -13,7 +13,7 @@ import { isFieldURL } from '../../types/guards/isFieldURL';
export const useURLField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('url', isFieldURL, fieldDefinition);
assertFieldMetadata('URL', isFieldURL, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -13,7 +13,7 @@ import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
export const useURLV2Field = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('urlV2', isFieldURLV2, fieldDefinition);
assertFieldMetadata('URL_V2', isFieldURLV2, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -36,7 +36,7 @@ const BooleanFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'boolean',
label: 'Boolean',
type: 'boolean',
type: 'BOOLEAN',
metadata: {
fieldName: 'Boolean',
},

View File

@ -46,7 +46,7 @@ const ChipFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'chip',
label: 'Chip',
type: 'chip',
type: 'CHIP',
metadata: {
contentFieldName: 'name',
urlFieldName: 'xURL',

View File

@ -46,7 +46,7 @@ const DateFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'date',
label: 'Date',
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'Date',
},

View File

@ -59,7 +59,7 @@ const DoubleTextChipFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'double-text-chip',
label: 'Double-Text-Chip',
type: 'double-text-chip',
type: 'DOUBLE_TEXT_CHIP',
metadata: {
firstValueFieldName: 'First-text',
firstValuePlaceholder: 'First-text',

View File

@ -57,7 +57,7 @@ const DoubleTextFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'double-text',
label: 'Double-Text',
type: 'double-text',
type: 'DOUBLE_TEXT',
metadata: {
firstValueFieldName: 'First-text',
firstValuePlaceholder: 'First-text',

View File

@ -45,7 +45,7 @@ const EmailFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'email',
label: 'Email',
type: 'email',
type: 'EMAIL',
metadata: {
fieldName: 'email',
placeHolder: 'username@email.com',

View File

@ -45,7 +45,7 @@ const MoneyFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'moneyAmount',
label: 'MoneyAmout',
type: 'moneyAmount',
type: 'MONEY_AMOUNT',
metadata: {
fieldName: 'moneyAmount',
placeHolder: 'Enter Amount',

View File

@ -45,7 +45,7 @@ const NumberFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'number',
label: 'Number',
type: 'number',
type: 'NUMBER',
metadata: {
fieldName: 'number',
placeHolder: 'Enter number',

View File

@ -45,7 +45,7 @@ const PhoneFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'phone',
label: 'Phone',
type: 'phone',
type: 'PHONE',
metadata: {
fieldName: 'Phone',
placeHolder: 'Enter phone number',

View File

@ -43,7 +43,7 @@ const ProbabilityFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'probability',
label: 'Probability',
type: 'probability',
type: 'PROBABILITY',
metadata: {
fieldName: 'Probability',
},

View File

@ -48,7 +48,7 @@ const RelationFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'relation',
label: 'Relation',
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'Relation',
relationType: Entity.Person,

View File

@ -45,7 +45,7 @@ const TextFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'text',
label: 'Text',
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'Text',
placeHolder: 'Enter text',

View File

@ -45,7 +45,7 @@ const URLFieldInputWithContext = ({
fieldDefinition={{
fieldId: 'url',
label: 'URL',
type: 'url',
type: 'URL',
metadata: {
fieldName: 'URL',
placeHolder: 'Enter URL',

View File

@ -1,17 +1,17 @@
export type FieldType =
| 'text'
| 'relation'
| 'chip'
| 'double-text-chip'
| 'double-text'
| 'number'
| 'email'
| 'boolean'
| 'date'
| 'phone'
| 'url'
| 'urlV2'
| 'probability'
| 'moneyAmountV2'
| 'moneyAmount'
| 'money';
| 'TEXT'
| 'RELATION'
| 'CHIP'
| 'DOUBLE_TEXT_CHIP'
| 'DOUBLE_TEXT'
| 'NUMBER'
| 'EMAIL'
| 'BOOLEAN'
| 'DATE'
| 'PHONE'
| 'URL'
| 'URL_V2'
| 'PROBABILITY'
| 'MONEY_AMOUNT_V2'
| 'MONEY_AMOUNT'
| 'MONEY';

View File

@ -21,35 +21,35 @@ import { FieldType } from '../FieldType';
type AssertFieldMetadataFunction = <
E extends FieldType,
T extends E extends 'text'
T extends E extends 'TEXT'
? FieldTextMetadata
: E extends 'relation'
: E extends 'RELATION'
? FieldRelationMetadata
: E extends 'chip'
: E extends 'CHIP'
? FieldChipMetadata
: E extends 'double-text-chip'
: E extends 'DOUBLE_TEXT_CHIP'
? FieldDoubleTextChipMetadata
: E extends 'double-text'
: E extends 'DOUBLE_TEXT'
? FieldDoubleTextMetadata
: E extends 'number'
: E extends 'NUMBER'
? FieldNumberMetadata
: E extends 'email'
: E extends 'EMAIL'
? FieldEmailMetadata
: E extends 'boolean'
: E extends 'BOOLEAN'
? FieldBooleanMetadata
: E extends 'date'
: E extends 'DATE'
? FieldDateMetadata
: E extends 'phone'
: E extends 'PHONE'
? FieldPhoneMetadata
: E extends 'url'
: E extends 'URL'
? FieldURLMetadata
: E extends 'urlV2'
: E extends 'URL_V2'
? FieldURLV2Metadata
: E extends 'probability'
: E extends 'PROBABILITY'
? FieldProbabilityMetadata
: E extends 'moneyAmount'
: E extends 'MONEY_AMOUNT'
? FieldMoneyMetadata
: E extends 'moneyAmountV2'
: E extends 'MONEY_AMOUNT_V2'
? FieldMoneyAmountV2Metadata
: never,
>(

View File

@ -3,4 +3,4 @@ import { FieldBooleanMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldBoolean = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldBooleanMetadata> => field.type === 'boolean';
): field is FieldDefinition<FieldBooleanMetadata> => field.type === 'BOOLEAN';

View File

@ -3,4 +3,4 @@ import { FieldChipMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldChip = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldChipMetadata> => field.type === 'chip';
): field is FieldDefinition<FieldChipMetadata> => field.type === 'CHIP';

View File

@ -3,4 +3,4 @@ import { FieldDateMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldDate = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldDateMetadata> => field.type === 'date';
): field is FieldDefinition<FieldDateMetadata> => field.type === 'DATE';

View File

@ -4,4 +4,4 @@ import { FieldDoubleTextMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldDoubleText = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldDoubleTextMetadata> =>
field.type === 'double-text';
field.type === 'DOUBLE_TEXT';

View File

@ -4,4 +4,4 @@ import { FieldDoubleTextChipMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldDoubleTextChip = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldDoubleTextChipMetadata> =>
field.type === 'double-text-chip';
field.type === 'DOUBLE_TEXT_CHIP';

View File

@ -3,4 +3,4 @@ import { FieldEmailMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldEmail = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldEmailMetadata> => field.type === 'email';
): field is FieldDefinition<FieldEmailMetadata> => field.type === 'EMAIL';

View File

@ -3,4 +3,5 @@ import { FieldMetadata, FieldMoneyMetadata } from '../FieldMetadata';
export const isFieldMoney = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldMoneyMetadata> => field.type === 'moneyAmount';
): field is FieldDefinition<FieldMoneyMetadata> =>
field.type === 'MONEY_AMOUNT';

View File

@ -4,4 +4,4 @@ import { FieldMetadata, FieldMoneyAmountV2Metadata } from '../FieldMetadata';
export const isFieldMoneyAmountV2 = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldMoneyAmountV2Metadata> =>
field.type === 'moneyAmountV2';
field.type === 'MONEY_AMOUNT_V2';

View File

@ -3,4 +3,4 @@ import { FieldMetadata, FieldNumberMetadata } from '../FieldMetadata';
export const isFieldNumber = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldNumberMetadata> => field.type === 'number';
): field is FieldDefinition<FieldNumberMetadata> => field.type === 'NUMBER';

View File

@ -3,4 +3,4 @@ import { FieldMetadata, FieldPhoneMetadata } from '../FieldMetadata';
export const isFieldPhone = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldPhoneMetadata> => field.type === 'phone';
): field is FieldDefinition<FieldPhoneMetadata> => field.type === 'PHONE';

View File

@ -4,4 +4,4 @@ import { FieldMetadata, FieldProbabilityMetadata } from '../FieldMetadata';
export const isFieldProbability = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldProbabilityMetadata> =>
field.type === 'probability';
field.type === 'PROBABILITY';

View File

@ -3,4 +3,4 @@ import { FieldMetadata, FieldRelationMetadata } from '../FieldMetadata';
export const isFieldRelation = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldRelationMetadata> => field.type === 'relation';
): field is FieldDefinition<FieldRelationMetadata> => field.type === 'RELATION';

View File

@ -3,4 +3,4 @@ import { FieldMetadata, FieldTextMetadata } from '../FieldMetadata';
export const isFieldText = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldTextMetadata> => field.type === 'text';
): field is FieldDefinition<FieldTextMetadata> => field.type === 'TEXT';

View File

@ -3,4 +3,4 @@ import { FieldMetadata, FieldURLMetadata } from '../FieldMetadata';
export const isFieldURL = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldURLMetadata> => field.type === 'url';
): field is FieldDefinition<FieldURLMetadata> => field.type === 'URL';

View File

@ -3,4 +3,4 @@ import { FieldMetadata, FieldURLV2Metadata } from '../FieldMetadata';
export const isFieldURLV2 = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldURLV2Metadata> => field.type === 'urlV2';
): field is FieldDefinition<FieldURLV2Metadata> => field.type === 'URL_V2';

View File

@ -30,19 +30,19 @@ export const MultipleFiltersDropdownContent = () => {
<>
<ObjectFilterDropdownOperandButton />
<DropdownMenuSeparator />
{filterDefinitionUsedInDropdown.type === 'text' && (
{filterDefinitionUsedInDropdown.type === 'TEXT' && (
<ObjectFilterDropdownTextSearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'number' && (
{filterDefinitionUsedInDropdown.type === 'NUMBER' && (
<ObjectFilterDropdownNumberSearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'date' && (
{filterDefinitionUsedInDropdown.type === 'DATE' && (
<ObjectFilterDropdownDateSearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'entity' && (
{filterDefinitionUsedInDropdown.type === 'ENTITY' && (
<ObjectFilterDropdownEntitySearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'entity' && (
{filterDefinitionUsedInDropdown.type === 'ENTITY' && (
<ObjectFilterDropdownEntitySelect />
)}
</>

View File

@ -16,7 +16,7 @@ export const ObjectFilterDropdownButton = ({
const hasOnlyOneEntityFilter =
availableFilterDefinitions.length === 1 &&
availableFilterDefinitions[0].type === 'entity';
availableFilterDefinitions[0].type === 'ENTITY';
if (!availableFilterDefinitions.length) {
return <></>;

View File

@ -6,7 +6,7 @@ import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownEntitySelect = () => {
const { filterDefinitionUsedInDropdown } = useFilter();
if (filterDefinitionUsedInDropdown?.type !== 'entity') {
if (filterDefinitionUsedInDropdown?.type !== 'ENTITY') {
return null;
}

View File

@ -25,7 +25,7 @@ export const ObjectFilterDropdownFilterSelect = () => {
onClick={() => {
setFilterDefinitionUsedInDropdown(availableFilterDefinition);
if (availableFilterDefinition.type === 'entity') {
if (availableFilterDefinition.type === 'ENTITY') {
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
}

View File

@ -1 +1 @@
export type FilterType = 'text' | 'date' | 'entity' | 'number';
export type FilterType = 'TEXT' | 'DATE' | 'ENTITY' | 'NUMBER';

View File

@ -6,12 +6,12 @@ export const getOperandsForFilterType = (
filterType: FilterType | null | undefined,
): ViewFilterOperand[] => {
switch (filterType) {
case 'text':
case 'TEXT':
return [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain];
case 'number':
case 'date':
case 'NUMBER':
case 'DATE':
return [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan];
case 'entity':
case 'ENTITY':
return [ViewFilterOperand.Is, ViewFilterOperand.IsNot];
default:
return [];

View File

@ -24,7 +24,7 @@ export const turnFilterIntoWhereClause = (
};
default:
switch (filter.definition.type) {
case 'text':
case 'TEXT':
switch (filter.operand) {
case ViewFilterOperand.Contains:
return {
@ -47,7 +47,7 @@ export const turnFilterIntoWhereClause = (
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
);
}
case 'number':
case 'NUMBER':
switch (filter.operand) {
case ViewFilterOperand.GreaterThan:
return {
@ -66,7 +66,7 @@ export const turnFilterIntoWhereClause = (
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
);
}
case 'date':
case 'DATE':
switch (filter.operand) {
case ViewFilterOperand.GreaterThan:
return {
@ -85,7 +85,7 @@ export const turnFilterIntoWhereClause = (
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
);
}
case 'entity':
case 'ENTITY':
switch (filter.operand) {
case ViewFilterOperand.Is:
return {

View File

@ -26,7 +26,7 @@ export const turnFiltersIntoWhereClauseV2 = (
}
switch (filter.definition.type) {
case 'text':
case 'TEXT':
switch (filter.operand) {
case ViewFilterOperand.Contains:
whereClause[correspondingField.name] = {

View File

@ -25,7 +25,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'domainName',
label: 'Domain name',
Icon: IconLink,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'domainName',
placeHolder: 'URL',
@ -35,7 +35,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'accountOwner',
label: 'Account owner',
Icon: IconUserCircle,
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'accountOwner',
relationType: Entity.User,
@ -52,7 +52,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'employees',
label: 'Employees',
Icon: IconUsers,
type: 'number',
type: 'NUMBER',
metadata: {
fieldName: 'employees',
placeHolder: 'Employees',
@ -62,7 +62,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'address',
label: 'Address',
Icon: IconMap,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'address',
placeHolder: 'Address',
@ -72,7 +72,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'idealCustomerProfile',
label: 'ICP',
Icon: IconTarget,
type: 'boolean',
type: 'BOOLEAN',
metadata: {
fieldName: 'idealCustomerProfile',
},
@ -81,7 +81,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'xUrl',
label: 'Twitter',
Icon: IconBrandX,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'xUrl',
placeHolder: 'X',
@ -91,7 +91,7 @@ export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendar,
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'createdAt',
},

View File

@ -16,37 +16,37 @@ export const companyTableFilterDefinitions: FilterDefinitionByEntity<Company>[]
fieldId: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'employees',
label: 'Employees',
Icon: IconUsers,
type: 'number',
type: 'NUMBER',
},
{
fieldId: 'domainName',
label: 'URL',
Icon: IconLink,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'address',
label: 'Address',
Icon: IconMap,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
type: 'date',
type: 'DATE',
},
{
fieldId: 'accountOwnerId',
label: 'Account owner',
Icon: IconUser,
type: 'entity',
type: 'ENTITY',
entitySelectComponent: <FilterDropdownUserSearchSelect />,
},
];

View File

@ -16,26 +16,26 @@ export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity<Pipelin
fieldId: 'amount',
label: 'Amount',
Icon: IconCurrencyDollar,
type: 'number',
type: 'NUMBER',
},
{
fieldId: 'closeDate',
label: 'Close date',
Icon: IconCalendarEvent,
type: 'date',
type: 'DATE',
},
{
fieldId: 'companyId',
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
type: 'ENTITY',
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
{
fieldId: 'pointOfContactId',
label: 'Point of contact',
Icon: IconUser,
type: 'entity',
type: 'ENTITY',
entitySelectComponent: <FilterDropdownPeopleSearchSelect />,
},
];

View File

@ -26,7 +26,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'email',
label: 'Email',
Icon: IconMail,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'email',
placeHolder: 'Email',
@ -36,7 +36,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'company',
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'relation',
type: 'RELATION',
metadata: {
fieldName: 'company',
relationType: Entity.Company,
@ -53,7 +53,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'phone',
label: 'Phone',
Icon: IconPhone,
type: 'phone',
type: 'PHONE',
metadata: {
fieldName: 'phone',
placeHolder: 'Phone',
@ -63,7 +63,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'jobTitle',
label: 'Job Title',
Icon: IconBriefcase,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'jobTitle',
placeHolder: 'Job Title',
@ -73,7 +73,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'city',
label: 'City',
Icon: IconMap,
type: 'text',
type: 'TEXT',
metadata: {
fieldName: 'city',
placeHolder: 'City',
@ -83,7 +83,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'linkedinUrl',
label: 'Linkedin URL',
Icon: IconBrandLinkedin,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'linkedinUrl',
placeHolder: 'Linkedin URL',
@ -93,7 +93,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'xUrl',
label: 'X URL',
Icon: IconBrandX,
type: 'url',
type: 'URL',
metadata: {
fieldName: 'xUrl',
placeHolder: 'X URL',
@ -103,7 +103,7 @@ export const personShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendar,
type: 'date',
type: 'DATE',
metadata: {
fieldName: 'createdAt',
},

View File

@ -16,25 +16,25 @@ export const personTableFilterDefinitions: FilterDefinitionByEntity<Person>[] =
fieldId: 'firstName',
label: 'First name',
Icon: IconUser,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'lastName',
label: 'Last name',
Icon: IconUser,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'email',
label: 'Email',
Icon: IconMail,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'companyId',
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
type: 'ENTITY',
// TODO: replace this with a component that selects the dropdown to use based on the entity type
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
@ -42,18 +42,18 @@ export const personTableFilterDefinitions: FilterDefinitionByEntity<Person>[] =
fieldId: 'phone',
label: 'Phone',
Icon: IconPhone,
type: 'text',
type: 'TEXT',
},
{
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
type: 'date',
type: 'DATE',
},
{
fieldId: 'city',
label: 'City',
Icon: IconMap,
type: 'text',
type: 'TEXT',
},
];

View File

@ -40,7 +40,7 @@ export const SettingsObjectNewFieldStep2 = () => {
icon: string;
label: string;
type: MetadataFieldDataType;
}>({ icon: 'IconUsers', label: '', type: 'number' });
}>({ icon: 'IconUsers', label: '', type: 'NUMBER' });
const [objectViews, setObjectViews] = useState<View[]>([]);

View File

@ -8,7 +8,7 @@ export const tasksFilterDefinitions: FilterDefinitionByEntity<Activity>[] = [
fieldId: 'assigneeId',
label: 'Assignee',
Icon: IconUser,
type: 'entity',
type: 'ENTITY',
entitySelectComponent: <FilterDropdownUserSearchSelect />,
selectAllLabel: 'All assignees',
SelectAllIcon: IconUserCircle,

View File

@ -19,7 +19,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '5db475e7-8208-402d-97a1-62c9ce344dd4',
type: 'text',
type: 'TEXT',
name: 'objectId',
label: 'Object Id',
description: 'View target object',
@ -35,7 +35,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: 'ddc89a56-9add-4110-aa53-4ecdbba36767',
type: 'text',
type: 'TEXT',
name: 'type',
label: 'Type',
description: 'View type',
@ -51,7 +51,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '35fa806b-5d9d-446d-bd0e-1a6874b871ee',
type: 'text',
type: 'TEXT',
name: 'name',
label: 'Name',
description: 'View name',
@ -94,7 +94,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '1d718fcf-5a17-4694-91a4-4d3968a51aa4',
type: 'text',
type: 'TEXT',
name: 'viewId',
label: 'View Id',
description: 'View Field related view',
@ -110,7 +110,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '8ead2e86-7b60-4a47-9b4f-ad008e744d52',
type: 'number',
type: 'NUMBER',
name: 'position',
label: 'Position',
description: 'View Field position',
@ -126,7 +126,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '4d77c2dd-2b04-4989-b11e-cb0e386d1b4d',
type: 'text',
type: 'TEXT',
name: 'fieldId',
label: 'Field Id',
description: 'View Field target field',
@ -142,7 +142,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '0f5ab566-9fc4-44b7-85c5-1e05db9f6b49',
type: 'boolean',
type: 'BOOLEAN',
name: 'isVisible',
label: 'Visible',
description: 'View Field visibility',
@ -158,7 +158,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '21268ece-7002-4b04-a442-f25278f8ca13',
type: 'number',
type: 'NUMBER',
name: 'size',
label: 'Size',
description: 'View Field size',
@ -201,7 +201,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '397eabc0-c5a1-4550-8e68-839c878a8d0e',
type: 'text',
type: 'TEXT',
name: 'name',
label: 'Name',
description: 'The company name.',
@ -217,8 +217,8 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '7ad234c7-f3b9-4efc-813c-43dc97070b07',
type: 'url',
name: 'url',
type: 'URL',
name: 'URL',
label: 'URL',
description:
'The company website URL. We use this url to fetch the company icon.',
@ -234,7 +234,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: 'a578ffb2-13db-483c-ace7-5c30a13dff2d',
type: 'relation',
type: 'RELATION',
name: 'accountOwner',
label: 'Account Owner',
description:
@ -251,7 +251,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: 'b7fd622d-7d8b-4f5a-b148-a7e9fd2c4660',
type: 'number',
type: 'NUMBER',
name: 'employees',
label: 'Employees',
description: 'Number of employees in the company.',
@ -267,7 +267,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '60ab27ed-a959-471e-b583-887387f7accd',
type: 'url',
type: 'URL',
name: 'linkedin',
label: 'Linkedin',
description: null,
@ -283,7 +283,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: '6daadb98-83ca-4c85-bca5-7792a7d958ad',
type: 'boolean',
type: 'BOOLEAN',
name: 'prioritySupport',
label: 'Priority Support',
description: 'Whether the company has priority support.',
@ -326,7 +326,7 @@ export const mockedObjectMetadataItems = {
{
node: {
id: 'f955402c-9e8f-4b91-a82c-95f6de392b99',
type: 'text',
type: 'TEXT',
name: 'slug',
label: 'Slug',
description: null,

View File

@ -43,6 +43,7 @@
"@aws-sdk/credential-providers": "^3.363.0",
"@casl/ability": "^6.5.0",
"@casl/prisma": "1.4.0",
"@graphql-tools/schema": "^10.0.0",
"@graphql-yoga/nestjs": "^2.1.0",
"@nestjs/apollo": "^11.0.5",
"@nestjs/common": "^9.0.0",
@ -78,6 +79,7 @@
"graphql": "16.8.0",
"graphql-fields": "^2.0.3",
"graphql-subscriptions": "2.0.0",
"graphql-tag": "^2.12.6",
"graphql-type-json": "^0.3.2",
"graphql-upload": "^13.0.0",
"graphql-yoga": "^4.0.4",

View File

@ -30,7 +30,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'name',
label: 'Name',
targetColumnMap: {
@ -45,7 +45,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'domainName',
label: 'Domain Name',
targetColumnMap: {
@ -60,7 +60,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'address',
label: 'Address',
targetColumnMap: {
@ -75,7 +75,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'employees',
label: 'Employees',
targetColumnMap: {
@ -91,7 +91,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'name',
label: 'Name',
targetColumnMap: {
@ -106,7 +106,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'objectId',
label: 'Object Id',
targetColumnMap: {
@ -121,7 +121,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'type',
label: 'Type',
targetColumnMap: {
@ -137,7 +137,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'fieldId',
label: 'Field Id',
targetColumnMap: {
@ -152,7 +152,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'viewId',
label: 'View Id',
targetColumnMap: {
@ -167,7 +167,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'boolean',
type: 'BOOLEAN',
name: 'isVisible',
label: 'Visible',
targetColumnMap: {
@ -182,7 +182,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'number',
type: 'NUMBER',
name: 'size',
label: 'Size',
targetColumnMap: {
@ -197,7 +197,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'number',
type: 'NUMBER',
name: 'position',
label: 'Position',
targetColumnMap: {
@ -213,7 +213,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'fieldId',
label: 'Field Id',
targetColumnMap: {
@ -228,7 +228,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'viewId',
label: 'View Id',
targetColumnMap: {
@ -243,7 +243,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'operand',
label: 'Operand',
targetColumnMap: {
@ -258,7 +258,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'value',
label: 'Value',
targetColumnMap: {
@ -273,7 +273,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'displayValue',
label: 'Display Value',
targetColumnMap: {
@ -289,7 +289,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'fieldId',
label: 'Field Id',
targetColumnMap: {
@ -304,7 +304,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'viewId',
label: 'View Id',
targetColumnMap: {
@ -319,7 +319,7 @@ export const seedFieldMetadata = async (
isCustom: false,
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
isActive: true,
type: 'text',
type: 'TEXT',
name: 'direction',
label: 'Direction',
targetColumnMap: {

View File

@ -14,6 +14,9 @@ import { EnvironmentService } from './integrations/environment/environment.servi
const bootstrap = async () => {
const app = await NestFactory.create(AppModule, {
cors: true,
logger: process.env.DEBUG_MODE
? ['error', 'warn', 'log', 'verbose', 'debug']
: ['error', 'warn', 'log'],
});
// Apply validation pipes globally

View File

@ -8,6 +8,8 @@ import {
IsUUID,
} from 'class-validator';
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
@InputType()
export class CreateFieldInput {
@IsString()
@ -20,20 +22,10 @@ export class CreateFieldInput {
@Field()
label: string;
// Todo: use a type enum and share with typeorm entity
@IsEnum([
'text',
'phone',
'email',
'number',
'boolean',
'date',
'url',
'money',
])
@IsEnum(FieldMetadataType)
@IsNotEmpty()
@Field()
type: string;
@Field(() => FieldMetadataType)
type: FieldMetadataType;
@IsUUID()
@Field()

View File

@ -1,4 +1,4 @@
import { Field, ID, ObjectType } from '@nestjs/graphql';
import { Field, ID, ObjectType, registerEnumType } from '@nestjs/graphql';
import {
Column,
@ -17,13 +17,31 @@ import {
QueryOptions,
} from '@ptc-org/nestjs-query-graphql';
import { FieldMetadataInterface } from 'src/tenant/schema-builder/interfaces/field-metadata.interface';
import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity';
import { BeforeCreateOneField } from './hooks/before-create-one-field.hook';
import { FieldMetadataTargetColumnMap } from './interfaces/field-metadata-target-column-map.interface';
export enum FieldMetadataType {
UUID = 'uuid',
TEXT = 'TEXT',
PHONE = 'PHONE',
EMAIL = 'EMAIL',
DATE = 'DATE',
BOOLEAN = 'BOOLEAN',
NUMBER = 'NUMBER',
ENUM = 'ENUM',
URL = 'URL',
MONEY = 'MONEY',
}
registerEnumType(FieldMetadataType, {
name: 'FieldMetadataType',
description: 'Type of the field',
});
export type FieldMetadataTargetColumnMap = {
[key: string]: string;
};
@Entity('field_metadata')
@ObjectType('field')
@BeforeCreateOne(BeforeCreateOneField)
@ -43,7 +61,7 @@ export type FieldMetadataTargetColumnMap = {
'objectId',
'workspaceId',
])
export class FieldMetadata {
export class FieldMetadata implements FieldMetadataInterface {
@IDField(() => ID)
@PrimaryGeneratedColumn('uuid')
id: string;
@ -51,9 +69,9 @@ export class FieldMetadata {
@Column({ nullable: false, name: 'object_id' })
objectId: string;
@Field()
@Field(() => FieldMetadataType)
@Column({ nullable: false })
type: string;
type: FieldMetadataType;
@Field()
@Column({ nullable: false })

View File

@ -0,0 +1,35 @@
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
export interface FieldMetadataTargetColumnMapValue {
value: string;
}
export interface FieldMetadataTargetColumnMapUrl {
text: string;
link: string;
}
export interface FieldMetadataTargetColumnMapMoney {
value: number;
currency: string;
}
type AllFieldMetadataTypes = {
[key: string]: any;
};
type FieldMetadataTypeMapping = {
[FieldMetadataType.URL]: FieldMetadataTargetColumnMapUrl;
[FieldMetadataType.MONEY]: FieldMetadataTargetColumnMapMoney;
};
type TypeByFieldMetadata<T extends FieldMetadataType | 'default'> =
T extends keyof FieldMetadataTypeMapping
? FieldMetadataTypeMapping[T]
: T extends 'default'
? AllFieldMetadataTypes
: FieldMetadataTargetColumnMapValue;
export type FieldMetadataTargetColumnMap<
T extends FieldMetadataType | 'default' = 'default',
> = TypeByFieldMetadata<T>;

View File

@ -1,9 +1,11 @@
import { v4 } from 'uuid';
import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface';
import { uuidToBase36 } from 'src/metadata/data-source/data-source.util';
import {
FieldMetadata,
FieldMetadataTargetColumnMap,
FieldMetadataType,
} from 'src/metadata/field-metadata/field-metadata.entity';
import { TenantMigrationColumnAction } from 'src/metadata/tenant-migration/tenant-migration.entity';
@ -25,24 +27,24 @@ export function generateColumnName(name: string): string {
* @returns FieldMetadataTargetColumnMap
*/
export function generateTargetColumnMap(
type: string,
type: FieldMetadataType,
): FieldMetadataTargetColumnMap {
switch (type) {
case 'text':
case 'phone':
case 'email':
case 'number':
case 'boolean':
case 'date':
case FieldMetadataType.TEXT:
case FieldMetadataType.PHONE:
case FieldMetadataType.EMAIL:
case FieldMetadataType.NUMBER:
case FieldMetadataType.BOOLEAN:
case FieldMetadataType.DATE:
return {
value: `column_${uuidToBase36(v4())}`,
};
case 'url':
case FieldMetadataType.URL:
return {
text: `column_${uuidToBase36(v4())}`,
link: `column_${uuidToBase36(v4())}`,
};
case 'money':
case FieldMetadataType.MONEY:
return {
amount: `column_${uuidToBase36(v4())}`,
currency: `column_${uuidToBase36(v4())}`,
@ -56,7 +58,7 @@ export function convertFieldMetadataToColumnActions(
fieldMetadata: FieldMetadata,
): TenantMigrationColumnAction[] {
switch (fieldMetadata.type) {
case 'text':
case FieldMetadataType.TEXT:
return [
{
name: fieldMetadata.targetColumnMap.value,
@ -64,8 +66,8 @@ export function convertFieldMetadataToColumnActions(
type: 'text',
},
];
case 'phone':
case 'email':
case FieldMetadataType.PHONE:
case FieldMetadataType.EMAIL:
return [
{
name: fieldMetadata.targetColumnMap.value,
@ -73,7 +75,7 @@ export function convertFieldMetadataToColumnActions(
type: 'varchar',
},
];
case 'number':
case FieldMetadataType.NUMBER:
return [
{
name: fieldMetadata.targetColumnMap.value,
@ -81,7 +83,7 @@ export function convertFieldMetadataToColumnActions(
type: 'integer',
},
];
case 'boolean':
case FieldMetadataType.BOOLEAN:
return [
{
name: fieldMetadata.targetColumnMap.value,
@ -89,7 +91,7 @@ export function convertFieldMetadataToColumnActions(
type: 'boolean',
},
];
case 'date':
case FieldMetadataType.DATE:
return [
{
name: fieldMetadata.targetColumnMap.value,
@ -97,7 +99,7 @@ export function convertFieldMetadataToColumnActions(
type: 'timestamp',
},
];
case 'url':
case FieldMetadataType.URL:
return [
{
name: fieldMetadata.targetColumnMap.text,
@ -110,7 +112,7 @@ export function convertFieldMetadataToColumnActions(
type: 'varchar',
},
];
case 'money':
case FieldMetadataType.MONEY:
return [
{
name: fieldMetadata.targetColumnMap.amount,
@ -127,24 +129,3 @@ export function convertFieldMetadataToColumnActions(
throw new Error(`Unknown type ${fieldMetadata.type}`);
}
}
// Deprecated with target_column_name deprecation
export function convertMetadataTypeToColumnType(type: string) {
switch (type) {
case 'text':
case 'url':
case 'phone':
case 'email':
return 'text';
case 'number':
return 'int';
case 'boolean':
return 'boolean';
case 'date':
return 'timestamp';
case 'money':
return 'integer';
default:
throw new Error('Invalid type');
}
}

View File

@ -0,0 +1,25 @@
import { TableColumnOptions } from 'typeorm';
export const customTableDefaultColumns: TableColumnOptions[] = [
{
name: 'id',
type: 'uuid',
isPrimary: true,
default: 'public.uuid_generate_v4()',
},
{
name: 'createdAt',
type: 'timestamp',
default: 'now()',
},
{
name: 'updatedAt',
type: 'timestamp',
default: 'now()',
},
{
name: 'deletedAt',
type: 'timestamp',
isNullable: true,
},
];

Some files were not shown because too many files have changed in this diff Show More