From 9c8e0f628e5adadf0ecadd887256abffd20fdef1 Mon Sep 17 00:00:00 2001 From: ANIMESH DUTTA <132822834+animesh65432@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:09:48 +0530 Subject: [PATCH] Redirect to select option creation when no result (#14460) fix:Ability to add a new option for a multi-select on the fly Issues:#13877 --------- Co-authored-by: ehconitin Co-authored-by: Lucas Bordeau --- .../ObjectFilterDropdownOptionSelect.tsx | 4 +- .../ui/meta-types/hooks/useAddSelectOption.ts | 45 +++++++++++++++++ .../meta-types/hooks/useCanAddSelectOption.ts | 19 ++++++++ .../components/MultiSelectFieldInput.tsx | 17 ++++++- .../input/components/SelectFieldInput.tsx | 16 +++++++ .../components/AddSelectOptionMenuItem.tsx | 37 ++++++++++++++ .../SettingsDataModelFieldSelectForm.tsx | 21 ++++++++ .../select/utils/generateNewSelectOption.ts | 4 +- .../input/components/MultiSelectInput.tsx | 23 +++++++-- .../ui/field/input/components/SelectInput.tsx | 3 ++ .../ui/input/components/SelectInput.tsx | 14 ++++++ ...ldNavigateBackToMemorizedUrlOnSaveState.ts | 8 ++++ .../data-model/SettingsObjectFieldEdit.tsx | 48 +++++++++++++++---- 13 files changed, 242 insertions(+), 17 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useAddSelectOption.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useCanAddSelectOption.ts create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/AddSelectOptionMenuItem.tsx create mode 100644 packages/twenty-front/src/modules/ui/navigation/states/shouldNavigateBackToMemorizedUrlOnSaveState.ts diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx index 24a7fb87e2..b94ba55f99 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx @@ -18,6 +18,7 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; +import { t } from '@lingui/core/macro'; import { isNonEmptyString } from '@sniptt/guards'; import { MAX_OPTIONS_TO_DISPLAY } from 'twenty-shared/constants'; import { isDefined } from 'twenty-shared/utils'; @@ -145,6 +146,7 @@ export const ObjectFilterDropdownOptionSelect = ({ ); const showNoResult = optionsInDropdown?.length === 0; + const objectRecordsIds = optionsInDropdown.map((option) => option.id); return ( @@ -155,7 +157,7 @@ export const ObjectFilterDropdownOptionSelect = ({ > {showNoResult ? ( - + ) : ( optionsInDropdown?.map((option) => ( { + const { objectNamePlural } = useParams(); + const navigateSettings = useNavigateSettings(); + const setNavigationMemorizedUrl = useSetRecoilState( + navigationMemorizedUrlState, + ); + + const setShouldNavigateBackToMemorizedUrlOnSave = useSetRecoilState( + shouldNavigateBackToMemorizedUrlOnSaveState, + ); + + const addSelectOption = useCallback( + (optionName: string) => { + if (!fieldName || !objectNamePlural) return; + + setNavigationMemorizedUrl( + window.location.pathname + window.location.search, + ); + setShouldNavigateBackToMemorizedUrlOnSave(true); + + navigateSettings( + SettingsPath.ObjectFieldEdit, + { objectNamePlural, fieldName }, + { newOption: optionName }, + ); + }, + [ + fieldName, + objectNamePlural, + navigateSettings, + setNavigationMemorizedUrl, + setShouldNavigateBackToMemorizedUrlOnSave, + ], + ); + + return { addSelectOption }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useCanAddSelectOption.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useCanAddSelectOption.ts new file mode 100644 index 0000000000..83df7c5465 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useCanAddSelectOption.ts @@ -0,0 +1,19 @@ +import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag'; +import { isNonEmptyString } from '@sniptt/guards'; +import { useParams } from 'react-router-dom'; +import { PermissionFlagType } from '~/generated-metadata/graphql'; + +export const useCanAddSelectOption = (fieldName: string) => { + const { objectNamePlural } = useParams(); + + const userHasPermissionToEditDataModel = useHasPermissionFlag( + PermissionFlagType.DATA_MODEL, + ); + + const canAddSelectOption = + userHasPermissionToEditDataModel && + isNonEmptyString(fieldName) && + isNonEmptyString(objectNamePlural); + + return { canAddSelectOption }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/MultiSelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/MultiSelectFieldInput.tsx index 42bf337a1a..572f6e82b3 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/MultiSelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/MultiSelectFieldInput.tsx @@ -1,15 +1,22 @@ import { FieldInputEventContext } from '@/object-record/record-field/ui/contexts/FieldInputEventContext'; +import { useAddSelectOption } from '@/object-record/record-field/ui/meta-types/hooks/useAddSelectOption'; +import { useCanAddSelectOption } from '@/object-record/record-field/ui/meta-types/hooks/useCanAddSelectOption'; import { useMultiSelectField } from '@/object-record/record-field/ui/meta-types/hooks/useMultiSelectField'; import { SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-field/ui/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId'; import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext'; import { type FieldMultiSelectValue } from '@/object-record/record-field/ui/types/FieldMetadata'; - import { MultiSelectInput } from '@/ui/field/input/components/MultiSelectInput'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useContext } from 'react'; export const MultiSelectFieldInput = () => { const { fieldDefinition, draftValue, setDraftValue } = useMultiSelectField(); + const { addSelectOption } = useAddSelectOption( + fieldDefinition?.metadata?.fieldName, + ); + const { canAddSelectOption } = useCanAddSelectOption( + fieldDefinition?.metadata?.fieldName, + ); const { onSubmit } = useContext(FieldInputEventContext); @@ -25,6 +32,13 @@ export const MultiSelectFieldInput = () => { onSubmit?.({ newValue: draftValue }); }; + const handleAddSelectOption = (optionName: string) => { + if (!canAddSelectOption) { + return; + } + addSelectOption(optionName); + }; + return ( { onCancel={handleCancel} onOptionSelected={handleOptionSelected} values={draftValue} + onAddSelectOption={handleAddSelectOption} /> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/SelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/SelectFieldInput.tsx index 53a1feb384..83dfa8ab1e 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/SelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/SelectFieldInput.tsx @@ -1,5 +1,7 @@ import { FieldInputEventContext } from '@/object-record/record-field/ui/contexts/FieldInputEventContext'; import { useClearField } from '@/object-record/record-field/ui/hooks/useClearField'; +import { useAddSelectOption } from '@/object-record/record-field/ui/meta-types/hooks/useAddSelectOption'; +import { useCanAddSelectOption } from '@/object-record/record-field/ui/meta-types/hooks/useCanAddSelectOption'; import { useSelectField } from '@/object-record/record-field/ui/meta-types/hooks/useSelectField'; import { SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-field/ui/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId'; import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext'; @@ -14,6 +16,12 @@ import { type SelectOption } from 'twenty-ui/input'; export const SelectFieldInput = () => { const { fieldDefinition, fieldValue } = useSelectField(); + const { addSelectOption } = useAddSelectOption( + fieldDefinition?.metadata?.fieldName, + ); + const { canAddSelectOption } = useCanAddSelectOption( + fieldDefinition?.metadata?.fieldName, + ); const { onCancel, onSubmit } = useContext(FieldInputEventContext); @@ -37,6 +45,13 @@ export const SelectFieldInput = () => { onCancel?.(); }; + const handleAddSelectOption = (optionName: string) => { + if (!canAddSelectOption) { + return; + } + addSelectOption(optionName); + }; + const handleSubmit = (option: SelectOption) => { onSubmit?.({ newValue: option.value }); @@ -82,6 +97,7 @@ export const SelectFieldInput = () => { fieldDefinition.metadata.isNullable ? handleClearField : undefined } clearLabel={fieldDefinition.label} + onAddSelectOption={handleAddSelectOption} /> ); }; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/AddSelectOptionMenuItem.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/AddSelectOptionMenuItem.tsx new file mode 100644 index 0000000000..82ae9033ec --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/AddSelectOptionMenuItem.tsx @@ -0,0 +1,37 @@ +import { t } from '@lingui/core/macro'; +import { isNonEmptyString } from '@sniptt/guards'; +import { isDefined } from 'twenty-shared/utils'; +import { IconPlus } from 'twenty-ui/display'; +import { MenuItem } from 'twenty-ui/navigation'; + +type AddSelectOptionMenuItemProps = { + name: string; + onAddSelectOption?: (optionName: string) => void; +}; + +export const AddSelectOptionMenuItem = ({ + name, + onAddSelectOption, +}: AddSelectOptionMenuItemProps) => { + const trimmedName = name.trim(); + const showAddOption = + isNonEmptyString(trimmedName) && isDefined(onAddSelectOption); + + const handleClick = () => { + if (isDefined(onAddSelectOption)) { + onAddSelectOption(trimmedName); + } + }; + + if (!showAddOption) { + return null; + } + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx index afeafb3503..a5eebe77d6 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx @@ -20,7 +20,10 @@ import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToStr import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsWrapper'; import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; import { t } from '@lingui/core/macro'; +import { useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-shared/utils'; import { IconPlus, IconPoint } from 'twenty-ui/display'; import { LightButton } from 'twenty-ui/input'; import { CardContent, CardFooter } from 'twenty-ui/layout'; @@ -114,8 +117,11 @@ export const SettingsDataModelFieldSelectForm = ({ useSelectSettingsFormInitialValues({ fieldMetadataId: existingFieldMetadataId, }); + const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState); + const [searchParams] = useSearchParams(); + const { control, setValue: setFormValue, @@ -123,6 +129,21 @@ export const SettingsDataModelFieldSelectForm = ({ getValues, } = useFormContext(); + const [hasAppliedNewOption, setHasAppliedNewOption] = useState(false); + + useEffect(() => { + const newOptionValue = searchParams.get('newOption'); + + if (isDefined(newOptionValue) && !hasAppliedNewOption) { + const newOption = generateNewSelectOption(initialOptions, newOptionValue); + + const optionsWithNew = [...initialOptions, newOption]; + + setFormValue('options', optionsWithNew, { shouldDirty: true }); + setHasAppliedNewOption(true); + } + }, [searchParams, hasAppliedNewOption, initialOptions, setFormValue]); + const handleDragEnd = ( values: FieldMetadataItemOption[], result: DropResult, diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/utils/generateNewSelectOption.ts b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/utils/generateNewSelectOption.ts index f3872e5172..4392d72562 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/utils/generateNewSelectOption.ts +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/utils/generateNewSelectOption.ts @@ -7,9 +7,9 @@ import { computeOptionValueFromLabel } from '~/pages/settings/data-model/utils/c export const generateNewSelectOption = ( options: FieldMetadataItemOption[], + label?: string, ): FieldMetadataItemOption => { - const newOptionLabel = generateNewSelectOptionLabel(options); - + const newOptionLabel = label ?? generateNewSelectOptionLabel(options); return { color: getNextThemeColor(options[options.length - 1]?.color), id: v4(), diff --git a/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx index be64184b63..3d601681bf 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx @@ -7,6 +7,7 @@ import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/Dropdow import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; +import { AddSelectOptionMenuItem } from '@/settings/data-model/fields/forms/select/components/AddSelectOptionMenuItem'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; @@ -14,7 +15,7 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import { useLingui } from '@lingui/react/macro'; +import { t } from '@lingui/core/macro'; import { isDefined } from 'twenty-shared/utils'; import { type SelectOption } from 'twenty-ui/input'; import { MenuItem, MenuItemMultiSelectTag } from 'twenty-ui/navigation'; @@ -29,6 +30,7 @@ type MultiSelectInputProps = { options: SelectOption[]; onOptionSelected: (value: FieldMultiSelectValue) => void; dropdownWidth?: number; + onAddSelectOption?: (optionName: string) => void; }; export const MultiSelectInput = ({ @@ -39,9 +41,8 @@ export const MultiSelectInput = ({ onCancel, onOptionSelected, dropdownWidth, + onAddSelectOption, }: MultiSelectInputProps) => { - const { t } = useLingui(); - const { resetSelectedItem } = useSelectableList( selectableListComponentInstanceId, ); @@ -50,6 +51,7 @@ export const MultiSelectInput = ({ selectedItemIdComponentState, selectableListComponentInstanceId, ); + const [searchFilter, setSearchFilter] = useState(''); const containerRef = useRef(null); @@ -129,7 +131,7 @@ export const MultiSelectInput = ({ {filteredOptionsInDropDown.length === 0 ? ( - + ) : ( filteredOptionsInDropDown.map((option) => { return ( @@ -156,6 +158,19 @@ export const MultiSelectInput = ({ }) )} + {onAddSelectOption && + searchFilter && + filteredOptionsInDropDown.length === 0 && ( + <> + + + + + + )} ); diff --git a/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx index 9fcdb1a41c..5942d7521e 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx @@ -14,6 +14,7 @@ type SelectInputProps = { onFilterChange?: ((filteredOptions: SelectOption[]) => void) | undefined; onClear?: (() => void) | undefined; clearLabel?: string; + onAddSelectOption?: (optionName: string) => void; }; export const SelectInput = ({ @@ -27,6 +28,7 @@ export const SelectInput = ({ onFilterChange, onClear, clearLabel, + onAddSelectOption, }: SelectInputProps) => { return ( ); diff --git a/packages/twenty-front/src/modules/ui/input/components/SelectInput.tsx b/packages/twenty-front/src/modules/ui/input/components/SelectInput.tsx index 1e25318ee8..c8d314b40f 100644 --- a/packages/twenty-front/src/modules/ui/input/components/SelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/SelectInput.tsx @@ -1,3 +1,4 @@ +import { AddSelectOptionMenuItem } from '@/settings/data-model/fields/forms/select/components/AddSelectOptionMenuItem'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; @@ -24,6 +25,7 @@ interface SelectInputProps { onClear?: () => void; clearLabel?: string; focusId: string; + onAddSelectOption?: (optionName: string) => void; } export const SelectInput = ({ @@ -34,6 +36,7 @@ export const SelectInput = ({ onCancel, defaultOption, onFilterChange, + onAddSelectOption, }: SelectInputProps) => { const containerRef = useRef(null); @@ -144,6 +147,17 @@ export const SelectInput = ({ ); })} + {onAddSelectOption && searchFilter && optionsToSelect.length === 0 && ( + <> + + + + + + )} ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/states/shouldNavigateBackToMemorizedUrlOnSaveState.ts b/packages/twenty-front/src/modules/ui/navigation/states/shouldNavigateBackToMemorizedUrlOnSaveState.ts new file mode 100644 index 0000000000..40220c21f8 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/states/shouldNavigateBackToMemorizedUrlOnSaveState.ts @@ -0,0 +1,8 @@ +import { createState } from 'twenty-ui/utilities'; + +export const shouldNavigateBackToMemorizedUrlOnSaveState = createState( + { + key: 'shouldNavigateBackToMemorizedUrlOnSaveState', + defaultValue: false, + }, +); diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx index 392e452317..aa950d0fb6 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx @@ -3,7 +3,7 @@ import omit from 'lodash.omit'; import pick from 'lodash.pick'; import { useEffect, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import { type z } from 'zod'; import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem'; @@ -23,8 +23,11 @@ import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/vali import { type SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; +import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; +import { shouldNavigateBackToMemorizedUrlOnSaveState } from '@/ui/navigation/states/shouldNavigateBackToMemorizedUrlOnSaveState'; import { ApolloError } from '@apollo/client'; import { useLingui } from '@lingui/react/macro'; +import { useRecoilState } from 'recoil'; import { AppPath, SettingsPath } from 'twenty-shared/types'; import { getSettingsPath, isDefined } from 'twenty-shared/utils'; import { H2Title, IconArchive, IconArchiveOff } from 'twenty-ui/display'; @@ -45,6 +48,17 @@ export const SettingsObjectFieldEdit = () => { const navigateApp = useNavigateApp(); const { t } = useLingui(); + const navigate = useNavigate(); + + const [navigationMemorizedUrl, setNavigationMemorizedUrl] = useRecoilState( + navigationMemorizedUrlState, + ); + + const [ + shouldNavigateBackToMemorizedUrlOnSave, + setShouldNavigateBackToMemorizedUrlOnSave, + ] = useRecoilState(shouldNavigateBackToMemorizedUrlOnSaveState); + const { enqueueErrorSnackBar } = useSnackBar(); const { objectNamePlural = '', fieldName = '' } = useParams(); @@ -141,9 +155,7 @@ export const SettingsObjectFieldEdit = () => { updatePayload: formattedInput, }); - navigateSettings(SettingsPath.ObjectDetail, { - objectNamePlural, - }); + navigateBackOrToSettings(); } } catch (error) { enqueueErrorSnackBar({ @@ -152,6 +164,28 @@ export const SettingsObjectFieldEdit = () => { } }; + const navigateBackOrToSettings = () => { + if ( + shouldNavigateBackToMemorizedUrlOnSave && + isDefined(navigationMemorizedUrl) + ) { + navigate(navigationMemorizedUrl, { replace: true }); + + setShouldNavigateBackToMemorizedUrlOnSave(false); + setNavigationMemorizedUrl('/'); + + return; + } + + navigateSettings(SettingsPath.ObjectDetail, { + objectNamePlural, + }); + }; + + const handleCancel = () => { + navigateBackOrToSettings(); + }; + const handleDeactivate = async () => { await deactivateMetadataField(fieldMetadataItem.id, objectMetadataItem.id); navigateSettings(SettingsPath.ObjectDetail, { @@ -196,11 +230,7 @@ export const SettingsObjectFieldEdit = () => { isLoading={isSubmitting} isSaveDisabled={!canSave} isCancelDisabled={isSubmitting} - onCancel={() => - navigateSettings(SettingsPath.ObjectDetail, { - objectNamePlural, - }) - } + onCancel={handleCancel} onSave={formConfig.handleSubmit(handleSave)} /> }