Add configuration types for widgets (#14717)

closes https://github.com/twentyhq/core-team-issues/issues/1532
This commit is contained in:
nitin
2025-09-29 17:11:26 +05:30
committed by GitHub
parent 2685f4a5b9
commit ea144c434b
88 changed files with 2829 additions and 1487 deletions
@@ -2,11 +2,4 @@ export const PAGE_LAYOUT_SEEDS = {
SALES_DASHBOARD: 'SALES_DASHBOARD',
CUSTOMER_DASHBOARD: 'CUSTOMER_DASHBOARD',
TEAM_DASHBOARD: 'TEAM_DASHBOARD',
REVENUE_ANALYTICS: 'REVENUE_ANALYTICS',
MARKETING_METRICS: 'MARKETING_METRICS',
SUPPORT_DASHBOARD: 'SUPPORT_DASHBOARD',
PRODUCT_USAGE: 'PRODUCT_USAGE',
OPERATIONS_KPI: 'OPERATIONS_KPI',
FINANCE_OVERVIEW: 'FINANCE_OVERVIEW',
EXECUTIVE_SUMMARY: 'EXECUTIVE_SUMMARY',
};
@@ -5,11 +5,4 @@ export const PAGE_LAYOUT_TAB_SEEDS = {
CUSTOMER_ANALYTICS: 'CUSTOMER_ANALYTICS_TAB',
TEAM_OVERVIEW: 'TEAM_OVERVIEW_TAB',
TEAM_METRICS: 'TEAM_METRICS_TAB',
REVENUE_MAIN: 'REVENUE_MAIN_TAB',
MARKETING_MAIN: 'MARKETING_MAIN_TAB',
SUPPORT_MAIN: 'SUPPORT_MAIN_TAB',
PRODUCT_MAIN: 'PRODUCT_MAIN_TAB',
OPERATIONS_MAIN: 'OPERATIONS_MAIN_TAB',
FINANCE_MAIN: 'FINANCE_MAIN_TAB',
EXECUTIVE_MAIN: 'EXECUTIVE_MAIN_TAB',
};
@@ -1,55 +1,20 @@
export const PAGE_LAYOUT_WIDGET_SEEDS = {
SALES_PIPELINE_NUMBER: 'SALES_PIPELINE_NUMBER_WIDGET',
SALES_CONVERSION_GAUGE: 'SALES_CONVERSION_GAUGE_WIDGET',
SALES_MONTHLY_REVENUE: 'SALES_MONTHLY_REVENUE_WIDGET',
SALES_PIPELINE_VALUE: 'SALES_PIPELINE_VALUE_WIDGET',
SALES_AVERAGE_DEAL_SIZE: 'SALES_AVERAGE_DEAL_SIZE_WIDGET',
SALES_REVENUE_FORECAST: 'SALES_REVENUE_FORECAST_WIDGET',
SALES_DEALS_BY_STAGE: 'SALES_DEALS_BY_STAGE_WIDGET',
SALES_TOP_PERFORMERS: 'SALES_TOP_PERFORMERS_WIDGET',
SALES_FORECAST_LINE: 'SALES_FORECAST_LINE_WIDGET',
SALES_DEAL_DISTRIBUTION: 'SALES_DEAL_DISTRIBUTION_WIDGET',
SALES_OPPORTUNITY_COUNT: 'SALES_OPPORTUNITY_COUNT_WIDGET',
CUSTOMER_TOTAL_COUNT: 'CUSTOMER_TOTAL_COUNT_WIDGET',
CUSTOMER_ACQUISITION_TREND: 'CUSTOMER_ACQUISITION_TREND_WIDGET',
CUSTOMER_SEGMENTS_PIE: 'CUSTOMER_SEGMENTS_PIE_WIDGET',
CUSTOMER_SATISFACTION_GAUGE: 'CUSTOMER_SATISFACTION_GAUGE_WIDGET',
CUSTOMER_RETENTION_RATE: 'CUSTOMER_RETENTION_RATE_WIDGET',
CUSTOMER_LIFETIME_VALUE: 'CUSTOMER_LIFETIME_VALUE_WIDGET',
CUSTOMER_NEW_OVER_TIME: 'CUSTOMER_NEW_OVER_TIME_WIDGET',
CUSTOMER_COMPANIES_BY_SIZE: 'CUSTOMER_COMPANIES_BY_SIZE_WIDGET',
CUSTOMER_ANNUAL_RECURRING_REVENUE: 'CUSTOMER_ANNUAL_RECURRING_REVENUE_WIDGET',
CUSTOMER_REVENUE_DISTRIBUTION: 'CUSTOMER_REVENUE_DISTRIBUTION_WIDGET',
CUSTOMER_AVERAGE_ARR: 'CUSTOMER_AVERAGE_ARR_WIDGET',
TEAM_ACTIVITY_OVERVIEW: 'TEAM_ACTIVITY_OVERVIEW_WIDGET',
TEAM_PRODUCTIVITY_METRICS: 'TEAM_PRODUCTIVITY_METRICS_WIDGET',
TEAM_GOAL_PROGRESS: 'TEAM_GOAL_PROGRESS_WIDGET',
TEAM_MEMBER_LEADERBOARD: 'TEAM_MEMBER_LEADERBOARD_WIDGET',
REVENUE_TOTAL_NUMBER: 'REVENUE_TOTAL_NUMBER_WIDGET',
REVENUE_GROWTH_TREND: 'REVENUE_GROWTH_TREND_WIDGET',
REVENUE_BY_PRODUCT: 'REVENUE_BY_PRODUCT_WIDGET',
REVENUE_BY_REGION: 'REVENUE_BY_REGION_WIDGET',
MARKETING_LEADS_GENERATED: 'MARKETING_LEADS_GENERATED_WIDGET',
MARKETING_CAMPAIGN_ROI: 'MARKETING_CAMPAIGN_ROI_WIDGET',
MARKETING_CHANNEL_PERFORMANCE: 'MARKETING_CHANNEL_PERFORMANCE_WIDGET',
MARKETING_CONVERSION_FUNNEL: 'MARKETING_CONVERSION_FUNNEL_WIDGET',
SUPPORT_TICKET_COUNT: 'SUPPORT_TICKET_COUNT_WIDGET',
SUPPORT_RESOLUTION_TIME: 'SUPPORT_RESOLUTION_TIME_WIDGET',
SUPPORT_SATISFACTION_SCORE: 'SUPPORT_SATISFACTION_SCORE_WIDGET',
SUPPORT_TICKET_BY_PRIORITY: 'SUPPORT_TICKET_BY_PRIORITY_WIDGET',
PRODUCT_ACTIVE_USERS: 'PRODUCT_ACTIVE_USERS_WIDGET',
PRODUCT_FEATURE_ADOPTION: 'PRODUCT_FEATURE_ADOPTION_WIDGET',
PRODUCT_USAGE_HEATMAP: 'PRODUCT_USAGE_HEATMAP_WIDGET',
PRODUCT_USER_ENGAGEMENT: 'PRODUCT_USER_ENGAGEMENT_WIDGET',
OPERATIONS_EFFICIENCY_GAUGE: 'OPERATIONS_EFFICIENCY_GAUGE_WIDGET',
OPERATIONS_COST_BREAKDOWN: 'OPERATIONS_COST_BREAKDOWN_WIDGET',
OPERATIONS_PROCESS_TIME: 'OPERATIONS_PROCESS_TIME_WIDGET',
OPERATIONS_ERROR_RATE: 'OPERATIONS_ERROR_RATE_WIDGET',
FINANCE_CASH_FLOW: 'FINANCE_CASH_FLOW_WIDGET',
FINANCE_EXPENSES_PIE: 'FINANCE_EXPENSES_PIE_WIDGET',
FINANCE_PROFIT_MARGIN: 'FINANCE_PROFIT_MARGIN_WIDGET',
FINANCE_BUDGET_VARIANCE: 'FINANCE_BUDGET_VARIANCE_WIDGET',
EXECUTIVE_KEY_METRICS: 'EXECUTIVE_KEY_METRICS_WIDGET',
EXECUTIVE_COMPANY_HEALTH: 'EXECUTIVE_COMPANY_HEALTH_WIDGET',
EXECUTIVE_QUARTERLY_REVIEW: 'EXECUTIVE_QUARTERLY_REVIEW_WIDGET',
EXECUTIVE_STRATEGIC_GOALS: 'EXECUTIVE_STRATEGIC_GOALS_WIDGET',
TEAM_SIZE: 'TEAM_SIZE_WIDGET',
TEAM_GEOGRAPHIC_DISTRIBUTION: 'TEAM_GEOGRAPHIC_DISTRIBUTION_WIDGET',
TEAM_CONTACT_ROLES: 'TEAM_CONTACT_ROLES_WIDGET',
TEAM_OPEN_TASKS: 'TEAM_OPEN_TASKS_WIDGET',
};
@@ -34,53 +34,4 @@ export const getPageLayoutDataSeeds = (
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.REVENUE_ANALYTICS),
name: 'Revenue Analytics Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.MARKETING_METRICS),
name: 'Marketing Metrics Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.SUPPORT_DASHBOARD),
name: 'Support Dashboard Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.PRODUCT_USAGE),
name: 'Product Usage Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.OPERATIONS_KPI),
name: 'Operations KPI Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.FINANCE_OVERVIEW),
name: 'Finance Overview Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.EXECUTIVE_SUMMARY),
name: 'Executive Summary Layout',
type: PageLayoutType.DASHBOARD,
objectMetadataId: null,
workspaceId,
},
];
@@ -55,80 +55,16 @@ export const getPageLayoutTabDataSeeds = (
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.TEAM_OVERVIEW),
title: 'Overview',
title: 'Team & People',
position: 0,
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.TEAM_DASHBOARD),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.TEAM_METRICS),
title: 'Metrics',
title: 'Tasks & Activity',
position: 1,
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.TEAM_DASHBOARD),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.REVENUE_MAIN),
title: 'Revenue',
position: 0,
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.REVENUE_ANALYTICS,
),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.MARKETING_MAIN),
title: 'Marketing',
position: 0,
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.MARKETING_METRICS,
),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.SUPPORT_MAIN),
title: 'Support',
position: 0,
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.SUPPORT_DASHBOARD,
),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.PRODUCT_MAIN),
title: 'Product',
position: 0,
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.PRODUCT_USAGE),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.OPERATIONS_MAIN),
title: 'Operations',
position: 0,
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.OPERATIONS_KPI),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.FINANCE_MAIN),
title: 'Finance',
position: 0,
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.FINANCE_OVERVIEW,
),
workspaceId,
},
{
id: generateSeedId(workspaceId, PAGE_LAYOUT_TAB_SEEDS.EXECUTIVE_MAIN),
title: 'Executive',
position: 0,
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.EXECUTIVE_SUMMARY,
),
workspaceId,
},
];
@@ -4,9 +4,6 @@ import { seedBillingSubscriptions } from 'src/engine/workspace-manager/dev-seede
import { seedAgents } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-agents.util';
import { seedApiKeys } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-api-keys.util';
import { seedFeatureFlags } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util';
import { seedPageLayouts } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layouts.util';
import { seedPageLayoutTabs } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layout-tabs.util';
import { seedPageLayoutWidgets } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layout-widgets.util';
import { seedUserWorkspaces } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-user-workspaces.util';
import { seedUsers } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-users.util';
import { seedWorkspaces } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
@@ -17,7 +14,6 @@ type SeedCoreSchemaArgs = {
appVersion: string | undefined;
seedBilling?: boolean;
seedFeatureFlags?: boolean;
seedPageLayouts?: boolean;
};
export const seedCoreSchema = async ({
@@ -26,7 +22,6 @@ export const seedCoreSchema = async ({
workspaceId,
seedBilling = true,
seedFeatureFlags: shouldSeedFeatureFlags = true,
seedPageLayouts: shouldSeedPageLayouts = true,
}: SeedCoreSchemaArgs) => {
const schemaName = 'core';
@@ -50,10 +45,4 @@ export const seedCoreSchema = async ({
if (seedBilling) {
await seedBillingSubscriptions(dataSource, schemaName, workspaceId);
}
if (shouldSeedPageLayouts) {
await seedPageLayouts(dataSource, schemaName, workspaceId);
await seedPageLayoutTabs(dataSource, schemaName, workspaceId);
await seedPageLayoutWidgets(dataSource, schemaName, workspaceId);
}
};
@@ -1,20 +1,33 @@
import { type DataSource } from 'typeorm';
import { validateAndTransformWidgetConfiguration } from 'src/engine/core-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { getPageLayoutWidgetDataSeeds } from 'src/engine/workspace-manager/dev-seeder/core/utils/get-page-layout-widget-data-seeds.util';
export const seedPageLayoutWidgets = async (
dataSource: DataSource,
schemaName: string,
workspaceId: string,
objectMetadataItems: ObjectMetadataEntity[],
) => {
const pageLayoutWidgets = getPageLayoutWidgetDataSeeds(workspaceId).map(
(widget) => ({
const pageLayoutWidgets = getPageLayoutWidgetDataSeeds(
workspaceId,
objectMetadataItems,
).map((widget) => {
const validatedConfiguration = widget.configuration
? validateAndTransformWidgetConfiguration(
widget.type,
widget.configuration,
)
: null;
return {
...widget,
workspaceId,
gridPosition: widget.gridPosition,
configuration: widget.configuration,
}),
);
configuration: validatedConfiguration,
};
});
if (pageLayoutWidgets.length > 0) {
await dataSource
@@ -26,13 +26,6 @@ export const DASHBOARD_DATA_SEED_IDS = {
SALES_OVERVIEW: '20202020-9e82-4342-91ef-c9e70f16a675',
CUSTOMER_INSIGHTS: '20202020-d64e-4588-98cc-c56ba821247b',
TEAM_PERFORMANCE: '20202020-b888-4c58-8975-76b4c2035d3a',
REVENUE_ANALYTICS: '20202020-842e-4cd0-a205-a5bfb1efdb1c',
MARKETING_METRICS: '20202020-7b87-4522-9fa8-7f97332c4fa7',
SUPPORT_DASHBOARD: '20202020-5404-49ba-a10a-7941205e577f',
PRODUCT_USAGE: '20202020-fce2-4c4c-b1dd-6db836141c11',
OPERATIONS_KPI: '20202020-c1e4-444c-ab36-4fb42d493eb3',
FINANCE_OVERVIEW: '20202020-b993-4601-945b-996ec668f9e9',
EXECUTIVE_SUMMARY: '20202020-d2e3-4304-9c80-b3db67903974',
};
export const getDashboardDataSeeds = (
@@ -64,89 +57,11 @@ export const getDashboardDataSeeds = (
},
{
id: DASHBOARD_DATA_SEED_IDS.TEAM_PERFORMANCE,
title: 'Team Performance',
title: 'Team & Activity',
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.TEAM_DASHBOARD),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.PHIL,
createdByName: 'Phil Schiller',
position: 2,
},
{
id: DASHBOARD_DATA_SEED_IDS.REVENUE_ANALYTICS,
title: 'Revenue Analytics',
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.REVENUE_ANALYTICS,
),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
createdByName: 'Tim Apple',
position: 3,
},
{
id: DASHBOARD_DATA_SEED_IDS.MARKETING_METRICS,
title: 'Marketing Metrics',
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.MARKETING_METRICS,
),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.JONY,
createdByName: 'Jony Ive',
position: 4,
},
{
id: DASHBOARD_DATA_SEED_IDS.SUPPORT_DASHBOARD,
title: 'Support Dashboard',
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.SUPPORT_DASHBOARD,
),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.PHIL,
createdByName: 'Phil Schiller',
position: 5,
},
{
id: DASHBOARD_DATA_SEED_IDS.PRODUCT_USAGE,
title: 'Product Usage',
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.PRODUCT_USAGE),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
createdByName: 'Tim Apple',
position: 6,
},
{
id: DASHBOARD_DATA_SEED_IDS.OPERATIONS_KPI,
title: 'Operations KPI',
pageLayoutId: generateSeedId(workspaceId, PAGE_LAYOUT_SEEDS.OPERATIONS_KPI),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.JONY,
createdByName: 'Jony Ive',
position: 7,
},
{
id: DASHBOARD_DATA_SEED_IDS.FINANCE_OVERVIEW,
title: 'Finance Overview',
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.FINANCE_OVERVIEW,
),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.PHIL,
createdByName: 'Phil Schiller',
position: 8,
},
{
id: DASHBOARD_DATA_SEED_IDS.EXECUTIVE_SUMMARY,
title: 'Executive Summary',
pageLayoutId: generateSeedId(
workspaceId,
PAGE_LAYOUT_SEEDS.EXECUTIVE_SUMMARY,
),
createdBySource: 'MANUAL',
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
createdByName: 'Tim Apple',
position: 9,
},
];
@@ -6,10 +6,14 @@ import { DataSource } from 'typeorm';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
import { DevSeederPermissionsService } from 'src/engine/workspace-manager/dev-seeder/core/services/dev-seeder-permissions.service';
import { seedCoreSchema } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-core-schema.util';
import { seedPageLayoutTabs } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layout-tabs.util';
import { seedPageLayoutWidgets } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layout-widgets.util';
import { seedPageLayouts } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layouts.util';
import { DevSeederDataService } from 'src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service';
import { DevSeederMetadataService } from 'src/engine/workspace-manager/dev-seeder/metadata/services/dev-seeder-metadata.service';
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
@@ -73,6 +77,22 @@ export class DevSeederService {
await this.devSeederPermissionsService.initPermissions(workspaceId);
await seedPageLayouts(this.coreDataSource, 'core', workspaceId);
await seedPageLayoutTabs(this.coreDataSource, 'core', workspaceId);
const objectMetadataRepository =
this.coreDataSource.getRepository(ObjectMetadataEntity);
const objectMetadataItems = await objectMetadataRepository.find({
where: { workspaceId },
});
await seedPageLayoutWidgets(
this.coreDataSource,
'core',
workspaceId,
objectMetadataItems,
);
await this.devSeederDataService.seed({
schemaName: dataSourceMetadata.schema,
workspaceId,