Settings Form Select refacto (#8875)

fixes #8751
This commit is contained in:
Guillim
2024-12-05 14:44:24 +01:00
committed by GitHub
parent 6c78cac908
commit 9ed9b4746a
8 changed files with 156 additions and 142 deletions

View File

@ -5,45 +5,31 @@ import {
StyledSettingsOptionCardTitle,
} from '@/settings/components/SettingsOptions/SettingsOptionCardContentBase';
import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer';
import { Select, SelectValue } from '@/ui/input/components/Select';
import styled from '@emotion/styled';
import { IconComponent } from 'twenty-ui';
type SettingsOptionCardContentSelectProps<Value extends SelectValue> = {
type SettingsOptionCardContentSelectProps = {
Icon?: IconComponent;
title: React.ReactNode;
description?: string;
divider?: boolean;
disabled?: boolean;
value: Value;
onChange: (value: Value) => void;
options: {
value: Value;
label: string;
Icon?: IconComponent;
}[];
selectClassName?: string;
dropdownId: string;
fullWidth?: boolean;
children?: React.ReactNode;
};
const StyledSelectContainer = styled.div`
margin-left: auto;
`;
export const SettingsOptionCardContentSelect = <Value extends SelectValue>({
export const SettingsOptionCardContentSelect = ({
Icon,
title,
description,
divider,
disabled = false,
value,
onChange,
options,
selectClassName,
dropdownId,
fullWidth,
}: SettingsOptionCardContentSelectProps<Value>) => {
children,
}: SettingsOptionCardContentSelectProps) => {
return (
<StyledSettingsOptionCardContent divider={divider} disabled={disabled}>
{Icon && (
@ -57,18 +43,7 @@ export const SettingsOptionCardContentSelect = <Value extends SelectValue>({
{description}
</StyledSettingsOptionCardDescription>
</div>
<StyledSelectContainer>
<Select<Value>
className={selectClassName}
dropdownWidth={fullWidth ? 'auto' : 120}
disabled={disabled}
dropdownId={dropdownId}
value={value}
onChange={onChange}
options={options}
selectSizeVariant="small"
/>
</StyledSelectContainer>
<StyledSelectContainer>{children}</StyledSelectContainer>
</StyledSettingsOptionCardContent>
);
};

View File

@ -1,4 +1,5 @@
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { Select, SelectValue } from '@/ui/input/components/Select';
import styled from '@emotion/styled';
import { Meta, StoryObj } from '@storybook/react';
import { useState } from 'react';
@ -16,28 +17,37 @@ const StyledContainer = styled.div`
width: 480px;
`;
type SelectValue = string | number | boolean | null;
interface SettingsOptionCardContentSelectProps
extends React.ComponentProps<typeof SettingsOptionCardContentSelect> {}
interface SettingsOptionCardContentSelectWrapperProps
extends SettingsOptionCardContentSelectProps {
onChange: any;
options: any;
value: any;
dropdownId: string;
}
const SettingsOptionCardContentSelectWrapper = <Value extends SelectValue>(
args: React.ComponentProps<typeof SettingsOptionCardContentSelect<Value>>,
args: SettingsOptionCardContentSelectWrapperProps,
) => {
const [value, setValue] = useState<Value>(args.value);
const [value] = useState<Value>(args.value);
return (
<StyledContainer>
<SettingsOptionCardContentSelect
value={value}
onChange={(newValue) => setValue(newValue as Value)}
Icon={args.Icon}
title={args.title}
description={args.description}
divider={args.divider}
disabled={args.disabled}
options={args.options}
selectClassName={args.selectClassName}
dropdownId={args.dropdownId}
fullWidth={args.fullWidth}
/>
>
<Select<Value>
value={value}
onChange={args.onChange}
dropdownId={args.dropdownId}
options={args.options}
selectSizeVariant="small"
dropdownWidth={120}
/>
</SettingsOptionCardContentSelect>
</StyledContainer>
);
};
@ -137,6 +147,5 @@ export const FullWidth: Story = {
},
],
dropdownId: 'full-width-select',
fullWidth: true,
},
};

View File

@ -4,11 +4,11 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { addressSchema as addressFieldDefaultValueSchema } from '@/object-record/record-field/types/guards/isFieldAddressValue';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
import { Select } from '@/ui/input/components/Select';
import { IconMap } from 'twenty-ui';
import { z } from 'zod';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
type SettingsDataModelFieldAddressFormProps = {
disabled?: boolean;
defaultCountry?: string;
@ -63,22 +63,26 @@ export const SettingsDataModelFieldAddressForm = ({
render={({ field: { onChange, value } }) => {
const defaultCountry = value?.addressCountry || '';
return (
<SettingsOptionCardContentSelect<string>
<SettingsOptionCardContentSelect
Icon={IconMap}
dropdownId="selectDefaultCountry"
title="Default Country"
description="The default country for new addresses"
value={stripSimpleQuotesFromString(defaultCountry)}
onChange={(newCountry) =>
onChange({
...value,
addressCountry: applySimpleQuotesToString(newCountry),
})
}
disabled={disabled}
options={countries}
fullWidth={true}
/>
>
<Select<string>
dropdownWidth={'auto'}
disabled={disabled}
dropdownId="selectDefaultCountry"
value={stripSimpleQuotesFromString(defaultCountry)}
onChange={(newCountry) =>
onChange({
...value,
addressCountry: applySimpleQuotesToString(newCountry),
})
}
options={countries}
selectSizeVariant="small"
/>
</SettingsOptionCardContentSelect>
);
}}
/>

View File

@ -5,6 +5,7 @@ import { z } from 'zod';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { useBooleanSettingsFormInitialValues } from '@/settings/data-model/fields/forms/boolean/hooks/useBooleanSettingsFormInitialValues';
import { Select } from '@/ui/input/components/Select';
export const settingsDataModelFieldBooleanFormSchema = z.object({
defaultValue: z.boolean(),
@ -15,12 +16,10 @@ export type SettingsDataModelFieldBooleanFormValues = z.infer<
>;
type SettingsDataModelFieldBooleanFormProps = {
className?: string;
fieldMetadataItem: Pick<FieldMetadataItem, 'defaultValue'>;
};
export const SettingsDataModelFieldBooleanForm = ({
className,
fieldMetadataItem,
}: SettingsDataModelFieldBooleanFormProps) => {
const { control } = useFormContext<SettingsDataModelFieldBooleanFormValues>();
@ -39,23 +38,27 @@ export const SettingsDataModelFieldBooleanForm = ({
Icon={IconCheck}
title="Default Value"
description="Select the default value for this boolean field"
value={value}
onChange={onChange}
selectClassName={className}
dropdownId="object-field-default-value-select-boolean"
options={[
{
value: true,
label: 'True',
Icon: IconCheck,
},
{
value: false,
label: 'False',
Icon: IconX,
},
]}
/>
>
<Select<boolean>
value={value}
onChange={onChange}
dropdownId="object-field-default-value-select-boolean"
dropdownWidth={120}
options={[
{
value: true,
label: 'True',
Icon: IconCheck,
},
{
value: false,
label: 'False',
Icon: IconX,
},
]}
selectSizeVariant="small"
/>
</SettingsOptionCardContentSelect>
)}
/>
);

View File

@ -2,6 +2,7 @@ import { Controller, useFormContext } from 'react-hook-form';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { Select } from '@/ui/input/components/Select';
import { IconTextWrap } from 'twenty-ui';
import { z } from 'zod';
@ -44,35 +45,39 @@ export const SettingsDataModelFieldTextForm = ({
<>
<SettingsOptionCardContentSelect
Icon={IconTextWrap}
dropdownId="text-wrap"
title="Wrap on record pages"
description="Display text on multiple lines"
value={displayedMaxRows}
onChange={(value) => onChange({ displayedMaxRows: value })}
disabled={disabled}
options={[
{
label: 'Deactivated',
value: 0,
},
{
label: 'First 2 lines',
value: 2,
},
{
label: 'First 5 lines',
value: 5,
},
{
label: 'First 10 lines',
value: 10,
},
{
label: 'All lines',
value: 99,
},
]}
/>
>
<Select<number>
dropdownId="text-wrap"
value={displayedMaxRows}
onChange={(value) => onChange({ displayedMaxRows: value })}
disabled={disabled}
options={[
{
label: 'Deactivated',
value: 0,
},
{
label: 'First 2 lines',
value: 2,
},
{
label: 'First 5 lines',
value: 5,
},
{
label: 'First 10 lines',
value: 10,
},
{
label: 'All lines',
value: 99,
},
]}
selectSizeVariant="small"
/>
</SettingsOptionCardContentSelect>
</>
);
}}

View File

@ -6,6 +6,7 @@ import { currencyFieldDefaultValueSchema } from '@/object-record/record-field/va
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { SETTINGS_FIELD_CURRENCY_CODES } from '@/settings/data-model/constants/SettingsFieldCurrencyCodes';
import { useCurrencySettingsFormInitialValues } from '@/settings/data-model/fields/forms/currency/hooks/useCurrencySettingsFormInitialValues';
import { Select } from '@/ui/input/components/Select';
import { IconCurrencyDollar } from 'twenty-ui';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
@ -57,13 +58,17 @@ export const SettingsDataModelFieldCurrencyForm = ({
Icon={IconCurrencyDollar}
title="Default Value"
description="Choose the default currency that will apply"
value={value}
onChange={onChange}
disabled={disabled}
fullWidth
dropdownId="object-field-default-value-select-currency"
options={OPTIONS}
/>
>
<Select<string>
dropdownWidth={'auto'}
value={value}
onChange={onChange}
disabled={disabled}
dropdownId="object-field-default-value-select-currency"
options={OPTIONS}
selectSizeVariant="small"
/>
</SettingsOptionCardContentSelect>
)}
/>
</>

View File

@ -5,6 +5,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { numberFieldDefaultValueSchema } from '@/object-record/record-field/validation-schemas/numberFieldDefaultValueSchema';
import { SettingsOptionCardContentCounter } from '@/settings/components/SettingsOptions/SettingsOptionCardContentCounter';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { Select } from '@/ui/input/components/Select';
import { IconDecimal, IconEye, IconNumber9, IconPercentage } from 'twenty-ui';
import { DEFAULT_DECIMAL_VALUE } from '~/utils/format/number';
@ -47,25 +48,30 @@ export const SettingsDataModelFieldNumberForm = ({
<>
<SettingsOptionCardContentSelect
Icon={IconEye}
dropdownId="number-type"
title="Number type"
description="Display as a plain number or a percentage"
value={type}
onChange={(value) => onChange({ type: value, decimals: count })}
disabled={disabled}
options={[
{
Icon: IconNumber9,
label: 'Number',
value: 'number',
},
{
Icon: IconPercentage,
label: 'Percentage',
value: 'percentage',
},
]}
/>
>
<Select<string>
selectSizeVariant="small"
dropdownId="number-type"
dropdownWidth={120}
value={type}
onChange={(value) => onChange({ type: value, decimals: count })}
disabled={disabled}
options={[
{
Icon: IconNumber9,
label: 'Number',
value: 'number',
},
{
Icon: IconPercentage,
label: 'Percentage',
value: 'percentage',
},
]}
/>
</SettingsOptionCardContentSelect>
<SettingsOptionCardContentCounter
Icon={IconDecimal}
title="Number of decimals"

View File

@ -4,6 +4,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { phonesSchema as phonesFieldDefaultValueSchema } from '@/object-record/record-field/types/guards/isFieldPhonesValue';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
import { Select } from '@/ui/input/components/Select';
import { IconMap } from 'twenty-ui';
import { z } from 'zod';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
@ -56,23 +57,29 @@ export const SettingsDataModelFieldPhonesForm = ({
control={control}
render={({ field: { onChange, value } }) => {
return (
<SettingsOptionCardContentSelect<string>
<SettingsOptionCardContentSelect
Icon={IconMap}
dropdownId="selectDefaultCountryCode"
title="Default Country Code"
description="The default country code for new phone numbers."
value={stripSimpleQuotesFromString(value?.primaryPhoneCountryCode)}
onChange={(newPhoneCountryCode) =>
onChange({
...value,
primaryPhoneCountryCode:
applySimpleQuotesToString(newPhoneCountryCode),
})
}
disabled={disabled}
options={countries}
fullWidth={true}
/>
>
<Select<string>
dropdownWidth={'auto'}
dropdownId="selectDefaultCountryCode"
value={stripSimpleQuotesFromString(
value?.primaryPhoneCountryCode,
)}
onChange={(newPhoneCountryCode) =>
onChange({
...value,
primaryPhoneCountryCode:
applySimpleQuotesToString(newPhoneCountryCode),
})
}
disabled={disabled}
options={countries}
selectSizeVariant="small"
/>
</SettingsOptionCardContentSelect>
);
}}
/>