feat: add Settings Object Edit identifiers form (#4300)

* feat: add Settings Object Edit identifiers form

Closes #3836

* fix: fix wrong imports after renaming directories
This commit is contained in:
Thaïs
2024-03-08 17:55:30 -03:00
committed by GitHub
parent 40a3b7d849
commit 40bea0d95e
11 changed files with 212 additions and 24 deletions

View File

@ -0,0 +1,101 @@
import { useMemo } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { z } from 'zod';
import { LABEL_IDENTIFIER_FIELD_METADATA_TYPES } from '@/object-metadata/constants/LabelIdentifierFieldMetadataTypes';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems';
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
import { IconCircleOff } from '@/ui/display/icon';
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
import { Select, SelectOption } from '@/ui/input/components/Select';
export const settingsDataModelObjectIdentifiersFormSchema =
objectMetadataItemSchema.pick({
labelIdentifierFieldMetadataId: true,
imageIdentifierFieldMetadataId: true,
});
export type SettingsDataModelObjectIdentifiersFormValues = z.infer<
typeof settingsDataModelObjectIdentifiersFormSchema
>;
type SettingsDataModelObjectIdentifiersFormProps = {
objectMetadataItem: ObjectMetadataItem;
};
const StyledContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
`;
export const SettingsDataModelObjectIdentifiersForm = ({
objectMetadataItem,
}: SettingsDataModelObjectIdentifiersFormProps) => {
const { control } =
useFormContext<SettingsDataModelObjectIdentifiersFormValues>();
const { getIcon } = useIcons();
const labelIdentifierFieldOptions = useMemo(
() =>
getActiveFieldMetadataItems(objectMetadataItem)
.filter(
({ id, type }) =>
LABEL_IDENTIFIER_FIELD_METADATA_TYPES.includes(type) ||
objectMetadataItem.labelIdentifierFieldMetadataId === id,
)
.map<SelectOption<string | null>>((fieldMetadataItem) => ({
Icon: getIcon(fieldMetadataItem.icon),
label: fieldMetadataItem.label,
value: fieldMetadataItem.id,
})),
[getIcon, objectMetadataItem],
);
const imageIdentifierFieldOptions: SelectOption<string | null>[] = [];
const emptyOption: SelectOption<string | null> = {
Icon: IconCircleOff,
label: 'None',
value: null,
};
return (
<StyledContainer>
{[
{
label: 'Record label',
fieldName: 'labelIdentifierFieldMetadataId' as const,
options: labelIdentifierFieldOptions,
},
{
label: 'Record image',
fieldName: 'imageIdentifierFieldMetadataId' as const,
options: imageIdentifierFieldOptions,
},
].map(({ fieldName, label, options }) => (
<Controller
key={fieldName}
name={fieldName}
control={control}
defaultValue={objectMetadataItem[fieldName]}
render={({ field: { onBlur, onChange, value } }) => {
return (
<Select
label={label}
disabled={!objectMetadataItem.isCustom || !options.length}
fullWidth
dropdownId={`${fieldName}-select`}
emptyOption={emptyOption}
options={options}
value={value}
onChange={onChange}
onBlur={onBlur}
/>
);
}}
/>
))}
</StyledContainer>
);
};

View File

@ -1,9 +1,15 @@
import { useMemo } from 'react';
import { useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard';
import { SettingsDataModelCardTitle } from '@/settings/data-model/components/SettingsDataModelCardTitle';
import { SettingsDataModelFieldPreviewCard } from '@/settings/data-model/fields/preview/components/SettingsDataModelFieldPreviewCard';
import {
SettingsDataModelObjectIdentifiersForm,
SettingsDataModelObjectIdentifiersFormValues,
} from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm';
import { SettingsDataModelObjectSummary } from '@/settings/data-model/objects/SettingsDataModelObjectSummary';
import { Card } from '@/ui/layout/card/components/Card';
import { CardContent } from '@/ui/layout/card/components/CardContent';
@ -16,6 +22,10 @@ const StyledFieldPreviewCard = styled(SettingsDataModelFieldPreviewCard)`
width: 100%;
`;
const StyledTopCardContent = styled(CardContent)`
background-color: ${({ theme }) => theme.background.transparent.lighter};
`;
const StyledObjectSummaryCard = styled(Card)`
border-radius: ${({ theme }) => theme.border.radius.md};
color: ${({ theme }) => theme.font.color.primary};
@ -29,13 +39,27 @@ const StyledObjectSummaryCardContent = styled(CardContent)`
export const SettingsDataModelObjectSettingsFormCard = ({
objectMetadataItem,
}: SettingsDataModelObjectSettingsFormCardProps) => {
const labelIdentifierFieldMetadataItem =
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
const { watch: watchFormValue } =
useFormContext<SettingsDataModelObjectIdentifiersFormValues>();
const labelIdentifierFieldMetadataIdFormValue = watchFormValue(
'labelIdentifierFieldMetadataId',
);
const labelIdentifierFieldMetadataItem = useMemo(
() =>
getLabelIdentifierFieldMetadataItem({
fields: objectMetadataItem.fields,
labelIdentifierFieldMetadataId: labelIdentifierFieldMetadataIdFormValue,
}),
[labelIdentifierFieldMetadataIdFormValue, objectMetadataItem],
);
return (
<SettingsDataModelPreviewFormCard
preview={
labelIdentifierFieldMetadataItem ? (
<Card fullWidth>
<StyledTopCardContent divider>
<SettingsDataModelCardTitle>Preview</SettingsDataModelCardTitle>
{labelIdentifierFieldMetadataItem ? (
<StyledFieldPreviewCard
objectMetadataItem={objectMetadataItem}
fieldMetadataItem={labelIdentifierFieldMetadataItem}
@ -49,8 +73,13 @@ export const SettingsDataModelObjectSettingsFormCard = ({
/>
</StyledObjectSummaryCardContent>
</StyledObjectSummaryCard>
)
}
/>
)}
</StyledTopCardContent>
<CardContent>
<SettingsDataModelObjectIdentifiersForm
objectMetadataItem={objectMetadataItem}
/>
</CardContent>
</Card>
);
};