diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index bf7849817f..04c0d6de9c 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -4550,6 +4550,7 @@ export enum WidgetType { GRAPH = 'GRAPH', IFRAME = 'IFRAME', NOTES = 'NOTES', + RICH_TEXT = 'RICH_TEXT', TASKS = 'TASKS', TIMELINE = 'TIMELINE', VIEW = 'VIEW' diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index e4c895b8be..e08d1b78c6 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -4378,6 +4378,7 @@ export enum WidgetType { GRAPH = 'GRAPH', IFRAME = 'IFRAME', NOTES = 'NOTES', + RICH_TEXT = 'RICH_TEXT', TASKS = 'TASKS', TIMELINE = 'TIMELINE', VIEW = 'VIEW' diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx index 2ac54ffb4e..ce6309c12a 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx @@ -3,7 +3,7 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; -import { DEFAULT_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPageLayoutId'; +import { DEFAULT_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultRecordPageLayoutId'; import { useResetDraftPageLayoutToPersistedPageLayout } from '@/page-layout/hooks/useResetDraftPageLayoutToPersistedPageLayout'; import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode'; import { useRecoilValue } from 'recoil'; @@ -15,11 +15,9 @@ export const CancelRecordPageLayoutSingleRecordAction = () => { const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); - // For COMPANY objects, use DEFAULT_PAGE_LAYOUT_ID - // For other objects, use the record's pageLayoutId (when backend is ready) const pageLayoutId = objectMetadataItem.nameSingular === CoreObjectNameSingular.Company - ? DEFAULT_PAGE_LAYOUT_ID + ? DEFAULT_RECORD_PAGE_LAYOUT_ID : selectedRecord?.pageLayoutId; const { setIsPageLayoutInEditMode } = diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx index 74e37c064c..6405db5896 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx @@ -3,7 +3,7 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; -import { DEFAULT_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPageLayoutId'; +import { DEFAULT_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultRecordPageLayoutId'; import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode'; import { useRecoilValue } from 'recoil'; @@ -14,11 +14,9 @@ export const EditRecordPageLayoutSingleRecordAction = () => { const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); - // For COMPANY objects, use DEFAULT_PAGE_LAYOUT_ID - // For other objects, use the record's pageLayoutId (when backend is ready) const pageLayoutId = objectMetadataItem.nameSingular === CoreObjectNameSingular.Company - ? DEFAULT_PAGE_LAYOUT_ID + ? DEFAULT_RECORD_PAGE_LAYOUT_ID : selectedRecord?.pageLayoutId; const { setIsPageLayoutInEditMode } = diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx index 54571245f3..66a5b9288e 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx @@ -3,7 +3,7 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; -import { DEFAULT_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPageLayoutId'; +import { DEFAULT_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultRecordPageLayoutId'; import { useSavePageLayout } from '@/page-layout/hooks/useSavePageLayout'; import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode'; import { useRecoilValue } from 'recoil'; @@ -15,11 +15,9 @@ export const SaveRecordPageLayoutSingleRecordAction = () => { const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); - // For COMPANY objects, use DEFAULT_PAGE_LAYOUT_ID - // For other objects, use the record's pageLayoutId (when backend is ready) const pageLayoutId = objectMetadataItem.nameSingular === CoreObjectNameSingular.Company - ? DEFAULT_PAGE_LAYOUT_ID + ? DEFAULT_RECORD_PAGE_LAYOUT_ID : selectedRecord?.pageLayoutId; const { savePageLayout } = useSavePageLayout(pageLayoutId); diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutDispatcher.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutDispatcher.tsx index 1a01e77d9b..60ea78e158 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutDispatcher.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutDispatcher.tsx @@ -18,12 +18,22 @@ export const PageLayoutDispatcher = ({ FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_ENABLED, ); + const isStandardObjectWithDefaultLayout = + targetRecordIdentifier.targetObjectNameSingular === + CoreObjectNameSingular.Company || + targetRecordIdentifier.targetObjectNameSingular === + CoreObjectNameSingular.Person || + targetRecordIdentifier.targetObjectNameSingular === + CoreObjectNameSingular.Opportunity || + targetRecordIdentifier.targetObjectNameSingular === + CoreObjectNameSingular.Note || + targetRecordIdentifier.targetObjectNameSingular === + CoreObjectNameSingular.Task; + if ( targetRecordIdentifier.targetObjectNameSingular === CoreObjectNameSingular.Dashboard || - (targetRecordIdentifier.targetObjectNameSingular === - CoreObjectNameSingular.Company && - isRecordPageEnabled) + (isRecordPageEnabled && isStandardObjectWithDefaultLayout) ) { return ( { + switch (layoutId) { + case DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID: + return DEFAULT_COMPANY_RECORD_PAGE_LAYOUT; + case DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID: + return DEFAULT_PERSON_RECORD_PAGE_LAYOUT; + case DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID: + return DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT; + case DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID: + return DEFAULT_NOTE_RECORD_PAGE_LAYOUT; + case DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID: + return DEFAULT_TASK_RECORD_PAGE_LAYOUT; + case DEFAULT_RECORD_PAGE_LAYOUT_ID: + default: + return DEFAULT_RECORD_PAGE_LAYOUT; + } +}; + type PageLayoutInitializationQueryEffectProps = { pageLayoutId: string; onInitialized?: (pageLayout: PageLayout) => void; @@ -26,7 +54,13 @@ export const PageLayoutInitializationQueryEffect = ({ }: PageLayoutInitializationQueryEffectProps) => { const [isInitialized, setIsInitialized] = useState(false); - const isDefaultLayout = pageLayoutId === DEFAULT_PAGE_LAYOUT_ID; + const isDefaultLayout = + pageLayoutId === DEFAULT_RECORD_PAGE_LAYOUT_ID || + pageLayoutId === DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID || + pageLayoutId === DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID || + pageLayoutId === DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID || + pageLayoutId === DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID || + pageLayoutId === DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID; const { data } = useQuery(FIND_ONE_PAGE_LAYOUT, { variables: { @@ -36,7 +70,7 @@ export const PageLayoutInitializationQueryEffect = ({ }); const pageLayout: PageLayout | undefined = isDefaultLayout - ? DEFAULT_PAGE_LAYOUT + ? getDefaultLayoutById(pageLayoutId) : data?.getPageLayout ? transformPageLayout(data.getPageLayout) : undefined; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultCompanyRecordPageLayout.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultCompanyRecordPageLayout.ts new file mode 100644 index 0000000000..da057af6f9 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultCompanyRecordPageLayout.ts @@ -0,0 +1,241 @@ +import { DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultCompanyRecordPageLayoutId'; +import { type PageLayout } from '@/page-layout/types/PageLayout'; +import { PageLayoutType, WidgetType } from '~/generated/graphql'; + +export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = { + __typename: 'PageLayout', + id: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + name: 'Default Company Layout', + type: PageLayoutType.RECORD_PAGE, + objectMetadataId: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + tabs: [ + { + __typename: 'PageLayoutTab', + id: 'company-tab-fields', + title: 'Fields', + position: 100, + layoutMode: 'vertical-list', + selfDisplayMode: 'pinned-left', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-fields', + pageLayoutTabId: 'company-tab-fields', + title: 'Fields', + type: WidgetType.FIELDS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 12, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'company-tab-timeline', + title: 'Timeline', + position: 200, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-timeline', + pageLayoutTabId: 'company-tab-timeline', + title: 'Timeline', + type: WidgetType.TIMELINE, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'company-tab-tasks', + title: 'Tasks', + position: 300, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-tasks', + pageLayoutTabId: 'company-tab-tasks', + title: 'Tasks', + type: WidgetType.TASKS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'company-tab-notes', + title: 'Notes', + position: 400, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-notes', + pageLayoutTabId: 'company-tab-notes', + title: 'Notes', + type: WidgetType.NOTES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'company-tab-files', + title: 'Files', + position: 500, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-files', + pageLayoutTabId: 'company-tab-files', + title: 'Files', + type: WidgetType.FILES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'company-tab-emails', + title: 'Emails', + position: 600, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-emails', + pageLayoutTabId: 'company-tab-emails', + title: 'Emails', + type: WidgetType.EMAILS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'company-tab-calendar', + title: 'Calendar', + position: 700, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'company-widget-calendar', + pageLayoutTabId: 'company-tab-calendar', + title: 'Calendar', + type: WidgetType.CALENDAR, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + ], +}; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultCompanyRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultCompanyRecordPageLayoutId.ts new file mode 100644 index 0000000000..7a86f51fa8 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultCompanyRecordPageLayoutId.ts @@ -0,0 +1,2 @@ +export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID = + 'default-company-page-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultNoteRecordPageLayout.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultNoteRecordPageLayout.ts new file mode 100644 index 0000000000..9f0a0a6487 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultNoteRecordPageLayout.ts @@ -0,0 +1,132 @@ +import { DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultNoteRecordPageLayoutId'; +import { type PageLayout } from '@/page-layout/types/PageLayout'; +import { PageLayoutType, WidgetType } from '~/generated/graphql'; + +export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = { + __typename: 'PageLayout', + id: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID, + name: 'Default Note Layout', + type: PageLayoutType.RECORD_PAGE, + objectMetadataId: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + tabs: [ + { + __typename: 'PageLayoutTab', + id: 'note-tab-fields', + title: 'Fields', + position: 100, + layoutMode: 'vertical-list', + selfDisplayMode: 'pinned-left', + pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'note-widget-fields', + pageLayoutTabId: 'note-tab-fields', + title: 'Fields', + type: WidgetType.FIELDS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 12, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + { + __typename: 'PageLayoutWidget', + id: 'note-widget-note', + pageLayoutTabId: 'note-tab-fields', + title: 'Note', + type: WidgetType.RICH_TEXT, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 12, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'note-tab-timeline', + title: 'Timeline', + position: 200, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'note-widget-timeline', + pageLayoutTabId: 'note-tab-timeline', + title: 'Timeline', + type: WidgetType.TIMELINE, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'note-tab-files', + title: 'Files', + position: 300, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'note-widget-files', + pageLayoutTabId: 'note-tab-files', + title: 'Files', + type: WidgetType.FILES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + ], +}; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultNoteRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultNoteRecordPageLayoutId.ts new file mode 100644 index 0000000000..686f4a7e57 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultNoteRecordPageLayoutId.ts @@ -0,0 +1 @@ +export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID = 'default-note-page-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultOpportunityRecordPageLayout.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultOpportunityRecordPageLayout.ts new file mode 100644 index 0000000000..c6aeae6650 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultOpportunityRecordPageLayout.ts @@ -0,0 +1,241 @@ +import { DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultOpportunityRecordPageLayoutId'; +import { type PageLayout } from '@/page-layout/types/PageLayout'; +import { PageLayoutType, WidgetType } from '~/generated/graphql'; + +export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = { + __typename: 'PageLayout', + id: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + name: 'Default Opportunity Layout', + type: PageLayoutType.RECORD_PAGE, + objectMetadataId: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + tabs: [ + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-fields', + title: 'Fields', + position: 100, + layoutMode: 'vertical-list', + selfDisplayMode: 'pinned-left', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-fields', + pageLayoutTabId: 'opportunity-tab-fields', + title: 'Fields', + type: WidgetType.FIELDS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 12, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-timeline', + title: 'Timeline', + position: 200, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-timeline', + pageLayoutTabId: 'opportunity-tab-timeline', + title: 'Timeline', + type: WidgetType.TIMELINE, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-tasks', + title: 'Tasks', + position: 300, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-tasks', + pageLayoutTabId: 'opportunity-tab-tasks', + title: 'Tasks', + type: WidgetType.TASKS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-notes', + title: 'Notes', + position: 400, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-notes', + pageLayoutTabId: 'opportunity-tab-notes', + title: 'Notes', + type: WidgetType.NOTES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-files', + title: 'Files', + position: 500, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-files', + pageLayoutTabId: 'opportunity-tab-files', + title: 'Files', + type: WidgetType.FILES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-emails', + title: 'Emails', + position: 600, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-emails', + pageLayoutTabId: 'opportunity-tab-emails', + title: 'Emails', + type: WidgetType.EMAILS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'opportunity-tab-calendar', + title: 'Calendar', + position: 700, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'opportunity-widget-calendar', + pageLayoutTabId: 'opportunity-tab-calendar', + title: 'Calendar', + type: WidgetType.CALENDAR, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + ], +}; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultOpportunityRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultOpportunityRecordPageLayoutId.ts new file mode 100644 index 0000000000..22ff3e1e05 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultOpportunityRecordPageLayoutId.ts @@ -0,0 +1,2 @@ +export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID = + 'default-opportunity-page-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultPageLayoutId.ts deleted file mode 100644 index dc46202365..0000000000 --- a/packages/twenty-front/src/modules/page-layout/constants/DefaultPageLayoutId.ts +++ /dev/null @@ -1 +0,0 @@ -export const DEFAULT_PAGE_LAYOUT_ID = 'DEFAULT_LAYOUT_ID'; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultPersonRecordPageLayout.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultPersonRecordPageLayout.ts new file mode 100644 index 0000000000..e4c3005d05 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultPersonRecordPageLayout.ts @@ -0,0 +1,241 @@ +import { DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPersonRecordPageLayoutId'; +import { type PageLayout } from '@/page-layout/types/PageLayout'; +import { PageLayoutType, WidgetType } from '~/generated/graphql'; + +export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = { + __typename: 'PageLayout', + id: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + name: 'Default Person Layout', + type: PageLayoutType.RECORD_PAGE, + objectMetadataId: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + tabs: [ + { + __typename: 'PageLayoutTab', + id: 'person-tab-fields', + title: 'Fields', + position: 100, + layoutMode: 'vertical-list', + selfDisplayMode: 'pinned-left', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-fields', + pageLayoutTabId: 'person-tab-fields', + title: 'Fields', + type: WidgetType.FIELDS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 12, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'person-tab-timeline', + title: 'Timeline', + position: 200, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-timeline', + pageLayoutTabId: 'person-tab-timeline', + title: 'Timeline', + type: WidgetType.TIMELINE, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'person-tab-tasks', + title: 'Tasks', + position: 300, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-tasks', + pageLayoutTabId: 'person-tab-tasks', + title: 'Tasks', + type: WidgetType.TASKS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'person-tab-notes', + title: 'Notes', + position: 400, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-notes', + pageLayoutTabId: 'person-tab-notes', + title: 'Notes', + type: WidgetType.NOTES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'person-tab-files', + title: 'Files', + position: 500, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-files', + pageLayoutTabId: 'person-tab-files', + title: 'Files', + type: WidgetType.FILES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'person-tab-emails', + title: 'Emails', + position: 600, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-emails', + pageLayoutTabId: 'person-tab-emails', + title: 'Emails', + type: WidgetType.EMAILS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'person-tab-calendar', + title: 'Calendar', + position: 700, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'person-widget-calendar', + pageLayoutTabId: 'person-tab-calendar', + title: 'Calendar', + type: WidgetType.CALENDAR, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + ], +}; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultPersonRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultPersonRecordPageLayoutId.ts new file mode 100644 index 0000000000..55e015bf14 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultPersonRecordPageLayoutId.ts @@ -0,0 +1,2 @@ +export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID = + 'default-person-page-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultPageLayout.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultRecordPageLayout.ts similarity index 80% rename from packages/twenty-front/src/modules/page-layout/constants/DefaultPageLayout.ts rename to packages/twenty-front/src/modules/page-layout/constants/DefaultRecordPageLayout.ts index a5167557d7..b546475a27 100644 --- a/packages/twenty-front/src/modules/page-layout/constants/DefaultPageLayout.ts +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultRecordPageLayout.ts @@ -1,15 +1,10 @@ -import { DEFAULT_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPageLayoutId'; +import { DEFAULT_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultRecordPageLayoutId'; import { type PageLayout } from '@/page-layout/types/PageLayout'; import { PageLayoutType, WidgetType } from '~/generated/graphql'; -/** - * Default mock PageLayout used when pageLayoutId equals DEFAULT_PAGE_LAYOUT_ID. - * This combines base record layout tabs (fields, timeline, tasks, notes, files) - * with company-specific tabs (emails, calendar). - */ -export const DEFAULT_PAGE_LAYOUT: PageLayout = { +export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = { __typename: 'PageLayout', - id: DEFAULT_PAGE_LAYOUT_ID, + id: DEFAULT_RECORD_PAGE_LAYOUT_ID, name: 'Default Record Layout', type: PageLayoutType.RECORD_PAGE, objectMetadataId: null, @@ -17,7 +12,6 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { updatedAt: new Date().toISOString(), deletedAt: null, tabs: [ - // Fields tab (position 100) { __typename: 'PageLayoutTab', id: 'default-tab-fields', @@ -25,7 +19,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { position: 100, layoutMode: 'vertical-list', selfDisplayMode: 'pinned-left', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, @@ -51,14 +45,13 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { }, ], }, - // Timeline tab (position 200) { __typename: 'PageLayoutTab', id: 'default-tab-timeline', title: 'Timeline', position: 200, layoutMode: 'vertical-list', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, @@ -84,14 +77,13 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { }, ], }, - // Tasks tab (position 300) { __typename: 'PageLayoutTab', id: 'default-tab-tasks', title: 'Tasks', position: 300, layoutMode: 'vertical-list', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, @@ -115,35 +107,15 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { updatedAt: new Date().toISOString(), deletedAt: null, }, - { - __typename: 'PageLayoutWidget', - id: 'default-widget-tasks-2', - pageLayoutTabId: 'default-tab-tasks', - title: 'Tasks', - type: WidgetType.TASKS, - objectMetadataId: null, - gridPosition: { - __typename: 'GridPosition', - row: 0, - column: 0, - rowSpan: 6, - columnSpan: 12, - }, - configuration: null, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - deletedAt: null, - }, ], }, - // Notes tab (position 400) { __typename: 'PageLayoutTab', id: 'default-tab-notes', title: 'Notes', position: 400, layoutMode: 'vertical-list', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, @@ -169,14 +141,13 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { }, ], }, - // Files tab (position 500) { __typename: 'PageLayoutTab', id: 'default-tab-files', title: 'Files', position: 500, layoutMode: 'vertical-list', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, @@ -202,14 +173,13 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { }, ], }, - // Emails tab (position 600) - Company specific { __typename: 'PageLayoutTab', id: 'default-tab-emails', title: 'Emails', position: 600, layoutMode: 'vertical-list', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, @@ -235,14 +205,13 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { }, ], }, - // Calendar tab (position 700) - Company specific { __typename: 'PageLayoutTab', id: 'default-tab-calendar', title: 'Calendar', position: 700, layoutMode: 'vertical-list', - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deletedAt: null, diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultRecordPageLayoutId.ts new file mode 100644 index 0000000000..e57e4c9027 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultRecordPageLayoutId.ts @@ -0,0 +1 @@ +export const DEFAULT_RECORD_PAGE_LAYOUT_ID = 'default-page-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultTaskRecordPageLayout.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultTaskRecordPageLayout.ts new file mode 100644 index 0000000000..74cf5d2109 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultTaskRecordPageLayout.ts @@ -0,0 +1,132 @@ +import { DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultTaskRecordPageLayoutId'; +import { type PageLayout } from '@/page-layout/types/PageLayout'; +import { PageLayoutType, WidgetType } from '~/generated/graphql'; + +export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = { + __typename: 'PageLayout', + id: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID, + name: 'Default Task Layout', + type: PageLayoutType.RECORD_PAGE, + objectMetadataId: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + tabs: [ + { + __typename: 'PageLayoutTab', + id: 'task-tab-fields', + title: 'Fields', + position: 100, + layoutMode: 'vertical-list', + selfDisplayMode: 'pinned-left', + pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'task-widget-fields', + pageLayoutTabId: 'task-tab-fields', + title: 'Fields', + type: WidgetType.FIELDS, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 12, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + { + __typename: 'PageLayoutWidget', + id: 'task-widget-note', + pageLayoutTabId: 'task-tab-fields', + title: 'Note', + type: WidgetType.RICH_TEXT, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 12, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'task-tab-timeline', + title: 'Timeline', + position: 200, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'task-widget-timeline', + pageLayoutTabId: 'task-tab-timeline', + title: 'Timeline', + type: WidgetType.TIMELINE, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + { + __typename: 'PageLayoutTab', + id: 'task-tab-files', + title: 'Files', + position: 300, + layoutMode: 'vertical-list', + pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'task-widget-files', + pageLayoutTabId: 'task-tab-files', + title: 'Files', + type: WidgetType.FILES, + objectMetadataId: null, + gridPosition: { + __typename: 'GridPosition', + row: 0, + column: 0, + rowSpan: 6, + columnSpan: 12, + }, + configuration: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + deletedAt: null, + }, + ], + }, + ], +}; diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultTaskRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/constants/DefaultTaskRecordPageLayoutId.ts new file mode 100644 index 0000000000..e297b908bc --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/constants/DefaultTaskRecordPageLayoutId.ts @@ -0,0 +1 @@ +export const DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID = 'default-task-page-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/hooks/useRecordPageLayoutId.ts b/packages/twenty-front/src/modules/page-layout/hooks/useRecordPageLayoutId.ts index 9c9081a583..83dce97e73 100644 --- a/packages/twenty-front/src/modules/page-layout/hooks/useRecordPageLayoutId.ts +++ b/packages/twenty-front/src/modules/page-layout/hooks/useRecordPageLayoutId.ts @@ -1,9 +1,24 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; import { type ObjectRecord } from '@/object-record/types/ObjectRecord'; -import { DEFAULT_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPageLayoutId'; +import { DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultCompanyRecordPageLayoutId'; +import { DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultNoteRecordPageLayoutId'; +import { DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultOpportunityRecordPageLayoutId'; +import { DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultPersonRecordPageLayoutId'; +import { DEFAULT_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultRecordPageLayoutId'; +import { DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultTaskRecordPageLayoutId'; import { type TargetRecordIdentifier } from '@/ui/layout/contexts/TargetRecordIdentifier'; import { isDefined } from 'twenty-shared/utils'; +const OBJECT_NAME_TO_DEFAULT_LAYOUT_ID: Record = { + [CoreObjectNameSingular.Company]: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID, + [CoreObjectNameSingular.Person]: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID, + [CoreObjectNameSingular.Opportunity]: + DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID, + [CoreObjectNameSingular.Note]: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID, + [CoreObjectNameSingular.Task]: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID, +}; + export const useRecordPageLayoutId = ({ id, targetObjectNameSingular, @@ -27,8 +42,11 @@ export const useRecordPageLayoutId = ({ }; } - // TODO: implement a default layout + const defaultLayoutId = + OBJECT_NAME_TO_DEFAULT_LAYOUT_ID[targetObjectNameSingular] ?? + DEFAULT_RECORD_PAGE_LAYOUT_ID; + return { - pageLayoutId: DEFAULT_PAGE_LAYOUT_ID, + pageLayoutId: defaultLayoutId, }; }; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/components/WidgetContentRenderer.tsx b/packages/twenty-front/src/modules/page-layout/widgets/components/WidgetContentRenderer.tsx index 16038dd6df..33e39902d0 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/components/WidgetContentRenderer.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/components/WidgetContentRenderer.tsx @@ -5,9 +5,13 @@ import { FileWidget } from '@/page-layout/widgets/files/components/FileWidget'; import { GraphWidgetRenderer } from '@/page-layout/widgets/graph/components/GraphWidgetRenderer'; import { IframeWidget } from '@/page-layout/widgets/iframe/components/IframeWidget'; import { NoteWidget } from '@/page-layout/widgets/notes/components/NoteWidget'; +import { RichTextWidget } from '@/page-layout/widgets/rich-text/components/RichTextWidget'; import { TaskWidget } from '@/page-layout/widgets/tasks/components/TaskWidget'; import { TimelineWidget } from '@/page-layout/widgets/timeline/components/TimelineWidget'; -import { type PageLayoutWidget, WidgetType } from '~/generated/graphql'; +import { + type PageLayoutWidget, + WidgetType, +} from '~/generated-metadata/graphql'; type WidgetContentRendererProps = { widget: PageLayoutWidget; @@ -35,6 +39,9 @@ export const WidgetContentRenderer = ({ case WidgetType.NOTES: return ; + case WidgetType.RICH_TEXT: + return ; + case WidgetType.FILES: return ; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/rich-text/components/RichTextWidget.tsx b/packages/twenty-front/src/modules/page-layout/widgets/rich-text/components/RichTextWidget.tsx new file mode 100644 index 0000000000..63f0056d86 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/rich-text/components/RichTextWidget.tsx @@ -0,0 +1,21 @@ +import { RichTextCard } from '@/ui/layout/show-page/components/RichTextCard'; +import styled from '@emotion/styled'; +import { type PageLayoutWidget } from '~/generated/graphql'; + +const StyledContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; +`; + +type RichTextWidgetProps = { + widget: PageLayoutWidget; +}; + +export const RichTextWidget = ({ widget: _widget }: RichTextWidgetProps) => { + return ( + + + + ); +}; diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/common/1761215000000-addRichTextWidgetType.ts b/packages/twenty-server/src/database/typeorm/core/migrations/common/1761215000000-addRichTextWidgetType.ts new file mode 100644 index 0000000000..acbc555bd7 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/common/1761215000000-addRichTextWidgetType.ts @@ -0,0 +1,45 @@ +import { type MigrationInterface, type QueryRunner } from 'typeorm'; + +export class AddRichTextWidgetType1761215000000 implements MigrationInterface { + name = 'AddRichTextWidgetType1761215000000'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TYPE "core"."pageLayoutWidget_type_enum" RENAME TO "pageLayoutWidget_type_enum_old"`, + ); + await queryRunner.query( + `CREATE TYPE "core"."pageLayoutWidget_type_enum" AS ENUM('VIEW', 'IFRAME', 'FIELDS', 'GRAPH', 'TIMELINE', 'TASKS', 'NOTES', 'FILES', 'EMAILS', 'CALENDAR', 'RICH_TEXT')`, + ); + await queryRunner.query( + `ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" TYPE "core"."pageLayoutWidget_type_enum" USING "type"::"text"::"core"."pageLayoutWidget_type_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" SET DEFAULT 'VIEW'`, + ); + await queryRunner.query( + `DROP TYPE "core"."pageLayoutWidget_type_enum_old"`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "core"."pageLayoutWidget_type_enum_old" AS ENUM('VIEW', 'IFRAME', 'FIELDS', 'GRAPH', 'TIMELINE', 'TASKS', 'NOTES', 'FILES', 'EMAILS', 'CALENDAR')`, + ); + await queryRunner.query( + `ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" TYPE "core"."pageLayoutWidget_type_enum_old" USING "type"::"text"::"core"."pageLayoutWidget_type_enum_old"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" SET DEFAULT 'VIEW'`, + ); + await queryRunner.query(`DROP TYPE "core"."pageLayoutWidget_type_enum"`); + await queryRunner.query( + `ALTER TYPE "core"."pageLayoutWidget_type_enum_old" RENAME TO "pageLayoutWidget_type_enum"`, + ); + } +} diff --git a/packages/twenty-server/src/engine/core-modules/page-layout/enums/widget-type.enum.ts b/packages/twenty-server/src/engine/core-modules/page-layout/enums/widget-type.enum.ts index 311476a945..3b801571a9 100644 --- a/packages/twenty-server/src/engine/core-modules/page-layout/enums/widget-type.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/page-layout/enums/widget-type.enum.ts @@ -9,4 +9,5 @@ export enum WidgetType { FILES = 'FILES', EMAILS = 'EMAILS', CALENDAR = 'CALENDAR', + RICH_TEXT = 'RICH_TEXT', }