removing feature flag IS_MORPH_RELATION_ENABLED (#15783)

releasing the morph feature for all workspaces
This commit is contained in:
Guillim
2025-11-13 12:03:25 +01:00
committed by GitHub
parent cb759aa22e
commit 0389fcf00d
9 changed files with 13 additions and 99 deletions
@@ -1274,7 +1274,6 @@ export enum FeatureFlagKey {
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
IS_MESSAGE_FOLDER_CONTROL_ENABLED = 'IS_MESSAGE_FOLDER_CONTROL_ENABLED',
IS_MORPH_RELATION_ENABLED = 'IS_MORPH_RELATION_ENABLED',
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED',
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
@@ -1215,7 +1215,6 @@ export enum FeatureFlagKey {
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
IS_MESSAGE_FOLDER_CONTROL_ENABLED = 'IS_MESSAGE_FOLDER_CONTROL_ENABLED',
IS_MORPH_RELATION_ENABLED = 'IS_MORPH_RELATION_ENABLED',
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED',
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
@@ -11,18 +11,14 @@ import { useRelationSettingsFormInitialTargetObjectMetadatas } from '@/settings/
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation';
import { IconPicker } from '@/ui/input/components/IconPicker';
import { Select } from '@/ui/input/components/Select';
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { FeatureFlagKey, RelationType } from '~/generated-metadata/graphql';
import { RelationType } from '~/generated-metadata/graphql';
const StyledSelectsContainer = styled.div<{ isMobile: boolean }>`
display: grid;
@@ -77,7 +73,7 @@ export const SettingsDataModelFieldRelationForm = ({
const { t } = useLingui();
const { control } =
useFormContext<SettingsDataModelFieldMorphRelationFormValues>();
const { getIcon } = useIcons();
const { fieldMetadataItem: existingFieldMetadataItem } =
useFieldMetadataItemById(existingFieldMetadataId);
@@ -108,12 +104,6 @@ export const SettingsDataModelFieldRelationForm = ({
);
const isMobile = useIsMobile();
const isMorphRelationEnabled = useIsFeatureEnabled(
FeatureFlagKey.IS_MORPH_RELATION_ENABLED,
);
const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
return (
<StyledContainer>
<StyledSelectsContainer isMobile={isMobile}>
@@ -138,40 +128,17 @@ export const SettingsDataModelFieldRelationForm = ({
name="morphRelationObjectMetadataIds"
control={control}
defaultValue={initialMorphRelationsObjectMetadataIds}
render={({ field: { onChange, value } }) =>
isMorphRelationEnabled ? (
<SettingsMorphRelationMultiSelect
label={t`Object destination`}
dropdownId="object-destination-select"
fullWidth
disabled={disableRelationEdition}
selectedObjectMetadataIds={value}
withSearchInput={true}
onChange={onChange}
/>
) : (
<Select
label={t`Object destination`}
dropdownId="object-destination-select"
fullWidth
disabled={disableRelationEdition}
value={value[0]}
options={activeObjectMetadataItems
.filter(isObjectMetadataAvailableForRelation)
.sort((item1, item2) =>
item1.labelSingular.localeCompare(item2.labelSingular),
)
.map((objectMetadataItem) => ({
label: objectMetadataItem.labelPlural,
value: objectMetadataItem.id,
Icon: getIcon(objectMetadataItem.icon),
}))}
onChange={(value) => {
onChange([value]);
}}
/>
)
}
render={({ field: { onChange, value } }) => (
<SettingsMorphRelationMultiSelect
label={t`Object destination`}
dropdownId="object-destination-select"
fullWidth
disabled={disableRelationEdition}
selectedObjectMetadataIds={value}
withSearchInput={true}
onChange={onChange}
/>
)}
/>
</StyledSelectsContainer>
<StyledInputsLabel>{t`Field on destination`}</StyledInputsLabel>
@@ -39,15 +39,6 @@ export const PUBLIC_FEATURE_FLAGS: PublicFeatureFlag[] = [
imagePath: 'https://twenty.com/images/lab/is-dashboards-enabled.png',
},
},
{
key: FeatureFlagKey.IS_MORPH_RELATION_ENABLED,
metadata: {
label: 'Morph Relations',
description:
'Create polymorphic relationships that can link to multiple object types',
imagePath: 'https://twenty.com/images/lab/is-morph-relation-enabled.png',
},
},
...(process.env.CLOUDFLARE_API_KEY
? [
// {
@@ -7,7 +7,6 @@ export enum FeatureFlagKey {
IS_AI_ENABLED = 'IS_AI_ENABLED',
IS_APPLICATION_ENABLED = 'IS_APPLICATION_ENABLED',
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_MORPH_RELATION_ENABLED = 'IS_MORPH_RELATION_ENABLED',
IS_WORKSPACE_MIGRATION_V2_ENABLED = 'IS_WORKSPACE_MIGRATION_V2_ENABLED',
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
IS_RECORD_PAGE_LAYOUT_ENABLED = 'IS_RECORD_PAGE_LAYOUT_ENABLED',
@@ -652,24 +652,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
{ workspaceId: fieldMetadataInputs[0].workspaceId },
);
const isMorphRelationEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IS_MORPH_RELATION_ENABLED,
workspaceId,
);
const isSomeFieldMetadatInputsMorph = fieldMetadataInputs.some(
(fieldMetadataInput) =>
fieldMetadataInput.type === FieldMetadataType.MORPH_RELATION,
);
if (isSomeFieldMetadatInputsMorph && !isMorphRelationEnabled) {
throw new FieldMetadataException(
'Morph Relation feature is not enabled for this workspace',
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
);
}
const queryRunner = this.coreDataSource.createQueryRunner();
await queryRunner.connect();
@@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { isDefined } from 'class-validator';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { type FlatFieldMetadataTypeValidator } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-type-validator.type';
@@ -44,22 +43,6 @@ export class FlatFieldMetadataTypeValidatorService {
UUID: DEFAULT_NO_VALIDATION,
MORPH_RELATION: async (args) => {
const isMorphRelationEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IS_MORPH_RELATION_ENABLED,
args.workspaceId,
);
if (!isMorphRelationEnabled) {
return [
{
code: FieldMetadataExceptionCode.UNCOVERED_FIELD_METADATA_TYPE_VALIDATION,
message: 'Morph relation feature flag is disabled',
userFriendlyMessage: msg`Morph relation fields are disabled for your workspace`,
},
];
}
return validateMorphOrRelationFlatFieldMetadata(args);
},
MULTI_SELECT: validateEnumSelectFlatFieldMetadata,
@@ -158,7 +158,6 @@ describe('WorkspaceEntityManager', () => {
IS_AI_ENABLED: false,
IS_APPLICATION_ENABLED: false,
IS_IMAP_SMTP_CALDAV_ENABLED: false,
IS_MORPH_RELATION_ENABLED: false,
IS_WORKSPACE_MIGRATION_V2_ENABLED: false,
IS_PAGE_LAYOUT_ENABLED: false,
IS_RECORD_PAGE_LAYOUT_ENABLED: false,
@@ -57,11 +57,6 @@ export const seedFeatureFlags = async ({
workspaceId: workspaceId,
value: true,
},
{
key: FeatureFlagKey.IS_MORPH_RELATION_ENABLED,
workspaceId: workspaceId,
value: true,
},
{
key: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
workspaceId: workspaceId,