Settings Option Card component (#8456)
fixes - #8195 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,11 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { IconCheck, IconX, CardContent } from 'twenty-ui';
|
||||
import { IconCheck, IconX } from 'twenty-ui';
|
||||
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';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const settingsDataModelFieldBooleanFormSchema = z.object({
|
||||
@ -21,18 +20,6 @@ type SettingsDataModelFieldBooleanFormProps = {
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'defaultValue'>;
|
||||
};
|
||||
|
||||
const StyledContainer = styled(CardContent)`
|
||||
padding-bottom: ${({ theme }) => theme.spacing(3.5)};
|
||||
`;
|
||||
|
||||
const StyledLabel = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
display: block;
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin-bottom: 6px;
|
||||
`;
|
||||
|
||||
export const SettingsDataModelFieldBooleanForm = ({
|
||||
className,
|
||||
fieldMetadataItem,
|
||||
@ -45,37 +32,36 @@ export const SettingsDataModelFieldBooleanForm = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledLabel>Default Value</StyledLabel>
|
||||
<Controller
|
||||
name="defaultValue"
|
||||
control={control}
|
||||
defaultValue={initialDefaultValue}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Select
|
||||
className={className}
|
||||
fullWidth
|
||||
// TODO: temporary fix - disabling edition because after editing the defaultValue,
|
||||
// newly created records are not taking into account the updated defaultValue properly.
|
||||
disabled={isEditMode}
|
||||
dropdownId="object-field-default-value-select"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
options={[
|
||||
{
|
||||
value: true,
|
||||
label: 'True',
|
||||
Icon: IconCheck,
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
label: 'False',
|
||||
Icon: IconX,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</StyledContainer>
|
||||
<Controller
|
||||
name="defaultValue"
|
||||
control={control}
|
||||
defaultValue={initialDefaultValue}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<SettingsOptionCardContentSelect
|
||||
Icon={IconCheck}
|
||||
title="Default Value"
|
||||
description="Select the default value for this boolean field"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
selectClassName={className}
|
||||
// TODO: temporary fix - disabling edition because after editing the defaultValue,
|
||||
// newly created records are not taking into account the updated defaultValue properly.
|
||||
disabled={isEditMode}
|
||||
dropdownId="object-field-default-value-select-boolean"
|
||||
options={[
|
||||
{
|
||||
value: true,
|
||||
label: 'True',
|
||||
Icon: IconCheck,
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
label: 'False',
|
||||
Icon: IconX,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { createPortal } from 'react-dom';
|
||||
import {
|
||||
AppTooltip,
|
||||
IconComponent,
|
||||
IconInfoCircle,
|
||||
Toggle,
|
||||
TooltipDelay,
|
||||
} from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div<{ disabled?: boolean }>`
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.background.transparent.lighter};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
box-sizing: border-box;
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
color: ${({ disabled, theme }) =>
|
||||
disabled ? theme.font.color.tertiary : theme.font.color.primary};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: ${({ theme }) => theme.spacing(8)};
|
||||
justify-content: space-between;
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledGroup = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
interface SettingsDataModelFieldToggleProps {
|
||||
disabled?: boolean;
|
||||
Icon?: IconComponent;
|
||||
label: string;
|
||||
tooltip?: string;
|
||||
value?: boolean;
|
||||
onChange: (value: boolean) => void;
|
||||
}
|
||||
|
||||
export const SettingsDataModelFieldToggle = ({
|
||||
disabled,
|
||||
Icon,
|
||||
label,
|
||||
tooltip,
|
||||
value,
|
||||
onChange,
|
||||
}: SettingsDataModelFieldToggleProps) => {
|
||||
const theme = useTheme();
|
||||
const infoCircleElementId = `info-circle-id-${Math.random().toString(36).slice(2)}`;
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledGroup>
|
||||
{Icon && (
|
||||
<Icon color={theme.font.color.tertiary} size={theme.icon.size.md} />
|
||||
)}
|
||||
{label}
|
||||
</StyledGroup>
|
||||
<StyledGroup>
|
||||
{tooltip && (
|
||||
<IconInfoCircle
|
||||
id={infoCircleElementId}
|
||||
size={theme.icon.size.md}
|
||||
color={theme.font.color.tertiary}
|
||||
/>
|
||||
)}
|
||||
{tooltip &&
|
||||
createPortal(
|
||||
<AppTooltip
|
||||
anchorSelect={`#${infoCircleElementId}`}
|
||||
content={tooltip}
|
||||
offset={5}
|
||||
noArrow
|
||||
place="bottom"
|
||||
positionStrategy="absolute"
|
||||
delay={TooltipDelay.shortDelay}
|
||||
/>,
|
||||
document.body,
|
||||
)}
|
||||
<Toggle
|
||||
disabled={disabled}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
toggleSize="small"
|
||||
/>
|
||||
</StyledGroup>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -3,10 +3,10 @@ import { z } from 'zod';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { currencyFieldDefaultValueSchema } from '@/object-record/record-field/validation-schemas/currencyFieldDefaultValueSchema';
|
||||
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 { CardContent } from 'twenty-ui';
|
||||
import { IconCurrencyDollar } from 'twenty-ui';
|
||||
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
|
||||
|
||||
export const settingsDataModelFieldCurrencyFormSchema = z.object({
|
||||
@ -41,7 +41,7 @@ export const SettingsDataModelFieldCurrencyForm = ({
|
||||
useCurrencySettingsFormInitialValues({ fieldMetadataItem });
|
||||
|
||||
return (
|
||||
<CardContent>
|
||||
<>
|
||||
<Controller
|
||||
name="defaultValue.amountMicros"
|
||||
control={control}
|
||||
@ -53,17 +53,19 @@ export const SettingsDataModelFieldCurrencyForm = ({
|
||||
control={control}
|
||||
defaultValue={initialCurrencyCodeValue}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Select
|
||||
fullWidth
|
||||
disabled={disabled}
|
||||
label="Default Unit"
|
||||
dropdownId="currency-unit-select"
|
||||
<SettingsOptionCardContentSelect
|
||||
Icon={IconCurrencyDollar}
|
||||
title="Default Value"
|
||||
description="Choose the default currency that will apply"
|
||||
value={value}
|
||||
options={OPTIONS}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
fullWidth
|
||||
dropdownId="object-field-default-value-select-currency"
|
||||
options={OPTIONS}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -2,10 +2,9 @@ import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { StyledFormCardTitle } from '@/settings/data-model/fields/components/StyledFormCardTitle';
|
||||
import { SettingsDataModelFieldToggle } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldToggle';
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { useDateSettingsFormInitialValues } from '@/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues';
|
||||
import { IconClockShare, CardContent } from 'twenty-ui';
|
||||
import { IconSlash } from 'twenty-ui';
|
||||
|
||||
export const settingsDataModelFieldDateFormSchema = z.object({
|
||||
settings: z
|
||||
@ -36,27 +35,19 @@ export const SettingsDataModelFieldDateForm = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<CardContent>
|
||||
<Controller
|
||||
name="settings.displayAsRelativeDate"
|
||||
control={control}
|
||||
defaultValue={initialDisplayAsRelativeDateValue}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<>
|
||||
<StyledFormCardTitle>Options</StyledFormCardTitle>
|
||||
<SettingsDataModelFieldToggle
|
||||
label="Display as relative date"
|
||||
Icon={IconClockShare}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
tooltip={
|
||||
'Show dates in a human-friendly format. Example: "13 mins ago" instead of "Jul 30, 2024 7:11pm"'
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
<Controller
|
||||
name="settings.displayAsRelativeDate"
|
||||
control={control}
|
||||
defaultValue={initialDisplayAsRelativeDateValue}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconSlash}
|
||||
title="Display as relative date"
|
||||
checked={value ?? false}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,167 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Button, IconInfoCircle, IconMinus, IconPlus } from 'twenty-ui';
|
||||
import { castAsNumberOrNull } from '~/utils/cast-as-number-or-null';
|
||||
|
||||
type SettingsDataModelFieldNumberDecimalsInputProps = {
|
||||
value: number;
|
||||
onChange: (value: number) => void;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const StyledCounterContainer = styled.div`
|
||||
align-items: center;
|
||||
background: ${({ theme }) => theme.background.noisy};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const StyledExampleText = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
`;
|
||||
|
||||
const StyledCounterControlsIcons = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledCounterInnerContainer = styled.div`
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
height: 24px;
|
||||
`;
|
||||
|
||||
const StyledTextInput = styled(TextInput)`
|
||||
width: ${({ theme }) => theme.spacing(16)};
|
||||
input {
|
||||
width: ${({ theme }) => theme.spacing(16)};
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
text-align: center;
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
background: ${({ theme }) => theme.background.noisy};
|
||||
}
|
||||
input ~ div {
|
||||
padding-right: ${({ theme }) => theme.spacing(0)};
|
||||
border-radius: ${({ theme }) => theme.spacing(1)};
|
||||
background: ${({ theme }) => theme.background.noisy};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTitle = 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)};
|
||||
`;
|
||||
|
||||
const StyledControlButton = styled(Button)`
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
width: ${({ theme }) => theme.spacing(6)};
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
svg {
|
||||
height: ${({ theme }) => theme.spacing(4)};
|
||||
width: ${({ theme }) => theme.spacing(4)};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledInfoButton = styled(Button)`
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
width: ${({ theme }) => theme.spacing(6)};
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
svg {
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
height: ${({ theme }) => theme.spacing(4)};
|
||||
width: ${({ theme }) => theme.spacing(4)};
|
||||
}
|
||||
`;
|
||||
|
||||
const MIN_VALUE = 0;
|
||||
const MAX_VALUE = 100;
|
||||
export const SettingsDataModelFieldNumberDecimalsInput = ({
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
}: SettingsDataModelFieldNumberDecimalsInputProps) => {
|
||||
const exampleValue = (1000).toFixed(value);
|
||||
|
||||
const handleIncrementCounter = () => {
|
||||
if (value < MAX_VALUE) {
|
||||
const newValue = value + 1;
|
||||
onChange(newValue);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDecrementCounter = () => {
|
||||
if (value > MIN_VALUE) {
|
||||
const newValue = value - 1;
|
||||
onChange(newValue);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTextInputChange = (value: string) => {
|
||||
const castedNumber = castAsNumberOrNull(value);
|
||||
if (castedNumber === null) {
|
||||
onChange(MIN_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (castedNumber < MIN_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (castedNumber > MAX_VALUE) {
|
||||
onChange(MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
onChange(castedNumber);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<StyledTitle>Number of decimals</StyledTitle>
|
||||
<StyledCounterContainer>
|
||||
<StyledCounterInnerContainer>
|
||||
<StyledExampleText>Example: {exampleValue}</StyledExampleText>
|
||||
<StyledCounterControlsIcons>
|
||||
<StyledInfoButton variant="tertiary" Icon={IconInfoCircle} />
|
||||
<StyledControlButton
|
||||
variant="secondary"
|
||||
onClick={handleDecrementCounter}
|
||||
Icon={IconMinus}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<StyledTextInput
|
||||
name="decimals"
|
||||
fullWidth
|
||||
value={value.toString()}
|
||||
onChange={(value) => handleTextInputChange(value)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<StyledControlButton
|
||||
variant="secondary"
|
||||
onClick={handleIncrementCounter}
|
||||
Icon={IconPlus}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</StyledCounterControlsIcons>
|
||||
</StyledCounterInnerContainer>
|
||||
</StyledCounterContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -3,10 +3,9 @@ import { z } from 'zod';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { numberFieldDefaultValueSchema } from '@/object-record/record-field/validation-schemas/numberFieldDefaultValueSchema';
|
||||
import { SettingsDataModelFieldNumberDecimalsInput } from '@/settings/data-model/fields/forms/number/components/SettingsDataModelFieldNumberDecimalInput';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import styled from '@emotion/styled';
|
||||
import { CardContent, IconNumber9, IconPercentage } from 'twenty-ui';
|
||||
import { SettingsOptionCardContentCounter } from '@/settings/components/SettingsOptions/SettingsOptionCardContentCounter';
|
||||
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
|
||||
import { IconDecimal, IconEye, IconNumber9, IconPercentage } from 'twenty-ui';
|
||||
import { DEFAULT_DECIMAL_VALUE } from '~/utils/format/number';
|
||||
|
||||
export const settingsDataModelFieldNumberFormSchema = z.object({
|
||||
@ -17,13 +16,6 @@ export type SettingsDataModelFieldNumberFormValues = z.infer<
|
||||
typeof settingsDataModelFieldNumberFormSchema
|
||||
>;
|
||||
|
||||
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 SettingsDataModelFieldNumberFormProps = {
|
||||
disabled?: boolean;
|
||||
fieldMetadataItem: Pick<
|
||||
@ -39,52 +31,54 @@ export const SettingsDataModelFieldNumberForm = ({
|
||||
const { control } = useFormContext<SettingsDataModelFieldNumberFormValues>();
|
||||
|
||||
return (
|
||||
<CardContent>
|
||||
<Controller
|
||||
name="settings"
|
||||
defaultValue={{
|
||||
decimals:
|
||||
fieldMetadataItem?.settings?.decimals ?? DEFAULT_DECIMAL_VALUE,
|
||||
type: fieldMetadataItem?.settings?.type || 'number',
|
||||
}}
|
||||
control={control}
|
||||
render={({ field: { onChange, value } }) => {
|
||||
const count = value?.decimals ?? 0;
|
||||
const type = value?.type ?? 'number';
|
||||
<Controller
|
||||
name="settings"
|
||||
defaultValue={{
|
||||
decimals:
|
||||
fieldMetadataItem?.settings?.decimals ?? DEFAULT_DECIMAL_VALUE,
|
||||
type: fieldMetadataItem?.settings?.type ?? 'number',
|
||||
}}
|
||||
control={control}
|
||||
render={({ field: { onChange, value } }) => {
|
||||
const count = value?.decimals ?? 0;
|
||||
const type = value?.type ?? 'number';
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledFormCardTitle>Type</StyledFormCardTitle>
|
||||
<Select
|
||||
disabled={disabled}
|
||||
dropdownId="selectNumberTypes"
|
||||
options={[
|
||||
{
|
||||
label: 'Number',
|
||||
value: 'number',
|
||||
Icon: IconNumber9,
|
||||
},
|
||||
{
|
||||
label: 'Percentage',
|
||||
value: 'percentage',
|
||||
Icon: IconPercentage,
|
||||
},
|
||||
]}
|
||||
value={type}
|
||||
onChange={(value) => onChange({ type: value, decimals: count })}
|
||||
withSearchInput={false}
|
||||
dropdownWidthAuto={true}
|
||||
/>
|
||||
<br />
|
||||
<SettingsDataModelFieldNumberDecimalsInput
|
||||
value={count}
|
||||
onChange={(value) => onChange({ type: type, decimals: value })}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</CardContent>
|
||||
return (
|
||||
<>
|
||||
<SettingsOptionCardContentSelect
|
||||
Icon={IconEye}
|
||||
dropdownId="number-type"
|
||||
title="Number type"
|
||||
description="The number type you want to use, e.g. 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',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<SettingsOptionCardContentCounter
|
||||
Icon={IconDecimal}
|
||||
title="Number of decimals"
|
||||
description={`Example: ${(1000).toFixed(count)}`}
|
||||
value={count}
|
||||
onChange={(value) => onChange({ type: type, decimals: value })}
|
||||
disabled={disabled}
|
||||
minValue={0}
|
||||
maxValue={100} // needs to be changed
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -28,9 +28,8 @@ import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
||||
import { toSpliced } from '~/utils/array/toSpliced';
|
||||
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
|
||||
|
||||
import { EXPANDED_WIDTH_ANIMATION_VARIANTS } from '@/settings/constants/ExpandedWidthAnimationVariants';
|
||||
import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsWrapper';
|
||||
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { SettingsDataModelFieldSelectFormOptionRow } from './SettingsDataModelFieldSelectFormOptionRow';
|
||||
|
||||
@ -251,26 +250,14 @@ export const SettingsDataModelFieldSelectForm = ({
|
||||
<>
|
||||
<StyledContainer>
|
||||
<StyledLabelContainer>
|
||||
<AnimatePresence>
|
||||
{isAdvancedModeEnabled && (
|
||||
<motion.div
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
variants={EXPANDED_WIDTH_ANIMATION_VARIANTS}
|
||||
>
|
||||
<StyledApiKeyContainer>
|
||||
<StyledIconContainer>
|
||||
<StyledIconTool
|
||||
size={12}
|
||||
color={MAIN_COLORS.yellow}
|
||||
/>
|
||||
</StyledIconContainer>
|
||||
<StyledApiKey>API values</StyledApiKey>
|
||||
</StyledApiKeyContainer>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<AdvancedSettingsWrapper dimension="width" hideIcon={true}>
|
||||
<StyledApiKeyContainer>
|
||||
<StyledIconContainer>
|
||||
<StyledIconTool size={12} color={MAIN_COLORS.yellow} />
|
||||
</StyledIconContainer>
|
||||
<StyledApiKey>API values</StyledApiKey>
|
||||
</StyledApiKeyContainer>
|
||||
</AdvancedSettingsWrapper>
|
||||
<StyledOptionsLabel
|
||||
isAdvancedModeEnabled={isAdvancedModeEnabled}
|
||||
>
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsWrapper';
|
||||
import { OPTION_VALUE_MAXIMUM_LENGTH } from '@/settings/data-model/constants/OptionValueMaximumLength';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useMemo } from 'react';
|
||||
@ -14,18 +22,6 @@ import {
|
||||
MenuItemSelectColor,
|
||||
} from 'twenty-ui';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { EXPANDED_WIDTH_ANIMATION_VARIANTS } from '@/settings/constants/ExpandedWidthAnimationVariants';
|
||||
import { OPTION_VALUE_MAXIMUM_LENGTH } from '@/settings/data-model/constants/OptionValueMaximumLength';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { computeOptionValueFromLabel } from '~/pages/settings/data-model/utils/compute-option-value-from-label.utils';
|
||||
|
||||
type SettingsDataModelFieldSelectFormOptionRowProps = {
|
||||
@ -83,7 +79,6 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
option,
|
||||
isNewRow,
|
||||
}: SettingsDataModelFieldSelectFormOptionRowProps) => {
|
||||
const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState);
|
||||
const theme = useTheme();
|
||||
|
||||
const dropdownIds = useMemo(() => {
|
||||
@ -111,28 +106,19 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
stroke={theme.icon.stroke.sm}
|
||||
color={theme.font.color.extraLight}
|
||||
/>
|
||||
<AnimatePresence>
|
||||
{isAdvancedModeEnabled && (
|
||||
<motion.div
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
variants={EXPANDED_WIDTH_ANIMATION_VARIANTS}
|
||||
>
|
||||
<StyledOptionInput
|
||||
value={option.value}
|
||||
onChange={(input) =>
|
||||
onChange({
|
||||
...option,
|
||||
value: computeOptionValueFromLabel(input),
|
||||
})
|
||||
}
|
||||
RightIcon={isDefault ? IconCheck : undefined}
|
||||
maxLength={OPTION_VALUE_MAXIMUM_LENGTH}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<AdvancedSettingsWrapper dimension="width" hideIcon={true}>
|
||||
<StyledOptionInput
|
||||
value={option.value}
|
||||
onChange={(input) =>
|
||||
onChange({
|
||||
...option,
|
||||
value: computeOptionValueFromLabel(input),
|
||||
})
|
||||
}
|
||||
RightIcon={isDefault ? IconCheck : undefined}
|
||||
maxLength={OPTION_VALUE_MAXIMUM_LENGTH}
|
||||
/>
|
||||
</AdvancedSettingsWrapper>
|
||||
<Dropdown
|
||||
dropdownId={dropdownIds.color}
|
||||
dropdownPlacement="bottom-start"
|
||||
|
||||
Reference in New Issue
Block a user