@memberjunction/ng-explorer-core 5.30.1 → 5.31.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 (83) hide show
  1. package/dist/app-routing.module.d.ts +9 -0
  2. package/dist/app-routing.module.d.ts.map +1 -1
  3. package/dist/app-routing.module.js +13 -1
  4. package/dist/app-routing.module.js.map +1 -1
  5. package/dist/generated/lazy-feature-config.d.ts +1 -1
  6. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  7. package/dist/generated/lazy-feature-config.js +5 -3
  8. package/dist/generated/lazy-feature-config.js.map +1 -1
  9. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts +2 -1
  10. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -1
  11. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +12 -11
  12. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
  13. package/dist/lib/guards/entities.guard.d.ts +2 -1
  14. package/dist/lib/guards/entities.guard.d.ts.map +1 -1
  15. package/dist/lib/guards/entities.guard.js +14 -1
  16. package/dist/lib/guards/entities.guard.js.map +1 -1
  17. package/dist/lib/oauth/oauth-callback.component.d.ts +2 -1
  18. package/dist/lib/oauth/oauth-callback.component.d.ts.map +1 -1
  19. package/dist/lib/oauth/oauth-callback.component.js +7 -6
  20. package/dist/lib/oauth/oauth-callback.component.js.map +1 -1
  21. package/dist/lib/resource-wrappers/artifact-resource.component.js +2 -3
  22. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
  23. package/dist/lib/resource-wrappers/chat-collections-resource.component.js +3 -3
  24. package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
  25. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +4 -4
  26. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  27. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +1 -2
  28. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
  29. package/dist/lib/resource-wrappers/dashboard-resource.component.js +5 -5
  30. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  31. package/dist/lib/resource-wrappers/list-detail-resource.component.js +2 -2
  32. package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
  33. package/dist/lib/resource-wrappers/query-resource.component.js +2 -2
  34. package/dist/lib/resource-wrappers/query-resource.component.js.map +1 -1
  35. package/dist/lib/resource-wrappers/record-resource.component.d.ts +2 -2
  36. package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
  37. package/dist/lib/resource-wrappers/record-resource.component.js +8 -7
  38. package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
  39. package/dist/lib/resource-wrappers/search-results-resource.component.js +3 -3
  40. package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
  41. package/dist/lib/resource-wrappers/view-resource.component.d.ts +1 -1
  42. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  43. package/dist/lib/resource-wrappers/view-resource.component.js +3 -3
  44. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  45. package/dist/lib/services/startup-validation.service.d.ts +9 -0
  46. package/dist/lib/services/startup-validation.service.d.ts.map +1 -1
  47. package/dist/lib/services/startup-validation.service.js +13 -1
  48. package/dist/lib/services/startup-validation.service.js.map +1 -1
  49. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +2 -1
  50. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  51. package/dist/lib/shell/components/tabs/tab-container.component.js +7 -5
  52. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  53. package/dist/lib/shell/shell.component.d.ts +5 -2
  54. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  55. package/dist/lib/shell/shell.component.js +43 -27
  56. package/dist/lib/shell/shell.component.js.map +1 -1
  57. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts +3 -2
  58. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
  59. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +8 -6
  60. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
  61. package/dist/lib/single-dashboard/single-dashboard.component.js +1 -2
  62. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  63. package/dist/lib/single-list-detail/single-list-detail.component.d.ts +2 -1
  64. package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
  65. package/dist/lib/single-list-detail/single-list-detail.component.js +18 -16
  66. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  67. package/dist/lib/single-record/single-record.component.d.ts +2 -1
  68. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  69. package/dist/lib/single-record/single-record.component.js +7 -5
  70. package/dist/lib/single-record/single-record.component.js.map +1 -1
  71. package/dist/lib/single-search-result/single-search-result.component.d.ts +2 -1
  72. package/dist/lib/single-search-result/single-search-result.component.d.ts.map +1 -1
  73. package/dist/lib/single-search-result/single-search-result.component.js +8 -6
  74. package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
  75. package/dist/lib/user-notifications/user-notifications.component.d.ts +2 -1
  76. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  77. package/dist/lib/user-notifications/user-notifications.component.js +9 -7
  78. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  79. package/dist/lib/user-profile/user-profile.component.d.ts +2 -1
  80. package/dist/lib/user-profile/user-profile.component.d.ts.map +1 -1
  81. package/dist/lib/user-profile/user-profile.component.js +6 -5
  82. package/dist/lib/user-profile/user-profile.component.js.map +1 -1
  83. package/package.json +42 -41
