@memberjunction/ng-explorer-core 6.2.0-edge.5 → 6.2.0-edge.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +22 -4
- package/dist/app-routing.module.js.map +1 -1
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +16 -2
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +2 -2
- package/dist/lib/office/office-connect.component.d.ts +19 -0
- package/dist/lib/office/office-connect.component.d.ts.map +1 -0
- package/dist/lib/office/office-connect.component.js +80 -0
- package/dist/lib/office/office-connect.component.js.map +1 -0
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +7 -0
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +20 -8
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-class-resolution.d.ts +14 -0
- package/dist/lib/resource-wrappers/dashboard-class-resolution.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-class-resolution.js +21 -0
- package/dist/lib/resource-wrappers/dashboard-class-resolution.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +3 -2
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/record-form-mode.d.ts +44 -0
- package/dist/lib/resource-wrappers/record-form-mode.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/record-form-mode.js +47 -0
- package/dist/lib/resource-wrappers/record-form-mode.js.map +1 -0
- package/dist/lib/resource-wrappers/record-resource.component.d.ts +56 -1
- package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/record-resource.component.js +124 -9
- package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/standard-form-create.d.ts +4 -0
- package/dist/lib/resource-wrappers/standard-form-create.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/standard-form-create.js +6 -0
- package/dist/lib/resource-wrappers/standard-form-create.js.map +1 -0
- package/dist/lib/resource-wrappers/view-resource.component.d.ts +18 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.js +105 -39
- package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.js +2 -2
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.d.ts.map +1 -1
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.js +12 -8
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +6 -0
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +18 -3
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +2 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +38 -10
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell-chrome-policy.d.ts +6 -0
- package/dist/lib/shell/shell-chrome-policy.d.ts.map +1 -1
- package/dist/lib/shell/shell-chrome-policy.js +1 -0
- package/dist/lib/shell/shell-chrome-policy.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +23 -0
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +283 -71
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +2 -2
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/lib/single-record/single-record.component.d.ts +27 -2
- package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
- package/dist/lib/single-record/single-record.component.js +54 -8
- package/dist/lib/single-record/single-record.component.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.d.ts +24 -2
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +139 -24
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/lib/user-profile/user-profile.component.js +2 -2
- package/dist/module.d.ts +64 -63
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +3 -0
- package/dist/module.js.map +1 -1
- package/package.json +58 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-notifications.component.js","sourceRoot":"","sources":["../../../src/lib/user-notifications/user-notifications.component.ts","../../../src/lib/user-notifications/user-notifications.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, OnDestroy, OnInit, AfterViewInit, inject } from '@angular/core';\nimport { SharedService, NavigationService } from '@memberjunction/ng-shared';\nimport { MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { CompositeKey, TransactionGroupBase } from '@memberjunction/core';\nimport { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ApplicationManager, NavItem } from '@memberjunction/ng-base-application';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Radio button filter options for notification read status\n */\ntype ReadFilterOption = 'All' | 'Unread' | 'Read';\n\n/** How a notification's Message should be rendered. */\ntype MessageKind = 'html' | 'markdown' | 'text';\n\n/**\n * Render-ready view model for one notification. Built once per data/filter change\n * (never inside template bindings): the Message is classified (full HTML document /\n * HTML fragment / Markdown / plain text), reduced to a sanitary body + plain-text\n * preview, and the time-relative label is SNAPSHOT here — computing relative time in\n * the template throws NG0100 at minute boundaries.\n */\ninterface NotificationVM {\n N: MJUserNotificationEntity;\n Kind: MessageKind;\n /** Rich body: extracted+stripped HTML fragment (html) or the raw message (markdown). Empty for plain text. */\n Body: string;\n /** Plain-text excerpt for the collapsed card. */\n Preview: string;\n /** True when there is more to see than the collapsed preview. */\n Expandable: boolean;\n /** Snapshot \"2h ago\" label (refreshed on a timer, never computed in the template). */\n Relative: string;\n Clickable: boolean;\n}\n\n/** One day-bucket of notifications (\"Today\", \"Yesterday\", ...). */\ninterface NotificationGroup {\n Key: string;\n Label: string;\n Items: NotificationVM[];\n}\n\n/**\n * Configuration for record-type resource navigation\n */\ninterface RecordResourceConfig {\n Entity?: string;\n}\n\n/**\n * Configuration for conversation-type resource navigation\n */\ninterface ConversationResourceConfig {\n type: 'conversation';\n conversationId?: string;\n messageId?: string;\n artifactId?: string;\n versionNumber?: string;\n taskId?: string;\n}\n\n/**\n * Configuration for agent-request-type resource navigation\n */\ninterface AgentRequestResourceConfig {\n type: 'agent-request';\n requestId: string;\n}\n\n/**\n * Result of parsing a notification URL\n */\ninterface NotificationUrlInfo {\n urlParts: string[];\n queryString: string;\n}\n\n/** Collapsed-preview cap (characters of plain text). */\nconst PREVIEW_MAX_CHARS = 240;\n\n/** How often the snapshot relative-time labels refresh. */\nconst RELATIVE_REFRESH_MS = 60_000;\n\n@Component({\n standalone: false,\n selector: 'app-user-notifications',\n templateUrl: './user-notifications.component.html',\n styleUrls: ['./user-notifications.component.css']\n})\nexport class UserNotificationsComponent extends BaseAngularComponent implements OnInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n public RadioSelected: ReadFilterOption = 'All';\n\n /** @deprecated Use {@link RadioSelected}. */\n public get radioSelected(): ReadFilterOption {\n return this.RadioSelected;\n }\n /** @deprecated Use {@link RadioSelected}. */\n public set radioSelected(value: ReadFilterOption) {\n this.RadioSelected = value;\n }\n public CurrentFilter: string = '';\n\n /** @deprecated Use {@link CurrentFilter}. */\n public get currentFilter(): string {\n return this.CurrentFilter;\n }\n /** @deprecated Use {@link CurrentFilter}. */\n public set currentFilter(value: string) {\n this.CurrentFilter = value;\n }\n public NotificationTypes: MJUserNotificationTypeEntity[] = [];\n\n /** @deprecated Use {@link NotificationTypes}. */\n public get notificationTypes(): MJUserNotificationTypeEntity[] {\n return this.NotificationTypes;\n }\n /** @deprecated Use {@link NotificationTypes}. */\n public set notificationTypes(value: MJUserNotificationTypeEntity[]) {\n this.NotificationTypes = value;\n }\n public SelectedTypeFilter: string | null = null;\n\n /** @deprecated Use {@link SelectedTypeFilter}. */\n public get selectedTypeFilter(): string | null {\n return this.SelectedTypeFilter;\n }\n /** @deprecated Use {@link SelectedTypeFilter}. */\n public set selectedTypeFilter(value: string | null) {\n this.SelectedTypeFilter = value;\n }\n public LoadingTypes: boolean = true;\n\n /** @deprecated Use {@link LoadingTypes}. */\n public get loadingTypes(): boolean {\n return this.LoadingTypes;\n }\n /** @deprecated Use {@link LoadingTypes}. */\n public set loadingTypes(value: boolean) {\n this.LoadingTypes = value;\n }\n\n /** IDs of cards currently expanded to their full rendered content. */\n public Expanded = new Set<string>();\n\n private groups: NotificationGroup[] = [];\n private groupsKey = '';\n private vmCache = new Map<string, NotificationVM>();\n private relativeTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor (\n public SharedService: SharedService,\n private navigationService: NavigationService,\n private appManager: ApplicationManager\n ) {\n super();\n }\n\n /** @deprecated Use {@link SharedService}. */\n public get sharedService(): SharedService {\n return this.SharedService;\n }\n /** @deprecated Use {@link SharedService}. */\n public set sharedService(value: SharedService) {\n this.SharedService = value;\n }\n\n async ngOnInit() {\n this.loadNotificationTypes();\n // Refresh the snapshot relative-time labels between change-detection passes.\n this.relativeTimer = setInterval(() => {\n for (const vm of this.vmCache.values()) {\n vm.Relative = this.relativeTime(vm.N.__mj_CreatedAt);\n }\n this.groupsKey = ''; // day buckets can shift at midnight\n this.cdr.markForCheck();\n }, RELATIVE_REFRESH_MS);\n }\n\n ngAfterViewInit(): void {\n this.SharedService.InvokeManualResize(); // make sure the notifications component is sized correctly\n }\n\n ngOnDestroy(): void {\n if (this.relativeTimer != null) {\n clearInterval(this.relativeTimer);\n }\n }\n\n private loadNotificationTypes() {\n // Get notification types from UserInfoEngine cache, sorted client-side\n // UserInfoEngine is auto-configured via @RegisterForStartup()\n this.NotificationTypes = [...UserInfoEngine.Instance.NotificationTypes].sort((a, b) => {\n const priorityA = a.Priority ?? 999;\n const priorityB = b.Priority ?? 999;\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n return a.Name.localeCompare(b.Name);\n });\n this.LoadingTypes = false;\n }\n\n // ========================================================================\n // Data shaping (filter → view models → day groups)\n // ========================================================================\n\n public get NotificationsToShow(): MJUserNotificationEntity[] {\n let temp: MJUserNotificationEntity[] = [];\n switch (this.RadioSelected) {\n case 'All':\n temp = this.AllNotifications;\n break;\n case 'Unread':\n temp = this.AllNotifications.filter(n => n.Unread);\n break;\n case 'Read':\n temp = this.AllNotifications.filter(n => !n.Unread);\n break;\n }\n\n // Apply type filter if selected\n if (this.SelectedTypeFilter) {\n temp = temp.filter(n => UUIDsEqual(n.NotificationTypeID, this.SelectedTypeFilter));\n }\n\n // Apply text filter if it is not empty\n if (this.CurrentFilter.trim().length > 0) {\n // check for inclusion of filter value in title or message\n temp = temp.filter(n => n.Title?.toLowerCase().includes(this.CurrentFilter.trim().toLowerCase()) ||\n n.Message?.toLowerCase().includes(this.CurrentFilter.trim().toLowerCase())\n );\n }\n\n return temp;\n }\n\n /**\n * The filtered notifications as render-ready day groups. Memoized on a composite\n * key of the inputs so the getter stays cheap across change-detection passes and\n * the (time-sensitive) VM snapshots never rebuild mid-pass.\n */\n public get Groups(): NotificationGroup[] {\n const list = this.NotificationsToShow;\n const unread = list.filter(n => n.Unread).length;\n const key = `${list.length}|${unread}|${this.RadioSelected}|${this.SelectedTypeFilter}|${this.CurrentFilter}|${list[0]?.ID ?? ''}|${list[list.length - 1]?.ID ?? ''}`;\n if (key !== this.groupsKey) {\n this.groups = this.buildGroups(list);\n this.groupsKey = key;\n }\n return this.groups;\n }\n\n private buildGroups(list: MJUserNotificationEntity[]): NotificationGroup[] {\n const groups: NotificationGroup[] = [];\n let current: NotificationGroup | null = null;\n for (const n of list) {\n const label = this.dayLabel(n.__mj_CreatedAt);\n if (!current || current.Label !== label) {\n current = { Key: `${label}-${n.ID}`, Label: label, Items: [] };\n groups.push(current);\n }\n current.Items.push(this.vmFor(n));\n }\n return groups;\n }\n\n private vmFor(n: MJUserNotificationEntity): NotificationVM {\n const cached = this.vmCache.get(n.ID);\n if (cached) {\n cached.N = n;\n cached.Clickable = this.IsNotificationClickable(n);\n return cached;\n }\n const { kind, body, preview, expandable } = this.classifyMessage(n.Message ?? '');\n const vm: NotificationVM = {\n N: n,\n Kind: kind,\n Body: body,\n Preview: preview,\n Expandable: expandable,\n Relative: this.relativeTime(n.__mj_CreatedAt),\n Clickable: this.IsNotificationClickable(n),\n };\n this.vmCache.set(n.ID, vm);\n return vm;\n }\n\n /**\n * Classifies a notification Message for rendering:\n * - Full HTML documents (e.g. templated email bodies) and HTML fragments →\n * parsed with DOMParser, chrome elements (style/script/link/meta/title) removed,\n * and the body markup kept for a SANITIZED [innerHTML] binding (Angular's\n * default sanitizer strips scripts/event handlers on bind).\n * - Markdown-looking text → rendered through mj-markdown when expanded.\n * - Everything else → plain text.\n */\n private classifyMessage(message: string): { kind: MessageKind; body: string; preview: string; expandable: boolean } {\n const trimmed = (message ?? '').trim();\n const looksHtml = /^<!doctype\\s|^<html[\\s>]/i.test(trimmed) || /<\\/?[a-z][^>]*>/i.test(trimmed);\n if (looksHtml) {\n const doc = new DOMParser().parseFromString(trimmed, 'text/html');\n for (const el of Array.from(doc.querySelectorAll('style, script, link, meta, title'))) {\n el.remove();\n }\n const body = doc.body?.innerHTML?.trim() ?? '';\n const text = this.collapseWhitespace(doc.body?.textContent ?? '');\n return { kind: 'html', body, preview: this.excerpt(text), expandable: true };\n }\n const looksMarkdown = /(^|\\n)#{1,6}\\s|\\*\\*[^*]+\\*\\*|(^|\\n)\\s*[-*]\\s+|\\[[^\\]]+\\]\\([^)]+\\)|```/m.test(trimmed);\n const text = this.collapseWhitespace(trimmed);\n if (looksMarkdown) {\n return { kind: 'markdown', body: trimmed, preview: this.excerpt(this.stripMarkdown(text)), expandable: true };\n }\n return { kind: 'text', body: '', preview: text, expandable: text.length > PREVIEW_MAX_CHARS };\n }\n\n private collapseWhitespace(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n }\n\n private excerpt(text: string): string {\n return text.length > PREVIEW_MAX_CHARS ? `${text.substring(0, PREVIEW_MAX_CHARS - 1)}…` : text;\n }\n\n /** Light de-noising of markdown syntax for the plain-text preview. */\n private stripMarkdown(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, ' ')\n .replace(/[#*_`>]+/g, '')\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\s+/g, ' ')\n .trim();\n }\n\n /** Compact \"just now / 5m ago / 3h ago / 2d ago\" label. NEVER call from templates (NG0100) — snapshot only. */\n private relativeTime(value: Date | string | null | undefined): string {\n if (!value) {\n return '';\n }\n const ms = Date.now() - new Date(value).getTime();\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : '';\n }\n\n private dayLabel(value: Date | string | null | undefined): string {\n if (!value) {\n return 'Earlier';\n }\n const d = new Date(value);\n const now = new Date();\n const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const diffDays = Math.round((startOfDay(now) - startOfDay(d)) / 86_400_000);\n if (diffDays <= 0) return 'Today';\n if (diffDays === 1) return 'Yesterday';\n if (diffDays < 7) return 'This Week';\n return 'Earlier';\n }\n\n // ========================================================================\n // Expand / collapse\n // ========================================================================\n\n public IsExpanded(vm: NotificationVM): boolean {\n return this.Expanded.has(vm.N.ID);\n }\n\n public ToggleExpanded(vm: NotificationVM, event: Event): void {\n event.stopPropagation();\n if (this.Expanded.has(vm.N.ID)) {\n this.Expanded.delete(vm.N.ID);\n } else {\n this.Expanded.add(vm.N.ID);\n // Reading the full content is reading — mark it as such.\n if (vm.N.Unread) {\n void this.MarkAsRead(vm.N, true, null);\n }\n }\n this.cdr.markForCheck();\n }\n\n // ========================================================================\n // Clickability + navigation (unchanged behavior)\n // ========================================================================\n\n public IsNotificationClickable(notification: MJUserNotificationEntity): boolean {\n // Check for special types navigated via NavigationService (not a URL)\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (config && config.type?.trim().toLowerCase() === 'agent-request' && config.requestId) {\n return true;\n }\n const typeName = SafeJSONParse<{ type?: string }>(notification.ResourceConfiguration)?.type?.trim().toLowerCase();\n if (typeName === 'meet-room') {\n return true;\n }\n }\n\n const info = this.NotificationUrl(notification);\n return (info !== null && info.urlParts && info.urlParts.length > 0);\n }\n\n /** @deprecated Use {@link IsNotificationClickable}. */\n public isNotificationClickable(notification: MJUserNotificationEntity): boolean {\n return this.IsNotificationClickable(notification);\n }\n\n public NotificationUrl(notification: MJUserNotificationEntity): NotificationUrlInfo {\n const url: string[] = [];\n let queryString = '';\n if (notification.ResourceRecordID && notification.ResourceRecordID.length > 0 &&\n notification.ResourceTypeID && notification.ResourceTypeID.length > 0) {\n // we have a resource here, like a Report, Dashboard, etc\n // we can generate a url to navigate to it\n const rt = this.SharedService.ResourceTypeByID(notification.ResourceTypeID);\n let routeSegment: string | null | undefined;\n if (rt)\n routeSegment = this.SharedService.mapResourceTypeNameToRouteSegment(rt.Name);\n\n if (rt && routeSegment && routeSegment.trim().length > 0) {\n url.push('resource');\n url.push(routeSegment);\n url.push(notification.ResourceRecordID.toString());\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n if (rt.Name.trim().toLowerCase() === 'records') {\n // special handling for records\n const config = SafeJSONParse<RecordResourceConfig>(notification.ResourceConfiguration);\n if (config && config.Entity)\n queryString = `Entity=${config.Entity}`;\n }\n else\n queryString = notification.ResourceConfiguration;\n }\n }\n }\n else if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n // we do NOT have a resource type or resource record id, but we do have a ResourceConfiguration\n // string, which means we might have information on how to navigate to what we want if we parse the config\n // HOME screen stuff is done this way\n\n const config = SafeJSONParse<ConversationResourceConfig>(notification.ResourceConfiguration);\n if (config && config.type?.trim().toLowerCase() === 'conversation') {\n url.push('chat');\n // Build query string with conversation and artifact navigation\n const queryParams: string[] = [];\n if (config.conversationId) queryParams.push(`conversationId=${config.conversationId}`);\n if (config.messageId) queryParams.push(`messageId=${config.messageId}`);\n if (config.artifactId) queryParams.push(`artifactId=${config.artifactId}`);\n if (config.versionNumber) queryParams.push(`versionNumber=${config.versionNumber}`);\n if (config.taskId) queryParams.push(`taskId=${config.taskId}`);\n queryString = queryParams.join('&');\n }\n }\n\n return { urlParts: url, queryString };\n }\n\n /** @deprecated Use {@link NotificationUrl}. */\n public notificationUrl(notification: MJUserNotificationEntity): NotificationUrlInfo {\n return this.NotificationUrl(notification);\n }\n\n public get AllNotifications(): MJUserNotificationEntity[] {\n return SharedService.UserNotifications;\n }\n\n public get UnreadNotifications(): MJUserNotificationEntity[] {\n return this.AllNotifications.filter(n => n.Unread);\n }\n\n public get ReadNotifications(): MJUserNotificationEntity[] {\n return this.AllNotifications.filter(n => !n.Unread);\n }\n\n SelectReadOption(option: ReadFilterOption): void {\n this.RadioSelected = option;\n }\n\n /** @deprecated Use {@link SelectReadOption}. */\n selectReadOption(option: ReadFilterOption): void {\n return this.SelectReadOption(option);\n }\n\n OnFilterChanged(value: string): void {\n this.CurrentFilter = value;\n }\n\n /** @deprecated Use {@link OnFilterChanged}. */\n onFilterChanged(value: string): void {\n return this.OnFilterChanged(value);\n }\n\n async MarkAsRead(notification: MJUserNotificationEntity, bRead: boolean, transGroup: TransactionGroupBase | null): Promise<boolean> {\n if (notification) {\n const notificationId = notification.ID;\n notification.Unread = !bRead;\n let notificationEntity: MJUserNotificationEntity;\n if (notification instanceof MJUserNotificationEntity) {\n // the passed in param truly is a MJUserNotificationEntity or subclass, so just use it, saves a DB round trip\n notificationEntity = notification;\n }\n else {\n // the passed in param is just a plain object, so we need to load the entity\n const md = this.ProviderToUse;\n notificationEntity = await md.GetEntityObject<MJUserNotificationEntity>('MJ: User Notifications');\n await notificationEntity.Load(notificationId);\n notificationEntity.Unread = !bRead;\n }\n\n // part of a transaction group, if so, add it as that will defer the actual network traffic/save\n if (transGroup) {\n notificationEntity.TransactionGroup = transGroup;\n await notificationEntity.Save()\n return true;\n }\n else {\n // Save the notification (not part of transaction group)\n await notificationEntity.Save();\n // Update the observables so badge count refreshes immediately\n MJNotificationService.UpdateNotificationObservables();\n return true;\n }\n }\n else {\n return false;\n }\n }\n\n /** @deprecated Use {@link MarkAsRead}. */\n async markAsRead(notification: MJUserNotificationEntity, bRead: boolean, transGroup: TransactionGroupBase | null): Promise<boolean> {\n return this.MarkAsRead(notification, bRead, transGroup);\n }\n\n public async MarkAllAsRead() {\n await this.MarkAll(true);\n }\n\n /** @deprecated Use {@link MarkAllAsRead}. */\n public async markAllAsRead() {\n return this.MarkAllAsRead();\n }\n\n public async MarkAllAsUnread() {\n await this.MarkAll(false);\n }\n\n /** @deprecated Use {@link MarkAllAsUnread}. */\n public async markAllAsUnread() {\n return this.MarkAllAsUnread();\n }\n\n public async MarkAll(bRead: boolean) {\n // Use transaction group for batching - all saves are queued and sent in one round-trip\n const md = this.ProviderToUse;\n const transGroup = await md.CreateTransactionGroup();\n\n // Queue all saves - no need to await individual saves since transaction group queues them\n for (const notification of this.AllNotifications) {\n if (notification.Unread && bRead || !notification.Unread && !bRead) {\n // Don't await - Save() with transaction group queues the operation immediately\n this.MarkAsRead(notification, bRead, transGroup);\n }\n }\n\n // Submit transaction group - this is where the actual network call happens\n if (!await transGroup.Submit())\n this.SharedService.CreateSimpleNotification('Unable to mark all notifications as read', 'error', 5000);\n else\n SharedService.RefreshUserNotifications();\n }\n\n /** @deprecated Use {@link MarkAll}. */\n public async markAll(bRead: boolean) {\n return this.MarkAll(bRead);\n }\n\n NotificationClicked(notification: MJUserNotificationEntity): void {\n if (this.IsNotificationClickable(notification)) {\n // also mark this as read when we click it\n this.MarkAsRead(notification, true, null);\n\n // Check for special navigation types that use NavigationService (not router)\n if (this.navigateToAgentRequest(notification)) {\n return;\n }\n if (this.navigateToConversation(notification)) {\n return;\n }\n if (this.navigateToMeetRoom(notification)) {\n return;\n }\n if (this.navigateToHandoffConsole(notification)) {\n return;\n }\n if (this.navigateToMeeting(notification)) {\n return;\n }\n\n this.navigateToResource(notification);\n }\n }\n\n /** @deprecated Use {@link NotificationClicked}. */\n notificationClicked(notification: MJUserNotificationEntity): void {\n return this.NotificationClicked(notification);\n }\n\n /**\n * Opens the Meet app's Live Room in JOIN mode for a `meet-room` invite notification (the\n * `{ type:'meet-room', room }` ResourceConfiguration), mirroring {@link navigateToConversation}.\n * Returns `false` (not handled) when the config isn't a meet-room invite or the Meet app is absent.\n */\n private navigateToMeetRoom(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n const config = SafeJSONParse<{ type?: string; room?: string }>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'meet-room') {\n return false;\n }\n const meetApp = this.appManager.GetAppByName('Meet');\n if (!meetApp) {\n return false;\n }\n const navConfig: Record<string, string> = {};\n if (config.room) {\n navConfig['room'] = config.room;\n }\n this.navigationService.OpenNavItemByName('Live Room', navConfig, meetApp.ID);\n return true;\n }\n\n /**\n * Opens the Conversation Console for a `handoff-offer` notification (the `{ type:'handoff-offer', offerId, room }`\n * ResourceConfiguration the server sends when an AI agent offers a conversation to this person). The nav item is built here\n * rather than looked up, so it works without an application metadata row; it lands in the Meet app when present, otherwise\n * in whichever app the person is in. Returns `false` (not handled) for any other notification or when there is no app to host it.\n */\n private navigateToHandoffConsole(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n const config = SafeJSONParse<{ type?: string; offerId?: string }>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'handoff-offer') {\n return false;\n }\n const app = this.appManager.GetAppByName('Meet') ?? this.appManager.GetActiveApp();\n if (!app) {\n return false;\n }\n const consoleItem: NavItem = {\n Label: 'Conversation Console',\n Icon: 'fa-solid fa-headset',\n ResourceType: 'Custom',\n DriverClass: 'HumanHandoffConsoleResource',\n Configuration: config.offerId ? { offer: config.offerId } : {},\n };\n this.navigationService.OpenNavItem(app.ID, consoleItem, app.GetColor());\n return true;\n }\n\n /**\n * Opens the Meet app's Meetings resource for a `meeting` or `meeting-invitation` notification (the\n * `{ type:'meeting', meetingId }` ResourceConfiguration), or when NotificationType is 'Meeting Invitation'.\n * Returns `false` (not handled) when the config isn't a meeting invite or the Meet app is absent.\n */\n private navigateToMeeting(notification: MJUserNotificationEntity): boolean {\n let meetingId: string | undefined;\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n const config = SafeJSONParse<{ type?: string; meetingId?: string }>(notification.ResourceConfiguration);\n if (\n config &&\n (config.type?.trim().toLowerCase() === 'meeting' ||\n config.type?.trim().toLowerCase() === 'meeting-invitation')\n ) {\n meetingId = config.meetingId;\n }\n }\n const typeName = notification.NotificationType?.trim();\n if (!meetingId && typeName !== 'Meeting Invitation') {\n return false;\n }\n const app = this.appManager.GetAppByName('Meet') ?? this.appManager.GetActiveApp();\n if (!app) {\n return false;\n }\n const meetingItem: NavItem = {\n Label: 'Meetings',\n Icon: 'fa-solid fa-users',\n ResourceType: 'Custom',\n DriverClass: 'MeetingsResource',\n Configuration: meetingId ? { meeting: meetingId } : {},\n };\n this.navigationService.OpenNavItem(app.ID, meetingItem, app.GetColor());\n return true;\n }\n\n /**\n * Navigate to a resource-based notification using NavigationService methods.\n * Routes to the correct resource based on the notification's ResourceType.\n */\n private navigateToResource(notification: MJUserNotificationEntity): void {\n if (!notification.ResourceRecordID || !notification.ResourceTypeID) return;\n\n const rt = this.SharedService.ResourceTypeByID(notification.ResourceTypeID);\n if (!rt) return;\n\n const recordId = notification.ResourceRecordID.toString();\n const rtName = rt.Name.trim().toLowerCase();\n\n switch (rtName) {\n case 'records': {\n const config = SafeJSONParse<RecordResourceConfig>(notification.ResourceConfiguration || '');\n if (config?.Entity) {\n const key = new CompositeKey();\n key.SimpleLoadFromURLSegment(recordId);\n this.navigationService.OpenEntityRecord(config.Entity, key);\n }\n break;\n }\n case 'user views':\n case 'mj: user views':\n this.navigationService.OpenView(recordId, 'View');\n break;\n case 'dashboards':\n this.navigationService.OpenDashboard(recordId, 'Dashboard');\n break;\n default:\n console.warn(`[UserNotifications] Unhandled resource type for navigation: ${rt.Name}`);\n break;\n }\n }\n\n /**\n * Handle navigation to an agent request via NavigationService.\n * Returns true if the notification was an agent-request type and navigation was attempted.\n */\n private navigateToAgentRequest(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'agent-request' || !config.requestId) {\n return false;\n }\n\n // Try the AI app first (has dedicated Agent Requests nav item)\n const aiApp = this.appManager.GetAppByName('AI');\n if (aiApp) {\n this.navigationService.OpenNavItemByName(\n 'Agent Requests',\n { requestId: config.requestId },\n aiApp.ID\n );\n return true;\n }\n\n // Fallback: navigate to Chat app's Conversations with the request context\n const chatApp = this.appManager.GetAppByName('Chat');\n if (chatApp) {\n this.navigationService.OpenNavItemByName(\n 'Conversations',\n { requestId: config.requestId },\n chatApp.ID\n );\n return true;\n }\n\n return false;\n }\n\n /**\n * Handle navigation to a conversation via NavigationService.\n * Returns true if the notification was a conversation type and navigation was attempted.\n */\n private navigateToConversation(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n\n const config = SafeJSONParse<ConversationResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'conversation') {\n return false;\n }\n\n const chatApp = this.appManager.GetAppByName('Chat');\n if (!chatApp) {\n return false;\n }\n\n const navConfig: Record<string, string> = {};\n if (config.conversationId) navConfig['conversationId'] = config.conversationId;\n if (config.messageId) navConfig['messageId'] = config.messageId;\n if (config.artifactId) navConfig['artifactId'] = config.artifactId;\n if (config.versionNumber) navConfig['versionNumber'] = config.versionNumber;\n if (config.taskId) navConfig['taskId'] = config.taskId;\n\n this.navigationService.OpenNavItemByName(\n 'Conversations',\n navConfig,\n chatApp.ID\n );\n return true;\n }\n\n public GetNotificationType(typeId: string | null): MJUserNotificationTypeEntity | null {\n if (!typeId) return null;\n return this.NotificationTypes.find(t => UUIDsEqual(t.ID, typeId)) || null;\n }\n\n /** @deprecated Use {@link GetNotificationType}. */\n public getNotificationType(typeId: string | null): MJUserNotificationTypeEntity | null {\n return this.GetNotificationType(typeId);\n }\n\n public GetTypeIcon(notification: MJUserNotificationEntity): string {\n const type = this.GetNotificationType(notification.NotificationTypeID);\n return type?.Icon || 'fa-bell';\n }\n\n /** @deprecated Use {@link GetTypeIcon}. */\n public getTypeIcon(notification: MJUserNotificationEntity): string {\n return this.GetTypeIcon(notification);\n }\n\n public GetTypeColor(notification: MJUserNotificationEntity): string {\n const type = this.GetNotificationType(notification.NotificationTypeID);\n return type?.Color || 'var(--mj-text-muted)';\n }\n\n /** @deprecated Use {@link GetTypeColor}. */\n public getTypeColor(notification: MJUserNotificationEntity): string {\n return this.GetTypeColor(notification);\n }\n\n public GetTypeName(notification: MJUserNotificationEntity): string {\n const type = this.GetNotificationType(notification.NotificationTypeID);\n return type ? type.Name : 'Notification';\n }\n\n /** @deprecated Use {@link GetTypeName}. */\n public getTypeName(notification: MJUserNotificationEntity): string {\n return this.GetTypeName(notification);\n }\n\n public OnTypeFilterChange(typeId: string | null): void {\n this.SelectedTypeFilter = typeId;\n }\n\n /** @deprecated Use {@link OnTypeFilterChange}. */\n public onTypeFilterChange(typeId: string | null): void {\n return this.OnTypeFilterChange(typeId);\n }\n}\n","<div class=\"notifications-container\">\n <!-- Header Section -->\n <div class=\"notifications-header\">\n <div class=\"header-top\">\n <div class=\"header-title\">\n <div class=\"title-icon\">\n <i class=\"fa-solid fa-bell\"></i>\n </div>\n <div class=\"title-text\">\n <h1>Notifications</h1>\n @if (UnreadNotifications.length > 0) {\n <span class=\"title-subtitle\">{{UnreadNotifications.length}} unread</span>\n } @else if (AllNotifications.length > 0) {\n <span class=\"title-subtitle\">All caught up</span>\n }\n </div>\n </div>\n\n @if (AllNotifications.length > 0) {\n <div class=\"header-actions\">\n @if (UnreadNotifications.length > 0) {\n <button class=\"action-btn action-btn-ghost\"\n type=\"button\"\n (click)=\"markAllAsRead()\"\n aria-label=\"Mark all notifications as read\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Read</span>\n </button>\n }\n @if (ReadNotifications.length > 0) {\n <button class=\"action-btn action-btn-secondary\"\n type=\"button\"\n (click)=\"markAllAsUnread()\"\n aria-label=\"Mark all notifications as unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Unread</span>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Filters Section -->\n @if (AllNotifications.length > 0) {\n <div class=\"filters-section\">\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Read-status pills -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'All'\"\n (click)=\"selectReadOption('All')\"\n [attr.aria-pressed]=\"radioSelected === 'All'\"\n aria-label=\"Show all notifications\">\n <span class=\"stat-label\">All</span>\n <span class=\"stat-count\">{{AllNotifications.length}}</span>\n </button>\n\n @if (UnreadNotifications.length > 0 || ReadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Unread'\"\n [class.has-unread]=\"UnreadNotifications.length > 0\"\n (click)=\"selectReadOption('Unread')\"\n [attr.aria-pressed]=\"radioSelected === 'Unread'\"\n aria-label=\"Show unread notifications\">\n <span class=\"stat-label\">Unread</span>\n <span class=\"stat-count\" [class.unread-count]=\"UnreadNotifications.length > 0\">\n {{UnreadNotifications.length}}\n </span>\n </button>\n }\n\n @if (ReadNotifications.length > 0 || UnreadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Read'\"\n (click)=\"selectReadOption('Read')\"\n [attr.aria-pressed]=\"radioSelected === 'Read'\"\n aria-label=\"Show read notifications\">\n <span class=\"stat-label\">Read</span>\n <span class=\"stat-count\">{{ReadNotifications.length}}</span>\n </button>\n }\n </div>\n\n <!-- Type filter -->\n @if (notificationTypes.length > 0) {\n <div class=\"filter-item type-filter-slider\">\n <select class=\"type-select\"\n [(ngModel)]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange(selectedTypeFilter)\"\n aria-label=\"Filter by notification type\">\n <option [value]=\"null\">All Types</option>\n @for (type of notificationTypes; track type.ID) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n </div>\n }\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-section\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search notifications...\"\n [value]=\"currentFilter\"\n (input)=\"onFilterChanged($any($event.target).value)\"\n aria-label=\"Search notifications\" />\n </div>\n </div>\n\n @if (NotificationsToShow.length !== AllNotifications.length) {\n <div class=\"filter-info\">\n <span class=\"filter-badge\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Showing {{NotificationsToShow.length}} of {{AllNotifications.length}}\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Notifications Content -->\n <div class=\"notifications-content\">\n @if (NotificationsToShow.length === 0 && AllNotifications.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Icon=\"fa-solid fa-bell-slash\"\n Title=\"No Notifications\"\n Message=\"You're all caught up! New notifications will appear here.\" />\n } @else if (NotificationsToShow.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-filter-circle-xmark\"\n Title=\"No Matching Notifications\"\n Message=\"Try adjusting your filters to see more notifications.\" />\n } @else {\n <!-- Day-grouped notification list -->\n <div class=\"notifications-list\">\n @for (group of Groups; track group.Key) {\n <div class=\"group-label\">{{group.Label}}</div>\n\n @for (vm of group.Items; track vm.N.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"vm.N.Unread\"\n [class.expanded]=\"IsExpanded(vm)\"\n [class.clickable]=\"vm.Clickable\"\n role=\"article\"\n [attr.aria-label]=\"vm.N.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.N)\"\n [style.color]=\"getTypeColor(vm.N)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(vm.N)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"vm.N.Unread\">\n {{vm.N.Title}}\n </h3>\n <span class=\"card-time\" [title]=\"(vm.N.__mj_CreatedAt | date:'medium') ?? ''\">\n @if (vm.Relative) {\n {{vm.Relative}}\n } @else {\n <time [attr.datetime]=\"vm.N.__mj_CreatedAt\">{{vm.N.__mj_CreatedAt | date:'MMM d, h:mm a'}}</time>\n }\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\">{{getTypeName(vm.N)}}</span>\n @if (vm.Clickable) {\n <span class=\"card-open-hint\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i> Open\n </span>\n }\n </div>\n\n @if (!IsExpanded(vm)) {\n <p class=\"card-message\">{{vm.Preview}}</p>\n } @else {\n <div class=\"card-rich\" (click)=\"$event.stopPropagation()\">\n @switch (vm.Kind) {\n @case ('html') {\n <!-- Angular sanitizes on [innerHTML] bind; chrome tags were stripped at classification -->\n <div class=\"card-rich-html\" [innerHTML]=\"vm.Body\"></div>\n }\n @case ('markdown') {\n <mj-markdown class=\"card-rich-md\" [data]=\"vm.Body\" [enableMermaid]=\"false\"></mj-markdown>\n }\n @default {\n <p class=\"card-message card-message-full\">{{vm.N.Message}}</p>\n }\n }\n </div>\n }\n\n @if (vm.Expandable) {\n <button class=\"card-expand-btn\" type=\"button\"\n (click)=\"ToggleExpanded(vm, $event)\"\n [attr.aria-expanded]=\"IsExpanded(vm)\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!IsExpanded(vm)\" [class.fa-chevron-up]=\"IsExpanded(vm)\" aria-hidden=\"true\"></i>\n {{ IsExpanded(vm) ? 'Show less' : 'Show more' }}\n </button>\n }\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (vm.N.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, true, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as read'\"\n title=\"Mark as Read\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Read</span>\n </button>\n } @else {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, false, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as unread'\"\n title=\"Mark as Unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Unread</span>\n </button>\n }\n </div>\n </article>\n }\n }\n </div>\n }\n </div>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"user-notifications.component.js","sourceRoot":"","sources":["../../../src/lib/user-notifications/user-notifications.component.ts","../../../src/lib/user-notifications/user-notifications.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, NgZone, OnDestroy, OnInit, AfterViewInit, inject } from '@angular/core';\nimport { SharedService, NavigationService } from '@memberjunction/ng-shared';\nimport { MJUserNotificationEntity, MJUserNotificationTypeEntity, MJUserRoutineEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { CompositeKey, TransactionGroupBase } from '@memberjunction/core';\nimport { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ApplicationManager, NavItem } from '@memberjunction/ng-base-application';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Radio button filter options for notification read status\n */\ntype ReadFilterOption = 'All' | 'Unread' | 'Read';\n\n/** How a notification's Message should be rendered. */\ntype MessageKind = 'html' | 'markdown' | 'text';\n\n/**\n * Render-ready view model for one notification. Built once per data/filter change\n * (never inside template bindings): the Message is classified (full HTML document /\n * HTML fragment / Markdown / plain text), reduced to a sanitary body + plain-text\n * preview, and the time-relative label is SNAPSHOT here — computing relative time in\n * the template throws NG0100 at minute boundaries.\n */\ninterface NotificationVM {\n N: MJUserNotificationEntity;\n Kind: MessageKind;\n /** Rich body: extracted+stripped HTML fragment (html) or the raw message (markdown). Empty for plain text. */\n Body: string;\n /** Plain-text excerpt for the collapsed card. */\n Preview: string;\n /** True when there is more to see than the collapsed preview. */\n Expandable: boolean;\n /** Snapshot \"2h ago\" label (refreshed on a timer, never computed in the template). */\n Relative: string;\n Clickable: boolean;\n}\n\n/** One day-bucket of notifications (\"Today\", \"Yesterday\", ...). */\ninterface NotificationGroup {\n Key: string;\n Label: string;\n Items: NotificationVM[];\n}\n\n/**\n * Configuration for record-type resource navigation\n */\ninterface RecordResourceConfig {\n Entity?: string;\n}\n\n/**\n * Configuration for conversation-type resource navigation\n */\ninterface ConversationResourceConfig {\n type: 'conversation';\n conversationId?: string;\n messageId?: string;\n artifactId?: string;\n versionNumber?: string;\n taskId?: string;\n}\n\n/**\n * Configuration for agent-request-type resource navigation\n */\ninterface AgentRequestResourceConfig {\n type: 'agent-request';\n requestId: string;\n}\n\n/**\n * Configuration written by the User Routine dispatcher for a routine run. `conversationId` is\n * the routine's own conversation, where the run's reply lives; older notifications lack it.\n */\ninterface UserRoutineResourceConfig {\n type: 'UserRoutine';\n routineId: string;\n runId?: string;\n conversationId?: string;\n}\n\n/**\n * Result of parsing a notification URL\n */\ninterface NotificationUrlInfo {\n urlParts: string[];\n queryString: string;\n}\n\n/** Collapsed-preview cap (characters of plain text). */\nconst PREVIEW_MAX_CHARS = 240;\n\n/** How often the snapshot relative-time labels refresh. */\nconst RELATIVE_REFRESH_MS = 60_000;\n\n@Component({\n standalone: false,\n selector: 'app-user-notifications',\n templateUrl: './user-notifications.component.html',\n styleUrls: ['./user-notifications.component.css']\n})\nexport class UserNotificationsComponent extends BaseAngularComponent implements OnInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone, { optional: true });\n\n public RadioSelected: ReadFilterOption = 'All';\n\n /** @deprecated Use {@link RadioSelected}. */\n public get radioSelected(): ReadFilterOption {\n return this.RadioSelected;\n }\n /** @deprecated Use {@link RadioSelected}. */\n public set radioSelected(value: ReadFilterOption) {\n this.RadioSelected = value;\n }\n public CurrentFilter: string = '';\n\n /** @deprecated Use {@link CurrentFilter}. */\n public get currentFilter(): string {\n return this.CurrentFilter;\n }\n /** @deprecated Use {@link CurrentFilter}. */\n public set currentFilter(value: string) {\n this.CurrentFilter = value;\n }\n public NotificationTypes: MJUserNotificationTypeEntity[] = [];\n\n /** @deprecated Use {@link NotificationTypes}. */\n public get notificationTypes(): MJUserNotificationTypeEntity[] {\n return this.NotificationTypes;\n }\n /** @deprecated Use {@link NotificationTypes}. */\n public set notificationTypes(value: MJUserNotificationTypeEntity[]) {\n this.NotificationTypes = value;\n }\n public SelectedTypeFilter: string | null = null;\n\n /** @deprecated Use {@link SelectedTypeFilter}. */\n public get selectedTypeFilter(): string | null {\n return this.SelectedTypeFilter;\n }\n /** @deprecated Use {@link SelectedTypeFilter}. */\n public set selectedTypeFilter(value: string | null) {\n this.SelectedTypeFilter = value;\n }\n public LoadingTypes: boolean = true;\n\n /** @deprecated Use {@link LoadingTypes}. */\n public get loadingTypes(): boolean {\n return this.LoadingTypes;\n }\n /** @deprecated Use {@link LoadingTypes}. */\n public set loadingTypes(value: boolean) {\n this.LoadingTypes = value;\n }\n\n /** IDs of cards currently expanded to their full rendered content. */\n public Expanded = new Set<string>();\n\n private groups: NotificationGroup[] = [];\n private groupsKey = '';\n private vmCache = new Map<string, NotificationVM>();\n private relativeTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor (\n public SharedService: SharedService,\n private navigationService: NavigationService,\n private appManager: ApplicationManager\n ) {\n super();\n }\n\n /** @deprecated Use {@link SharedService}. */\n public get sharedService(): SharedService {\n return this.SharedService;\n }\n /** @deprecated Use {@link SharedService}. */\n public set sharedService(value: SharedService) {\n this.SharedService = value;\n }\n\n async ngOnInit() {\n this.loadNotificationTypes();\n // Refresh the snapshot relative-time labels between change-detection passes.\n // Run outside NgZone so the 60s timer only triggers Angular CD when a label actually changes.\n const startTimer = () => {\n this.relativeTimer = setInterval(() => {\n let anyChanged = false;\n for (const vm of this.vmCache.values()) {\n const next = this.relativeTime(vm.N.__mj_CreatedAt);\n if (vm.Relative !== next) {\n vm.Relative = next;\n anyChanged = true;\n }\n }\n this.groupsKey = ''; // day buckets can shift at midnight\n if (anyChanged) {\n if (this.ngZone) {\n this.ngZone.run(() => this.cdr.markForCheck());\n } else {\n this.cdr.markForCheck();\n }\n }\n }, RELATIVE_REFRESH_MS);\n };\n if (this.ngZone) {\n this.ngZone.runOutsideAngular(startTimer);\n } else {\n startTimer();\n }\n }\n\n ngAfterViewInit(): void {\n this.SharedService.InvokeManualResize(); // make sure the notifications component is sized correctly\n }\n\n ngOnDestroy(): void {\n if (this.relativeTimer != null) {\n clearInterval(this.relativeTimer);\n }\n }\n\n private loadNotificationTypes() {\n // Get notification types from UserInfoEngine cache, sorted client-side\n // UserInfoEngine is auto-configured via @RegisterForStartup()\n this.NotificationTypes = [...UserInfoEngine.Instance.NotificationTypes].sort((a, b) => {\n const priorityA = a.Priority ?? 999;\n const priorityB = b.Priority ?? 999;\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n return a.Name.localeCompare(b.Name);\n });\n this.LoadingTypes = false;\n }\n\n // ========================================================================\n // Data shaping (filter → view models → day groups)\n // ========================================================================\n\n private notificationsToShowCache: MJUserNotificationEntity[] = [];\n private notificationsToShowKey = '';\n private unreadNotificationsCache: MJUserNotificationEntity[] = [];\n private unreadNotificationsKey = '';\n private readNotificationsCache: MJUserNotificationEntity[] = [];\n private readNotificationsKey = '';\n\n private computeAllNotificationsSignature(): { all: MJUserNotificationEntity[]; unreadCount: number; baseKey: string } {\n const all = this.AllNotifications;\n let unreadCount = 0;\n for (let i = 0; i < all.length; i++) {\n if (all[i].Unread) unreadCount++;\n }\n const baseKey = `${all.length}|${unreadCount}|${all[0]?.ID ?? ''}|${all[all.length - 1]?.ID ?? ''}`;\n return { all, unreadCount, baseKey };\n }\n\n public get NotificationsToShow(): MJUserNotificationEntity[] {\n const { all, baseKey } = this.computeAllNotificationsSignature();\n const key = `${baseKey}|${this.RadioSelected}|${this.SelectedTypeFilter ?? ''}|${this.CurrentFilter}`;\n if (key === this.notificationsToShowKey) {\n return this.notificationsToShowCache;\n }\n\n let temp: MJUserNotificationEntity[] = [];\n switch (this.RadioSelected) {\n case 'All':\n temp = all;\n break;\n case 'Unread':\n temp = all.filter(n => n.Unread);\n break;\n case 'Read':\n temp = all.filter(n => !n.Unread);\n break;\n }\n\n // Apply type filter if selected\n if (this.SelectedTypeFilter) {\n temp = temp.filter(n => UUIDsEqual(n.NotificationTypeID, this.SelectedTypeFilter));\n }\n\n // Apply text filter if it is not empty\n const filterLower = this.CurrentFilter.trim().toLowerCase();\n if (filterLower.length > 0) {\n // check for inclusion of filter value in title or message\n temp = temp.filter(n => n.Title?.toLowerCase().includes(filterLower) ||\n n.Message?.toLowerCase().includes(filterLower)\n );\n }\n\n this.notificationsToShowKey = key;\n this.notificationsToShowCache = temp;\n return temp;\n }\n\n /**\n * The filtered notifications as render-ready day groups. Memoized on a composite\n * key of the inputs BEFORE filtering `AllNotifications`, so the getter stays $O(1)$\n * across change-detection passes and the (time-sensitive) VM snapshots never rebuild mid-pass.\n */\n public get Groups(): NotificationGroup[] {\n const { baseKey } = this.computeAllNotificationsSignature();\n const key = `${baseKey}|${this.RadioSelected}|${this.SelectedTypeFilter ?? ''}|${this.CurrentFilter}`;\n if (key !== this.groupsKey) {\n this.groups = this.buildGroups(this.NotificationsToShow);\n this.groupsKey = key;\n }\n return this.groups;\n }\n\n private buildGroups(list: MJUserNotificationEntity[]): NotificationGroup[] {\n const groups: NotificationGroup[] = [];\n let current: NotificationGroup | null = null;\n for (const n of list) {\n const label = this.dayLabel(n.__mj_CreatedAt);\n if (!current || current.Label !== label) {\n current = { Key: `${label}-${n.ID}`, Label: label, Items: [] };\n groups.push(current);\n }\n current.Items.push(this.vmFor(n));\n }\n return groups;\n }\n\n private vmFor(n: MJUserNotificationEntity): NotificationVM {\n const cached = this.vmCache.get(n.ID);\n if (cached) {\n cached.N = n;\n cached.Clickable = this.IsNotificationClickable(n);\n return cached;\n }\n const { kind, body, preview, expandable } = this.classifyMessage(n.Message ?? '');\n const vm: NotificationVM = {\n N: n,\n Kind: kind,\n Body: body,\n Preview: preview,\n Expandable: expandable,\n Relative: this.relativeTime(n.__mj_CreatedAt),\n Clickable: this.IsNotificationClickable(n),\n };\n this.vmCache.set(n.ID, vm);\n return vm;\n }\n\n /**\n * Classifies a notification Message for rendering:\n * - Full HTML documents (e.g. templated email bodies) and HTML fragments →\n * parsed with DOMParser, chrome elements (style/script/link/meta/title) removed,\n * and the body markup kept for a SANITIZED [innerHTML] binding (Angular's\n * default sanitizer strips scripts/event handlers on bind).\n * - Markdown-looking text → rendered through mj-markdown when expanded.\n * - Everything else → plain text.\n */\n private classifyMessage(message: string): { kind: MessageKind; body: string; preview: string; expandable: boolean } {\n const trimmed = (message ?? '').trim();\n const looksHtml = /^<!doctype\\s|^<html[\\s>]/i.test(trimmed) || /<\\/?[a-z][^>]*>/i.test(trimmed);\n if (looksHtml) {\n const doc = new DOMParser().parseFromString(trimmed, 'text/html');\n for (const el of Array.from(doc.querySelectorAll('style, script, link, meta, title'))) {\n el.remove();\n }\n const body = doc.body?.innerHTML?.trim() ?? '';\n const text = this.collapseWhitespace(doc.body?.textContent ?? '');\n return { kind: 'html', body, preview: this.excerpt(text), expandable: true };\n }\n const looksMarkdown = /(^|\\n)#{1,6}\\s|\\*\\*[^*]+\\*\\*|(^|\\n)\\s*[-*]\\s+|\\[[^\\]]+\\]\\([^)]+\\)|```/m.test(trimmed);\n const text = this.collapseWhitespace(trimmed);\n if (looksMarkdown) {\n return { kind: 'markdown', body: trimmed, preview: this.excerpt(this.stripMarkdown(text)), expandable: true };\n }\n return { kind: 'text', body: '', preview: text, expandable: text.length > PREVIEW_MAX_CHARS };\n }\n\n private collapseWhitespace(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n }\n\n private excerpt(text: string): string {\n return text.length > PREVIEW_MAX_CHARS ? `${text.substring(0, PREVIEW_MAX_CHARS - 1)}…` : text;\n }\n\n /** Light de-noising of markdown syntax for the plain-text preview. */\n private stripMarkdown(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, ' ')\n .replace(/[#*_`>]+/g, '')\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\s+/g, ' ')\n .trim();\n }\n\n /** Compact \"just now / 5m ago / 3h ago / 2d ago\" label. NEVER call from templates (NG0100) — snapshot only. */\n private relativeTime(value: Date | string | null | undefined): string {\n if (!value) {\n return '';\n }\n const ms = Date.now() - new Date(value).getTime();\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : '';\n }\n\n private dayLabel(value: Date | string | null | undefined): string {\n if (!value) {\n return 'Earlier';\n }\n const d = new Date(value);\n const now = new Date();\n const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const diffDays = Math.round((startOfDay(now) - startOfDay(d)) / 86_400_000);\n if (diffDays <= 0) return 'Today';\n if (diffDays === 1) return 'Yesterday';\n if (diffDays < 7) return 'This Week';\n return 'Earlier';\n }\n\n // ========================================================================\n // Expand / collapse\n // ========================================================================\n\n public IsExpanded(vm: NotificationVM): boolean {\n return this.Expanded.has(vm.N.ID);\n }\n\n public ToggleExpanded(vm: NotificationVM, event: Event): void {\n event.stopPropagation();\n if (this.Expanded.has(vm.N.ID)) {\n this.Expanded.delete(vm.N.ID);\n } else {\n this.Expanded.add(vm.N.ID);\n // Reading the full content is reading — mark it as such.\n if (vm.N.Unread) {\n void this.MarkAsRead(vm.N, true, null);\n }\n }\n this.cdr.markForCheck();\n }\n\n // ========================================================================\n // Clickability + navigation (unchanged behavior)\n // ========================================================================\n\n public IsNotificationClickable(notification: MJUserNotificationEntity): boolean {\n // Check for special types navigated via NavigationService (not a URL)\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (config && config.type?.trim().toLowerCase() === 'agent-request' && config.requestId) {\n return true;\n }\n const typeName = SafeJSONParse<{ type?: string }>(notification.ResourceConfiguration)?.type?.trim().toLowerCase();\n if (typeName === 'meet-room') {\n return true;\n }\n if (this.parseUserRoutineConfig(notification)) {\n return true;\n }\n }\n\n const info = this.NotificationUrl(notification);\n return (info !== null && info.urlParts && info.urlParts.length > 0);\n }\n\n /** @deprecated Use {@link IsNotificationClickable}. */\n public isNotificationClickable(notification: MJUserNotificationEntity): boolean {\n return this.IsNotificationClickable(notification);\n }\n\n public NotificationUrl(notification: MJUserNotificationEntity): NotificationUrlInfo {\n const url: string[] = [];\n let queryString = '';\n if (notification.ResourceRecordID && notification.ResourceRecordID.length > 0 &&\n notification.ResourceTypeID && notification.ResourceTypeID.length > 0) {\n // we have a resource here, like a Report, Dashboard, etc\n // we can generate a url to navigate to it\n const rt = this.SharedService.ResourceTypeByID(notification.ResourceTypeID);\n let routeSegment: string | null | undefined;\n if (rt)\n routeSegment = this.SharedService.mapResourceTypeNameToRouteSegment(rt.Name);\n\n if (rt && routeSegment && routeSegment.trim().length > 0) {\n url.push('resource');\n url.push(routeSegment);\n url.push(notification.ResourceRecordID.toString());\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n if (rt.Name.trim().toLowerCase() === 'records') {\n // special handling for records\n const config = SafeJSONParse<RecordResourceConfig>(notification.ResourceConfiguration);\n if (config && config.Entity)\n queryString = `Entity=${config.Entity}`;\n }\n else\n queryString = notification.ResourceConfiguration;\n }\n }\n }\n else if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n // we do NOT have a resource type or resource record id, but we do have a ResourceConfiguration\n // string, which means we might have information on how to navigate to what we want if we parse the config\n // HOME screen stuff is done this way\n\n const config = SafeJSONParse<ConversationResourceConfig>(notification.ResourceConfiguration);\n if (config && config.type?.trim().toLowerCase() === 'conversation') {\n url.push('chat');\n // Build query string with conversation and artifact navigation\n const queryParams: string[] = [];\n if (config.conversationId) queryParams.push(`conversationId=${config.conversationId}`);\n if (config.messageId) queryParams.push(`messageId=${config.messageId}`);\n if (config.artifactId) queryParams.push(`artifactId=${config.artifactId}`);\n if (config.versionNumber) queryParams.push(`versionNumber=${config.versionNumber}`);\n if (config.taskId) queryParams.push(`taskId=${config.taskId}`);\n queryString = queryParams.join('&');\n }\n }\n\n return { urlParts: url, queryString };\n }\n\n /** @deprecated Use {@link NotificationUrl}. */\n public notificationUrl(notification: MJUserNotificationEntity): NotificationUrlInfo {\n return this.NotificationUrl(notification);\n }\n\n public get AllNotifications(): MJUserNotificationEntity[] {\n return SharedService.UserNotifications;\n }\n\n public get UnreadNotifications(): MJUserNotificationEntity[] {\n const { all, baseKey } = this.computeAllNotificationsSignature();\n if (baseKey !== this.unreadNotificationsKey) {\n this.unreadNotificationsKey = baseKey;\n this.unreadNotificationsCache = all.filter(n => n.Unread);\n }\n return this.unreadNotificationsCache;\n }\n\n public get ReadNotifications(): MJUserNotificationEntity[] {\n const { all, baseKey } = this.computeAllNotificationsSignature();\n if (baseKey !== this.readNotificationsKey) {\n this.readNotificationsKey = baseKey;\n this.readNotificationsCache = all.filter(n => !n.Unread);\n }\n return this.readNotificationsCache;\n }\n\n SelectReadOption(option: ReadFilterOption): void {\n this.RadioSelected = option;\n }\n\n /** @deprecated Use {@link SelectReadOption}. */\n selectReadOption(option: ReadFilterOption): void {\n return this.SelectReadOption(option);\n }\n\n OnFilterChanged(value: string): void {\n this.CurrentFilter = value;\n }\n\n /** @deprecated Use {@link OnFilterChanged}. */\n onFilterChanged(value: string): void {\n return this.OnFilterChanged(value);\n }\n\n async MarkAsRead(notification: MJUserNotificationEntity, bRead: boolean, transGroup: TransactionGroupBase | null): Promise<boolean> {\n if (notification) {\n const notificationId = notification.ID;\n notification.Unread = !bRead;\n let notificationEntity: MJUserNotificationEntity;\n if (notification instanceof MJUserNotificationEntity) {\n // the passed in param truly is a MJUserNotificationEntity or subclass, so just use it, saves a DB round trip\n notificationEntity = notification;\n }\n else {\n // the passed in param is just a plain object, so we need to load the entity\n const md = this.ProviderToUse;\n notificationEntity = await md.GetEntityObject<MJUserNotificationEntity>('MJ: User Notifications');\n await notificationEntity.Load(notificationId);\n notificationEntity.Unread = !bRead;\n }\n\n // part of a transaction group, if so, add it as that will defer the actual network traffic/save\n if (transGroup) {\n notificationEntity.TransactionGroup = transGroup;\n await notificationEntity.Save()\n return true;\n }\n else {\n // Save the notification (not part of transaction group)\n await notificationEntity.Save();\n // Update the observables so badge count refreshes immediately\n MJNotificationService.UpdateNotificationObservables();\n return true;\n }\n }\n else {\n return false;\n }\n }\n\n /** @deprecated Use {@link MarkAsRead}. */\n async markAsRead(notification: MJUserNotificationEntity, bRead: boolean, transGroup: TransactionGroupBase | null): Promise<boolean> {\n return this.MarkAsRead(notification, bRead, transGroup);\n }\n\n public async MarkAllAsRead() {\n await this.MarkAll(true);\n }\n\n /** @deprecated Use {@link MarkAllAsRead}. */\n public async markAllAsRead() {\n return this.MarkAllAsRead();\n }\n\n public async MarkAllAsUnread() {\n await this.MarkAll(false);\n }\n\n /** @deprecated Use {@link MarkAllAsUnread}. */\n public async markAllAsUnread() {\n return this.MarkAllAsUnread();\n }\n\n public async MarkAll(bRead: boolean) {\n // Use transaction group for batching - all saves are queued and sent in one round-trip\n const md = this.ProviderToUse;\n const transGroup = await md.CreateTransactionGroup();\n\n // Queue all saves - no need to await individual saves since transaction group queues them\n for (const notification of this.AllNotifications) {\n if (notification.Unread && bRead || !notification.Unread && !bRead) {\n // Don't await - Save() with transaction group queues the operation immediately\n this.MarkAsRead(notification, bRead, transGroup);\n }\n }\n\n // Submit transaction group - this is where the actual network call happens\n if (!await transGroup.Submit())\n this.SharedService.CreateSimpleNotification('Unable to mark all notifications as read', 'error', 5000);\n else\n SharedService.RefreshUserNotifications();\n }\n\n /** @deprecated Use {@link MarkAll}. */\n public async markAll(bRead: boolean) {\n return this.MarkAll(bRead);\n }\n\n NotificationClicked(notification: MJUserNotificationEntity): void {\n if (this.IsNotificationClickable(notification)) {\n // also mark this as read when we click it\n this.MarkAsRead(notification, true, null);\n\n // Check for special navigation types that use NavigationService (not router)\n if (this.navigateToAgentRequest(notification)) {\n return;\n }\n if (this.navigateToConversation(notification)) {\n return;\n }\n if (this.navigateToMeetRoom(notification)) {\n return;\n }\n if (this.navigateToUserRoutine(notification)) {\n return;\n }\n if (this.navigateToHandoffConsole(notification)) {\n return;\n }\n if (this.navigateToMeeting(notification)) {\n return;\n }\n\n this.navigateToResource(notification);\n }\n }\n\n /** @deprecated Use {@link NotificationClicked}. */\n notificationClicked(notification: MJUserNotificationEntity): void {\n return this.NotificationClicked(notification);\n }\n\n /**\n * Opens the Meet app's Live Room in JOIN mode for a `meet-room` invite notification (the\n * `{ type:'meet-room', room }` ResourceConfiguration), mirroring {@link navigateToConversation}.\n * Returns `false` (not handled) when the config isn't a meet-room invite or the Meet app is absent.\n */\n private navigateToMeetRoom(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n const config = SafeJSONParse<{ type?: string; room?: string }>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'meet-room') {\n return false;\n }\n const meetApp = this.appManager.GetAppByName('Meet');\n if (!meetApp) {\n return false;\n }\n const navConfig: Record<string, string> = {};\n if (config.room) {\n navConfig['room'] = config.room;\n }\n this.navigationService.OpenNavItemByName('Live Room', navConfig, meetApp.ID);\n return true;\n }\n\n /**\n * Opens the Conversation Console for a `handoff-offer` notification (the `{ type:'handoff-offer', offerId, room }`\n * ResourceConfiguration the server sends when an AI agent offers a conversation to this person). The nav item is built here\n * rather than looked up, so it works without an application metadata row; it lands in the Meet app when present, otherwise\n * in whichever app the person is in. Returns `false` (not handled) for any other notification or when there is no app to host it.\n */\n private navigateToHandoffConsole(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n const config = SafeJSONParse<{ type?: string; offerId?: string }>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'handoff-offer') {\n return false;\n }\n const app = this.appManager.GetAppByName('Meet') ?? this.appManager.GetActiveApp();\n if (!app) {\n return false;\n }\n const consoleItem: NavItem = {\n Label: 'Conversation Console',\n Icon: 'fa-solid fa-headset',\n ResourceType: 'Custom',\n DriverClass: 'HumanHandoffConsoleResource',\n Configuration: config.offerId ? { offer: config.offerId } : {},\n };\n this.navigationService.OpenNavItem(app.ID, consoleItem, app.GetColor());\n return true;\n }\n\n /**\n * Opens the Meet app's Meetings resource for a `meeting` or `meeting-invitation` notification (the\n * `{ type:'meeting', meetingId }` ResourceConfiguration), or when NotificationType is 'Meeting Invitation'.\n * Returns `false` (not handled) when the config isn't a meeting invite or the Meet app is absent.\n */\n private navigateToMeeting(notification: MJUserNotificationEntity): boolean {\n let meetingId: string | undefined;\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n const config = SafeJSONParse<{ type?: string; meetingId?: string }>(notification.ResourceConfiguration);\n if (\n config &&\n (config.type?.trim().toLowerCase() === 'meeting' ||\n config.type?.trim().toLowerCase() === 'meeting-invitation')\n ) {\n meetingId = config.meetingId;\n }\n }\n const typeName = notification.NotificationType?.trim();\n if (!meetingId && typeName !== 'Meeting Invitation') {\n return false;\n }\n const app = this.appManager.GetAppByName('Meet') ?? this.appManager.GetActiveApp();\n if (!app) {\n return false;\n }\n const meetingItem: NavItem = {\n Label: 'Meetings',\n Icon: 'fa-solid fa-users',\n ResourceType: 'Custom',\n DriverClass: 'MeetingsResource',\n Configuration: meetingId ? { meeting: meetingId } : {},\n };\n this.navigationService.OpenNavItem(app.ID, meetingItem, app.GetColor());\n return true;\n }\n\n /**\n * Navigate to a resource-based notification using NavigationService methods.\n * Routes to the correct resource based on the notification's ResourceType.\n */\n private navigateToResource(notification: MJUserNotificationEntity): void {\n if (!notification.ResourceRecordID || !notification.ResourceTypeID) return;\n\n const rt = this.SharedService.ResourceTypeByID(notification.ResourceTypeID);\n if (!rt) return;\n\n const recordId = notification.ResourceRecordID.toString();\n const rtName = rt.Name.trim().toLowerCase();\n\n switch (rtName) {\n case 'records': {\n const config = SafeJSONParse<RecordResourceConfig>(notification.ResourceConfiguration || '');\n if (config?.Entity) {\n const key = new CompositeKey();\n key.SimpleLoadFromURLSegment(recordId);\n this.navigationService.OpenEntityRecord(config.Entity, key);\n }\n break;\n }\n case 'user views':\n case 'mj: user views':\n this.navigationService.OpenView(recordId, 'View');\n break;\n case 'dashboards':\n this.navigationService.OpenDashboard(recordId, 'Dashboard');\n break;\n default:\n console.warn(`[UserNotifications] Unhandled resource type for navigation: ${rt.Name}`);\n break;\n }\n }\n\n /**\n * Handle navigation to an agent request via NavigationService.\n * Returns true if the notification was an agent-request type and navigation was attempted.\n */\n private navigateToAgentRequest(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'agent-request' || !config.requestId) {\n return false;\n }\n\n // Try the AI app first (has dedicated Agent Requests nav item)\n const aiApp = this.appManager.GetAppByName('AI');\n if (aiApp) {\n this.navigationService.OpenNavItemByName(\n 'Agent Requests',\n { requestId: config.requestId },\n aiApp.ID\n );\n return true;\n }\n\n // Fallback: navigate to Chat app's Conversations with the request context\n const chatApp = this.appManager.GetAppByName('Chat');\n if (chatApp) {\n this.navigationService.OpenNavItemByName(\n 'Conversations',\n { requestId: config.requestId },\n chatApp.ID\n );\n return true;\n }\n\n return false;\n }\n\n /**\n * Handle navigation to a conversation via NavigationService.\n * Returns true if the notification was a conversation type and navigation was attempted.\n */\n private navigateToConversation(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n\n const config = SafeJSONParse<ConversationResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'conversation') {\n return false;\n }\n\n const chatApp = this.appManager.GetAppByName('Chat');\n if (!chatApp) {\n return false;\n }\n\n const navConfig: Record<string, string> = {};\n if (config.conversationId) navConfig['conversationId'] = config.conversationId;\n if (config.messageId) navConfig['messageId'] = config.messageId;\n if (config.artifactId) navConfig['artifactId'] = config.artifactId;\n if (config.versionNumber) navConfig['versionNumber'] = config.versionNumber;\n if (config.taskId) navConfig['taskId'] = config.taskId;\n\n // The Chat tab is usually already open and gets reused; a reused tab reads its configuration\n // only at init, so the same values go in the query params, which it does react to.\n this.navigationService.OpenNavItemByName(\n 'Conversations',\n navConfig,\n chatApp.ID,\n { queryParams: { ...navConfig } }\n );\n return true;\n }\n\n /** The routine-run config of a notification, or null when it is not one (or names no routine). */\n private parseUserRoutineConfig(notification: MJUserNotificationEntity): UserRoutineResourceConfig | null {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return null;\n }\n const config = SafeJSONParse<UserRoutineResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'userroutine' || !config.routineId) {\n return null;\n }\n return config;\n }\n\n /**\n * Opens what a routine run produced: its reply, in the routine's own conversation (the\n * `{ type:'UserRoutine', routineId, runId, conversationId? }` ResourceConfiguration). That\n * conversation is application-scoped, so the chat sidebar never lists it; the click deep-links\n * into the Chat app's Conversations item. A notification written before the config carried the\n * conversation reads it off the routine; a routine with no conversation opens in the Routines\n * app. Returns false (not handled) when the notification is not a routine run.\n */\n private navigateToUserRoutine(notification: MJUserNotificationEntity): boolean {\n const config = this.parseUserRoutineConfig(notification);\n if (!config) {\n return false;\n }\n void this.openUserRoutineOutput(config);\n return true;\n }\n\n private async openUserRoutineOutput(config: UserRoutineResourceConfig): Promise<void> {\n const conversationId = config.conversationId ?? await this.loadRoutineConversationId(config.routineId);\n const chatApp = conversationId ? this.appManager.GetAppByName('Chat') : null;\n if (conversationId && chatApp) {\n // Query params as well as configuration: an already-open Chat tab is reused and reacts\n // only to a query-param change (its configuration is read once, at init).\n await this.navigationService.OpenNavItemByName('Conversations', { conversationId }, chatApp.ID, { queryParams: { conversationId } });\n return;\n }\n const routinesApp = this.appManager.GetAppByName('Routines');\n if (routinesApp) {\n await this.navigationService.OpenNavItemByName('My Routines', { routine: config.routineId }, routinesApp.ID);\n return;\n }\n MJNotificationService.Instance.CreateSimpleNotification('The Routines app is not installed, so this routine cannot be opened', 'error', 4000);\n }\n\n /** The routine's ConversationID, or null when the routine cannot be read or has none. */\n private async loadRoutineConversationId(routineId: string): Promise<string | null> {\n const p = this.ProviderToUse;\n const routine = await p.GetEntityObject<MJUserRoutineEntity>('MJ: User Routines', p.CurrentUser);\n if (!await routine.Load(routineId)) {\n return null;\n }\n return routine.ConversationID ?? null;\n }\n\n public GetNotificationType(typeId: string | null): MJUserNotificationTypeEntity | null {\n if (!typeId) return null;\n return this.NotificationTypes.find(t => UUIDsEqual(t.ID, typeId)) || null;\n }\n\n /** @deprecated Use {@link GetNotificationType}. */\n public getNotificationType(typeId: string | null): MJUserNotificationTypeEntity | null {\n return this.GetNotificationType(typeId);\n }\n\n public GetTypeIcon(notification: MJUserNotificationEntity): string {\n const type = this.GetNotificationType(notification.NotificationTypeID);\n return type?.Icon || 'fa-bell';\n }\n\n /** @deprecated Use {@link GetTypeIcon}. */\n public getTypeIcon(notification: MJUserNotificationEntity): string {\n return this.GetTypeIcon(notification);\n }\n\n public GetTypeColor(notification: MJUserNotificationEntity): string {\n const type = this.GetNotificationType(notification.NotificationTypeID);\n return type?.Color || 'var(--mj-text-muted)';\n }\n\n /** @deprecated Use {@link GetTypeColor}. */\n public getTypeColor(notification: MJUserNotificationEntity): string {\n return this.GetTypeColor(notification);\n }\n\n public GetTypeName(notification: MJUserNotificationEntity): string {\n const type = this.GetNotificationType(notification.NotificationTypeID);\n return type ? type.Name : 'Notification';\n }\n\n /** @deprecated Use {@link GetTypeName}. */\n public getTypeName(notification: MJUserNotificationEntity): string {\n return this.GetTypeName(notification);\n }\n\n public OnTypeFilterChange(typeId: string | null): void {\n this.SelectedTypeFilter = typeId;\n }\n\n /** @deprecated Use {@link OnTypeFilterChange}. */\n public onTypeFilterChange(typeId: string | null): void {\n return this.OnTypeFilterChange(typeId);\n }\n}\n","<div class=\"notifications-container\">\n <!-- Header Section -->\n <div class=\"notifications-header\">\n <div class=\"header-top\">\n <div class=\"header-title\">\n <div class=\"title-icon\">\n <i class=\"fa-solid fa-bell\"></i>\n </div>\n <div class=\"title-text\">\n <h1>Notifications</h1>\n @if (UnreadNotifications.length > 0) {\n <span class=\"title-subtitle\">{{UnreadNotifications.length}} unread</span>\n } @else if (AllNotifications.length > 0) {\n <span class=\"title-subtitle\">All caught up</span>\n }\n </div>\n </div>\n\n @if (AllNotifications.length > 0) {\n <div class=\"header-actions\">\n @if (UnreadNotifications.length > 0) {\n <button class=\"action-btn action-btn-ghost\"\n type=\"button\"\n (click)=\"markAllAsRead()\"\n aria-label=\"Mark all notifications as read\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Read</span>\n </button>\n }\n @if (ReadNotifications.length > 0) {\n <button class=\"action-btn action-btn-secondary\"\n type=\"button\"\n (click)=\"markAllAsUnread()\"\n aria-label=\"Mark all notifications as unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Unread</span>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Filters Section -->\n @if (AllNotifications.length > 0) {\n <div class=\"filters-section\">\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Read-status pills -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'All'\"\n (click)=\"selectReadOption('All')\"\n [attr.aria-pressed]=\"radioSelected === 'All'\"\n aria-label=\"Show all notifications\">\n <span class=\"stat-label\">All</span>\n <span class=\"stat-count\">{{AllNotifications.length}}</span>\n </button>\n\n @if (UnreadNotifications.length > 0 || ReadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Unread'\"\n [class.has-unread]=\"UnreadNotifications.length > 0\"\n (click)=\"selectReadOption('Unread')\"\n [attr.aria-pressed]=\"radioSelected === 'Unread'\"\n aria-label=\"Show unread notifications\">\n <span class=\"stat-label\">Unread</span>\n <span class=\"stat-count\" [class.unread-count]=\"UnreadNotifications.length > 0\">\n {{UnreadNotifications.length}}\n </span>\n </button>\n }\n\n @if (ReadNotifications.length > 0 || UnreadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Read'\"\n (click)=\"selectReadOption('Read')\"\n [attr.aria-pressed]=\"radioSelected === 'Read'\"\n aria-label=\"Show read notifications\">\n <span class=\"stat-label\">Read</span>\n <span class=\"stat-count\">{{ReadNotifications.length}}</span>\n </button>\n }\n </div>\n\n <!-- Type filter -->\n @if (notificationTypes.length > 0) {\n <div class=\"filter-item type-filter-slider\">\n <select class=\"type-select\"\n [(ngModel)]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange(selectedTypeFilter)\"\n aria-label=\"Filter by notification type\">\n <option [value]=\"null\">All Types</option>\n @for (type of notificationTypes; track type.ID) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n </div>\n }\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-section\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search notifications...\"\n [value]=\"currentFilter\"\n (input)=\"onFilterChanged($any($event.target).value)\"\n aria-label=\"Search notifications\" />\n </div>\n </div>\n\n @if (NotificationsToShow.length !== AllNotifications.length) {\n <div class=\"filter-info\">\n <span class=\"filter-badge\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Showing {{NotificationsToShow.length}} of {{AllNotifications.length}}\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Notifications Content -->\n <div class=\"notifications-content\">\n @if (NotificationsToShow.length === 0 && AllNotifications.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Icon=\"fa-solid fa-bell-slash\"\n Title=\"No Notifications\"\n Message=\"You're all caught up! New notifications will appear here.\" />\n } @else if (NotificationsToShow.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-filter-circle-xmark\"\n Title=\"No Matching Notifications\"\n Message=\"Try adjusting your filters to see more notifications.\" />\n } @else {\n <!-- Day-grouped notification list -->\n <div class=\"notifications-list\">\n @for (group of Groups; track group.Key) {\n <div class=\"group-label\">{{group.Label}}</div>\n\n @for (vm of group.Items; track vm.N.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"vm.N.Unread\"\n [class.expanded]=\"IsExpanded(vm)\"\n [class.clickable]=\"vm.Clickable\"\n role=\"article\"\n [attr.aria-label]=\"vm.N.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.N)\"\n [style.color]=\"getTypeColor(vm.N)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(vm.N)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"vm.N.Unread\">\n {{vm.N.Title}}\n </h3>\n <span class=\"card-time\" [title]=\"(vm.N.__mj_CreatedAt | date:'medium') ?? ''\">\n @if (vm.Relative) {\n {{vm.Relative}}\n } @else {\n <time [attr.datetime]=\"vm.N.__mj_CreatedAt\">{{vm.N.__mj_CreatedAt | date:'MMM d, h:mm a'}}</time>\n }\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\">{{getTypeName(vm.N)}}</span>\n @if (vm.Clickable) {\n <span class=\"card-open-hint\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i> Open\n </span>\n }\n </div>\n\n @if (!IsExpanded(vm)) {\n <p class=\"card-message\">{{vm.Preview}}</p>\n } @else {\n <div class=\"card-rich\" (click)=\"$event.stopPropagation()\">\n @switch (vm.Kind) {\n @case ('html') {\n <!-- Angular sanitizes on [innerHTML] bind; chrome tags were stripped at classification -->\n <div class=\"card-rich-html\" [innerHTML]=\"vm.Body\"></div>\n }\n @case ('markdown') {\n <mj-markdown class=\"card-rich-md\" [data]=\"vm.Body\" [enableMermaid]=\"false\"></mj-markdown>\n }\n @default {\n <p class=\"card-message card-message-full\">{{vm.N.Message}}</p>\n }\n }\n </div>\n }\n\n @if (vm.Expandable) {\n <button class=\"card-expand-btn\" type=\"button\"\n (click)=\"ToggleExpanded(vm, $event)\"\n [attr.aria-expanded]=\"IsExpanded(vm)\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!IsExpanded(vm)\" [class.fa-chevron-up]=\"IsExpanded(vm)\" aria-hidden=\"true\"></i>\n {{ IsExpanded(vm) ? 'Show less' : 'Show more' }}\n </button>\n }\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (vm.N.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, true, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as read'\"\n title=\"Mark as Read\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Read</span>\n </button>\n } @else {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, false, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as unread'\"\n title=\"Mark as Unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Unread</span>\n </button>\n }\n </div>\n </article>\n }\n }\n </div>\n }\n </div>\n</div>\n"]}
|
|
@@ -317,11 +317,11 @@ export class UserProfileComponent extends BaseAngularComponent {
|
|
|
317
317
|
i0.ɵɵconditional(ctx.Loading ? 0 : -1);
|
|
318
318
|
i0.ɵɵadvance();
|
|
319
319
|
i0.ɵɵconditional(!ctx.Loading ? 1 : -1);
|
|
320
|
-
} }, dependencies: [i3.LoadingComponent, i4.AsyncPipe], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n \n display: block;\n width: 100%;\n padding: 1.5rem;\n}\n\n\n\n\n.user-profile-container[_ngcontent-%COMP%] {\n max-width: 900px;\n margin: 0 auto;\n display: grid;\n grid-template-columns: 1fr;\n gap: 1.5rem;\n}\n\n\n\n\n.profile-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.profile-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.profile-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1.25rem;\n}\n\n.avatar-container[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: 3px solid var(--mj-border-default);\n transition: border-color 0.2s;\n}\n\n.profile-card[_ngcontent-%COMP%]:hover .avatar-container[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.avatar-icon[_ngcontent-%COMP%] {\n font-size: 2.5rem;\n color: var(--mj-brand-primary);\n}\n\n.profile-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.user-name[_ngcontent-%COMP%] {\n margin: 0 0 0.375rem 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.user-email[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n}\n\n\n\n\n.notification-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n\n.notification-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.header-icon[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n color: var(--mj-brand-primary);\n}\n\n.card-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.unread-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 28px;\n padding: 0 0.5rem;\n background: var(--mj-status-success);\n color:
|
|
320
|
+
} }, dependencies: [i3.LoadingComponent, i4.AsyncPipe], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n \n display: block;\n width: 100%;\n padding: 1.5rem;\n}\n\n\n\n\n.user-profile-container[_ngcontent-%COMP%] {\n max-width: 900px;\n margin: 0 auto;\n display: grid;\n grid-template-columns: 1fr;\n gap: 1.5rem;\n}\n\n\n\n\n.profile-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.profile-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.profile-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1.25rem;\n}\n\n.avatar-container[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: 3px solid var(--mj-border-default);\n transition: border-color 0.2s;\n}\n\n.profile-card[_ngcontent-%COMP%]:hover .avatar-container[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.avatar-icon[_ngcontent-%COMP%] {\n font-size: 2.5rem;\n color: var(--mj-brand-primary);\n}\n\n.profile-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.user-name[_ngcontent-%COMP%] {\n margin: 0 0 0.375rem 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.user-email[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n}\n\n\n\n\n.notification-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n\n.notification-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.header-icon[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n color: var(--mj-brand-primary);\n}\n\n.card-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.unread-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 28px;\n padding: 0 0.5rem;\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n border-radius: 9999px;\n font-size: 0.875rem;\n font-weight: 600;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.card-body[_ngcontent-%COMP%] {\n padding: 1.25rem;\n}\n\n.card-description[_ngcontent-%COMP%] {\n margin: 0 0 1.25rem 0;\n font-size: 0.9375rem;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n\n\n\n.channel-toggles[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n margin-bottom: 1.5rem;\n}\n\n.channel-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.875rem;\n padding: 1rem 1.25rem;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n min-height: 56px;\n}\n\n.channel-toggle[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.channel-label[_ngcontent-%COMP%] {\n flex: 1;\n text-align: left;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.toggle-indicator[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-text-muted);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.toggle-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: transparent;\n}\n\n.channel-toggle[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-toggle[_ngcontent-%COMP%]:hover:not(:disabled) i[_ngcontent-%COMP%]:first-child {\n color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-toggle.active[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active[_ngcontent-%COMP%] .toggle-indicator[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active[_ngcontent-%COMP%] .toggle-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-primary);\n}\n\n.channel-toggle[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.channel-toggle[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n\n\n\n.card-footer[_ngcontent-%COMP%] {\n padding-top: 1rem;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.settings-link[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-brand-primary);\n text-decoration: none;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0.5rem;\n margin: -0.5rem;\n border-radius: 8px;\n}\n\n.settings-link[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.settings-link[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n transition: transform 0.2s;\n}\n\n.settings-link[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: translateX(4px);\n}\n\n\n\n\nbutton[_ngcontent-%COMP%]:focus-visible, \na[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n\n\n\n@media (max-width: 639px) {\n [_nghost-%COMP%] {\n padding: 1rem;\n }\n\n .user-profile-container[_ngcontent-%COMP%] {\n gap: 1rem;\n }\n\n .profile-card[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .profile-header[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .avatar-container[_ngcontent-%COMP%] {\n width: 100px;\n height: 100px;\n }\n\n .avatar-icon[_ngcontent-%COMP%] {\n font-size: 3rem;\n }\n\n .user-name[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .channel-toggles[_ngcontent-%COMP%] {\n gap: 0.625rem;\n }\n\n .channel-toggle[_ngcontent-%COMP%] {\n padding: 0.875rem 1rem;\n }\n}\n\n@media (min-width: 640px) {\n .channel-toggles[_ngcontent-%COMP%] {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (min-width: 768px) {\n [_nghost-%COMP%] {\n padding: 2rem;\n }\n\n .user-profile-container[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .user-profile-container[_ngcontent-%COMP%] {\n gap: 2rem;\n }\n}"] });
|
|
321
321
|
}
|
|
322
322
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserProfileComponent, [{
|
|
323
323
|
type: Component,
|
|
324
|
-
args: [{ standalone: false, selector: 'app-user-profile', template: "@if (Loading) {\n <mj-loading text=\"Loading profile...\"></mj-loading>\n}\n\n@if (!Loading) {\n <div class=\"user-profile-container\">\n <!-- User Info Card -->\n @if (User | async; as user) {\n <div class=\"profile-card\">\n <div class=\"profile-header\">\n <div class=\"avatar-container\">\n <i class=\"fa-solid fa-user avatar-icon\"></i>\n </div>\n <div class=\"profile-info\">\n <h3 class=\"user-name\">{{ user.name }}</h3>\n <p class=\"user-email\">{{ user.email }}</p>\n </div>\n </div>\n </div>\n }\n <!-- Notification Summary Card -->\n <div class=\"notification-card\">\n <div class=\"card-header\">\n <div class=\"header-left\">\n <i class=\"fa-solid fa-bell header-icon\"></i>\n <h4>Notifications</h4>\n </div>\n @if (UnreadNotificationCount > 0) {\n <span class=\"unread-badge\">\n {{ UnreadNotificationCount }}\n </span>\n }\n </div>\n <div class=\"card-body\">\n <p class=\"card-description\">\n Manage your notification preferences for all channels\n </p>\n <div class=\"channel-toggles\">\n <!-- In-App Toggle -->\n <button\n class=\"channel-toggle\"\n [class.active]=\"IsChannelEnabled('InApp')\"\n [disabled]=\"Saving\"\n (click)=\"ToggleChannel('InApp')\"\n type=\"button\"\n >\n <i [class]=\"GetChannelIcon('InApp')\"></i>\n <span class=\"channel-label\">{{ GetChannelLabel('InApp') }}</span>\n <span class=\"toggle-indicator\">\n @if (IsChannelEnabled('InApp')) {\n <i class=\"fa-solid fa-check\"></i>\n }\n </span>\n </button>\n <!-- Email Toggle -->\n <button\n class=\"channel-toggle\"\n [class.active]=\"IsChannelEnabled('Email')\"\n [disabled]=\"Saving\"\n (click)=\"ToggleChannel('Email')\"\n type=\"button\"\n >\n <i [class]=\"GetChannelIcon('Email')\"></i>\n <span class=\"channel-label\">{{ GetChannelLabel('Email') }}</span>\n <span class=\"toggle-indicator\">\n @if (IsChannelEnabled('Email')) {\n <i class=\"fa-solid fa-check\"></i>\n }\n </span>\n </button>\n <!-- SMS Toggle -->\n <button\n class=\"channel-toggle\"\n [class.active]=\"IsChannelEnabled('SMS')\"\n [disabled]=\"Saving\"\n (click)=\"ToggleChannel('SMS')\"\n type=\"button\"\n >\n <i [class]=\"GetChannelIcon('SMS')\"></i>\n <span class=\"channel-label\">{{ GetChannelLabel('SMS') }}</span>\n <span class=\"toggle-indicator\">\n @if (IsChannelEnabled('SMS')) {\n <i class=\"fa-solid fa-check\"></i>\n }\n </span>\n </button>\n </div>\n <div class=\"card-footer\">\n <a href=\"/settings\" class=\"settings-link\">\n View all notification preferences\n <i class=\"fa-solid fa-arrow-right\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n}", styles: ["/* =============================================================================\n User Profile Component\n Using MJ Design Tokens\n ============================================================================= */\n\n:host {\n /* Host element configuration */\n display: block;\n width: 100%;\n padding: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.user-profile-container {\n max-width: 900px;\n margin: 0 auto;\n display: grid;\n grid-template-columns: 1fr;\n gap: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Profile Card\n ----------------------------------------------------------------------------- */\n.profile-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.profile-card:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.profile-header {\n display: flex;\n align-items: center;\n gap: 1.25rem;\n}\n\n.avatar-container {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: 3px solid var(--mj-border-default);\n transition: border-color 0.2s;\n}\n\n.profile-card:hover .avatar-container {\n border-color: var(--mj-brand-primary);\n}\n\n.avatar-icon {\n font-size: 2.5rem;\n color: var(--mj-brand-primary);\n}\n\n.profile-info {\n flex: 1;\n min-width: 0;\n}\n\n.user-name {\n margin: 0 0 0.375rem 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.user-email {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n}\n\n/* -----------------------------------------------------------------------------\n Notification Card\n ----------------------------------------------------------------------------- */\n.notification-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n\n.notification-card:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.header-icon {\n font-size: 1.5rem;\n color: var(--mj-brand-primary);\n}\n\n.card-header h4 {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.unread-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 28px;\n padding: 0 0.5rem;\n background: var(--mj-status-success);\n color: white;\n border-radius: 9999px;\n font-size: 0.875rem;\n font-weight: 600;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.card-body {\n padding: 1.25rem;\n}\n\n.card-description {\n margin: 0 0 1.25rem 0;\n font-size: 0.9375rem;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n/* -----------------------------------------------------------------------------\n Channel Toggles\n ----------------------------------------------------------------------------- */\n.channel-toggles {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n margin-bottom: 1.5rem;\n}\n\n.channel-toggle {\n display: flex;\n align-items: center;\n gap: 0.875rem;\n padding: 1rem 1.25rem;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n min-height: 56px;\n}\n\n.channel-toggle i:first-child {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.channel-label {\n flex: 1;\n text-align: left;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.toggle-indicator {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-text-muted);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.toggle-indicator i {\n font-size: 0.875rem;\n color: transparent;\n}\n\n.channel-toggle:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-toggle:hover:not(:disabled) i:first-child {\n color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-toggle.active i:first-child {\n color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active .toggle-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active .toggle-indicator i {\n color: white;\n}\n\n.channel-toggle:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.channel-toggle:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Card Footer\n ----------------------------------------------------------------------------- */\n.card-footer {\n padding-top: 1rem;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.settings-link {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-brand-primary);\n text-decoration: none;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0.5rem;\n margin: -0.5rem;\n border-radius: 8px;\n}\n\n.settings-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.settings-link i {\n font-size: 0.875rem;\n transition: transform 0.2s;\n}\n\n.settings-link:hover i {\n transform: translateX(4px);\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\nbutton:focus-visible,\na:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Reduced Motion\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile First\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n :host {\n padding: 1rem;\n }\n\n .user-profile-container {\n gap: 1rem;\n }\n\n .profile-card {\n padding: 1rem;\n }\n\n .profile-header {\n flex-direction: column;\n text-align: center;\n }\n\n .avatar-container {\n width: 100px;\n height: 100px;\n }\n\n .avatar-icon {\n font-size: 3rem;\n }\n\n .user-name {\n font-size: 1.25rem;\n }\n\n .card-header {\n padding: 1rem;\n }\n\n .card-body {\n padding: 1rem;\n }\n\n .channel-toggles {\n gap: 0.625rem;\n }\n\n .channel-toggle {\n padding: 0.875rem 1rem;\n }\n}\n\n@media (min-width: 640px) {\n .channel-toggles {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (min-width: 768px) {\n :host {\n padding: 2rem;\n }\n\n .user-profile-container {\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .user-profile-container {\n gap: 2rem;\n }\n}\n"] }]
|
|
324
|
+
args: [{ standalone: false, selector: 'app-user-profile', template: "@if (Loading) {\n <mj-loading text=\"Loading profile...\"></mj-loading>\n}\n\n@if (!Loading) {\n <div class=\"user-profile-container\">\n <!-- User Info Card -->\n @if (User | async; as user) {\n <div class=\"profile-card\">\n <div class=\"profile-header\">\n <div class=\"avatar-container\">\n <i class=\"fa-solid fa-user avatar-icon\"></i>\n </div>\n <div class=\"profile-info\">\n <h3 class=\"user-name\">{{ user.name }}</h3>\n <p class=\"user-email\">{{ user.email }}</p>\n </div>\n </div>\n </div>\n }\n <!-- Notification Summary Card -->\n <div class=\"notification-card\">\n <div class=\"card-header\">\n <div class=\"header-left\">\n <i class=\"fa-solid fa-bell header-icon\"></i>\n <h4>Notifications</h4>\n </div>\n @if (UnreadNotificationCount > 0) {\n <span class=\"unread-badge\">\n {{ UnreadNotificationCount }}\n </span>\n }\n </div>\n <div class=\"card-body\">\n <p class=\"card-description\">\n Manage your notification preferences for all channels\n </p>\n <div class=\"channel-toggles\">\n <!-- In-App Toggle -->\n <button\n class=\"channel-toggle\"\n [class.active]=\"IsChannelEnabled('InApp')\"\n [disabled]=\"Saving\"\n (click)=\"ToggleChannel('InApp')\"\n type=\"button\"\n >\n <i [class]=\"GetChannelIcon('InApp')\"></i>\n <span class=\"channel-label\">{{ GetChannelLabel('InApp') }}</span>\n <span class=\"toggle-indicator\">\n @if (IsChannelEnabled('InApp')) {\n <i class=\"fa-solid fa-check\"></i>\n }\n </span>\n </button>\n <!-- Email Toggle -->\n <button\n class=\"channel-toggle\"\n [class.active]=\"IsChannelEnabled('Email')\"\n [disabled]=\"Saving\"\n (click)=\"ToggleChannel('Email')\"\n type=\"button\"\n >\n <i [class]=\"GetChannelIcon('Email')\"></i>\n <span class=\"channel-label\">{{ GetChannelLabel('Email') }}</span>\n <span class=\"toggle-indicator\">\n @if (IsChannelEnabled('Email')) {\n <i class=\"fa-solid fa-check\"></i>\n }\n </span>\n </button>\n <!-- SMS Toggle -->\n <button\n class=\"channel-toggle\"\n [class.active]=\"IsChannelEnabled('SMS')\"\n [disabled]=\"Saving\"\n (click)=\"ToggleChannel('SMS')\"\n type=\"button\"\n >\n <i [class]=\"GetChannelIcon('SMS')\"></i>\n <span class=\"channel-label\">{{ GetChannelLabel('SMS') }}</span>\n <span class=\"toggle-indicator\">\n @if (IsChannelEnabled('SMS')) {\n <i class=\"fa-solid fa-check\"></i>\n }\n </span>\n </button>\n </div>\n <div class=\"card-footer\">\n <a href=\"/settings\" class=\"settings-link\">\n View all notification preferences\n <i class=\"fa-solid fa-arrow-right\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n}", styles: ["/* =============================================================================\n User Profile Component\n Using MJ Design Tokens\n ============================================================================= */\n\n:host {\n /* Host element configuration */\n display: block;\n width: 100%;\n padding: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.user-profile-container {\n max-width: 900px;\n margin: 0 auto;\n display: grid;\n grid-template-columns: 1fr;\n gap: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Profile Card\n ----------------------------------------------------------------------------- */\n.profile-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.profile-card:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.profile-header {\n display: flex;\n align-items: center;\n gap: 1.25rem;\n}\n\n.avatar-container {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: 3px solid var(--mj-border-default);\n transition: border-color 0.2s;\n}\n\n.profile-card:hover .avatar-container {\n border-color: var(--mj-brand-primary);\n}\n\n.avatar-icon {\n font-size: 2.5rem;\n color: var(--mj-brand-primary);\n}\n\n.profile-info {\n flex: 1;\n min-width: 0;\n}\n\n.user-name {\n margin: 0 0 0.375rem 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.user-email {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n}\n\n/* -----------------------------------------------------------------------------\n Notification Card\n ----------------------------------------------------------------------------- */\n.notification-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n\n.notification-card:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.header-icon {\n font-size: 1.5rem;\n color: var(--mj-brand-primary);\n}\n\n.card-header h4 {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.unread-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 28px;\n padding: 0 0.5rem;\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n border-radius: 9999px;\n font-size: 0.875rem;\n font-weight: 600;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.card-body {\n padding: 1.25rem;\n}\n\n.card-description {\n margin: 0 0 1.25rem 0;\n font-size: 0.9375rem;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n/* -----------------------------------------------------------------------------\n Channel Toggles\n ----------------------------------------------------------------------------- */\n.channel-toggles {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n margin-bottom: 1.5rem;\n}\n\n.channel-toggle {\n display: flex;\n align-items: center;\n gap: 0.875rem;\n padding: 1rem 1.25rem;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n min-height: 56px;\n}\n\n.channel-toggle i:first-child {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.channel-label {\n flex: 1;\n text-align: left;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.toggle-indicator {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-text-muted);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.toggle-indicator i {\n font-size: 0.875rem;\n color: transparent;\n}\n\n.channel-toggle:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-toggle:hover:not(:disabled) i:first-child {\n color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-toggle.active i:first-child {\n color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active .toggle-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.channel-toggle.active .toggle-indicator i {\n color: var(--mj-brand-on-primary);\n}\n\n.channel-toggle:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.channel-toggle:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Card Footer\n ----------------------------------------------------------------------------- */\n.card-footer {\n padding-top: 1rem;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.settings-link {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-brand-primary);\n text-decoration: none;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0.5rem;\n margin: -0.5rem;\n border-radius: 8px;\n}\n\n.settings-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.settings-link i {\n font-size: 0.875rem;\n transition: transform 0.2s;\n}\n\n.settings-link:hover i {\n transform: translateX(4px);\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\nbutton:focus-visible,\na:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Reduced Motion\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile First\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n :host {\n padding: 1rem;\n }\n\n .user-profile-container {\n gap: 1rem;\n }\n\n .profile-card {\n padding: 1rem;\n }\n\n .profile-header {\n flex-direction: column;\n text-align: center;\n }\n\n .avatar-container {\n width: 100px;\n height: 100px;\n }\n\n .avatar-icon {\n font-size: 3rem;\n }\n\n .user-name {\n font-size: 1.25rem;\n }\n\n .card-header {\n padding: 1rem;\n }\n\n .card-body {\n padding: 1rem;\n }\n\n .channel-toggles {\n gap: 0.625rem;\n }\n\n .channel-toggle {\n padding: 0.875rem 1rem;\n }\n}\n\n@media (min-width: 640px) {\n .channel-toggles {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (min-width: 768px) {\n :host {\n padding: 2rem;\n }\n\n .user-profile-container {\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .user-profile-container {\n gap: 2rem;\n }\n}\n"] }]
|
|
325
325
|
}], () => [{ type: i1.MJAuthBase }, { type: i2.SharedService }, { type: i0.ChangeDetectorRef }], null); })();
|
|
326
326
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserProfileComponent, { className: "UserProfileComponent", filePath: "src/lib/user-profile/user-profile.component.ts", lineNumber: 24 }); })();
|
|
327
327
|
//# sourceMappingURL=user-profile.component.js.map
|