@memberjunction/ng-conversations 5.4.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/lib/components/agent/agent-process-panel.component.d.ts.map +1 -1
  2. package/dist/lib/components/agent/agent-process-panel.component.js +3 -2
  3. package/dist/lib/components/agent/agent-process-panel.component.js.map +1 -1
  4. package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -1
  5. package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +10 -9
  6. package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -1
  7. package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -1
  8. package/dist/lib/components/collection/artifact-create-modal.component.js +3 -2
  9. package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -1
  10. package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
  11. package/dist/lib/components/collection/collection-form-modal.component.js +4 -3
  12. package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
  13. package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
  14. package/dist/lib/components/collection/collection-share-modal.component.js +5 -4
  15. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  16. package/dist/lib/components/collection/collection-tree.component.d.ts +2 -0
  17. package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
  18. package/dist/lib/components/collection/collection-tree.component.js +24 -17
  19. package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
  20. package/dist/lib/components/collection/collections-full-view.component.d.ts +1 -0
  21. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  22. package/dist/lib/components/collection/collections-full-view.component.js +14 -10
  23. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  24. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +21 -7
  25. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  26. package/dist/lib/components/conversation/conversation-chat-area.component.js +44 -14
  27. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  28. package/dist/lib/components/conversation/conversation-list.component.d.ts +3 -0
  29. package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
  30. package/dist/lib/components/conversation/conversation-list.component.js +21 -11
  31. package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
  32. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  33. package/dist/lib/components/mention/mention-editor.component.js +4 -3
  34. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  35. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  36. package/dist/lib/components/message/conversation-message-rating.component.js +3 -2
  37. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  38. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  39. package/dist/lib/components/message/message-input.component.js +21 -7
  40. package/dist/lib/components/message/message-input.component.js.map +1 -1
  41. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  42. package/dist/lib/components/message/message-item.component.js +7 -6
  43. package/dist/lib/components/message/message-item.component.js.map +1 -1
  44. package/dist/lib/components/project/project-selector.component.d.ts.map +1 -1
  45. package/dist/lib/components/project/project-selector.component.js +3 -2
  46. package/dist/lib/components/project/project-selector.component.js.map +1 -1
  47. package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
  48. package/dist/lib/components/task/tasks-full-view.component.js +4 -3
  49. package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
  50. package/dist/lib/services/agent-state.service.d.ts +4 -0
  51. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  52. package/dist/lib/services/agent-state.service.js +15 -6
  53. package/dist/lib/services/agent-state.service.js.map +1 -1
  54. package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
  55. package/dist/lib/services/artifact-permission.service.js +3 -2
  56. package/dist/lib/services/artifact-permission.service.js.map +1 -1
  57. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  58. package/dist/lib/services/conversation-agent.service.js +5 -4
  59. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  60. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  61. package/dist/lib/services/conversation-attachment.service.js +2 -1
  62. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  63. package/dist/lib/services/conversation-data.service.d.ts.map +1 -1
  64. package/dist/lib/services/conversation-data.service.js +7 -6
  65. package/dist/lib/services/conversation-data.service.js.map +1 -1
  66. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  67. package/dist/lib/services/data-cache.service.js +9 -8
  68. package/dist/lib/services/data-cache.service.js.map +1 -1
  69. package/package.json +17 -17
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-data.service.js","sourceRoot":"","sources":["../../../src/lib/services/conversation-data.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { MJConversationEntity } from '@memberjunction/core-entities';\nimport { Metadata, RunView, UserInfo } from '@memberjunction/core';\n\n/**\n * Shared data service for conversations\n * This is a SINGLETON service that manages the conversation data (list of conversations)\n * Selection state (which conversation is active) is managed by parent components locally\n *\n * This architecture enables multiple conversation panels to coexist (e.g., in tabs)\n * without conflicting over which conversation is \"active\"\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ConversationDataService {\n // The list of conversations - shared across all components\n public conversations: MJConversationEntity[] = [];\n\n // Observable for conversation list changes (for components that need reactive updates)\n private _conversations$ = new BehaviorSubject<MJConversationEntity[]>([]);\n public readonly conversations$ = this._conversations$.asObservable();\n\n // Search query for filtering - shared across sidebars\n public searchQuery: string = '';\n\n // Loading state\n public isLoading: boolean = false;\n\n constructor() {}\n\n /**\n * Gets a conversation by ID\n * @param id The conversation ID\n * @returns The conversation entity or null if not found\n */\n getConversationById(id: string): MJConversationEntity | null {\n return this.conversations.find(c => c.ID === id) || null;\n }\n\n /**\n * Gets filtered conversations based on search query\n */\n get filteredConversations(): MJConversationEntity[] {\n if (!this.searchQuery || this.searchQuery.trim() === '') {\n return this.conversations;\n }\n const lowerQuery = this.searchQuery.toLowerCase();\n return this.conversations.filter(c =>\n (c.Name?.toLowerCase().includes(lowerQuery)) ||\n (c.Description?.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Gets pinned conversations\n */\n get pinnedConversations(): MJConversationEntity[] {\n return this.conversations.filter(c => c.IsPinned);\n }\n\n /**\n * Sets the search query\n * @param query The search query string\n */\n setSearchQuery(query: string): void {\n this.searchQuery = query;\n }\n\n /**\n * Clears the search query\n */\n clearSearchQuery(): void {\n this.searchQuery = '';\n }\n\n /**\n * Adds a conversation to the list\n * @param conversation The conversation to add\n */\n addConversation(conversation: MJConversationEntity): void {\n this.conversations = [conversation, ...this.conversations];\n this._conversations$.next(this.conversations);\n }\n\n /**\n * Updates a conversation in the list by directly modifying the entity object\n * Angular change detection will pick up the changes automatically\n * @param id The conversation ID\n * @param updates The fields to update\n */\n updateConversationInPlace(id: string, updates: Partial<MJConversationEntity>): void {\n const conversation = this.conversations.find(c => c.ID === id);\n if (conversation) {\n Object.assign(conversation, updates);\n // Emit update to trigger reactive subscribers\n this._conversations$.next(this.conversations);\n }\n }\n\n /**\n * Removes a conversation from the list\n * @param id The conversation ID to remove\n * @returns True if the conversation was the active one (caller may need to handle)\n */\n removeConversation(id: string): void {\n this.conversations = this.conversations.filter(c => c.ID !== id);\n this._conversations$.next(this.conversations);\n }\n\n /**\n * Loads conversations from the database.\n * Skips if already loaded to prevent redundant DB calls.\n * @param environmentId The environment ID to filter by\n * @param currentUser The current user context\n */\n async loadConversations(environmentId: string, currentUser: UserInfo): Promise<void> {\n // Skip if already loaded - prevents redundant DB calls when multiple components initialize\n if (this.conversations.length > 0) {\n return;\n }\n await this.fetchConversations(environmentId, currentUser);\n }\n\n /**\n * Force refresh conversations from the database, ignoring cache.\n * Use this when user explicitly requests a refresh.\n * @param environmentId The environment ID to filter by\n * @param currentUser The current user context\n */\n async refreshConversations(environmentId: string, currentUser: UserInfo): Promise<void> {\n await this.fetchConversations(environmentId, currentUser);\n }\n\n /**\n * Internal method to fetch conversations from the database.\n * @param environmentId The environment ID to filter by\n * @param currentUser The current user context\n */\n private async fetchConversations(environmentId: string, currentUser: UserInfo): Promise<void> {\n this.isLoading = true;\n try {\n const rv = new RunView();\n const filter = `EnvironmentID='${environmentId}' AND UserID='${currentUser.ID}' AND (IsArchived IS NULL OR IsArchived=0)`;\n\n const result = await rv.RunView<MJConversationEntity>(\n {\n EntityName: 'MJ: Conversations',\n ExtraFilter: filter,\n OrderBy: 'IsPinned DESC, __mj_UpdatedAt DESC',\n MaxRows: 1000,\n ResultType: 'entity_object' \n },\n currentUser\n );\n\n if (result.Success) {\n this.conversations = result.Results || [];\n } else {\n console.error('Failed to load conversations:', result.ErrorMessage);\n this.conversations = [];\n }\n this._conversations$.next(this.conversations);\n } catch (error) {\n console.error('Error loading conversations:', error);\n this.conversations = [];\n this._conversations$.next(this.conversations);\n } finally {\n this.isLoading = false;\n }\n }\n\n /**\n * Creates a new conversation\n * @param name The conversation name\n * @param environmentId The environment ID\n * @param currentUser The current user context\n * @param description Optional description\n * @param projectId Optional project ID\n * @returns The created conversation entity\n */\n async createConversation(\n name: string,\n environmentId: string,\n currentUser: UserInfo,\n description?: string,\n projectId?: string\n ): Promise<MJConversationEntity> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n conversation.Name = name;\n conversation.EnvironmentID = environmentId;\n conversation.UserID = currentUser.ID;\n if (description) conversation.Description = description;\n if (projectId) conversation.ProjectID = projectId;\n\n const saved = await conversation.Save();\n if (saved) {\n this.addConversation(conversation);\n return conversation;\n } else {\n throw new Error(conversation.LatestResult?.Message || 'Failed to create conversation');\n }\n }\n\n /**\n * Deletes a conversation\n * @param id The conversation ID\n * @param currentUser The current user context\n * @returns True if successful\n */\n async deleteConversation(id: string, currentUser: UserInfo): Promise<boolean> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n const loaded = await conversation.Load(id);\n if (!loaded) {\n throw new Error('Conversation not found');\n }\n\n const deleted = await conversation.Delete();\n if (deleted) {\n this.removeConversation(id);\n return true;\n } else {\n throw new Error(conversation.LatestResult?.Message || 'Failed to delete conversation');\n }\n }\n\n /**\n * Deletes multiple conversations in a batch operation\n * @param ids - Array of conversation IDs to delete\n * @param currentUser - Current user info\n * @returns Object with successful deletions and failed deletions with error info\n */\n async deleteMultipleConversations(\n ids: string[],\n currentUser: UserInfo\n ): Promise<{\n successful: string[];\n failed: Array<{ id: string; name: string; error: string }>;\n }> {\n const successful: string[] = [];\n const failed: Array<{ id: string; name: string; error: string }> = [];\n\n for (const id of ids) {\n try {\n const conversation = this.conversations.find(c => c.ID === id);\n const name = conversation?.Name || 'Unknown';\n\n const deleted = await this.deleteConversation(id, currentUser);\n if (deleted) {\n successful.push(id);\n } else {\n failed.push({ id, name, error: 'Delete returned false' });\n }\n } catch (error) {\n const conversation = this.conversations.find(c => c.ID === id);\n failed.push({\n id,\n name: conversation?.Name || 'Unknown',\n error: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n }\n\n return { successful, failed };\n }\n\n /**\n * Updates a conversation - saves to database AND updates in-place in the array\n * @param id The conversation ID\n * @param updates The fields to update\n * @param currentUser The current user context\n * @returns True if successful\n */\n async saveConversation(\n id: string,\n updates: Partial<MJConversationEntity>,\n currentUser: UserInfo\n ): Promise<boolean> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n const loaded = await conversation.Load(id);\n if (!loaded) {\n throw new Error('Conversation not found');\n }\n\n // Apply updates\n Object.assign(conversation, updates);\n\n const saved = await conversation.Save();\n if (saved) {\n // Update the in-memory conversation directly\n this.updateConversationInPlace(id, updates);\n return true;\n } else {\n throw new Error(conversation.LatestResult?.Message || 'Failed to update conversation');\n }\n }\n\n /**\n * Toggles the pinned status of a conversation\n * @param id The conversation ID\n * @param currentUser The current user context\n */\n async togglePin(id: string, currentUser: UserInfo): Promise<void> {\n const conversation = this.conversations.find(c => c.ID === id);\n if (conversation) {\n await this.saveConversation(id, { IsPinned: !conversation.IsPinned }, currentUser);\n }\n }\n\n /**\n * Archives a conversation\n * @param id The conversation ID\n * @param currentUser The current user context\n */\n async archiveConversation(id: string, currentUser: UserInfo): Promise<void> {\n await this.saveConversation(id, { IsArchived: true }, currentUser);\n }\n}\n"]}
1
+ {"version":3,"file":"conversation-data.service.js","sourceRoot":"","sources":["../../../src/lib/services/conversation-data.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { MJConversationEntity } from '@memberjunction/core-entities';\nimport { Metadata, RunView, UserInfo } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Shared data service for conversations\n * This is a SINGLETON service that manages the conversation data (list of conversations)\n * Selection state (which conversation is active) is managed by parent components locally\n *\n * This architecture enables multiple conversation panels to coexist (e.g., in tabs)\n * without conflicting over which conversation is \"active\"\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ConversationDataService {\n // The list of conversations - shared across all components\n public conversations: MJConversationEntity[] = [];\n\n // Observable for conversation list changes (for components that need reactive updates)\n private _conversations$ = new BehaviorSubject<MJConversationEntity[]>([]);\n public readonly conversations$ = this._conversations$.asObservable();\n\n // Search query for filtering - shared across sidebars\n public searchQuery: string = '';\n\n // Loading state\n public isLoading: boolean = false;\n\n constructor() {}\n\n /**\n * Gets a conversation by ID\n * @param id The conversation ID\n * @returns The conversation entity or null if not found\n */\n getConversationById(id: string): MJConversationEntity | null {\n return this.conversations.find(c => UUIDsEqual(c.ID, id)) || null;\n }\n\n /**\n * Gets filtered conversations based on search query\n */\n get filteredConversations(): MJConversationEntity[] {\n if (!this.searchQuery || this.searchQuery.trim() === '') {\n return this.conversations;\n }\n const lowerQuery = this.searchQuery.toLowerCase();\n return this.conversations.filter(c =>\n (c.Name?.toLowerCase().includes(lowerQuery)) ||\n (c.Description?.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Gets pinned conversations\n */\n get pinnedConversations(): MJConversationEntity[] {\n return this.conversations.filter(c => c.IsPinned);\n }\n\n /**\n * Sets the search query\n * @param query The search query string\n */\n setSearchQuery(query: string): void {\n this.searchQuery = query;\n }\n\n /**\n * Clears the search query\n */\n clearSearchQuery(): void {\n this.searchQuery = '';\n }\n\n /**\n * Adds a conversation to the list\n * @param conversation The conversation to add\n */\n addConversation(conversation: MJConversationEntity): void {\n this.conversations = [conversation, ...this.conversations];\n this._conversations$.next(this.conversations);\n }\n\n /**\n * Updates a conversation in the list by directly modifying the entity object\n * Angular change detection will pick up the changes automatically\n * @param id The conversation ID\n * @param updates The fields to update\n */\n updateConversationInPlace(id: string, updates: Partial<MJConversationEntity>): void {\n const conversation = this.conversations.find(c => UUIDsEqual(c.ID, id));\n if (conversation) {\n Object.assign(conversation, updates);\n // Emit update to trigger reactive subscribers\n this._conversations$.next(this.conversations);\n }\n }\n\n /**\n * Removes a conversation from the list\n * @param id The conversation ID to remove\n * @returns True if the conversation was the active one (caller may need to handle)\n */\n removeConversation(id: string): void {\n this.conversations = this.conversations.filter(c => !UUIDsEqual(c.ID, id));\n this._conversations$.next(this.conversations);\n }\n\n /**\n * Loads conversations from the database.\n * Skips if already loaded to prevent redundant DB calls.\n * @param environmentId The environment ID to filter by\n * @param currentUser The current user context\n */\n async loadConversations(environmentId: string, currentUser: UserInfo): Promise<void> {\n // Skip if already loaded - prevents redundant DB calls when multiple components initialize\n if (this.conversations.length > 0) {\n return;\n }\n await this.fetchConversations(environmentId, currentUser);\n }\n\n /**\n * Force refresh conversations from the database, ignoring cache.\n * Use this when user explicitly requests a refresh.\n * @param environmentId The environment ID to filter by\n * @param currentUser The current user context\n */\n async refreshConversations(environmentId: string, currentUser: UserInfo): Promise<void> {\n await this.fetchConversations(environmentId, currentUser);\n }\n\n /**\n * Internal method to fetch conversations from the database.\n * @param environmentId The environment ID to filter by\n * @param currentUser The current user context\n */\n private async fetchConversations(environmentId: string, currentUser: UserInfo): Promise<void> {\n this.isLoading = true;\n try {\n const rv = new RunView();\n const filter = `EnvironmentID='${environmentId}' AND UserID='${currentUser.ID}' AND (IsArchived IS NULL OR IsArchived=0)`;\n\n const result = await rv.RunView<MJConversationEntity>(\n {\n EntityName: 'MJ: Conversations',\n ExtraFilter: filter,\n OrderBy: 'IsPinned DESC, __mj_UpdatedAt DESC',\n MaxRows: 1000,\n ResultType: 'entity_object' \n },\n currentUser\n );\n\n if (result.Success) {\n this.conversations = result.Results || [];\n } else {\n console.error('Failed to load conversations:', result.ErrorMessage);\n this.conversations = [];\n }\n this._conversations$.next(this.conversations);\n } catch (error) {\n console.error('Error loading conversations:', error);\n this.conversations = [];\n this._conversations$.next(this.conversations);\n } finally {\n this.isLoading = false;\n }\n }\n\n /**\n * Creates a new conversation\n * @param name The conversation name\n * @param environmentId The environment ID\n * @param currentUser The current user context\n * @param description Optional description\n * @param projectId Optional project ID\n * @returns The created conversation entity\n */\n async createConversation(\n name: string,\n environmentId: string,\n currentUser: UserInfo,\n description?: string,\n projectId?: string\n ): Promise<MJConversationEntity> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n conversation.Name = name;\n conversation.EnvironmentID = environmentId;\n conversation.UserID = currentUser.ID;\n if (description) conversation.Description = description;\n if (projectId) conversation.ProjectID = projectId;\n\n const saved = await conversation.Save();\n if (saved) {\n this.addConversation(conversation);\n return conversation;\n } else {\n throw new Error(conversation.LatestResult?.Message || 'Failed to create conversation');\n }\n }\n\n /**\n * Deletes a conversation\n * @param id The conversation ID\n * @param currentUser The current user context\n * @returns True if successful\n */\n async deleteConversation(id: string, currentUser: UserInfo): Promise<boolean> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n const loaded = await conversation.Load(id);\n if (!loaded) {\n throw new Error('Conversation not found');\n }\n\n const deleted = await conversation.Delete();\n if (deleted) {\n this.removeConversation(id);\n return true;\n } else {\n throw new Error(conversation.LatestResult?.Message || 'Failed to delete conversation');\n }\n }\n\n /**\n * Deletes multiple conversations in a batch operation\n * @param ids - Array of conversation IDs to delete\n * @param currentUser - Current user info\n * @returns Object with successful deletions and failed deletions with error info\n */\n async deleteMultipleConversations(\n ids: string[],\n currentUser: UserInfo\n ): Promise<{\n successful: string[];\n failed: Array<{ id: string; name: string; error: string }>;\n }> {\n const successful: string[] = [];\n const failed: Array<{ id: string; name: string; error: string }> = [];\n\n for (const id of ids) {\n try {\n const conversation = this.conversations.find(c => UUIDsEqual(c.ID, id));\n const name = conversation?.Name || 'Unknown';\n\n const deleted = await this.deleteConversation(id, currentUser);\n if (deleted) {\n successful.push(id);\n } else {\n failed.push({ id, name, error: 'Delete returned false' });\n }\n } catch (error) {\n const conversation = this.conversations.find(c => UUIDsEqual(c.ID, id));\n failed.push({\n id,\n name: conversation?.Name || 'Unknown',\n error: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n }\n\n return { successful, failed };\n }\n\n /**\n * Updates a conversation - saves to database AND updates in-place in the array\n * @param id The conversation ID\n * @param updates The fields to update\n * @param currentUser The current user context\n * @returns True if successful\n */\n async saveConversation(\n id: string,\n updates: Partial<MJConversationEntity>,\n currentUser: UserInfo\n ): Promise<boolean> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n const loaded = await conversation.Load(id);\n if (!loaded) {\n throw new Error('Conversation not found');\n }\n\n // Apply updates\n Object.assign(conversation, updates);\n\n const saved = await conversation.Save();\n if (saved) {\n // Update the in-memory conversation directly\n this.updateConversationInPlace(id, updates);\n return true;\n } else {\n throw new Error(conversation.LatestResult?.Message || 'Failed to update conversation');\n }\n }\n\n /**\n * Toggles the pinned status of a conversation\n * @param id The conversation ID\n * @param currentUser The current user context\n */\n async togglePin(id: string, currentUser: UserInfo): Promise<void> {\n const conversation = this.conversations.find(c => UUIDsEqual(c.ID, id));\n if (conversation) {\n await this.saveConversation(id, { IsPinned: !conversation.IsPinned }, currentUser);\n }\n }\n\n /**\n * Archives a conversation\n * @param id The conversation ID\n * @param currentUser The current user context\n */\n async archiveConversation(id: string, currentUser: UserInfo): Promise<void> {\n await this.saveConversation(id, { IsArchived: true }, currentUser);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"data-cache.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/data-cache.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAY,QAAQ,EAAc,MAAM,sBAAsB,CAAC;;AAEtE;;;;;;;;;GASG;AACH,qBAGa,gBAAgB;IAE3B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,mBAAmB,CAAoC;;IAQ/D;;;;;OAKG;IACG,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAqB9F;;;;;OAKG;IACG,kBAAkB,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAY9E;;;OAGG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIpC;;;OAGG;IACH,sBAAsB,IAAI,oBAAoB,EAAE;IAQhD;;;;;OAKG;IACG,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC;IAqB1G;;;;;OAKG;IACG,wBAAwB,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAe1F;;;;;;OAMG;IACG,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAyCnH;;;;OAIG;IACH,4BAA4B,CAAC,cAAc,EAAE,MAAM,GAAG,0BAA0B,EAAE;IAIlF;;;OAGG;IACH,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ1C;;;;OAIG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatD;;;;OAIG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvE;;;OAGG;IACH,KAAK,IAAI,IAAI;IAKb;;;OAGG;IACH,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAK/C;;;OAGG;IACH,QAAQ,IAAI;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE;yCAlQvD,gBAAgB;6CAAhB,gBAAgB;CAwQ5B"}
1
+ {"version":3,"file":"data-cache.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/data-cache.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAY,QAAQ,EAAc,MAAM,sBAAsB,CAAC;;AAGtE;;;;;;;;;GASG;AACH,qBAGa,gBAAgB;IAE3B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,mBAAmB,CAAoC;;IAQ/D;;;;;OAKG;IACG,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAqB9F;;;;;OAKG;IACG,kBAAkB,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAY9E;;;OAGG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIpC;;;OAGG;IACH,sBAAsB,IAAI,oBAAoB,EAAE;IAQhD;;;;;OAKG;IACG,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC;IAqB1G;;;;;OAKG;IACG,wBAAwB,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAe1F;;;;;;OAMG;IACG,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAyCnH;;;;OAIG;IACH,4BAA4B,CAAC,cAAc,EAAE,MAAM,GAAG,0BAA0B,EAAE;IAIlF;;;OAGG;IACH,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ1C;;;;OAIG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatD;;;;OAIG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvE;;;OAGG;IACH,KAAK,IAAI,IAAI;IAKb;;;OAGG;IACH,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAK/C;;;OAGG;IACH,QAAQ,IAAI;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE;yCAlQvD,gBAAgB;6CAAhB,gBAAgB;CAwQ5B"}
@@ -1,5 +1,6 @@
1
1
  import { Injectable } from '@angular/core';
2
2
  import { Metadata } from '@memberjunction/core';
3
+ import { UUIDsEqual } from '@memberjunction/global';
3
4
  import * as i0 from "@angular/core";
4
5
  /**
5
6
  * Global singleton cache for conversation-related entities.
@@ -27,7 +28,7 @@ export class DataCacheService {
27
28
  */
28
29
  async getConversation(id, currentUser) {
29
30
  // Check cache first
30
- const cached = this.conversations.find(c => c.ID === id);
31
+ const cached = this.conversations.find(c => UUIDsEqual(c.ID, id));
31
32
  if (cached) {
32
33
  return cached;
33
34
  }
@@ -62,7 +63,7 @@ export class DataCacheService {
62
63
  * @param id The conversation ID to remove
63
64
  */
64
65
  removeConversation(id) {
65
- this.conversations = this.conversations.filter(c => c.ID !== id);
66
+ this.conversations = this.conversations.filter(c => !UUIDsEqual(c.ID, id));
66
67
  }
67
68
  /**
68
69
  * Get all cached MJConversationEntity objects (no DB call)
@@ -82,7 +83,7 @@ export class DataCacheService {
82
83
  */
83
84
  async getConversationDetail(id, currentUser) {
84
85
  // Check cache first
85
- const cached = this.conversationDetails.find(d => d.ID === id);
86
+ const cached = this.conversationDetails.find(d => UUIDsEqual(d.ID, id));
86
87
  if (cached) {
87
88
  return cached;
88
89
  }
@@ -137,7 +138,7 @@ export class DataCacheService {
137
138
  console.log(`[${timestamp}] 💾 DataCacheService - Loaded ${details.length} message(s) for conversation ${conversationId}`);
138
139
  // Add all to cache (avoid duplicates by checking ID)
139
140
  for (const detail of details) {
140
- const existingIndex = this.conversationDetails.findIndex(d => d.ID === detail.ID);
141
+ const existingIndex = this.conversationDetails.findIndex(d => UUIDsEqual(d.ID, detail.ID));
141
142
  if (existingIndex >= 0) {
142
143
  // Replace existing (ensures we keep the same object reference)
143
144
  this.conversationDetails[existingIndex] = detail;
@@ -158,14 +159,14 @@ export class DataCacheService {
158
159
  * @returns Array of cached conversation details
159
160
  */
160
161
  getCachedConversationDetails(conversationId) {
161
- return this.conversationDetails.filter(d => d.ConversationID === conversationId);
162
+ return this.conversationDetails.filter(d => UUIDsEqual(d.ConversationID, conversationId));
162
163
  }
163
164
  /**
164
165
  * Remove a MJConversationDetailEntity from the cache
165
166
  * @param id The conversation detail ID to remove
166
167
  */
167
168
  removeConversationDetail(id) {
168
- this.conversationDetails = this.conversationDetails.filter(d => d.ID !== id);
169
+ this.conversationDetails = this.conversationDetails.filter(d => !UUIDsEqual(d.ID, id));
169
170
  }
170
171
  // =============================================================================
171
172
  // Cache Management
@@ -224,8 +225,8 @@ export class DataCacheService {
224
225
  * @param conversationId The conversation ID
225
226
  */
226
227
  clearConversation(conversationId) {
227
- this.conversations = this.conversations.filter(c => c.ID !== conversationId);
228
- this.conversationDetails = this.conversationDetails.filter(d => d.ConversationID !== conversationId);
228
+ this.conversations = this.conversations.filter(c => !UUIDsEqual(c.ID, conversationId));
229
+ this.conversationDetails = this.conversationDetails.filter(d => !UUIDsEqual(d.ConversationID, conversationId));
229
230
  }
230
231
  /**
231
232
  * Get cache statistics for debugging
@@ -1 +1 @@
1
- {"version":3,"file":"data-cache.service.js","sourceRoot":"","sources":["../../../src/lib/services/data-cache.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJConversationEntity, MJConversationDetailEntity } from '@memberjunction/core-entities';\nimport { Metadata, UserInfo, BaseEntity } from '@memberjunction/core';\n\n/**\n * Global singleton cache for conversation-related entities.\n * Maintains single instances of entities to prevent race conditions and ensure\n * all components see the same object state.\n *\n * Pattern: Instead of creating new entity instances with GetEntityObject() everywhere,\n * request entities from this cache. The cache returns the same instance each time,\n * so when one component updates entity.Status = 'Complete', all other components\n * see that change immediately without needing to reload from the database.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class DataCacheService {\n // Separate arrays for each entity type\n private conversations: MJConversationEntity[] = [];\n private conversationDetails: MJConversationDetailEntity[] = [];\n\n constructor() {}\n\n // =============================================================================\n // MJConversationEntity Methods\n // =============================================================================\n\n /**\n * Get a MJConversationEntity by ID from cache, or load it if not cached\n * @param id The conversation ID\n * @param currentUser User context for loading\n * @returns The cached or loaded MJConversationEntity, or null if not found\n */\n async getConversation(id: string, currentUser: UserInfo): Promise<MJConversationEntity | null> {\n // Check cache first\n const cached = this.conversations.find(c => c.ID === id);\n if (cached) {\n return cached;\n }\n\n // Not in cache - load from DB\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n const loaded = await conversation.Load(id);\n\n if (loaded) {\n // Add to cache\n this.conversations.push(conversation);\n return conversation;\n }\n\n return null;\n }\n\n /**\n * Create a new MJConversationEntity and automatically cache it\n * The cache is the ONLY place GetEntityObject() should be called\n * @param currentUser User context\n * @returns New MJConversationEntity instance (already cached)\n */\n async createConversation(currentUser: UserInfo): Promise<MJConversationEntity> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n // Automatically add to cache - user code doesn't need to do anything\n // Note: Conversation has no ID yet (not saved), so we can't deduplicate\n // After Save(), the ID will be populated and future getConversation() calls will find it\n this.conversations.push(conversation);\n\n return conversation;\n }\n\n /**\n * Remove a MJConversationEntity from the cache\n * @param id The conversation ID to remove\n */\n removeConversation(id: string): void {\n this.conversations = this.conversations.filter(c => c.ID !== id);\n }\n\n /**\n * Get all cached MJConversationEntity objects (no DB call)\n * @returns Array of cached conversations\n */\n getCachedConversations(): MJConversationEntity[] {\n return this.conversations;\n }\n\n // =============================================================================\n // MJConversationDetailEntity Methods\n // =============================================================================\n\n /**\n * Get a MJConversationDetailEntity by ID from cache, or load it if not cached\n * @param id The conversation detail ID\n * @param currentUser User context for loading\n * @returns The cached or loaded MJConversationDetailEntity, or null if not found\n */\n async getConversationDetail(id: string, currentUser: UserInfo): Promise<MJConversationDetailEntity | null> {\n // Check cache first\n const cached = this.conversationDetails.find(d => d.ID === id);\n if (cached) {\n return cached;\n }\n\n // Not in cache - load from DB\n const md = new Metadata();\n const detail = await md.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', currentUser);\n const loaded = await detail.Load(id);\n\n if (loaded) {\n // Add to cache\n this.conversationDetails.push(detail);\n return detail;\n }\n\n return null;\n }\n\n /**\n * Create a new MJConversationDetailEntity and automatically cache it\n * The cache is the ONLY place GetEntityObject() should be called\n * @param currentUser User context\n * @returns New MJConversationDetailEntity instance (already cached)\n */\n async createConversationDetail(currentUser: UserInfo): Promise<MJConversationDetailEntity> {\n const md = new Metadata();\n const detail = await md.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', currentUser);\n\n // Automatically add to cache - user code doesn't need to do anything\n // Note: Detail has no ID yet (not saved), so we can't deduplicate\n // After Save(), the ID will be populated and future getConversationDetail() calls will find it\n\n detail.UserRating = 1 // TO-DO - temp fix for a BUG - remove this after 2.105.0 makes this field optional again, right now it requires a value even though column is nullable\n\n this.conversationDetails.push(detail);\n\n return detail;\n }\n\n /**\n * Load all ConversationDetail entities for a conversation and cache them\n * Used when loading a conversation's message history\n * @param conversationId The conversation ID\n * @param currentUser User context\n * @returns Array of MJConversationDetailEntity objects\n */\n async loadConversationDetails(conversationId: string, currentUser: UserInfo): Promise<MJConversationDetailEntity[]> {\n const timestamp = new Date().toISOString();\n console.log(`[${timestamp}] 💾 DataCacheService.loadConversationDetails - Loading messages for conversation ${conversationId}`);\n\n const md = new Metadata();\n const rv = new (await import('@memberjunction/core')).RunView();\n\n console.log(`[${timestamp}] 💾 DataCacheService - Executing RunView for Conversation Details`);\n const result = await rv.RunView<MJConversationDetailEntity>(\n {\n EntityName: 'MJ: Conversation Details',\n ExtraFilter: `ConversationID='${conversationId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n ResultType: 'entity_object'\n },\n currentUser\n );\n\n if (result.Success) {\n const details = result.Results || [];\n console.log(`[${timestamp}] 💾 DataCacheService - Loaded ${details.length} message(s) for conversation ${conversationId}`);\n\n // Add all to cache (avoid duplicates by checking ID)\n for (const detail of details) {\n const existingIndex = this.conversationDetails.findIndex(d => d.ID === detail.ID);\n if (existingIndex >= 0) {\n // Replace existing (ensures we keep the same object reference)\n this.conversationDetails[existingIndex] = detail;\n } else {\n // Add new\n this.conversationDetails.push(detail);\n }\n }\n\n return details;\n }\n\n console.log(`[${timestamp}] 💾 DataCacheService - Failed to load messages for conversation ${conversationId}`);\n return [];\n }\n\n /**\n * Get all cached ConversationDetail entities for a conversation (no DB call)\n * @param conversationId The conversation ID\n * @returns Array of cached conversation details\n */\n getCachedConversationDetails(conversationId: string): MJConversationDetailEntity[] {\n return this.conversationDetails.filter(d => d.ConversationID === conversationId);\n }\n\n /**\n * Remove a MJConversationDetailEntity from the cache\n * @param id The conversation detail ID to remove\n */\n removeConversationDetail(id: string): void {\n this.conversationDetails = this.conversationDetails.filter(d => d.ID !== id);\n }\n\n // =============================================================================\n // Cache Management\n // =============================================================================\n\n /**\n * Refresh entity data by clearing cached entities of a specific type\n * This forces a reload from the database on next access\n * @param entityName The entity name to refresh (e.g., 'Conversations', 'MJ: Conversation Details')\n */\n async refreshEntity(entityName: string): Promise<void> {\n switch (entityName) {\n case 'Conversations':\n this.conversations = [];\n break;\n case 'MJ: Conversation Details':\n this.conversationDetails = [];\n break;\n default:\n console.warn('Unknown entity name for refresh:', entityName);\n }\n }\n\n /**\n * Refresh a specific cache by name\n * This method can be extended to handle different cache types\n * @param cacheName The cache name ('Core', 'AI', 'Actions')\n */\n async refreshCache(cacheName: 'Core' | 'AI' | 'Actions'): Promise<void> {\n switch (cacheName) {\n case 'Core':\n // Clear core entity caches\n this.clear();\n break;\n case 'AI':\n // AI-specific cache refresh would go here\n // For now, just log it\n console.log('AI cache refresh requested (not yet implemented)');\n break;\n case 'Actions':\n // Actions-specific cache refresh would go here\n console.log('Actions cache refresh requested (not yet implemented)');\n break;\n default:\n console.warn('Unknown cache name for refresh:', cacheName);\n }\n }\n\n /**\n * Clear all cached entities\n * Call when switching environments, users, or when needed\n */\n clear(): void {\n this.conversations = [];\n this.conversationDetails = [];\n }\n\n /**\n * Clear cached entities for a specific conversation\n * @param conversationId The conversation ID\n */\n clearConversation(conversationId: string): void {\n this.conversations = this.conversations.filter(c => c.ID !== conversationId);\n this.conversationDetails = this.conversationDetails.filter(d => d.ConversationID !== conversationId);\n }\n\n /**\n * Get cache statistics for debugging\n * @returns Object with cache sizes\n */\n getStats(): { conversations: number; conversationDetails: number } {\n return {\n conversations: this.conversations.length,\n conversationDetails: this.conversationDetails.length\n };\n }\n}\n"]}
1
+ {"version":3,"file":"data-cache.service.js","sourceRoot":"","sources":["../../../src/lib/services/data-cache.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJConversationEntity, MJConversationDetailEntity } from '@memberjunction/core-entities';\nimport { Metadata, UserInfo, BaseEntity } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Global singleton cache for conversation-related entities.\n * Maintains single instances of entities to prevent race conditions and ensure\n * all components see the same object state.\n *\n * Pattern: Instead of creating new entity instances with GetEntityObject() everywhere,\n * request entities from this cache. The cache returns the same instance each time,\n * so when one component updates entity.Status = 'Complete', all other components\n * see that change immediately without needing to reload from the database.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class DataCacheService {\n // Separate arrays for each entity type\n private conversations: MJConversationEntity[] = [];\n private conversationDetails: MJConversationDetailEntity[] = [];\n\n constructor() {}\n\n // =============================================================================\n // MJConversationEntity Methods\n // =============================================================================\n\n /**\n * Get a MJConversationEntity by ID from cache, or load it if not cached\n * @param id The conversation ID\n * @param currentUser User context for loading\n * @returns The cached or loaded MJConversationEntity, or null if not found\n */\n async getConversation(id: string, currentUser: UserInfo): Promise<MJConversationEntity | null> {\n // Check cache first\n const cached = this.conversations.find(c => UUIDsEqual(c.ID, id));\n if (cached) {\n return cached;\n }\n\n // Not in cache - load from DB\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n const loaded = await conversation.Load(id);\n\n if (loaded) {\n // Add to cache\n this.conversations.push(conversation);\n return conversation;\n }\n\n return null;\n }\n\n /**\n * Create a new MJConversationEntity and automatically cache it\n * The cache is the ONLY place GetEntityObject() should be called\n * @param currentUser User context\n * @returns New MJConversationEntity instance (already cached)\n */\n async createConversation(currentUser: UserInfo): Promise<MJConversationEntity> {\n const md = new Metadata();\n const conversation = await md.GetEntityObject<MJConversationEntity>('MJ: Conversations', currentUser);\n\n // Automatically add to cache - user code doesn't need to do anything\n // Note: Conversation has no ID yet (not saved), so we can't deduplicate\n // After Save(), the ID will be populated and future getConversation() calls will find it\n this.conversations.push(conversation);\n\n return conversation;\n }\n\n /**\n * Remove a MJConversationEntity from the cache\n * @param id The conversation ID to remove\n */\n removeConversation(id: string): void {\n this.conversations = this.conversations.filter(c => !UUIDsEqual(c.ID, id));\n }\n\n /**\n * Get all cached MJConversationEntity objects (no DB call)\n * @returns Array of cached conversations\n */\n getCachedConversations(): MJConversationEntity[] {\n return this.conversations;\n }\n\n // =============================================================================\n // MJConversationDetailEntity Methods\n // =============================================================================\n\n /**\n * Get a MJConversationDetailEntity by ID from cache, or load it if not cached\n * @param id The conversation detail ID\n * @param currentUser User context for loading\n * @returns The cached or loaded MJConversationDetailEntity, or null if not found\n */\n async getConversationDetail(id: string, currentUser: UserInfo): Promise<MJConversationDetailEntity | null> {\n // Check cache first\n const cached = this.conversationDetails.find(d => UUIDsEqual(d.ID, id));\n if (cached) {\n return cached;\n }\n\n // Not in cache - load from DB\n const md = new Metadata();\n const detail = await md.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', currentUser);\n const loaded = await detail.Load(id);\n\n if (loaded) {\n // Add to cache\n this.conversationDetails.push(detail);\n return detail;\n }\n\n return null;\n }\n\n /**\n * Create a new MJConversationDetailEntity and automatically cache it\n * The cache is the ONLY place GetEntityObject() should be called\n * @param currentUser User context\n * @returns New MJConversationDetailEntity instance (already cached)\n */\n async createConversationDetail(currentUser: UserInfo): Promise<MJConversationDetailEntity> {\n const md = new Metadata();\n const detail = await md.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', currentUser);\n\n // Automatically add to cache - user code doesn't need to do anything\n // Note: Detail has no ID yet (not saved), so we can't deduplicate\n // After Save(), the ID will be populated and future getConversationDetail() calls will find it\n\n detail.UserRating = 1 // TO-DO - temp fix for a BUG - remove this after 2.105.0 makes this field optional again, right now it requires a value even though column is nullable\n\n this.conversationDetails.push(detail);\n\n return detail;\n }\n\n /**\n * Load all ConversationDetail entities for a conversation and cache them\n * Used when loading a conversation's message history\n * @param conversationId The conversation ID\n * @param currentUser User context\n * @returns Array of MJConversationDetailEntity objects\n */\n async loadConversationDetails(conversationId: string, currentUser: UserInfo): Promise<MJConversationDetailEntity[]> {\n const timestamp = new Date().toISOString();\n console.log(`[${timestamp}] 💾 DataCacheService.loadConversationDetails - Loading messages for conversation ${conversationId}`);\n\n const md = new Metadata();\n const rv = new (await import('@memberjunction/core')).RunView();\n\n console.log(`[${timestamp}] 💾 DataCacheService - Executing RunView for Conversation Details`);\n const result = await rv.RunView<MJConversationDetailEntity>(\n {\n EntityName: 'MJ: Conversation Details',\n ExtraFilter: `ConversationID='${conversationId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n ResultType: 'entity_object'\n },\n currentUser\n );\n\n if (result.Success) {\n const details = result.Results || [];\n console.log(`[${timestamp}] 💾 DataCacheService - Loaded ${details.length} message(s) for conversation ${conversationId}`);\n\n // Add all to cache (avoid duplicates by checking ID)\n for (const detail of details) {\n const existingIndex = this.conversationDetails.findIndex(d => UUIDsEqual(d.ID, detail.ID));\n if (existingIndex >= 0) {\n // Replace existing (ensures we keep the same object reference)\n this.conversationDetails[existingIndex] = detail;\n } else {\n // Add new\n this.conversationDetails.push(detail);\n }\n }\n\n return details;\n }\n\n console.log(`[${timestamp}] 💾 DataCacheService - Failed to load messages for conversation ${conversationId}`);\n return [];\n }\n\n /**\n * Get all cached ConversationDetail entities for a conversation (no DB call)\n * @param conversationId The conversation ID\n * @returns Array of cached conversation details\n */\n getCachedConversationDetails(conversationId: string): MJConversationDetailEntity[] {\n return this.conversationDetails.filter(d => UUIDsEqual(d.ConversationID, conversationId));\n }\n\n /**\n * Remove a MJConversationDetailEntity from the cache\n * @param id The conversation detail ID to remove\n */\n removeConversationDetail(id: string): void {\n this.conversationDetails = this.conversationDetails.filter(d => !UUIDsEqual(d.ID, id));\n }\n\n // =============================================================================\n // Cache Management\n // =============================================================================\n\n /**\n * Refresh entity data by clearing cached entities of a specific type\n * This forces a reload from the database on next access\n * @param entityName The entity name to refresh (e.g., 'Conversations', 'MJ: Conversation Details')\n */\n async refreshEntity(entityName: string): Promise<void> {\n switch (entityName) {\n case 'Conversations':\n this.conversations = [];\n break;\n case 'MJ: Conversation Details':\n this.conversationDetails = [];\n break;\n default:\n console.warn('Unknown entity name for refresh:', entityName);\n }\n }\n\n /**\n * Refresh a specific cache by name\n * This method can be extended to handle different cache types\n * @param cacheName The cache name ('Core', 'AI', 'Actions')\n */\n async refreshCache(cacheName: 'Core' | 'AI' | 'Actions'): Promise<void> {\n switch (cacheName) {\n case 'Core':\n // Clear core entity caches\n this.clear();\n break;\n case 'AI':\n // AI-specific cache refresh would go here\n // For now, just log it\n console.log('AI cache refresh requested (not yet implemented)');\n break;\n case 'Actions':\n // Actions-specific cache refresh would go here\n console.log('Actions cache refresh requested (not yet implemented)');\n break;\n default:\n console.warn('Unknown cache name for refresh:', cacheName);\n }\n }\n\n /**\n * Clear all cached entities\n * Call when switching environments, users, or when needed\n */\n clear(): void {\n this.conversations = [];\n this.conversationDetails = [];\n }\n\n /**\n * Clear cached entities for a specific conversation\n * @param conversationId The conversation ID\n */\n clearConversation(conversationId: string): void {\n this.conversations = this.conversations.filter(c => !UUIDsEqual(c.ID, conversationId));\n this.conversationDetails = this.conversationDetails.filter(d => !UUIDsEqual(d.ConversationID, conversationId));\n }\n\n /**\n * Get cache statistics for debugging\n * @returns Object with cache sizes\n */\n getStats(): { conversations: number; conversationDetails: number } {\n return {\n conversations: this.conversations.length,\n conversationDetails: this.conversationDetails.length\n };\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-conversations",
3
- "version": "5.4.0",
3
+ "version": "5.5.0",
4
4
  "description": "MemberJunction: Conversation, Collection, and Artifact management components for any Angular application",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -31,21 +31,21 @@
31
31
  "dependencies": {
32
32
  "@angular/animations": "21.1.3",
33
33
  "@angular/cdk": "21.1.3",
34
- "@memberjunction/ai": "5.4.0",
35
- "@memberjunction/ai-core-plus": "5.4.0",
36
- "@memberjunction/ai-engine-base": "5.4.0",
37
- "@memberjunction/core": "5.4.0",
38
- "@memberjunction/core-entities": "5.4.0",
39
- "@memberjunction/global": "5.4.0",
40
- "@memberjunction/graphql-dataprovider": "5.4.0",
41
- "@memberjunction/ng-artifacts": "5.4.0",
42
- "@memberjunction/ng-base-types": "5.4.0",
43
- "@memberjunction/ng-code-editor": "5.4.0",
44
- "@memberjunction/ng-container-directives": "5.4.0",
45
- "@memberjunction/ng-notifications": "5.4.0",
46
- "@memberjunction/ng-shared-generic": "5.4.0",
47
- "@memberjunction/ng-tasks": "5.4.0",
48
- "@memberjunction/ng-testing": "5.4.0",
34
+ "@memberjunction/ai": "5.5.0",
35
+ "@memberjunction/ai-core-plus": "5.5.0",
36
+ "@memberjunction/ai-engine-base": "5.5.0",
37
+ "@memberjunction/core": "5.5.0",
38
+ "@memberjunction/core-entities": "5.5.0",
39
+ "@memberjunction/global": "5.5.0",
40
+ "@memberjunction/graphql-dataprovider": "5.5.0",
41
+ "@memberjunction/ng-artifacts": "5.5.0",
42
+ "@memberjunction/ng-base-types": "5.5.0",
43
+ "@memberjunction/ng-code-editor": "5.5.0",
44
+ "@memberjunction/ng-container-directives": "5.5.0",
45
+ "@memberjunction/ng-notifications": "5.5.0",
46
+ "@memberjunction/ng-shared-generic": "5.5.0",
47
+ "@memberjunction/ng-tasks": "5.5.0",
48
+ "@memberjunction/ng-testing": "5.5.0",
49
49
  "@progress/kendo-angular-buttons": "22.0.1",
50
50
  "@progress/kendo-angular-dateinputs": "22.0.1",
51
51
  "@progress/kendo-angular-dialog": "22.0.1",
@@ -55,7 +55,7 @@
55
55
  "@progress/kendo-angular-layout": "22.0.1",
56
56
  "@progress/kendo-angular-notification": "22.0.1",
57
57
  "@progress/kendo-angular-upload": "22.0.1",
58
- "@memberjunction/ng-markdown": "5.4.0",
58
+ "@memberjunction/ng-markdown": "5.5.0",
59
59
  "rxjs": "^7.8.2",
60
60
  "tslib": "^2.8.1"
61
61
  },