campaign sending prototype

This commit is contained in:
2026-06-24 16:20:37 +02:00
parent 44516a03aa
commit ce30b4d054
17 changed files with 1233 additions and 14 deletions

View File

@@ -0,0 +1,46 @@
const HAS_TIMEZONE_OFFSET = /(?:Z|[+-]\d{2}:?\d{2})$/i;
function normalizeServerDateTime(value: string): string {
const trimmed = value.trim();
if (!trimmed) return trimmed;
return HAS_TIMEZONE_OFFSET.test(trimmed) ? trimmed : `${trimmed}Z`;
}
export function parseServerDateTime(value?: string | null): Date | null {
if (!value) return null;
const date = new Date(normalizeServerDateTime(value));
return Number.isNaN(date.getTime()) ? null : date;
}
export type FormatDateTimeOptions = Intl.DateTimeFormatOptions & {
fallback?: string;
};
export const defaultDateTimeFormatOptions: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "short",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
timeZoneName: "short"
};
export function formatDateTime(value?: string | null, options: FormatDateTimeOptions = {}): string {
const fallback = options.fallback ?? "—";
if (!value) return fallback;
const date = parseServerDateTime(value);
if (!date) return value;
const { fallback: _fallback, ...intlOptions } = options;
return date.toLocaleString(undefined, {
...defaultDateTimeFormatOptions,
...intlOptions
});
}
export function formatDateTimeFromDate(value: Date, options: FormatDateTimeOptions = {}): string {
const { fallback: _fallback, ...intlOptions } = options;
return value.toLocaleString(undefined, {
...defaultDateTimeFormatOptions,
...intlOptions
});
}

View File

@@ -6,7 +6,7 @@ const legacyTenantScopes = [
"recipients:read", "recipients:write", "recipients:import", "recipients:export",
"files:read", "files:download", "files:upload", "files:organize", "files:share", "files:delete", "files:admin",
"reports:read", "reports:export", "reports:send", "audit:read",
"mail_servers:read", "mail_servers:use", "mail_servers:test", "mail_servers:write", "mail_servers:manage_credentials",
"mail_servers:read", "mail_servers:use", "mail_servers:test", "mail_servers:mailbox_read", "mail_servers:write", "mail_servers:manage_credentials",
"admin:users:read", "admin:users:create", "admin:users:update", "admin:users:suspend",
"admin:groups:read", "admin:groups:write", "admin:groups:manage_members",
"admin:roles:read", "admin:roles:write", "admin:roles:assign",
@@ -48,6 +48,7 @@ const legacyToModuleScopes: Record<string, string> = {
"mail_servers:read": "mail:profile:read",
"mail_servers:use": "mail:profile:use",
"mail_servers:test": "mail:profile:test",
"mail_servers:mailbox_read": "mail:mailbox:read",
"mail_servers:write": "mail:profile:write",
"mail_servers:manage_credentials": "mail:secret:manage"
};