feat: save edited custom field (#2245)
Closes #2161 Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -636,6 +636,7 @@ export type UpdateFieldInput = {
|
||||
icon?: InputMaybe<Scalars['String']['input']>;
|
||||
isActive?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
label?: InputMaybe<Scalars['String']['input']>;
|
||||
name?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
export type UpdateObjectInput = {
|
||||
|
||||
@ -21,6 +21,15 @@ export const useMetadataField = () => {
|
||||
createOneMetadataField({
|
||||
...formatMetadataFieldInput(input),
|
||||
objectId: input.objectId,
|
||||
type: input.type,
|
||||
});
|
||||
|
||||
const editMetadataField = (
|
||||
input: Pick<Field, 'id' | 'label' | 'icon' | 'description'>,
|
||||
) =>
|
||||
updateOneMetadataField({
|
||||
fieldIdToUpdate: input.id,
|
||||
updatePayload: formatMetadataFieldInput(input),
|
||||
});
|
||||
|
||||
const activateMetadataField = (metadataField: Field) =>
|
||||
@ -43,5 +52,6 @@ export const useMetadataField = () => {
|
||||
createMetadataField,
|
||||
disableMetadataField,
|
||||
eraseMetadataField,
|
||||
editMetadataField,
|
||||
};
|
||||
};
|
||||
|
||||
@ -28,7 +28,7 @@ export const useUpdateOneMetadataField = () => {
|
||||
fieldIdToUpdate: UpdateOneMetadataFieldMutationVariables['idToUpdate'];
|
||||
updatePayload: Pick<
|
||||
UpdateOneMetadataFieldMutationVariables['updatePayload'],
|
||||
'description' | 'icon' | 'isActive' | 'label'
|
||||
'description' | 'icon' | 'isActive' | 'label' | 'name'
|
||||
>;
|
||||
}) => {
|
||||
return await mutate({
|
||||
|
||||
@ -1,16 +1,12 @@
|
||||
import toCamelCase from 'lodash.camelcase';
|
||||
|
||||
import { MetadataFieldDataType } from '@/settings/data-model/types/ObjectFieldDataType';
|
||||
import { Field } from '~/generated-metadata/graphql';
|
||||
|
||||
export const formatMetadataFieldInput = (
|
||||
input: Pick<Field, 'label' | 'icon' | 'description'> & {
|
||||
type: MetadataFieldDataType;
|
||||
},
|
||||
input: Pick<Field, 'label' | 'icon' | 'description'>,
|
||||
) => ({
|
||||
description: input.description?.trim() ?? null,
|
||||
icon: input.icon,
|
||||
label: input.label.trim(),
|
||||
name: toCamelCase(input.label.trim()),
|
||||
type: input.type,
|
||||
});
|
||||
|
||||
@ -42,6 +42,7 @@ export const SettingsObjectFieldFormSection = ({
|
||||
/>
|
||||
<StyledInputsContainer>
|
||||
<IconPicker
|
||||
disabled={disabled}
|
||||
selectedIconKey={iconKey}
|
||||
onChange={(value) => onChange?.({ icon: value.iconKey })}
|
||||
variant="primary"
|
||||
|
||||
@ -96,7 +96,7 @@ export const SettingsObjectEdit = () => {
|
||||
{ children: 'Edit' },
|
||||
]}
|
||||
/>
|
||||
{!!activeMetadataObject.isCustom && (
|
||||
{activeMetadataObject.isCustom && (
|
||||
<SaveAndCancelButtons
|
||||
isSaveDisabled={!canSave}
|
||||
onCancel={() => navigate(`/settings/objects/${objectSlug}`)}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import { useMetadataField } from '@/metadata/hooks/useMetadataField';
|
||||
import { useMetadataObjectForSettings } from '@/metadata/hooks/useMetadataObjectForSettings';
|
||||
import { getFieldSlug } from '@/metadata/utils/getFieldSlug';
|
||||
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
|
||||
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsObjectFieldFormSection } from '@/settings/data-model/components/SettingsObjectFieldFormSection';
|
||||
@ -26,22 +27,64 @@ export const SettingsObjectFieldEdit = () => {
|
||||
|
||||
const activeMetadataObject = findActiveMetadataObjectBySlug(objectSlug);
|
||||
|
||||
const { disableMetadataField: disableField } = useMetadataField();
|
||||
const { disableMetadataField, editMetadataField } = useMetadataField();
|
||||
const activeMetadataField = activeMetadataObject?.fields.find(
|
||||
(metadataField) =>
|
||||
metadataField.isActive && getFieldSlug(metadataField) === fieldSlug,
|
||||
);
|
||||
|
||||
const [formValues, setFormValues] = useState<
|
||||
Partial<{
|
||||
icon: string;
|
||||
label: string;
|
||||
description: string;
|
||||
}>
|
||||
>({});
|
||||
|
||||
useEffect(() => {
|
||||
if (loading) return;
|
||||
if (!activeMetadataObject || !activeMetadataField)
|
||||
|
||||
if (!activeMetadataObject || !activeMetadataField) {
|
||||
navigate(AppPath.NotFound);
|
||||
}, [activeMetadataField, activeMetadataObject, loading, navigate]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Object.keys(formValues).length) {
|
||||
setFormValues({
|
||||
icon: activeMetadataField.icon ?? undefined,
|
||||
label: activeMetadataField.label,
|
||||
description: activeMetadataField.description ?? undefined,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
activeMetadataField,
|
||||
activeMetadataObject,
|
||||
formValues,
|
||||
loading,
|
||||
navigate,
|
||||
]);
|
||||
|
||||
if (!activeMetadataObject || !activeMetadataField) return null;
|
||||
|
||||
const areRequiredFieldsFilled = !!formValues.label;
|
||||
|
||||
const hasChanges =
|
||||
formValues.description !== activeMetadataField.description ||
|
||||
formValues.icon !== activeMetadataField.icon ||
|
||||
formValues.label !== activeMetadataField.label;
|
||||
|
||||
const canSave = areRequiredFieldsFilled && hasChanges;
|
||||
|
||||
const handleSave = async () => {
|
||||
const editedField = { ...activeMetadataField, ...formValues };
|
||||
|
||||
await editMetadataField(editedField);
|
||||
|
||||
navigate(`/settings/objects/${objectSlug}`);
|
||||
};
|
||||
|
||||
const handleDisable = async () => {
|
||||
await disableField(activeMetadataField);
|
||||
await disableMetadataField(activeMetadataField);
|
||||
navigate(`/settings/objects/${objectSlug}`);
|
||||
};
|
||||
|
||||
@ -59,13 +102,25 @@ export const SettingsObjectFieldEdit = () => {
|
||||
{ children: activeMetadataField.label },
|
||||
]}
|
||||
/>
|
||||
{activeMetadataField.isCustom && (
|
||||
<SaveAndCancelButtons
|
||||
isSaveDisabled={!canSave}
|
||||
onCancel={() => navigate(`/settings/objects/${objectSlug}`)}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
)}
|
||||
</SettingsHeaderContainer>
|
||||
<SettingsObjectFieldFormSection
|
||||
disabled={!activeMetadataField.isCustom}
|
||||
name={activeMetadataField.label}
|
||||
description={activeMetadataField.description ?? undefined}
|
||||
iconKey={activeMetadataField.icon ?? undefined}
|
||||
onChange={() => undefined}
|
||||
name={formValues.label}
|
||||
description={formValues.description}
|
||||
iconKey={formValues.icon}
|
||||
onChange={(values) =>
|
||||
setFormValues((previousFormValues) => ({
|
||||
...previousFormValues,
|
||||
...values,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
<SettingsObjectFieldTypeSelectSection
|
||||
disabled
|
||||
|
||||
@ -9,6 +9,11 @@ export class UpdateFieldInput {
|
||||
@Field({ nullable: true })
|
||||
label?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Field({ nullable: true })
|
||||
name?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Field({ nullable: true })
|
||||
|
||||
Reference in New Issue
Block a user