@memberjunction/ng-explorer-core 5.4.1 → 5.5.0

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.
Files changed (32) hide show
  1. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -1
  2. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +7 -6
  3. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
  4. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +2 -2
  5. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  6. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  7. package/dist/lib/resource-wrappers/dashboard-resource.component.js +16 -5
  8. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  9. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  10. package/dist/lib/resource-wrappers/view-resource.component.js +13 -3
  11. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  12. package/dist/lib/shell/components/header/app-switcher.component.d.ts +4 -0
  13. package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -1
  14. package/dist/lib/shell/components/header/app-switcher.component.js +15 -6
  15. package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -1
  16. package/dist/lib/shell/shell.component.d.ts +2 -0
  17. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  18. package/dist/lib/shell/shell.component.js +28 -15
  19. package/dist/lib/shell/shell.component.js.map +1 -1
  20. package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
  21. package/dist/lib/single-list-detail/single-list-detail.component.js +4 -3
  22. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  23. package/dist/lib/single-record/single-record.component.d.ts +1 -0
  24. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  25. package/dist/lib/single-record/single-record.component.js +3 -1
  26. package/dist/lib/single-record/single-record.component.js.map +1 -1
  27. package/dist/lib/user-notifications/user-notifications.component.js +3 -3
  28. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  29. package/dist/lib/user-profile/user-profile.component.d.ts.map +1 -1
  30. package/dist/lib/user-profile/user-profile.component.js +3 -2
  31. package/dist/lib/user-profile/user-profile.component.js.map +1 -1
  32. package/package.json +34 -34
