@memberjunction/ng-conversations 6.1.4 → 6.2.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/README.md +36 -3
- package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +19 -3
- package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts.map +1 -1
- package/dist/lib/components/active-tasks/active-tasks-panel.component.js +39 -7
- package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
- package/dist/lib/components/agent/active-agent-indicator.component.d.ts +74 -6
- package/dist/lib/components/agent/active-agent-indicator.component.d.ts.map +1 -1
- package/dist/lib/components/agent/active-agent-indicator.component.js +111 -21
- package/dist/lib/components/agent/active-agent-indicator.component.js.map +1 -1
- package/dist/lib/components/agent/agent-process-panel.component.d.ts +31 -5
- package/dist/lib/components/agent/agent-process-panel.component.d.ts.map +1 -1
- package/dist/lib/components/agent/agent-process-panel.component.js +71 -15
- package/dist/lib/components/agent/agent-process-panel.component.js.map +1 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +65 -9
- package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.js +169 -57
- package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
- package/dist/lib/components/attachment/image-viewer.component.d.ts +77 -11
- package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/attachment/image-viewer.component.js +181 -47
- package/dist/lib/components/attachment/image-viewer.component.js.map +1 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts +129 -19
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +350 -116
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts +60 -8
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.js +130 -46
- package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-artifact-card.component.d.ts +63 -3
- package/dist/lib/components/collection/collection-artifact-card.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-artifact-card.component.js +113 -19
- package/dist/lib/components/collection/collection-artifact-card.component.js.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts +54 -8
- package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.js +130 -46
- package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.d.ts +70 -10
- package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.js +175 -53
- package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts +89 -9
- package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.js +220 -70
- package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
- package/dist/lib/components/collection/collection-view.component.d.ts +89 -11
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +154 -40
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts +390 -38
- package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.js +951 -367
- package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.d.ts +213 -18
- package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.js +388 -44
- package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +12 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.js +26 -4
- package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +1090 -123
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +2407 -731
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +139 -19
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.js +296 -59
- package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.d.ts +579 -78
- package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.js +2322 -823
- package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
- package/dist/lib/components/conversation/pinned-messages-panel.component.d.ts +40 -4
- package/dist/lib/components/conversation/pinned-messages-panel.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/pinned-messages-panel.component.js +72 -14
- package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
- package/dist/lib/components/dialogs/input-dialog.component.d.ts +57 -11
- package/dist/lib/components/dialogs/input-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/dialogs/input-dialog.component.js +128 -16
- package/dist/lib/components/dialogs/input-dialog.component.js.map +1 -1
- package/dist/lib/components/dialogs/rating-dialog.component.d.ts +68 -10
- package/dist/lib/components/dialogs/rating-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/dialogs/rating-dialog.component.js +151 -27
- package/dist/lib/components/dialogs/rating-dialog.component.js.map +1 -1
- package/dist/lib/components/export/export-modal.component.d.ts +84 -10
- package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
- package/dist/lib/components/export/export-modal.component.js +173 -49
- package/dist/lib/components/export/export-modal.component.js.map +1 -1
- package/dist/lib/components/global-tasks/global-tasks-panel.component.d.ts +29 -3
- package/dist/lib/components/global-tasks/global-tasks-panel.component.d.ts.map +1 -1
- package/dist/lib/components/global-tasks/global-tasks-panel.component.js +58 -12
- package/dist/lib/components/global-tasks/global-tasks-panel.component.js.map +1 -1
- package/dist/lib/components/library/library-full-view.component.d.ts +57 -8
- package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/library/library-full-view.component.js +119 -35
- package/dist/lib/components/library/library-full-view.component.js.map +1 -1
- package/dist/lib/components/members/members-modal.component.d.ts +76 -10
- package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
- package/dist/lib/components/members/members-modal.component.js +164 -50
- package/dist/lib/components/members/members-modal.component.js.map +1 -1
- package/dist/lib/components/message/actionable-commands.component.d.ts +37 -5
- package/dist/lib/components/message/actionable-commands.component.d.ts.map +1 -1
- package/dist/lib/components/message/actionable-commands.component.js +82 -16
- package/dist/lib/components/message/actionable-commands.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts +46 -10
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +120 -36
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +549 -74
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +1250 -421
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +411 -29
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +896 -222
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +288 -29
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +561 -123
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/navigation/conversation-navigation.component.d.ts +64 -5
- package/dist/lib/components/navigation/conversation-navigation.component.d.ts.map +1 -1
- package/dist/lib/components/navigation/conversation-navigation.component.js +101 -11
- package/dist/lib/components/navigation/conversation-navigation.component.js.map +1 -1
- package/dist/lib/components/notification/activity-indicator.component.d.ts +6 -2
- package/dist/lib/components/notification/activity-indicator.component.d.ts.map +1 -1
- package/dist/lib/components/notification/activity-indicator.component.js +13 -3
- package/dist/lib/components/notification/activity-indicator.component.js.map +1 -1
- package/dist/lib/components/notification/notification-badge.component.d.ts +15 -3
- package/dist/lib/components/notification/notification-badge.component.d.ts.map +1 -1
- package/dist/lib/components/notification/notification-badge.component.js +36 -8
- package/dist/lib/components/notification/notification-badge.component.js.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.js +4 -4
- package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.d.ts +93 -11
- package/dist/lib/components/project/project-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.js +348 -87
- package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
- package/dist/lib/components/project/project-selector.component.d.ts +78 -8
- package/dist/lib/components/project/project-selector.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-selector.component.js +177 -46
- package/dist/lib/components/project/project-selector.component.js.map +1 -1
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts +1 -1
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js.map +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.js +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +3 -0
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
- package/dist/lib/components/realtime/media/media-channel.d.ts +2 -1
- package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/media/media-channel.js +1 -1
- package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.js +2 -2
- package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.d.ts +3 -1
- package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.js +26 -8
- package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.js +2 -2
- package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +4 -4
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.js +19 -19
- package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-state.d.ts +2 -3
- package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-state.js +3 -2
- package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-thread.component.d.ts +17 -1
- package/dist/lib/components/realtime/realtime-session-thread.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-thread.component.js +122 -45
- package/dist/lib/components/realtime/realtime-session-thread.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +47 -31
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +138 -124
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +4 -4
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js +4 -4
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js +3 -3
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.d.ts +13 -11
- package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.js +29 -25
- package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +4 -2
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +7 -3
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
- package/dist/lib/components/search/search-panel.component.d.ts +133 -22
- package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
- package/dist/lib/components/search/search-panel.component.js +312 -83
- package/dist/lib/components/search/search-panel.component.js.map +1 -1
- package/dist/lib/components/share/share-modal.component.d.ts +69 -9
- package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/share/share-modal.component.js +139 -31
- package/dist/lib/components/share/share-modal.component.js.map +1 -1
- package/dist/lib/components/shared/user-picker.component.d.ts +48 -8
- package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
- package/dist/lib/components/shared/user-picker.component.js +110 -30
- package/dist/lib/components/shared/user-picker.component.js.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +114 -11
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.js +199 -21
- package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
- package/dist/lib/components/sidebar/routines-section.component.d.ts +20 -1
- package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -1
- package/dist/lib/components/sidebar/routines-section.component.js +25 -5
- package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
- package/dist/lib/components/slots/slot-interfaces.d.ts +19 -0
- package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -1
- package/dist/lib/components/slots/slot-interfaces.js.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts +95 -13
- package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.js +223 -75
- package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
- package/dist/lib/components/tasks/task-widget.component.d.ts +46 -6
- package/dist/lib/components/tasks/task-widget.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/task-widget.component.js +100 -16
- package/dist/lib/components/tasks/task-widget.component.js.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +64 -7
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +127 -27
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.d.ts +66 -8
- package/dist/lib/components/thread/thread-panel.component.d.ts.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.js +146 -36
- package/dist/lib/components/thread/thread-panel.component.js.map +1 -1
- package/dist/lib/components/toast/toast.component.d.ts +11 -1
- package/dist/lib/components/toast/toast.component.d.ts.map +1 -1
- package/dist/lib/components/toast/toast.component.js +25 -5
- package/dist/lib/components/toast/toast.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +385 -42
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +887 -291
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +8 -0
- package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -1
- package/dist/lib/composer-plugins/base-conversation-mention.provider.js +8 -1
- package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -1
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/directives/chat-slot.directive.d.ts +5 -1
- package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -1
- package/dist/lib/directives/chat-slot.directive.js.map +1 -1
- package/dist/lib/directives/search-shortcut.directive.d.ts +9 -1
- package/dist/lib/directives/search-shortcut.directive.d.ts.map +1 -1
- package/dist/lib/directives/search-shortcut.directive.js +14 -4
- package/dist/lib/directives/search-shortcut.directive.js.map +1 -1
- package/dist/lib/events/chat-events.d.ts +34 -7
- package/dist/lib/events/chat-events.d.ts.map +1 -1
- package/dist/lib/events/chat-events.js +37 -7
- package/dist/lib/events/chat-events.js.map +1 -1
- package/dist/lib/models/agent-turn.model.d.ts +103 -0
- package/dist/lib/models/agent-turn.model.d.ts.map +1 -0
- package/dist/lib/models/agent-turn.model.js +12 -0
- package/dist/lib/models/agent-turn.model.js.map +1 -0
- package/dist/lib/models/collection-view.model.js.map +1 -1
- package/dist/lib/models/conversation-state.model.d.ts +8 -0
- package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
- package/dist/lib/models/conversation-state.model.js.map +1 -1
- package/dist/lib/models/lazy-artifact-info.d.ts +44 -12
- package/dist/lib/models/lazy-artifact-info.d.ts.map +1 -1
- package/dist/lib/models/lazy-artifact-info.js +98 -34
- package/dist/lib/models/lazy-artifact-info.js.map +1 -1
- package/dist/lib/services/active-tasks.service.d.ts +30 -4
- package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
- package/dist/lib/services/active-tasks.service.js +71 -19
- package/dist/lib/services/active-tasks.service.js.map +1 -1
- package/dist/lib/services/agent-state.service.d.ts +17 -1
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +48 -16
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/artifact-permission.service.d.ts +39 -0
- package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-permission.service.js +152 -17
- package/dist/lib/services/artifact-permission.service.js.map +1 -1
- package/dist/lib/services/artifact-state.service.d.ts +58 -5
- package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +135 -35
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/browser-realtime-media-host.d.ts +24 -0
- package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -0
- package/dist/lib/services/browser-realtime-media-host.js +95 -0
- package/dist/lib/services/browser-realtime-media-host.js.map +1 -0
- package/dist/lib/services/collection-permission.service.d.ts +28 -0
- package/dist/lib/services/collection-permission.service.d.ts.map +1 -1
- package/dist/lib/services/collection-permission.service.js +88 -32
- package/dist/lib/services/collection-permission.service.js.map +1 -1
- package/dist/lib/services/collection-state.service.d.ts +11 -1
- package/dist/lib/services/collection-state.service.d.ts.map +1 -1
- package/dist/lib/services/collection-state.service.js +25 -5
- package/dist/lib/services/collection-state.service.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +26 -4
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +57 -18
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts +41 -2
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js +80 -13
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/conversation-streaming.service.d.ts +22 -0
- package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-streaming.service.js +50 -10
- package/dist/lib/services/conversation-streaming.service.js.map +1 -1
- package/dist/lib/services/data-cache.service.d.ts +31 -0
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +71 -15
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/dialog.service.d.ts +13 -0
- package/dist/lib/services/dialog.service.d.ts.map +1 -1
- package/dist/lib/services/dialog.service.js +25 -5
- package/dist/lib/services/dialog.service.js.map +1 -1
- package/dist/lib/services/export.service.d.ts +2 -0
- package/dist/lib/services/export.service.d.ts.map +1 -1
- package/dist/lib/services/export.service.js +5 -1
- package/dist/lib/services/export.service.js.map +1 -1
- package/dist/lib/services/graphql-attachment-blob-store.d.ts +44 -0
- package/dist/lib/services/graphql-attachment-blob-store.d.ts.map +1 -0
- package/dist/lib/services/graphql-attachment-blob-store.js +113 -0
- package/dist/lib/services/graphql-attachment-blob-store.js.map +1 -0
- package/dist/lib/services/mention-autocomplete.service.d.ts +17 -141
- package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.js +15 -460
- package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
- package/dist/lib/services/mention-parser.service.d.ts +10 -0
- package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
- package/dist/lib/services/mention-parser.service.js +25 -5
- package/dist/lib/services/mention-parser.service.js.map +1 -1
- package/dist/lib/services/notification.service.d.ts +54 -6
- package/dist/lib/services/notification.service.d.ts.map +1 -1
- package/dist/lib/services/notification.service.js +123 -27
- package/dist/lib/services/notification.service.js.map +1 -1
- package/dist/lib/services/realtime-audio-recorder.d.ts +4 -4
- package/dist/lib/services/realtime-audio-recorder.js +12 -12
- package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
- package/dist/lib/services/realtime-pcm-wav.d.ts +4 -0
- package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -1
- package/dist/lib/services/realtime-pcm-wav.js +10 -2
- package/dist/lib/services/realtime-pcm-wav.js.map +1 -1
- package/dist/lib/services/realtime-session-review.service.d.ts +1 -1
- package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session-review.service.js +1 -1
- package/dist/lib/services/realtime-session-review.service.js.map +1 -1
- package/dist/lib/services/realtime-session.service.d.ts +16 -1150
- package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session.service.js +28 -2430
- package/dist/lib/services/realtime-session.service.js.map +1 -1
- package/dist/lib/services/search.service.d.ts +42 -9
- package/dist/lib/services/search.service.d.ts.map +1 -1
- package/dist/lib/services/search.service.js +103 -23
- package/dist/lib/services/search.service.js.map +1 -1
- package/dist/lib/services/toast.service.d.ts +19 -1
- package/dist/lib/services/toast.service.d.ts.map +1 -1
- package/dist/lib/services/toast.service.js +45 -9
- package/dist/lib/services/toast.service.js.map +1 -1
- package/dist/lib/services/ui-command-handler.service.d.ts +16 -2
- package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
- package/dist/lib/services/ui-command-handler.service.js +36 -8
- package/dist/lib/services/ui-command-handler.service.js.map +1 -1
- package/dist/lib/utils/agent-artifact-summary.d.ts +2 -2
- package/dist/lib/utils/agent-artifact-summary.js +3 -3
- package/dist/lib/utils/agent-artifact-summary.js.map +1 -1
- package/dist/lib/utils/agent-turn-routing.d.ts +69 -0
- package/dist/lib/utils/agent-turn-routing.d.ts.map +1 -0
- package/dist/lib/utils/agent-turn-routing.js +96 -0
- package/dist/lib/utils/agent-turn-routing.js.map +1 -0
- package/dist/lib/utils/artifact-panel-action.d.ts +15 -4
- package/dist/lib/utils/artifact-panel-action.d.ts.map +1 -1
- package/dist/lib/utils/artifact-panel-action.js +10 -2
- package/dist/lib/utils/artifact-panel-action.js.map +1 -1
- package/dist/lib/utils/distinct-artifacts.d.ts +2 -0
- package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
- package/dist/lib/utils/distinct-artifacts.js +5 -1
- package/dist/lib/utils/distinct-artifacts.js.map +1 -1
- package/dist/lib/utils/plan-mode-preference.d.ts +2 -2
- package/dist/lib/utils/plan-mode-preference.js +6 -6
- package/dist/lib/utils/plan-mode-preference.js.map +1 -1
- package/dist/lib/utils/realtime-session-timeline.d.ts +8 -79
- package/dist/lib/utils/realtime-session-timeline.d.ts.map +1 -1
- package/dist/lib/utils/realtime-session-timeline.js +8 -89
- package/dist/lib/utils/realtime-session-timeline.js.map +1 -1
- package/dist/public-api.d.ts +5 -2
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +9 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +33 -32
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +0 -384
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +0 -1
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +0 -231
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +0 -1
- package/dist/lib/services/delegation-result-parser.d.ts +0 -50
- package/dist/lib/services/delegation-result-parser.d.ts.map +0 -1
- package/dist/lib/services/delegation-result-parser.js +0 -60
- package/dist/lib/services/delegation-result-parser.js.map +0 -1
- package/dist/lib/services/narration-template.d.ts +0 -42
- package/dist/lib/services/narration-template.d.ts.map +0 -1
- package/dist/lib/services/narration-template.js +0 -73
- package/dist/lib/services/narration-template.js.map +0 -1
- package/dist/lib/services/skill-picker-narrowing.d.ts +0 -13
- package/dist/lib/services/skill-picker-narrowing.d.ts.map +0 -1
- package/dist/lib/services/skill-picker-narrowing.js +0 -13
- package/dist/lib/services/skill-picker-narrowing.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.service.js","sourceRoot":"","sources":["../../../src/lib/services/dialog.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJDialogService, MJDialogRef, MJDialogAction } from '@memberjunction/ng-ui-components';\nimport { Observable } from 'rxjs';\nimport { InputDialogComponent } from '../components/dialogs/input-dialog.component';\nimport { RatingDialogComponent } from '../components/dialogs/rating-dialog.component';\n\nexport interface DialogButton {\n text: string;\n primary?: boolean;\n action: () => void;\n}\n\nexport interface InputDialogOptions {\n title: string;\n message: string;\n inputLabel: string;\n inputValue?: string;\n inputType?: 'text' | 'textarea' | 'number' | 'email';\n placeholder?: string;\n required?: boolean;\n secondInputLabel?: string;\n secondInputValue?: string;\n secondInputPlaceholder?: string;\n secondInputRequired?: boolean;\n okText?: string;\n cancelText?: string;\n}\n\nexport interface ConfirmDialogOptions {\n title: string;\n message: string;\n okText?: string;\n cancelText?: string;\n dangerous?: boolean;\n}\n\nexport interface RatingDialogOptions {\n title?: string;\n message?: string;\n initialRating?: number | null;\n initialComments?: string;\n okText?: string;\n cancelText?: string;\n /** When true, the rating dialog shows a consent checkbox the user must\n * accept before submitting (first-time-only authorization). */\n requireConsent?: boolean;\n}\n\nexport interface RatingDialogResult {\n rating: number;\n comments: string;\n /** True only when the user *just* acknowledged consent in this dialog —\n * i.e. `requireConsent` was true and they checked the box. The caller\n * should persist the acknowledgement so consent isn't requested again. */\n consentNewlyAcknowledged: boolean;\n}\n\n/**\n * Dialog service for displaying MJ dialogs.\n * Replaces browser alert() and confirm() with proper UI components.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class DialogService {\n constructor(private mjDialogService: MJDialogService) {}\n\n /**\n * Show a confirmation dialog\n * @returns Promise<boolean> - true if user clicked OK, false if cancelled\n */\n confirm(options: ConfirmDialogOptions): Promise<boolean> {\n return new Promise((resolve) => {\n const dialogRef = this.mjDialogService.open({\n title: options.title,\n content: options.message,\n actions: [\n {\n text: options.okText || 'OK',\n primary: true,\n themeColor: options.dangerous ? 'error' : 'primary'\n },\n {\n text: options.cancelText || 'Cancel',\n primary: false\n }\n ],\n width: 450,\n minWidth: 250\n });\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action) {\n resolve(action.text === (options.okText || 'OK'));\n } else {\n resolve(false);\n }\n });\n });\n }\n\n /**\n * Show an alert dialog\n */\n alert(title: string, message: string, okText: string = 'OK'): Promise<void> {\n return new Promise((resolve) => {\n const dialogRef = this.mjDialogService.open({\n title: title,\n content: message,\n actions: [\n {\n text: okText,\n primary: true\n }\n ],\n width: 450,\n minWidth: 250\n });\n\n dialogRef.Result.subscribe(() => {\n resolve();\n });\n });\n }\n\n /**\n * Show an input dialog\n * @returns Promise<string | {value: string; secondValue?: string} | null> -\n * If single input: returns string\n * If dual input: returns object with both values\n * Returns null if cancelled\n */\n input(options: InputDialogOptions): Promise<string | {value: string; secondValue?: string} | null> {\n return new Promise((resolve) => {\n const dialogRef = this.mjDialogService.open({\n title: options.title,\n content: InputDialogComponent,\n actions: [\n {\n text: options.okText || 'OK',\n primary: true\n },\n {\n text: options.cancelText || 'Cancel',\n primary: false\n }\n ],\n width: 500,\n minWidth: 300\n });\n\n // Pass data to the component\n const componentInstance = dialogRef.Content!.instance as unknown as InputDialogComponent;\n componentInstance.message = options.message;\n componentInstance.inputLabel = options.inputLabel;\n componentInstance.inputType = options.inputType || 'text';\n componentInstance.placeholder = options.placeholder || '';\n componentInstance.required = options.required || false;\n componentInstance.value = options.inputValue || '';\n componentInstance.secondInputLabel = options.secondInputLabel || '';\n componentInstance.secondInputPlaceholder = options.secondInputPlaceholder || '';\n componentInstance.secondInputRequired = options.secondInputRequired || false;\n componentInstance.secondValue = options.secondInputValue || '';\n\n // Focus and select input after dialog opens\n setTimeout(() => {\n const inputElement = document.querySelector('.mj-dialog-body input, .mj-dialog-body textarea') as HTMLInputElement | HTMLTextAreaElement;\n if (inputElement) {\n inputElement.focus();\n inputElement.select();\n }\n }, 100);\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action && action.text === (options.okText || 'OK')) {\n const value = componentInstance.getValue();\n if (options.required && !value) {\n resolve(null);\n } else {\n // If second input is present, return object with both values\n if (options.secondInputLabel) {\n resolve({\n value: value,\n secondValue: componentInstance.getSecondValue()\n });\n } else {\n // Single input - return string for backward compatibility\n resolve(value);\n }\n }\n } else {\n resolve(null);\n }\n });\n });\n }\n\n /**\n * Show a rating dialog (1-10 + free-form comments).\n * @returns Promise<RatingDialogResult | null> — null if cancelled or no rating selected.\n */\n rating(options: RatingDialogOptions = {}): Promise<RatingDialogResult | null> {\n return new Promise((resolve) => {\n const okText = options.okText || 'Submit';\n const cancelText = options.cancelText || 'Cancel';\n\n const dialogRef = this.mjDialogService.open({\n title: options.title || 'Rate this response',\n content: RatingDialogComponent,\n actions: [\n { text: okText, primary: true },\n { text: cancelText, primary: false }\n ],\n width: 560,\n minWidth: 320\n });\n\n const componentInstance = dialogRef.Content!.instance as unknown as RatingDialogComponent;\n componentInstance.message = options.message ?? '';\n componentInstance.initialRating = options.initialRating ?? null;\n componentInstance.initialComments = options.initialComments ?? '';\n componentInstance.requireConsent = options.requireConsent ?? false;\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action && action.text === okText) {\n const rating = componentInstance.getRating();\n if (rating == null || !componentInstance.isConsentValid()) {\n resolve(null);\n } else {\n resolve({\n rating,\n comments: componentInstance.getComments(),\n consentNewlyAcknowledged: componentInstance.wasConsentNewlyAcknowledged()\n });\n }\n } else {\n resolve(null);\n }\n });\n });\n }\n\n /**\n * Show a custom dialog with custom content and actions\n */\n custom(title: string, content: string, buttons: DialogButton[], width: number = 500): MJDialogRef {\n const actions = buttons.map(btn => ({\n text: btn.text,\n primary: btn.primary || false\n }));\n\n const dialogRef = this.mjDialogService.open({\n title: title,\n content: content,\n actions: actions,\n width: width,\n minWidth: 300\n });\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action) {\n const button = buttons.find(b => b.text === action.text);\n if (button && button.action) {\n button.action();\n }\n }\n });\n\n return dialogRef;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dialog.service.js","sourceRoot":"","sources":["../../../src/lib/services/dialog.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJDialogService, MJDialogRef, MJDialogAction } from '@memberjunction/ng-ui-components';\nimport { Observable } from 'rxjs';\nimport { InputDialogComponent } from '../components/dialogs/input-dialog.component';\nimport { RatingDialogComponent } from '../components/dialogs/rating-dialog.component';\n\nexport interface DialogButton {\n text: string;\n primary?: boolean;\n action: () => void;\n}\n\nexport interface InputDialogOptions {\n title: string;\n message: string;\n inputLabel: string;\n inputValue?: string;\n inputType?: 'text' | 'textarea' | 'number' | 'email';\n placeholder?: string;\n required?: boolean;\n secondInputLabel?: string;\n secondInputValue?: string;\n secondInputPlaceholder?: string;\n secondInputRequired?: boolean;\n okText?: string;\n cancelText?: string;\n}\n\nexport interface ConfirmDialogOptions {\n title: string;\n message: string;\n okText?: string;\n cancelText?: string;\n dangerous?: boolean;\n}\n\nexport interface RatingDialogOptions {\n title?: string;\n message?: string;\n initialRating?: number | null;\n initialComments?: string;\n okText?: string;\n cancelText?: string;\n /** When true, the rating dialog shows a consent checkbox the user must\n * accept before submitting (first-time-only authorization). */\n requireConsent?: boolean;\n}\n\nexport interface RatingDialogResult {\n rating: number;\n comments: string;\n /** True only when the user *just* acknowledged consent in this dialog —\n * i.e. `requireConsent` was true and they checked the box. The caller\n * should persist the acknowledgement so consent isn't requested again. */\n consentNewlyAcknowledged: boolean;\n}\n\n/**\n * Dialog service for displaying MJ dialogs.\n * Replaces browser alert() and confirm() with proper UI components.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class DialogService {\n constructor(private mjDialogService: MJDialogService) {}\n\n /**\n * Show a confirmation dialog\n * @returns Promise<boolean> - true if user clicked OK, false if cancelled\n */\n Confirm(options: ConfirmDialogOptions): Promise<boolean> {\n return new Promise((resolve) => {\n const dialogRef = this.mjDialogService.open({\n title: options.title,\n content: options.message,\n actions: [\n {\n text: options.okText || 'OK',\n primary: true,\n themeColor: options.dangerous ? 'error' : 'primary'\n },\n {\n text: options.cancelText || 'Cancel',\n primary: false\n }\n ],\n width: 450,\n minWidth: 250\n });\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action) {\n resolve(action.text === (options.okText || 'OK'));\n } else {\n resolve(false);\n }\n });\n });\n }\n\n /** @deprecated Use {@link Confirm}. */\n confirm(options: ConfirmDialogOptions): Promise<boolean> {\n return this.Confirm(options);\n }\n\n /**\n * Show an alert dialog\n */\n Alert(title: string, message: string, okText: string = 'OK'): Promise<void> {\n return new Promise((resolve) => {\n const dialogRef = this.mjDialogService.open({\n title: title,\n content: message,\n actions: [\n {\n text: okText,\n primary: true\n }\n ],\n width: 450,\n minWidth: 250\n });\n\n dialogRef.Result.subscribe(() => {\n resolve();\n });\n });\n }\n\n /** @deprecated Use {@link Alert}. */\n alert(title: string, message: string, okText: string = 'OK'): Promise<void> {\n return this.Alert(title, message, okText);\n }\n\n /**\n * Show an input dialog\n * @returns Promise<string | {value: string; secondValue?: string} | null> -\n * If single input: returns string\n * If dual input: returns object with both values\n * Returns null if cancelled\n */\n Input(options: InputDialogOptions): Promise<string | {value: string; secondValue?: string} | null> {\n return new Promise((resolve) => {\n const dialogRef = this.mjDialogService.open({\n title: options.title,\n content: InputDialogComponent,\n actions: [\n {\n text: options.okText || 'OK',\n primary: true\n },\n {\n text: options.cancelText || 'Cancel',\n primary: false\n }\n ],\n width: 500,\n minWidth: 300\n });\n\n // Pass data to the component\n const componentInstance = dialogRef.Content!.instance as unknown as InputDialogComponent;\n componentInstance.message = options.message;\n componentInstance.inputLabel = options.inputLabel;\n componentInstance.inputType = options.inputType || 'text';\n componentInstance.placeholder = options.placeholder || '';\n componentInstance.required = options.required || false;\n componentInstance.value = options.inputValue || '';\n componentInstance.secondInputLabel = options.secondInputLabel || '';\n componentInstance.secondInputPlaceholder = options.secondInputPlaceholder || '';\n componentInstance.secondInputRequired = options.secondInputRequired || false;\n componentInstance.secondValue = options.secondInputValue || '';\n\n // Focus and select input after dialog opens\n setTimeout(() => {\n const inputElement = document.querySelector('.mj-dialog-body input, .mj-dialog-body textarea') as HTMLInputElement | HTMLTextAreaElement;\n if (inputElement) {\n inputElement.focus();\n inputElement.select();\n }\n }, 100);\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action && action.text === (options.okText || 'OK')) {\n const value = componentInstance.getValue();\n if (options.required && !value) {\n resolve(null);\n } else {\n // If second input is present, return object with both values\n if (options.secondInputLabel) {\n resolve({\n value: value,\n secondValue: componentInstance.getSecondValue()\n });\n } else {\n // Single input - return string for backward compatibility\n resolve(value);\n }\n }\n } else {\n resolve(null);\n }\n });\n });\n }\n\n /** @deprecated Use {@link Input}. */\n input(options: InputDialogOptions): Promise<string | {value: string; secondValue?: string} | null> {\n return this.Input(options);\n }\n\n /**\n * Show a rating dialog (1-10 + free-form comments).\n * @returns Promise<RatingDialogResult | null> — null if cancelled or no rating selected.\n */\n Rating(options: RatingDialogOptions = {}): Promise<RatingDialogResult | null> {\n return new Promise((resolve) => {\n const okText = options.okText || 'Submit';\n const cancelText = options.cancelText || 'Cancel';\n\n const dialogRef = this.mjDialogService.open({\n title: options.title || 'Rate this response',\n content: RatingDialogComponent,\n actions: [\n { text: okText, primary: true },\n { text: cancelText, primary: false }\n ],\n width: 560,\n minWidth: 320\n });\n\n const componentInstance = dialogRef.Content!.instance as unknown as RatingDialogComponent;\n componentInstance.message = options.message ?? '';\n componentInstance.initialRating = options.initialRating ?? null;\n componentInstance.initialComments = options.initialComments ?? '';\n componentInstance.requireConsent = options.requireConsent ?? false;\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action && action.text === okText) {\n const rating = componentInstance.getRating();\n if (rating == null || !componentInstance.isConsentValid()) {\n resolve(null);\n } else {\n resolve({\n rating,\n comments: componentInstance.getComments(),\n consentNewlyAcknowledged: componentInstance.wasConsentNewlyAcknowledged()\n });\n }\n } else {\n resolve(null);\n }\n });\n });\n }\n\n /** @deprecated Use {@link Rating}. */\n rating(options: RatingDialogOptions = {}): Promise<RatingDialogResult | null> {\n return this.Rating(options);\n }\n\n /**\n * Show a custom dialog with custom content and actions\n */\n Custom(title: string, content: string, buttons: DialogButton[], width: number = 500): MJDialogRef {\n const actions = buttons.map(btn => ({\n text: btn.text,\n primary: btn.primary || false\n }));\n\n const dialogRef = this.mjDialogService.open({\n title: title,\n content: content,\n actions: actions,\n width: width,\n minWidth: 300\n });\n\n dialogRef.Result.subscribe((result) => {\n const action = result as MJDialogAction | undefined;\n if (action && 'text' in action) {\n const button = buttons.find(b => b.text === action.text);\n if (button && button.action) {\n button.action();\n }\n }\n });\n\n return dialogRef;\n }\n\n /** @deprecated Use {@link Custom}. */\n custom(title: string, content: string, buttons: DialogButton[], width: number = 500): MJDialogRef {\n return this.Custom(title, content, buttons, width);\n }\n}\n"]}
|
|
@@ -95,6 +95,8 @@ export declare class ExportService {
|
|
|
95
95
|
*/
|
|
96
96
|
set Provider(value: IMetadataProvider | null);
|
|
97
97
|
get Provider(): IMetadataProvider;
|
|
98
|
+
ExportConversation(conversationId: string, format: ExportFormat, currentUser: UserInfo, options?: ExportOptions): Promise<void>;
|
|
99
|
+
/** @deprecated Use {@link ExportConversation}. */
|
|
98
100
|
exportConversation(conversationId: string, format: ExportFormat, currentUser: UserInfo, options?: ExportOptions): Promise<void>;
|
|
99
101
|
/**
|
|
100
102
|
* Build the export document for already-loaded conversation data — the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/export.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAW,QAAQ,EAAY,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAEtF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAWxD,CAAC;AAeF,qBAGa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAkC;IAEnD;;OAEG;IACH,IAAW,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAElD;IAED,IAAW,QAAQ,IAAI,iBAAiB,CAEvC;IAEK,kBAAkB,CACtB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,QAAQ,EACrB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAMhB;;;;;OAKG;IACU,kBAAkB,CAC7B,IAAI,EAAE;QAAE,YAAY,EAAE,oBAAoB,CAAC;QAAC,OAAO,EAAE,0BAA0B,EAAE,CAAA;KAAE,EACnF,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IA8BnE;;;;;;;;;;OAUG;IACI,mBAAmB,CACxB,MAAM,GAAE,SAAS,MAAM,EAAgC,EACvD,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAwCzB,8FAA8F;YAChF,YAAY;IAiB1B,6FAA6F;IAC7F,OAAO,CAAC,kBAAkB;IAQ1B,4FAA4F;IAC5F,OAAO,CAAC,YAAY;IAOpB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAIvC;IAEH;;;;;;;;;OASG;IACH,OAAO,CAAC,cAAc;IAgBtB,mFAAmF;IACnF,OAAO,CAAC,oBAAoB;IAS5B;;kCAE8B;YAChB,UAAU;YAsBV,oBAAoB;IA+BlC,OAAO,CAAC,YAAY;IAqDpB,OAAO,CAAC,gBAAgB;IAiDxB,OAAO,CAAC,YAAY;IA6EpB,OAAO,CAAC,YAAY;IA0CpB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,UAAU;IAMlB,kFAAkF;IAClF,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"export.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/export.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,11 +29,15 @@ export class ExportService {
|
|
|
29
29
|
get Provider() {
|
|
30
30
|
return this._provider ?? Metadata.Provider;
|
|
31
31
|
}
|
|
32
|
-
async
|
|
32
|
+
async ExportConversation(conversationId, format, currentUser, options = {}) {
|
|
33
33
|
const conversation = await this.loadConversationData(conversationId, currentUser);
|
|
34
34
|
const { content, filename, mimeType } = await this.BuildExportContent(conversation, format, options);
|
|
35
35
|
this.downloadFile(content, filename, mimeType);
|
|
36
36
|
}
|
|
37
|
+
/** @deprecated Use {@link ExportConversation}. */
|
|
38
|
+
async exportConversation(conversationId, format, currentUser, options = {}) {
|
|
39
|
+
return this.ExportConversation(conversationId, format, currentUser, options);
|
|
40
|
+
}
|
|
37
41
|
/**
|
|
38
42
|
* Build the export document for already-loaded conversation data — the
|
|
39
43
|
* download-free seam of {@link exportConversation}. Async because HTML-format
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.service.js","sourceRoot":"","sources":["../../../src/lib/services/export.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,OAAO,EAAY,QAAQ,EAAqB,MAAM,sBAAsB,CAAC;;AAsFtF;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAsB;IAC5D,cAAc;IACd,mBAAmB;IACnB,qBAAqB;IACrB,oBAAoB;IACpB,qBAAqB;IACrB,oBAAoB;IACpB,0BAA0B;IAC1B,sBAAsB;IACtB,kBAAkB;IAClB,gBAAgB;CACjB,CAAC;AAkBF,MAAM,OAAO,aAAa;IAChB,SAAS,GAA6B,IAAI,CAAC;IAEnD;;OAEG;IACH,IAAW,QAAQ,CAAC,KAA+B;QAC/C,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IAC3B,CAAC;IAED,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,cAAsB,EACtB,MAAoB,EACpB,WAAqB,EACrB,UAAyB,EAAE;QAE3B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAClF,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACrG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,kBAAkB,CAC7B,IAAmF,EACnF,MAAoB,EACpB,UAAyB,EAAE;QAE3B,MAAM,aAAa,GAA0B;YAC3C,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,IAAI;YAChD,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,IAAI;YAChD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;YACxC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;YACtC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK;YAC3C,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO;YACvC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC;QACF,MAAM,QAAQ,GAAG,gBAAgB,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QAEjF,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,MAAM;gBACT,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,QAAQ,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC;YACzH,KAAK,UAAU;gBACb,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,QAAQ,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;YACxH,KAAK,MAAM;gBACT,OAAO;oBACL,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;oBACvF,QAAQ,EAAE,GAAG,QAAQ,OAAO;oBAC5B,QAAQ,EAAE,WAAW;iBACtB,CAAC;YACJ,KAAK,MAAM;gBACT,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,QAAQ,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;YAClH;gBACE,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACI,mBAAmB,CACxB,SAA4B,2BAA2B,EACvD,IAAuB;QAEvB,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,8EAA8E;QAC9E,4EAA4E;QAC5E,+EAA+E;QAC/E,6EAA6E;QAC7E,MAAM,QAAQ,GAAG,IAAI,KAAK,MAAM,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;QAErD,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,GAAG,GAA2B,EAAE,CAAC;YACvC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnD,IAAI,KAAK,EAAE,CAAC;oBACV,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,4EAA4E;YAC5E,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;oBACtB,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,8FAA8F;IACtF,KAAK,CAAC,YAAY,CAAC,OAA8B;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClD,OAAO;YACL,SAAS;YACT,iFAAiF;YACjF,yEAAyE;YACzE,uEAAuE;YACvE,2DAA2D;YAC3D,WAAW,EAAE,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;YAClF,kFAAkF;YAClF,qFAAqF;YACrF,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI;SAC/C,CAAC;IACJ,CAAC;IAED,6FAA6F;IACrF,kBAAkB,CAAC,OAA8B;QACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC/C,IAAI,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,2BAA2B,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChH,CAAC;IAED,4FAA4F;IACpF,YAAY,CAClB,IAAmF,EACnF,OAA8B;QAE9B,OAAO,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,cAAc,CAAC;IACrF,CAAC;IAED;;;;;OAKG;IACK,kBAAkB,CAAC,OAA8B;QACvD,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC3B,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAA2B,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QAClC,IAAI,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QAC/B,IAAI,SAAS;YAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3C,IAAI,OAAO;YAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,CAAC;IAED;;;;;;;;OAQG;IACK,MAAM,CAAU,kBAAkB,GAAG,IAAI,GAAG,CAAC;QACnD,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO;QACpC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO;QACnE,OAAO,EAAE,WAAW;KACrB,CAAC,CAAC;IAEH;;;;;;;;;OASG;IACK,cAAc,CAAC,MAA8B;QACnD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3E,SAAS;YACX,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;mBACX,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,mFAAmF;IAC3E,oBAAoB,CAAC,KAAa;QACxC,sEAAsE;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,4BAA4B,CAAC,IAAI,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACtB,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACnD,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;kCAE8B;IACtB,KAAK,CAAC,UAAU,CAAC,GAAW;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,GAAG,CAAC;YACb,CAAC;YACD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC/D,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBACnC,OAAO,GAAG,CAAC;YACb,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACnD,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAChC,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBACxD,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5C,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAChC,cAAsB,EACtB,WAAqB;QAErB,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEvD,4CAA4C;QAC5C,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAAC,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC;YAC5D;gBACE,UAAU,EAAE,mBAAmB;gBAC/B,WAAW,EAAE,OAAO,cAAc,GAAG;gBACrC,UAAU,EAAE,eAAe;aAC5B;YACD;gBACE,UAAU,EAAE,0BAA0B;gBACtC,WAAW,EAAE,mBAAmB,cAAc,GAAG;gBACjD,OAAO,EAAE,cAAc;gBACvB,UAAU,EAAE,eAAe;aAC5B;SACF,EAAE,WAAW,CAAC,CAAC;QAEhB,IAAI,CAAC,kBAAkB,CAAC,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO;YACL,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAyB;YACnE,OAAO,EAAE,CAAC,aAAa,CAAC,OAAO,IAAI,EAAE,CAAiC;SACvE,CAAC;IACJ,CAAC;IAEO,YAAY,CAClB,IAGC,EACD,OAA8B;QAE9B,MAAM,UAAU,GAA4B,EAAE,CAAC;QAE/C,4BAA4B;QAC5B,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,UAAU,CAAC,YAAY,GAAG;gBACxB,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE;gBACxB,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;gBAC5B,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,WAAW;gBAC1C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc;gBAC3C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc;aAC5C,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,YAAY,GAAG;gBACxB,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;aAC7B,CAAC;QACJ,CAAC;QAED,8EAA8E;QAC9E,kEAAkE;QAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,QAAQ,EAAE,CAAC;YACb,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACjC,CAAC;QAED,4BAA4B;QAC5B,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBACvD,MAAM,OAAO,GAA4B;oBACvC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;iBACxB,CAAC;gBAEF,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;oBAC5B,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;oBAC7B,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC;gBAC5C,CAAC;gBAED,OAAO,OAAO,CAAC;YACjB,CAAC,CAAC,CAAC;QACL,CAAC;QAED,0BAA0B;QAC1B,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IAEO,gBAAgB,CACtB,IAGC,EACD,OAA8B;QAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClD,+EAA+E;QAC/E,8EAA8E;QAC9E,sDAAsD;QACtD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;QACxE,IAAI,EAAE,GAAG,EAAE,CAAC;QACZ,IAAI,OAAO,EAAE,CAAC;YACZ,EAAE,IAAI,KAAK,KAAK,KAAK,OAAO,OAAO,CAAC;QACtC,CAAC;QACD,EAAE,IAAI,KAAK,KAAK,MAAM,CAAC;QAEvB,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;YAClC,EAAE,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,MAAM,CAAC;QAC/C,CAAC;QAED,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,EAAE,IAAI,gBAAgB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC;QAChF,CAAC;QAED,EAAE,IAAI,SAAS,CAAC;QAEhB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,EAAE,IAAI,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,SAAS,CAAC,MAAM,CAAC;gBAChE,EAAE,IAAI,GAAG,MAAM,CAAC,OAAO,MAAM,CAAC;gBAE9B,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;oBAC5B,EAAE,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC;gBAC1D,CAAC;gBAED,EAAE,IAAI,SAAS,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACtD,IAAI,SAAS,EAAE,CAAC;YACd,EAAE,IAAI,IAAI,SAAS,KAAK,CAAC;QAC3B,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,YAAY,CAClB,IAGC,EACD,OAA8B,EAC9B,KAA0B;QAE1B,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACtD,6EAA6E;QAC7E,6EAA6E;QAC7E,gDAAgD;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;;;;;;;;;;6FAUqD,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;2EACtC,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;gMACiG,CAAC,CAAC,CAAC,EAAE;YACzL,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAE/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,cAAc,CAAC,CAAC;QACxE,IAAI,IAAI,GAAG;;;;;WAKJ,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,MAAM;;;IAG9C,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,gCAAgC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;GACvF,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;QAEzC,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,IAAI;;MAER,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;kBACnF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC;SAC1D,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,SAAS,CAAC;gBAC1D,IAAI,IAAI;wBACQ,SAAS;wBACT,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,SAAS,CAAC;2BAC1C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,QAAQ,CAAC;gBAEjE,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;oBAC5B,IAAI,IAAI;6BACW,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC;gBACpE,CAAC;gBAED,IAAI,IAAI;SACP,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,UAAU,IAAI,SAAS,EAAE,CAAC;YACpC,IAAI,IAAI;oCACsB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC;QACtE,CAAC;QAED,IAAI,IAAI;;QAEJ,CAAC;QAEL,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,YAAY,CAClB,IAGC,EACD,OAA8B;QAE9B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,cAAc,CAAC;QAChE,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC;QACvB,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QAEzC,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;YAClC,IAAI,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,MAAM,CAAC;QACjD,CAAC;QAED,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,IAAI,YAAY,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC;QAC9E,CAAC;QAED,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;QAEhC,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAI,IAAI,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,SAAS,CAAC,KAAK,CAAC;gBAC/D,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC;gBAE9B,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;oBAC5B,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC;gBAC1D,CAAC;gBAED,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;YACzC,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACtD,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,IAAI,GAAG,SAAS,IAAI,CAAC;QAC3B,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,YAAY,CAAC,OAAe,EAAE,QAAgB,EAAE,QAAgB;QACtE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAEO,UAAU,CAAC,IAAmB;QACpC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE;YAC/B,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,MAAM;YACb,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IAEO,cAAc,CAAC,IAAY;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACpE,CAAC;IAEO,UAAU,CAAC,IAAY;QAC7B,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC;QACvB,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,kFAAkF;IAC1E,UAAU,CAAC,IAAY;QAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvD,CAAC;IAEO,YAAY;QAClB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;uGAhiBU,aAAa;gEAAb,aAAa,WAAb,aAAa,mBAFZ,MAAM;;iFAEP,aAAa;cAHzB,UAAU;eAAC;gBACV,UAAU,EAAE,MAAM;aACnB","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJConversationEntity, MJConversationDetailEntity } from '@memberjunction/core-entities';\nimport { RunView, UserInfo, Metadata, IMetadataProvider } from '@memberjunction/core';\n\nexport type ExportFormat = 'json' | 'markdown' | 'html' | 'text';\n\n/**\n * Branding applied to exported files, across EVERY format. HTML gets the full\n * treatment (theme colors, an inlined logo, the title, and a trademark footer);\n * JSON/markdown/text carry the title and trademark (markdown also references the\n * logo). Hosts supply this via `mj-conversation-chat-area`'s `exportBranding`\n * input. Color theming (`brandTokens`) is HTML-only — it has no meaning in the\n * data/plain-text formats.\n */\nexport interface ExportBranding {\n /**\n * CSS custom-property snapshot emitted as a `:root{}` block in the exported\n * document, so the export's stylesheet (which reads `var(--mj-…, fallback)`)\n * renders in the app's theme. HTML export only. Keys must be valid\n * custom-property names (`--like-this`). Entries are DROPPED when the key is\n * invalid or the value carries declaration-escape / network-call characters\n * (`<>{};@\\`, `url(`, `expression(`) — plain colors, `var()`, and\n * `color-mix()` pass. When omitted and `ExportOptions.includeTheme` is true,\n * the current theme is auto-snapshotted from `document.documentElement` (see\n * {@link DEFAULT_EXPORT_THEME_TOKENS}).\n */\n brandTokens?: Record<string, string>;\n /**\n * Logo URL. In HTML it is fetched and inlined as a data URI (so the file stays\n * self-contained) and rendered above the title — requires\n * `ExportOptions.includeCSS`, since it needs its stylesheet rule. In markdown it is\n * referenced by URL. JSON carries it as a string; plain text omits it.\n *\n * If the fetch fails, or the response isn't `content-type: image/*`, the raw URL is\n * emitted instead — so the exported file will reach out to that URL when opened.\n * There is no size or timeout guard on the fetch: a very large logo inflates the\n * export.\n */\n logoUrl?: string;\n /** Overrides the exported document's title (defaults to the conversation name). */\n title?: string;\n /**\n * A short trademark / attribution line (e.g. `© 2026 Acme Association ·\n * Powered by Betty`) rendered at the FOOT of the exported document: a styled HTML\n * footer, a markdown/text trailer, and a field in the JSON `branding` block.\n *\n * In HTML it needs its stylesheet rule, so — like the logo — it is emitted only when\n * `ExportOptions.includeCSS` is true. The markdown/text/JSON trailers have no such\n * dependency and always emit.\n *\n * NOT escaped for markdown: a value containing `_`, `]`, `)`, or a newline can break\n * the surrounding markdown. Supply plain text (HTML and JSON are escaped).\n */\n trademark?: string;\n}\n\nexport interface ExportOptions {\n includeMessages?: boolean;\n includeMetadata?: boolean;\n prettyPrint?: boolean;\n includeCSS?: boolean;\n /**\n * Emit the current app theme into the HTML export. When true and\n * `branding.brandTokens` is absent, the {@link DEFAULT_EXPORT_THEME_TOKENS}\n * are auto-snapshotted from the live document at export time. Default false —\n * an unthemed export renders exactly as before (the stylesheet's `var()`\n * fallbacks carry the legacy palette).\n *\n * Gates only the TOKEN auto-snapshot: a supplied `branding`'s `logoUrl`,\n * `title`, and `trademark` apply whenever `branding` is present — in HTML AND\n * in the JSON/markdown/text formats. (The export modal passes `branding`\n * through only while its \"Include branding\" checkbox is on, so in the UI flow\n * everything travels together.)\n */\n includeTheme?: boolean;\n /**\n * Which theme mode the snapshot captures — NOT whichever mode the app happens to be\n * in when the user clicks Export. Defaults to `'light'`: an export taken during a\n * dark session would otherwise bake dark text onto the page's white background and\n * come out unreadable. `'dark'` pairs the dark palette with the dark\n * `--mj-bg-page` the body rule applies, so the file is coherent either way.\n * HTML only — the data formats carry no colors.\n */\n themeMode?: 'light' | 'dark';\n /** Branding (tokens / logo / title) applied to the export — see {@link ExportBranding}. */\n branding?: ExportBranding;\n}\n\n/**\n * Tokens captured by the theme auto-snapshot — exactly the custom properties the\n * HTML export's stylesheet consumes. Hosts wanting more control supply their own\n * map via {@link ExportBranding.brandTokens} instead.\n */\nexport const DEFAULT_EXPORT_THEME_TOKENS: readonly string[] = [\n '--mj-bg-page',\n '--mj-text-primary',\n '--mj-text-secondary',\n '--mj-text-disabled',\n '--mj-border-default',\n '--mj-brand-primary',\n '--mj-brand-accent-subtle',\n '--mj-bg-surface-card',\n '--mj-font-family',\n '--mj-radius-md',\n];\n\n/** Internal: options with defaults applied (branding stays optional). */\ntype ResolvedExportOptions = Required<Omit<ExportOptions, 'branding'>> & Pick<ExportOptions, 'branding'>;\n\n/** Internal: the theme pieces resolved once per HTML export. */\ninterface ResolvedExportTheme {\n /** `<style>:root{…}</style>` block (empty string when no tokens resolved). */\n rootBlock: string;\n /** Inlined logo (data URI, or the raw URL on fetch failure); null = no logo. */\n logoDataUri: string | null;\n /** Document-title override; null = use the conversation name. */\n title: string | null;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ExportService {\n private _provider: IMetadataProvider | null = null;\n\n /**\n * Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.\n */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n async exportConversation(\n conversationId: string,\n format: ExportFormat,\n currentUser: UserInfo,\n options: ExportOptions = {}\n ): Promise<void> {\n const conversation = await this.loadConversationData(conversationId, currentUser);\n const { content, filename, mimeType } = await this.BuildExportContent(conversation, format, options);\n this.downloadFile(content, filename, mimeType);\n }\n\n /**\n * Build the export document for already-loaded conversation data — the\n * download-free seam of {@link exportConversation}. Async because HTML-format\n * branding may inline a logo. Exposed publicly so hosts (and tests) can build\n * export content without triggering a browser download.\n */\n public async BuildExportContent(\n data: { conversation: MJConversationEntity; details: MJConversationDetailEntity[] },\n format: ExportFormat,\n options: ExportOptions = {}\n ): Promise<{ content: string; filename: string; mimeType: string }> {\n const exportOptions: ResolvedExportOptions = {\n includeMessages: options.includeMessages ?? true,\n includeMetadata: options.includeMetadata ?? true,\n prettyPrint: options.prettyPrint ?? true,\n includeCSS: options.includeCSS ?? true,\n includeTheme: options.includeTheme ?? false,\n themeMode: options.themeMode ?? 'light',\n branding: options.branding\n };\n const baseName = `conversation-${data.conversation.Name}-${this.getTimestamp()}`;\n\n switch (format) {\n case 'json':\n return { content: this.exportAsJSON(data, exportOptions), filename: `${baseName}.json`, mimeType: 'application/json' };\n case 'markdown':\n return { content: this.exportAsMarkdown(data, exportOptions), filename: `${baseName}.md`, mimeType: 'text/markdown' };\n case 'html':\n return {\n content: this.exportAsHTML(data, exportOptions, await this.resolveTheme(exportOptions)),\n filename: `${baseName}.html`,\n mimeType: 'text/html'\n };\n case 'text':\n return { content: this.exportAsText(data, exportOptions), filename: `${baseName}.txt`, mimeType: 'text/plain' };\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n /**\n * Snapshot the given theme tokens from the live document. Empty/unset tokens are\n * skipped.\n *\n * `mode` captures a SPECIFIC palette rather than whatever the app is rendering right\n * now. Without it, exporting from a dark session bakes dark text onto the export's\n * white page and the file is unreadable. When the requested mode isn't the active one,\n * `data-theme` is flipped on `documentElement`, read, and restored — all synchronous\n * within one task, so the browser never paints the intermediate state. Omit `mode`\n * to read the live values as-is.\n */\n public SnapshotBrandTokens(\n tokens: readonly string[] = DEFAULT_EXPORT_THEME_TOKENS,\n mode?: 'light' | 'dark'\n ): Record<string, string> {\n const root = document.documentElement;\n const previous = root.getAttribute('data-theme');\n // The app's two real states are `data-theme=\"dark\"` and NO attribute at all —\n // `MJExplorerAppComponent` removes it for light rather than writing \"light\"\n // (explorer-app.component.ts). Reproduce those exactly rather than inventing a\n // third state, so the transient DOM is one the stylesheet has actually seen.\n const wantDark = mode === 'dark';\n const isDark = previous === 'dark';\n const mustSwap = mode != null && wantDark !== isDark;\n\n if (mustSwap) {\n if (wantDark) {\n root.setAttribute('data-theme', 'dark');\n } else {\n root.removeAttribute('data-theme');\n }\n }\n try {\n const style = getComputedStyle(root);\n const out: Record<string, string> = {};\n for (const token of tokens) {\n const value = style.getPropertyValue(token).trim();\n if (value) {\n out[token] = value;\n }\n }\n return out;\n } finally {\n // Restore even if reading throws — never strand the app in the other theme.\n if (mustSwap) {\n if (previous === null) {\n root.removeAttribute('data-theme');\n } else {\n root.setAttribute('data-theme', previous);\n }\n }\n }\n }\n\n /** Resolve the HTML export's theme pieces once: tokens (explicit > snapshot), logo, title. */\n private async resolveTheme(options: ResolvedExportOptions): Promise<ResolvedExportTheme> {\n const tokens = this.resolveBrandTokens(options);\n const rootBlock = tokens ? this.buildRootBlock(tokens) : '';\n const logoUrl = options.branding?.logoUrl?.trim();\n return {\n rootBlock,\n // The logo needs its `.brand-logo` rule (as the trademark footer needs its own),\n // so both are gated on includeCSS — a CSS-less export must never carry a\n // full-size unstyled logo. The modal enforces this too, but the public\n // BuildExportContent seam has to hold the line on its own.\n logoDataUri: options.includeCSS && logoUrl ? await this.inlineLogo(logoUrl) : null,\n // The title is deliberately NOT includeCSS-gated: it lands in <title>/<h1>, needs\n // no stylesheet, and is the one branding field every format carries unconditionally.\n title: options.branding?.title?.trim() || null\n };\n }\n\n /** Explicit host tokens win; `includeTheme` falls back to a live snapshot; else no theme. */\n private resolveBrandTokens(options: ResolvedExportOptions): Record<string, string> | null {\n const explicit = options.branding?.brandTokens;\n if (explicit && Object.keys(explicit).length > 0) {\n return explicit;\n }\n return options.includeTheme ? this.SnapshotBrandTokens(DEFAULT_EXPORT_THEME_TOKENS, options.themeMode) : null;\n }\n\n /** Document title used by every format: branding override → conversation name → generic. */\n private resolveTitle(\n data: { conversation: MJConversationEntity; details: MJConversationDetailEntity[] },\n options: ResolvedExportOptions\n ): string {\n return options.branding?.title?.trim() || data.conversation.Name || 'Conversation';\n }\n\n /**\n * The JSON `branding` block — the data-format analogue of the HTML header +\n * trademark footer. Carries the title, trademark, and logo URL the host set;\n * null when no branding (or none of those fields) is present. Theme color\n * tokens are HTML-only and never included here.\n */\n private buildBrandingBlock(options: ResolvedExportOptions): Record<string, string> | null {\n const b = options.branding;\n if (!b) {\n return null;\n }\n const block: Record<string, string> = {};\n const title = b.title?.trim();\n const trademark = b.trademark?.trim();\n const logoUrl = b.logoUrl?.trim();\n if (title) block.title = title;\n if (trademark) block.trademark = trademark;\n if (logoUrl) block.logoUrl = logoUrl;\n return Object.keys(block).length > 0 ? block : null;\n }\n\n /**\n * CSS functions permitted inside an exported token value. This is an ALLOWLIST\n * (not a blocklist) so no network-capable function can slip through: blocking\n * only `url(`/`expression(` let `image-set()`, `-webkit-image-set()`,\n * `cross-fade()`, `image()`, and `src()` fetch a beacon URL without ever\n * writing the literal `url(`. Anything not on this list drops the whole entry.\n * The set is the safe value/color-math functions the export could legitimately\n * carry; extend it only with functions that CANNOT load an external resource.\n */\n private static readonly SAFE_CSS_FUNCTIONS = new Set([\n 'var', 'calc', 'min', 'max', 'clamp',\n 'rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'lab', 'lch', 'oklab', 'oklch',\n 'color', 'color-mix',\n ]);\n\n /**\n * Emit the sanitized `:root{}` style block. Keys must be custom-property names.\n * A value is REJECTED (the entry is dropped, not stripped) when it carries any\n * declaration/tag-escape or network-reach vector: `<>{}` (tag/rule breakout),\n * `;` (declaration breakout — e.g. `; background: url(beacon)`), `\\` (CSS\n * escapes), `@` (at-rules), OR any CSS function not in\n * {@link SAFE_CSS_FUNCTIONS} (which excludes every resource-loading function —\n * url/image-set/cross-fade/image/src/expression/…). Plain colors, `var()`, and\n * `color-mix()` pass untouched.\n */\n private buildRootBlock(tokens: Record<string, string>): string {\n const rules: string[] = [];\n for (const [key, rawValue] of Object.entries(tokens)) {\n if (!/^--[A-Za-z0-9_-]+$/.test(key)) {\n continue;\n }\n const value = String(rawValue).trim();\n if (!value || /[<>{};@\\\\]/.test(value) || this.hasUnsafeCssFunction(value)) {\n continue;\n }\n rules.push(`${key}: ${value};`);\n }\n return rules.length > 0 ? `\n <style>:root { ${rules.join(' ')} }</style>` : '';\n }\n\n /** True if the value calls any CSS function outside {@link SAFE_CSS_FUNCTIONS}. */\n private hasUnsafeCssFunction(value: string): boolean {\n // Every `name(` occurrence — the identifier immediately before a '('.\n const calls = value.match(/([a-zA-Z][a-zA-Z-]*)\\s*\\(/g) ?? [];\n return calls.some((c) => {\n const name = c.replace(/\\s*\\($/, '').toLowerCase();\n return !ExportService.SAFE_CSS_FUNCTIONS.has(name);\n });\n }\n\n /** Fetch → data URI so the export stays self-contained; raw URL on any failure\n * (or when the response isn't actually an image — don't inline HTML/other as\n * a bogus `data:` image). */\n private async inlineLogo(url: string): Promise<string> {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n return url;\n }\n const contentType = response.headers.get('content-type') ?? '';\n if (!/^image\\//i.test(contentType)) {\n return url;\n }\n const blob = await response.blob();\n return await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(String(reader.result));\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(blob);\n });\n } catch {\n return url;\n }\n }\n\n private async loadConversationData(\n conversationId: string,\n currentUser: UserInfo\n ): Promise<{ conversation: MJConversationEntity; details: MJConversationDetailEntity[] }> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load conversation and details in parallel\n const [conversationResult, detailsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Conversations',\n ExtraFilter: `ID='${conversationId}'`,\n ResultType: 'entity_object'\n },\n {\n EntityName: 'MJ: Conversation Details',\n ExtraFilter: `ConversationID='${conversationId}'`,\n OrderBy: 'Sequence ASC',\n ResultType: 'entity_object'\n }\n ], currentUser);\n\n if (!conversationResult.Success || !conversationResult.Results?.length) {\n throw new Error('Conversation not found');\n }\n\n return {\n conversation: conversationResult.Results[0] as MJConversationEntity,\n details: (detailsResult.Results || []) as MJConversationDetailEntity[]\n };\n }\n\n private exportAsJSON(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions\n ): string {\n const exportData: Record<string, unknown> = {};\n\n // Add metadata if requested\n if (options.includeMetadata) {\n exportData.conversation = {\n id: data.conversation.ID,\n name: data.conversation.Name,\n description: data.conversation.Description,\n createdAt: data.conversation.__mj_CreatedAt,\n updatedAt: data.conversation.__mj_UpdatedAt\n };\n } else {\n exportData.conversation = {\n name: data.conversation.Name\n };\n }\n\n // Branding block (title / trademark / logo) when the host supplied branding —\n // the data-format analogue of the HTML header + trademark footer.\n const branding = this.buildBrandingBlock(options);\n if (branding) {\n exportData.branding = branding;\n }\n\n // Add messages if requested\n if (options.includeMessages) {\n exportData.messages = data.details.map((detail, index) => {\n const message: Record<string, unknown> = {\n role: detail.Role,\n message: detail.Message\n };\n\n if (options.includeMetadata) {\n message.id = detail.ID;\n message.sequence = index + 1;\n message.timestamp = detail.__mj_CreatedAt;\n }\n\n return message;\n });\n }\n\n // Use pretty print option\n return JSON.stringify(exportData, null, options.prettyPrint ? 2 : 0);\n }\n\n private exportAsMarkdown(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions\n ): string {\n const logoUrl = options.branding?.logoUrl?.trim();\n // Unbranded markdown must stay byte-identical to before (`# <Name>`), so DON'T\n // route through resolveTitle's 'Conversation' fallback here — only a supplied\n // branding title overrides the raw conversation name.\n const title = options.branding?.title?.trim() || data.conversation.Name;\n let md = '';\n if (logoUrl) {\n md += `\\n\\n`;\n }\n md += `# ${title}\\n\\n`;\n\n if (data.conversation.Description) {\n md += `${data.conversation.Description}\\n\\n`;\n }\n\n if (options.includeMetadata) {\n md += `**Created:** ${this.formatDate(data.conversation.__mj_CreatedAt)}\\n\\n`;\n }\n\n md += `---\\n\\n`;\n\n if (options.includeMessages) {\n for (const detail of data.details) {\n md += `## ${this.capitalizeRole(detail.Role || 'Unknown')}\\n\\n`;\n md += `${detail.Message}\\n\\n`;\n\n if (options.includeMetadata) {\n md += `*${this.formatDate(detail.__mj_CreatedAt)}*\\n\\n`;\n }\n\n md += `---\\n\\n`;\n }\n }\n\n const trademark = options.branding?.trademark?.trim();\n if (trademark) {\n md += `_${trademark}_\\n`;\n }\n\n return md;\n }\n\n private exportAsHTML(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions,\n theme: ResolvedExportTheme\n ): string {\n const trademark = options.branding?.trademark?.trim();\n // Every color reads a theme token with the legacy hex as its fallback, so an\n // unthemed export (no :root block emitted) renders exactly as it always has,\n // while a themed one follows the app's palette.\n const styles = options.includeCSS ? `\n <style>\n body { font-family: var(--mj-font-family, system-ui, -apple-system, sans-serif); background: var(--mj-bg-page, #fff); color: var(--mj-text-primary, #333); max-width: 800px; margin: 40px auto; padding: 0 20px; line-height: 1.6; }\n h1 { color: var(--mj-text-primary, #333); border-bottom: 2px solid var(--mj-brand-primary, #007bff); padding-bottom: 10px; }\n .meta { color: var(--mj-text-secondary, #666); font-size: 14px; margin-bottom: 30px; }\n .message { margin-bottom: 30px; padding: 20px; border-radius: var(--mj-radius-md, 8px); background: var(--mj-bg-surface-card, #f5f5f5); }\n .message.user { background: var(--mj-brand-accent-subtle, #e3f2fd); }\n .message.assistant { background: var(--mj-bg-surface-card, #f5f5f5); }\n .role { font-weight: 600; color: var(--mj-brand-primary, #007bff); margin-bottom: 10px; }\n .content { white-space: pre-wrap; }\n .timestamp { color: var(--mj-text-disabled, #999); font-size: 12px; margin-top: 10px; }${theme.logoDataUri ? `\n .brand-logo { display: block; max-height: 48px; margin-bottom: 12px; }` : ''}${trademark ? `\n .brand-trademark { margin-top: 40px; padding-top: 16px; border-top: 1px solid var(--mj-border-default, #ddd); color: var(--mj-text-secondary, #666); font-size: 12px; text-align: center; }` : ''}\n </style>${theme.rootBlock}` : '';\n\n const title = theme.title ?? (data.conversation.Name || 'Conversation');\n let html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${this.escapeHtml(title)}</title>${styles}\n</head>\n<body>\n ${theme.logoDataUri ? `<img class=\"brand-logo\" src=\"${this.escapeAttr(theme.logoDataUri)}\" alt=\"\" />\n ` : ''}<h1>${this.escapeHtml(title)}</h1>`;\n\n if (options.includeMetadata) {\n html += `\n <div class=\"meta\">\n ${data.conversation.Description ? `<p>${this.escapeHtml(data.conversation.Description)}</p>` : ''}\n <p>Created: ${this.formatDate(data.conversation.__mj_CreatedAt)}</p>\n </div>`;\n }\n\n if (options.includeMessages) {\n for (const detail of data.details) {\n const roleClass = detail.Role?.toLowerCase() || 'unknown';\n html += `\n <div class=\"message ${roleClass}\">\n <div class=\"role\">${this.capitalizeRole(detail.Role || 'Unknown')}</div>\n <div class=\"content\">${this.escapeHtml(detail.Message || '')}</div>`;\n\n if (options.includeMetadata) {\n html += `\n <div class=\"timestamp\">${this.formatDate(detail.__mj_CreatedAt)}</div>`;\n }\n\n html += `\n </div>`;\n }\n }\n\n if (options.includeCSS && trademark) {\n html += `\n <footer class=\"brand-trademark\">${this.escapeHtml(trademark)}</footer>`;\n }\n\n html += `\n</body>\n</html>`;\n\n return html;\n }\n\n private exportAsText(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions\n ): string {\n const name = this.resolveTitle(data, options) || 'Conversation';\n let text = `${name}\\n`;\n text += '='.repeat(name.length) + '\\n\\n';\n\n if (data.conversation.Description) {\n text += `${data.conversation.Description}\\n\\n`;\n }\n\n if (options.includeMetadata) {\n text += `Created: ${this.formatDate(data.conversation.__mj_CreatedAt)}\\n\\n`;\n }\n\n text += '-'.repeat(80) + '\\n\\n';\n\n if (options.includeMessages) {\n for (const detail of data.details) {\n text += `[${this.capitalizeRole(detail.Role || 'Unknown')}]\\n`;\n text += `${detail.Message}\\n`;\n\n if (options.includeMetadata) {\n text += `(${this.formatDate(detail.__mj_CreatedAt)})\\n`;\n }\n\n text += '\\n' + '-'.repeat(80) + '\\n\\n';\n }\n }\n\n const trademark = options.branding?.trademark?.trim();\n if (trademark) {\n text += `${trademark}\\n`;\n }\n\n return text;\n }\n\n private downloadFile(content: string, filename: string, mimeType: string): void {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n }\n\n private formatDate(date: Date | string): string {\n const d = new Date(date);\n return d.toLocaleString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n private capitalizeRole(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1).toLowerCase();\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n /** escapeHtml + quote escaping — for values interpolated into HTML attributes. */\n private escapeAttr(text: string): string {\n return this.escapeHtml(text).replace(/\"/g, '"');\n }\n\n private getTimestamp(): string {\n const now = new Date();\n return now.toISOString().replace(/[:.]/g, '-').slice(0, -5);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"export.service.js","sourceRoot":"","sources":["../../../src/lib/services/export.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { MJConversationEntity, MJConversationDetailEntity } from '@memberjunction/core-entities';\nimport { RunView, UserInfo, Metadata, IMetadataProvider } from '@memberjunction/core';\n\nexport type ExportFormat = 'json' | 'markdown' | 'html' | 'text';\n\n/**\n * Branding applied to exported files, across EVERY format. HTML gets the full\n * treatment (theme colors, an inlined logo, the title, and a trademark footer);\n * JSON/markdown/text carry the title and trademark (markdown also references the\n * logo). Hosts supply this via `mj-conversation-chat-area`'s `exportBranding`\n * input. Color theming (`brandTokens`) is HTML-only — it has no meaning in the\n * data/plain-text formats.\n */\nexport interface ExportBranding {\n /**\n * CSS custom-property snapshot emitted as a `:root{}` block in the exported\n * document, so the export's stylesheet (which reads `var(--mj-…, fallback)`)\n * renders in the app's theme. HTML export only. Keys must be valid\n * custom-property names (`--like-this`). Entries are DROPPED when the key is\n * invalid or the value carries declaration-escape / network-call characters\n * (`<>{};@\\`, `url(`, `expression(`) — plain colors, `var()`, and\n * `color-mix()` pass. When omitted and `ExportOptions.includeTheme` is true,\n * the current theme is auto-snapshotted from `document.documentElement` (see\n * {@link DEFAULT_EXPORT_THEME_TOKENS}).\n */\n brandTokens?: Record<string, string>;\n /**\n * Logo URL. In HTML it is fetched and inlined as a data URI (so the file stays\n * self-contained) and rendered above the title — requires\n * `ExportOptions.includeCSS`, since it needs its stylesheet rule. In markdown it is\n * referenced by URL. JSON carries it as a string; plain text omits it.\n *\n * If the fetch fails, or the response isn't `content-type: image/*`, the raw URL is\n * emitted instead — so the exported file will reach out to that URL when opened.\n * There is no size or timeout guard on the fetch: a very large logo inflates the\n * export.\n */\n logoUrl?: string;\n /** Overrides the exported document's title (defaults to the conversation name). */\n title?: string;\n /**\n * A short trademark / attribution line (e.g. `© 2026 Acme Association ·\n * Powered by Betty`) rendered at the FOOT of the exported document: a styled HTML\n * footer, a markdown/text trailer, and a field in the JSON `branding` block.\n *\n * In HTML it needs its stylesheet rule, so — like the logo — it is emitted only when\n * `ExportOptions.includeCSS` is true. The markdown/text/JSON trailers have no such\n * dependency and always emit.\n *\n * NOT escaped for markdown: a value containing `_`, `]`, `)`, or a newline can break\n * the surrounding markdown. Supply plain text (HTML and JSON are escaped).\n */\n trademark?: string;\n}\n\nexport interface ExportOptions {\n includeMessages?: boolean;\n includeMetadata?: boolean;\n prettyPrint?: boolean;\n includeCSS?: boolean;\n /**\n * Emit the current app theme into the HTML export. When true and\n * `branding.brandTokens` is absent, the {@link DEFAULT_EXPORT_THEME_TOKENS}\n * are auto-snapshotted from the live document at export time. Default false —\n * an unthemed export renders exactly as before (the stylesheet's `var()`\n * fallbacks carry the legacy palette).\n *\n * Gates only the TOKEN auto-snapshot: a supplied `branding`'s `logoUrl`,\n * `title`, and `trademark` apply whenever `branding` is present — in HTML AND\n * in the JSON/markdown/text formats. (The export modal passes `branding`\n * through only while its \"Include branding\" checkbox is on, so in the UI flow\n * everything travels together.)\n */\n includeTheme?: boolean;\n /**\n * Which theme mode the snapshot captures — NOT whichever mode the app happens to be\n * in when the user clicks Export. Defaults to `'light'`: an export taken during a\n * dark session would otherwise bake dark text onto the page's white background and\n * come out unreadable. `'dark'` pairs the dark palette with the dark\n * `--mj-bg-page` the body rule applies, so the file is coherent either way.\n * HTML only — the data formats carry no colors.\n */\n themeMode?: 'light' | 'dark';\n /** Branding (tokens / logo / title) applied to the export — see {@link ExportBranding}. */\n branding?: ExportBranding;\n}\n\n/**\n * Tokens captured by the theme auto-snapshot — exactly the custom properties the\n * HTML export's stylesheet consumes. Hosts wanting more control supply their own\n * map via {@link ExportBranding.brandTokens} instead.\n */\nexport const DEFAULT_EXPORT_THEME_TOKENS: readonly string[] = [\n '--mj-bg-page',\n '--mj-text-primary',\n '--mj-text-secondary',\n '--mj-text-disabled',\n '--mj-border-default',\n '--mj-brand-primary',\n '--mj-brand-accent-subtle',\n '--mj-bg-surface-card',\n '--mj-font-family',\n '--mj-radius-md',\n];\n\n/** Internal: options with defaults applied (branding stays optional). */\ntype ResolvedExportOptions = Required<Omit<ExportOptions, 'branding'>> & Pick<ExportOptions, 'branding'>;\n\n/** Internal: the theme pieces resolved once per HTML export. */\ninterface ResolvedExportTheme {\n /** `<style>:root{…}</style>` block (empty string when no tokens resolved). */\n rootBlock: string;\n /** Inlined logo (data URI, or the raw URL on fetch failure); null = no logo. */\n logoDataUri: string | null;\n /** Document-title override; null = use the conversation name. */\n title: string | null;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ExportService {\n private _provider: IMetadataProvider | null = null;\n\n /**\n * Set the metadata provider this service should use. When unset, falls back to Metadata.Provider.\n */\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n\n async ExportConversation(\n conversationId: string,\n format: ExportFormat,\n currentUser: UserInfo,\n options: ExportOptions = {}\n ): Promise<void> {\n const conversation = await this.loadConversationData(conversationId, currentUser);\n const { content, filename, mimeType } = await this.BuildExportContent(conversation, format, options);\n this.downloadFile(content, filename, mimeType);\n }\n\n /** @deprecated Use {@link ExportConversation}. */\n async exportConversation(\n conversationId: string,\n format: ExportFormat,\n currentUser: UserInfo,\n options: ExportOptions = {}\n ): Promise<void> {\n return this.ExportConversation(conversationId, format, currentUser, options);\n }\n\n /**\n * Build the export document for already-loaded conversation data — the\n * download-free seam of {@link exportConversation}. Async because HTML-format\n * branding may inline a logo. Exposed publicly so hosts (and tests) can build\n * export content without triggering a browser download.\n */\n public async BuildExportContent(\n data: { conversation: MJConversationEntity; details: MJConversationDetailEntity[] },\n format: ExportFormat,\n options: ExportOptions = {}\n ): Promise<{ content: string; filename: string; mimeType: string }> {\n const exportOptions: ResolvedExportOptions = {\n includeMessages: options.includeMessages ?? true,\n includeMetadata: options.includeMetadata ?? true,\n prettyPrint: options.prettyPrint ?? true,\n includeCSS: options.includeCSS ?? true,\n includeTheme: options.includeTheme ?? false,\n themeMode: options.themeMode ?? 'light',\n branding: options.branding\n };\n const baseName = `conversation-${data.conversation.Name}-${this.getTimestamp()}`;\n\n switch (format) {\n case 'json':\n return { content: this.exportAsJSON(data, exportOptions), filename: `${baseName}.json`, mimeType: 'application/json' };\n case 'markdown':\n return { content: this.exportAsMarkdown(data, exportOptions), filename: `${baseName}.md`, mimeType: 'text/markdown' };\n case 'html':\n return {\n content: this.exportAsHTML(data, exportOptions, await this.resolveTheme(exportOptions)),\n filename: `${baseName}.html`,\n mimeType: 'text/html'\n };\n case 'text':\n return { content: this.exportAsText(data, exportOptions), filename: `${baseName}.txt`, mimeType: 'text/plain' };\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n /**\n * Snapshot the given theme tokens from the live document. Empty/unset tokens are\n * skipped.\n *\n * `mode` captures a SPECIFIC palette rather than whatever the app is rendering right\n * now. Without it, exporting from a dark session bakes dark text onto the export's\n * white page and the file is unreadable. When the requested mode isn't the active one,\n * `data-theme` is flipped on `documentElement`, read, and restored — all synchronous\n * within one task, so the browser never paints the intermediate state. Omit `mode`\n * to read the live values as-is.\n */\n public SnapshotBrandTokens(\n tokens: readonly string[] = DEFAULT_EXPORT_THEME_TOKENS,\n mode?: 'light' | 'dark'\n ): Record<string, string> {\n const root = document.documentElement;\n const previous = root.getAttribute('data-theme');\n // The app's two real states are `data-theme=\"dark\"` and NO attribute at all —\n // `MJExplorerAppComponent` removes it for light rather than writing \"light\"\n // (explorer-app.component.ts). Reproduce those exactly rather than inventing a\n // third state, so the transient DOM is one the stylesheet has actually seen.\n const wantDark = mode === 'dark';\n const isDark = previous === 'dark';\n const mustSwap = mode != null && wantDark !== isDark;\n\n if (mustSwap) {\n if (wantDark) {\n root.setAttribute('data-theme', 'dark');\n } else {\n root.removeAttribute('data-theme');\n }\n }\n try {\n const style = getComputedStyle(root);\n const out: Record<string, string> = {};\n for (const token of tokens) {\n const value = style.getPropertyValue(token).trim();\n if (value) {\n out[token] = value;\n }\n }\n return out;\n } finally {\n // Restore even if reading throws — never strand the app in the other theme.\n if (mustSwap) {\n if (previous === null) {\n root.removeAttribute('data-theme');\n } else {\n root.setAttribute('data-theme', previous);\n }\n }\n }\n }\n\n /** Resolve the HTML export's theme pieces once: tokens (explicit > snapshot), logo, title. */\n private async resolveTheme(options: ResolvedExportOptions): Promise<ResolvedExportTheme> {\n const tokens = this.resolveBrandTokens(options);\n const rootBlock = tokens ? this.buildRootBlock(tokens) : '';\n const logoUrl = options.branding?.logoUrl?.trim();\n return {\n rootBlock,\n // The logo needs its `.brand-logo` rule (as the trademark footer needs its own),\n // so both are gated on includeCSS — a CSS-less export must never carry a\n // full-size unstyled logo. The modal enforces this too, but the public\n // BuildExportContent seam has to hold the line on its own.\n logoDataUri: options.includeCSS && logoUrl ? await this.inlineLogo(logoUrl) : null,\n // The title is deliberately NOT includeCSS-gated: it lands in <title>/<h1>, needs\n // no stylesheet, and is the one branding field every format carries unconditionally.\n title: options.branding?.title?.trim() || null\n };\n }\n\n /** Explicit host tokens win; `includeTheme` falls back to a live snapshot; else no theme. */\n private resolveBrandTokens(options: ResolvedExportOptions): Record<string, string> | null {\n const explicit = options.branding?.brandTokens;\n if (explicit && Object.keys(explicit).length > 0) {\n return explicit;\n }\n return options.includeTheme ? this.SnapshotBrandTokens(DEFAULT_EXPORT_THEME_TOKENS, options.themeMode) : null;\n }\n\n /** Document title used by every format: branding override → conversation name → generic. */\n private resolveTitle(\n data: { conversation: MJConversationEntity; details: MJConversationDetailEntity[] },\n options: ResolvedExportOptions\n ): string {\n return options.branding?.title?.trim() || data.conversation.Name || 'Conversation';\n }\n\n /**\n * The JSON `branding` block — the data-format analogue of the HTML header +\n * trademark footer. Carries the title, trademark, and logo URL the host set;\n * null when no branding (or none of those fields) is present. Theme color\n * tokens are HTML-only and never included here.\n */\n private buildBrandingBlock(options: ResolvedExportOptions): Record<string, string> | null {\n const b = options.branding;\n if (!b) {\n return null;\n }\n const block: Record<string, string> = {};\n const title = b.title?.trim();\n const trademark = b.trademark?.trim();\n const logoUrl = b.logoUrl?.trim();\n if (title) block.title = title;\n if (trademark) block.trademark = trademark;\n if (logoUrl) block.logoUrl = logoUrl;\n return Object.keys(block).length > 0 ? block : null;\n }\n\n /**\n * CSS functions permitted inside an exported token value. This is an ALLOWLIST\n * (not a blocklist) so no network-capable function can slip through: blocking\n * only `url(`/`expression(` let `image-set()`, `-webkit-image-set()`,\n * `cross-fade()`, `image()`, and `src()` fetch a beacon URL without ever\n * writing the literal `url(`. Anything not on this list drops the whole entry.\n * The set is the safe value/color-math functions the export could legitimately\n * carry; extend it only with functions that CANNOT load an external resource.\n */\n private static readonly SAFE_CSS_FUNCTIONS = new Set([\n 'var', 'calc', 'min', 'max', 'clamp',\n 'rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'lab', 'lch', 'oklab', 'oklch',\n 'color', 'color-mix',\n ]);\n\n /**\n * Emit the sanitized `:root{}` style block. Keys must be custom-property names.\n * A value is REJECTED (the entry is dropped, not stripped) when it carries any\n * declaration/tag-escape or network-reach vector: `<>{}` (tag/rule breakout),\n * `;` (declaration breakout — e.g. `; background: url(beacon)`), `\\` (CSS\n * escapes), `@` (at-rules), OR any CSS function not in\n * {@link SAFE_CSS_FUNCTIONS} (which excludes every resource-loading function —\n * url/image-set/cross-fade/image/src/expression/…). Plain colors, `var()`, and\n * `color-mix()` pass untouched.\n */\n private buildRootBlock(tokens: Record<string, string>): string {\n const rules: string[] = [];\n for (const [key, rawValue] of Object.entries(tokens)) {\n if (!/^--[A-Za-z0-9_-]+$/.test(key)) {\n continue;\n }\n const value = String(rawValue).trim();\n if (!value || /[<>{};@\\\\]/.test(value) || this.hasUnsafeCssFunction(value)) {\n continue;\n }\n rules.push(`${key}: ${value};`);\n }\n return rules.length > 0 ? `\n <style>:root { ${rules.join(' ')} }</style>` : '';\n }\n\n /** True if the value calls any CSS function outside {@link SAFE_CSS_FUNCTIONS}. */\n private hasUnsafeCssFunction(value: string): boolean {\n // Every `name(` occurrence — the identifier immediately before a '('.\n const calls = value.match(/([a-zA-Z][a-zA-Z-]*)\\s*\\(/g) ?? [];\n return calls.some((c) => {\n const name = c.replace(/\\s*\\($/, '').toLowerCase();\n return !ExportService.SAFE_CSS_FUNCTIONS.has(name);\n });\n }\n\n /** Fetch → data URI so the export stays self-contained; raw URL on any failure\n * (or when the response isn't actually an image — don't inline HTML/other as\n * a bogus `data:` image). */\n private async inlineLogo(url: string): Promise<string> {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n return url;\n }\n const contentType = response.headers.get('content-type') ?? '';\n if (!/^image\\//i.test(contentType)) {\n return url;\n }\n const blob = await response.blob();\n return await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(String(reader.result));\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(blob);\n });\n } catch {\n return url;\n }\n }\n\n private async loadConversationData(\n conversationId: string,\n currentUser: UserInfo\n ): Promise<{ conversation: MJConversationEntity; details: MJConversationDetailEntity[] }> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Load conversation and details in parallel\n const [conversationResult, detailsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Conversations',\n ExtraFilter: `ID='${conversationId}'`,\n ResultType: 'entity_object'\n },\n {\n EntityName: 'MJ: Conversation Details',\n ExtraFilter: `ConversationID='${conversationId}'`,\n OrderBy: 'Sequence ASC',\n ResultType: 'entity_object'\n }\n ], currentUser);\n\n if (!conversationResult.Success || !conversationResult.Results?.length) {\n throw new Error('Conversation not found');\n }\n\n return {\n conversation: conversationResult.Results[0] as MJConversationEntity,\n details: (detailsResult.Results || []) as MJConversationDetailEntity[]\n };\n }\n\n private exportAsJSON(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions\n ): string {\n const exportData: Record<string, unknown> = {};\n\n // Add metadata if requested\n if (options.includeMetadata) {\n exportData.conversation = {\n id: data.conversation.ID,\n name: data.conversation.Name,\n description: data.conversation.Description,\n createdAt: data.conversation.__mj_CreatedAt,\n updatedAt: data.conversation.__mj_UpdatedAt\n };\n } else {\n exportData.conversation = {\n name: data.conversation.Name\n };\n }\n\n // Branding block (title / trademark / logo) when the host supplied branding —\n // the data-format analogue of the HTML header + trademark footer.\n const branding = this.buildBrandingBlock(options);\n if (branding) {\n exportData.branding = branding;\n }\n\n // Add messages if requested\n if (options.includeMessages) {\n exportData.messages = data.details.map((detail, index) => {\n const message: Record<string, unknown> = {\n role: detail.Role,\n message: detail.Message\n };\n\n if (options.includeMetadata) {\n message.id = detail.ID;\n message.sequence = index + 1;\n message.timestamp = detail.__mj_CreatedAt;\n }\n\n return message;\n });\n }\n\n // Use pretty print option\n return JSON.stringify(exportData, null, options.prettyPrint ? 2 : 0);\n }\n\n private exportAsMarkdown(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions\n ): string {\n const logoUrl = options.branding?.logoUrl?.trim();\n // Unbranded markdown must stay byte-identical to before (`# <Name>`), so DON'T\n // route through resolveTitle's 'Conversation' fallback here — only a supplied\n // branding title overrides the raw conversation name.\n const title = options.branding?.title?.trim() || data.conversation.Name;\n let md = '';\n if (logoUrl) {\n md += `\\n\\n`;\n }\n md += `# ${title}\\n\\n`;\n\n if (data.conversation.Description) {\n md += `${data.conversation.Description}\\n\\n`;\n }\n\n if (options.includeMetadata) {\n md += `**Created:** ${this.formatDate(data.conversation.__mj_CreatedAt)}\\n\\n`;\n }\n\n md += `---\\n\\n`;\n\n if (options.includeMessages) {\n for (const detail of data.details) {\n md += `## ${this.capitalizeRole(detail.Role || 'Unknown')}\\n\\n`;\n md += `${detail.Message}\\n\\n`;\n\n if (options.includeMetadata) {\n md += `*${this.formatDate(detail.__mj_CreatedAt)}*\\n\\n`;\n }\n\n md += `---\\n\\n`;\n }\n }\n\n const trademark = options.branding?.trademark?.trim();\n if (trademark) {\n md += `_${trademark}_\\n`;\n }\n\n return md;\n }\n\n private exportAsHTML(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions,\n theme: ResolvedExportTheme\n ): string {\n const trademark = options.branding?.trademark?.trim();\n // Every color reads a theme token with the legacy hex as its fallback, so an\n // unthemed export (no :root block emitted) renders exactly as it always has,\n // while a themed one follows the app's palette.\n const styles = options.includeCSS ? `\n <style>\n body { font-family: var(--mj-font-family, system-ui, -apple-system, sans-serif); background: var(--mj-bg-page, #fff); color: var(--mj-text-primary, #333); max-width: 800px; margin: 40px auto; padding: 0 20px; line-height: 1.6; }\n h1 { color: var(--mj-text-primary, #333); border-bottom: 2px solid var(--mj-brand-primary, #007bff); padding-bottom: 10px; }\n .meta { color: var(--mj-text-secondary, #666); font-size: 14px; margin-bottom: 30px; }\n .message { margin-bottom: 30px; padding: 20px; border-radius: var(--mj-radius-md, 8px); background: var(--mj-bg-surface-card, #f5f5f5); }\n .message.user { background: var(--mj-brand-accent-subtle, #e3f2fd); }\n .message.assistant { background: var(--mj-bg-surface-card, #f5f5f5); }\n .role { font-weight: 600; color: var(--mj-brand-primary, #007bff); margin-bottom: 10px; }\n .content { white-space: pre-wrap; }\n .timestamp { color: var(--mj-text-disabled, #999); font-size: 12px; margin-top: 10px; }${theme.logoDataUri ? `\n .brand-logo { display: block; max-height: 48px; margin-bottom: 12px; }` : ''}${trademark ? `\n .brand-trademark { margin-top: 40px; padding-top: 16px; border-top: 1px solid var(--mj-border-default, #ddd); color: var(--mj-text-secondary, #666); font-size: 12px; text-align: center; }` : ''}\n </style>${theme.rootBlock}` : '';\n\n const title = theme.title ?? (data.conversation.Name || 'Conversation');\n let html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${this.escapeHtml(title)}</title>${styles}\n</head>\n<body>\n ${theme.logoDataUri ? `<img class=\"brand-logo\" src=\"${this.escapeAttr(theme.logoDataUri)}\" alt=\"\" />\n ` : ''}<h1>${this.escapeHtml(title)}</h1>`;\n\n if (options.includeMetadata) {\n html += `\n <div class=\"meta\">\n ${data.conversation.Description ? `<p>${this.escapeHtml(data.conversation.Description)}</p>` : ''}\n <p>Created: ${this.formatDate(data.conversation.__mj_CreatedAt)}</p>\n </div>`;\n }\n\n if (options.includeMessages) {\n for (const detail of data.details) {\n const roleClass = detail.Role?.toLowerCase() || 'unknown';\n html += `\n <div class=\"message ${roleClass}\">\n <div class=\"role\">${this.capitalizeRole(detail.Role || 'Unknown')}</div>\n <div class=\"content\">${this.escapeHtml(detail.Message || '')}</div>`;\n\n if (options.includeMetadata) {\n html += `\n <div class=\"timestamp\">${this.formatDate(detail.__mj_CreatedAt)}</div>`;\n }\n\n html += `\n </div>`;\n }\n }\n\n if (options.includeCSS && trademark) {\n html += `\n <footer class=\"brand-trademark\">${this.escapeHtml(trademark)}</footer>`;\n }\n\n html += `\n</body>\n</html>`;\n\n return html;\n }\n\n private exportAsText(\n data: {\n conversation: MJConversationEntity;\n details: MJConversationDetailEntity[];\n },\n options: ResolvedExportOptions\n ): string {\n const name = this.resolveTitle(data, options) || 'Conversation';\n let text = `${name}\\n`;\n text += '='.repeat(name.length) + '\\n\\n';\n\n if (data.conversation.Description) {\n text += `${data.conversation.Description}\\n\\n`;\n }\n\n if (options.includeMetadata) {\n text += `Created: ${this.formatDate(data.conversation.__mj_CreatedAt)}\\n\\n`;\n }\n\n text += '-'.repeat(80) + '\\n\\n';\n\n if (options.includeMessages) {\n for (const detail of data.details) {\n text += `[${this.capitalizeRole(detail.Role || 'Unknown')}]\\n`;\n text += `${detail.Message}\\n`;\n\n if (options.includeMetadata) {\n text += `(${this.formatDate(detail.__mj_CreatedAt)})\\n`;\n }\n\n text += '\\n' + '-'.repeat(80) + '\\n\\n';\n }\n }\n\n const trademark = options.branding?.trademark?.trim();\n if (trademark) {\n text += `${trademark}\\n`;\n }\n\n return text;\n }\n\n private downloadFile(content: string, filename: string, mimeType: string): void {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n }\n\n private formatDate(date: Date | string): string {\n const d = new Date(date);\n return d.toLocaleString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n private capitalizeRole(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1).toLowerCase();\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n /** escapeHtml + quote escaping — for values interpolated into HTML attributes. */\n private escapeAttr(text: string): string {\n return this.escapeHtml(text).replace(/\"/g, '"');\n }\n\n private getTimestamp(): string {\n const now = new Date();\n return now.toISOString().replace(/[:.]/g, '-').slice(0, -5);\n }\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { UserInfo, IMetadataProvider } from '@memberjunction/core';
|
|
2
|
+
import type { AttachmentBlobUploadInput, AttachmentBlobUploadResult, IAttachmentBlobStore } from '@memberjunction/ai-core-plus';
|
|
3
|
+
export declare class GraphQLAttachmentBlobStore implements IAttachmentBlobStore {
|
|
4
|
+
/**
|
|
5
|
+
* Uploads bytes through MJAPI's storage subsystem, which creates the `MJ: Files` record.
|
|
6
|
+
*
|
|
7
|
+
* Storage account selection is the server's decision here: a browser has no business choosing
|
|
8
|
+
* a storage backend, and `UploadFile` resolves a default when none is named.
|
|
9
|
+
*/
|
|
10
|
+
Upload(input: AttachmentBlobUploadInput, _contextUser: UserInfo, _provider?: IMetadataProvider): Promise<AttachmentBlobUploadResult>;
|
|
11
|
+
/**
|
|
12
|
+
* Not supported from the browser, deliberately.
|
|
13
|
+
*
|
|
14
|
+
* Pulling file bytes through JavaScript only to re-encode them as base64 wastes memory and
|
|
15
|
+
* bandwidth for no benefit — {@link GetDownloadUrl} gives the browser something it can hand
|
|
16
|
+
* straight to an `<img>`, a download, or a fetch, and the service falls back to exactly that
|
|
17
|
+
* when this returns `null`. This is the one operation where "not supported" is the better
|
|
18
|
+
* answer rather than a gap.
|
|
19
|
+
*/
|
|
20
|
+
Download(_fileId: string, _contextUser: UserInfo, _provider?: IMetadataProvider): Promise<string | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Mints a permission-gated, time-limited URL for a stored file.
|
|
23
|
+
*
|
|
24
|
+
* Goes through `CreateMediaAccessToken` rather than `CreatePreAuthDownloadUrl`: the latter is
|
|
25
|
+
* keyed by storage account + object name, so using it would mean the client resolving storage
|
|
26
|
+
* internals it has no business knowing. The media route is keyed by `MJ: Files` id, checks the
|
|
27
|
+
* caller's permissions server-side, and Range-streams — it is the same path
|
|
28
|
+
* `mj-storage-media-player` already uses, so this adds a caller rather than a second mechanism.
|
|
29
|
+
*
|
|
30
|
+
* This is what makes the write path readable. Explorer only started producing storage-backed
|
|
31
|
+
* attachments when this seam was bound; without a URL here, every attachment over the inline
|
|
32
|
+
* threshold would upload successfully and then be permanently undisplayable.
|
|
33
|
+
*/
|
|
34
|
+
GetDownloadUrl(fileId: string, _contextUser: UserInfo, _provider?: IMetadataProvider): Promise<string | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Not supported from the browser.
|
|
37
|
+
*
|
|
38
|
+
* Deleting stored bytes is a server-side concern with its own permission and retention rules;
|
|
39
|
+
* a client requesting it directly would bypass them. Returning `false` leaves the attachment
|
|
40
|
+
* row intact rather than orphaning it against content the client could not remove.
|
|
41
|
+
*/
|
|
42
|
+
Delete(_fileId: string, _contextUser: UserInfo, _provider?: IMetadataProvider): Promise<boolean>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=graphql-attachment-blob-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-attachment-blob-store.d.ts","sourceRoot":"","sources":["../../../src/lib/services/graphql-attachment-blob-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAY,MAAM,sBAAsB,CAAC;AAE7E,OAAO,KAAK,EACR,yBAAyB,EACzB,0BAA0B,EAC1B,oBAAoB,EACvB,MAAM,8BAA8B,CAAC;AA4CtC,qBAAa,0BAA2B,YAAW,oBAAoB;IACnE;;;;;OAKG;IACU,MAAM,CACf,KAAK,EAAE,yBAAyB,EAChC,YAAY,EAAE,QAAQ,EACtB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,0BAA0B,CAAC;IAkBtC;;;;;;;;OAQG;IACU,QAAQ,CACjB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,QAAQ,EACtB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB;;;;;;;;;;;;OAYG;IACU,cAAc,CACvB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,QAAQ,EACtB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAoBzB;;;;;;OAMG;IACU,MAAM,CACf,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,QAAQ,EACtB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,OAAO,CAAC;CAGtB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { LogError } from '@memberjunction/core';
|
|
2
|
+
import { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Browser-side implementation of the conversation-attachment blob seam.
|
|
5
|
+
*
|
|
6
|
+
* The server binds an MJStorage implementation that talks to S3/Azure/Dropbox directly. A browser
|
|
7
|
+
* obviously cannot — and should not — hold those credentials, so it goes through MJAPI instead:
|
|
8
|
+
* `GraphQLFileStorageClient` already exposes exactly the four operations the seam needs, backed by
|
|
9
|
+
* the server's own storage subsystem and the caller's permissions.
|
|
10
|
+
*
|
|
11
|
+
* Binding this is what gives Explorer real large-attachment support. Before the seam existed, the
|
|
12
|
+
* Angular attachment service stored **everything inline** — it never consulted
|
|
13
|
+
* `ConversationUtility.ShouldStoreInline`, so a 5 MB image went into a database column rather than
|
|
14
|
+
* MJStorage, silently contradicting the `MJ: Conversation Detail Attachments` contract that
|
|
15
|
+
* `InlineData` is for small attachments and `FileID` for large ones. That is the concrete cost of
|
|
16
|
+
* having had three implementations of one policy.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Mints a short-lived, permission-checked URL for one `MJ: Files` record.
|
|
20
|
+
*
|
|
21
|
+
* The server resolves the storage account and object name behind the token and serves the bytes
|
|
22
|
+
* through its Range-capable `/media` route, so the browser never learns either.
|
|
23
|
+
*/
|
|
24
|
+
const CreateMediaAccessTokenMutation = `
|
|
25
|
+
mutation CreateMediaAccessToken($fileId: String!) {
|
|
26
|
+
CreateMediaAccessToken(fileId: $fileId) {
|
|
27
|
+
Success
|
|
28
|
+
Url
|
|
29
|
+
MimeType
|
|
30
|
+
ErrorMessage
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
export class GraphQLAttachmentBlobStore {
|
|
35
|
+
/**
|
|
36
|
+
* Uploads bytes through MJAPI's storage subsystem, which creates the `MJ: Files` record.
|
|
37
|
+
*
|
|
38
|
+
* Storage account selection is the server's decision here: a browser has no business choosing
|
|
39
|
+
* a storage backend, and `UploadFile` resolves a default when none is named.
|
|
40
|
+
*/
|
|
41
|
+
async Upload(input, _contextUser, _provider) {
|
|
42
|
+
try {
|
|
43
|
+
const client = new GraphQLFileStorageClient(GraphQLDataProvider.Instance);
|
|
44
|
+
const result = await client.UploadFile({
|
|
45
|
+
FileName: input.FileName,
|
|
46
|
+
Base64Data: input.Base64Data,
|
|
47
|
+
MimeType: input.MimeType,
|
|
48
|
+
AccountID: input.StorageAccountID ?? undefined,
|
|
49
|
+
});
|
|
50
|
+
if (!result?.Success || !result.FileID) {
|
|
51
|
+
return { Success: false, Error: result?.ErrorMessage ?? 'Upload failed.' };
|
|
52
|
+
}
|
|
53
|
+
return { Success: true, FileID: result.FileID };
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
return { Success: false, Error: err instanceof Error ? err.message : String(err) };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Not supported from the browser, deliberately.
|
|
61
|
+
*
|
|
62
|
+
* Pulling file bytes through JavaScript only to re-encode them as base64 wastes memory and
|
|
63
|
+
* bandwidth for no benefit — {@link GetDownloadUrl} gives the browser something it can hand
|
|
64
|
+
* straight to an `<img>`, a download, or a fetch, and the service falls back to exactly that
|
|
65
|
+
* when this returns `null`. This is the one operation where "not supported" is the better
|
|
66
|
+
* answer rather than a gap.
|
|
67
|
+
*/
|
|
68
|
+
async Download(_fileId, _contextUser, _provider) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Mints a permission-gated, time-limited URL for a stored file.
|
|
73
|
+
*
|
|
74
|
+
* Goes through `CreateMediaAccessToken` rather than `CreatePreAuthDownloadUrl`: the latter is
|
|
75
|
+
* keyed by storage account + object name, so using it would mean the client resolving storage
|
|
76
|
+
* internals it has no business knowing. The media route is keyed by `MJ: Files` id, checks the
|
|
77
|
+
* caller's permissions server-side, and Range-streams — it is the same path
|
|
78
|
+
* `mj-storage-media-player` already uses, so this adds a caller rather than a second mechanism.
|
|
79
|
+
*
|
|
80
|
+
* This is what makes the write path readable. Explorer only started producing storage-backed
|
|
81
|
+
* attachments when this seam was bound; without a URL here, every attachment over the inline
|
|
82
|
+
* threshold would upload successfully and then be permanently undisplayable.
|
|
83
|
+
*/
|
|
84
|
+
async GetDownloadUrl(fileId, _contextUser, _provider) {
|
|
85
|
+
try {
|
|
86
|
+
const result = (await GraphQLDataProvider.Instance.ExecuteGQL(CreateMediaAccessTokenMutation, {
|
|
87
|
+
fileId,
|
|
88
|
+
}));
|
|
89
|
+
const minted = result?.CreateMediaAccessToken;
|
|
90
|
+
if (!minted?.Success || !minted.Url) {
|
|
91
|
+
LogError(`[GraphQLAttachmentBlobStore] Could not mint a media URL for file ${fileId}: ` +
|
|
92
|
+
`${minted?.ErrorMessage ?? 'no URL returned'}`);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return minted.Url;
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
LogError(`[GraphQLAttachmentBlobStore] Failed to mint a media URL for file ${fileId}: ${err}`);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Not supported from the browser.
|
|
104
|
+
*
|
|
105
|
+
* Deleting stored bytes is a server-side concern with its own permission and retention rules;
|
|
106
|
+
* a client requesting it directly would bypass them. Returning `false` leaves the attachment
|
|
107
|
+
* row intact rather than orphaning it against content the client could not remove.
|
|
108
|
+
*/
|
|
109
|
+
async Delete(_fileId, _contextUser, _provider) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=graphql-attachment-blob-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-attachment-blob-store.js","sourceRoot":"","sources":["../../../src/lib/services/graphql-attachment-blob-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAOrG;;;;;;;;;;;;;;GAcG;AACH;;;;;GAKG;AACH,MAAM,8BAA8B,GAAG;;;;;;;;;CAStC,CAAC;AAYF,MAAM,OAAO,0BAA0B;IACnC;;;;;OAKG;IACI,KAAK,CAAC,MAAM,CACf,KAAgC,EAChC,YAAsB,EACtB,SAA6B;QAE7B,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,wBAAwB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;gBACnC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,SAAS,EAAE,KAAK,CAAC,gBAAgB,IAAI,SAAS;aACjD,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACrC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,IAAI,gBAAgB,EAAE,CAAC;YAC/E,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACvF,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,QAAQ,CACjB,OAAe,EACf,YAAsB,EACtB,SAA6B;QAE7B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,KAAK,CAAC,cAAc,CACvB,MAAc,EACd,YAAsB,EACtB,SAA6B;QAE7B,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,MAAM,mBAAmB,CAAC,QAAQ,CAAC,UAAU,CAAC,8BAA8B,EAAE;gBAC1F,MAAM;aACT,CAAC,CAA6B,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,EAAE,sBAAsB,CAAC;YAC9C,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAClC,QAAQ,CACJ,oEAAoE,MAAM,IAAI;oBAC1E,GAAG,MAAM,EAAE,YAAY,IAAI,iBAAiB,EAAE,CACrD,CAAC;gBACF,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,OAAO,MAAM,CAAC,GAAG,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,QAAQ,CAAC,oEAAoE,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC;YAC/F,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,MAAM,CACf,OAAe,EACf,YAAsB,EACtB,SAA6B;QAE7B,OAAO,KAAK,CAAC;IACjB,CAAC;CACJ","sourcesContent":["import { UserInfo, IMetadataProvider, LogError } from '@memberjunction/core';\nimport { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';\nimport type {\n AttachmentBlobUploadInput,\n AttachmentBlobUploadResult,\n IAttachmentBlobStore,\n} from '@memberjunction/ai-core-plus';\n\n/**\n * @fileoverview Browser-side implementation of the conversation-attachment blob seam.\n *\n * The server binds an MJStorage implementation that talks to S3/Azure/Dropbox directly. A browser\n * obviously cannot — and should not — hold those credentials, so it goes through MJAPI instead:\n * `GraphQLFileStorageClient` already exposes exactly the four operations the seam needs, backed by\n * the server's own storage subsystem and the caller's permissions.\n *\n * Binding this is what gives Explorer real large-attachment support. Before the seam existed, the\n * Angular attachment service stored **everything inline** — it never consulted\n * `ConversationUtility.ShouldStoreInline`, so a 5 MB image went into a database column rather than\n * MJStorage, silently contradicting the `MJ: Conversation Detail Attachments` contract that\n * `InlineData` is for small attachments and `FileID` for large ones. That is the concrete cost of\n * having had three implementations of one policy.\n */\n/**\n * Mints a short-lived, permission-checked URL for one `MJ: Files` record.\n *\n * The server resolves the storage account and object name behind the token and serves the bytes\n * through its Range-capable `/media` route, so the browser never learns either.\n */\nconst CreateMediaAccessTokenMutation = `\n mutation CreateMediaAccessToken($fileId: String!) {\n CreateMediaAccessToken(fileId: $fileId) {\n Success\n Url\n MimeType\n ErrorMessage\n }\n }\n`;\n\n/** The shape `CreateMediaAccessToken` returns, narrowed once at this boundary. */\ntype MediaAccessTokenResponse = {\n CreateMediaAccessToken?: {\n Success?: boolean;\n Url?: string | null;\n MimeType?: string | null;\n ErrorMessage?: string | null;\n } | null;\n};\n\nexport class GraphQLAttachmentBlobStore implements IAttachmentBlobStore {\n /**\n * Uploads bytes through MJAPI's storage subsystem, which creates the `MJ: Files` record.\n *\n * Storage account selection is the server's decision here: a browser has no business choosing\n * a storage backend, and `UploadFile` resolves a default when none is named.\n */\n public async Upload(\n input: AttachmentBlobUploadInput,\n _contextUser: UserInfo,\n _provider?: IMetadataProvider\n ): Promise<AttachmentBlobUploadResult> {\n try {\n const client = new GraphQLFileStorageClient(GraphQLDataProvider.Instance);\n const result = await client.UploadFile({\n FileName: input.FileName,\n Base64Data: input.Base64Data,\n MimeType: input.MimeType,\n AccountID: input.StorageAccountID ?? undefined,\n });\n if (!result?.Success || !result.FileID) {\n return { Success: false, Error: result?.ErrorMessage ?? 'Upload failed.' };\n }\n return { Success: true, FileID: result.FileID };\n } catch (err) {\n return { Success: false, Error: err instanceof Error ? err.message : String(err) };\n }\n }\n\n /**\n * Not supported from the browser, deliberately.\n *\n * Pulling file bytes through JavaScript only to re-encode them as base64 wastes memory and\n * bandwidth for no benefit — {@link GetDownloadUrl} gives the browser something it can hand\n * straight to an `<img>`, a download, or a fetch, and the service falls back to exactly that\n * when this returns `null`. This is the one operation where \"not supported\" is the better\n * answer rather than a gap.\n */\n public async Download(\n _fileId: string,\n _contextUser: UserInfo,\n _provider?: IMetadataProvider\n ): Promise<string | null> {\n return null;\n }\n\n /**\n * Mints a permission-gated, time-limited URL for a stored file.\n *\n * Goes through `CreateMediaAccessToken` rather than `CreatePreAuthDownloadUrl`: the latter is\n * keyed by storage account + object name, so using it would mean the client resolving storage\n * internals it has no business knowing. The media route is keyed by `MJ: Files` id, checks the\n * caller's permissions server-side, and Range-streams — it is the same path\n * `mj-storage-media-player` already uses, so this adds a caller rather than a second mechanism.\n *\n * This is what makes the write path readable. Explorer only started producing storage-backed\n * attachments when this seam was bound; without a URL here, every attachment over the inline\n * threshold would upload successfully and then be permanently undisplayable.\n */\n public async GetDownloadUrl(\n fileId: string,\n _contextUser: UserInfo,\n _provider?: IMetadataProvider\n ): Promise<string | null> {\n try {\n const result = (await GraphQLDataProvider.Instance.ExecuteGQL(CreateMediaAccessTokenMutation, {\n fileId,\n })) as MediaAccessTokenResponse;\n const minted = result?.CreateMediaAccessToken;\n if (!minted?.Success || !minted.Url) {\n LogError(\n `[GraphQLAttachmentBlobStore] Could not mint a media URL for file ${fileId}: ` +\n `${minted?.ErrorMessage ?? 'no URL returned'}`\n );\n return null;\n }\n return minted.Url;\n } catch (err) {\n LogError(`[GraphQLAttachmentBlobStore] Failed to mint a media URL for file ${fileId}: ${err}`);\n return null;\n }\n }\n\n /**\n * Not supported from the browser.\n *\n * Deleting stored bytes is a server-side concern with its own permission and retention rules;\n * a client requesting it directly would bypass them. Returning `false` leaves the attachment\n * row intact rather than orphaning it against content the client could not remove.\n */\n public async Delete(\n _fileId: string,\n _contextUser: UserInfo,\n _provider?: IMetadataProvider\n ): Promise<boolean> {\n return false;\n }\n}\n"]}
|