Hide workflows + remove feature flag from entities (#9768)

From now on workflow entities and views will be seed for every new
workspace. What will prevent user to see those is the feature flag used
in frontend. It will prevent workflow objects to be stored in the recoil
state.

Without feature flag, workflows will:
- remain invisible in metadata
- not be accessible through views or show page
- remain invisible on side menu
This commit is contained in:
Thomas Trompette
2025-01-21 16:11:57 +01:00
committed by GitHub
parent e82d4d9f8e
commit 2e9a77f702
12 changed files with 22 additions and 95 deletions

View File

@ -2,10 +2,16 @@ import { FIND_MANY_OBJECT_METADATA_ITEMS } from '@/object-metadata/graphql/queri
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
import { isAppWaitingForFreshObjectMetadataState } from '@/object-metadata/states/isAppWaitingForFreshObjectMetadataState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isWorkflowSubObjectMetadata } from '@/object-metadata/utils/isWorkflowSubObjectMetadata';
import { mapPaginatedObjectMetadataItemsToObjectMetadataItems } from '@/object-metadata/utils/mapPaginatedObjectMetadataItemsToObjectMetadataItems';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRecoilCallback } from 'recoil';
import { ObjectMetadataItemsQuery } from '~/generated-metadata/graphql';
import {
FeatureFlagKey,
ObjectMetadataItemsQuery,
} from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
type FetchPolicy = 'network-only' | 'cache-first';
@ -14,6 +20,9 @@ export const useRefreshObjectMetadataItems = (
fetchPolicy: FetchPolicy = 'cache-first',
) => {
const client = useApolloMetadataClient();
const isWorkflowEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsWorkflowEnabled,
);
const refreshObjectMetadataItems = async () => {
const result = await client.query<ObjectMetadataItemsQuery>({
@ -27,7 +36,15 @@ export const useRefreshObjectMetadataItems = (
pagedObjectMetadataItems: result.data,
});
replaceObjectMetadataItemIfDifferent(objectMetadataItems);
const filteredObjectMetadataItems = objectMetadataItems.filter((object) => {
return (
isWorkflowEnabled ||
(object.nameSingular !== CoreObjectNameSingular.Workflow &&
!isWorkflowSubObjectMetadata(object.nameSingular))
);
});
replaceObjectMetadataItemIfDifferent(filteredObjectMetadataItems);
};
const replaceObjectMetadataItemIfDifferent = useRecoilCallback(

View File

@ -32,7 +32,6 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service';
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
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 { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
@ -183,12 +182,6 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
dataSourceMetadata.workspaceId,
);
const isWorkflowEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsWorkflowEnabled,
dataSourceMetadata.workspaceId,
);
await seedCompanies(entityManager, dataSourceMetadata.schema);
await seedPeople(entityManager, dataSourceMetadata.schema);
await seedOpportunity(entityManager, dataSourceMetadata.schema);
@ -229,7 +222,6 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
entityManager,
dataSourceMetadata.schema,
objectMetadataStandardIdToIdMap,
isWorkflowEnabled,
);
const devViewDefinitionsWithId = await createWorkspaceViews(

View File

@ -13,7 +13,6 @@ export const seedWorkspaceWithDemoData = async (
workspaceDataSource: DataSource,
schemaName: string,
objectMetadata: ObjectMetadataEntity[],
isWorkflowEnabled: boolean,
) => {
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
acc[object.standardId ?? ''] = {
@ -38,7 +37,6 @@ export const seedWorkspaceWithDemoData = async (
entityManager,
schemaName,
objectMetadataMap,
isWorkflowEnabled,
);
await seedWorkspaceFavorites(

View File

@ -18,7 +18,6 @@ export const seedViewWithDemoData = async (
entityManager: EntityManager,
schemaName: string,
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
isWorkflowEnabled: boolean,
) => {
const viewDefinitions = [
seedCompaniesAllView(objectMetadataStandardIdToIdMap),
@ -28,13 +27,9 @@ export const seedViewWithDemoData = async (
notesAllView(objectMetadataStandardIdToIdMap),
tasksAllView(objectMetadataStandardIdToIdMap),
tasksByStatusView(objectMetadataStandardIdToIdMap),
...(isWorkflowEnabled
? [
workflowsAllView(objectMetadataStandardIdToIdMap),
workflowVersionsAllView(objectMetadataStandardIdToIdMap),
workflowRunsAllView(objectMetadataStandardIdToIdMap),
]
: []),
workflowsAllView(objectMetadataStandardIdToIdMap),
workflowVersionsAllView(objectMetadataStandardIdToIdMap),
workflowRunsAllView(objectMetadataStandardIdToIdMap),
];
return createWorkspaceViews(entityManager, schemaName, viewDefinitions);

View File

@ -11,7 +11,6 @@ export const standardObjectsPrefillData = async (
workspaceDataSource: DataSource,
schemaName: string,
objectMetadata: ObjectMetadataEntity[],
isWorkflowEnabled: boolean,
) => {
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
if (!object.standardId) {
@ -41,7 +40,6 @@ export const standardObjectsPrefillData = async (
entityManager,
schemaName,
objectMetadataMap,
isWorkflowEnabled,
);
await seedWorkspaceFavorites(

View File

@ -1,6 +1,5 @@
import { Injectable } from '@nestjs/common';
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 { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
@ -104,16 +103,10 @@ export class WorkspaceManagerService {
const createdObjectMetadata =
await this.objectMetadataService.findManyWithinWorkspace(workspaceId);
const isWorkflowEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsWorkflowEnabled,
workspaceId,
);
await standardObjectsPrefillData(
workspaceDataSource,
dataSourceMetadata.schema,
createdObjectMetadata,
isWorkflowEnabled,
);
}
@ -140,16 +133,10 @@ export class WorkspaceManagerService {
const createdObjectMetadata =
await this.objectMetadataService.findManyWithinWorkspace(workspaceId);
const isWorkflowEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsWorkflowEnabled,
workspaceId,
);
await seedWorkspaceWithDemoData(
workspaceDataSource,
dataSourceMetadata.schema,
createdObjectMetadata,
isWorkflowEnabled,
);
await this.seederService.seedCustomObjects(

View File

@ -2,14 +2,12 @@ import { FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
@ -137,16 +135,10 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'favorites',
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsNullable()
workflow: Relation<WorkflowWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflow')
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
workflowId: string;
@WorkspaceRelation({
@ -158,16 +150,10 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
inverseSideFieldKey: 'favorites',
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsNullable()
workflowVersion: Relation<WorkflowVersionWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflowVersion')
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
workflowVersionId: string;
@WorkspaceRelation({
@ -179,16 +165,10 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
inverseSideFieldKey: 'favorites',
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsNullable()
workflowRun: Relation<WorkflowRunWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflowRun')
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
workflowRunId: string;
@WorkspaceRelation({

View File

@ -2,14 +2,12 @@ import { FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
@ -198,16 +196,10 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsNullable()
workflow: Relation<WorkflowWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflow')
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
workflowId: string | null;
@WorkspaceRelation({
@ -219,16 +211,10 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsNullable()
workflowVersion: Relation<WorkflowVersionWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflowVersion')
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
workflowVersionId: string | null;
@WorkspaceRelation({
@ -240,16 +226,10 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsNullable()
workflowRun: Relation<WorkflowRunWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflowRun')
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
workflowRunId: string | null;
@WorkspaceDynamicRelation({

View File

@ -2,12 +2,10 @@ import { FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
@ -27,9 +25,6 @@ import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-ob
labelIdentifierStandardId:
WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS.eventName,
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
@WorkspaceIsSystem()
export class WorkflowEventListenerWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({

View File

@ -2,7 +2,6 @@ import { FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import {
ActorMetadata,
FieldActorSource,
@ -14,7 +13,6 @@ import {
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
@ -59,9 +57,6 @@ export type WorkflowRunOutput = {
labelIdentifierStandardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.name,
icon: STANDARD_OBJECT_ICONS.workflowRun,
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.name,

View File

@ -2,7 +2,6 @@ import { FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FieldMetadataComplexOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
import {
RelationMetadataType,
@ -11,7 +10,6 @@ import {
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
@ -69,9 +67,6 @@ const WorkflowVersionStatusOptions: FieldMetadataComplexOption[] = [
icon: STANDARD_OBJECT_ICONS.workflowVersion,
labelIdentifierStandardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.name,
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
export class WorkflowVersionWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.name,

View File

@ -2,7 +2,6 @@ import { FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import {
ActorMetadata,
FieldActorSource,
@ -15,7 +14,6 @@ import {
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
@ -65,9 +63,6 @@ const WorkflowStatusOptions: FieldMetadataComplexOption[] = [
shortcut: 'W',
labelIdentifierStandardId: WORKFLOW_STANDARD_FIELD_IDS.name,
})
@WorkspaceGate({
featureFlag: FeatureFlagKey.IsWorkflowEnabled,
})
export class WorkflowWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.name,