feat: add Url field preview in settings (#2402)

* feat: add Url field preview in settings

Closes #2326

* feat: add Date field type in settings (#2414)

Closes #2331
This commit is contained in:
Thaïs 2023-11-09 18:51:21 +01:00 committed by GitHub
parent 588091d3dd
commit b28ff9c97e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 70 additions and 16 deletions

View File

@ -6,6 +6,7 @@ import { logError } from '~/utils/logError';
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
import { PaginatedObjectType } from '../types/PaginatedObjectType';
import { PaginatedObjectTypeResults } from '../types/PaginatedObjectTypeResults';
import { formatPagedObjectsToObjects } from '../utils/formatPagedObjectsToObjects';
import { useFindOneObjectMetadataItem } from './useFindOneObjectMetadataItem';
@ -23,7 +24,7 @@ export const useFindManyObjects = <
}: Pick<ObjectMetadataItemIdentifier, 'objectNamePlural'> & {
filter?: any;
orderBy?: any;
onCompleted?: (data: any) => void;
onCompleted?: (data: PaginatedObjectTypeResults<ObjectType>) => void;
skip?: boolean;
}) => {
const { foundObjectMetadataItem, objectNotFoundInMetadata, findManyQuery } =

View File

@ -64,7 +64,9 @@ export const SettingsObjectFieldTypeSelectSection = ({
}),
)}
/>
{['BOOLEAN', 'MONEY', 'NUMBER', 'TEXT'].includes(fieldType) && (
{['BOOLEAN', 'DATE', 'MONEY', 'NUMBER', 'TEXT', 'URL'].includes(
fieldType,
) && (
<StyledSettingsObjectFieldTypeCard
preview={
<SettingsObjectFieldPreview

View File

@ -1,3 +1,4 @@
import { MemoryRouter } from 'react-router-dom';
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
@ -40,6 +41,29 @@ export const Currency: Story = {
},
};
export const Date: Story = {
args: {
fieldIconKey: 'IconCalendarEvent',
fieldLabel: 'Registration Date',
fieldType: 'DATE',
},
};
export const Link: Story = {
decorators: [
(Story) => (
<MemoryRouter>
<Story />
</MemoryRouter>
),
],
args: {
fieldIconKey: 'IconWorldWww',
fieldLabel: 'Website',
fieldType: 'URL',
},
};
export const Number: Story = {
args: {
fieldIconKey: 'IconUsers',

View File

@ -1,4 +1,5 @@
import {
IconCalendarEvent,
IconCheck,
IconCoins,
IconLink,
@ -11,23 +12,35 @@ import { Currency } from '~/generated-metadata/graphql';
import { MetadataFieldDataType } from '../types/ObjectFieldDataType';
const defaultDateValue = new Date();
defaultDateValue.setFullYear(defaultDateValue.getFullYear() + 2);
export const dataTypes: Record<
MetadataFieldDataType,
{ label: string; Icon: IconComponent; defaultValue?: unknown }
> = {
BOOLEAN: { label: 'True/False', Icon: IconCheck, defaultValue: true },
MONEY: {
label: 'Currency',
Icon: IconCoins,
defaultValue: { amount: 2000, currency: Currency.Usd },
},
NUMBER: { label: 'Number', Icon: IconNumbers, defaultValue: 2000 },
RELATION: { label: 'Relation', Icon: IconPlug },
TEXT: {
label: 'Text',
Icon: IconTextSize,
defaultValue:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum magna enim, dapibus non enim in, lacinia faucibus nunc. Sed interdum ante sed felis facilisis, eget ultricies neque molestie. Mauris auctor, justo eu volutpat cursus, libero erat tempus nulla, non sodales lorem lacus a est.',
},
URL: { label: 'Link', Icon: IconLink },
NUMBER: { label: 'Number', Icon: IconNumbers, defaultValue: 2000 },
URL: {
label: 'Link',
Icon: IconLink,
defaultValue: { link: 'www.twenty.com', text: '' },
},
BOOLEAN: { label: 'True/False', Icon: IconCheck, defaultValue: true },
DATE: {
label: 'Date',
Icon: IconCalendarEvent,
defaultValue: defaultDateValue.toISOString(),
},
MONEY: {
label: 'Currency',
Icon: IconCoins,
defaultValue: { amount: 2000, currency: Currency.Usd },
},
RELATION: { label: 'Relation', Icon: IconPlug },
};

View File

@ -1,5 +1,6 @@
export type MetadataFieldDataType =
| 'BOOLEAN'
| 'DATE'
| 'MONEY'
| 'NUMBER'
| 'RELATION'

View File

@ -50,7 +50,7 @@ export const URLV2Display = ({ value }: URLV2DisplayProps) => {
: 'https://' + value.link
: '';
const displayedValue = value?.text ?? '';
const displayedValue = value?.text || value?.link || '';
const type = checkUrlType(absoluteUrl);

View File

@ -9,6 +9,7 @@ import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldURL } from '../../types/guards/isFieldURL';
import { isFieldURLValue } from '../../types/guards/isFieldURLValue';
export const useURLField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
@ -23,12 +24,13 @@ export const useURLField = () => {
fieldName: fieldName,
}),
);
const fieldUrlValue = isFieldURLValue(fieldValue) ? fieldValue : '';
const fieldInitialValue = useFieldInitialValue();
const initialValue = fieldInitialValue?.isEmpty
? ''
: fieldInitialValue?.value ?? fieldValue;
: fieldInitialValue?.value ?? fieldUrlValue;
const persistField = usePersistField();
@ -42,7 +44,7 @@ export const useURLField = () => {
return {
fieldDefinition,
fieldValue,
fieldValue: fieldUrlValue,
initialValue,
setFieldValue,
hotkeyScope,

View File

@ -28,7 +28,9 @@ export const useURLV2Field = () => {
const initialValue: FieldURLV2Value = fieldInitialValue?.isEmpty
? { link: '', text: '' }
: { link: fieldInitialValue?.value ?? '', text: '' } ?? fieldValue;
: fieldInitialValue?.value
? { link: fieldInitialValue.value, text: '' }
: fieldValue;
const persistField = usePersistField();

View File

@ -19,6 +19,8 @@ import { isFieldRelation } from '../../types/guards/isFieldRelation';
import { isFieldRelationValue } from '../../types/guards/isFieldRelationValue';
import { isFieldText } from '../../types/guards/isFieldText';
import { isFieldURL } from '../../types/guards/isFieldURL';
import { isFieldURLV2 } from '../../types/guards/isFieldURLV2';
import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
import { entityFieldsFamilyState } from '../entityFieldsFamilyState';
const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === '';
@ -104,6 +106,13 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
);
}
if (isFieldURLV2(fieldDefinition)) {
const fieldName = fieldDefinition.metadata.fieldName;
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
return !isFieldURLV2Value(fieldValue) || isValueEmpty(fieldValue?.link);
}
throw new Error(
`Entity field type not supported in isEntityFieldEmptyFamilySelector : ${fieldDefinition.type}}`,
);

View File

@ -18,7 +18,7 @@ export const SettingsExperience = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer width={350}>
<SettingsPageContainer>
<StyledH1Title title="Experience" />
<Section>
<H2Title title="Appearance" />