refactor: validate objectMetadataItem with Zod on creation and update… (#4270)

* refactor: validate objectMetadataItem with Zod on creation and update & remove logic from useObjectMetadataItemForSettings

* refactor: review
This commit is contained in:
Thaïs
2024-03-05 07:32:30 -03:00
committed by GitHub
parent 0a2d8056bd
commit a9f4a66c4f
20 changed files with 332 additions and 189 deletions

View File

@ -1,12 +1,15 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useCreateOneObjectMetadataItem } from '@/object-metadata/hooks/useCreateOneObjectMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsObjectFormSection } from '@/settings/data-model/components/SettingsObjectFormSection';
import { settingsCreateObjectInputSchema } from '@/settings/data-model/validation-schemas/settingsCreateObjectInputSchema';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { IconSettings } from '@/ui/display/icon';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
@ -16,27 +19,22 @@ export const SettingsNewObject = () => {
const navigate = useNavigate();
const { enqueueSnackBar } = useSnackBar();
const { createObjectMetadataItem: createObject } =
useObjectMetadataItemForSettings();
const { createOneObjectMetadataItem } = useCreateOneObjectMetadataItem();
const [customFormValues, setCustomFormValues] = useState<{
const [formValues, setFormValues] = useState<{
description?: string;
icon: string;
labelPlural: string;
labelSingular: string;
}>({ icon: 'IconListNumbers', labelPlural: '', labelSingular: '' });
const canSave =
!!customFormValues.labelPlural && !!customFormValues.labelSingular;
const canSave = !!formValues.labelPlural && !!formValues.labelSingular;
const handleSave = async () => {
try {
const createdObject = await createObject({
labelPlural: customFormValues.labelPlural,
labelSingular: customFormValues.labelSingular,
description: customFormValues.description,
icon: customFormValues.icon,
});
const createdObject = await createOneObjectMetadataItem(
settingsCreateObjectInputSchema.parse(formValues),
);
navigate(
createdObject.data?.createOneObject.isActive
@ -58,25 +56,26 @@ export const SettingsNewObject = () => {
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Objects', href: '/settings/objects' },
{
children: 'Objects',
href: getSettingsPagePath(SettingsPath.Objects),
},
{ children: 'New' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/objects');
}}
onCancel={() => navigate(getSettingsPagePath(SettingsPath.Objects))}
onSave={handleSave}
/>
</SettingsHeaderContainer>
<SettingsObjectFormSection
icon={customFormValues.icon}
singularName={customFormValues.labelSingular}
pluralName={customFormValues.labelPlural}
description={customFormValues.description}
icon={formValues.icon}
singularName={formValues.labelSingular}
pluralName={formValues.labelPlural}
description={formValues.description}
onChange={(formValues) => {
setCustomFormValues((previousValues) => ({
setFormValues((previousValues) => ({
...previousValues,
...formValues,
}));

View File

@ -4,6 +4,7 @@ import styled from '@emotion/styled';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
@ -16,7 +17,9 @@ import {
StyledObjectFieldTableRow,
} from '@/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow';
import { getFieldIdentifierType } from '@/settings/data-model/utils/getFieldIdentifierType';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { IconPlus, IconSettings } from '@/ui/display/icon';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { Button } from '@/ui/input/button/components/Button';
@ -38,11 +41,9 @@ export const SettingsObjectDetail = () => {
const navigate = useNavigate();
const { objectSlug = '' } = useParams();
const {
disableObjectMetadataItem,
editObjectMetadataItem,
findActiveObjectMetadataItemBySlug,
} = useObjectMetadataItemForSettings();
const { findActiveObjectMetadataItemBySlug } =
useObjectMetadataItemForSettings();
const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem();
const activeObjectMetadataItem =
findActiveObjectMetadataItemBySlug(objectSlug);
@ -64,8 +65,11 @@ export const SettingsObjectDetail = () => {
);
const handleDisableObject = async () => {
await disableObjectMetadataItem(activeObjectMetadataItem);
navigate('/settings/objects');
await updateOneObjectMetadataItem({
idToUpdate: activeObjectMetadataItem.id,
updatePayload: { isActive: false },
});
navigate(getSettingsPagePath(SettingsPath.Objects));
};
const handleDisableField = (activeFieldMetadatItem: FieldMetadataItem) => {
@ -74,12 +78,13 @@ export const SettingsObjectDetail = () => {
const handleSetLabelIdentifierField = (
activeFieldMetadatItem: FieldMetadataItem,
) => {
editObjectMetadataItem({
...activeObjectMetadataItem,
labelIdentifierFieldMetadataId: activeFieldMetadatItem.id,
) =>
updateOneObjectMetadataItem({
idToUpdate: activeObjectMetadataItem.id,
updatePayload: {
labelIdentifierFieldMetadataId: activeFieldMetadatItem.id,
},
});
};
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">

View File

@ -2,13 +2,17 @@ import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsObjectFormSection } from '@/settings/data-model/components/SettingsObjectFormSection';
import { SettingsDataModelObjectSettingsFormCard } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectSettingsFormCard';
import { settingsUpdateObjectInputSchema } from '@/settings/data-model/validation-schemas/settingsUpdateObjectInputSchema';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { IconArchive, IconSettings } from '@/ui/display/icon';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -22,11 +26,9 @@ export const SettingsObjectEdit = () => {
const { enqueueSnackBar } = useSnackBar();
const { objectSlug = '' } = useParams();
const {
disableObjectMetadataItem,
editObjectMetadataItem,
findActiveObjectMetadataItemBySlug,
} = useObjectMetadataItemForSettings();
const { findActiveObjectMetadataItemBySlug } =
useObjectMetadataItemForSettings();
const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem();
const activeObjectMetadataItem =
findActiveObjectMetadataItemBySlug(objectSlug);
@ -76,7 +78,10 @@ export const SettingsObjectEdit = () => {
};
try {
await editObjectMetadataItem(editedObjectMetadataItem);
await updateOneObjectMetadataItem({
idToUpdate: activeObjectMetadataItem.id,
updatePayload: settingsUpdateObjectInputSchema.parse(formValues),
});
navigate(`/settings/objects/${getObjectSlug(editedObjectMetadataItem)}`);
} catch (error) {
@ -87,8 +92,11 @@ export const SettingsObjectEdit = () => {
};
const handleDisable = async () => {
await disableObjectMetadataItem(activeObjectMetadataItem);
navigate('/settings/objects');
await updateOneObjectMetadataItem({
idToUpdate: activeObjectMetadataItem.id,
updatePayload: { isActive: false },
});
navigate(getSettingsPagePath(SettingsPath.Objects));
};
return (

View File

@ -2,7 +2,9 @@ import { useNavigate } from 'react-router-dom';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
@ -12,6 +14,8 @@ import {
} from '@/settings/data-model/object-details/components/SettingsObjectItemTableRow';
import { SettingsObjectCoverImage } from '@/settings/data-model/objects/SettingsObjectCoverImage';
import { SettingsObjectInactiveMenuDropDown } from '@/settings/data-model/objects/SettingsObjectInactiveMenuDropDown';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { IconChevronRight, IconPlus, IconSettings } from '@/ui/display/icon';
import { H1Title } from '@/ui/display/typography/components/H1Title';
import { H2Title } from '@/ui/display/typography/components/H2Title';
@ -34,12 +38,10 @@ export const SettingsObjects = () => {
const theme = useTheme();
const navigate = useNavigate();
const {
activateObjectMetadataItem,
activeObjectMetadataItems,
inactiveObjectMetadataItems,
eraseObjectMetadataItem,
} = useObjectMetadataItemForSettings();
const { activeObjectMetadataItems, inactiveObjectMetadataItems } =
useObjectMetadataItemForSettings();
const { deleteOneObjectMetadataItem } = useDeleteOneObjectMetadataItem();
const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem();
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
@ -51,7 +53,9 @@ export const SettingsObjects = () => {
title="Add object"
accent="blue"
size="small"
onClick={() => navigate('/settings/objects/new')}
onClick={() =>
navigate(getSettingsPagePath(SettingsPath.NewObject))
}
/>
</SettingsHeaderContainer>
<div>
@ -101,13 +105,14 @@ export const SettingsObjects = () => {
isCustomObject={inactiveObjectMetadataItem.isCustom}
scopeKey={inactiveObjectMetadataItem.namePlural}
onActivate={() =>
activateObjectMetadataItem(
inactiveObjectMetadataItem,
)
updateOneObjectMetadataItem({
idToUpdate: inactiveObjectMetadataItem.id,
updatePayload: { isActive: true },
})
}
onErase={() =>
eraseObjectMetadataItem(
inactiveObjectMetadataItem,
deleteOneObjectMetadataItem(
inactiveObjectMetadataItem.id,
)
}
/>