Skip to content

Commit

Permalink
feat: update links field (twentyhq#5212)
Browse files Browse the repository at this point in the history
Closes twentyhq#5113

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
  • Loading branch information
2 people authored and i-am-chitti committed May 4, 2024
1 parent 3e8fa12 commit 2f1e6c4
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { isUndefined } from '@sniptt/guards';

import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import {
FieldMetadataType,
RelationMetadataType,
} from '~/generated-metadata/graphql';

import { FieldMetadataItem } from '../types/FieldMetadataItem';

Expand All @@ -23,29 +26,29 @@ export const mapFieldMetadataToGraphQLQuery = ({
}): any => {
const fieldType = field.type;

const fieldIsSimpleValue = (
[
'UUID',
'TEXT',
'PHONE',
'DATE_TIME',
'DATE',
'EMAIL',
'NUMBER',
'BOOLEAN',
'RATING',
'SELECT',
'MULTI_SELECT',
'POSITION',
'RAW_JSON',
] as FieldMetadataType[]
).includes(fieldType);
const fieldIsSimpleValue = [
FieldMetadataType.Uuid,
FieldMetadataType.Text,
FieldMetadataType.Phone,
FieldMetadataType.DateTime,
FieldMetadataType.Date,
FieldMetadataType.Email,
FieldMetadataType.Number,
FieldMetadataType.Boolean,
FieldMetadataType.Rating,
FieldMetadataType.Select,
FieldMetadataType.MultiSelect,
FieldMetadataType.Position,
FieldMetadataType.RawJson,
].includes(fieldType);

if (fieldIsSimpleValue) {
return field.name;
} else if (
fieldType === 'RELATION' &&
field.toRelationMetadata?.relationType === 'ONE_TO_MANY'
}

if (
fieldType === FieldMetadataType.Relation &&
field.toRelationMetadata?.relationType === RelationMetadataType.OneToMany
) {
const relationMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
Expand All @@ -65,9 +68,11 @@ ${mapObjectMetadataToGraphQLQuery({
computeReferences: computeReferences,
isRootLevel: false,
})}`;
} else if (
fieldType === 'RELATION' &&
field.fromRelationMetadata?.relationType === 'ONE_TO_MANY'
}

if (
fieldType === FieldMetadataType.Relation &&
field.fromRelationMetadata?.relationType === RelationMetadataType.OneToMany
) {
const relationMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
Expand All @@ -91,26 +96,43 @@ ${mapObjectMetadataToGraphQLQuery({
})}
}
}`;
} else if (fieldType === 'LINK') {
}

if (fieldType === FieldMetadataType.Link) {
return `${field.name}
{
label
url
}`;
} else if (fieldType === 'CURRENCY') {
}

if (fieldType === FieldMetadataType.Links) {
return `${field.name}
{
primaryLinkUrl
primaryLinkLabel
secondaryLinks
}`;
}

if (fieldType === FieldMetadataType.Currency) {
return `${field.name}
{
amountMicros
currencyCode
}
`;
} else if (fieldType === 'FULL_NAME') {
}

if (fieldType === FieldMetadataType.FullName) {
return `${field.name}
{
firstName
lastName
}`;
} else if (fieldType === 'ADDRESS') {
}

if (fieldType === FieldMetadataType.Address) {
return `${field.name}
{
addressStreet1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const LinksFieldInput = ({
persistLinksField({
primaryLinkUrl: url,
primaryLinkLabel: '',
secondaryLinks: [],
}),
);
};
Expand All @@ -36,6 +37,7 @@ export const LinksFieldInput = ({
persistLinksField({
primaryLinkUrl: url,
primaryLinkLabel: '',
secondaryLinks: [],
}),
);
};
Expand All @@ -45,6 +47,7 @@ export const LinksFieldInput = ({
persistLinksField({
primaryLinkUrl: url,
primaryLinkLabel: '',
secondaryLinks: [],
}),
);
};
Expand All @@ -54,6 +57,7 @@ export const LinksFieldInput = ({
persistLinksField({
primaryLinkUrl: url,
primaryLinkLabel: '',
secondaryLinks: [],
}),
);
};
Expand All @@ -63,6 +67,7 @@ export const LinksFieldInput = ({
persistLinksField({
primaryLinkUrl: url,
primaryLinkLabel: '',
secondaryLinks: [],
}),
);
};
Expand All @@ -71,6 +76,7 @@ export const LinksFieldInput = ({
setDraftValue({
primaryLinkUrl: url,
primaryLinkLabel: '',
secondaryLinks: [],
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type FieldLinkDraftValue = { url: string; label: string };
export type FieldLinksDraftValue = {
primaryLinkLabel: string;
primaryLinkUrl: string;
secondaryLinks?: string | null;
secondaryLinks?: { label: string; url: string }[] | null;
};
export type FieldCurrencyDraftValue = {
currencyCode: CurrencyCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export type FieldLinkValue = { url: string; label: string };
export type FieldLinksValue = {
primaryLinkLabel: string;
primaryLinkUrl: string;
secondaryLinks?: string | null;
secondaryLinks?: { label: string; url: string }[] | null;
};
export type FieldCurrencyValue = {
currencyCode: CurrencyCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { FieldLinksValue } from '../FieldMetadata';
export const linksSchema = z.object({
primaryLinkLabel: z.string(),
primaryLinkUrl: absoluteUrlSchema,
secondaryLinks: z.string().optional().nullable(),
secondaryLinks: z
.array(z.object({ label: z.string(), url: absoluteUrlSchema }))
.nullable(),
}) satisfies z.ZodType<FieldLinksValue>;

export const isFieldLinksValue = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JsonScalarType } from './json.scalar';
import { RawJSONScalar } from './raw-json.scalar';
import { PositionScalarType } from './position.scalar';
import { CursorScalarType } from './cursor.scalar';
import { BigFloatScalarType } from './big-float.scalar';
Expand All @@ -25,5 +25,5 @@ export const scalars = [
UUIDScalarType,
CursorScalarType,
PositionScalarType,
JsonScalarType,
RawJSONScalar,
];

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { GraphQLScalarType } from 'graphql';
import { Maybe } from 'graphql-yoga';
import { ObjMap } from 'graphql/jsutils/ObjMap';
import { ASTNode, Kind, ValueNode } from 'graphql/language';

const parseLiteral = (
ast: ValueNode,
variables?: Maybe<ObjMap<unknown>>,
): any => {
switch (ast.kind) {
case Kind.STRING:
case Kind.BOOLEAN:
return ast.value;
case Kind.INT:
case Kind.FLOAT:
return parseFloat(ast.value);
case Kind.OBJECT:
return parseObject(ast as any, variables);
case Kind.LIST:
return (ast as any).values.map((n: ValueNode) =>
parseLiteral(n, variables),
);
case Kind.NULL:
return null;
case Kind.VARIABLE:
return variables ? variables[ast.name.value] : undefined;
default:
throw new TypeError(
`JSONStringify cannot represent value: ${JSON.stringify(ast)}`,
);
}
};

const parseObject = (
ast: ASTNode,
variables?: Maybe<ObjMap<unknown>>,
): object => {
const value = Object.create(null);

if ('fields' in ast) {
ast.fields?.forEach((field: any) => {
value[field.name.value] = parseLiteral(field.value, variables);
});
}

return value;
};

const stringify = (value: any): string => {
return JSON.stringify(value);
};

const parseJSON = (value: string): object => {
try {
return JSON.parse(value);
} catch (e) {
throw new TypeError(`Value is not valid JSON: ${value}`);
}
};

export const RawJSONScalar = new GraphQLScalarType({
name: 'RawJSONScalar',
description:
'The `RawJSONScalar` scalar type represents JSON values, but stringifies inputs and parses outputs.',
serialize: parseJSON,
parseValue: stringify,
parseLiteral: (ast, variables) => {
if (ast.kind === Kind.STRING) {
return stringify(ast.value);
} else {
return stringify(parseLiteral(ast, variables));
}
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
UUIDScalarType,
} from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { PositionScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars/position.scalar';
import { JsonScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars/json.scalar';
import { RawJSONScalar } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars/raw-json.scalar';
import { IDFilterType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/input/id-filter.input-type';

export interface TypeOptions<T = any> {
Expand Down Expand Up @@ -76,7 +76,7 @@ export class TypeMapperService {
[FieldMetadataType.NUMERIC, BigFloatScalarType],
[FieldMetadataType.PROBABILITY, GraphQLFloat],
[FieldMetadataType.POSITION, PositionScalarType],
[FieldMetadataType.RAW_JSON, JsonScalarType],
[FieldMetadataType.RAW_JSON, RawJSONScalar],
]);

return typeScalarMapping.get(fieldMetadataType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ export const linksCompositeType: CompositeType = {
export type LinksMetadata = {
primaryLinkLabel: string;
primaryLinkUrl: string;
secondaryLinks: JSON | null;
secondaryLinks: object | null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {
IsArray,
IsBoolean,
IsDate,
IsJSON,
IsNotEmpty,
IsNumber,
IsNumberString,
IsObject,
IsString,
Matches,
ValidateIf,
Expand All @@ -28,9 +28,9 @@ export class FieldMetadataDefaultValueString {
}

export class FieldMetadataDefaultValueRawJson {
@ValidateIf((object, value) => value !== null)
@IsJSON()
value: JSON | null;
@ValidateIf((_object, value) => value !== null)
@IsObject()
value: object | null;
}

export class FieldMetadataDefaultValueNumber {
Expand Down Expand Up @@ -149,6 +149,6 @@ export class FieldMetadataDefaultValueLinks {
primaryLinkUrl: string | null;

@ValidateIf((_object, value) => value !== null)
@IsJSON()
secondaryLinks: JSON | null;
@IsObject()
secondaryLinks: object | null;
}

0 comments on commit 2f1e6c4

Please sign in to comment.