Add email thread widget and message thread record page layout (#19351)
## Summary - Move email thread display from side panel to a dedicated record page with a new `EMAIL_THREAD` widget type - Add message thread as a standard object with page layout, subject field, and backfill command - Add reply-to-email command menu item for message thread records - Remove old side panel message thread components in favor of the new widget-based approach ## Type fixes - Add `EMAIL_THREAD` to `WidgetConfigurationType`, `WidgetType`, and all configuration/validator maps - Create `EmailThreadConfigurationDTO` and shared `EmailThreadConfiguration` type - Register EMAIL_THREAD in widget type validators, configuration resolvers, and standard widget mappings ## Test plan - [ ] Verify message thread record pages render with the email thread widget - [ ] Verify email thread preview navigates to the record page instead of opening side panel - [ ] Verify reply-to-email command appears for message thread records - [ ] Verify typecheck passes for both twenty-front and twenty-server - [ ] Run existing test suites to check for regressions 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -921,6 +921,7 @@ enum WidgetType {
|
||||
WORKFLOW_RUN
|
||||
FRONT_COMPONENT
|
||||
RECORD_TABLE
|
||||
EMAIL_THREAD
|
||||
}
|
||||
|
||||
union PageLayoutWidgetPosition = PageLayoutWidgetGridPosition | PageLayoutWidgetVerticalListPosition | PageLayoutWidgetCanvasPosition
|
||||
@@ -948,7 +949,7 @@ type PageLayoutWidgetCanvasPosition {
|
||||
layoutMode: PageLayoutTabLayoutMode!
|
||||
}
|
||||
|
||||
union WidgetConfiguration = AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration
|
||||
union WidgetConfiguration = AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration
|
||||
|
||||
type AggregateChartConfiguration {
|
||||
configurationType: WidgetConfigurationType!
|
||||
@@ -989,6 +990,7 @@ enum WidgetConfigurationType {
|
||||
WORKFLOW_RUN
|
||||
FRONT_COMPONENT
|
||||
RECORD_TABLE
|
||||
EMAIL_THREAD
|
||||
}
|
||||
|
||||
type StandaloneRichTextConfiguration {
|
||||
@@ -1154,6 +1156,10 @@ type EmailsConfiguration {
|
||||
configurationType: WidgetConfigurationType!
|
||||
}
|
||||
|
||||
type EmailThreadConfiguration {
|
||||
configurationType: WidgetConfigurationType!
|
||||
}
|
||||
|
||||
type FieldConfiguration {
|
||||
configurationType: WidgetConfigurationType!
|
||||
fieldMetadataId: String!
|
||||
@@ -2632,6 +2638,7 @@ enum EngineComponentKey {
|
||||
VIEW_PREVIOUS_AI_CHATS
|
||||
TRIGGER_WORKFLOW_VERSION
|
||||
FRONT_COMPONENT_RENDERER
|
||||
REPLY_TO_EMAIL_THREAD
|
||||
DELETE_SINGLE_RECORD
|
||||
DELETE_MULTIPLE_RECORDS
|
||||
RESTORE_SINGLE_RECORD
|
||||
|
||||
@@ -676,7 +676,7 @@ export interface PageLayoutWidget {
|
||||
__typename: 'PageLayoutWidget'
|
||||
}
|
||||
|
||||
export type WidgetType = 'VIEW' | 'IFRAME' | 'FIELD' | 'FIELDS' | 'GRAPH' | 'STANDALONE_RICH_TEXT' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE'
|
||||
export type WidgetType = 'VIEW' | 'IFRAME' | 'FIELD' | 'FIELDS' | 'GRAPH' | 'STANDALONE_RICH_TEXT' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE' | 'EMAIL_THREAD'
|
||||
|
||||
export type PageLayoutWidgetPosition = (PageLayoutWidgetGridPosition | PageLayoutWidgetVerticalListPosition | PageLayoutWidgetCanvasPosition) & { __isUnion?: true }
|
||||
|
||||
@@ -702,7 +702,7 @@ export interface PageLayoutWidgetCanvasPosition {
|
||||
__typename: 'PageLayoutWidgetCanvasPosition'
|
||||
}
|
||||
|
||||
export type WidgetConfiguration = (AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration) & { __isUnion?: true }
|
||||
export type WidgetConfiguration = (AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration) & { __isUnion?: true }
|
||||
|
||||
export interface AggregateChartConfiguration {
|
||||
configurationType: WidgetConfigurationType
|
||||
@@ -721,7 +721,7 @@ export interface AggregateChartConfiguration {
|
||||
__typename: 'AggregateChartConfiguration'
|
||||
}
|
||||
|
||||
export type WidgetConfigurationType = 'AGGREGATE_CHART' | 'GAUGE_CHART' | 'PIE_CHART' | 'BAR_CHART' | 'LINE_CHART' | 'IFRAME' | 'STANDALONE_RICH_TEXT' | 'VIEW' | 'FIELD' | 'FIELDS' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE'
|
||||
export type WidgetConfigurationType = 'AGGREGATE_CHART' | 'GAUGE_CHART' | 'PIE_CHART' | 'BAR_CHART' | 'LINE_CHART' | 'IFRAME' | 'STANDALONE_RICH_TEXT' | 'VIEW' | 'FIELD' | 'FIELDS' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE' | 'EMAIL_THREAD'
|
||||
|
||||
export interface StandaloneRichTextConfiguration {
|
||||
configurationType: WidgetConfigurationType
|
||||
@@ -869,6 +869,11 @@ export interface EmailsConfiguration {
|
||||
__typename: 'EmailsConfiguration'
|
||||
}
|
||||
|
||||
export interface EmailThreadConfiguration {
|
||||
configurationType: WidgetConfigurationType
|
||||
__typename: 'EmailThreadConfiguration'
|
||||
}
|
||||
|
||||
export interface FieldConfiguration {
|
||||
configurationType: WidgetConfigurationType
|
||||
fieldMetadataId: Scalars['String']
|
||||
@@ -2290,7 +2295,7 @@ export interface CommandMenuItem {
|
||||
__typename: 'CommandMenuItem'
|
||||
}
|
||||
|
||||
export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS'
|
||||
export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'REPLY_TO_EMAIL_THREAD' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS'
|
||||
|
||||
export type CommandMenuItemAvailabilityType = 'GLOBAL' | 'RECORD_SELECTION' | 'FALLBACK'
|
||||
|
||||
@@ -3790,6 +3795,7 @@ export interface WidgetConfigurationGenqlSelection{
|
||||
on_CalendarConfiguration?:CalendarConfigurationGenqlSelection,
|
||||
on_FrontComponentConfiguration?:FrontComponentConfigurationGenqlSelection,
|
||||
on_EmailsConfiguration?:EmailsConfigurationGenqlSelection,
|
||||
on_EmailThreadConfiguration?:EmailThreadConfigurationGenqlSelection,
|
||||
on_FieldConfiguration?:FieldConfigurationGenqlSelection,
|
||||
on_FieldRichTextConfiguration?:FieldRichTextConfigurationGenqlSelection,
|
||||
on_FieldsConfiguration?:FieldsConfigurationGenqlSelection,
|
||||
@@ -3958,6 +3964,12 @@ export interface EmailsConfigurationGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface EmailThreadConfigurationGenqlSelection{
|
||||
configurationType?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface FieldConfigurationGenqlSelection{
|
||||
configurationType?: boolean | number
|
||||
fieldMetadataId?: boolean | number
|
||||
@@ -6956,7 +6968,7 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const WidgetConfiguration_possibleTypes: string[] = ['AggregateChartConfiguration','StandaloneRichTextConfiguration','PieChartConfiguration','LineChartConfiguration','IframeConfiguration','GaugeChartConfiguration','BarChartConfiguration','CalendarConfiguration','FrontComponentConfiguration','EmailsConfiguration','FieldConfiguration','FieldRichTextConfiguration','FieldsConfiguration','FilesConfiguration','NotesConfiguration','TasksConfiguration','TimelineConfiguration','ViewConfiguration','RecordTableConfiguration','WorkflowConfiguration','WorkflowRunConfiguration','WorkflowVersionConfiguration']
|
||||
const WidgetConfiguration_possibleTypes: string[] = ['AggregateChartConfiguration','StandaloneRichTextConfiguration','PieChartConfiguration','LineChartConfiguration','IframeConfiguration','GaugeChartConfiguration','BarChartConfiguration','CalendarConfiguration','FrontComponentConfiguration','EmailsConfiguration','EmailThreadConfiguration','FieldConfiguration','FieldRichTextConfiguration','FieldsConfiguration','FilesConfiguration','NotesConfiguration','TasksConfiguration','TimelineConfiguration','ViewConfiguration','RecordTableConfiguration','WorkflowConfiguration','WorkflowRunConfiguration','WorkflowVersionConfiguration']
|
||||
export const isWidgetConfiguration = (obj?: { __typename?: any } | null): obj is WidgetConfiguration => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isWidgetConfiguration"')
|
||||
return WidgetConfiguration_possibleTypes.includes(obj.__typename)
|
||||
@@ -7044,6 +7056,14 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const EmailThreadConfiguration_possibleTypes: string[] = ['EmailThreadConfiguration']
|
||||
export const isEmailThreadConfiguration = (obj?: { __typename?: any } | null): obj is EmailThreadConfiguration => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isEmailThreadConfiguration"')
|
||||
return EmailThreadConfiguration_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const FieldConfiguration_possibleTypes: string[] = ['FieldConfiguration']
|
||||
export const isFieldConfiguration = (obj?: { __typename?: any } | null): obj is FieldConfiguration => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isFieldConfiguration"')
|
||||
@@ -8912,7 +8932,8 @@ export const enumWidgetType = {
|
||||
WORKFLOW_VERSION: 'WORKFLOW_VERSION' as const,
|
||||
WORKFLOW_RUN: 'WORKFLOW_RUN' as const,
|
||||
FRONT_COMPONENT: 'FRONT_COMPONENT' as const,
|
||||
RECORD_TABLE: 'RECORD_TABLE' as const
|
||||
RECORD_TABLE: 'RECORD_TABLE' as const,
|
||||
EMAIL_THREAD: 'EMAIL_THREAD' as const
|
||||
}
|
||||
|
||||
export const enumPageLayoutTabLayoutMode = {
|
||||
@@ -8943,7 +8964,8 @@ export const enumWidgetConfigurationType = {
|
||||
WORKFLOW_VERSION: 'WORKFLOW_VERSION' as const,
|
||||
WORKFLOW_RUN: 'WORKFLOW_RUN' as const,
|
||||
FRONT_COMPONENT: 'FRONT_COMPONENT' as const,
|
||||
RECORD_TABLE: 'RECORD_TABLE' as const
|
||||
RECORD_TABLE: 'RECORD_TABLE' as const,
|
||||
EMAIL_THREAD: 'EMAIL_THREAD' as const
|
||||
}
|
||||
|
||||
export const enumObjectRecordGroupByDateGranularity = {
|
||||
@@ -9251,6 +9273,7 @@ export const enumEngineComponentKey = {
|
||||
VIEW_PREVIOUS_AI_CHATS: 'VIEW_PREVIOUS_AI_CHATS' as const,
|
||||
TRIGGER_WORKFLOW_VERSION: 'TRIGGER_WORKFLOW_VERSION' as const,
|
||||
FRONT_COMPONENT_RENDERER: 'FRONT_COMPONENT_RENDERER' as const,
|
||||
REPLY_TO_EMAIL_THREAD: 'REPLY_TO_EMAIL_THREAD' as const,
|
||||
DELETE_SINGLE_RECORD: 'DELETE_SINGLE_RECORD' as const,
|
||||
DELETE_MULTIPLE_RECORDS: 'DELETE_MULTIPLE_RECORDS' as const,
|
||||
RESTORE_SINGLE_RECORD: 'RESTORE_SINGLE_RECORD' as const,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user