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:
Félix Malfait
2026-04-06 12:02:04 +02:00
committed by GitHub
parent 4aa1d71b12
commit 8acfacc69c
56 changed files with 2441 additions and 2371 deletions
@@ -3,10 +3,26 @@ type MessageThreadDataSeed = {
createdAt: Date;
updatedAt: Date;
deletedAt: Date | null;
subject: string;
};
export const MESSAGE_THREAD_DATA_SEED_COLUMNS: (keyof MessageThreadDataSeed)[] =
['id', 'createdAt', 'updatedAt', 'deletedAt'];
['id', 'createdAt', 'updatedAt', 'deletedAt', 'subject'];
const EMAIL_SUBJECTS = [
'Meeting Request',
'Project Update',
'Invoice for Services',
'Thank You for the Meeting',
'Proposal Submission',
'Follow-up on Discussion',
'Customer Feedback',
'Training Session Reminder',
'Contract Renewal',
'Quarterly Report',
'Partnership Opportunity',
'Event Invitation',
];
const GENERATE_MESSAGE_THREAD_IDS = (): Record<string, string> => {
const THREAD_IDS: Record<string, string> = {};
@@ -41,11 +57,14 @@ const GENERATE_MESSAGE_THREAD_SEEDS = (): MessageThreadDataSeed[] => {
CREATED_DATE.getTime() + UPDATE_OFFSET * 24 * 60 * 60 * 1000,
);
const TEMPLATE_INDEX = ((INDEX - 1) * 2) % EMAIL_SUBJECTS.length;
THREAD_SEEDS.push({
id: MESSAGE_THREAD_DATA_SEED_IDS[`ID_${INDEX}`],
createdAt: CREATED_DATE,
updatedAt: UPDATED_DATE,
deletedAt: null,
subject: EMAIL_SUBJECTS[TEMPLATE_INDEX],
});
}