chore: remove IS_DASHBOARD_V2_ENABLED feature flag (#19079)
## Summary - Remove the `IS_DASHBOARD_V2_ENABLED` feature flag from the codebase - Dashboard V2 features (gauge charts, line charts, pie charts) are now always enabled - Remove the validator gate that blocked gauge chart creation/update without the flag - Clean up all related code: seed data, dev-seeder service, widget seeds, and test mocks
This commit is contained in:
@@ -1730,7 +1730,6 @@ enum FeatureFlagKey {
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED
|
||||
IS_PUBLIC_DOMAIN_ENABLED
|
||||
IS_EMAILING_DOMAIN_ENABLED
|
||||
IS_DASHBOARD_V2_ENABLED
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED
|
||||
IS_JUNCTION_RELATIONS_ENABLED
|
||||
IS_COMMAND_MENU_ITEM_ENABLED
|
||||
|
||||
@@ -1427,7 +1427,7 @@ export interface PublicFeatureFlag {
|
||||
__typename: 'PublicFeatureFlag'
|
||||
}
|
||||
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_APPLICATION_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_DASHBOARD_V2_ENABLED' | 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_ENABLED' | 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_APPLICATION_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_ENABLED' | 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
|
||||
|
||||
export interface ClientConfig {
|
||||
appVersion?: Scalars['String']
|
||||
@@ -9146,7 +9146,6 @@ export const enumFeatureFlagKey = {
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED: 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' as const,
|
||||
IS_PUBLIC_DOMAIN_ENABLED: 'IS_PUBLIC_DOMAIN_ENABLED' as const,
|
||||
IS_EMAILING_DOMAIN_ENABLED: 'IS_EMAILING_DOMAIN_ENABLED' as const,
|
||||
IS_DASHBOARD_V2_ENABLED: 'IS_DASHBOARD_V2_ENABLED' as const,
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED' as const,
|
||||
IS_JUNCTION_RELATIONS_ENABLED: 'IS_JUNCTION_RELATIONS_ENABLED' as const,
|
||||
IS_COMMAND_MENU_ITEM_ENABLED: 'IS_COMMAND_MENU_ITEM_ENABLED' as const,
|
||||
|
||||
@@ -1705,7 +1705,6 @@ export enum FeatureFlagKey {
|
||||
IS_APPLICATION_ENABLED = 'IS_APPLICATION_ENABLED',
|
||||
IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED',
|
||||
IS_CONNECTED_ACCOUNT_MIGRATED = 'IS_CONNECTED_ACCOUNT_MIGRATED',
|
||||
IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED',
|
||||
IS_DATASOURCE_MIGRATED = 'IS_DATASOURCE_MIGRATED',
|
||||
IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED = 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED',
|
||||
IS_DIRECT_GRAPHQL_EXECUTION_ENABLED = 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED',
|
||||
|
||||
+15
-25
@@ -1,7 +1,5 @@
|
||||
import { GRAPH_TYPE_INFORMATION } from '@/side-panel/pages/page-layout/constants/GraphTypeInformation';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
|
||||
import { GraphType } from '@/side-panel/pages/page-layout/types/GraphType';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -32,31 +30,23 @@ export const ChartTypeSelectionSection = ({
|
||||
currentGraphType,
|
||||
setCurrentGraphType,
|
||||
}: ChartTypeSelectionSectionProps) => {
|
||||
const isDashboardV2Enabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_DASHBOARD_V2_ENABLED,
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledChartTypeSelectionContainer>
|
||||
{graphTypeOptions
|
||||
.filter(
|
||||
(graphType) => isDashboardV2Enabled || graphType !== GraphType.GAUGE,
|
||||
)
|
||||
.map((graphType) => {
|
||||
return (
|
||||
<MenuPicker
|
||||
id={graphType}
|
||||
selected={currentGraphType === graphType}
|
||||
key={graphType}
|
||||
icon={GRAPH_TYPE_INFORMATION[graphType].icon}
|
||||
onClick={() => {
|
||||
setCurrentGraphType(graphType);
|
||||
}}
|
||||
showLabel
|
||||
tooltipContent={t(GRAPH_TYPE_INFORMATION[graphType].label)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{graphTypeOptions.map((graphType) => {
|
||||
return (
|
||||
<MenuPicker
|
||||
id={graphType}
|
||||
selected={currentGraphType === graphType}
|
||||
key={graphType}
|
||||
icon={GRAPH_TYPE_INFORMATION[graphType].icon}
|
||||
onClick={() => {
|
||||
setCurrentGraphType(graphType);
|
||||
}}
|
||||
showLabel
|
||||
tooltipContent={t(GRAPH_TYPE_INFORMATION[graphType].label)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</StyledChartTypeSelectionContainer>
|
||||
);
|
||||
};
|
||||
|
||||
-2
@@ -238,7 +238,6 @@ describe('WorkspaceEntityManager', () => {
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED: false,
|
||||
IS_PUBLIC_DOMAIN_ENABLED: false,
|
||||
IS_EMAILING_DOMAIN_ENABLED: false,
|
||||
IS_DASHBOARD_V2_ENABLED: false,
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false,
|
||||
IS_JUNCTION_RELATIONS_ENABLED: false,
|
||||
IS_COMMAND_MENU_ITEM_ENABLED: false,
|
||||
@@ -277,7 +276,6 @@ describe('WorkspaceEntityManager', () => {
|
||||
IS_APPLICATION_ENABLED: false,
|
||||
IS_PUBLIC_DOMAIN_ENABLED: false,
|
||||
IS_EMAILING_DOMAIN_ENABLED: false,
|
||||
IS_DASHBOARD_V2_ENABLED: false,
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false,
|
||||
},
|
||||
permissionsPerRoleId: {},
|
||||
|
||||
+4
-4
@@ -29,7 +29,6 @@ const getFieldId = (
|
||||
export const getPageLayoutWidgetDataSeeds = (
|
||||
workspaceId: string,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
isDashboardV2Enabled: boolean,
|
||||
): SeederFlatPageLayoutWidget[] => {
|
||||
const opportunityObject = objectMetadataItems.find(
|
||||
(obj) =>
|
||||
@@ -524,9 +523,10 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
} satisfies SeederFlatPageLayoutWidget,
|
||||
].filter(isDefined);
|
||||
|
||||
const v2Widgets = isDashboardV2Enabled
|
||||
? getPageLayoutWidgetDataSeedsV2(workspaceId, objectMetadataItems)
|
||||
: [];
|
||||
const v2Widgets = getPageLayoutWidgetDataSeedsV2(
|
||||
workspaceId,
|
||||
objectMetadataItems,
|
||||
);
|
||||
|
||||
return [...v1Widgets, ...v2Widgets];
|
||||
};
|
||||
|
||||
-5
@@ -45,11 +45,6 @@ export const seedFeatureFlags = async ({
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_DASHBOARD_V2_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
|
||||
-3
@@ -11,20 +11,17 @@ export const seedPageLayoutWidgets = async ({
|
||||
schemaName,
|
||||
workspaceId,
|
||||
objectMetadataItems,
|
||||
isDashboardV2Enabled,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
dataSource: DataSource;
|
||||
schemaName: string;
|
||||
workspaceId: string;
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
isDashboardV2Enabled: boolean;
|
||||
workspaceCustomApplicationId: string;
|
||||
}) => {
|
||||
const widgetSeeds = getPageLayoutWidgetDataSeeds(
|
||||
workspaceId,
|
||||
objectMetadataItems,
|
||||
isDashboardV2Enabled,
|
||||
);
|
||||
|
||||
const pageLayoutWidgets = widgetSeeds.map((widget) => {
|
||||
|
||||
-5
@@ -2,7 +2,6 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectDataSource } from '@nestjs/typeorm';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { FeatureFlagKey } from 'twenty-shared/types';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { ApplicationRegistrationService } from 'src/engine/core-modules/application/application-registration/application-registration.service';
|
||||
@@ -146,15 +145,11 @@ export class DevSeederService {
|
||||
relations: { fields: true },
|
||||
});
|
||||
|
||||
const isDashboardV2Enabled =
|
||||
featureFlagsMap[FeatureFlagKey.IS_DASHBOARD_V2_ENABLED] ?? false;
|
||||
|
||||
await seedPageLayoutWidgets({
|
||||
dataSource: this.coreDataSource,
|
||||
schemaName: 'core',
|
||||
workspaceId,
|
||||
objectMetadataItems,
|
||||
isDashboardV2Enabled,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
|
||||
-68
@@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common';
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import {
|
||||
FeatureFlagKey,
|
||||
PageLayoutTabLayoutMode,
|
||||
PageLayoutWidgetPosition,
|
||||
type GridPosition,
|
||||
@@ -13,8 +12,6 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { FlatPageLayoutWidgetTypeValidatorService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/flat-page-layout-widget-type-validator.service';
|
||||
import { PageLayoutTabExceptionCode } from 'src/engine/metadata-modules/page-layout-tab/exceptions/page-layout-tab.exception';
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { PageLayoutWidgetExceptionCode } from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
|
||||
import { validatePageLayoutWidgetGridPosition } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-page-layout-widget-grid-position.util';
|
||||
import { validatePageLayoutWidgetVerticalListPosition } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-page-layout-widget-vertical-list-position.util';
|
||||
@@ -44,9 +41,6 @@ export class FlatPageLayoutWidgetValidatorService {
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget
|
||||
>): Promise<FailedFlatEntityValidation<'pageLayoutWidget', 'update'>> {
|
||||
const isDashboardV2Enabled =
|
||||
featureFlagsMap[FeatureFlagKey.IS_DASHBOARD_V2_ENABLED] ?? false;
|
||||
|
||||
const existingFlatPageLayoutWidget = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier,
|
||||
flatEntityMaps:
|
||||
@@ -104,15 +98,6 @@ export class FlatPageLayoutWidgetValidatorService {
|
||||
|
||||
validationResult.errors.push(...positionErrors);
|
||||
|
||||
const featureFlagErrors = this.validateFeatureFlags({
|
||||
type: updatedFlatPageLayoutWidget.type,
|
||||
configuration: updatedFlatPageLayoutWidget.universalConfiguration,
|
||||
widgetTitle: updatedFlatPageLayoutWidget.title,
|
||||
isDashboardV2Enabled,
|
||||
});
|
||||
|
||||
validationResult.errors.push(...featureFlagErrors);
|
||||
|
||||
const typeSpecificityErrors =
|
||||
this.flatPageLayoutWidgetTypeValidatorService.validateFlatPageLayoutWidgetTypeSpecificitiesForUpdate(
|
||||
{
|
||||
@@ -176,9 +161,6 @@ export class FlatPageLayoutWidgetValidatorService {
|
||||
}: UniversalFlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget
|
||||
>): Promise<FailedFlatEntityValidation<'pageLayoutWidget', 'create'>> {
|
||||
const isDashboardV2Enabled =
|
||||
featureFlagsMap[FeatureFlagKey.IS_DASHBOARD_V2_ENABLED] ?? false;
|
||||
|
||||
const validationResult = getEmptyFlatEntityValidationError({
|
||||
flatEntityMinimalInformation: {
|
||||
universalIdentifier: flatPageLayoutWidgetToValidate.universalIdentifier,
|
||||
@@ -236,15 +218,6 @@ export class FlatPageLayoutWidgetValidatorService {
|
||||
|
||||
validationResult.errors.push(...positionErrors);
|
||||
|
||||
const featureFlagErrors = this.validateFeatureFlags({
|
||||
type: flatPageLayoutWidgetToValidate.type,
|
||||
configuration: flatPageLayoutWidgetToValidate.universalConfiguration,
|
||||
widgetTitle: flatPageLayoutWidgetToValidate.title,
|
||||
isDashboardV2Enabled,
|
||||
});
|
||||
|
||||
validationResult.errors.push(...featureFlagErrors);
|
||||
|
||||
const typeSpecificityErrors =
|
||||
this.flatPageLayoutWidgetTypeValidatorService.validateFlatPageLayoutWidgetTypeSpecificitiesForCreation(
|
||||
{
|
||||
@@ -282,47 +255,6 @@ export class FlatPageLayoutWidgetValidatorService {
|
||||
return validateWidgetGridPosition(gridPosition, widgetTitle);
|
||||
}
|
||||
|
||||
private validateFeatureFlags({
|
||||
type,
|
||||
configuration,
|
||||
widgetTitle,
|
||||
isDashboardV2Enabled,
|
||||
}: {
|
||||
type: WidgetType | undefined;
|
||||
configuration: { configurationType?: unknown } | null | undefined;
|
||||
widgetTitle: string;
|
||||
isDashboardV2Enabled: boolean;
|
||||
}): FlatEntityValidationError[] {
|
||||
if (!isDefined(type) || !isDefined(configuration)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (type !== WidgetType.GRAPH) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const graphConfiguration = configuration as {
|
||||
configurationType?: GraphType;
|
||||
};
|
||||
|
||||
if (
|
||||
graphConfiguration.configurationType === GraphType.GAUGE_CHART &&
|
||||
!isDashboardV2Enabled
|
||||
) {
|
||||
const chartType = graphConfiguration.configurationType;
|
||||
|
||||
return [
|
||||
{
|
||||
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
||||
message: t`Invalid configuration for widget "${widgetTitle}": Chart type ${chartType} requires IS_DASHBOARD_V2_ENABLED feature flag`,
|
||||
userFriendlyMessage: msg`This chart type requires the Dashboard V2 feature to be enabled`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private validatePosition({
|
||||
position,
|
||||
pageLayoutTab,
|
||||
|
||||
@@ -7,7 +7,6 @@ export enum FeatureFlagKey {
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED',
|
||||
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
|
||||
IS_EMAILING_DOMAIN_ENABLED = 'IS_EMAILING_DOMAIN_ENABLED',
|
||||
IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED',
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED',
|
||||
IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED',
|
||||
IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED',
|
||||
|
||||
Reference in New Issue
Block a user