From d61d5857f8f3fdcad8aa14c69029bb05b0ca40a8 Mon Sep 17 00:00:00 2001 From: "gitstart-app[bot]" <57568882+gitstart-app[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:10:32 +0200 Subject: [PATCH] View becomes blank after deleting select (#6703) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-6027](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6027). This ticket was imported from: [TWNTY-6027](https://github.com/twentyhq/twenty/issues/6027) --- ### Description - Delete corresponding view simultaneously once select field is deactivated instead of deleted because the bug happens on the deactivation (one step before deleting), confirmation: - Is still possible to create Kanban views with deactivated Select fields, but this is not related to the PR. - The changes on the frontend are for refreshing the data after the view deletion ### Refs #6027 ### Demo Fixes #6027 --------- Co-authored-by: gitstart-twenty Co-authored-by: Lucas Bordeau --- .../RecordIndexOptionsDropdownContent.tsx | 3 +- .../SettingsObjectFieldItemTableRow.tsx | 48 ++++++++++++++++++- .../field-metadata/field-metadata.service.ts | 14 ++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx index 8a2201d81..73de518b0 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx @@ -12,6 +12,7 @@ import { } from 'twenty-ui'; import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObjectNamePluralFromSingular'; +import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter'; import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId'; import { displayedExportProgress, @@ -38,7 +39,6 @@ import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { ViewType } from '@/views/types/ViewType'; import { useLocation } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; -import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter'; type RecordIndexOptionsMenu = 'fields' | 'hiddenFields'; @@ -218,6 +218,7 @@ export const RecordIndexOptionsDropdownContent = ({ to={settingsUrl} onClick={() => { setNavigationMemorizedUrl(location.pathname + location.search); + closeDropdown(); }} > diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx index 92c7afecb..8793be03d 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx @@ -15,12 +15,18 @@ import { RELATION_TYPES } from '../../constants/RelationTypes'; import { LABEL_IDENTIFIER_FIELD_METADATA_TYPES } from '@/object-metadata/constants/LabelIdentifierFieldMetadataTypes'; import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem'; import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug'; import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; +import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteRecordFromCache'; +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown'; import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown'; import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; +import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; +import { View } from '@/views/types/View'; import { useNavigate } from 'react-router-dom'; import { useRecoilState } from 'recoil'; import { RelationMetadataType } from '~/generated-metadata/graphql'; @@ -61,6 +67,10 @@ export const SettingsObjectFieldItemTableRow = ({ const navigate = useNavigate(); + const [navigationMemorizedUrl, setNavigationMemorizedUrl] = useRecoilState( + navigationMemorizedUrlState, + ); + const theme = useTheme(); const { getIcon } = useIcons(); const Icon = getIcon(fieldMetadataItem.icon); @@ -100,8 +110,42 @@ export const SettingsObjectFieldItemTableRow = ({ deleteMetadataField, } = useFieldMetadataItem(); - const handleDisableField = (activeFieldMetadatItem: FieldMetadataItem) => { - deactivateMetadataField(activeFieldMetadatItem); + const { records: allViews } = usePrefetchedData(PrefetchKey.AllViews); + + const deleteViewFromCache = useDeleteRecordFromCache({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const handleDisableField = async ( + activeFieldMetadatItem: FieldMetadataItem, + ) => { + await deactivateMetadataField(activeFieldMetadatItem); + + const deletedViewIds = allViews + .map((view) => { + if (view.kanbanFieldMetadataId === activeFieldMetadatItem.id) { + deleteViewFromCache(view); + return view.id; + } + + return null; + }) + .filter(isDefined); + + const [baseUrl, queryParams] = navigationMemorizedUrl.includes('?') + ? navigationMemorizedUrl.split('?') + : [navigationMemorizedUrl, '']; + + const params = new URLSearchParams(queryParams); + const currentViewId = params.get('view'); + + if (isDefined(currentViewId) && deletedViewIds.includes(currentViewId)) { + params.delete('view'); + const updatedUrl = params.toString() + ? `${baseUrl}?${params.toString()}` + : baseUrl; + setNavigationMemorizedUrl(updatedUrl); + } }; const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem(); diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts index 277db13e4..6c428c468 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts @@ -51,6 +51,7 @@ import { } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.factory'; import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; @@ -78,6 +79,7 @@ export class FieldMetadataService extends TypeOrmQueryService