campaign sending prototype
This commit is contained in:
46
webui/src/utils/datetime.ts
Normal file
46
webui/src/utils/datetime.ts
Normal 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
|
||||
});
|
||||
}
|
||||
@@ -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"
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user