From a20ebfa8807ee2abbef3f6e35242cc6191e04fed Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 25 Jun 2026 12:29:45 +0200 Subject: [PATCH] feat(applications): remove the application custom settings tab (#22156) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Removes the application **custom settings tab** feature. This is one half of #22059, split out so it can be reviewed/merged independently from the variable-types enrichment. ## Changes - Remove the `SettingsApplicationCustomTab` component and its tab entry/rendering in `SettingsApplicationDetails`. - Stop syncing `settingsCustomTabFrontComponent` from application manifests — `ApplicationManifestMigrationService` now only syncs the default role. - Deprecate the now-unused fields (kept for backward compatibility, no longer read or synced): - `ApplicationDTO.settingsCustomTabFrontComponentId` (GraphQL `@deprecated`) - `ApplicationManifest.settingsCustomTabFrontComponentUniversalIdentifier` - the `settingsCustomTabFrontComponentId` column comment on `ApplicationEntity` The DB column is intentionally **not dropped**, so existing installations upgrade cleanly. --- .../src/metadata/generated/schema.graphql | 2 +- .../src/metadata/generated/schema.ts | 2 + .../src/generated-metadata/graphql.ts | 1 + .../SettingsApplicationDetails.tsx | 18 -------- .../tabs/SettingsApplicationCustomTab.tsx | 32 -------------- .../application-manifest-migration.service.ts | 43 +++++-------------- .../application/application.entity.ts | 5 +++ .../application/dtos/application.dto.ts | 10 ++++- .../src/application/applicationType.ts | 5 +++ 9 files changed, 33 insertions(+), 85 deletions(-) delete mode 100644 packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationCustomTab.tsx diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index b705dc68ec..ed335e3a21 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -714,7 +714,7 @@ type Application { applicationRegistrationId: UUID canBeUninstalled: Boolean! defaultRoleId: String - settingsCustomTabFrontComponentId: UUID + settingsCustomTabFrontComponentId: UUID @deprecated(reason: "Custom settings tabs are no longer supported. This field is ignored.") defaultLogicFunctionRole: Role agents: [Agent!]! frontComponents: [FrontComponent!]! diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 6dd53433fc..478dfb24b4 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -475,6 +475,7 @@ export interface Application { applicationRegistrationId?: Scalars['UUID'] canBeUninstalled: Scalars['Boolean'] defaultRoleId?: Scalars['String'] + /** @deprecated Custom settings tabs are no longer supported. This field is ignored. */ settingsCustomTabFrontComponentId?: Scalars['UUID'] defaultLogicFunctionRole?: Role agents: Agent[] @@ -3510,6 +3511,7 @@ export interface ApplicationGenqlSelection{ applicationRegistrationId?: boolean | number canBeUninstalled?: boolean | number defaultRoleId?: boolean | number + /** @deprecated Custom settings tabs are no longer supported. This field is ignored. */ settingsCustomTabFrontComponentId?: boolean | number defaultLogicFunctionRole?: RoleGenqlSelection agents?: AgentGenqlSelection diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index fb91d9dde4..b241e072e5 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -302,6 +302,7 @@ export type Application = { objects: Array; packageJsonChecksum?: Maybe; packageJsonFileId?: Maybe; + /** @deprecated Custom settings tabs are no longer supported. This field is ignored. */ settingsCustomTabFrontComponentId?: Maybe; universalIdentifier: Scalars['String']['output']; version?: Maybe; diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx index e6266bfff7..6db5a2de4b 100644 --- a/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx +++ b/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx @@ -22,7 +22,6 @@ import { type Manifest } from 'twenty-shared/application'; import { SettingsPath } from 'twenty-shared/types'; import { getSettingsPath, isDefined } from 'twenty-shared/utils'; import { - IconApps, IconBox, IconCommand, IconGraph, @@ -44,7 +43,6 @@ import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSec import { CUSTOM_APPLICATION_ILLUSTRATIONS } from '~/pages/settings/applications/constants/CustomApplicationIllustrations'; import { STANDARD_APPLICATION_ILLUSTRATIONS } from '~/pages/settings/applications/constants/StandardApplicationIllustrations'; import { useFindApplicationConnectionProviders } from '~/pages/settings/applications/hooks/useFindApplicationConnectionProviders'; -import { SettingsApplicationCustomTab } from '~/pages/settings/applications/tabs/SettingsApplicationCustomTab'; import { SettingsApplicationDetailAboutTab } from '~/pages/settings/applications/tabs/SettingsApplicationDetailAboutTab'; import { SettingsApplicationDetailContentTab } from '~/pages/settings/applications/tabs/SettingsApplicationDetailContentTab'; import { SettingsApplicationDetailSettingsTab } from '~/pages/settings/applications/tabs/SettingsApplicationDetailSettingsTab'; @@ -102,9 +100,6 @@ export const SettingsApplicationDetails = () => { const screenshots = getScreenshots(); - const settingsCustomTabFrontComponentId = - application?.settingsCustomTabFrontComponentId; - const { upgrade, isUpgrading } = useUpgradeApplication(); const canInstallMarketplaceApps = useHasPermissionFlag( @@ -245,9 +240,6 @@ export const SettingsApplicationDetails = () => { disabled: hasNothingToConfigure, }; })(), - ...(isDefined(settingsCustomTabFrontComponentId) - ? [{ id: 'custom', title: t`Custom`, Icon: IconApps }] - : []), ]; const renderActiveTabContent = () => { @@ -312,16 +304,6 @@ export const SettingsApplicationDetails = () => { return ( ); - case 'custom': - return isDefined(settingsCustomTabFrontComponentId) ? ( - - ) : ( - <> - ); default: return <>; } diff --git a/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationCustomTab.tsx b/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationCustomTab.tsx deleted file mode 100644 index 122b30dce8..0000000000 --- a/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationCustomTab.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { styled } from '@linaria/react'; -import { Suspense, lazy } from 'react'; - -const FrontComponentRenderer = lazy(() => - import('@/front-components/components/FrontComponentRenderer').then( - (module) => ({ default: module.FrontComponentRenderer }), - ), -); - -const StyledContainer = styled.div` - height: 100%; - overflow: auto; - width: 100%; -`; - -type SettingsApplicationCustomTabProps = { - settingsCustomTabFrontComponentId: string; -}; - -export const SettingsApplicationCustomTab = ({ - settingsCustomTabFrontComponentId, -}: SettingsApplicationCustomTabProps) => { - return ( - - - - - - ); -}; diff --git a/packages/twenty-server/src/engine/core-modules/application/application-manifest/application-manifest-migration.service.ts b/packages/twenty-server/src/engine/core-modules/application/application-manifest/application-manifest-migration.service.ts index 599a44f885..ffeb9ea228 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application-manifest/application-manifest-migration.service.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application-manifest/application-manifest-migration.service.ts @@ -257,7 +257,7 @@ export class ApplicationManifestMigrationService { ); if (!dryRun) { - await this.syncDefaultRoleAndSettingsCustomTab({ + await this.syncDefaultRole({ manifest, workspaceId, ownerFlatApplication, @@ -270,7 +270,7 @@ export class ApplicationManifestMigrationService { }; } - private async syncDefaultRoleAndSettingsCustomTab({ + private async syncDefaultRole({ manifest, workspaceId, ownerFlatApplication, @@ -279,13 +279,10 @@ export class ApplicationManifestMigrationService { workspaceId: string; ownerFlatApplication: FlatApplication; }) { - const { - flatRoleMaps: refreshedFlatRoleMaps, - flatFrontComponentMaps: refreshedFlatFrontComponentMaps, - } = await this.workspaceCacheService.getOrRecompute(workspaceId, [ - 'flatRoleMaps', - 'flatFrontComponentMaps', - ]); + const { flatRoleMaps: refreshedFlatRoleMaps } = + await this.workspaceCacheService.getOrRecompute(workspaceId, [ + 'flatRoleMaps', + ]); let defaultRoleId: string | null = null; @@ -310,31 +307,11 @@ export class ApplicationManifestMigrationService { } } - let settingsCustomTabFrontComponentId: string | null = null; - - const settingsCustomTabUniversalIdentifier = - manifest.application.settingsCustomTabFrontComponentUniversalIdentifier; - - if (isDefined(settingsCustomTabUniversalIdentifier)) { - const flatFrontComponent = findFlatEntityByUniversalIdentifier({ - flatEntityMaps: refreshedFlatFrontComponentMaps, - universalIdentifier: settingsCustomTabUniversalIdentifier, + if (isDefined(defaultRoleId)) { + await this.applicationService.update(ownerFlatApplication.id, { + workspaceId, + defaultRoleId, }); - - if (!isDefined(flatFrontComponent)) { - throw new ApplicationException( - `Failed to resolve front component for settingsCustomTabFrontComponentUniversalIdentifier ${settingsCustomTabUniversalIdentifier}`, - ApplicationExceptionCode.ENTITY_NOT_FOUND, - ); - } - - settingsCustomTabFrontComponentId = flatFrontComponent.id; } - - await this.applicationService.update(ownerFlatApplication.id, { - workspaceId, - settingsCustomTabFrontComponentId, - ...(isDefined(defaultRoleId) ? { defaultRoleId } : {}), - }); } } diff --git a/packages/twenty-server/src/engine/core-modules/application/application.entity.ts b/packages/twenty-server/src/engine/core-modules/application/application.entity.ts index c2f52a1923..c4894c03f5 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application.entity.ts @@ -102,6 +102,11 @@ export class ApplicationEntity extends WorkspaceRelatedEntity { @Field(() => RoleDTO, { nullable: true }) defaultRole: RoleDTO | null; + /** + * @deprecated Custom settings tabs are no longer supported. The column is + * kept (not dropped) so existing installations upgrade cleanly, but the + * value is no longer read or synced from manifests. + */ @Column({ nullable: true, type: 'uuid' }) settingsCustomTabFrontComponentId: string | null; diff --git a/packages/twenty-server/src/engine/core-modules/application/dtos/application.dto.ts b/packages/twenty-server/src/engine/core-modules/application/dtos/application.dto.ts index 255efa9fe4..81f187009a 100644 --- a/packages/twenty-server/src/engine/core-modules/application/dtos/application.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/application/dtos/application.dto.ts @@ -86,9 +86,17 @@ export class ApplicationDTO { @Field({ nullable: true }) defaultRoleId?: string; + /** + * @deprecated Custom settings tabs are no longer supported. Kept for + * backward compatibility with existing installations; the value is ignored. + */ @IsOptional() @IsUUID() - @Field(() => UUIDScalarType, { nullable: true }) + @Field(() => UUIDScalarType, { + nullable: true, + deprecationReason: + 'Custom settings tabs are no longer supported. This field is ignored.', + }) settingsCustomTabFrontComponentId?: string; @IsOptional() diff --git a/packages/twenty-shared/src/application/applicationType.ts b/packages/twenty-shared/src/application/applicationType.ts index 3651ed0878..75e9c132b7 100644 --- a/packages/twenty-shared/src/application/applicationType.ts +++ b/packages/twenty-shared/src/application/applicationType.ts @@ -21,6 +21,11 @@ export type ApplicationManifest = SyncableEntityOptions & { issueReportUrl?: string; postInstallLogicFunction?: PostInstallLogicFunctionApplicationManifest; preInstallLogicFunction?: PreInstallLogicFunctionApplicationManifest; + /** + * @deprecated Custom settings tabs are no longer supported. This property is + * kept for backward compatibility with older manifests but is now ignored. + * Use typed `applicationVariables` / `serverVariables` instead. + */ settingsCustomTabFrontComponentUniversalIdentifier?: string; packageJsonChecksum: string | null; yarnLockChecksum: string | null;