mirror of
https://github.com/twentyhq/twenty.git
synced 2025-01-09 02:11:55 +03:00
Add links composite field (#9059)
- only primary links for now - need for a global strat for validation. This will come later
This commit is contained in:
parent
7e67b1c5a6
commit
32e7eb79b9
@ -1,6 +1,7 @@
|
|||||||
import { FormAddressFieldInput } from '@/object-record/record-field/form-types/components/FormAddressFieldInput';
|
import { FormAddressFieldInput } from '@/object-record/record-field/form-types/components/FormAddressFieldInput';
|
||||||
import { FormBooleanFieldInput } from '@/object-record/record-field/form-types/components/FormBooleanFieldInput';
|
import { FormBooleanFieldInput } from '@/object-record/record-field/form-types/components/FormBooleanFieldInput';
|
||||||
import { FormFullNameFieldInput } from '@/object-record/record-field/form-types/components/FormFullNameFieldInput';
|
import { FormFullNameFieldInput } from '@/object-record/record-field/form-types/components/FormFullNameFieldInput';
|
||||||
|
import { FormLinksFieldInput } from '@/object-record/record-field/form-types/components/FormLinksFieldInput';
|
||||||
import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput';
|
import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput';
|
||||||
import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput';
|
import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput';
|
||||||
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
|
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
|
||||||
@ -9,11 +10,13 @@ import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinit
|
|||||||
import {
|
import {
|
||||||
FieldAddressValue,
|
FieldAddressValue,
|
||||||
FieldFullNameValue,
|
FieldFullNameValue,
|
||||||
|
FieldLinksValue,
|
||||||
FieldMetadata,
|
FieldMetadata,
|
||||||
} from '@/object-record/record-field/types/FieldMetadata';
|
} from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
|
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
|
||||||
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
|
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
|
||||||
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
||||||
|
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
|
||||||
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
||||||
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
|
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
|
||||||
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
||||||
@ -74,7 +77,14 @@ export const FormFieldInput = ({
|
|||||||
) : isFieldAddress(field) ? (
|
) : isFieldAddress(field) ? (
|
||||||
<FormAddressFieldInput
|
<FormAddressFieldInput
|
||||||
label={field.label}
|
label={field.label}
|
||||||
defaultValue={defaultValue as FieldAddressValue}
|
defaultValue={defaultValue as FieldAddressValue | undefined}
|
||||||
|
onPersist={onPersist}
|
||||||
|
VariablePicker={VariablePicker}
|
||||||
|
/>
|
||||||
|
) : isFieldLinks(field) ? (
|
||||||
|
<FormLinksFieldInput
|
||||||
|
label={field.label}
|
||||||
|
defaultValue={defaultValue as FieldLinksValue | undefined}
|
||||||
onPersist={onPersist}
|
onPersist={onPersist}
|
||||||
VariablePicker={VariablePicker}
|
VariablePicker={VariablePicker}
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FormCountrySelectInput } from '@/object-record/record-field/form-types/components/FormCountrySelectInput';
|
import { FormCountrySelectInput } from '@/object-record/record-field/form-types/components/FormCountrySelectInput';
|
||||||
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
|
|
||||||
import { FormNestedFieldInputContainer } from '@/object-record/record-field/form-types/components/FormNestedFieldInputContainer';
|
|
||||||
import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer';
|
import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer';
|
||||||
|
import { FormNestedFieldInputContainer } from '@/object-record/record-field/form-types/components/FormNestedFieldInputContainer';
|
||||||
|
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
|
||||||
import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
|
import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
|
||||||
import { FieldAddressDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
import { FieldAddressDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
||||||
import { FieldAddressValue } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldAddressValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
@ -9,7 +9,7 @@ import { InputLabel } from '@/ui/input/components/InputLabel';
|
|||||||
|
|
||||||
type FormAddressFieldInputProps = {
|
type FormAddressFieldInputProps = {
|
||||||
label?: string;
|
label?: string;
|
||||||
defaultValue: FieldAddressDraftValue | null;
|
defaultValue?: FieldAddressDraftValue | null;
|
||||||
onPersist: (value: FieldAddressValue) => void;
|
onPersist: (value: FieldAddressValue) => void;
|
||||||
VariablePicker?: VariablePickerComponent;
|
VariablePicker?: VariablePickerComponent;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer';
|
||||||
|
import { FormNestedFieldInputContainer } from '@/object-record/record-field/form-types/components/FormNestedFieldInputContainer';
|
||||||
|
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
|
||||||
|
import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
|
||||||
|
import { FieldLinksDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
||||||
|
import { FieldLinksValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
|
import { InputLabel } from '@/ui/input/components/InputLabel';
|
||||||
|
|
||||||
|
type FormLinksFieldInputProps = {
|
||||||
|
label?: string;
|
||||||
|
defaultValue?: FieldLinksValue;
|
||||||
|
onPersist: (value: FieldLinksValue) => void;
|
||||||
|
VariablePicker?: VariablePickerComponent;
|
||||||
|
readonly?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormLinksFieldInput = ({
|
||||||
|
label,
|
||||||
|
defaultValue,
|
||||||
|
onPersist,
|
||||||
|
readonly,
|
||||||
|
VariablePicker,
|
||||||
|
}: FormLinksFieldInputProps) => {
|
||||||
|
const handleChange =
|
||||||
|
(field: keyof FieldLinksDraftValue) => (updatedLinksPart: string) => {
|
||||||
|
const updatedLinks = {
|
||||||
|
primaryLinkLabel: defaultValue?.primaryLinkLabel ?? '',
|
||||||
|
primaryLinkUrl: defaultValue?.primaryLinkUrl ?? '',
|
||||||
|
[field]: updatedLinksPart,
|
||||||
|
};
|
||||||
|
// We need to validate the links and display an error message if the links are not valid
|
||||||
|
onPersist(updatedLinks);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormFieldInputContainer>
|
||||||
|
{label ? <InputLabel>{label}</InputLabel> : null}
|
||||||
|
<FormNestedFieldInputContainer>
|
||||||
|
<FormTextFieldInput
|
||||||
|
label="Primary Link Label"
|
||||||
|
defaultValue={defaultValue?.primaryLinkLabel}
|
||||||
|
onPersist={handleChange('primaryLinkLabel')}
|
||||||
|
placeholder={'Primary Link Label'}
|
||||||
|
readonly={readonly}
|
||||||
|
VariablePicker={VariablePicker}
|
||||||
|
/>
|
||||||
|
<FormTextFieldInput
|
||||||
|
label="Primary Link URL"
|
||||||
|
defaultValue={defaultValue?.primaryLinkUrl}
|
||||||
|
onPersist={handleChange('primaryLinkUrl')}
|
||||||
|
placeholder={'Primary Link URL'}
|
||||||
|
readonly={readonly}
|
||||||
|
VariablePicker={VariablePicker}
|
||||||
|
/>
|
||||||
|
</FormNestedFieldInputContainer>
|
||||||
|
</FormFieldInputContainer>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { within } from '@storybook/test';
|
||||||
|
import { FormLinksFieldInput } from '../FormLinksFieldInput';
|
||||||
|
|
||||||
|
const meta: Meta<typeof FormLinksFieldInput> = {
|
||||||
|
title: 'UI/Data/Field/Form/Input/FormLinksFieldInput',
|
||||||
|
component: FormLinksFieldInput,
|
||||||
|
args: {},
|
||||||
|
argTypes: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof FormLinksFieldInput>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
label: 'Domain Name',
|
||||||
|
defaultValue: {
|
||||||
|
primaryLinkLabel: 'Google',
|
||||||
|
primaryLinkUrl: 'https://www.google.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
play: async ({ canvasElement }) => {
|
||||||
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
|
await canvas.findByText('Domain Name');
|
||||||
|
await canvas.findByText('Primary Link Label');
|
||||||
|
await canvas.findByText('Google');
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user