ultisuite-client/lib/agenda/agenda-destination-identities.ts
R3D347HR4Y ad1370ea7e
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: enhance configuration and add new demo layouts
- Introduced turbopack alias for canvas in next.config.mjs.
- Updated package.json scripts for development and branding tasks.
- Added new dependencies for Tiptap extensions.
- Implemented new demo layouts for agenda, contacts, drive, and mail applications.
- Enhanced globals.css for improved theming and splash screen animations.
- Added OAuth callback handling for drive mounts.
- Updated layout components to integrate new demo shells and improve structure.
2026-06-12 19:10:24 +02:00

134 lines
4.1 KiB
TypeScript

import type { Identity } from "@/lib/compose-context"
import type {
AgendaAutoImportSource,
AgendaInvitationExclusion,
} from "@/lib/agenda/agenda-settings-types"
export function normalizeDestinationEmail(email: string): string {
return email.trim().toLowerCase()
}
/** Extrait l'email d'une clé stockée (legacy `accountId:email` ou email seul). */
export function destinationEmailFromStoredKey(key: string): string {
const trimmed = key.trim()
if (!trimmed) return trimmed
const at = trimmed.lastIndexOf("@")
if (at <= 0) return normalizeDestinationEmail(trimmed)
const colon = trimmed.lastIndexOf(":", at)
if (colon >= 0) return normalizeDestinationEmail(trimmed.slice(colon + 1))
return normalizeDestinationEmail(trimmed)
}
export type AgendaDestinationMailbox = {
/** Clé stable (email normalisé). */
key: string
/** Libellé affiché (casse d'origine). */
label: string
}
function addDestinationEmail(map: Map<string, string>, raw: string) {
const trimmed = raw.trim()
if (!trimmed || !trimmed.includes("@")) return
const key = normalizeDestinationEmail(trimmed)
if (!map.has(key)) map.set(key, trimmed)
}
/** Boîtes mail de destination uniques (comptes + identités), dédupliquées par email. */
export function buildDestinationMailboxes(
identities: Identity[],
accountEmails: string[] = [],
): AgendaDestinationMailbox[] {
const map = new Map<string, string>()
for (const email of accountEmails) addDestinationEmail(map, email)
for (const identity of identities) addDestinationEmail(map, identity.email)
return [...map.entries()]
.map(([key, label]) => ({ key, label }))
.sort((a, b) => a.label.localeCompare(b.label, "fr", { sensitivity: "base" }))
}
export function destinationMailboxLabel(
storedKey: string,
mailboxes: AgendaDestinationMailbox[],
): string {
const key = destinationEmailFromStoredKey(storedKey)
return mailboxes.find((m) => m.key === key)?.label ?? key
}
export function normalizeAutoImportDestinationKeys(keys: string[]): string[] {
return [...new Set(keys.map(destinationEmailFromStoredKey).filter(Boolean))]
}
export function normalizeAutoImportInvitationSources(
items: AgendaInvitationExclusion[],
mailboxes: AgendaDestinationMailbox[] = [],
): AgendaAutoImportSource[] {
const seen = new Set<string>()
const out: AgendaAutoImportSource[] = []
for (const item of items) {
if (item.type !== "identity" && item.type !== "contact") continue
let normalized: AgendaAutoImportSource
if (item.type === "identity") {
const value = destinationEmailFromStoredKey(item.value)
normalized = {
type: "identity",
value,
label: destinationMailboxLabel(value, mailboxes) || value,
}
} else {
const value = normalizeDestinationEmail(item.value)
if (!value) continue
normalized = {
type: "contact",
value,
label: item.label.trim() || value,
}
}
const id =
normalized.type === "identity"
? `identity:${normalized.value}`
: `contact:${normalized.value}`
if (seen.has(id)) continue
seen.add(id)
out.push(normalized)
}
return out
}
export function migrateAutoImportIdentityKeys(
keys: string[],
mailboxes: AgendaDestinationMailbox[] = [],
): AgendaAutoImportSource[] {
return normalizeAutoImportInvitationSources(
keys.map((key) => ({
type: "identity" as const,
value: destinationEmailFromStoredKey(key),
label: destinationEmailFromStoredKey(key),
})),
mailboxes,
)
}
export function normalizeInvitationImportExclusions(
items: AgendaInvitationExclusion[],
mailboxes: AgendaDestinationMailbox[] = [],
): AgendaInvitationExclusion[] {
const seen = new Set<string>()
const out: AgendaInvitationExclusion[] = []
for (const item of items) {
if (item.type !== "identity") {
out.push(item)
continue
}
const value = destinationEmailFromStoredKey(item.value)
const id = `identity:${value}`
if (seen.has(id)) continue
seen.add(id)
out.push({
type: "identity",
value,
label: destinationMailboxLabel(value, mailboxes) || value,
})
}
return out
}