feat: add organization email templates management

- Created a new SQL migration to establish the organization_email_templates table with necessary fields and default templates for common events.
- Implemented CRUD operations for email templates in Rust, including listing, creating, updating, and deleting templates.
- Developed a React component for managing email templates, allowing users to create, edit, and delete templates with a user-friendly interface.
This commit is contained in:
2026-04-15 10:26:44 -04:00
parent e1d5975e57
commit 6f8b723d64
18 changed files with 997 additions and 36 deletions
+31 -2
View File
@@ -308,7 +308,7 @@ export interface OrganizationEmailService {
service_type: string;
provider_key: string;
display_name: string;
smtp_enabled: boolean;
is_enabled: boolean;
is_default: boolean;
smtp_host?: string;
smtp_port: number;
@@ -322,7 +322,7 @@ export interface UpsertOrganizationEmailServicePayload {
service_type: string;
provider_key: string;
display_name: string;
smtp_enabled: boolean;
is_enabled: boolean;
is_default: boolean;
smtp_host?: string;
smtp_port: number;
@@ -332,6 +332,28 @@ export interface UpsertOrganizationEmailServicePayload {
smtp_starttls: boolean;
}
export interface OrganizationEmailTemplate {
id: string;
organization_id: string;
template_key: string;
display_name: string;
subject_template: string;
body_template: string;
is_html: bool;
is_enabled: bool;
created_at: string;
updated_at: string;
}
export interface UpsertOrganizationEmailTemplatePayload {
template_key: string;
display_name: string;
subject_template: string;
body_template: string;
is_html: bool;
is_enabled: bool;
}
export interface ProvisionPayload {
org_name: string;
org_domain?: string;
@@ -923,6 +945,13 @@ export const cmsApi = {
apiFetch(`/organization/email-services/${id}`, { method: 'DELETE' }),
selectOrganizationEmailService: (id: string): Promise<void> =>
apiFetch(`/organization/email-services/${id}/select`, { method: 'POST' }),
listOrganizationEmailTemplates: (): Promise<OrganizationEmailTemplate[]> => apiFetch('/organization/email-templates'),
createOrganizationEmailTemplate: (payload: UpsertOrganizationEmailTemplatePayload): Promise<OrganizationEmailTemplate> =>
apiFetch('/organization/email-templates', { method: 'POST', body: JSON.stringify(payload) }),
updateOrganizationEmailTemplate: (id: string, payload: UpsertOrganizationEmailTemplatePayload): Promise<OrganizationEmailTemplate> =>
apiFetch(`/organization/email-templates/${id}`, { method: 'PUT', body: JSON.stringify(payload) }),
deleteOrganizationEmailTemplate: (id: string): Promise<void> =>
apiFetch(`/organization/email-templates/${id}`, { method: 'DELETE' }),
getOrganizationExerciseSettings: (): Promise<OrganizationExerciseSettings> => apiFetch('/organization/exercise-settings'),
updateOrganizationExerciseSettings: (payload: Omit<OrganizationExerciseSettings, 'organization_id'>): Promise<OrganizationExerciseSettings> =>
apiFetch('/organization/exercise-settings', { method: 'PUT', body: JSON.stringify(payload) }),