diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts index d243cbd901..a37a10ca25 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts @@ -3,6 +3,7 @@ import { type ViewFilterOperand as SharedViewFilterOperand } from 'twenty-shared import { type DataSource, type QueryRunner } from 'typeorm'; import { v4 } from 'uuid'; +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; @@ -13,6 +14,7 @@ import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { companiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view'; +import { dashboardsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view'; import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view'; import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view'; import { opportunitiesTableByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-table-by-stage.view'; @@ -30,6 +32,7 @@ export const prefillCoreViews = async ( dataSource: DataSource, workspaceId: string, objectMetadataItems: ObjectMetadataEntity[], + featureFlags?: Record, ): Promise => { const views = [ companiesAllView(objectMetadataItems, true), @@ -45,6 +48,10 @@ export const prefillCoreViews = async ( workflowRunsAllView(objectMetadataItems, true), ]; + if (featureFlags?.[FeatureFlagKey.IS_PAGE_LAYOUT_ENABLED]) { + views.push(dashboardsAllView(objectMetadataItems, true)); + } + const queryRunner = dataSource.createQueryRunner(); await queryRunner.connect(); diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-views.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-views.ts index 453c8c2354..8e556cba54 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-views.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-views.ts @@ -1,10 +1,12 @@ import { v4 } from 'uuid'; +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { companiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view'; import { customAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/custom-all.view'; +import { dashboardsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view'; import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view'; import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view'; import { opportunitiesByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view'; @@ -20,6 +22,7 @@ export const prefillViews = async ( entityManager: WorkspaceEntityManager, schemaName: string, objectMetadataItems: ObjectMetadataEntity[], + featureFlags?: Record, ) => { const customObjectMetadataItems = objectMetadataItems.filter( (item) => item.isCustom, @@ -44,6 +47,10 @@ export const prefillViews = async ( ...customViews, ]; + if (featureFlags?.[FeatureFlagKey.IS_PAGE_LAYOUT_ENABLED]) { + views.push(dashboardsAllView(objectMetadataItems)); + } + return createWorkspaceViews(entityManager, schemaName, views); }; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts index 312f595931..e2ffd39c47 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts @@ -13,6 +13,7 @@ export const standardObjectsPrefillData = async ( mainDataSource: DataSource, schemaName: string, objectMetadataItems: ObjectMetadataEntity[], + featureFlags?: Record, ) => { mainDataSource.transaction(async (entityManager: WorkspaceEntityManager) => { await prefillCompanies(entityManager, schemaName); @@ -25,6 +26,7 @@ export const standardObjectsPrefillData = async ( entityManager, schemaName, objectMetadataItems, + featureFlags, ); await prefillWorkspaceFavorites( diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts new file mode 100644 index 0000000000..0f595bf175 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts @@ -0,0 +1,63 @@ +import { msg } from '@lingui/core/macro'; + +import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { + BASE_OBJECT_STANDARD_FIELD_IDS, + DASHBOARD_STANDARD_FIELD_IDS, +} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; + +export const dashboardsAllView = ( + objectMetadataItems: ObjectMetadataEntity[], + useCoreNaming = false, +) => { + const dashboardObjectMetadata = objectMetadataItems.find( + (object) => object.standardId === STANDARD_OBJECT_IDS.dashboard, + ); + + if (!dashboardObjectMetadata) { + throw new Error('Dashboard object metadata not found'); + } + + return { + name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Dashboards', + objectMetadataId: dashboardObjectMetadata.id ?? '', + type: 'table', + key: 'INDEX', + position: 0, + icon: 'IconLayoutDashboard', + kanbanFieldMetadataId: '', + filters: [], + fields: [ + { + fieldMetadataId: + dashboardObjectMetadata.fields.find( + (field) => field.standardId === DASHBOARD_STANDARD_FIELD_IDS.title, + )?.id ?? '', + position: 0, + isVisible: true, + size: 200, + }, + { + fieldMetadataId: + dashboardObjectMetadata.fields.find( + (field) => + field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt, + )?.id ?? '', + position: 1, + isVisible: true, + size: 150, + }, + { + fieldMetadataId: + dashboardObjectMetadata.fields.find( + (field) => + field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt, + )?.id ?? '', + position: 2, + isVisible: true, + size: 150, + }, + ], + }; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts index 0ce58ec0b6..932ff3f15c 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts @@ -137,6 +137,7 @@ export class WorkspaceManagerService { mainDataSource, dataSourceMetadata.schema, createdObjectMetadata, + featureFlags, ); if (featureFlags[FeatureFlagKey.IS_CORE_VIEW_SYNCING_ENABLED]) { @@ -146,6 +147,7 @@ export class WorkspaceManagerService { mainDataSource, workspaceId, createdObjectMetadata, + featureFlags, ); } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts index d3ab536299..8d18e3ef8f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts @@ -536,6 +536,11 @@ export const CUSTOM_OBJECT_STANDARD_FIELD_IDS = { searchVector: '70e56537-18ef-4811-b1c7-0a444006b815', } as const; +export const DASHBOARD_STANDARD_FIELD_IDS = { + title: '20202020-20ee-4091-95dc-44b57eda3a89', + pageLayoutId: '20202020-bb53-4648-aa36-1d9d54e6f7f2', +} as const; + export const STANDARD_OBJECT_FIELD_IDS = { activityTarget: ACTIVITY_TARGET_STANDARD_FIELD_IDS, activity: ACTIVITY_STANDARD_FIELD_IDS, @@ -550,6 +555,7 @@ export const STANDARD_OBJECT_FIELD_IDS = { comment: COMMENT_STANDARD_FIELD_IDS, company: COMPANY_STANDARD_FIELD_IDS, connectedAccount: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS, + dashboard: DASHBOARD_STANDARD_FIELD_IDS, favorite: FAVORITE_STANDARD_FIELD_IDS, auditLog: AUDIT_LOGS_STANDARD_FIELD_IDS, messageChannelMessageAssociation: diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts index a214c7dc8c..3ceac12d5b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts @@ -12,6 +12,7 @@ export const STANDARD_OBJECT_ICONS = { comment: 'IconMessageCircle', company: 'IconBuildingSkyscraper', connectedAccount: 'IconAt', + dashboard: 'IconLayoutDashboard', favorite: 'IconHeart', auditLog: 'IconTimelineEvent', messageChannelMessageAssociation: 'IconMessage', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts index 59cbbd689f..9b1ed07242 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts @@ -19,6 +19,7 @@ export const STANDARD_OBJECT_IDS = { comment: '20202020-435f-4de9-89b5-97e32233bf5f', company: '20202020-b374-4779-a561-80086cb2e17f', connectedAccount: '20202020-977e-46b2-890b-c3002ddfd5c5', + dashboard: '20202020-3840-4b6d-9425-0c5188b05ca8', favorite: '20202020-ab56-4e05-92a3-e2414a499860', favoriteFolder: '20202020-7cf8-401f-8211-a9587d27fd2d', auditLog: '20202020-0566-476a-b4c4-a0f9781bd80a', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts index 80a080fb18..2dc2b51c77 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts @@ -6,6 +6,7 @@ import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/co import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; +import { DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity'; import { FavoriteFolderWorkspaceEntity } from 'src/modules/favorite-folder/standard-objects/favorite-folder.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @@ -43,6 +44,7 @@ export const standardObjectMetadataDefinitions = [ CalendarEventParticipantWorkspaceEntity, CompanyWorkspaceEntity, ConnectedAccountWorkspaceEntity, + DashboardWorkspaceEntity, FavoriteWorkspaceEntity, FavoriteFolderWorkspaceEntity, TimelineActivityWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/dashboard/standard-objects/dashboard.workspace-entity.ts b/packages/twenty-server/src/modules/dashboard/standard-objects/dashboard.workspace-entity.ts new file mode 100644 index 0000000000..446622d0ef --- /dev/null +++ b/packages/twenty-server/src/modules/dashboard/standard-objects/dashboard.workspace-entity.ts @@ -0,0 +1,43 @@ +import { msg } from '@lingui/core/macro'; +import { FieldMetadataType } from 'twenty-shared/types'; + +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +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 { DASHBOARD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; + +@WorkspaceEntity({ + standardId: STANDARD_OBJECT_IDS.dashboard, + namePlural: 'dashboards', + labelSingular: msg`Dashboard`, + labelPlural: msg`Dashboards`, + description: msg`A dashboard`, + icon: STANDARD_OBJECT_ICONS.dashboard, + labelIdentifierStandardId: DASHBOARD_STANDARD_FIELD_IDS.title, +}) +@WorkspaceGate({ + featureFlag: FeatureFlagKey.IS_PAGE_LAYOUT_ENABLED, +}) +export class DashboardWorkspaceEntity extends BaseWorkspaceEntity { + @WorkspaceField({ + standardId: DASHBOARD_STANDARD_FIELD_IDS.title, + type: FieldMetadataType.TEXT, + label: msg`Title`, + description: msg`Dashboard title`, + icon: 'IconNotes', + }) + title: string; + + @WorkspaceField({ + standardId: DASHBOARD_STANDARD_FIELD_IDS.pageLayoutId, + type: FieldMetadataType.UUID, + label: msg`Page Layout ID`, + description: msg`Dashboard page layout`, + icon: 'IconLayout', + }) + pageLayoutId: string; +}