@memberjunction/ng-explorer-core 5.51.0 → 6.1.0-edge.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +5 -23
- package/dist/app-routing.module.js.map +1 -1
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +5 -4
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +28 -0
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.d.ts +2 -1
- package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.js +58 -42
- package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
- package/dist/lib/shell/components/record-open/record-bar.component.d.ts +29 -0
- package/dist/lib/shell/components/record-open/record-bar.component.d.ts.map +1 -0
- package/dist/lib/shell/components/record-open/record-bar.component.js +72 -0
- package/dist/lib/shell/components/record-open/record-bar.component.js.map +1 -0
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.d.ts +26 -0
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.d.ts.map +1 -0
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.js +140 -0
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.js.map +1 -0
- package/dist/lib/shell/components/record-open/record-switcher-sheet.component.d.ts +43 -0
- package/dist/lib/shell/components/record-open/record-switcher-sheet.component.d.ts.map +1 -0
- package/dist/lib/shell/components/record-open/record-switcher-sheet.component.js +102 -0
- package/dist/lib/shell/components/record-open/record-switcher-sheet.component.js.map +1 -0
- package/dist/lib/shell/components/record-open/record-switcher.service.d.ts +21 -0
- package/dist/lib/shell/components/record-open/record-switcher.service.d.ts.map +1 -0
- package/dist/lib/shell/components/record-open/record-switcher.service.js +30 -0
- package/dist/lib/shell/components/record-open/record-switcher.service.js.map +1 -0
- package/dist/lib/shell/components/record-open/records-hub-pill.component.d.ts +63 -0
- package/dist/lib/shell/components/record-open/records-hub-pill.component.d.ts.map +1 -0
- package/dist/lib/shell/components/record-open/records-hub-pill.component.js +143 -0
- package/dist/lib/shell/components/record-open/records-hub-pill.component.js.map +1 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +228 -2
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +1073 -115
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/services/sharing-center-dialog-host.component.d.ts.map +1 -1
- package/dist/lib/shell/services/sharing-center-dialog-host.component.js +2 -0
- package/dist/lib/shell/services/sharing-center-dialog-host.component.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +41 -4
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +400 -266
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +4 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +14 -3
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts +0 -3
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +16 -78
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +0 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +0 -3
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/package.json +66 -63
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-notifications.component.js","sourceRoot":"","sources":["../../../src/lib/user-notifications/user-notifications.component.ts","../../../src/lib/user-notifications/user-notifications.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, OnDestroy, OnInit, AfterViewInit, inject } from '@angular/core';\nimport { SharedService, NavigationService } from '@memberjunction/ng-shared';\nimport { MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { CompositeKey, TransactionGroupBase } from '@memberjunction/core';\nimport { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Radio button filter options for notification read status\n */\ntype ReadFilterOption = 'All' | 'Unread' | 'Read';\n\n/** How a notification's Message should be rendered. */\ntype MessageKind = 'html' | 'markdown' | 'text';\n\n/**\n * Render-ready view model for one notification. Built once per data/filter change\n * (never inside template bindings): the Message is classified (full HTML document /\n * HTML fragment / Markdown / plain text), reduced to a sanitary body + plain-text\n * preview, and the time-relative label is SNAPSHOT here — computing relative time in\n * the template throws NG0100 at minute boundaries.\n */\ninterface NotificationVM {\n N: MJUserNotificationEntity;\n Kind: MessageKind;\n /** Rich body: extracted+stripped HTML fragment (html) or the raw message (markdown). Empty for plain text. */\n Body: string;\n /** Plain-text excerpt for the collapsed card. */\n Preview: string;\n /** True when there is more to see than the collapsed preview. */\n Expandable: boolean;\n /** Snapshot \"2h ago\" label (refreshed on a timer, never computed in the template). */\n Relative: string;\n Clickable: boolean;\n}\n\n/** One day-bucket of notifications (\"Today\", \"Yesterday\", ...). */\ninterface NotificationGroup {\n Key: string;\n Label: string;\n Items: NotificationVM[];\n}\n\n/**\n * Configuration for record-type resource navigation\n */\ninterface RecordResourceConfig {\n Entity?: string;\n}\n\n/**\n * Configuration for conversation-type resource navigation\n */\ninterface ConversationResourceConfig {\n type: 'conversation';\n conversationId?: string;\n messageId?: string;\n artifactId?: string;\n versionNumber?: string;\n taskId?: string;\n}\n\n/**\n * Configuration for agent-request-type resource navigation\n */\ninterface AgentRequestResourceConfig {\n type: 'agent-request';\n requestId: string;\n}\n\n/**\n * Result of parsing a notification URL\n */\ninterface NotificationUrlInfo {\n urlParts: string[];\n queryString: string;\n}\n\n/** Collapsed-preview cap (characters of plain text). */\nconst PREVIEW_MAX_CHARS = 240;\n\n/** How often the snapshot relative-time labels refresh. */\nconst RELATIVE_REFRESH_MS = 60_000;\n\n@Component({\n standalone: false,\n selector: 'app-user-notifications',\n templateUrl: './user-notifications.component.html',\n styleUrls: ['./user-notifications.component.css']\n})\nexport class UserNotificationsComponent extends BaseAngularComponent implements OnInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n public radioSelected: ReadFilterOption = 'All';\n public currentFilter: string = '';\n public notificationTypes: MJUserNotificationTypeEntity[] = [];\n public selectedTypeFilter: string | null = null;\n public loadingTypes: boolean = true;\n\n /** IDs of cards currently expanded to their full rendered content. */\n public Expanded = new Set<string>();\n\n private groups: NotificationGroup[] = [];\n private groupsKey = '';\n private vmCache = new Map<string, NotificationVM>();\n private relativeTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor (\n public sharedService: SharedService,\n private navigationService: NavigationService,\n private appManager: ApplicationManager\n ) {\n super();\n }\n\n async ngOnInit() {\n this.loadNotificationTypes();\n // Refresh the snapshot relative-time labels between change-detection passes.\n this.relativeTimer = setInterval(() => {\n for (const vm of this.vmCache.values()) {\n vm.Relative = this.relativeTime(vm.N.__mj_CreatedAt);\n }\n this.groupsKey = ''; // day buckets can shift at midnight\n this.cdr.markForCheck();\n }, RELATIVE_REFRESH_MS);\n }\n\n ngAfterViewInit(): void {\n this.sharedService.InvokeManualResize(); // make sure the notifications component is sized correctly\n }\n\n ngOnDestroy(): void {\n if (this.relativeTimer != null) {\n clearInterval(this.relativeTimer);\n }\n }\n\n private loadNotificationTypes() {\n // Get notification types from UserInfoEngine cache, sorted client-side\n // UserInfoEngine is auto-configured via @RegisterForStartup()\n this.notificationTypes = [...UserInfoEngine.Instance.NotificationTypes].sort((a, b) => {\n const priorityA = a.Priority ?? 999;\n const priorityB = b.Priority ?? 999;\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n return a.Name.localeCompare(b.Name);\n });\n this.loadingTypes = false;\n }\n\n // ========================================================================\n // Data shaping (filter → view models → day groups)\n // ========================================================================\n\n public get NotificationsToShow(): MJUserNotificationEntity[] {\n let temp: MJUserNotificationEntity[] = [];\n switch (this.radioSelected) {\n case 'All':\n temp = this.AllNotifications;\n break;\n case 'Unread':\n temp = this.AllNotifications.filter(n => n.Unread);\n break;\n case 'Read':\n temp = this.AllNotifications.filter(n => !n.Unread);\n break;\n }\n\n // Apply type filter if selected\n if (this.selectedTypeFilter) {\n temp = temp.filter(n => UUIDsEqual(n.NotificationTypeID, this.selectedTypeFilter));\n }\n\n // Apply text filter if it is not empty\n if (this.currentFilter.trim().length > 0) {\n // check for inclusion of filter value in title or message\n temp = temp.filter(n => n.Title?.toLowerCase().includes(this.currentFilter.trim().toLowerCase()) ||\n n.Message?.toLowerCase().includes(this.currentFilter.trim().toLowerCase())\n );\n }\n\n return temp;\n }\n\n /**\n * The filtered notifications as render-ready day groups. Memoized on a composite\n * key of the inputs so the getter stays cheap across change-detection passes and\n * the (time-sensitive) VM snapshots never rebuild mid-pass.\n */\n public get Groups(): NotificationGroup[] {\n const list = this.NotificationsToShow;\n const unread = list.filter(n => n.Unread).length;\n const key = `${list.length}|${unread}|${this.radioSelected}|${this.selectedTypeFilter}|${this.currentFilter}|${list[0]?.ID ?? ''}|${list[list.length - 1]?.ID ?? ''}`;\n if (key !== this.groupsKey) {\n this.groups = this.buildGroups(list);\n this.groupsKey = key;\n }\n return this.groups;\n }\n\n private buildGroups(list: MJUserNotificationEntity[]): NotificationGroup[] {\n const groups: NotificationGroup[] = [];\n let current: NotificationGroup | null = null;\n for (const n of list) {\n const label = this.dayLabel(n.__mj_CreatedAt);\n if (!current || current.Label !== label) {\n current = { Key: `${label}-${n.ID}`, Label: label, Items: [] };\n groups.push(current);\n }\n current.Items.push(this.vmFor(n));\n }\n return groups;\n }\n\n private vmFor(n: MJUserNotificationEntity): NotificationVM {\n const cached = this.vmCache.get(n.ID);\n if (cached) {\n cached.N = n;\n cached.Clickable = this.isNotificationClickable(n);\n return cached;\n }\n const { kind, body, preview, expandable } = this.classifyMessage(n.Message ?? '');\n const vm: NotificationVM = {\n N: n,\n Kind: kind,\n Body: body,\n Preview: preview,\n Expandable: expandable,\n Relative: this.relativeTime(n.__mj_CreatedAt),\n Clickable: this.isNotificationClickable(n),\n };\n this.vmCache.set(n.ID, vm);\n return vm;\n }\n\n /**\n * Classifies a notification Message for rendering:\n * - Full HTML documents (e.g. templated email bodies) and HTML fragments →\n * parsed with DOMParser, chrome elements (style/script/link/meta/title) removed,\n * and the body markup kept for a SANITIZED [innerHTML] binding (Angular's\n * default sanitizer strips scripts/event handlers on bind).\n * - Markdown-looking text → rendered through mj-markdown when expanded.\n * - Everything else → plain text.\n */\n private classifyMessage(message: string): { kind: MessageKind; body: string; preview: string; expandable: boolean } {\n const trimmed = (message ?? '').trim();\n const looksHtml = /^<!doctype\\s|^<html[\\s>]/i.test(trimmed) || /<\\/?[a-z][^>]*>/i.test(trimmed);\n if (looksHtml) {\n const doc = new DOMParser().parseFromString(trimmed, 'text/html');\n for (const el of Array.from(doc.querySelectorAll('style, script, link, meta, title'))) {\n el.remove();\n }\n const body = doc.body?.innerHTML?.trim() ?? '';\n const text = this.collapseWhitespace(doc.body?.textContent ?? '');\n return { kind: 'html', body, preview: this.excerpt(text), expandable: true };\n }\n const looksMarkdown = /(^|\\n)#{1,6}\\s|\\*\\*[^*]+\\*\\*|(^|\\n)\\s*[-*]\\s+|\\[[^\\]]+\\]\\([^)]+\\)|```/m.test(trimmed);\n const text = this.collapseWhitespace(trimmed);\n if (looksMarkdown) {\n return { kind: 'markdown', body: trimmed, preview: this.excerpt(this.stripMarkdown(text)), expandable: true };\n }\n return { kind: 'text', body: '', preview: text, expandable: text.length > PREVIEW_MAX_CHARS };\n }\n\n private collapseWhitespace(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n }\n\n private excerpt(text: string): string {\n return text.length > PREVIEW_MAX_CHARS ? `${text.substring(0, PREVIEW_MAX_CHARS - 1)}…` : text;\n }\n\n /** Light de-noising of markdown syntax for the plain-text preview. */\n private stripMarkdown(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, ' ')\n .replace(/[#*_`>]+/g, '')\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\s+/g, ' ')\n .trim();\n }\n\n /** Compact \"just now / 5m ago / 3h ago / 2d ago\" label. NEVER call from templates (NG0100) — snapshot only. */\n private relativeTime(value: Date | string | null | undefined): string {\n if (!value) {\n return '';\n }\n const ms = Date.now() - new Date(value).getTime();\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : '';\n }\n\n private dayLabel(value: Date | string | null | undefined): string {\n if (!value) {\n return 'Earlier';\n }\n const d = new Date(value);\n const now = new Date();\n const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const diffDays = Math.round((startOfDay(now) - startOfDay(d)) / 86_400_000);\n if (diffDays <= 0) return 'Today';\n if (diffDays === 1) return 'Yesterday';\n if (diffDays < 7) return 'This Week';\n return 'Earlier';\n }\n\n // ========================================================================\n // Expand / collapse\n // ========================================================================\n\n public IsExpanded(vm: NotificationVM): boolean {\n return this.Expanded.has(vm.N.ID);\n }\n\n public ToggleExpanded(vm: NotificationVM, event: Event): void {\n event.stopPropagation();\n if (this.Expanded.has(vm.N.ID)) {\n this.Expanded.delete(vm.N.ID);\n } else {\n this.Expanded.add(vm.N.ID);\n // Reading the full content is reading — mark it as such.\n if (vm.N.Unread) {\n void this.markAsRead(vm.N, true, null);\n }\n }\n this.cdr.markForCheck();\n }\n\n // ========================================================================\n // Clickability + navigation (unchanged behavior)\n // ========================================================================\n\n public isNotificationClickable(notification: MJUserNotificationEntity): boolean {\n // Check for special types navigated via NavigationService (not a URL)\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (config && config.type?.trim().toLowerCase() === 'agent-request' && config.requestId) {\n return true;\n }\n const typeName = SafeJSONParse<{ type?: string }>(notification.ResourceConfiguration)?.type?.trim().toLowerCase();\n if (typeName === 'meet-room') {\n return true;\n }\n }\n\n const info = this.notificationUrl(notification);\n return (info !== null && info.urlParts && info.urlParts.length > 0);\n }\n\n 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 }\n\n onFilterChanged(value: string): void {\n this.currentFilter = value;\n }\n\n async markAsRead(notification: MJUserNotificationEntity, bRead: boolean, transGroup: TransactionGroupBase | null): Promise<boolean> {\n if (notification) {\n const notificationId = notification.ID;\n notification.Unread = !bRead;\n let notificationEntity: MJUserNotificationEntity;\n if (notification instanceof MJUserNotificationEntity) {\n // the passed in param truly is a MJUserNotificationEntity or subclass, so just use it, saves a DB round trip\n notificationEntity = notification;\n }\n else {\n // the passed in param is just a plain object, so we need to load the entity\n const md = this.ProviderToUse;\n notificationEntity = await md.GetEntityObject<MJUserNotificationEntity>('MJ: User Notifications');\n await notificationEntity.Load(notificationId);\n notificationEntity.Unread = !bRead;\n }\n\n // part of a transaction group, if so, add it as that will defer the actual network traffic/save\n if (transGroup) {\n notificationEntity.TransactionGroup = transGroup;\n await notificationEntity.Save()\n return true;\n }\n else {\n // Save the notification (not part of transaction group)\n await notificationEntity.Save();\n // Update the observables so badge count refreshes immediately\n MJNotificationService.UpdateNotificationObservables();\n return true;\n }\n }\n else {\n return false;\n }\n }\n\n public async markAllAsRead() {\n await this.markAll(true);\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 if (this.navigateToMeetRoom(notification)) {\n return;\n }\n\n this.navigateToResource(notification);\n }\n }\n\n /**\n * Opens the Meet app's Live Room in JOIN mode for a `meet-room` invite notification (the\n * `{ type:'meet-room', room }` ResourceConfiguration), mirroring {@link navigateToConversation}.\n * Returns `false` (not handled) when the config isn't a meet-room invite or the Meet app is absent.\n */\n private navigateToMeetRoom(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n const config = SafeJSONParse<{ type?: string; room?: string }>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'meet-room') {\n return false;\n }\n const meetApp = this.appManager.GetAppByName('Meet');\n if (!meetApp) {\n return false;\n }\n const navConfig: Record<string, string> = {};\n if (config.room) {\n navConfig['room'] = config.room;\n }\n this.navigationService.OpenNavItemByName('Live Room', navConfig, meetApp.ID);\n return true;\n }\n\n /**\n * 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 || 'var(--mj-text-muted)';\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 <div class=\"title-text\">\n <h1>Notifications</h1>\n @if (UnreadNotifications.length > 0) {\n <span class=\"title-subtitle\">{{UnreadNotifications.length}} unread</span>\n } @else if (AllNotifications.length > 0) {\n <span class=\"title-subtitle\">All caught up</span>\n }\n </div>\n </div>\n\n @if (AllNotifications.length > 0) {\n <div class=\"header-actions\">\n @if (UnreadNotifications.length > 0) {\n <button class=\"action-btn action-btn-ghost\"\n type=\"button\"\n (click)=\"markAllAsRead()\"\n aria-label=\"Mark all notifications as read\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Read</span>\n </button>\n }\n @if (ReadNotifications.length > 0) {\n <button class=\"action-btn action-btn-secondary\"\n type=\"button\"\n (click)=\"markAllAsUnread()\"\n aria-label=\"Mark all notifications as unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Unread</span>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Filters Section -->\n @if (AllNotifications.length > 0) {\n <div class=\"filters-section\">\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Read-status pills -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'All'\"\n (click)=\"selectReadOption('All')\"\n [attr.aria-pressed]=\"radioSelected === 'All'\"\n aria-label=\"Show all notifications\">\n <span class=\"stat-label\">All</span>\n <span class=\"stat-count\">{{AllNotifications.length}}</span>\n </button>\n\n @if (UnreadNotifications.length > 0 || ReadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Unread'\"\n [class.has-unread]=\"UnreadNotifications.length > 0\"\n (click)=\"selectReadOption('Unread')\"\n [attr.aria-pressed]=\"radioSelected === 'Unread'\"\n aria-label=\"Show unread notifications\">\n <span class=\"stat-label\">Unread</span>\n <span class=\"stat-count\" [class.unread-count]=\"UnreadNotifications.length > 0\">\n {{UnreadNotifications.length}}\n </span>\n </button>\n }\n\n @if (ReadNotifications.length > 0 || UnreadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Read'\"\n (click)=\"selectReadOption('Read')\"\n [attr.aria-pressed]=\"radioSelected === 'Read'\"\n aria-label=\"Show read notifications\">\n <span class=\"stat-label\">Read</span>\n <span class=\"stat-count\">{{ReadNotifications.length}}</span>\n </button>\n }\n </div>\n\n <!-- Type filter -->\n @if (notificationTypes.length > 0) {\n <div class=\"filter-item type-filter-slider\">\n <select class=\"type-select\"\n [(ngModel)]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange(selectedTypeFilter)\"\n aria-label=\"Filter by notification type\">\n <option [value]=\"null\">All Types</option>\n @for (type of notificationTypes; track type.ID) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n </div>\n }\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-section\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search notifications...\"\n [value]=\"currentFilter\"\n (input)=\"onFilterChanged($any($event.target).value)\"\n aria-label=\"Search notifications\" />\n </div>\n </div>\n\n @if (NotificationsToShow.length !== AllNotifications.length) {\n <div class=\"filter-info\">\n <span class=\"filter-badge\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Showing {{NotificationsToShow.length}} of {{AllNotifications.length}}\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Notifications Content -->\n <div class=\"notifications-content\">\n @if (NotificationsToShow.length === 0 && AllNotifications.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Icon=\"fa-solid fa-bell-slash\"\n Title=\"No Notifications\"\n Message=\"You're all caught up! New notifications will appear here.\" />\n } @else if (NotificationsToShow.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-filter-circle-xmark\"\n Title=\"No Matching Notifications\"\n Message=\"Try adjusting your filters to see more notifications.\" />\n } @else {\n <!-- Day-grouped notification list -->\n <div class=\"notifications-list\">\n @for (group of Groups; track group.Key) {\n <div class=\"group-label\">{{group.Label}}</div>\n\n @for (vm of group.Items; track vm.N.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"vm.N.Unread\"\n [class.expanded]=\"IsExpanded(vm)\"\n [class.clickable]=\"vm.Clickable\"\n role=\"article\"\n [attr.aria-label]=\"vm.N.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.N)\"\n [style.color]=\"getTypeColor(vm.N)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(vm.N)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"vm.N.Unread\">\n {{vm.N.Title}}\n </h3>\n <span class=\"card-time\" [title]=\"(vm.N.__mj_CreatedAt | date:'medium') ?? ''\">\n @if (vm.Relative) {\n {{vm.Relative}}\n } @else {\n <time [attr.datetime]=\"vm.N.__mj_CreatedAt\">{{vm.N.__mj_CreatedAt | date:'MMM d, h:mm a'}}</time>\n }\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\">{{getTypeName(vm.N)}}</span>\n @if (vm.Clickable) {\n <span class=\"card-open-hint\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i> Open\n </span>\n }\n </div>\n\n @if (!IsExpanded(vm)) {\n <p class=\"card-message\">{{vm.Preview}}</p>\n } @else {\n <div class=\"card-rich\" (click)=\"$event.stopPropagation()\">\n @switch (vm.Kind) {\n @case ('html') {\n <!-- Angular sanitizes on [innerHTML] bind; chrome tags were stripped at classification -->\n <div class=\"card-rich-html\" [innerHTML]=\"vm.Body\"></div>\n }\n @case ('markdown') {\n <mj-markdown class=\"card-rich-md\" [data]=\"vm.Body\" [enableMermaid]=\"false\"></mj-markdown>\n }\n @default {\n <p class=\"card-message card-message-full\">{{vm.N.Message}}</p>\n }\n }\n </div>\n }\n\n @if (vm.Expandable) {\n <button class=\"card-expand-btn\" type=\"button\"\n (click)=\"ToggleExpanded(vm, $event)\"\n [attr.aria-expanded]=\"IsExpanded(vm)\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!IsExpanded(vm)\" [class.fa-chevron-up]=\"IsExpanded(vm)\" aria-hidden=\"true\"></i>\n {{ IsExpanded(vm) ? 'Show less' : 'Show more' }}\n </button>\n }\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (vm.N.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, true, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as read'\"\n title=\"Mark as Read\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Read</span>\n </button>\n } @else {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, false, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as unread'\"\n title=\"Mark as Unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Unread</span>\n </button>\n }\n </div>\n </article>\n }\n }\n </div>\n }\n </div>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"user-notifications.component.js","sourceRoot":"","sources":["../../../src/lib/user-notifications/user-notifications.component.ts","../../../src/lib/user-notifications/user-notifications.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, OnDestroy, OnInit, AfterViewInit, inject } from '@angular/core';\nimport { SharedService, NavigationService } from '@memberjunction/ng-shared';\nimport { MJUserNotificationEntity, MJUserNotificationTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { CompositeKey, TransactionGroupBase } from '@memberjunction/core';\nimport { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Radio button filter options for notification read status\n */\ntype ReadFilterOption = 'All' | 'Unread' | 'Read';\n\n/** How a notification's Message should be rendered. */\ntype MessageKind = 'html' | 'markdown' | 'text';\n\n/**\n * Render-ready view model for one notification. Built once per data/filter change\n * (never inside template bindings): the Message is classified (full HTML document /\n * HTML fragment / Markdown / plain text), reduced to a sanitary body + plain-text\n * preview, and the time-relative label is SNAPSHOT here — computing relative time in\n * the template throws NG0100 at minute boundaries.\n */\ninterface NotificationVM {\n N: MJUserNotificationEntity;\n Kind: MessageKind;\n /** Rich body: extracted+stripped HTML fragment (html) or the raw message (markdown). Empty for plain text. */\n Body: string;\n /** Plain-text excerpt for the collapsed card. */\n Preview: string;\n /** True when there is more to see than the collapsed preview. */\n Expandable: boolean;\n /** Snapshot \"2h ago\" label (refreshed on a timer, never computed in the template). */\n Relative: string;\n Clickable: boolean;\n}\n\n/** One day-bucket of notifications (\"Today\", \"Yesterday\", ...). */\ninterface NotificationGroup {\n Key: string;\n Label: string;\n Items: NotificationVM[];\n}\n\n/**\n * Configuration for record-type resource navigation\n */\ninterface RecordResourceConfig {\n Entity?: string;\n}\n\n/**\n * Configuration for conversation-type resource navigation\n */\ninterface ConversationResourceConfig {\n type: 'conversation';\n conversationId?: string;\n messageId?: string;\n artifactId?: string;\n versionNumber?: string;\n taskId?: string;\n}\n\n/**\n * Configuration for agent-request-type resource navigation\n */\ninterface AgentRequestResourceConfig {\n type: 'agent-request';\n requestId: string;\n}\n\n/**\n * Result of parsing a notification URL\n */\ninterface NotificationUrlInfo {\n urlParts: string[];\n queryString: string;\n}\n\n/** Collapsed-preview cap (characters of plain text). */\nconst PREVIEW_MAX_CHARS = 240;\n\n/** How often the snapshot relative-time labels refresh. */\nconst RELATIVE_REFRESH_MS = 60_000;\n\n@Component({\n standalone: false,\n selector: 'app-user-notifications',\n templateUrl: './user-notifications.component.html',\n styleUrls: ['./user-notifications.component.css']\n})\nexport class UserNotificationsComponent extends BaseAngularComponent implements OnInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n public radioSelected: ReadFilterOption = 'All';\n public currentFilter: string = '';\n public notificationTypes: MJUserNotificationTypeEntity[] = [];\n public selectedTypeFilter: string | null = null;\n public loadingTypes: boolean = true;\n\n /** IDs of cards currently expanded to their full rendered content. */\n public Expanded = new Set<string>();\n\n private groups: NotificationGroup[] = [];\n private groupsKey = '';\n private vmCache = new Map<string, NotificationVM>();\n private relativeTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor (\n public sharedService: SharedService,\n private navigationService: NavigationService,\n private appManager: ApplicationManager\n ) {\n super();\n }\n\n async ngOnInit() {\n this.loadNotificationTypes();\n // Refresh the snapshot relative-time labels between change-detection passes.\n this.relativeTimer = setInterval(() => {\n for (const vm of this.vmCache.values()) {\n vm.Relative = this.relativeTime(vm.N.__mj_CreatedAt);\n }\n this.groupsKey = ''; // day buckets can shift at midnight\n this.cdr.markForCheck();\n }, RELATIVE_REFRESH_MS);\n }\n\n ngAfterViewInit(): void {\n this.sharedService.InvokeManualResize(); // make sure the notifications component is sized correctly\n }\n\n ngOnDestroy(): void {\n if (this.relativeTimer != null) {\n clearInterval(this.relativeTimer);\n }\n }\n\n private loadNotificationTypes() {\n // Get notification types from UserInfoEngine cache, sorted client-side\n // UserInfoEngine is auto-configured via @RegisterForStartup()\n this.notificationTypes = [...UserInfoEngine.Instance.NotificationTypes].sort((a, b) => {\n const priorityA = a.Priority ?? 999;\n const priorityB = b.Priority ?? 999;\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n return a.Name.localeCompare(b.Name);\n });\n this.loadingTypes = false;\n }\n\n // ========================================================================\n // Data shaping (filter → view models → day groups)\n // ========================================================================\n\n public get NotificationsToShow(): MJUserNotificationEntity[] {\n let temp: MJUserNotificationEntity[] = [];\n switch (this.radioSelected) {\n case 'All':\n temp = this.AllNotifications;\n break;\n case 'Unread':\n temp = this.AllNotifications.filter(n => n.Unread);\n break;\n case 'Read':\n temp = this.AllNotifications.filter(n => !n.Unread);\n break;\n }\n\n // Apply type filter if selected\n if (this.selectedTypeFilter) {\n temp = temp.filter(n => UUIDsEqual(n.NotificationTypeID, this.selectedTypeFilter));\n }\n\n // Apply text filter if it is not empty\n if (this.currentFilter.trim().length > 0) {\n // check for inclusion of filter value in title or message\n temp = temp.filter(n => n.Title?.toLowerCase().includes(this.currentFilter.trim().toLowerCase()) ||\n n.Message?.toLowerCase().includes(this.currentFilter.trim().toLowerCase())\n );\n }\n\n return temp;\n }\n\n /**\n * The filtered notifications as render-ready day groups. Memoized on a composite\n * key of the inputs so the getter stays cheap across change-detection passes and\n * the (time-sensitive) VM snapshots never rebuild mid-pass.\n */\n public get Groups(): NotificationGroup[] {\n const list = this.NotificationsToShow;\n const unread = list.filter(n => n.Unread).length;\n const key = `${list.length}|${unread}|${this.radioSelected}|${this.selectedTypeFilter}|${this.currentFilter}|${list[0]?.ID ?? ''}|${list[list.length - 1]?.ID ?? ''}`;\n if (key !== this.groupsKey) {\n this.groups = this.buildGroups(list);\n this.groupsKey = key;\n }\n return this.groups;\n }\n\n private buildGroups(list: MJUserNotificationEntity[]): NotificationGroup[] {\n const groups: NotificationGroup[] = [];\n let current: NotificationGroup | null = null;\n for (const n of list) {\n const label = this.dayLabel(n.__mj_CreatedAt);\n if (!current || current.Label !== label) {\n current = { Key: `${label}-${n.ID}`, Label: label, Items: [] };\n groups.push(current);\n }\n current.Items.push(this.vmFor(n));\n }\n return groups;\n }\n\n private vmFor(n: MJUserNotificationEntity): NotificationVM {\n const cached = this.vmCache.get(n.ID);\n if (cached) {\n cached.N = n;\n cached.Clickable = this.isNotificationClickable(n);\n return cached;\n }\n const { kind, body, preview, expandable } = this.classifyMessage(n.Message ?? '');\n const vm: NotificationVM = {\n N: n,\n Kind: kind,\n Body: body,\n Preview: preview,\n Expandable: expandable,\n Relative: this.relativeTime(n.__mj_CreatedAt),\n Clickable: this.isNotificationClickable(n),\n };\n this.vmCache.set(n.ID, vm);\n return vm;\n }\n\n /**\n * Classifies a notification Message for rendering:\n * - Full HTML documents (e.g. templated email bodies) and HTML fragments →\n * parsed with DOMParser, chrome elements (style/script/link/meta/title) removed,\n * and the body markup kept for a SANITIZED [innerHTML] binding (Angular's\n * default sanitizer strips scripts/event handlers on bind).\n * - Markdown-looking text → rendered through mj-markdown when expanded.\n * - Everything else → plain text.\n */\n private classifyMessage(message: string): { kind: MessageKind; body: string; preview: string; expandable: boolean } {\n const trimmed = (message ?? '').trim();\n const looksHtml = /^<!doctype\\s|^<html[\\s>]/i.test(trimmed) || /<\\/?[a-z][^>]*>/i.test(trimmed);\n if (looksHtml) {\n const doc = new DOMParser().parseFromString(trimmed, 'text/html');\n for (const el of Array.from(doc.querySelectorAll('style, script, link, meta, title'))) {\n el.remove();\n }\n const body = doc.body?.innerHTML?.trim() ?? '';\n const text = this.collapseWhitespace(doc.body?.textContent ?? '');\n return { kind: 'html', body, preview: this.excerpt(text), expandable: true };\n }\n const looksMarkdown = /(^|\\n)#{1,6}\\s|\\*\\*[^*]+\\*\\*|(^|\\n)\\s*[-*]\\s+|\\[[^\\]]+\\]\\([^)]+\\)|```/m.test(trimmed);\n const text = this.collapseWhitespace(trimmed);\n if (looksMarkdown) {\n return { kind: 'markdown', body: trimmed, preview: this.excerpt(this.stripMarkdown(text)), expandable: true };\n }\n return { kind: 'text', body: '', preview: text, expandable: text.length > PREVIEW_MAX_CHARS };\n }\n\n private collapseWhitespace(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n }\n\n private excerpt(text: string): string {\n return text.length > PREVIEW_MAX_CHARS ? `${text.substring(0, PREVIEW_MAX_CHARS - 1)}…` : text;\n }\n\n /** Light de-noising of markdown syntax for the plain-text preview. */\n private stripMarkdown(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, ' ')\n .replace(/[#*_`>]+/g, '')\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\s+/g, ' ')\n .trim();\n }\n\n /** Compact \"just now / 5m ago / 3h ago / 2d ago\" label. NEVER call from templates (NG0100) — snapshot only. */\n private relativeTime(value: Date | string | null | undefined): string {\n if (!value) {\n return '';\n }\n const ms = Date.now() - new Date(value).getTime();\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : '';\n }\n\n private dayLabel(value: Date | string | null | undefined): string {\n if (!value) {\n return 'Earlier';\n }\n const d = new Date(value);\n const now = new Date();\n const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const diffDays = Math.round((startOfDay(now) - startOfDay(d)) / 86_400_000);\n if (diffDays <= 0) return 'Today';\n if (diffDays === 1) return 'Yesterday';\n if (diffDays < 7) return 'This Week';\n return 'Earlier';\n }\n\n // ========================================================================\n // Expand / collapse\n // ========================================================================\n\n public IsExpanded(vm: NotificationVM): boolean {\n return this.Expanded.has(vm.N.ID);\n }\n\n public ToggleExpanded(vm: NotificationVM, event: Event): void {\n event.stopPropagation();\n if (this.Expanded.has(vm.N.ID)) {\n this.Expanded.delete(vm.N.ID);\n } else {\n this.Expanded.add(vm.N.ID);\n // Reading the full content is reading — mark it as such.\n if (vm.N.Unread) {\n void this.markAsRead(vm.N, true, null);\n }\n }\n this.cdr.markForCheck();\n }\n\n // ========================================================================\n // Clickability + navigation (unchanged behavior)\n // ========================================================================\n\n public isNotificationClickable(notification: MJUserNotificationEntity): boolean {\n // Check for special types navigated via NavigationService (not a URL)\n if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (config && config.type?.trim().toLowerCase() === 'agent-request' && config.requestId) {\n return true;\n }\n const typeName = SafeJSONParse<{ type?: string }>(notification.ResourceConfiguration)?.type?.trim().toLowerCase();\n if (typeName === 'meet-room') {\n return true;\n }\n }\n\n const info = this.notificationUrl(notification);\n return (info !== null && info.urlParts && info.urlParts.length > 0);\n }\n\n 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 }\n\n onFilterChanged(value: string): void {\n this.currentFilter = value;\n }\n\n async markAsRead(notification: MJUserNotificationEntity, bRead: boolean, transGroup: TransactionGroupBase | null): Promise<boolean> {\n if (notification) {\n const notificationId = notification.ID;\n notification.Unread = !bRead;\n let notificationEntity: MJUserNotificationEntity;\n if (notification instanceof MJUserNotificationEntity) {\n // the passed in param truly is a MJUserNotificationEntity or subclass, so just use it, saves a DB round trip\n notificationEntity = notification;\n }\n else {\n // the passed in param is just a plain object, so we need to load the entity\n const md = this.ProviderToUse;\n notificationEntity = await md.GetEntityObject<MJUserNotificationEntity>('MJ: User Notifications');\n await notificationEntity.Load(notificationId);\n notificationEntity.Unread = !bRead;\n }\n\n // part of a transaction group, if so, add it as that will defer the actual network traffic/save\n if (transGroup) {\n notificationEntity.TransactionGroup = transGroup;\n await notificationEntity.Save()\n return true;\n }\n else {\n // Save the notification (not part of transaction group)\n await notificationEntity.Save();\n // Update the observables so badge count refreshes immediately\n MJNotificationService.UpdateNotificationObservables();\n return true;\n }\n }\n else {\n return false;\n }\n }\n\n public async markAllAsRead() {\n await this.markAll(true);\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 if (this.navigateToMeetRoom(notification)) {\n return;\n }\n\n this.navigateToResource(notification);\n }\n }\n\n /**\n * Opens the Meet app's Live Room in JOIN mode for a `meet-room` invite notification (the\n * `{ type:'meet-room', room }` ResourceConfiguration), mirroring {@link navigateToConversation}.\n * Returns `false` (not handled) when the config isn't a meet-room invite or the Meet app is absent.\n */\n private navigateToMeetRoom(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n const config = SafeJSONParse<{ type?: string; room?: string }>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'meet-room') {\n return false;\n }\n const meetApp = this.appManager.GetAppByName('Meet');\n if (!meetApp) {\n return false;\n }\n const navConfig: Record<string, string> = {};\n if (config.room) {\n navConfig['room'] = config.room;\n }\n this.navigationService.OpenNavItemByName('Live Room', navConfig, meetApp.ID);\n return true;\n }\n\n /**\n * Navigate to a resource-based notification using NavigationService methods.\n * Routes to the correct resource based on the notification's ResourceType.\n */\n private navigateToResource(notification: MJUserNotificationEntity): void {\n if (!notification.ResourceRecordID || !notification.ResourceTypeID) return;\n\n const rt = this.sharedService.ResourceTypeByID(notification.ResourceTypeID);\n if (!rt) return;\n\n const recordId = notification.ResourceRecordID.toString();\n const rtName = rt.Name.trim().toLowerCase();\n\n switch (rtName) {\n case 'records': {\n const config = SafeJSONParse<RecordResourceConfig>(notification.ResourceConfiguration || '');\n if (config?.Entity) {\n const key = new CompositeKey();\n key.SimpleLoadFromURLSegment(recordId);\n this.navigationService.OpenEntityRecord(config.Entity, key);\n }\n break;\n }\n case 'user views':\n case 'mj: user views':\n this.navigationService.OpenView(recordId, 'View');\n break;\n case 'dashboards':\n this.navigationService.OpenDashboard(recordId, 'Dashboard');\n break;\n default:\n console.warn(`[UserNotifications] Unhandled resource type for navigation: ${rt.Name}`);\n break;\n }\n }\n\n /**\n * Handle navigation to an agent request via NavigationService.\n * Returns true if the notification was an agent-request type and navigation was attempted.\n */\n private navigateToAgentRequest(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n\n const config = SafeJSONParse<AgentRequestResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'agent-request' || !config.requestId) {\n return false;\n }\n\n // Try the AI app first (has dedicated Agent Requests nav item)\n const aiApp = this.appManager.GetAppByName('AI');\n if (aiApp) {\n this.navigationService.OpenNavItemByName(\n 'Agent Requests',\n { requestId: config.requestId },\n aiApp.ID\n );\n return true;\n }\n\n // Fallback: navigate to Chat app's Conversations with the request context\n const chatApp = this.appManager.GetAppByName('Chat');\n if (chatApp) {\n this.navigationService.OpenNavItemByName(\n 'Conversations',\n { requestId: config.requestId },\n chatApp.ID\n );\n return true;\n }\n\n return false;\n }\n\n /**\n * Handle navigation to a conversation via NavigationService.\n * Returns true if the notification was a conversation type and navigation was attempted.\n */\n private navigateToConversation(notification: MJUserNotificationEntity): boolean {\n if (!notification.ResourceConfiguration || notification.ResourceConfiguration.trim().length === 0) {\n return false;\n }\n\n const config = SafeJSONParse<ConversationResourceConfig>(notification.ResourceConfiguration);\n if (!config || config.type?.trim().toLowerCase() !== 'conversation') {\n return false;\n }\n\n const chatApp = this.appManager.GetAppByName('Chat');\n if (!chatApp) {\n return false;\n }\n\n const navConfig: Record<string, string> = {};\n if (config.conversationId) navConfig['conversationId'] = config.conversationId;\n if (config.messageId) navConfig['messageId'] = config.messageId;\n if (config.artifactId) navConfig['artifactId'] = config.artifactId;\n if (config.versionNumber) navConfig['versionNumber'] = config.versionNumber;\n if (config.taskId) navConfig['taskId'] = config.taskId;\n\n this.navigationService.OpenNavItemByName(\n 'Conversations',\n navConfig,\n chatApp.ID\n );\n return true;\n }\n\n public getNotificationType(typeId: string | null): MJUserNotificationTypeEntity | null {\n if (!typeId) return null;\n return this.notificationTypes.find(t => UUIDsEqual(t.ID, typeId)) || null;\n }\n\n 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 || 'var(--mj-text-muted)';\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 <div class=\"title-text\">\n <h1>Notifications</h1>\n @if (UnreadNotifications.length > 0) {\n <span class=\"title-subtitle\">{{UnreadNotifications.length}} unread</span>\n } @else if (AllNotifications.length > 0) {\n <span class=\"title-subtitle\">All caught up</span>\n }\n </div>\n </div>\n\n @if (AllNotifications.length > 0) {\n <div class=\"header-actions\">\n @if (UnreadNotifications.length > 0) {\n <button class=\"action-btn action-btn-ghost\"\n type=\"button\"\n (click)=\"markAllAsRead()\"\n aria-label=\"Mark all notifications as read\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Read</span>\n </button>\n }\n @if (ReadNotifications.length > 0) {\n <button class=\"action-btn action-btn-secondary\"\n type=\"button\"\n (click)=\"markAllAsUnread()\"\n aria-label=\"Mark all notifications as unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Unread</span>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Filters Section -->\n @if (AllNotifications.length > 0) {\n <div class=\"filters-section\">\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Read-status pills -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'All'\"\n (click)=\"selectReadOption('All')\"\n [attr.aria-pressed]=\"radioSelected === 'All'\"\n aria-label=\"Show all notifications\">\n <span class=\"stat-label\">All</span>\n <span class=\"stat-count\">{{AllNotifications.length}}</span>\n </button>\n\n @if (UnreadNotifications.length > 0 || ReadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Unread'\"\n [class.has-unread]=\"UnreadNotifications.length > 0\"\n (click)=\"selectReadOption('Unread')\"\n [attr.aria-pressed]=\"radioSelected === 'Unread'\"\n aria-label=\"Show unread notifications\">\n <span class=\"stat-label\">Unread</span>\n <span class=\"stat-count\" [class.unread-count]=\"UnreadNotifications.length > 0\">\n {{UnreadNotifications.length}}\n </span>\n </button>\n }\n\n @if (ReadNotifications.length > 0 || UnreadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Read'\"\n (click)=\"selectReadOption('Read')\"\n [attr.aria-pressed]=\"radioSelected === 'Read'\"\n aria-label=\"Show read notifications\">\n <span class=\"stat-label\">Read</span>\n <span class=\"stat-count\">{{ReadNotifications.length}}</span>\n </button>\n }\n </div>\n\n <!-- Type filter -->\n @if (notificationTypes.length > 0) {\n <div class=\"filter-item type-filter-slider\">\n <select class=\"type-select\"\n [(ngModel)]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange(selectedTypeFilter)\"\n aria-label=\"Filter by notification type\">\n <option [value]=\"null\">All Types</option>\n @for (type of notificationTypes; track type.ID) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n </div>\n }\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-section\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search notifications...\"\n [value]=\"currentFilter\"\n (input)=\"onFilterChanged($any($event.target).value)\"\n aria-label=\"Search notifications\" />\n </div>\n </div>\n\n @if (NotificationsToShow.length !== AllNotifications.length) {\n <div class=\"filter-info\">\n <span class=\"filter-badge\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Showing {{NotificationsToShow.length}} of {{AllNotifications.length}}\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Notifications Content -->\n <div class=\"notifications-content\">\n @if (NotificationsToShow.length === 0 && AllNotifications.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Icon=\"fa-solid fa-bell-slash\"\n Title=\"No Notifications\"\n Message=\"You're all caught up! New notifications will appear here.\" />\n } @else if (NotificationsToShow.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-filter-circle-xmark\"\n Title=\"No Matching Notifications\"\n Message=\"Try adjusting your filters to see more notifications.\" />\n } @else {\n <!-- Day-grouped notification list -->\n <div class=\"notifications-list\">\n @for (group of Groups; track group.Key) {\n <div class=\"group-label\">{{group.Label}}</div>\n\n @for (vm of group.Items; track vm.N.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"vm.N.Unread\"\n [class.expanded]=\"IsExpanded(vm)\"\n [class.clickable]=\"vm.Clickable\"\n role=\"article\"\n [attr.aria-label]=\"vm.N.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.N)\"\n [style.color]=\"getTypeColor(vm.N)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(vm.N)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"vm.N.Unread\">\n {{vm.N.Title}}\n </h3>\n <span class=\"card-time\" [title]=\"(vm.N.__mj_CreatedAt | date:'medium') ?? ''\">\n @if (vm.Relative) {\n {{vm.Relative}}\n } @else {\n <time [attr.datetime]=\"vm.N.__mj_CreatedAt\">{{vm.N.__mj_CreatedAt | date:'MMM d, h:mm a'}}</time>\n }\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\">{{getTypeName(vm.N)}}</span>\n @if (vm.Clickable) {\n <span class=\"card-open-hint\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i> Open\n </span>\n }\n </div>\n\n @if (!IsExpanded(vm)) {\n <p class=\"card-message\">{{vm.Preview}}</p>\n } @else {\n <div class=\"card-rich\" (click)=\"$event.stopPropagation()\">\n @switch (vm.Kind) {\n @case ('html') {\n <!-- Angular sanitizes on [innerHTML] bind; chrome tags were stripped at classification -->\n <div class=\"card-rich-html\" [innerHTML]=\"vm.Body\"></div>\n }\n @case ('markdown') {\n <mj-markdown class=\"card-rich-md\" [data]=\"vm.Body\" [enableMermaid]=\"false\"></mj-markdown>\n }\n @default {\n <p class=\"card-message card-message-full\">{{vm.N.Message}}</p>\n }\n }\n </div>\n }\n\n @if (vm.Expandable) {\n <button class=\"card-expand-btn\" type=\"button\"\n (click)=\"ToggleExpanded(vm, $event)\"\n [attr.aria-expanded]=\"IsExpanded(vm)\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!IsExpanded(vm)\" [class.fa-chevron-up]=\"IsExpanded(vm)\" aria-hidden=\"true\"></i>\n {{ IsExpanded(vm) ? 'Show less' : 'Show more' }}\n </button>\n }\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (vm.N.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, true, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as read'\"\n title=\"Mark as Read\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Read</span>\n </button>\n } @else {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, false, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as unread'\"\n title=\"Mark as Unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Unread</span>\n </button>\n }\n </div>\n </article>\n }\n }\n </div>\n }\n </div>\n</div>\n"]}
|
package/package.json
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-explorer-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0-edge.1",
|
|
4
4
|
"description": "MemberJunction Explorer: Core Angular Components",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"/dist"
|
|
9
9
|
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"test": "vitest run",
|
|
12
|
-
"prebuild": "mj codegen manifest --exclude-packages @memberjunction --appDir ../../../../packages/MJExplorer --output /dev/null --lazy-config ./src/generated/lazy-feature-config.ts || echo 'Warning: mj codegen manifest not available, using existing lazy-feature-config'",
|
|
13
|
-
"build": "ngc",
|
|
14
|
-
"watch": "ngc -w"
|
|
15
|
-
},
|
|
16
10
|
"keywords": [],
|
|
17
11
|
"author": "",
|
|
18
12
|
"license": "ISC",
|
|
@@ -20,75 +14,84 @@
|
|
|
20
14
|
"@angular/compiler": "21.1.3",
|
|
21
15
|
"@angular/compiler-cli": "21.1.3",
|
|
22
16
|
"sass": "^1.97.3",
|
|
23
|
-
"@memberjunction/ng-test-utils": "
|
|
17
|
+
"@memberjunction/ng-test-utils": "6.1.0-edge.1"
|
|
24
18
|
},
|
|
25
19
|
"peerDependencies": {
|
|
26
|
-
"@angular/common": "21.1.3",
|
|
27
|
-
"@angular/core": "21.1.3",
|
|
28
|
-
"@angular/forms": "21.1.3",
|
|
29
|
-
"@angular/router": "21.1.3"
|
|
20
|
+
"@angular/common": "^21.1.3",
|
|
21
|
+
"@angular/core": "^21.1.3",
|
|
22
|
+
"@angular/forms": "^21.1.3",
|
|
23
|
+
"@angular/router": "^21.1.3"
|
|
30
24
|
},
|
|
31
25
|
"dependencies": {
|
|
32
26
|
"@angular/animations": "21.1.3",
|
|
33
27
|
"@angular/cdk": "21.1.3",
|
|
34
28
|
"@angular/platform-browser": "21.1.3",
|
|
35
29
|
"@auth0/auth0-angular": "^2.6.0",
|
|
36
|
-
"@memberjunction/ai-core-plus": "
|
|
37
|
-
"@memberjunction/ai-engine-base": "
|
|
38
|
-
"@memberjunction/communication-types": "
|
|
39
|
-
"@memberjunction/core": "
|
|
40
|
-
"@memberjunction/core-entities": "
|
|
41
|
-
"@memberjunction/entity-communications-client": "
|
|
42
|
-
"@memberjunction/export-engine": "
|
|
43
|
-
"@memberjunction/global": "
|
|
44
|
-
"@memberjunction/graphql-dataprovider": "
|
|
45
|
-
"@memberjunction/interactive-component-types": "
|
|
46
|
-
"@memberjunction/lists-base": "
|
|
47
|
-
"@memberjunction/theme-engine": "
|
|
48
|
-
"@memberjunction/ng-ai-test-harness": "
|
|
49
|
-
"@memberjunction/ng-artifacts": "
|
|
50
|
-
"@memberjunction/ng-auth-services": "
|
|
51
|
-
"@memberjunction/ng-base-application": "
|
|
52
|
-
"@memberjunction/ng-base-forms": "
|
|
53
|
-
"@memberjunction/ng-base-types": "
|
|
54
|
-
"@memberjunction/ng-composer": "
|
|
55
|
-
"@memberjunction/ng-container-directives": "
|
|
56
|
-
"@memberjunction/ng-conversations": "
|
|
57
|
-
"@memberjunction/ng-dashboard-viewer": "
|
|
58
|
-
"@memberjunction/ng-dashboards": "
|
|
59
|
-
"@memberjunction/ng-entity-form-dialog": "
|
|
60
|
-
"@memberjunction/ng-entity-permissions": "
|
|
61
|
-
"@memberjunction/ng-entity-viewer": "
|
|
62
|
-
"@memberjunction/ng-explorer-settings": "
|
|
63
|
-
"@memberjunction/ng-export-service": "
|
|
64
|
-
"@memberjunction/ng-feedback": "
|
|
65
|
-
"@memberjunction/ng-file-storage": "
|
|
66
|
-
"@memberjunction/ng-generic-dialog": "
|
|
67
|
-
"@memberjunction/ng-list-detail-grid": "
|
|
68
|
-
"@memberjunction/ng-list-management": "
|
|
69
|
-
"@memberjunction/ng-markdown": "
|
|
70
|
-
"@memberjunction/ng-mj-livekit-room": "
|
|
71
|
-
"@memberjunction/ng-notifications": "
|
|
72
|
-
"@memberjunction/ng-pagination": "
|
|
73
|
-
"@memberjunction/ng-query-viewer": "
|
|
74
|
-
"@memberjunction/ng-record-changes": "
|
|
75
|
-
"@memberjunction/ng-record-selector": "
|
|
76
|
-
"@memberjunction/ng-record-tags": "
|
|
77
|
-
"@memberjunction/ng-resource-permissions": "
|
|
78
|
-
"@memberjunction/ng-search": "
|
|
79
|
-
"@memberjunction/ng-shared": "
|
|
80
|
-
"@memberjunction/ng-shared-generic": "
|
|
81
|
-
"@memberjunction/ng-ui-components": "
|
|
82
|
-
"@memberjunction/ng-user-avatar": "
|
|
83
|
-
"@memberjunction/ng-word-cloud": "
|
|
84
|
-
"@memberjunction/templates-base-types": "
|
|
30
|
+
"@memberjunction/ai-core-plus": "6.1.0-edge.1",
|
|
31
|
+
"@memberjunction/ai-engine-base": "6.1.0-edge.1",
|
|
32
|
+
"@memberjunction/communication-types": "6.1.0-edge.1",
|
|
33
|
+
"@memberjunction/core": "6.1.0-edge.1",
|
|
34
|
+
"@memberjunction/core-entities": "6.1.0-edge.1",
|
|
35
|
+
"@memberjunction/entity-communications-client": "6.1.0-edge.1",
|
|
36
|
+
"@memberjunction/export-engine": "6.1.0-edge.1",
|
|
37
|
+
"@memberjunction/global": "6.1.0-edge.1",
|
|
38
|
+
"@memberjunction/graphql-dataprovider": "6.1.0-edge.1",
|
|
39
|
+
"@memberjunction/interactive-component-types": "6.1.0-edge.1",
|
|
40
|
+
"@memberjunction/lists-base": "6.1.0-edge.1",
|
|
41
|
+
"@memberjunction/theme-engine": "6.1.0-edge.1",
|
|
42
|
+
"@memberjunction/ng-ai-test-harness": "6.1.0-edge.1",
|
|
43
|
+
"@memberjunction/ng-artifacts": "6.1.0-edge.1",
|
|
44
|
+
"@memberjunction/ng-auth-services": "6.1.0-edge.1",
|
|
45
|
+
"@memberjunction/ng-base-application": "6.1.0-edge.1",
|
|
46
|
+
"@memberjunction/ng-base-forms": "6.1.0-edge.1",
|
|
47
|
+
"@memberjunction/ng-base-types": "6.1.0-edge.1",
|
|
48
|
+
"@memberjunction/ng-composer": "6.1.0-edge.1",
|
|
49
|
+
"@memberjunction/ng-container-directives": "6.1.0-edge.1",
|
|
50
|
+
"@memberjunction/ng-conversations": "6.1.0-edge.1",
|
|
51
|
+
"@memberjunction/ng-dashboard-viewer": "6.1.0-edge.1",
|
|
52
|
+
"@memberjunction/ng-dashboards": "6.1.0-edge.1",
|
|
53
|
+
"@memberjunction/ng-entity-form-dialog": "6.1.0-edge.1",
|
|
54
|
+
"@memberjunction/ng-entity-permissions": "6.1.0-edge.1",
|
|
55
|
+
"@memberjunction/ng-entity-viewer": "6.1.0-edge.1",
|
|
56
|
+
"@memberjunction/ng-explorer-settings": "6.1.0-edge.1",
|
|
57
|
+
"@memberjunction/ng-export-service": "6.1.0-edge.1",
|
|
58
|
+
"@memberjunction/ng-feedback": "6.1.0-edge.1",
|
|
59
|
+
"@memberjunction/ng-file-storage": "6.1.0-edge.1",
|
|
60
|
+
"@memberjunction/ng-generic-dialog": "6.1.0-edge.1",
|
|
61
|
+
"@memberjunction/ng-list-detail-grid": "6.1.0-edge.1",
|
|
62
|
+
"@memberjunction/ng-list-management": "6.1.0-edge.1",
|
|
63
|
+
"@memberjunction/ng-markdown": "6.1.0-edge.1",
|
|
64
|
+
"@memberjunction/ng-mj-livekit-room": "6.1.0-edge.1",
|
|
65
|
+
"@memberjunction/ng-notifications": "6.1.0-edge.1",
|
|
66
|
+
"@memberjunction/ng-pagination": "6.1.0-edge.1",
|
|
67
|
+
"@memberjunction/ng-query-viewer": "6.1.0-edge.1",
|
|
68
|
+
"@memberjunction/ng-record-changes": "6.1.0-edge.1",
|
|
69
|
+
"@memberjunction/ng-record-selector": "6.1.0-edge.1",
|
|
70
|
+
"@memberjunction/ng-record-tags": "6.1.0-edge.1",
|
|
71
|
+
"@memberjunction/ng-resource-permissions": "6.1.0-edge.1",
|
|
72
|
+
"@memberjunction/ng-search": "6.1.0-edge.1",
|
|
73
|
+
"@memberjunction/ng-shared": "6.1.0-edge.1",
|
|
74
|
+
"@memberjunction/ng-shared-generic": "6.1.0-edge.1",
|
|
75
|
+
"@memberjunction/ng-ui-components": "6.1.0-edge.1",
|
|
76
|
+
"@memberjunction/ng-user-avatar": "6.1.0-edge.1",
|
|
77
|
+
"@memberjunction/ng-word-cloud": "6.1.0-edge.1",
|
|
78
|
+
"@memberjunction/templates-base-types": "6.1.0-edge.1",
|
|
85
79
|
"golden-layout": "^2.6.0",
|
|
86
80
|
"rxjs": "^7.8.2",
|
|
87
|
-
"tslib": "^2.8.1"
|
|
81
|
+
"tslib": "^2.8.1",
|
|
82
|
+
"@memberjunction/ng-react": "6.1.0-edge.1"
|
|
88
83
|
},
|
|
89
84
|
"sideEffects": false,
|
|
90
85
|
"repository": {
|
|
91
86
|
"type": "git",
|
|
92
87
|
"url": "https://github.com/MemberJunction/MJ"
|
|
88
|
+
},
|
|
89
|
+
"mjUILayer": "shell",
|
|
90
|
+
"scripts": {
|
|
91
|
+
"test": "vitest run",
|
|
92
|
+
"prebuild": "mj codegen manifest --exclude-packages @memberjunction --appDir ../../../../packages/MJExplorer --output /dev/null --lazy-config ./src/generated/lazy-feature-config.ts || echo 'Warning: mj codegen manifest not available, using existing lazy-feature-config'",
|
|
93
|
+
"build": "ngc",
|
|
94
|
+
"watch": "ngc -w",
|
|
95
|
+
"test:types": "tsc --noEmit -p tsconfig.spec.json"
|
|
93
96
|
}
|
|
94
|
-
}
|
|
97
|
+
}
|