From 5df73f8d1df87909e6aa47243858a0525024aa2c Mon Sep 17 00:00:00 2001 From: guillim Date: Thu, 14 Nov 2024 18:16:21 +0100 Subject: [PATCH 01/16] new display --- packages/twenty-ui/src/display/index.ts | 2 +- .../tooltip/OverflowingTextWithTooltip.tsx | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/twenty-ui/src/display/index.ts b/packages/twenty-ui/src/display/index.ts index 45144332b2bf..e8f248ba7a31 100644 --- a/packages/twenty-ui/src/display/index.ts +++ b/packages/twenty-ui/src/display/index.ts @@ -49,8 +49,8 @@ export * from './icon/types/IconComponent'; export * from './info/components/Info'; export * from './status/components/Status'; export * from './tag/components/Tag'; -export * from './text/components/SeparatorLineText'; export * from './text/components/HorizontalSeparator'; +export * from './text/components/SeparatorLineText'; export * from './tooltip/AppTooltip'; export * from './tooltip/OverflowingTextWithTooltip'; export * from './typography/components/H1Title'; diff --git a/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx b/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx index 7f8df1450282..ed2d81b50d5d 100644 --- a/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx +++ b/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx @@ -11,6 +11,7 @@ const spacing4 = THEME_COMMON.spacing(4); const StyledOverflowingText = styled.div<{ cursorPointer: boolean; size: 'large' | 'small'; + multilineNumber?: number; }>` cursor: ${({ cursorPointer }) => (cursorPointer ? 'pointer' : 'inherit')}; font-family: inherit; @@ -26,6 +27,14 @@ const StyledOverflowingText = styled.div<{ height: ${({ size }) => (size === 'large' ? spacing4 : 'auto')}; + text-wrap: ${({ multilineNumber }) => (multilineNumber ? 'auto' : 'inherit')}; + -webkit-line-clamp: ${({ multilineNumber }) => + multilineNumber ? multilineNumber : 'inherit'}; + display: ${({ multilineNumber }) => + multilineNumber ? `-webkit-box` : 'inherit'}; + -webkit-box-orient: ${({ multilineNumber }) => + multilineNumber ? 'vertical' : 'inherit'}; + & :hover { text-overflow: ${({ cursorPointer }) => cursorPointer ? 'clip' : 'ellipsis'}; @@ -37,11 +46,13 @@ const StyledOverflowingText = styled.div<{ export const OverflowingTextWithTooltip = ({ size = 'small', text, - mutliline, + multiline, + multilineNumber, }: { size?: 'large' | 'small'; text: string | null | undefined; - mutliline?: boolean; + multiline?: boolean; + multilineNumber?: number; }) => { const textElementId = `title-id-${+new Date()}`; @@ -74,6 +85,7 @@ export const OverflowingTextWithTooltip = ({ data-testid="tooltip" cursorPointer={isTitleOverflowing} size={size} + multilineNumber={multilineNumber} ref={textRef} id={textElementId} onMouseEnter={handleMouseEnter} @@ -86,7 +98,7 @@ export const OverflowingTextWithTooltip = ({
- {mutliline ?
{text}
: ''} + {multiline ?
{text}
: ''}
, document.body, From f3f91fe84c7a6b727dce99835aca8ae5642c11da Mon Sep 17 00:00:00 2001 From: guillim Date: Thu, 14 Nov 2024 18:42:37 +0100 Subject: [PATCH 02/16] removing usued --- .../modules/ui/field/display/components/DoubleTextDisplay.tsx | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 packages/twenty-front/src/modules/ui/field/display/components/DoubleTextDisplay.tsx diff --git a/packages/twenty-front/src/modules/ui/field/display/components/DoubleTextDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/DoubleTextDisplay.tsx deleted file mode 100644 index d8c2ac0b1bc6..000000000000 --- a/packages/twenty-front/src/modules/ui/field/display/components/DoubleTextDisplay.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { TextDisplay } from './TextDisplay'; - -export const DoubleTextDisplay = TextDisplay; From 55eea86e108ad148e42c4c057c5762d58edbfee0 Mon Sep 17 00:00:00 2001 From: guillim Date: Thu, 14 Nov 2024 18:42:56 +0100 Subject: [PATCH 03/16] renaming props --- .../tooltip/OverflowingTextWithTooltip.tsx | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx b/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx index ed2d81b50d5d..f39f12f9161f 100644 --- a/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx +++ b/packages/twenty-ui/src/display/tooltip/OverflowingTextWithTooltip.tsx @@ -11,7 +11,7 @@ const spacing4 = THEME_COMMON.spacing(4); const StyledOverflowingText = styled.div<{ cursorPointer: boolean; size: 'large' | 'small'; - multilineNumber?: number; + displayMaxRows?: number; }>` cursor: ${({ cursorPointer }) => (cursorPointer ? 'pointer' : 'inherit')}; font-family: inherit; @@ -27,13 +27,13 @@ const StyledOverflowingText = styled.div<{ height: ${({ size }) => (size === 'large' ? spacing4 : 'auto')}; - text-wrap: ${({ multilineNumber }) => (multilineNumber ? 'auto' : 'inherit')}; - -webkit-line-clamp: ${({ multilineNumber }) => - multilineNumber ? multilineNumber : 'inherit'}; - display: ${({ multilineNumber }) => - multilineNumber ? `-webkit-box` : 'inherit'}; - -webkit-box-orient: ${({ multilineNumber }) => - multilineNumber ? 'vertical' : 'inherit'}; + text-wrap: ${({ displayMaxRows }) => (displayMaxRows ? 'auto' : 'inherit')}; + -webkit-line-clamp: ${({ displayMaxRows }) => + displayMaxRows ? displayMaxRows : 'inherit'}; + display: ${({ displayMaxRows }) => + displayMaxRows ? `-webkit-box` : 'inherit'}; + -webkit-box-orient: ${({ displayMaxRows }) => + displayMaxRows ? 'vertical' : 'inherit'}; & :hover { text-overflow: ${({ cursorPointer }) => @@ -46,13 +46,13 @@ const StyledOverflowingText = styled.div<{ export const OverflowingTextWithTooltip = ({ size = 'small', text, - multiline, - multilineNumber, + isTooltipMultiline, + displayMaxRows, }: { size?: 'large' | 'small'; text: string | null | undefined; - multiline?: boolean; - multilineNumber?: number; + isTooltipMultiline?: boolean; + displayMaxRows?: number; }) => { const textElementId = `title-id-${+new Date()}`; @@ -85,7 +85,7 @@ export const OverflowingTextWithTooltip = ({ data-testid="tooltip" cursorPointer={isTitleOverflowing} size={size} - multilineNumber={multilineNumber} + displayMaxRows={displayMaxRows} ref={textRef} id={textElementId} onMouseEnter={handleMouseEnter} @@ -98,7 +98,7 @@ export const OverflowingTextWithTooltip = ({
- {multiline ?
{text}
: ''} + {isTooltipMultiline ?
{text}
: ''}
, document.body, From b92fb197dec5f4616f34e60387ef64e1f6548b30 Mon Sep 17 00:00:00 2001 From: guillim Date: Thu, 14 Nov 2024 18:45:13 +0100 Subject: [PATCH 04/16] adding property --- .../meta-types/display/components/TextFieldDisplay.tsx | 9 +++++++-- .../modules/ui/field/display/components/TextDisplay.tsx | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/TextFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/TextFieldDisplay.tsx index ce56ff7a6bb1..74b0d458390c 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/TextFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/TextFieldDisplay.tsx @@ -2,7 +2,12 @@ import { useTextFieldDisplay } from '@/object-record/record-field/meta-types/hoo import { TextDisplay } from '@/ui/field/display/components/TextDisplay'; export const TextFieldDisplay = () => { - const { fieldValue } = useTextFieldDisplay(); + const { fieldValue, fieldDefinition } = useTextFieldDisplay(); - return ; + return ( + + ); }; diff --git a/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx index 74f7f002df9f..7ca7fc0c1379 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx @@ -2,8 +2,9 @@ import { OverflowingTextWithTooltip } from 'twenty-ui'; type TextDisplayProps = { text: string; + displayMaxRows?: number; }; -export const TextDisplay = ({ text }: TextDisplayProps) => ( - +export const TextDisplay = ({ text, displayMaxRows }: TextDisplayProps) => ( + ); From 5461079502b84426506b836ecf3dcdc62f1d3bdc Mon Sep 17 00:00:00 2001 From: guillim Date: Fri, 15 Nov 2024 12:09:49 +0100 Subject: [PATCH 05/16] Server side for Text (setting field) validation --- .../record-field/types/FieldMetadata.ts | 4 ++- .../field-metadata-validation.service.ts | 26 ++++++++++++++----- .../field-metadata-settings.interface.ts | 5 ++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts b/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts index 53e037dbdaf6..8a0a92091ebc 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts @@ -23,7 +23,9 @@ export type FieldTextMetadata = { objectMetadataNameSingular?: string; placeHolder: string; fieldName: string; - settings?: Record; + settings?: { + displayMaxRows?: number; + }; }; export type FieldDateTimeMetadata = { diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata-validation.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata-validation.service.ts index 35b735fb2d94..80574970b2f7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata-validation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata-validation.service.ts @@ -5,6 +5,7 @@ import { IsEnum, IsInt, IsOptional, + Max, Min, validateOrReject, } from 'class-validator'; @@ -31,6 +32,12 @@ class SettingsValidation { @IsOptional() @IsEnum(ValueType) type?: 'percentage' | 'number'; + + @IsOptional() + @IsInt() + @Min(0) + @Max(100) + displayMaxRows?: number; } @Injectable() @@ -48,23 +55,28 @@ export class FieldMetadataValidationService< }) { switch (fieldType) { case FieldMetadataType.NUMBER: - await this.validateNumberSettings(settings); + await this.validateSettings(settings); + break; + case FieldMetadataType.TEXT: + await this.validateSettings(settings); break; default: break; } } - private async validateNumberSettings(settings: any) { + private async validateSettings(settings: any) { try { const settingsInstance = plainToInstance(SettingsValidation, settings); await validateOrReject(settingsInstance); - } catch (errors) { - const errorMessages = errors - .map((error: any) => Object.values(error.constraints)) - .flat() - .join(', '); + } catch (error) { + const errorMessages = Array.isArray(error) + ? error + .map((err: any) => Object.values(err.constraints)) + .flat() + .join(', ') + : error.message; throw new FieldMetadataException( `Value for settings is invalid: ${errorMessages}`, diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts index 727cbe2cf91e..69ffa2a91351 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts @@ -16,6 +16,10 @@ type FieldMetadataNumberSettings = { type?: string; }; +type FieldMetadataTextSettings = { + displayMaxRows?: number; +}; + type FieldMetadataDateSettings = { displayAsRelativeDate?: boolean; }; @@ -28,6 +32,7 @@ type FieldMetadataSettingsMapping = { [FieldMetadataType.NUMBER]: FieldMetadataNumberSettings; [FieldMetadataType.DATE]: FieldMetadataDateSettings; [FieldMetadataType.DATE_TIME]: FieldMetadataDateTimeSettings; + [FieldMetadataType.TEXT]: FieldMetadataTextSettings; }; type SettingsByFieldMetadata = From 3f951ec70de77c3df56b2b910c2db43811fe1336 Mon Sep 17 00:00:00 2001 From: guillim Date: Fri, 15 Nov 2024 17:17:33 +0100 Subject: [PATCH 06/16] new fields --- .../text/SettingsDataModelFieldTextForm.tsx | 96 +++++++++++++++++++ ...ingsDataModelFieldTextSettingsFormCard.tsx | 46 +++++++++ 2 files changed, 142 insertions(+) create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/text/SettingsDataModelFieldTextForm.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/text/SettingsDataModelFieldTextSettingsFormCard.tsx diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/text/SettingsDataModelFieldTextForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/text/SettingsDataModelFieldTextForm.tsx new file mode 100644 index 000000000000..b4f267ddad9a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/text/SettingsDataModelFieldTextForm.tsx @@ -0,0 +1,96 @@ +import { Controller, useFormContext } from 'react-hook-form'; + +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { Select } from '@/ui/input/components/Select'; +import styled from '@emotion/styled'; +import { CardContent } from 'twenty-ui'; +import { z } from 'zod'; + +const StyledFormCardTitle = styled.div` + color: ${({ theme }) => theme.font.color.light}; + font-size: ${({ theme }) => theme.font.size.xs}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + margin-bottom: ${({ theme }) => theme.spacing(1)}; +`; + +type SettingsDataModelFieldTextFormProps = { + disabled?: boolean; + fieldMetadataItem: Pick< + FieldMetadataItem, + 'icon' | 'label' | 'type' | 'defaultValue' | 'settings' + >; +}; + +export const textFieldDefaultValueSchema = z.object({ + displayMaxRows: z.number().nullable(), +}); + +export const settingsDataModelFieldtextFormSchema = z.object({ + settings: textFieldDefaultValueSchema, +}); + +export type SettingsDataModelFieldTextFormValues = z.infer< + typeof settingsDataModelFieldtextFormSchema +>; + +export const SettingsDataModelFieldTextForm = ({ + disabled, + fieldMetadataItem, +}: SettingsDataModelFieldTextFormProps) => { + const { control } = useFormContext(); + // console.log( + // 'SettingsDataModelFieldTextForm - fieldMetadataItem', + // fieldMetadataItem, + // ); + return ( + + { + console.log('value to disopaly in the form', value); + const displayMaxRows = value?.displayMaxRows ?? 0; + + return ( + <> + Wrap on record pages +