@@ -1 +1 @@
1
- {"version":3,"file":"single-search-result.component.js","sourceRoot":"","sources":["../../../src/lib/single-search-result/single-search-result.component.ts","../../../src/lib/single-search-result/single-search-result.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output, ChangeDetectorRef, OnChanges, SimpleChanges } from '@angular/core';\nimport { RunView, CompositeKey, EntityInfo, EntityFieldTSType, Metadata } from '@memberjunction/core';\nimport { NavigationService } from '@memberjunction/ng-shared';\nimport { DataLoadedEvent, RecordOpenedEvent, EntityViewerConfig, EntityViewMode, GridToolbarConfig } from '@memberjunction/ng-entity-viewer';\n\ntype SearchState = 'loading' | 'no-results' | 'single-result' | 'viewer';\n\n@Component({\n standalone: false,\n selector: 'mj-single-search-result',\n templateUrl: './single-search-result.component.html',\n styleUrls: ['./single-search-result.component.css']\n})\nexport class SingleSearchResultComponent implements OnChanges {\n @Input() public entity: string = '';\n @Input() public searchInput: string = '';\n @Output() public loadComplete = new EventEmitter<boolean>();\n @Output() public loadStarted = new EventEmitter<boolean>();\n\n public SearchState: SearchState = 'loading';\n public ResultCount = 0;\n public EntityInfo: EntityInfo | null = null;\n public CurrentViewMode: EntityViewMode = 'grid';\n\n /** Whether the current entity has date fields (enables timeline view toggle) */\n public get HasDateFields(): boolean {\n if (!this.EntityInfo) return false;\n return this.EntityInfo.Fields.some(f => f.TSType === EntityFieldTSType.Date);\n }\n\n /** Resolved icon class for the entity, matching Data Explorer's format */\n public get EntityIcon(): string {\n if (this.EntityInfo?.Icon) {\n return this.formatEntityIcon(this.EntityInfo.Icon);\n }\n return 'fa-solid fa-table';\n }\n\n /** Configuration for the entity-viewer — matches the Data Explorer's setup */\n public ViewerConfig: Partial<EntityViewerConfig> = {\n showFilter: false,\n showViewModeToggle: false,\n showRecordCount: false,\n showPagination: true,\n serverSideFiltering: true,\n serverSideSorting: true,\n height: '100%'\n };\n\n /** Grid toolbar config — minimal action bar (no search, no column chooser) */\n public GridToolbarConfig: Partial<GridToolbarConfig> = {\n showSearch: false,\n showRefresh: true,\n showAdd: true,\n showExport: true,\n showDelete: false,\n showColumnChooser: false,\n showRowCount: false,\n showSelectionCount: false\n };\n\n constructor(\n private navigationService: NavigationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnChanges(changes: SimpleChanges): void {\n if ((changes['entity'] || changes['searchInput']) && this.entity && this.searchInput) {\n this.ExecuteSearch();\n }\n }\n\n /**\n * Runs a lightweight pre-query (MaxRows: 2, PK fields only) to determine result count,\n * then routes to the appropriate state: no-results, single-result auto-nav, or viewer.\n */\n private async ExecuteSearch(): Promise<void> {\n this.SearchState = 'loading';\n this.ResultCount = 0;\n this.CurrentViewMode = 'grid';\n this.loadStarted.emit(true);\n\n // Resolve EntityInfo early so the header can show icon + display name during loading\n const entityInfo = this.findEntityInfo();\n this.EntityInfo = entityInfo ?? null;\n this.cdr.detectChanges();\n\n if (!entityInfo) {\n this.setNoResults();\n return;\n }\n\n const result = await this.runPreQuery(entityInfo);\n if (!result.Success || result.Results.length === 0) {\n this.setNoResults();\n return;\n }\n\n if (result.Results.length === 1) {\n this.navigateToSingleResult(entityInfo, result.Results[0]);\n return;\n }\n\n // 2+ results — show the entity-viewer\n this.SearchState = 'viewer';\n this.cdr.detectChanges();\n }\n\n private findEntityInfo(): EntityInfo | undefined {\n const md = new Metadata();\n return md.Entities.find(e =>\n e.Name.trim().toLowerCase() === this.entity.trim().toLowerCase()\n );\n }\n\n private async runPreQuery(entityInfo: EntityInfo) {\n const rv = new RunView();\n const pkFields = entityInfo.PrimaryKeys.map(pk => pk.Name);\n return rv.RunView<Record<string, unknown>>({\n EntityName: this.entity,\n ExtraFilter: 'ID IS NOT NULL',\n UserSearchString: this.searchInput,\n Fields: pkFields,\n ResultType: 'simple',\n MaxRows: 2,\n });\n }\n\n private setNoResults(): void {\n this.SearchState = 'no-results';\n this.ResultCount = 0;\n this.loadComplete.emit(true);\n this.cdr.detectChanges();\n }\n\n private navigateToSingleResult(entityInfo: EntityInfo, record: Record<string, unknown>): void {\n this.SearchState = 'single-result';\n this.ResultCount = 1;\n this.cdr.detectChanges();\n\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromEntityInfoAndRecord(entityInfo, record);\n this.navigationService.OpenEntityRecord(entityInfo.Name, compositeKey);\n this.loadComplete.emit(true);\n }\n\n // ── Header action handlers ──\n\n public SetViewMode(mode: EntityViewMode): void {\n this.CurrentViewMode = mode;\n this.cdr.detectChanges();\n }\n\n public OnViewModeChanged(mode: EntityViewMode): void {\n this.CurrentViewMode = mode;\n this.cdr.detectChanges();\n }\n\n public OnCreateNewRecord(): void {\n if (this.EntityInfo) {\n this.navigationService.OpenNewEntityRecord(this.EntityInfo.Name);\n }\n }\n\n // ── Entity-viewer event handlers ──\n\n public OnDataLoaded(event: DataLoadedEvent): void {\n this.ResultCount = event.totalRowCount;\n this.loadComplete.emit(true);\n this.cdr.detectChanges();\n }\n\n public OnRecordOpened(event: RecordOpenedEvent): void {\n this.navigationService.OpenEntityRecord(event.entity.Name, event.compositeKey);\n }\n\n /** Format entity icon to ensure proper Font Awesome class format */\n private formatEntityIcon(icon: string): string {\n if (!icon) {\n return 'fa-solid fa-table';\n }\n if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||\n icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||\n icon.startsWith('fa ')) {\n return icon;\n }\n if (icon.startsWith('fa-')) {\n return `fa-solid ${icon}`;\n }\n return `fa-solid fa-${icon}`;\n }\n}\n","<div class=\"search-result-container\">\n <!-- Content Header — matches Data Explorer layout -->\n <div class=\"content-header\">\n <div class=\"header-left\">\n <i [class]=\"EntityIcon\" class=\"entity-icon\"></i>\n <h2 class=\"entity-title\">{{ EntityInfo?.DisplayNameOrName || entity }}</h2>\n @if (SearchState === 'loading') {\n <span class=\"record-count\">Searching for \"{{ searchInput }}\"...</span>\n } @else if (SearchState === 'no-results') {\n <span class=\"record-count\">No results for \"{{ searchInput }}\"</span>\n } @else if (ResultCount > 0) {\n <span class=\"record-count\">{{ ResultCount | number }} {{ ResultCount === 1 ? 'result' : 'results' }} for \"{{ searchInput }}\"</span>\n }\n </div>\n\n @if (SearchState === 'viewer' && EntityInfo) {\n <div class=\"header-right\">\n <!-- New Record -->\n <button\n class=\"header-action-btn\"\n (click)=\"OnCreateNewRecord()\"\n title=\"New Record\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n\n <!-- View Mode Toggle -->\n <div class=\"view-mode-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"CurrentViewMode === 'grid'\"\n (click)=\"SetViewMode('grid')\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"CurrentViewMode === 'cards'\"\n (click)=\"SetViewMode('cards')\"\n title=\"Cards View\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n @if (HasDateFields) {\n <button\n class=\"toggle-btn\"\n [class.active]=\"CurrentViewMode === 'timeline'\"\n (click)=\"SetViewMode('timeline')\"\n title=\"Timeline View\">\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Loading state -->\n @if (SearchState === 'loading') {\n <div class=\"loading-container\">\n <mj-loading text=\"Searching...\"></mj-loading>\n </div>\n }\n\n <!-- No results -->\n @if (SearchState === 'no-results') {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-magnifying-glass empty-icon\"></i>\n <p>No results found for \"<strong>{{ searchInput }}</strong>\" in {{ entity }}</p>\n <p class=\"empty-hint\">Try a different search term or entity</p>\n </div>\n }\n\n <!-- Single result — auto-navigating to entity form -->\n @if (SearchState === 'single-result') {\n <div class=\"single-result-state\">\n <i class=\"fa-solid fa-arrow-right redirect-icon\"></i>\n <p>Found 1 result &mdash; opening record...</p>\n </div>\n }\n\n <!-- Entity Viewer (2+ results) -->\n @if (SearchState === 'viewer' && EntityInfo) {\n <div class=\"viewer-container\">\n <mj-entity-viewer\n [entity]=\"EntityInfo\"\n [viewMode]=\"CurrentViewMode\"\n [filterText]=\"searchInput\"\n [config]=\"ViewerConfig\"\n [showGridToolbar]=\"true\"\n [gridToolbarConfig]=\"GridToolbarConfig\"\n (viewModeChange)=\"OnViewModeChanged($event)\"\n (dataLoaded)=\"OnDataLoaded($event)\"\n (recordOpened)=\"OnRecordOpened($event)\"\n (addRequested)=\"OnCreateNewRecord()\">\n </mj-entity-viewer>\n </div>\n }\n</div>\n"]}
1
+ {"version":3,"file":"single-search-result.component.js","sourceRoot":"","sources":["../../../src/lib/single-search-result/single-search-result.component.ts","../../../src/lib/single-search-result/single-search-result.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output, ChangeDetectorRef, OnChanges, SimpleChanges } from '@angular/core';\nimport { RunView, CompositeKey, EntityInfo, EntityFieldTSType, Metadata } from '@memberjunction/core';\nimport { NavigationService } from '@memberjunction/ng-shared';\nimport { DataLoadedEvent, RecordOpenedEvent, EntityViewerConfig, EntityViewMode, GridToolbarConfig } from '@memberjunction/ng-entity-viewer';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\ntype SearchState = 'loading' | 'no-results' | 'single-result' | 'viewer';\n\n@Component({\n standalone: false,\n selector: 'mj-single-search-result',\n templateUrl: './single-search-result.component.html',\n styleUrls: ['./single-search-result.component.css']\n})\nexport class SingleSearchResultComponent extends BaseAngularComponent implements OnChanges {\n @Input() public entity: string = '';\n @Input() public searchInput: string = '';\n @Output() public loadComplete = new EventEmitter<boolean>();\n @Output() public loadStarted = new EventEmitter<boolean>();\n\n public SearchState: SearchState = 'loading';\n public ResultCount = 0;\n public EntityInfo: EntityInfo | null = null;\n public CurrentViewMode: EntityViewMode = 'grid';\n\n /** Whether the current entity has date fields (enables timeline view toggle) */\n public get HasDateFields(): boolean {\n if (!this.EntityInfo) return false;\n return this.EntityInfo.Fields.some(f => f.TSType === EntityFieldTSType.Date);\n }\n\n /** Resolved icon class for the entity, matching Data Explorer's format */\n public get EntityIcon(): string {\n if (this.EntityInfo?.Icon) {\n return this.formatEntityIcon(this.EntityInfo.Icon);\n }\n return 'fa-solid fa-table';\n }\n\n /** Configuration for the entity-viewer — matches the Data Explorer's setup */\n public ViewerConfig: Partial<EntityViewerConfig> = {\n showFilter: false,\n showViewModeToggle: false,\n showRecordCount: false,\n showPagination: true,\n serverSideFiltering: true,\n serverSideSorting: true,\n height: '100%'\n };\n\n /** Grid toolbar config — minimal action bar (no search, no column chooser) */\n public GridToolbarConfig: Partial<GridToolbarConfig> = {\n showSearch: false,\n showRefresh: true,\n showAdd: true,\n showExport: true,\n showDelete: false,\n showColumnChooser: false,\n showRowCount: false,\n showSelectionCount: false\n };\n\n constructor(\n private navigationService: NavigationService,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n ngOnChanges(changes: SimpleChanges): void {\n if ((changes['entity'] || changes['searchInput']) && this.entity && this.searchInput) {\n this.ExecuteSearch();\n }\n }\n\n /**\n * Runs a lightweight pre-query (MaxRows: 2, PK fields only) to determine result count,\n * then routes to the appropriate state: no-results, single-result auto-nav, or viewer.\n */\n private async ExecuteSearch(): Promise<void> {\n this.SearchState = 'loading';\n this.ResultCount = 0;\n this.CurrentViewMode = 'grid';\n this.loadStarted.emit(true);\n\n // Resolve EntityInfo early so the header can show icon + display name during loading\n const entityInfo = this.findEntityInfo();\n this.EntityInfo = entityInfo ?? null;\n this.cdr.detectChanges();\n\n if (!entityInfo) {\n this.setNoResults();\n return;\n }\n\n const result = await this.runPreQuery(entityInfo);\n if (!result.Success || result.Results.length === 0) {\n this.setNoResults();\n return;\n }\n\n if (result.Results.length === 1) {\n this.navigateToSingleResult(entityInfo, result.Results[0]);\n return;\n }\n\n // 2+ results — show the entity-viewer\n this.SearchState = 'viewer';\n this.cdr.detectChanges();\n }\n\n private findEntityInfo(): EntityInfo | undefined {\n const md = this.ProviderToUse;\n return md.Entities.find(e =>\n e.Name.trim().toLowerCase() === this.entity.trim().toLowerCase()\n );\n }\n\n private async runPreQuery(entityInfo: EntityInfo) {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const pkFields = entityInfo.PrimaryKeys.map(pk => pk.Name);\n return rv.RunView<Record<string, unknown>>({\n EntityName: this.entity,\n ExtraFilter: 'ID IS NOT NULL',\n UserSearchString: this.searchInput,\n Fields: pkFields,\n ResultType: 'simple',\n MaxRows: 2,\n });\n }\n\n private setNoResults(): void {\n this.SearchState = 'no-results';\n this.ResultCount = 0;\n this.loadComplete.emit(true);\n this.cdr.detectChanges();\n }\n\n private navigateToSingleResult(entityInfo: EntityInfo, record: Record<string, unknown>): void {\n this.SearchState = 'single-result';\n this.ResultCount = 1;\n this.cdr.detectChanges();\n\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromEntityInfoAndRecord(entityInfo, record);\n this.navigationService.OpenEntityRecord(entityInfo.Name, compositeKey);\n this.loadComplete.emit(true);\n }\n\n // ── Header action handlers ──\n\n public SetViewMode(mode: EntityViewMode): void {\n this.CurrentViewMode = mode;\n this.cdr.detectChanges();\n }\n\n public OnViewModeChanged(mode: EntityViewMode): void {\n this.CurrentViewMode = mode;\n this.cdr.detectChanges();\n }\n\n public OnCreateNewRecord(): void {\n if (this.EntityInfo) {\n this.navigationService.OpenNewEntityRecord(this.EntityInfo.Name);\n }\n }\n\n // ── Entity-viewer event handlers ──\n\n public OnDataLoaded(event: DataLoadedEvent): void {\n this.ResultCount = event.totalRowCount;\n this.loadComplete.emit(true);\n this.cdr.detectChanges();\n }\n\n public OnRecordOpened(event: RecordOpenedEvent): void {\n this.navigationService.OpenEntityRecord(event.entity.Name, event.compositeKey);\n }\n\n /** Format entity icon to ensure proper Font Awesome class format */\n private formatEntityIcon(icon: string): string {\n if (!icon) {\n return 'fa-solid fa-table';\n }\n if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||\n icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||\n icon.startsWith('fa ')) {\n return icon;\n }\n if (icon.startsWith('fa-')) {\n return `fa-solid ${icon}`;\n }\n return `fa-solid fa-${icon}`;\n }\n}\n","<div class=\"search-result-container\">\n <!-- Content Header — matches Data Explorer layout -->\n <div class=\"content-header\">\n <div class=\"header-left\">\n <i [class]=\"EntityIcon\" class=\"entity-icon\"></i>\n <h2 class=\"entity-title\">{{ EntityInfo?.DisplayNameOrName || entity }}</h2>\n @if (SearchState === 'loading') {\n <span class=\"record-count\">Searching for \"{{ searchInput }}\"...</span>\n } @else if (SearchState === 'no-results') {\n <span class=\"record-count\">No results for \"{{ searchInput }}\"</span>\n } @else if (ResultCount > 0) {\n <span class=\"record-count\">{{ ResultCount | number }} {{ ResultCount === 1 ? 'result' : 'results' }} for \"{{ searchInput }}\"</span>\n }\n </div>\n\n @if (SearchState === 'viewer' && EntityInfo) {\n <div class=\"header-right\">\n <!-- New Record -->\n <button\n class=\"header-action-btn\"\n (click)=\"OnCreateNewRecord()\"\n title=\"New Record\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n\n <!-- View Mode Toggle -->\n <div class=\"view-mode-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"CurrentViewMode === 'grid'\"\n (click)=\"SetViewMode('grid')\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"CurrentViewMode === 'cards'\"\n (click)=\"SetViewMode('cards')\"\n title=\"Cards View\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n @if (HasDateFields) {\n <button\n class=\"toggle-btn\"\n [class.active]=\"CurrentViewMode === 'timeline'\"\n (click)=\"SetViewMode('timeline')\"\n title=\"Timeline View\">\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Loading state -->\n @if (SearchState === 'loading') {\n <div class=\"loading-container\">\n <mj-loading text=\"Searching...\"></mj-loading>\n </div>\n }\n\n <!-- No results -->\n @if (SearchState === 'no-results') {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-magnifying-glass empty-icon\"></i>\n <p>No results found for \"<strong>{{ searchInput }}</strong>\" in {{ entity }}</p>\n <p class=\"empty-hint\">Try a different search term or entity</p>\n </div>\n }\n\n <!-- Single result — auto-navigating to entity form -->\n @if (SearchState === 'single-result') {\n <div class=\"single-result-state\">\n <i class=\"fa-solid fa-arrow-right redirect-icon\"></i>\n <p>Found 1 result &mdash; opening record...</p>\n </div>\n }\n\n <!-- Entity Viewer (2+ results) -->\n @if (SearchState === 'viewer' && EntityInfo) {\n <div class=\"viewer-container\">\n <mj-entity-viewer\n [entity]=\"EntityInfo\"\n [viewMode]=\"CurrentViewMode\"\n [filterText]=\"searchInput\"\n [config]=\"ViewerConfig\"\n [showGridToolbar]=\"true\"\n [gridToolbarConfig]=\"GridToolbarConfig\"\n (viewModeChange)=\"OnViewModeChanged($event)\"\n (dataLoaded)=\"OnDataLoaded($event)\"\n (recordOpened)=\"OnRecordOpened($event)\"\n (addRequested)=\"OnCreateNewRecord()\">\n </mj-entity-viewer>\n </div>\n }\n</div>\n"]}
@@ -3,6 +3,7 @@ import { SharedService, NavigationService } from '@memberjunction/ng-shared';
3
3
  import { MJUserNotificationEntity, MJUserNotificationTypeEntity } from '@memberjunction/core-entities';
