feat: address composite field (#4492)
Added new Address field input type. --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -9,6 +9,7 @@ import { fullNameObjectDefinition } from 'src/engine/metadata-modules/field-meta
|
||||
import { currencyObjectDefinition } from 'src/engine/metadata-modules/field-metadata/composite-types/currency.composite-type';
|
||||
import { linkObjectDefinition } from 'src/engine/metadata-modules/field-metadata/composite-types/link.composite-type';
|
||||
import { EnumTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory';
|
||||
import { addressObjectDefinition } from 'src/engine/metadata-modules/field-metadata/composite-types/address.composite-type';
|
||||
|
||||
import { TypeDefinitionsStorage } from './storages/type-definitions.storage';
|
||||
import {
|
||||
@ -68,7 +69,8 @@ export class TypeDefinitionsGenerator {
|
||||
currencyObjectDefinition,
|
||||
linkObjectDefinition,
|
||||
fullNameObjectDefinition,
|
||||
];
|
||||
addressObjectDefinition,
|
||||
] satisfies ObjectMetadataInterface[];
|
||||
|
||||
this.logger.log(
|
||||
`Generating staticObjects: [${staticObjectMetadataCollection
|
||||
|
||||
@ -104,5 +104,19 @@ export const mapFieldMetadataToGraphqlQuery = (
|
||||
lastName
|
||||
}
|
||||
`;
|
||||
} else if (fieldType === FieldMetadataType.ADDRESS) {
|
||||
return `
|
||||
${field.name}
|
||||
{
|
||||
addressStreet1
|
||||
addressStreet2
|
||||
addressCity
|
||||
addressPostcode
|
||||
addressState
|
||||
addressCountry
|
||||
addressLat
|
||||
addressLng
|
||||
}
|
||||
`;
|
||||
}
|
||||
};
|
||||
|
||||
@ -57,6 +57,7 @@ const getSchemaComponentsProperties = (
|
||||
case FieldMetadataType.LINK:
|
||||
case FieldMetadataType.CURRENCY:
|
||||
case FieldMetadataType.FULL_NAME:
|
||||
case FieldMetadataType.ADDRESS:
|
||||
itemProperty = {
|
||||
type: 'object',
|
||||
properties: Object.keys(field.targetColumnMap).reduce(
|
||||
|
||||
@ -0,0 +1,195 @@
|
||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { generateTargetColumnMap } from 'src/engine/metadata-modules/field-metadata/utils/generate-target-column-map.util';
|
||||
|
||||
export const addressFields = (
|
||||
fieldMetadata?: FieldMetadataInterface,
|
||||
): FieldMetadataInterface[] => {
|
||||
const inferredFieldMetadata = fieldMetadata as
|
||||
| FieldMetadataInterface<FieldMetadataType.ADDRESS>
|
||||
| undefined;
|
||||
const targetColumnMap = inferredFieldMetadata
|
||||
? generateTargetColumnMap(
|
||||
inferredFieldMetadata.type,
|
||||
inferredFieldMetadata.isCustom ?? false,
|
||||
inferredFieldMetadata.name,
|
||||
)
|
||||
: {
|
||||
addressStreet1: 'addressStreet1',
|
||||
addressStreet2: 'addressStreet2',
|
||||
addressCity: 'addressCity',
|
||||
addressPostcode: 'addressPostcode',
|
||||
addressState: 'addressState',
|
||||
addressCountry: 'addressCountry',
|
||||
addressLat: 'addressLat',
|
||||
addressLng: 'addressLng',
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'addressStreet1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressStreet1',
|
||||
label: 'Address',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressStreet1,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressStreet1 ?? undefined,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
|
||||
{
|
||||
id: 'addressStreet2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressStreet2',
|
||||
label: 'Address 2',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressStreet2,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressStreet2 ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
|
||||
{
|
||||
id: 'addressCity',
|
||||
type: FieldMetadataType.TEXT,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressCity',
|
||||
label: 'City',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressCity,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressCity ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
|
||||
{
|
||||
id: 'addressPostcode',
|
||||
type: FieldMetadataType.TEXT,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressPostcode',
|
||||
label: 'Postcode',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressPostcode,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressPostcode ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
|
||||
{
|
||||
id: 'addressState',
|
||||
type: FieldMetadataType.TEXT,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressState',
|
||||
label: 'State',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressState,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressState ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
|
||||
{
|
||||
id: 'addressCountry',
|
||||
type: FieldMetadataType.TEXT,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressCountry',
|
||||
label: 'Country',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressCountry,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressCountry ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
|
||||
{
|
||||
id: 'addressLat',
|
||||
type: FieldMetadataType.NUMBER,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressLat',
|
||||
label: 'Latitude',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressLat,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressLat ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.NUMBER>,
|
||||
{
|
||||
id: 'addressLng',
|
||||
type: FieldMetadataType.NUMBER,
|
||||
objectMetadataId: FieldMetadataType.ADDRESS.toString(),
|
||||
name: 'addressLng',
|
||||
label: 'Longitude',
|
||||
targetColumnMap: {
|
||||
value: targetColumnMap.addressLng,
|
||||
},
|
||||
isNullable: true,
|
||||
...(inferredFieldMetadata
|
||||
? {
|
||||
defaultValue:
|
||||
inferredFieldMetadata.defaultValue?.addressLng ?? null,
|
||||
}
|
||||
: {}),
|
||||
} satisfies FieldMetadataInterface<FieldMetadataType.NUMBER>,
|
||||
];
|
||||
};
|
||||
|
||||
export const addressObjectDefinition = {
|
||||
id: FieldMetadataType.ADDRESS.toString(),
|
||||
nameSingular: 'address',
|
||||
namePlural: 'address',
|
||||
labelSingular: 'Address',
|
||||
labelPlural: 'Addresses',
|
||||
targetTableName: '',
|
||||
fields: addressFields(),
|
||||
fromRelations: [],
|
||||
toRelations: [],
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
} satisfies ObjectMetadataInterface;
|
||||
|
||||
export type AddressMetadata = {
|
||||
addressStreet1: string;
|
||||
addressStreet2: string;
|
||||
addressCity: string;
|
||||
addressState: string;
|
||||
addressZipCode: string;
|
||||
addressCountry: string;
|
||||
addressLat: number;
|
||||
addressLng: number;
|
||||
};
|
||||
@ -4,6 +4,7 @@ import { currencyFields } from 'src/engine/metadata-modules/field-metadata/compo
|
||||
import { fullNameFields } from 'src/engine/metadata-modules/field-metadata/composite-types/full-name.composite-type';
|
||||
import { linkFields } from 'src/engine/metadata-modules/field-metadata/composite-types/link.composite-type';
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { addressFields } from 'src/engine/metadata-modules/field-metadata/composite-types/address.composite-type';
|
||||
|
||||
export type CompositeFieldsDefinitionFunction = (
|
||||
fieldMetadata?: FieldMetadataInterface,
|
||||
@ -16,4 +17,5 @@ export const compositeDefinitions = new Map<
|
||||
[FieldMetadataType.LINK, linkFields],
|
||||
[FieldMetadataType.CURRENCY, currencyFields],
|
||||
[FieldMetadataType.FULL_NAME, fullNameFields],
|
||||
[FieldMetadataType.ADDRESS, addressFields],
|
||||
]);
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsNumberString,
|
||||
IsString,
|
||||
Matches,
|
||||
ValidateIf,
|
||||
} from 'class-validator';
|
||||
@ -98,3 +99,36 @@ export class FieldMetadataDefaultValueNowFunction {
|
||||
@IsNotEmpty()
|
||||
value: typeof fieldMetadataDefaultValueFunctionName.NOW;
|
||||
}
|
||||
export class FieldMetadataDefaultValueAddress {
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsString()
|
||||
addressStreet1: string | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsString()
|
||||
addressStreet2: string | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsString()
|
||||
addressCity: string | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsString()
|
||||
addressPostcode: string | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsString()
|
||||
addressState: string | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsString()
|
||||
addressCountry: string | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsNumber()
|
||||
addressLat: number | null;
|
||||
|
||||
@ValidateIf((_object, value) => value !== null)
|
||||
@IsNumber()
|
||||
addressLng: number | null;
|
||||
}
|
||||
|
||||
@ -36,6 +36,8 @@ export enum FieldMetadataType {
|
||||
MULTI_SELECT = 'MULTI_SELECT',
|
||||
RELATION = 'RELATION',
|
||||
POSITION = 'POSITION',
|
||||
ADDRESS = 'ADDRESS',
|
||||
JSON = 'JSON',
|
||||
RAW_JSON = 'RAW_JSON',
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {
|
||||
FieldMetadataDefaultValueAddress,
|
||||
FieldMetadataDefaultValueBoolean,
|
||||
FieldMetadataDefaultValueCurrency,
|
||||
FieldMetadataDefaultValueDateTime,
|
||||
@ -35,6 +36,7 @@ type FieldMetadataDefaultValueMapping = {
|
||||
[FieldMetadataType.LINK]: FieldMetadataDefaultValueLink;
|
||||
[FieldMetadataType.CURRENCY]: FieldMetadataDefaultValueCurrency;
|
||||
[FieldMetadataType.FULL_NAME]: FieldMetadataDefaultValueFullName;
|
||||
[FieldMetadataType.ADDRESS]: FieldMetadataDefaultValueAddress;
|
||||
[FieldMetadataType.RATING]: FieldMetadataDefaultValueString;
|
||||
[FieldMetadataType.SELECT]: FieldMetadataDefaultValueString;
|
||||
[FieldMetadataType.MULTI_SELECT]: FieldMetadataDefaultValueStringArray;
|
||||
|
||||
@ -19,6 +19,17 @@ export interface FieldMetadataTargetColumnMapFullName {
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
export type FieldMetadataTargetColumnMapAddress = {
|
||||
addressStreet1: string;
|
||||
addressStreet2: string;
|
||||
addressCity: string;
|
||||
addressState: string;
|
||||
addressZipCode: string;
|
||||
addressCountry: string;
|
||||
addressLat: number;
|
||||
addressLng: number;
|
||||
};
|
||||
|
||||
type AllFieldMetadataTypes = {
|
||||
[key: string]: string;
|
||||
};
|
||||
@ -27,6 +38,7 @@ type FieldMetadataTypeMapping = {
|
||||
[FieldMetadataType.LINK]: FieldMetadataTargetColumnMapLink;
|
||||
[FieldMetadataType.CURRENCY]: FieldMetadataTargetColumnMapCurrency;
|
||||
[FieldMetadataType.FULL_NAME]: FieldMetadataTargetColumnMapFullName;
|
||||
[FieldMetadataType.ADDRESS]: FieldMetadataTargetColumnMapAddress;
|
||||
};
|
||||
|
||||
type TypeByFieldMetadata<T extends FieldMetadataType | 'default'> = [
|
||||
|
||||
@ -15,6 +15,17 @@ export function generateDefaultValue(
|
||||
firstName: "''",
|
||||
lastName: "''",
|
||||
};
|
||||
case FieldMetadataType.ADDRESS:
|
||||
return {
|
||||
addressStreet1: "''",
|
||||
addressStreet2: "''",
|
||||
addressCity: "''",
|
||||
addressState: "''",
|
||||
addressCountry: "''",
|
||||
addressPostcode: "''",
|
||||
addressLat: null,
|
||||
addressLng: null,
|
||||
};
|
||||
case FieldMetadataType.LINK:
|
||||
return {
|
||||
url: "''",
|
||||
|
||||
@ -54,6 +54,17 @@ export function generateTargetColumnMap(
|
||||
firstName: `${columnName}FirstName`,
|
||||
lastName: `${columnName}LastName`,
|
||||
};
|
||||
case FieldMetadataType.ADDRESS:
|
||||
return {
|
||||
addressStreet1: `${columnName}AddressStreet1`,
|
||||
addressStreet2: `${columnName}AddressStreet2`,
|
||||
addressCity: `${columnName}AddressCity`,
|
||||
addressPostcode: `${columnName}AddressPostcode`,
|
||||
addressState: `${columnName}AddressState`,
|
||||
addressCountry: `${columnName}AddressCountry`,
|
||||
addressLat: `${columnName}AddressLat`,
|
||||
addressLng: `${columnName}AddressLng`,
|
||||
};
|
||||
case FieldMetadataType.RELATION:
|
||||
return {};
|
||||
default:
|
||||
|
||||
@ -9,6 +9,7 @@ export const isCompositeFieldMetadataType = (
|
||||
return (
|
||||
type === FieldMetadataType.LINK ||
|
||||
type === FieldMetadataType.CURRENCY ||
|
||||
type === FieldMetadataType.FULL_NAME
|
||||
type === FieldMetadataType.FULL_NAME ||
|
||||
type === FieldMetadataType.ADDRESS
|
||||
);
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import {
|
||||
FieldMetadataDefaultValueAddress,
|
||||
FieldMetadataDefaultValueBoolean,
|
||||
FieldMetadataDefaultValueCurrency,
|
||||
FieldMetadataDefaultValueDateTime,
|
||||
@ -44,6 +45,7 @@ export const defaultValueValidatorsMap = {
|
||||
[FieldMetadataType.RATING]: [FieldMetadataDefaultValueString],
|
||||
[FieldMetadataType.SELECT]: [FieldMetadataDefaultValueString],
|
||||
[FieldMetadataType.MULTI_SELECT]: [FieldMetadataDefaultValueStringArray],
|
||||
[FieldMetadataType.ADDRESS]: [FieldMetadataDefaultValueAddress],
|
||||
[FieldMetadataType.RAW_JSON]: [FieldMetadataDefaultValueRawJson],
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ export const companyPrefillDemoData = async (
|
||||
.into(`${schemaName}.company`, [
|
||||
'name',
|
||||
'domainName',
|
||||
'address',
|
||||
'addressAddressCity',
|
||||
'employees',
|
||||
'linkedinLinkUrl',
|
||||
'position',
|
||||
|
||||
Reference in New Issue
Block a user