@ -11,17 +11,17 @@ import { Field } from '~/generated-metadata/graphql';
|
|||||||
import { relationTypes } from '../constants/relationTypes';
|
import { relationTypes } from '../constants/relationTypes';
|
||||||
import { RelationType } from '../types/RelationType';
|
import { RelationType } from '../types/RelationType';
|
||||||
|
|
||||||
export type SettingsObjectFieldRelationFormValues = Partial<{
|
export type SettingsObjectFieldRelationFormValues = {
|
||||||
field: Partial<Pick<Field, 'icon' | 'label'>>;
|
field: Pick<Field, 'icon' | 'label'>;
|
||||||
objectMetadataId: string;
|
objectMetadataId: string;
|
||||||
type: RelationType;
|
type: RelationType;
|
||||||
}>;
|
};
|
||||||
|
|
||||||
type SettingsObjectFieldRelationFormProps = {
|
type SettingsObjectFieldRelationFormProps = {
|
||||||
disableFieldEdition?: boolean;
|
disableFieldEdition?: boolean;
|
||||||
disableRelationEdition?: boolean;
|
disableRelationEdition?: boolean;
|
||||||
onChange: (values: SettingsObjectFieldRelationFormValues) => void;
|
onChange: (values: Partial<SettingsObjectFieldRelationFormValues>) => void;
|
||||||
values?: SettingsObjectFieldRelationFormValues;
|
values: SettingsObjectFieldRelationFormValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -61,7 +61,7 @@ export const SettingsObjectFieldRelationForm = ({
|
|||||||
useObjectMetadataItemForSettings();
|
useObjectMetadataItemForSettings();
|
||||||
|
|
||||||
const selectedObjectMetadataItem =
|
const selectedObjectMetadataItem =
|
||||||
(values?.objectMetadataId
|
(values.objectMetadataId
|
||||||
? findObjectMetadataItemById(values.objectMetadataId)
|
? findObjectMetadataItemById(values.objectMetadataId)
|
||||||
: undefined) || objectMetadataItems[0];
|
: undefined) || objectMetadataItems[0];
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ export const SettingsObjectFieldRelationForm = ({
|
|||||||
label="Relation type"
|
label="Relation type"
|
||||||
dropdownScopeId="relation-type-select"
|
dropdownScopeId="relation-type-select"
|
||||||
disabled={disableRelationEdition}
|
disabled={disableRelationEdition}
|
||||||
value={values?.type}
|
value={values.type}
|
||||||
options={Object.entries(relationTypes).map(
|
options={Object.entries(relationTypes).map(
|
||||||
([value, { label, Icon }]) => ({
|
([value, { label, Icon }]) => ({
|
||||||
label,
|
label,
|
||||||
@ -86,7 +86,7 @@ export const SettingsObjectFieldRelationForm = ({
|
|||||||
label="Object destination"
|
label="Object destination"
|
||||||
dropdownScopeId="object-destination-select"
|
dropdownScopeId="object-destination-select"
|
||||||
disabled={disableRelationEdition}
|
disabled={disableRelationEdition}
|
||||||
value={values?.objectMetadataId}
|
value={values.objectMetadataId}
|
||||||
options={objectMetadataItems.map((objectMetadataItem) => ({
|
options={objectMetadataItems.map((objectMetadataItem) => ({
|
||||||
label: objectMetadataItem.labelPlural,
|
label: objectMetadataItem.labelPlural,
|
||||||
value: objectMetadataItem.id,
|
value: objectMetadataItem.id,
|
||||||
@ -104,10 +104,10 @@ export const SettingsObjectFieldRelationForm = ({
|
|||||||
<IconPicker
|
<IconPicker
|
||||||
disabled={disableFieldEdition}
|
disabled={disableFieldEdition}
|
||||||
dropdownScopeId="field-destination-icon-picker"
|
dropdownScopeId="field-destination-icon-picker"
|
||||||
selectedIconKey={values?.field?.icon || undefined}
|
selectedIconKey={values.field.icon || undefined}
|
||||||
onChange={(value) =>
|
onChange={(value) =>
|
||||||
onChange({
|
onChange({
|
||||||
field: { ...values?.field, icon: value.iconKey },
|
field: { ...values.field, icon: value.iconKey },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
@ -115,11 +115,11 @@ export const SettingsObjectFieldRelationForm = ({
|
|||||||
<TextInput
|
<TextInput
|
||||||
disabled={disableFieldEdition}
|
disabled={disableFieldEdition}
|
||||||
placeholder="Field name"
|
placeholder="Field name"
|
||||||
value={values?.field?.label || ''}
|
value={values.field.label}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (!value || validateMetadataLabel(value)) {
|
if (!value || validateMetadataLabel(value)) {
|
||||||
onChange({
|
onChange({
|
||||||
field: { ...values?.field, label: value },
|
field: { ...values.field, label: value },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -4,17 +4,16 @@ import { IconPlus } from '@/ui/display/icon';
|
|||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
import { mainColors, ThemeColor } from '@/ui/theme/constants/colors';
|
import { mainColors, ThemeColor } from '@/ui/theme/constants/colors';
|
||||||
|
|
||||||
import {
|
import { SettingsObjectFieldSelectFormOption } from '../types/SettingsObjectFieldSelectFormOption';
|
||||||
SettingsObjectFieldSelectFormOption,
|
|
||||||
SettingsObjectFieldSelectFormOptionRow,
|
import { SettingsObjectFieldSelectFormOptionRow } from './SettingsObjectFieldSelectFormOptionRow';
|
||||||
} from './SettingsObjectFieldSelectFormOptionRow';
|
|
||||||
|
|
||||||
export type SettingsObjectFieldSelectFormValues =
|
export type SettingsObjectFieldSelectFormValues =
|
||||||
SettingsObjectFieldSelectFormOption[];
|
SettingsObjectFieldSelectFormOption[];
|
||||||
|
|
||||||
type SettingsObjectFieldSelectFormProps = {
|
type SettingsObjectFieldSelectFormProps = {
|
||||||
onChange: (values: SettingsObjectFieldSelectFormValues) => void;
|
onChange: (values: SettingsObjectFieldSelectFormValues) => void;
|
||||||
values?: SettingsObjectFieldSelectFormValues;
|
values: SettingsObjectFieldSelectFormValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -54,31 +53,38 @@ const getNextColor = (currentColor: ThemeColor) => {
|
|||||||
|
|
||||||
export const SettingsObjectFieldSelectForm = ({
|
export const SettingsObjectFieldSelectForm = ({
|
||||||
onChange,
|
onChange,
|
||||||
values = [],
|
values,
|
||||||
}: SettingsObjectFieldSelectFormProps) => {
|
}: SettingsObjectFieldSelectFormProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledLabel>Options</StyledLabel>
|
<StyledLabel>Options</StyledLabel>
|
||||||
<StyledRows>
|
<StyledRows>
|
||||||
{values.map((value, index) => (
|
{values.map((option, index) => (
|
||||||
<SettingsObjectFieldSelectFormOptionRow
|
<SettingsObjectFieldSelectFormOptionRow
|
||||||
key={index}
|
key={index}
|
||||||
onChange={(optionValue) => {
|
isDefault={option.isDefault}
|
||||||
const nextValues = [...values];
|
onChange={(nextOption) => {
|
||||||
nextValues.splice(index, 1, optionValue);
|
const hasDefaultOptionChanged =
|
||||||
onChange(nextValues);
|
!option.isDefault && nextOption.isDefault;
|
||||||
|
const nextOptions = hasDefaultOptionChanged
|
||||||
|
? values.map((value) => ({ ...value, isDefault: false }))
|
||||||
|
: [...values];
|
||||||
|
|
||||||
|
nextOptions.splice(index, 1, nextOption);
|
||||||
|
|
||||||
|
onChange(nextOptions);
|
||||||
}}
|
}}
|
||||||
onRemove={
|
onRemove={
|
||||||
values.length > 1
|
values.length > 1
|
||||||
? () => {
|
? () => {
|
||||||
const nextValues = [...values];
|
const nextOptions = [...values];
|
||||||
nextValues.splice(index, 1);
|
nextOptions.splice(index, 1);
|
||||||
onChange(nextValues);
|
onChange(nextOptions);
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
value={value}
|
option={option}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</StyledRows>
|
</StyledRows>
|
||||||
@ -92,7 +98,7 @@ export const SettingsObjectFieldSelectForm = ({
|
|||||||
...values,
|
...values,
|
||||||
{
|
{
|
||||||
color: getNextColor(values[values.length - 1].color),
|
color: getNextColor(values[values.length - 1].color),
|
||||||
text: `Option ${values.length + 1}`,
|
label: `Option ${values.length + 1}`,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,12 @@ import { useMemo } from 'react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { IconDotsVertical, IconTrash } from '@/ui/display/icon';
|
import {
|
||||||
|
IconCheck,
|
||||||
|
IconDotsVertical,
|
||||||
|
IconTrash,
|
||||||
|
IconX,
|
||||||
|
} from '@/ui/display/icon';
|
||||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
@ -11,17 +16,14 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
|||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
|
||||||
|
|
||||||
export type SettingsObjectFieldSelectFormOption = {
|
import { SettingsObjectFieldSelectFormOption } from '../types/SettingsObjectFieldSelectFormOption';
|
||||||
color: ThemeColor;
|
|
||||||
text: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type SettingsObjectFieldSelectFormOptionRowProps = {
|
type SettingsObjectFieldSelectFormOptionRowProps = {
|
||||||
|
isDefault?: boolean;
|
||||||
onChange: (value: SettingsObjectFieldSelectFormOption) => void;
|
onChange: (value: SettingsObjectFieldSelectFormOption) => void;
|
||||||
onRemove?: () => void;
|
onRemove?: () => void;
|
||||||
value: SettingsObjectFieldSelectFormOption;
|
option: SettingsObjectFieldSelectFormOption;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledRow = styled.div`
|
const StyledRow = styled.div`
|
||||||
@ -41,9 +43,10 @@ const StyledOptionInput = styled(TextInput)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const SettingsObjectFieldSelectFormOptionRow = ({
|
export const SettingsObjectFieldSelectFormOptionRow = ({
|
||||||
|
isDefault,
|
||||||
onChange,
|
onChange,
|
||||||
onRemove,
|
onRemove,
|
||||||
value,
|
option,
|
||||||
}: SettingsObjectFieldSelectFormOptionRowProps) => {
|
}: SettingsObjectFieldSelectFormOptionRowProps) => {
|
||||||
const dropdownScopeId = useMemo(() => `select-field-option-row-${v4()}`, []);
|
const dropdownScopeId = useMemo(() => `select-field-option-row-${v4()}`, []);
|
||||||
|
|
||||||
@ -52,8 +55,9 @@ export const SettingsObjectFieldSelectFormOptionRow = ({
|
|||||||
return (
|
return (
|
||||||
<StyledRow>
|
<StyledRow>
|
||||||
<StyledOptionInput
|
<StyledOptionInput
|
||||||
value={value.text}
|
value={option.label}
|
||||||
onChange={(text) => onChange({ ...value, text })}
|
onChange={(label) => onChange({ ...option, label })}
|
||||||
|
RightIcon={isDefault ? IconCheck : undefined}
|
||||||
/>
|
/>
|
||||||
<DropdownScope dropdownScopeId={dropdownScopeId}>
|
<DropdownScope dropdownScopeId={dropdownScopeId}>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
@ -65,6 +69,25 @@ export const SettingsObjectFieldSelectFormOptionRow = ({
|
|||||||
dropdownComponents={
|
dropdownComponents={
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
|
{isDefault ? (
|
||||||
|
<MenuItem
|
||||||
|
LeftIcon={IconX}
|
||||||
|
text="Remove as default"
|
||||||
|
onClick={() => {
|
||||||
|
onChange({ ...option, isDefault: false });
|
||||||
|
closeDropdown();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MenuItem
|
||||||
|
LeftIcon={IconCheck}
|
||||||
|
text="Set as default"
|
||||||
|
onClick={() => {
|
||||||
|
onChange({ ...option, isDefault: true });
|
||||||
|
closeDropdown();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{!!onRemove && (
|
{!!onRemove && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
accent="danger"
|
accent="danger"
|
||||||
|
|||||||
@ -22,18 +22,20 @@ import {
|
|||||||
} from './SettingsObjectFieldSelectForm';
|
} from './SettingsObjectFieldSelectForm';
|
||||||
import { SettingsObjectFieldTypeCard } from './SettingsObjectFieldTypeCard';
|
import { SettingsObjectFieldTypeCard } from './SettingsObjectFieldTypeCard';
|
||||||
|
|
||||||
export type SettingsObjectFieldTypeSelectSectionFormValues = Partial<{
|
export type SettingsObjectFieldTypeSelectSectionFormValues = {
|
||||||
type: FieldMetadataType;
|
type: FieldMetadataType;
|
||||||
relation: SettingsObjectFieldRelationFormValues;
|
relation: SettingsObjectFieldRelationFormValues;
|
||||||
select: SettingsObjectFieldSelectFormValues;
|
select: SettingsObjectFieldSelectFormValues;
|
||||||
}>;
|
};
|
||||||
|
|
||||||
type SettingsObjectFieldTypeSelectSectionProps = {
|
type SettingsObjectFieldTypeSelectSectionProps = {
|
||||||
excludedFieldTypes?: FieldMetadataType[];
|
excludedFieldTypes?: FieldMetadataType[];
|
||||||
fieldMetadata: Pick<Field, 'icon' | 'label'> & { id?: string };
|
fieldMetadata: Pick<Field, 'icon' | 'label'> & { id?: string };
|
||||||
onChange: (values: SettingsObjectFieldTypeSelectSectionFormValues) => void;
|
onChange: (
|
||||||
|
values: Partial<SettingsObjectFieldTypeSelectSectionFormValues>,
|
||||||
|
) => void;
|
||||||
relationFieldMetadata?: Pick<Field, 'id' | 'isCustom'>;
|
relationFieldMetadata?: Pick<Field, 'id' | 'isCustom'>;
|
||||||
values?: SettingsObjectFieldTypeSelectSectionFormValues;
|
values: SettingsObjectFieldTypeSelectSectionFormValues;
|
||||||
} & Pick<SettingsObjectFieldPreviewProps, 'objectMetadataId'>;
|
} & Pick<SettingsObjectFieldPreviewProps, 'objectMetadataId'>;
|
||||||
|
|
||||||
const StyledSettingsObjectFieldTypeCard = styled(SettingsObjectFieldTypeCard)`
|
const StyledSettingsObjectFieldTypeCard = styled(SettingsObjectFieldTypeCard)`
|
||||||
@ -58,8 +60,8 @@ export const SettingsObjectFieldTypeSelectSection = ({
|
|||||||
relationFieldMetadata,
|
relationFieldMetadata,
|
||||||
values,
|
values,
|
||||||
}: SettingsObjectFieldTypeSelectSectionProps) => {
|
}: SettingsObjectFieldTypeSelectSectionProps) => {
|
||||||
const relationFormConfig = values?.relation;
|
const relationFormConfig = values.relation;
|
||||||
const selectFormConfig = values?.select;
|
const selectFormConfig = values.select;
|
||||||
|
|
||||||
const fieldTypeOptions = Object.entries(settingsFieldMetadataTypes)
|
const fieldTypeOptions = Object.entries(settingsFieldMetadataTypes)
|
||||||
.filter(([key]) => !excludedFieldTypes?.includes(key as FieldMetadataType))
|
.filter(([key]) => !excludedFieldTypes?.includes(key as FieldMetadataType))
|
||||||
|
|||||||
@ -26,8 +26,10 @@ const defaultValues: FormValues = {
|
|||||||
type: FieldMetadataType.Text,
|
type: FieldMetadataType.Text,
|
||||||
relation: {
|
relation: {
|
||||||
type: RelationMetadataType.OneToMany,
|
type: RelationMetadataType.OneToMany,
|
||||||
|
objectMetadataId: '',
|
||||||
|
field: { label: '' },
|
||||||
},
|
},
|
||||||
select: [{ color: 'green', text: 'Option 1' }],
|
select: [{ color: 'green', label: 'Option 1' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
const fieldSchema = z.object({
|
const fieldSchema = z.object({
|
||||||
@ -60,7 +62,8 @@ const selectSchema = fieldSchema.merge(
|
|||||||
color: z.enum(
|
color: z.enum(
|
||||||
Object.keys(mainColors) as [ThemeColor, ...ThemeColor[]],
|
Object.keys(mainColors) as [ThemeColor, ...ThemeColor[]],
|
||||||
),
|
),
|
||||||
text: z.string().min(1),
|
isDefault: z.boolean().optional(),
|
||||||
|
label: z.string().min(1),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.nonempty(),
|
.nonempty(),
|
||||||
@ -90,7 +93,7 @@ const schema = z.discriminatedUnion('type', [
|
|||||||
otherFieldTypesSchema,
|
otherFieldTypesSchema,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
type PartialFormValues = Partial<FormValues> &
|
type PartialFormValues = Partial<Omit<FormValues, 'relation'>> &
|
||||||
DeepPartial<Pick<FormValues, 'relation'>>;
|
DeepPartial<Pick<FormValues, 'relation'>>;
|
||||||
|
|
||||||
export const useFieldMetadataForm = () => {
|
export const useFieldMetadataForm = () => {
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObj
|
|||||||
import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon';
|
import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon';
|
||||||
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
|
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
import { SettingsObjectFieldSelectFormValues } from '../components/SettingsObjectFieldSelectForm';
|
|
||||||
import { settingsFieldMetadataTypes } from '../constants/settingsFieldMetadataTypes';
|
import { settingsFieldMetadataTypes } from '../constants/settingsFieldMetadataTypes';
|
||||||
|
import { SettingsObjectFieldSelectFormOption } from '../types/SettingsObjectFieldSelectFormOption';
|
||||||
|
|
||||||
import { useFieldPreviewValue } from './useFieldPreviewValue';
|
import { useFieldPreviewValue } from './useFieldPreviewValue';
|
||||||
import { useRelationFieldPreviewValue } from './useRelationFieldPreviewValue';
|
import { useRelationFieldPreviewValue } from './useRelationFieldPreviewValue';
|
||||||
@ -17,7 +17,7 @@ export const useFieldPreview = ({
|
|||||||
fieldMetadata: Pick<Field, 'icon' | 'label' | 'type'> & { id?: string };
|
fieldMetadata: Pick<Field, 'icon' | 'label' | 'type'> & { id?: string };
|
||||||
objectMetadataId: string;
|
objectMetadataId: string;
|
||||||
relationObjectMetadataId?: string;
|
relationObjectMetadataId?: string;
|
||||||
selectOptions?: SettingsObjectFieldSelectFormValues;
|
selectOptions?: SettingsObjectFieldSelectFormOption[];
|
||||||
}) => {
|
}) => {
|
||||||
const { findObjectMetadataItemById } = useObjectMetadataItemForSettings();
|
const { findObjectMetadataItemById } = useObjectMetadataItemForSettings();
|
||||||
const objectMetadataItem = findObjectMetadataItemById(objectMetadataId);
|
const objectMetadataItem = findObjectMetadataItemById(objectMetadataId);
|
||||||
@ -44,17 +44,16 @@ export const useFieldPreview = ({
|
|||||||
skip: fieldMetadata.type !== FieldMetadataType.Relation,
|
skip: fieldMetadata.type !== FieldMetadataType.Relation,
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultValue =
|
const { defaultValue } = settingsFieldMetadataTypes[fieldMetadata.type];
|
||||||
fieldMetadata.type === FieldMetadataType.Enum
|
|
||||||
? selectOptions?.[0]
|
|
||||||
: settingsFieldMetadataTypes[fieldMetadata.type].defaultValue;
|
|
||||||
|
|
||||||
const isValidSelectValue =
|
const defaultSelectValue = selectOptions?.[0];
|
||||||
|
const selectValue =
|
||||||
fieldMetadata.type === FieldMetadataType.Enum &&
|
fieldMetadata.type === FieldMetadataType.Enum &&
|
||||||
!!firstRecordFieldValue &&
|
typeof firstRecordFieldValue === 'string'
|
||||||
selectOptions?.some(
|
? selectOptions?.find(
|
||||||
(selectOption) => selectOption.text === firstRecordFieldValue,
|
(selectOption) => selectOption.value === firstRecordFieldValue,
|
||||||
);
|
)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entityId: `${objectMetadataId}-field-form`,
|
entityId: `${objectMetadataId}-field-form`,
|
||||||
@ -64,10 +63,10 @@ export const useFieldPreview = ({
|
|||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
relationObjectMetadataItem,
|
relationObjectMetadataItem,
|
||||||
value:
|
value:
|
||||||
(fieldMetadata.type === FieldMetadataType.Relation
|
fieldMetadata.type === FieldMetadataType.Relation
|
||||||
? relationValue
|
? relationValue
|
||||||
: fieldMetadata.type !== FieldMetadataType.Enum || isValidSelectValue
|
: fieldMetadata.type === FieldMetadataType.Enum
|
||||||
? firstRecordFieldValue
|
? selectValue || defaultSelectValue
|
||||||
: undefined) || defaultValue,
|
: firstRecordFieldValue || defaultValue,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||||
|
|
||||||
|
export type SettingsObjectFieldSelectFormOption = {
|
||||||
|
color: ThemeColor;
|
||||||
|
isDefault?: boolean;
|
||||||
|
label: string;
|
||||||
|
value?: string;
|
||||||
|
};
|
||||||
@ -13,6 +13,7 @@ import { Key } from 'ts-key-enum';
|
|||||||
|
|
||||||
import { IconAlertCircle } from '@/ui/display/icon';
|
import { IconAlertCircle } from '@/ui/display/icon';
|
||||||
import { IconEye, IconEyeOff } from '@/ui/display/icon/index';
|
import { IconEye, IconEyeOff } from '@/ui/display/icon/index';
|
||||||
|
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
|
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
|
||||||
@ -29,6 +30,7 @@ export type TextInputComponentProps = Omit<
|
|||||||
fullWidth?: boolean;
|
fullWidth?: boolean;
|
||||||
disableHotkeys?: boolean;
|
disableHotkeys?: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
|
RightIcon?: IconComponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled.div<Pick<TextInputComponentProps, 'fullWidth'>>`
|
const StyledContainer = styled.div<Pick<TextInputComponentProps, 'fullWidth'>>`
|
||||||
@ -101,7 +103,7 @@ const StyledTrailingIconContainer = styled.div`
|
|||||||
const StyledTrailingIcon = styled.div`
|
const StyledTrailingIcon = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: ${({ theme }) => theme.font.color.light};
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
cursor: pointer;
|
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
`;
|
`;
|
||||||
@ -125,6 +127,7 @@ const TextInputComponent = (
|
|||||||
placeholder,
|
placeholder,
|
||||||
disabled,
|
disabled,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
RightIcon,
|
||||||
}: TextInputComponentProps,
|
}: TextInputComponentProps,
|
||||||
// eslint-disable-next-line twenty/component-props-naming
|
// eslint-disable-next-line twenty/component-props-naming
|
||||||
ref: ForwardedRef<HTMLInputElement>,
|
ref: ForwardedRef<HTMLInputElement>,
|
||||||
@ -201,6 +204,11 @@ const TextInputComponent = (
|
|||||||
)}
|
)}
|
||||||
</StyledTrailingIcon>
|
</StyledTrailingIcon>
|
||||||
)}
|
)}
|
||||||
|
{!error && type !== INPUT_TYPE_PASSWORD && !!RightIcon && (
|
||||||
|
<StyledTrailingIcon>
|
||||||
|
<RightIcon size={theme.icon.size.md} />
|
||||||
|
</StyledTrailingIcon>
|
||||||
|
)}
|
||||||
</StyledTrailingIconContainer>
|
</StyledTrailingIconContainer>
|
||||||
</StyledInputContainer>
|
</StyledInputContainer>
|
||||||
{error && <StyledErrorHelper>{error}</StyledErrorHelper>}
|
{error && <StyledErrorHelper>{error}</StyledErrorHelper>}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ import { useSelectField } from '../../hooks/useSelectField';
|
|||||||
export const SelectFieldDisplay = () => {
|
export const SelectFieldDisplay = () => {
|
||||||
const { fieldValue } = useSelectField();
|
const { fieldValue } = useSelectField();
|
||||||
|
|
||||||
return <Tag color={fieldValue.color} text={fieldValue.text} />;
|
return <Tag color={fieldValue.color} text={fieldValue.label} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,15 +26,15 @@ export const useSelectField = () => {
|
|||||||
);
|
);
|
||||||
const fieldSelectValue = isFieldSelectValue(fieldValue)
|
const fieldSelectValue = isFieldSelectValue(fieldValue)
|
||||||
? fieldValue
|
? fieldValue
|
||||||
: { color: 'green' as ThemeColor, text: '' };
|
: { color: 'green' as ThemeColor, label: '' };
|
||||||
|
|
||||||
const fieldInitialValue = useFieldInitialValue();
|
const fieldInitialValue = useFieldInitialValue();
|
||||||
|
|
||||||
const initialValue = {
|
const initialValue = {
|
||||||
color: 'green' as ThemeColor,
|
color: 'green' as ThemeColor,
|
||||||
text: fieldInitialValue?.isEmpty
|
label: fieldInitialValue?.isEmpty
|
||||||
? ''
|
? ''
|
||||||
: fieldInitialValue?.value ?? fieldSelectValue?.text ?? '',
|
: fieldInitialValue?.value ?? fieldSelectValue?.label ?? '',
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -116,6 +116,6 @@ export type FieldCurrencyValue = {
|
|||||||
};
|
};
|
||||||
export type FieldFullNameValue = { firstName: string; lastName: string };
|
export type FieldFullNameValue = { firstName: string; lastName: string };
|
||||||
export type FieldProbabilityValue = number;
|
export type FieldProbabilityValue = number;
|
||||||
export type FieldSelectValue = { color: ThemeColor; text: string };
|
export type FieldSelectValue = { color: ThemeColor; label: string };
|
||||||
|
|
||||||
export type FieldRelationValue = EntityForSelect | null;
|
export type FieldRelationValue = EntityForSelect | null;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { mainColors, ThemeColor } from '@/ui/theme/constants/colors';
|
|||||||
const selectColors = Object.keys(mainColors) as [ThemeColor, ...ThemeColor[]];
|
const selectColors = Object.keys(mainColors) as [ThemeColor, ...ThemeColor[]];
|
||||||
const selectValueSchema = z.object({
|
const selectValueSchema = z.object({
|
||||||
color: z.enum(selectColors),
|
color: z.enum(selectColors),
|
||||||
text: z.string(),
|
label: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const isFieldSelectValue = (
|
export const isFieldSelectValue = (
|
||||||
|
|||||||
@ -19,7 +19,10 @@ import { Button } from '@/ui/input/button/components/Button';
|
|||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
||||||
import { Section } from '@/ui/layout/section/components/Section';
|
import { Section } from '@/ui/layout/section/components/Section';
|
||||||
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import {
|
||||||
|
FieldMetadataType,
|
||||||
|
RelationMetadataType,
|
||||||
|
} from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
export const SettingsObjectFieldEdit = () => {
|
export const SettingsObjectFieldEdit = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -70,10 +73,10 @@ export const SettingsObjectFieldEdit = () => {
|
|||||||
relation: {
|
relation: {
|
||||||
field: {
|
field: {
|
||||||
icon: relationFieldMetadataItem?.icon,
|
icon: relationFieldMetadataItem?.icon,
|
||||||
label: relationFieldMetadataItem?.label,
|
label: relationFieldMetadataItem?.label || '',
|
||||||
},
|
},
|
||||||
objectMetadataId: relationObjectMetadataItem?.id,
|
objectMetadataId: relationObjectMetadataItem?.id || '',
|
||||||
type: relationType,
|
type: relationType || RelationMetadataType.OneToMany,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [
|
}, [
|
||||||
|
|||||||
@ -54,7 +54,8 @@ export const SettingsObjectNewFieldStep2 = () => {
|
|||||||
initForm({
|
initForm({
|
||||||
relation: {
|
relation: {
|
||||||
field: { icon: activeObjectMetadataItem.icon },
|
field: { icon: activeObjectMetadataItem.icon },
|
||||||
objectMetadataId: findObjectMetadataItemByNamePlural('people')?.id,
|
objectMetadataId:
|
||||||
|
findObjectMetadataItemByNamePlural('people')?.id || '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [
|
}, [
|
||||||
|
|||||||
Reference in New Issue
Block a user