4
4
  import { TransactionGroupBase } from '@memberjunction/core';
5
5
  import { ApplicationManager } from '@memberjunction/ng-base-application';
6
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
6
7
  import * as i0 from "@angular/core";
7
8
  /**
8
9
  * Radio button filter options for notification read status
@@ -15,7 +16,7 @@ interface NotificationUrlInfo {
15
16
  urlParts: string[];
16
17
  queryString: string;
17
18
  }
18
- export declare class UserNotificationsComponent implements OnInit, AfterViewInit {
19
+ export declare class UserNotificationsComponent extends BaseAngularComponent implements OnInit, AfterViewInit {
19
20
  sharedService: SharedService;
20
21
  private navigationService;
21
22
  private appManager;
@@ -1 +1 @@
1
- {"version":3,"file":"user-notifications.component.d.ts","sourceRoot":"","sources":["../../../src/lib/user-notifications/user-notifications.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user-notifications.component.d.ts","sourceRoot":"","sources":["../../../src/lib/user-notifications/user-notifications.component.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { Component, ViewChild } from '@angular/core';
2
2
  import { SharedService } from '@memberjunction/ng-shared';
3
3
  import { MJUserNotificationEntity, UserInfoEngine } from '@memberjunction/core-entities';
4
- import { Metadata, TransactionVariable, CompositeKey } from '@memberjunction/core';
4
+ import { TransactionVariable, CompositeKey } from '@memberjunction/core';
5
5
  import { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';
6
6
  import { MJNotificationService } from '@memberjunction/ng-notifications';
7
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
7
8
  import * as i0 from "@angular/core";
8
9
  import * as i1 from "@memberjunction/ng-shared";
9
10
  import * as i2 from "@memberjunction/ng-base-application";
@@ -276,7 +277,7 @@ function UserNotificationsComponent_Conditional_13_Template(rf, ctx) { if (rf &
276
277
  i0.ɵɵadvance();
277
278
  i0.ɵɵrepeater(ctx_r1.NotificationsToShow);
278
279
  } }
279
- export class UserNotificationsComponent {
280
+ export class UserNotificationsComponent extends BaseAngularComponent {
280
281
  sharedService;
281
282
  navigationService;
282
283
  appManager;
@@ -289,6 +290,7 @@ export class UserNotificationsComponent {
289
290
  selectedTypeFilter = null;
290
291
  loadingTypes = true;
291
292
  constructor(sharedService, navigationService, appManager) {
293
+ super();
292
294
  this.sharedService = sharedService;
293
295
  this.navigationService = navigationService;
294
296
  this.appManager = appManager;
@@ -456,7 +458,7 @@ export class UserNotificationsComponent {
456
458
  }
457
459
  else {
458
460
  // the passed in param is just a plain object, so we need to load the entity
459
- const md = new Metadata();
461
+ const md = this.ProviderToUse;
460
462
  notificationEntity = await md.GetEntityObject('MJ: User Notifications');
461
463
  await notificationEntity.Load(notificationId);
462
464
  notificationEntity.Unread = !bRead;
@@ -485,7 +487,7 @@ export class UserNotificationsComponent {
485
487
  await this.TestTransactionGroupVariables();
486
488
  }
487
489
  async TestTransactionGroupVariables() {
488
- const md = new Metadata();
490
+ const md = this.ProviderToUse;
489
491
  const transGroup = await md.CreateTransactionGroup();
490
492
  const conversation = await md.GetEntityObject('MJ: Conversations');
491
493
  conversation.UserID = md.CurrentUser.ID;
@@ -518,7 +520,7 @@ export class UserNotificationsComponent {
518
520
  }
519
521
  async markAll(bRead) {
520
522
  // Use transaction group for batching - all saves are queued and sent in one round-trip
521
- const md = new Metadata();
523
+ const md = this.ProviderToUse;
522
524
  const transGroup = await md.CreateTransactionGroup();
523
525
  // Queue all saves - no need to await individual saves since transaction group queues them
524
526
  for (const notification of this.AllNotifications) {
@@ -668,7 +670,7 @@ export class UserNotificationsComponent {
668
670
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.allRadio = _t.first);
669
671
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.unreadRadio = _t.first);
670
672
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.readRadio = _t.first);
671
- } }, standalone: false, decls: 14, vars: 3, consts: [["allRadio", ""], ["unreadRadio", ""], ["readRadio", ""], [1, "notifications-container"], [1, "notifications-header"], [1, "header-top"], [1, "header-title"], [1, "title-icon"], [1, "fa-solid", "fa-bell"], [1, "header-actions"], [1, "filters-section"], [1, "notifications-content"], [1, "empty-state"], [1, "notifications-list"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-double"], [1, "btn-text"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-envelope"], [1, "filters-slider"], [1, "slider-content"], ["role", "group", "aria-label", "Filter notifications by read status", 1, "header-stats"], ["type", "radio", "name", "UnreadStatus", "value", "All", "checked", "", "id", "filter-all", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show all notifications", 1, "stat-pill", 3, "click"], [1, "stat-label"], [1, "stat-count"], ["type", "radio", "name", "UnreadStatus", "value", "Unread", "id", "filter-unread", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "active", "has-unread"], ["type", "radio", "name", "UnreadStatus", "value", "Read", "id", "filter-read", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "active"], [1, "filter-item", "type-filter-slider"], [1, "search-section"], [1, "search-container"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass", "search-icon"], ["type", "text", "placeholder", "Search notifications...", "aria-label", "Search notifications", 1, "search-input", 3, "input", "value"], [1, "filter-info"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "click"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "click"], ["aria-label", "Filter by notification type", 1, "type-select", 3, "ngModelChange", "change", "ngModel"], [3, "value"], [1, "filter-badge"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "empty-icon"], [1, "fa-solid", "fa-bell-slash"], [1, "fa-solid", "fa-filter-circle-xmark"], ["role", "article", 1, "notification-card", 3, "unread", "clickable"], ["role", "article", 1, "notification-card"], ["aria-hidden", "true", 1, "card-indicator"], ["aria-hidden", "true", 1, "card-icon"], [1, "card-content", 3, "click"], [1, "card-header"], [1, "card-title"], [1, "card-time"], ["aria-hidden", "true", 1, "fa-regular", "fa-clock"], [1, "card-meta"], [1, "card-type"], [1, "card-message"], [1, "card-actions"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], [1, "action-text"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn", 3, "click"]], template: function UserNotificationsComponent_Template(rf, ctx) { if (rf & 1) {
673
+ } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 14, vars: 3, consts: [["allRadio", ""], ["unreadRadio", ""], ["readRadio", ""], [1, "notifications-container"], [1, "notifications-header"], [1, "header-top"], [1, "header-title"], [1, "title-icon"], [1, "fa-solid", "fa-bell"], [1, "header-actions"], [1, "filters-section"], [1, "notifications-content"], [1, "empty-state"], [1, "notifications-list"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-double"], [1, "btn-text"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-envelope"], [1, "filters-slider"], [1, "slider-content"], ["role", "group", "aria-label", "Filter notifications by read status", 1, "header-stats"], ["type", "radio", "name", "UnreadStatus", "value", "All", "checked", "", "id", "filter-all", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show all notifications", 1, "stat-pill", 3, "click"], [1, "stat-label"], [1, "stat-count"], ["type", "radio", "name", "UnreadStatus", "value", "Unread", "id", "filter-unread", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "active", "has-unread"], ["type", "radio", "name", "UnreadStatus", "value", "Read", "id", "filter-read", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "active"], [1, "filter-item", "type-filter-slider"], [1, "search-section"], [1, "search-container"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass", "search-icon"], ["type", "text", "placeholder", "Search notifications...", "aria-label", "Search notifications", 1, "search-input", 3, "input", "value"], [1, "filter-info"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "click"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "click"], ["aria-label", "Filter by notification type", 1, "type-select", 3, "ngModelChange", "change", "ngModel"], [3, "value"], [1, "filter-badge"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "empty-icon"], [1, "fa-solid", "fa-bell-slash"], [1, "fa-solid", "fa-filter-circle-xmark"], ["role", "article", 1, "notification-card", 3, "unread", "clickable"], ["role", "article", 1, "notification-card"], ["aria-hidden", "true", 1, "card-indicator"], ["aria-hidden", "true", 1, "card-icon"], [1, "card-content", 3, "click"], [1, "card-header"], [1, "card-title"], [1, "card-time"], ["aria-hidden", "true", 1, "fa-regular", "fa-clock"], [1, "card-meta"], [1, "card-type"], [1, "card-message"], [1, "card-actions"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], [1, "action-text"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn", 3, "click"]], template: function UserNotificationsComponent_Template(rf, ctx) { if (rf & 1) {
672
674
  i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "div", 5)(3, "div", 6)(4, "div", 7);
673
675
  i0.ɵɵelement(5, "i", 8);
674
676
  i0.ɵɵelementEnd();
@@ -704,5 +706,5 @@ export class UserNotificationsComponent {
704
706
  type: ViewChild,
705
707
  args: ['readRadio']
706
708
  }] }); })();
707
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserNotificationsComponent, { className: "UserNotificationsComponent", filePath: "src/lib/user-notifications/user-notifications.component.ts", lineNumber: 55 }); })();
709
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserNotificationsComponent, { className: "UserNotificationsComponent", filePath: "src/lib/user-notifications/user-notifications.component.ts", lineNumber: 56 }); })();
708
710
  //# sourceMappingURL=user-notifications.component.js.map
@@ -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, NavigationService } from '@memberjunction/ng-shared';\nimport { MJConversationDetailEntity, MJConversationEntity, MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { Metadata, TransactionGroupBase, TransactionVariable, CompositeKey } from '@memberjunction/core';\nimport { SafeJSONParse , UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\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 * 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@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 (\n public sharedService: SharedService,\n private navigationService: NavigationService,\n private appManager: ApplicationManager\n ) {}\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 // Check for agent-request type (navigated via NavigationService, not 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 }\n\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 // 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\n this.navigateToResource(notification);\n }\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 case 'reports':\n this.navigationService.OpenReport(recordId, 'Report');\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 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, NavigationService } from '@memberjunction/ng-shared';\nimport { MJConversationDetailEntity, MJConversationEntity, MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { Metadata, TransactionGroupBase, TransactionVariable, CompositeKey } from '@memberjunction/core';\nimport { SafeJSONParse , UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\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 * 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@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 {\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 (\n public sharedService: SharedService,\n private navigationService: NavigationService,\n private appManager: ApplicationManager\n ) {\n super();}\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 // Check for agent-request type (navigated via NavigationService, not 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 }\n\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 = 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 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 = this.ProviderToUse;\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 = 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 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\n this.navigateToResource(notification);\n }\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 case 'reports':\n this.navigationService.OpenReport(recordId, 'Report');\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 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"]}
@@ -2,13 +2,14 @@ import { OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
2
2
  import { MJAuthBase, StandardUserInfo } from '@memberjunction/ng-auth-services';
3
3
  import { SharedService } from '@memberjunction/ng-shared';
4
4
  import { Observable } from 'rxjs';
5
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
5
6
  import * as i0 from "@angular/core";
6
7
  interface NotificationSummary {
7
8
  InAppEnabled: boolean;
8
9
  EmailEnabled: boolean;
9
10
  SMSEnabled: boolean;
10
11
  }
11
- export declare class UserProfileComponent implements OnInit, OnDestroy {
12
+ export declare class UserProfileComponent extends BaseAngularComponent implements OnInit, OnDestroy {
12
13
  authBase: MJAuthBase;
13
14
  private sharedService;
14
15
  private cdr;
@@ -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;;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"}
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,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AACrE,UAAU,mBAAmB;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,qBAMa,oBAAqB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAehF,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;IAO1B,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;yCAnMlD,oBAAoB;2CAApB,oBAAoB;CA2MhC"}
@@ -1,8 +1,8 @@
1
1
  import { Component } from '@angular/core';
2
2
  import { UserInfoEngine } from '@memberjunction/core-entities';
3
- import { Metadata } from '@memberjunction/core';
4
3
  import { Subject } from 'rxjs';
5
4
  import { UUIDsEqual } from '@memberjunction/global';
5
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
6
6
  import * as i0 from "@angular/core";
7
7
  import * as i1 from "@memberjunction/ng-auth-services";
8
8
  import * as i2 from "@memberjunction/ng-shared";
@@ -127,7 +127,7 @@ function UserProfileComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
127
127
  i0.ɵɵadvance(2);
128
128
  i0.ɵɵconditional(ctx_r2.IsChannelEnabled("SMS") ? 31 : -1);
129
129
  } }
130
- export class UserProfileComponent {
130
+ export class UserProfileComponent extends BaseAngularComponent {
131
131
  authBase;
132
132
  sharedService;
133
133
  cdr;
@@ -143,6 +143,7 @@ export class UserProfileComponent {
143
143
  };
144
144
  destroy$ = new Subject();
145
145
  constructor(authBase, sharedService, cdr) {
146
+ super();
146
147
  this.authBase = authBase;
147
148
  this.sharedService = sharedService;
148
149
  this.cdr = cdr;
@@ -205,7 +206,7 @@ export class UserProfileComponent {
205
206
  async ToggleChannel(channel) {
206
207
  try {
207
208
  this.Saving = true;
208
- const md = new Metadata();
209
+ const md = this.ProviderToUse;
209
210
  const currentUser = md.CurrentUser;
210
211
  const transGroup = await md.CreateTransactionGroup();
211
212
  const types = UserInfoEngine.Instance.NotificationTypes;
@@ -308,7 +309,7 @@ export class UserProfileComponent {
308
309
  }
309
310
  }
310
311
  static ɵfac = function UserProfileComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserProfileComponent)(i0.ɵɵdirectiveInject(i1.MJAuthBase), i0.ɵɵdirectiveInject(i2.SharedService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
311
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserProfileComponent, selectors: [["app-user-profile"]], standalone: false, decls: 2, vars: 2, consts: [["text", "Loading profile..."], [1, "user-profile-container"], [1, "profile-card"], [1, "notification-card"], [1, "card-header"], [1, "header-left"], [1, "fa-solid", "fa-bell", "header-icon"], [1, "unread-badge"], [1, "card-body"], [1, "card-description"], [1, "channel-toggles"], ["type", "button", 1, "channel-toggle", 3, "click", "disabled"], [1, "channel-label"], [1, "toggle-indicator"], [1, "fa-solid", "fa-check"], [1, "card-footer"], ["href", "/settings", 1, "settings-link"], [1, "fa-solid", "fa-arrow-right"], [1, "profile-header"], [1, "avatar-container"], [1, "fa-solid", "fa-user", "avatar-icon"], [1, "profile-info"], [1, "user-name"], [1, "user-email"]], template: function UserProfileComponent_Template(rf, ctx) { if (rf & 1) {
312
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserProfileComponent, selectors: [["app-user-profile"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 2, consts: [["text", "Loading profile..."], [1, "user-profile-container"], [1, "profile-card"], [1, "notification-card"], [1, "card-header"], [1, "header-left"], [1, "fa-solid", "fa-bell", "header-icon"], [1, "unread-badge"], [1, "card-body"], [1, "card-description"], [1, "channel-toggles"], ["type", "button", 1, "channel-toggle", 3, "click", "disabled"], [1, "channel-label"], [1, "toggle-indicator"], [1, "fa-solid", "fa-check"], [1, "card-footer"], ["href", "/settings", 1, "settings-link"], [1, "fa-solid", "fa-arrow-right"], [1, "profile-header"], [1, "avatar-container"], [1, "fa-solid", "fa-user", "avatar-icon"], [1, "profile-info"], [1, "user-name"], [1, "user-email"]], template: function UserProfileComponent_Template(rf, ctx) { if (rf & 1) {
312
313
  i0.ɵɵconditionalCreate(0, UserProfileComponent_Conditional_0_Template, 1, 0, "mj-loading", 0);
313
314
  i0.ɵɵconditionalCreate(1, UserProfileComponent_Conditional_1_Template, 36, 25, "div", 1);
314
315
  } if (rf & 2) {
@@ -321,5 +322,5 @@ export class UserProfileComponent {
321
322
  type: Component,
322
323
  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"] }]
323
324
  }], () => [{ type: i1.MJAuthBase }, { type: i2.SharedService }, { type: i0.ChangeDetectorRef }], null); })();
324
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserProfileComponent, { className: "UserProfileComponent", filePath: "src/lib/user-profile/user-profile.component.ts", lineNumber: 23 }); })();
325
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserProfileComponent, { className: "UserProfileComponent", filePath: "src/lib/user-profile/user-profile.component.ts", lineNumber: 24 }); })();
325
326
  //# sourceMappingURL=user-profile.component.js.map