feat(mail) : extract Mail front into Nuxt module layer
LST-67 (2.5) front. Completes the Mail module. - New frontend/modules/mail/ layer (auto-detected): /mail page (3 columns), 7 components, mail service + DTO, mail store (folders/messages/unread polling). - sanitizeMailHtml util and useSystemFolderLabel composable stay global; AdminMailTab stays in /admin (service import repointed). - Consumers repointed: AdminMailTab and PM TaskModal -> ~/modules/mail/...; the store is auto-imported (Pinia storesDirs) so the layout badge/polling is unchanged. - /mail gated by the mail module: sidebar.php item with module=mail (so SidebarFilter disables /mail when the module is off); the layout filters /mail from the API sections to avoid a visual duplicate. ROLE_CLIENT exclusion kept. - i18n key sidebar.general.mail added. nuxt build passes; /mail and all other routes preserved.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
// Lecture de la configuration mail (singleton admin)
|
||||
export type MailConfigurationDto = {
|
||||
protocol: string | null
|
||||
imapHost: string | null
|
||||
imapPort: number | null
|
||||
imapEncryption: string | null
|
||||
smtpHost: string | null
|
||||
smtpPort: number | null
|
||||
smtpEncryption: string | null
|
||||
username: string | null
|
||||
sentFolderPath: string | null
|
||||
enabled: boolean
|
||||
hasPassword: boolean
|
||||
// password JAMAIS présent dans les réponses GET
|
||||
}
|
||||
|
||||
// Input PATCH configuration (password optionnel, write-only)
|
||||
export type MailConfigurationUpdateDto = {
|
||||
protocol?: string | null
|
||||
imapHost?: string | null
|
||||
imapPort?: number | null
|
||||
imapEncryption?: string | null
|
||||
smtpHost?: string | null
|
||||
smtpPort?: number | null
|
||||
smtpEncryption?: string | null
|
||||
username?: string | null
|
||||
sentFolderPath?: string | null
|
||||
enabled?: boolean
|
||||
password?: string // write-only, jamais retourné
|
||||
}
|
||||
|
||||
// Résultat du test de connexion
|
||||
export type MailTestConnectionResultDto = {
|
||||
ok: boolean
|
||||
foldersCount?: number
|
||||
error?: string
|
||||
}
|
||||
|
||||
// Dossier mail (peut être imbriqué)
|
||||
export type MailFolderDto = {
|
||||
path: string
|
||||
displayName: string
|
||||
parentPath: string | null
|
||||
unreadCount: number
|
||||
totalCount: number
|
||||
children?: MailFolderDto[]
|
||||
}
|
||||
|
||||
// Adresse mail (nom + email)
|
||||
export type MailAddressDto = {
|
||||
name: string | null
|
||||
email: string
|
||||
}
|
||||
|
||||
// En-tête d'un message (liste)
|
||||
export type MailMessageHeaderDto = {
|
||||
id: number
|
||||
messageId: string // identifiant IMAP unique
|
||||
folderPath: string
|
||||
subject: string | null
|
||||
fromName: string | null
|
||||
fromEmail: string | null
|
||||
toRecipients: MailAddressDto[]
|
||||
ccRecipients: MailAddressDto[]
|
||||
sentAt: string | null // ISO 8601
|
||||
receivedAt: string // ISO 8601
|
||||
isRead: boolean
|
||||
isFlagged: boolean
|
||||
hasAttachments: boolean
|
||||
linkedTaskIds: number[]
|
||||
}
|
||||
|
||||
// Pièce jointe (métadonnées uniquement, téléchargement via downloadId)
|
||||
export type MailAttachmentDto = {
|
||||
downloadId: string
|
||||
filename: string
|
||||
mimeType: string
|
||||
size: number // octets
|
||||
}
|
||||
|
||||
// Détail complet d'un message (enrichi avec body + PJ)
|
||||
export type MailMessageDetailDto = {
|
||||
header: MailMessageHeaderDto
|
||||
bodyHtml: string | null // HTML brut — TOUJOURS passer par sanitizeMailHtml() avant affichage
|
||||
bodyText: string | null // Fallback texte plain
|
||||
attachments: MailAttachmentDto[]
|
||||
}
|
||||
|
||||
// Page de messages paginée (cursor-based)
|
||||
export type MailMessagesPageDto = {
|
||||
items: MailMessageHeaderDto[]
|
||||
nextCursor: string | null // null = plus de page suivante
|
||||
total: number
|
||||
}
|
||||
|
||||
// Input : marquer lu/non-lu
|
||||
export type MailMessageReadInput = {
|
||||
read: boolean
|
||||
}
|
||||
|
||||
// Input : marquer étoilé/non-étoilé
|
||||
export type MailMessageFlagInput = {
|
||||
flagged: boolean
|
||||
}
|
||||
|
||||
// Input : créer une tâche depuis un mail
|
||||
export type MailCreateTaskInput = {
|
||||
projectId: number
|
||||
taskGroupId?: number | null
|
||||
assigneeId?: number
|
||||
statusId?: number
|
||||
}
|
||||
|
||||
// Input : lier une tâche existante à un mail
|
||||
export type MailLinkTaskInput = {
|
||||
taskId: number
|
||||
}
|
||||
|
||||
// Résultat de la sync manuelle
|
||||
export type MailSyncResultDto = {
|
||||
dispatched: boolean
|
||||
}
|
||||
Reference in New Issue
Block a user