Files
TREK/client/src/components/Settings/notificationLabels.ts
T
Maurice a7adef5353 feat(mail-ingest): admin card, review mark, inbox events and links, translations
- Admin settings (desktop and phone, self-hosted only): the instance switch,
  how mail arrives (IMAP or a signed webhook) with its fields, the address
  template, the AI allowance per person and day, a connection test and the
  status in counts. Changed fields only are saved; secrets stay masked.
- The review mark of an imported booking takes its mark off: the pill in the
  desktop dialog and a row in the phone's transport sheet ('Looks right'),
  through the ordinary booking update. Its hint no longer speaks of airports.
- The inbox follows mailInbox:changed and mailInbox:settings, and
  ?inbox=mail (the 'bookings waiting' notification) opens it.
- mailIngestRepo: the online-only path the views take, answers parsed
  against the shared contracts.
- Dropped 'read with AI' and the unused mail-review contract: the server
  reads a passing AI failure again on its own.
- mailInbox, mailAdmin and the new reservation, settings and notification
  strings in all 28 locales; the pending notice is a plural group.
- The live flight line on the booking cards is one of the card's fields,
  full width on the phone; the phone's live card keeps its map to the middle.
- Admin flight and mail cards sit in the left column.
2026-11-13 18:31:07 +01:00

50 lines
2.0 KiB
TypeScript

/**
* Labels for the notification matrix, shared by the desktop and phone settings
* and the admin's defaults for users (#1536), so the three can never name an
* event differently.
*/
export interface NotificationChannelDescriptor {
id: string
source?: 'builtin' | 'plugin'
labelKey?: string
label?: string
settingsPath?: string
active: boolean
configured: boolean
}
export const EVENT_LABEL_KEYS: Record<string, string> = {
trip_invite: 'settings.notifyTripInvite',
booking_change: 'settings.notifyBookingChange',
trip_reminder: 'settings.notifyTripReminder',
todo_due: 'settings.notifyTodoDue',
vacay_invite: 'settings.notifyVacayInvite',
vacay_share: 'settings.notifyVacayShare',
collection_invite: 'settings.notifyCollectionInvite',
synology_session_cleared: 'settings.notifySynologySessionCleared',
plugin_notification: 'settings.notifyPluginNotification',
photos_shared: 'settings.notifyPhotosShared',
collab_message: 'settings.notifyCollabMessage',
packing_tagged: 'settings.notifyPackingTagged',
wanderer_source_hint: 'settings.notifyWandererSourceHint',
version_available: 'settings.notifyVersionAvailable',
flight_departed: 'settings.notifyFlightDeparted',
flight_delayed: 'settings.notifyFlightDelayed',
flight_landed: 'settings.notifyFlightLanded',
mail_booking_added: 'settings.notifyMailBookingAdded',
mail_booking_pending: 'settings.notifyMailBookingPending',
mail_ingest_paused: 'settings.notifyMailIngestPaused',
}
/** Plugin channels have no i18n; the server sends their display name outright. */
export function channelLabel(ch: { id: string; labelKey?: string; label?: string }, t: (k: string) => string): string {
if (ch.labelKey) return t(ch.labelKey) || ch.id
return ch.label || ch.id
}
/** True when the admin switched this cell off for everyone (#1536). */
export function isLockedCell(locked: Record<string, string[]> | undefined, eventType: string, channel: string): boolean {
return !!locked?.[eventType]?.includes(channel)
}