@@ -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, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { MJConversationDetailEntity, MJConversationEntity, MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { Metadata, TransactionGroupBase, TransactionVariable } from '@memberjunction/core';\nimport { Router } from '@angular/router';\nimport { SafeJSONParse } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\n\n/**\n * Radio button filter options for notification read status\n */\ntype ReadFilterOption = 'All' | 'Unread' | 'Read';\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 * Result of parsing a notification URL\n */\ninterface NotificationUrlInfo {\n urlParts: string[];\n queryString: string;\n}\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 implements OnInit, AfterViewInit {\n @ViewChild('allRadio') allRadio!: ElementRef<HTMLInputElement>;\n @ViewChild('unreadRadio') unreadRadio!: ElementRef<HTMLInputElement>;\n @ViewChild('readRadio') readRadio!: ElementRef<HTMLInputElement>;\n\n public radioSelected: ReadFilterOption = 'All';\n public currentFilter: string = '';\n public notificationTypes: MJUserNotificationTypeEntity[] = [];\n public selectedTypeFilter: string | null = null;\n public loadingTypes: boolean = true;\n\n constructor (public sharedService: SharedService, private router: Router) {}\n\n async ngOnInit() {\n this.loadNotificationTypes();\n }\n\n ngAfterViewInit(): void {\n this.sharedService.InvokeManualResize(); // make sure the notifications component is sized correctly\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 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 => 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 public isNotificationClickable(notification: MJUserNotificationEntity): boolean {\n const info = this.notificationUrl(notification);\n return (info !== null && info.urlParts && info.urlParts.length > 0);\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 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 // now update the radio button group in the UI\n switch (option) {\n case 'All':\n this.allRadio.nativeElement.checked = true;\n break;\n case 'Unread':\n this.unreadRadio.nativeElement.checked = true;\n break;\n case 'Read':\n this.readRadio.nativeElement.checked = true;\n break;\n }\n }\n\n onReadRadioChanged(event: Event): void {\n if (event.target instanceof HTMLInputElement) {\n this.radioSelected = event.target.value as ReadFilterOption;\n }\n }\n\n onFilterChanged(value: string): void {\n this.currentFilter = value;\n }\n\n getItemTitleClass(notification: MJUserNotificationEntity): string {\n if (notification.Unread) {\n return 'notification-title notification-title-unread';\n }\n return 'notification-title';\n }\n\n getItemWrapperClass(notification: MJUserNotificationEntity): string {\n let classInfo = 'notification-wrap';\n\n if (this.isNotificationClickable(notification))\n classInfo += ' notification-wrap-clickable';\n\n if (notification.Unread)\n classInfo += ' notification-wrap-unread';\n\n return classInfo;\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 = new Metadata();\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 public async markAllAsRead() {\n await this.markAll(true);\n\n // test harness for creating Conversations and Conversation Details record in a single transaction using variables\n await this.TestTransactionGroupVariables();\n }\n\n public async TestTransactionGroupVariables() {\n const md = new Metadata();\n const transGroup = await md.CreateTransactionGroup();\n\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations');\n conversation.UserID = md.CurrentUser.ID;\n conversation.Description = 'Test Conversation';\n conversation.TransactionGroup = transGroup;\n if (!await conversation.Save()) {\n this.sharedService.CreateSimpleNotification('Unable to create conversation', 'error', 5000);\n }\n\n const tvDefine = new TransactionVariable('NewConvoID', conversation, 'ID', 'Define')\n transGroup.AddVariable(tvDefine);\n\n const conversationDetail = await md.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details');\n conversationDetail.Message = 'Test Message';\n conversationDetail.Role = 'User';\n conversationDetail.ConversationID = 'x'; // fake UUID must be non-null to pass validation, this will be replaced by the variable, since we're part of a TG, not a real save, so doesn't validate it as a true fkey\n conversationDetail.TransactionGroup = transGroup;\n if (!await conversationDetail.Save()) {\n this.sharedService.CreateSimpleNotification('Unable to create conversation detail', 'error', 500);\n } \n const tvUse = new TransactionVariable('NewConvoID', conversationDetail, 'ConversationID', 'Use')\n transGroup.AddVariable(tvUse);\n\n if (await transGroup.Submit()) {\n this.sharedService.CreateSimpleNotification('Transaction Group with Variables worked', 'success', 5000);\n }\n else {\n this.sharedService.CreateSimpleNotification('Transaction Group with Variables failed', 'error', 5000);\n }\n }\n\n public async markAllAsUnread() {\n await this.markAll(false);\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 = new Metadata();\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 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 const info = this.notificationUrl(notification);\n if (info.queryString && info.queryString.trim().length > 0) {\n const fullUrl = `${info.urlParts.join('/')}${info.queryString ? '?' + info.queryString : ''}`;\n this.router.navigateByUrl(fullUrl);\n }\n else {\n this.router.navigate(info.urlParts);\n }\n }\n }\n\n public getNotificationType(typeId: string | null): MJUserNotificationTypeEntity | null {\n if (!typeId) return null;\n return this.notificationTypes.find(t => t.ID === typeId) || null;\n }\n\n public getTypeIcon(notification: MJUserNotificationEntity): string {\n const type = this.getNotificationType(notification.NotificationTypeID);\n return type?.Icon || 'fa-bell';\n }\n\n public getTypeColor(notification: MJUserNotificationEntity): string {\n const type = this.getNotificationType(notification.NotificationTypeID);\n return type?.Color || '#999';\n }\n\n public getTypeName(notification: MJUserNotificationEntity): string {\n const type = this.getNotificationType(notification.NotificationTypeID);\n return type ? type.Name : 'Notification';\n }\n\n public onTypeFilterChange(typeId: string | null): void {\n this.selectedTypeFilter = 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 <h1>Notifications</h1>\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 <!-- Horizontal Slider for Filters (Mobile) -->\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Stats Pills (Filter Tabs) -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <input #allRadio type=\"radio\" name=\"UnreadStatus\" value=\"All\"\n (change)=\"onReadRadioChanged($event)\" checked class=\"hidden-radio\"\n id=\"filter-all\" />\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 <input #unreadRadio type=\"radio\" name=\"UnreadStatus\" value=\"Unread\"\n (change)=\"onReadRadioChanged($event)\" class=\"hidden-radio\"\n id=\"filter-unread\" />\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 <input #readRadio type=\"radio\" name=\"UnreadStatus\" value=\"Read\"\n (change)=\"onReadRadioChanged($event)\" class=\"hidden-radio\"\n id=\"filter-read\" />\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 <!-- Native Type Filter Dropdown (in slider on mobile) -->\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 Filter (separate, full-width on mobile) -->\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 <!-- Filter Info Badge -->\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 <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n </div>\n <h3>No Notifications</h3>\n <p>You're all caught up! New notifications will appear here.</p>\n </div>\n } @else if (NotificationsToShow.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-filter-circle-xmark\"></i>\n </div>\n <h3>No Matching Notifications</h3>\n <p>Try adjusting your filters to see more notifications.</p>\n </div>\n } @else {\n <!-- Notifications List -->\n <div class=\"notifications-list\">\n @for (notification of NotificationsToShow; track notification.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"notification.Unread\"\n [class.clickable]=\"isNotificationClickable(notification)\"\n role=\"article\"\n [attr.aria-label]=\"notification.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\"\n [style.background-color]=\"getTypeColor(notification) + '15'\"\n aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(notification)\"\n [style.color]=\"getTypeColor(notification)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(notification)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"notification.Unread\">\n {{notification.Title}}\n </h3>\n <span class=\"card-time\">\n <i class=\"fa-regular fa-clock\" aria-hidden=\"true\"></i>\n <time [attr.datetime]=\"notification.__mj_CreatedAt\">\n {{notification.__mj_CreatedAt | date:'MMM d, h:mm a'}}\n </time>\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\"\n [style.background-color]=\"getTypeColor(notification) + '15'\"\n [style.color]=\"getTypeColor(notification)\">\n {{getTypeName(notification)}}\n </span>\n </div>\n\n <p class=\"card-message\">{{notification.Message}}</p>\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (notification.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(notification, true, null)\"\n [attr.aria-label]=\"'Mark ' + notification.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(notification, false, null)\"\n [attr.aria-label]=\"'Mark ' + notification.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 </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, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { MJConversationDetailEntity, MJConversationEntity, MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { Metadata, TransactionGroupBase, TransactionVariable } from '@memberjunction/core';\nimport { Router } from '@angular/router';\nimport { SafeJSONParse , UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\n\n/**\n * Radio button filter options for notification read status\n */\ntype ReadFilterOption = 'All' | 'Unread' | 'Read';\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 * Result of parsing a notification URL\n */\ninterface NotificationUrlInfo {\n urlParts: string[];\n queryString: string;\n}\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 implements OnInit, AfterViewInit {\n @ViewChild('allRadio') allRadio!: ElementRef<HTMLInputElement>;\n @ViewChild('unreadRadio') unreadRadio!: ElementRef<HTMLInputElement>;\n @ViewChild('readRadio') readRadio!: ElementRef<HTMLInputElement>;\n\n public radioSelected: ReadFilterOption = 'All';\n public currentFilter: string = '';\n public notificationTypes: MJUserNotificationTypeEntity[] = [];\n public selectedTypeFilter: string | null = null;\n public loadingTypes: boolean = true;\n\n constructor (public sharedService: SharedService, private router: Router) {}\n\n async ngOnInit() {\n this.loadNotificationTypes();\n }\n\n ngAfterViewInit(): void {\n this.sharedService.InvokeManualResize(); // make sure the notifications component is sized correctly\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 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 public isNotificationClickable(notification: MJUserNotificationEntity): boolean {\n const info = this.notificationUrl(notification);\n return (info !== null && info.urlParts && info.urlParts.length > 0);\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 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 // now update the radio button group in the UI\n switch (option) {\n case 'All':\n this.allRadio.nativeElement.checked = true;\n break;\n case 'Unread':\n this.unreadRadio.nativeElement.checked = true;\n break;\n case 'Read':\n this.readRadio.nativeElement.checked = true;\n break;\n }\n }\n\n onReadRadioChanged(event: Event): void {\n if (event.target instanceof HTMLInputElement) {\n this.radioSelected = event.target.value as ReadFilterOption;\n }\n }\n\n onFilterChanged(value: string): void {\n this.currentFilter = value;\n }\n\n getItemTitleClass(notification: MJUserNotificationEntity): string {\n if (notification.Unread) {\n return 'notification-title notification-title-unread';\n }\n return 'notification-title';\n }\n\n getItemWrapperClass(notification: MJUserNotificationEntity): string {\n let classInfo = 'notification-wrap';\n\n if (this.isNotificationClickable(notification))\n classInfo += ' notification-wrap-clickable';\n\n if (notification.Unread)\n classInfo += ' notification-wrap-unread';\n\n return classInfo;\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 = new Metadata();\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 public async markAllAsRead() {\n await this.markAll(true);\n\n // test harness for creating Conversations and Conversation Details record in a single transaction using variables\n await this.TestTransactionGroupVariables();\n }\n\n public async TestTransactionGroupVariables() {\n const md = new Metadata();\n const transGroup = await md.CreateTransactionGroup();\n\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations');\n conversation.UserID = md.CurrentUser.ID;\n conversation.Description = 'Test Conversation';\n conversation.TransactionGroup = transGroup;\n if (!await conversation.Save()) {\n this.sharedService.CreateSimpleNotification('Unable to create conversation', 'error', 5000);\n }\n\n const tvDefine = new TransactionVariable('NewConvoID', conversation, 'ID', 'Define')\n transGroup.AddVariable(tvDefine);\n\n const conversationDetail = await md.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details');\n conversationDetail.Message = 'Test Message';\n conversationDetail.Role = 'User';\n conversationDetail.ConversationID = 'x'; // fake UUID must be non-null to pass validation, this will be replaced by the variable, since we're part of a TG, not a real save, so doesn't validate it as a true fkey\n conversationDetail.TransactionGroup = transGroup;\n if (!await conversationDetail.Save()) {\n this.sharedService.CreateSimpleNotification('Unable to create conversation detail', 'error', 500);\n } \n const tvUse = new TransactionVariable('NewConvoID', conversationDetail, 'ConversationID', 'Use')\n transGroup.AddVariable(tvUse);\n\n if (await transGroup.Submit()) {\n this.sharedService.CreateSimpleNotification('Transaction Group with Variables worked', 'success', 5000);\n }\n else {\n this.sharedService.CreateSimpleNotification('Transaction Group with Variables failed', 'error', 5000);\n }\n }\n\n public async markAllAsUnread() {\n await this.markAll(false);\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 = new Metadata();\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 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 const info = this.notificationUrl(notification);\n if (info.queryString && info.queryString.trim().length > 0) {\n const fullUrl = `${info.urlParts.join('/')}${info.queryString ? '?' + info.queryString : ''}`;\n this.router.navigateByUrl(fullUrl);\n }\n else {\n this.router.navigate(info.urlParts);\n }\n }\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 public getTypeIcon(notification: MJUserNotificationEntity): string {\n const type = this.getNotificationType(notification.NotificationTypeID);\n return type?.Icon || 'fa-bell';\n }\n\n public getTypeColor(notification: MJUserNotificationEntity): string {\n const type = this.getNotificationType(notification.NotificationTypeID);\n return type?.Color || '#999';\n }\n\n public getTypeName(notification: MJUserNotificationEntity): string {\n const type = this.getNotificationType(notification.NotificationTypeID);\n return type ? type.Name : 'Notification';\n }\n\n public onTypeFilterChange(typeId: string | null): void {\n this.selectedTypeFilter = 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 <h1>Notifications</h1>\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 <!-- Horizontal Slider for Filters (Mobile) -->\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Stats Pills (Filter Tabs) -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <input #allRadio type=\"radio\" name=\"UnreadStatus\" value=\"All\"\n (change)=\"onReadRadioChanged($event)\" checked class=\"hidden-radio\"\n id=\"filter-all\" />\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 <input #unreadRadio type=\"radio\" name=\"UnreadStatus\" value=\"Unread\"\n (change)=\"onReadRadioChanged($event)\" class=\"hidden-radio\"\n id=\"filter-unread\" />\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 <input #readRadio type=\"radio\" name=\"UnreadStatus\" value=\"Read\"\n (change)=\"onReadRadioChanged($event)\" class=\"hidden-radio\"\n id=\"filter-read\" />\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 <!-- Native Type Filter Dropdown (in slider on mobile) -->\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 Filter (separate, full-width on mobile) -->\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 <!-- Filter Info Badge -->\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 <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n </div>\n <h3>No Notifications</h3>\n <p>You're all caught up! New notifications will appear here.</p>\n </div>\n } @else if (NotificationsToShow.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-filter-circle-xmark\"></i>\n </div>\n <h3>No Matching Notifications</h3>\n <p>Try adjusting your filters to see more notifications.</p>\n </div>\n } @else {\n <!-- Notifications List -->\n <div class=\"notifications-list\">\n @for (notification of NotificationsToShow; track notification.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"notification.Unread\"\n [class.clickable]=\"isNotificationClickable(notification)\"\n role=\"article\"\n [attr.aria-label]=\"notification.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\"\n [style.background-color]=\"getTypeColor(notification) + '15'\"\n aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(notification)\"\n [style.color]=\"getTypeColor(notification)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(notification)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"notification.Unread\">\n {{notification.Title}}\n </h3>\n <span class=\"card-time\">\n <i class=\"fa-regular fa-clock\" aria-hidden=\"true\"></i>\n <time [attr.datetime]=\"notification.__mj_CreatedAt\">\n {{notification.__mj_CreatedAt | date:'MMM d, h:mm a'}}\n </time>\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\"\n [style.background-color]=\"getTypeColor(notification) + '15'\"\n [style.color]=\"getTypeColor(notification)\">\n {{getTypeName(notification)}}\n </span>\n </div>\n\n <p class=\"card-message\">{{notification.Message}}</p>\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (notification.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(notification, true, null)\"\n [attr.aria-label]=\"'Mark ' + notification.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(notification, false, null)\"\n [attr.aria-label]=\"'Mark ' + notification.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 </div>\n }\n </div>\n</div>\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"user-profile.component.d.ts","sourceRoot":"","sources":["../../../src/lib/user-profile/user-profile.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGhF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAW,MAAM,MAAM,CAAC;;AAG3C,UAAU,mBAAmB;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,qBAMa,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAenD,QAAQ,EAAE,UAAU;IAC3B,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,GAAG;IAhBN,IAAI,EAAE,GAAG,CAAQ;IACjB,IAAI,EAAE,UAAU,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,UAAQ;IACf,MAAM,UAAS;IACf,uBAAuB,SAAK;IAC5B,mBAAmB,EAAE,mBAAmB,CAI7C;IAEF,OAAO,CAAC,QAAQ,CAAuB;gBAG9B,QAAQ,EAAE,UAAU,EACnB,aAAa,EAAE,aAAa,EAC5B,GAAG,EAAE,iBAAiB;IAM1B,QAAQ;IAId,WAAW,IAAI,IAAI;IAKnB;;OAEG;YACW,oBAAoB;IA6ClC;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAoFtE;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM;IAS1D;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM;IAS3D;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO;yCAlMlD,oBAAoB;2CAApB,oBAAoB;CA0MhC"}
1
+ {"version":3,"file":"user-profile.component.d.ts","sourceRoot":"","sources":["../../../src/lib/user-profile/user-profile.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGhF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAW,MAAM,MAAM,CAAC;;AAI3C,UAAU,mBAAmB;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,qBAMa,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAenD,QAAQ,EAAE,UAAU;IAC3B,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,GAAG;IAhBN,IAAI,EAAE,GAAG,CAAQ;IACjB,IAAI,EAAE,UAAU,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,UAAQ;IACf,MAAM,UAAS;IACf,uBAAuB,SAAK;IAC5B,mBAAmB,EAAE,mBAAmB,CAI7C;IAEF,OAAO,CAAC,QAAQ,CAAuB;gBAG9B,QAAQ,EAAE,UAAU,EACnB,aAAa,EAAE,aAAa,EAC5B,GAAG,EAAE,iBAAiB;IAM1B,QAAQ;IAId,WAAW,IAAI,IAAI;IAKnB;;OAEG;YACW,oBAAoB;IA6ClC;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAoFtE;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM;IAS1D;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM;IAS3D;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO;yCAlMlD,oBAAoB;2CAApB,oBAAoB;CA0MhC"}
@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
2
2
  import { UserInfoEngine } from '@memberjunction/core-entities';
3
3
  import { Metadata } from '@memberjunction/core';
4
4
  import { Subject } from 'rxjs';
5
+ import { UUIDsEqual } from '@memberjunction/global';
5
6
  import * as i0 from "@angular/core";
6
7
  import * as i1 from "@memberjunction/ng-auth-services";
7
8
  import * as i2 from "@memberjunction/ng-shared";
@@ -228,7 +229,7 @@ export class UserProfileComponent {
228
229
  if (type.AllowUserPreference === false) {
229
230
  continue; // Skip locked types
230
231
  }
231
- let pref = preferences.find(p => p.NotificationTypeID === type.ID);
232
+ let pref = preferences.find(p => UUIDsEqual(p.NotificationTypeID, type.ID));
232
233
  if (!pref) {
233
234
  // Create new preference record
234
235
  pref = await md.GetEntityObject('MJ: User Notification Preferences');
@@ -320,5 +321,5 @@ export class UserProfileComponent {
320
321
  type: Component,
321
322
  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 - Material Design 3\n Following MD3 Design System Guidelines\n ============================================================================= */\n\n/* MD3 Color Tokens */\n:host {\n /* Primary - Deep Blue */\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n /* Secondary - Light Orange */\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n /* Tertiary - Light Green */\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n /* Surface Colors */\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n /* Elevation (Box Shadows) */\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n\n /* Corner Radii */\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-full: 9999px;\n\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(--md-surface-container-lowest);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n padding: 1.5rem;\n box-shadow: var(--md-elevation-1);\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.profile-card:hover {\n box-shadow: var(--md-elevation-2);\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: var(--md-primary-container);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: 3px solid var(--md-outline-variant);\n transition: border-color 0.2s;\n}\n\n.profile-card:hover .avatar-container {\n border-color: var(--md-primary);\n}\n\n.avatar-icon {\n font-size: 2.5rem;\n color: var(--md-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(--md-on-surface);\n}\n\n.user-email {\n margin: 0;\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n}\n\n/* -----------------------------------------------------------------------------\n Notification Card\n ----------------------------------------------------------------------------- */\n.notification-card {\n background: var(--md-surface-container-lowest);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n box-shadow: var(--md-elevation-1);\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(--md-elevation-2);\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(--md-outline-variant);\n background: var(--md-surface-container-low);\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(--md-primary);\n}\n\n.card-header h4 {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--md-on-surface);\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(--md-tertiary);\n color: var(--md-on-tertiary);\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 600;\n box-shadow: var(--md-elevation-1);\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(--md-on-surface-variant);\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(--md-surface);\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\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(--md-on-surface-variant);\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(--md-on-surface);\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(--md-outline);\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(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-toggle:hover:not(:disabled) i:first-child {\n color: var(--md-primary);\n}\n\n.channel-toggle.active {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-toggle.active i:first-child {\n color: var(--md-primary);\n}\n\n.channel-toggle.active .toggle-indicator {\n background: var(--md-primary);\n border-color: var(--md-primary);\n}\n\n.channel-toggle.active .toggle-indicator i {\n color: var(--md-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(--md-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(--md-outline-variant);\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(--md-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: var(--md-corner-small);\n}\n\n.settings-link:hover {\n background: var(--md-primary-container);\n color: var(--md-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(--md-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"] }]
322
323
  }], () => [{ type: i1.MJAuthBase }, { type: i2.SharedService }, { type: i0.ChangeDetectorRef }], null); })();
323
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserProfileComponent, { className: "UserProfileComponent", filePath: "src/lib/user-profile/user-profile.component.ts", lineNumber: 22 }); })();
324
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserProfileComponent, { className: "UserProfileComponent", filePath: "src/lib/user-profile/user-profile.component.ts", lineNumber: 23 }); })();
324
325
  //# sourceMappingURL=user-profile.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-profile.component.js","sourceRoot":"","sources":["../../../src/lib/user-profile/user-profile.component.ts","../../../src/lib/user-profile/user-profile.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { AuthService } from '@auth0/auth0-angular';\nimport { MJAuthBase, StandardUserInfo } from '@memberjunction/ng-auth-services';\nimport { UserInfoEngine, MJUserNotificationPreferenceEntity } from '@memberjunction/core-entities';\nimport { Metadata } from '@memberjunction/core';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { Observable, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\ninterface NotificationSummary {\n InAppEnabled: boolean;\n EmailEnabled: boolean;\n SMSEnabled: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'app-user-profile',\n templateUrl: './user-profile.component.html',\n styleUrls: ['./user-profile.component.css']\n})\nexport class UserProfileComponent implements OnInit, OnDestroy {\n public JSON: any = JSON;\n public User: Observable<StandardUserInfo | null>;\n public Loading = true;\n public Saving = false;\n public UnreadNotificationCount = 0;\n public NotificationSummary: NotificationSummary = {\n InAppEnabled: true,\n EmailEnabled: false,\n SMSEnabled: false\n };\n\n private destroy$ = new Subject<void>();\n\n constructor(\n public authBase: MJAuthBase,\n private sharedService: SharedService,\n private cdr: ChangeDetectorRef\n ) {\n // v3.0 API - User is now an observable that the template subscribes to\n this.User = authBase.getUserInfo();\n }\n\n async ngOnInit() {\n await this.LoadNotificationData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * Loads notification data from UserInfoEngine\n */\n private async LoadNotificationData() {\n try {\n this.Loading = true;\n\n // Get unread notification count\n this.UnreadNotificationCount = UserInfoEngine.Instance.UnreadNotificationCount;\n\n // Calculate global channel preferences\n const preferences = UserInfoEngine.Instance.NotificationPreferences;\n const types = UserInfoEngine.Instance.NotificationTypes;\n\n if (preferences.length === 0 && types.length > 0) {\n // No preferences set yet - use defaults from types\n const inApp = types.some(t => t.DefaultInApp ?? true);\n const email = types.some(t => t.DefaultEmail ?? false);\n const sms = types.some(t => t.DefaultSMS ?? false);\n\n this.NotificationSummary = {\n InAppEnabled: inApp,\n EmailEnabled: email,\n SMSEnabled: sms\n };\n } else if (preferences.length > 0) {\n // Calculate from existing preferences\n const inApp = preferences.some(p => p.InAppEnabled);\n const email = preferences.some(p => p.EmailEnabled);\n const sms = preferences.some(p => p.SMSEnabled);\n\n this.NotificationSummary = {\n InAppEnabled: inApp,\n EmailEnabled: email,\n SMSEnabled: sms\n };\n }\n\n this.Loading = false;\n this.cdr.detectChanges();\n } catch (error: unknown) {\n this.Loading = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to load notification data: ${message}`, 'error', 3000);\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Toggles a specific notification channel globally\n */\n async ToggleChannel(channel: 'InApp' | 'Email' | 'SMS'): Promise<void> {\n try {\n this.Saving = true;\n const md = new Metadata();\n const currentUser = md.CurrentUser;\n const transGroup = await md.CreateTransactionGroup();\n\n const types = UserInfoEngine.Instance.NotificationTypes;\n const preferences = UserInfoEngine.Instance.NotificationPreferences;\n\n // Determine new state\n let newState: boolean;\n if (channel === 'InApp') {\n newState = !this.NotificationSummary.InAppEnabled;\n this.NotificationSummary.InAppEnabled = newState;\n } else if (channel === 'Email') {\n newState = !this.NotificationSummary.EmailEnabled;\n this.NotificationSummary.EmailEnabled = newState;\n } else {\n newState = !this.NotificationSummary.SMSEnabled;\n this.NotificationSummary.SMSEnabled = newState;\n }\n\n // Update all notification types that allow user preference\n for (const type of types) {\n if (type.AllowUserPreference === false) {\n continue; // Skip locked types\n }\n\n let pref = preferences.find(p => p.NotificationTypeID === type.ID);\n\n if (!pref) {\n // Create new preference record\n pref = await md.GetEntityObject<MJUserNotificationPreferenceEntity>('MJ: User Notification Preferences');\n pref.UserID = currentUser.ID;\n pref.NotificationTypeID = type.ID;\n\n // Set defaults from type\n pref.InAppEnabled = type.DefaultInApp ?? true;\n pref.EmailEnabled = type.DefaultEmail ?? false;\n pref.SMSEnabled = type.DefaultSMS ?? false;\n }\n\n // Update the specific channel\n if (channel === 'InApp') {\n pref.InAppEnabled = newState;\n } else if (channel === 'Email') {\n pref.EmailEnabled = newState;\n } else {\n pref.SMSEnabled = newState;\n }\n\n // Set Enabled based on whether any channel is enabled\n pref.Enabled = pref.InAppEnabled || pref.EmailEnabled || pref.SMSEnabled;\n\n pref.TransactionGroup = transGroup;\n pref.Save();\n }\n\n // Submit transaction group\n const success = await transGroup.Submit();\n\n if (success) {\n this.sharedService.CreateSimpleNotification(\n `${channel} notifications ${newState ? 'enabled' : 'disabled'} globally`,\n 'success',\n 2500\n );\n } else {\n throw new Error('Failed to save preferences');\n }\n\n this.Saving = false;\n this.cdr.detectChanges();\n } catch (error: unknown) {\n this.Saving = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to update preferences: ${message}`, 'error', 3000);\n\n // Revert the UI state\n await this.LoadNotificationData();\n }\n }\n\n /**\n * Gets the appropriate icon for a channel\n */\n GetChannelIcon(channel: 'InApp' | 'Email' | 'SMS'): string {\n switch (channel) {\n case 'InApp': return 'fa-solid fa-bell';\n case 'Email': return 'fa-solid fa-envelope';\n case 'SMS': return 'fa-solid fa-mobile';\n default: return 'fa-solid fa-bell';\n }\n }\n\n /**\n * Gets the label for a channel\n */\n GetChannelLabel(channel: 'InApp' | 'Email' | 'SMS'): string {\n switch (channel) {\n case 'InApp': return 'In-App';\n case 'Email': return 'Email';\n case 'SMS': return 'SMS';\n default: return '';\n }\n }\n\n /**\n * Checks if a channel is enabled\n */\n IsChannelEnabled(channel: 'InApp' | 'Email' | 'SMS'): boolean {\n switch (channel) {\n case 'InApp': return this.NotificationSummary.InAppEnabled;\n case 'Email': return this.NotificationSummary.EmailEnabled;\n case 'SMS': return this.NotificationSummary.SMSEnabled;\n default: return false;\n }\n }\n}\n","@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}"]}
1
+ {"version":3,"file":"user-profile.component.js","sourceRoot":"","sources":["../../../src/lib/user-profile/user-profile.component.ts","../../../src/lib/user-profile/user-profile.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { AuthService } from '@auth0/auth0-angular';\nimport { MJAuthBase, StandardUserInfo } from '@memberjunction/ng-auth-services';\nimport { UserInfoEngine, MJUserNotificationPreferenceEntity } from '@memberjunction/core-entities';\nimport { Metadata } from '@memberjunction/core';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { Observable, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { UUIDsEqual } from '@memberjunction/global';\n\ninterface NotificationSummary {\n InAppEnabled: boolean;\n EmailEnabled: boolean;\n SMSEnabled: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'app-user-profile',\n templateUrl: './user-profile.component.html',\n styleUrls: ['./user-profile.component.css']\n})\nexport class UserProfileComponent implements OnInit, OnDestroy {\n public JSON: any = JSON;\n public User: Observable<StandardUserInfo | null>;\n public Loading = true;\n public Saving = false;\n public UnreadNotificationCount = 0;\n public NotificationSummary: NotificationSummary = {\n InAppEnabled: true,\n EmailEnabled: false,\n SMSEnabled: false\n };\n\n private destroy$ = new Subject<void>();\n\n constructor(\n public authBase: MJAuthBase,\n private sharedService: SharedService,\n private cdr: ChangeDetectorRef\n ) {\n // v3.0 API - User is now an observable that the template subscribes to\n this.User = authBase.getUserInfo();\n }\n\n async ngOnInit() {\n await this.LoadNotificationData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * Loads notification data from UserInfoEngine\n */\n private async LoadNotificationData() {\n try {\n this.Loading = true;\n\n // Get unread notification count\n this.UnreadNotificationCount = UserInfoEngine.Instance.UnreadNotificationCount;\n\n // Calculate global channel preferences\n const preferences = UserInfoEngine.Instance.NotificationPreferences;\n const types = UserInfoEngine.Instance.NotificationTypes;\n\n if (preferences.length === 0 && types.length > 0) {\n // No preferences set yet - use defaults from types\n const inApp = types.some(t => t.DefaultInApp ?? true);\n const email = types.some(t => t.DefaultEmail ?? false);\n const sms = types.some(t => t.DefaultSMS ?? false);\n\n this.NotificationSummary = {\n InAppEnabled: inApp,\n EmailEnabled: email,\n SMSEnabled: sms\n };\n } else if (preferences.length > 0) {\n // Calculate from existing preferences\n const inApp = preferences.some(p => p.InAppEnabled);\n const email = preferences.some(p => p.EmailEnabled);\n const sms = preferences.some(p => p.SMSEnabled);\n\n this.NotificationSummary = {\n InAppEnabled: inApp,\n EmailEnabled: email,\n SMSEnabled: sms\n };\n }\n\n this.Loading = false;\n this.cdr.detectChanges();\n } catch (error: unknown) {\n this.Loading = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to load notification data: ${message}`, 'error', 3000);\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Toggles a specific notification channel globally\n */\n async ToggleChannel(channel: 'InApp' | 'Email' | 'SMS'): Promise<void> {\n try {\n this.Saving = true;\n const md = new Metadata();\n const currentUser = md.CurrentUser;\n const transGroup = await md.CreateTransactionGroup();\n\n const types = UserInfoEngine.Instance.NotificationTypes;\n const preferences = UserInfoEngine.Instance.NotificationPreferences;\n\n // Determine new state\n let newState: boolean;\n if (channel === 'InApp') {\n newState = !this.NotificationSummary.InAppEnabled;\n this.NotificationSummary.InAppEnabled = newState;\n } else if (channel === 'Email') {\n newState = !this.NotificationSummary.EmailEnabled;\n this.NotificationSummary.EmailEnabled = newState;\n } else {\n newState = !this.NotificationSummary.SMSEnabled;\n this.NotificationSummary.SMSEnabled = newState;\n }\n\n // Update all notification types that allow user preference\n for (const type of types) {\n if (type.AllowUserPreference === false) {\n continue; // Skip locked types\n }\n\n let pref = preferences.find(p => UUIDsEqual(p.NotificationTypeID, type.ID));\n\n if (!pref) {\n // Create new preference record\n pref = await md.GetEntityObject<MJUserNotificationPreferenceEntity>('MJ: User Notification Preferences');\n pref.UserID = currentUser.ID;\n pref.NotificationTypeID = type.ID;\n\n // Set defaults from type\n pref.InAppEnabled = type.DefaultInApp ?? true;\n pref.EmailEnabled = type.DefaultEmail ?? false;\n pref.SMSEnabled = type.DefaultSMS ?? false;\n }\n\n // Update the specific channel\n if (channel === 'InApp') {\n pref.InAppEnabled = newState;\n } else if (channel === 'Email') {\n pref.EmailEnabled = newState;\n } else {\n pref.SMSEnabled = newState;\n }\n\n // Set Enabled based on whether any channel is enabled\n pref.Enabled = pref.InAppEnabled || pref.EmailEnabled || pref.SMSEnabled;\n\n pref.TransactionGroup = transGroup;\n pref.Save();\n }\n\n // Submit transaction group\n const success = await transGroup.Submit();\n\n if (success) {\n this.sharedService.CreateSimpleNotification(\n `${channel} notifications ${newState ? 'enabled' : 'disabled'} globally`,\n 'success',\n 2500\n );\n } else {\n throw new Error('Failed to save preferences');\n }\n\n this.Saving = false;\n this.cdr.detectChanges();\n } catch (error: unknown) {\n this.Saving = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to update preferences: ${message}`, 'error', 3000);\n\n // Revert the UI state\n await this.LoadNotificationData();\n }\n }\n\n /**\n * Gets the appropriate icon for a channel\n */\n GetChannelIcon(channel: 'InApp' | 'Email' | 'SMS'): string {\n switch (channel) {\n case 'InApp': return 'fa-solid fa-bell';\n case 'Email': return 'fa-solid fa-envelope';\n case 'SMS': return 'fa-solid fa-mobile';\n default: return 'fa-solid fa-bell';\n }\n }\n\n /**\n * Gets the label for a channel\n */\n GetChannelLabel(channel: 'InApp' | 'Email' | 'SMS'): string {\n switch (channel) {\n case 'InApp': return 'In-App';\n case 'Email': return 'Email';\n case 'SMS': return 'SMS';\n default: return '';\n }\n }\n\n /**\n * Checks if a channel is enabled\n */\n IsChannelEnabled(channel: 'InApp' | 'Email' | 'SMS'): boolean {\n switch (channel) {\n case 'InApp': return this.NotificationSummary.InAppEnabled;\n case 'Email': return this.NotificationSummary.EmailEnabled;\n case 'SMS': return this.NotificationSummary.SMSEnabled;\n default: return false;\n }\n }\n}\n","@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}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-explorer-core",
3
- "version": "5.4.1",
3
+ "version": "5.5.0",
4
4
  "description": "MemberJunction Explorer: Core Angular Components",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -30,39 +30,39 @@
30
30
  "@angular/cdk": "21.1.3",
31
31
  "@angular/platform-browser": "21.1.3",
32
32
  "@auth0/auth0-angular": "^2.6.0",
33
- "@memberjunction/ai-core-plus": "5.4.1",
34
- "@memberjunction/ai-engine-base": "5.4.1",
35
- "@memberjunction/communication-types": "5.4.1",
36
- "@memberjunction/core": "5.4.1",
37
- "@memberjunction/core-entities": "5.4.1",
38
- "@memberjunction/entity-communications-client": "5.4.1",
39
- "@memberjunction/global": "5.4.1",
40
- "@memberjunction/graphql-dataprovider": "5.4.1",
41
- "@memberjunction/ng-ai-test-harness": "5.4.1",
42
- "@memberjunction/ng-artifacts": "5.4.1",
43
- "@memberjunction/ng-auth-services": "5.4.1",
44
- "@memberjunction/ng-base-application": "5.4.1",
45
- "@memberjunction/ng-base-forms": "5.4.1",
46
- "@memberjunction/ng-container-directives": "5.4.1",
47
- "@memberjunction/ng-conversations": "5.4.1",
48
- "@memberjunction/ng-dashboards": "5.4.1",
49
- "@memberjunction/ng-entity-form-dialog": "5.4.1",
50
- "@memberjunction/ng-entity-permissions": "5.4.1",
51
- "@memberjunction/ng-dashboard-viewer": "5.4.1",
52
- "@memberjunction/ng-entity-viewer": "5.4.1",
53
- "@memberjunction/ng-list-detail-grid": "5.4.1",
54
- "@memberjunction/ng-explorer-settings": "5.4.1",
55
- "@memberjunction/ng-file-storage": "5.4.1",
56
- "@memberjunction/ng-generic-dialog": "5.4.1",
57
- "@memberjunction/ng-notifications": "5.4.1",
58
- "@memberjunction/ng-query-viewer": "5.4.1",
59
- "@memberjunction/ng-record-changes": "5.4.1",
60
- "@memberjunction/ng-record-selector": "5.4.1",
61
- "@memberjunction/ng-resource-permissions": "5.4.1",
62
- "@memberjunction/ng-shared": "5.4.1",
63
- "@memberjunction/ng-shared-generic": "5.4.1",
64
- "@memberjunction/ng-user-avatar": "5.4.1",
65
- "@memberjunction/templates-base-types": "5.4.1",
33
+ "@memberjunction/ai-core-plus": "5.5.0",
34
+ "@memberjunction/ai-engine-base": "5.5.0",
35
+ "@memberjunction/communication-types": "5.5.0",
36
+ "@memberjunction/core": "5.5.0",
37
+ "@memberjunction/core-entities": "5.5.0",
38
+ "@memberjunction/entity-communications-client": "5.5.0",
39
+ "@memberjunction/global": "5.5.0",
40
+ "@memberjunction/graphql-dataprovider": "5.5.0",
41
+ "@memberjunction/ng-ai-test-harness": "5.5.0",
42
+ "@memberjunction/ng-artifacts": "5.5.0",
43
+ "@memberjunction/ng-auth-services": "5.5.0",
44
+ "@memberjunction/ng-base-application": "5.5.0",
45
+ "@memberjunction/ng-base-forms": "5.5.0",
46
+ "@memberjunction/ng-container-directives": "5.5.0",
47
+ "@memberjunction/ng-conversations": "5.5.0",
48
+ "@memberjunction/ng-dashboards": "5.5.0",
49
+ "@memberjunction/ng-entity-form-dialog": "5.5.0",
50
+ "@memberjunction/ng-entity-permissions": "5.5.0",
51
+ "@memberjunction/ng-dashboard-viewer": "5.5.0",
52
+ "@memberjunction/ng-entity-viewer": "5.5.0",
53
+ "@memberjunction/ng-list-detail-grid": "5.5.0",
54
+ "@memberjunction/ng-explorer-settings": "5.5.0",
55
+ "@memberjunction/ng-file-storage": "5.5.0",
56
+ "@memberjunction/ng-generic-dialog": "5.5.0",
57
+ "@memberjunction/ng-notifications": "5.5.0",
58
+ "@memberjunction/ng-query-viewer": "5.5.0",
59
+ "@memberjunction/ng-record-changes": "5.5.0",
60
+ "@memberjunction/ng-record-selector": "5.5.0",
61
+ "@memberjunction/ng-resource-permissions": "5.5.0",
62
+ "@memberjunction/ng-shared": "5.5.0",
63
+ "@memberjunction/ng-shared-generic": "5.5.0",
64
+ "@memberjunction/ng-user-avatar": "5.5.0",
65
+ "@memberjunction/templates-base-types": "5.5.0",
66
66
  "@progress/kendo-angular-buttons": "22.0.1",
67
67
  "@progress/kendo-angular-dateinputs": "22.0.1",
68
68
  "@progress/kendo-angular-dialog": "22.0.1",