@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
|
@@ -931,97 +931,409 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
931
931
|
permissionService;
|
|
932
932
|
artifactIconService;
|
|
933
933
|
cdr;
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
934
|
+
EnvironmentId;
|
|
935
|
+
/** @deprecated Use {@link EnvironmentId}. */
|
|
936
|
+
set environmentId(value) {
|
|
937
|
+
this.EnvironmentId = value;
|
|
938
|
+
}
|
|
939
|
+
/** @deprecated Use {@link EnvironmentId}. */
|
|
940
|
+
get environmentId() {
|
|
941
|
+
return this.EnvironmentId;
|
|
942
|
+
}
|
|
943
|
+
CurrentUser;
|
|
944
|
+
/** @deprecated Use {@link CurrentUser}. */
|
|
945
|
+
set currentUser(value) {
|
|
946
|
+
this.CurrentUser = value;
|
|
947
|
+
}
|
|
948
|
+
/** @deprecated Use {@link CurrentUser}. */
|
|
949
|
+
get currentUser() {
|
|
950
|
+
return this.CurrentUser;
|
|
951
|
+
}
|
|
952
|
+
CollectionNavigated = new EventEmitter();
|
|
953
|
+
/**
|
|
954
|
+
* @deprecated Use {@link CollectionNavigated}.
|
|
955
|
+
*
|
|
956
|
+
* The same emitter under the old binding name, so a template still binding
|
|
957
|
+
* (collectionNavigated) keeps working. Must stay AFTER CollectionNavigated: class fields
|
|
958
|
+
* initialise in order, and the other way round this captures undefined.
|
|
959
|
+
*/
|
|
960
|
+
collectionNavigated = this.CollectionNavigated;
|
|
937
961
|
/** Emitted when the user asks to open the conversation an artifact was produced in. */
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
962
|
+
OpenConversationRequested = new EventEmitter();
|
|
963
|
+
/**
|
|
964
|
+
* @deprecated Use {@link OpenConversationRequested}.
|
|
965
|
+
*
|
|
966
|
+
* The same emitter under the old binding name, so a template still binding
|
|
967
|
+
* (openConversationRequested) keeps working. Must stay AFTER OpenConversationRequested: class fields
|
|
968
|
+
* initialise in order, and the other way round this captures undefined.
|
|
969
|
+
*/
|
|
970
|
+
openConversationRequested = this.OpenConversationRequested;
|
|
971
|
+
Collections = [];
|
|
972
|
+
/** @deprecated Use {@link Collections}. */
|
|
973
|
+
get collections() {
|
|
974
|
+
return this.Collections;
|
|
975
|
+
}
|
|
976
|
+
/** @deprecated Use {@link Collections}. */
|
|
977
|
+
set collections(value) {
|
|
978
|
+
this.Collections = value;
|
|
979
|
+
}
|
|
980
|
+
ArtifactVersions = [];
|
|
981
|
+
/** @deprecated Use {@link ArtifactVersions}. */
|
|
982
|
+
get artifactVersions() {
|
|
983
|
+
return this.ArtifactVersions;
|
|
984
|
+
}
|
|
985
|
+
/** @deprecated Use {@link ArtifactVersions}. */
|
|
986
|
+
set artifactVersions(value) {
|
|
987
|
+
this.ArtifactVersions = value;
|
|
988
|
+
}
|
|
989
|
+
FilteredCollections = [];
|
|
990
|
+
/** @deprecated Use {@link FilteredCollections}. */
|
|
991
|
+
get filteredCollections() {
|
|
992
|
+
return this.FilteredCollections;
|
|
993
|
+
}
|
|
994
|
+
/** @deprecated Use {@link FilteredCollections}. */
|
|
995
|
+
set filteredCollections(value) {
|
|
996
|
+
this.FilteredCollections = value;
|
|
997
|
+
}
|
|
998
|
+
FilteredArtifactVersions = [];
|
|
999
|
+
/** @deprecated Use {@link FilteredArtifactVersions}. */
|
|
1000
|
+
get filteredArtifactVersions() {
|
|
1001
|
+
return this.FilteredArtifactVersions;
|
|
1002
|
+
}
|
|
1003
|
+
/** @deprecated Use {@link FilteredArtifactVersions}. */
|
|
1004
|
+
set filteredArtifactVersions(value) {
|
|
1005
|
+
this.FilteredArtifactVersions = value;
|
|
1006
|
+
}
|
|
943
1007
|
isLoading = false;
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1008
|
+
Breadcrumbs = [];
|
|
1009
|
+
/** @deprecated Use {@link Breadcrumbs}. */
|
|
1010
|
+
get breadcrumbs() {
|
|
1011
|
+
return this.Breadcrumbs;
|
|
1012
|
+
}
|
|
1013
|
+
/** @deprecated Use {@link Breadcrumbs}. */
|
|
1014
|
+
set breadcrumbs(value) {
|
|
1015
|
+
this.Breadcrumbs = value;
|
|
1016
|
+
}
|
|
1017
|
+
CurrentCollectionId = null;
|
|
1018
|
+
/** @deprecated Use {@link CurrentCollectionId}. */
|
|
1019
|
+
get currentCollectionId() {
|
|
1020
|
+
return this.CurrentCollectionId;
|
|
1021
|
+
}
|
|
1022
|
+
/** @deprecated Use {@link CurrentCollectionId}. */
|
|
1023
|
+
set currentCollectionId(value) {
|
|
1024
|
+
this.CurrentCollectionId = value;
|
|
1025
|
+
}
|
|
1026
|
+
CurrentCollection = null;
|
|
1027
|
+
/** @deprecated Use {@link CurrentCollection}. */
|
|
1028
|
+
get currentCollection() {
|
|
1029
|
+
return this.CurrentCollection;
|
|
1030
|
+
}
|
|
1031
|
+
/** @deprecated Use {@link CurrentCollection}. */
|
|
1032
|
+
set currentCollection(value) {
|
|
1033
|
+
this.CurrentCollection = value;
|
|
1034
|
+
}
|
|
1035
|
+
IsFormModalOpen = false;
|
|
1036
|
+
/** @deprecated Use {@link IsFormModalOpen}. */
|
|
1037
|
+
get isFormModalOpen() {
|
|
1038
|
+
return this.IsFormModalOpen;
|
|
1039
|
+
}
|
|
1040
|
+
/** @deprecated Use {@link IsFormModalOpen}. */
|
|
1041
|
+
set isFormModalOpen(value) {
|
|
1042
|
+
this.IsFormModalOpen = value;
|
|
1043
|
+
}
|
|
1044
|
+
editingCollection; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
1045
|
+
IsArtifactModalOpen = false;
|
|
1046
|
+
/** @deprecated Use {@link IsArtifactModalOpen}. */
|
|
1047
|
+
get isArtifactModalOpen() {
|
|
1048
|
+
return this.IsArtifactModalOpen;
|
|
1049
|
+
}
|
|
1050
|
+
/** @deprecated Use {@link IsArtifactModalOpen}. */
|
|
1051
|
+
set isArtifactModalOpen(value) {
|
|
1052
|
+
this.IsArtifactModalOpen = value;
|
|
1053
|
+
}
|
|
1054
|
+
UserPermissions = new Map();
|
|
1055
|
+
/** @deprecated Use {@link UserPermissions}. */
|
|
1056
|
+
get userPermissions() {
|
|
1057
|
+
return this.UserPermissions;
|
|
1058
|
+
}
|
|
1059
|
+
/** @deprecated Use {@link UserPermissions}. */
|
|
1060
|
+
set userPermissions(value) {
|
|
1061
|
+
this.UserPermissions = value;
|
|
1062
|
+
}
|
|
1063
|
+
IsShareModalOpen = false;
|
|
1064
|
+
/** @deprecated Use {@link IsShareModalOpen}. */
|
|
1065
|
+
get isShareModalOpen() {
|
|
1066
|
+
return this.IsShareModalOpen;
|
|
1067
|
+
}
|
|
1068
|
+
/** @deprecated Use {@link IsShareModalOpen}. */
|
|
1069
|
+
set isShareModalOpen(value) {
|
|
1070
|
+
this.IsShareModalOpen = value;
|
|
1071
|
+
}
|
|
1072
|
+
SharingCollection = null;
|
|
1073
|
+
/** @deprecated Use {@link SharingCollection}. */
|
|
1074
|
+
get sharingCollection() {
|
|
1075
|
+
return this.SharingCollection;
|
|
1076
|
+
}
|
|
1077
|
+
/** @deprecated Use {@link SharingCollection}. */
|
|
1078
|
+
set sharingCollection(value) {
|
|
1079
|
+
this.SharingCollection = value;
|
|
1080
|
+
}
|
|
953
1081
|
// New UI state for Mac Finder-style view
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1082
|
+
ViewMode = 'grid';
|
|
1083
|
+
/** @deprecated Use {@link ViewMode}. */
|
|
1084
|
+
get viewMode() {
|
|
1085
|
+
return this.ViewMode;
|
|
1086
|
+
}
|
|
1087
|
+
/** @deprecated Use {@link ViewMode}. */
|
|
1088
|
+
set viewMode(value) {
|
|
1089
|
+
this.ViewMode = value;
|
|
1090
|
+
}
|
|
1091
|
+
SortBy = 'name';
|
|
1092
|
+
/** @deprecated Use {@link SortBy}. */
|
|
1093
|
+
get sortBy() {
|
|
1094
|
+
return this.SortBy;
|
|
1095
|
+
}
|
|
1096
|
+
/** @deprecated Use {@link SortBy}. */
|
|
1097
|
+
set sortBy(value) {
|
|
1098
|
+
this.SortBy = value;
|
|
1099
|
+
}
|
|
1100
|
+
SortOrder = 'asc';
|
|
1101
|
+
/** @deprecated Use {@link SortOrder}. */
|
|
1102
|
+
get sortOrder() {
|
|
1103
|
+
return this.SortOrder;
|
|
1104
|
+
}
|
|
1105
|
+
/** @deprecated Use {@link SortOrder}. */
|
|
1106
|
+
set sortOrder(value) {
|
|
1107
|
+
this.SortOrder = value;
|
|
1108
|
+
}
|
|
1109
|
+
SearchQuery = '';
|
|
1110
|
+
/** @deprecated Use {@link SearchQuery}. */
|
|
1111
|
+
get searchQuery() {
|
|
1112
|
+
return this.SearchQuery;
|
|
1113
|
+
}
|
|
1114
|
+
/** @deprecated Use {@link SearchQuery}. */
|
|
1115
|
+
set searchQuery(value) {
|
|
1116
|
+
this.SearchQuery = value;
|
|
1117
|
+
}
|
|
958
1118
|
/** Empty-state heading — varies by search / root / inside-collection context. */
|
|
959
1119
|
get EmptyStateTitle() {
|
|
960
|
-
if (this.
|
|
1120
|
+
if (this.SearchQuery)
|
|
961
1121
|
return 'No items found';
|
|
962
|
-
if (!this.
|
|
1122
|
+
if (!this.CurrentCollectionId)
|
|
963
1123
|
return 'No collections yet';
|
|
964
1124
|
return 'This collection is empty';
|
|
965
1125
|
}
|
|
966
1126
|
/** Empty-state supporting message (the rich inside-collection hint is projected, not bound here). */
|
|
967
1127
|
get EmptyStateMessage() {
|
|
968
|
-
if (this.
|
|
1128
|
+
if (this.SearchQuery)
|
|
969
1129
|
return 'Try adjusting your search';
|
|
970
|
-
if (!this.
|
|
1130
|
+
if (!this.CurrentCollectionId)
|
|
971
1131
|
return 'Create your first collection to get started';
|
|
972
1132
|
return '';
|
|
973
1133
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1134
|
+
UnifiedItems = [];
|
|
1135
|
+
/** @deprecated Use {@link UnifiedItems}. */
|
|
1136
|
+
get unifiedItems() {
|
|
1137
|
+
return this.UnifiedItems;
|
|
1138
|
+
}
|
|
1139
|
+
/** @deprecated Use {@link UnifiedItems}. */
|
|
1140
|
+
set unifiedItems(value) {
|
|
1141
|
+
this.UnifiedItems = value;
|
|
1142
|
+
}
|
|
1143
|
+
SelectedItems = new Set();
|
|
1144
|
+
/** @deprecated Use {@link SelectedItems}. */
|
|
1145
|
+
get selectedItems() {
|
|
1146
|
+
return this.SelectedItems;
|
|
1147
|
+
}
|
|
1148
|
+
/** @deprecated Use {@link SelectedItems}. */
|
|
1149
|
+
set selectedItems(value) {
|
|
1150
|
+
this.SelectedItems = value;
|
|
1151
|
+
}
|
|
1152
|
+
ShowNewDropdown = false;
|
|
1153
|
+
/** @deprecated Use {@link ShowNewDropdown}. */
|
|
1154
|
+
get showNewDropdown() {
|
|
1155
|
+
return this.ShowNewDropdown;
|
|
1156
|
+
}
|
|
1157
|
+
/** @deprecated Use {@link ShowNewDropdown}. */
|
|
1158
|
+
set showNewDropdown(value) {
|
|
1159
|
+
this.ShowNewDropdown = value;
|
|
1160
|
+
}
|
|
1161
|
+
ShowSortDropdown = false;
|
|
1162
|
+
/** @deprecated Use {@link ShowSortDropdown}. */
|
|
1163
|
+
get showSortDropdown() {
|
|
1164
|
+
return this.ShowSortDropdown;
|
|
1165
|
+
}
|
|
1166
|
+
/** @deprecated Use {@link ShowSortDropdown}. */
|
|
1167
|
+
set showSortDropdown(value) {
|
|
1168
|
+
this.ShowSortDropdown = value;
|
|
1169
|
+
}
|
|
1170
|
+
ActiveArtifactId = null;
|
|
1171
|
+
/** @deprecated Use {@link ActiveArtifactId}. */
|
|
1172
|
+
get activeArtifactId() {
|
|
1173
|
+
return this.ActiveArtifactId;
|
|
1174
|
+
}
|
|
1175
|
+
/** @deprecated Use {@link ActiveArtifactId}. */
|
|
1176
|
+
set activeArtifactId(value) {
|
|
1177
|
+
this.ActiveArtifactId = value;
|
|
1178
|
+
} // Track which artifact is currently being viewed
|
|
979
1179
|
itemCountMap = new Map();
|
|
980
1180
|
/** Normalized OwnerID → friendly display name (FirstName LastName when available, else Users.Name) */
|
|
981
1181
|
ownerNameMap = new Map();
|
|
982
|
-
|
|
1182
|
+
IsSelectMode = false;
|
|
1183
|
+
/** @deprecated Use {@link IsSelectMode}. */
|
|
1184
|
+
get isSelectMode() {
|
|
1185
|
+
return this.IsSelectMode;
|
|
1186
|
+
}
|
|
1187
|
+
/** @deprecated Use {@link IsSelectMode}. */
|
|
1188
|
+
set isSelectMode(value) {
|
|
1189
|
+
this.IsSelectMode = value;
|
|
1190
|
+
} // Toggle for selection mode
|
|
983
1191
|
// Pagination state
|
|
984
1192
|
PageSize = 50;
|
|
985
1193
|
CurrentPage = 1;
|
|
986
1194
|
/** Total number of pages based on current items and page size */
|
|
987
1195
|
get TotalPages() {
|
|
988
|
-
return Math.max(1, Math.ceil(this.
|
|
1196
|
+
return Math.max(1, Math.ceil(this.UnifiedItems.length / this.PageSize));
|
|
989
1197
|
}
|
|
990
1198
|
/** Items for the current page */
|
|
991
1199
|
get PagedItems() {
|
|
992
1200
|
const start = (this.CurrentPage - 1) * this.PageSize;
|
|
993
|
-
return this.
|
|
1201
|
+
return this.UnifiedItems.slice(start, start + this.PageSize);
|
|
994
1202
|
}
|
|
995
1203
|
/** Navigate to a specific page */
|
|
996
1204
|
GoToPage(page) {
|
|
997
1205
|
this.CurrentPage = Math.max(1, Math.min(page, this.TotalPages));
|
|
998
1206
|
}
|
|
999
1207
|
IsArtifactActive(item) {
|
|
1000
|
-
return UUIDsEqual(item.artifact?.ID, this.
|
|
1208
|
+
return UUIDsEqual(item.artifact?.ID, this.ActiveArtifactId);
|
|
1001
1209
|
}
|
|
1002
1210
|
// Context menu state
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1211
|
+
ShowContextMenu = false;
|
|
1212
|
+
/** @deprecated Use {@link ShowContextMenu}. */
|
|
1213
|
+
get showContextMenu() {
|
|
1214
|
+
return this.ShowContextMenu;
|
|
1215
|
+
}
|
|
1216
|
+
/** @deprecated Use {@link ShowContextMenu}. */
|
|
1217
|
+
set showContextMenu(value) {
|
|
1218
|
+
this.ShowContextMenu = value;
|
|
1219
|
+
}
|
|
1220
|
+
ContextMenuPosition = { x: 0, y: 0 };
|
|
1221
|
+
/** @deprecated Use {@link ContextMenuPosition}. */
|
|
1222
|
+
get contextMenuPosition() {
|
|
1223
|
+
return this.ContextMenuPosition;
|
|
1224
|
+
}
|
|
1225
|
+
/** @deprecated Use {@link ContextMenuPosition}. */
|
|
1226
|
+
set contextMenuPosition(value) {
|
|
1227
|
+
this.ContextMenuPosition = value;
|
|
1228
|
+
}
|
|
1229
|
+
ContextMenuItem = null;
|
|
1230
|
+
/** @deprecated Use {@link ContextMenuItem}. */
|
|
1231
|
+
get contextMenuItem() {
|
|
1232
|
+
return this.ContextMenuItem;
|
|
1233
|
+
}
|
|
1234
|
+
/** @deprecated Use {@link ContextMenuItem}. */
|
|
1235
|
+
set contextMenuItem(value) {
|
|
1236
|
+
this.ContextMenuItem = value;
|
|
1237
|
+
}
|
|
1006
1238
|
/** "Move to Collection" submenu state (within the artifact context menu). */
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1239
|
+
ShowMoveSubmenu = false;
|
|
1240
|
+
/** @deprecated Use {@link ShowMoveSubmenu}. */
|
|
1241
|
+
get showMoveSubmenu() {
|
|
1242
|
+
return this.ShowMoveSubmenu;
|
|
1243
|
+
}
|
|
1244
|
+
/** @deprecated Use {@link ShowMoveSubmenu}. */
|
|
1245
|
+
set showMoveSubmenu(value) {
|
|
1246
|
+
this.ShowMoveSubmenu = value;
|
|
1247
|
+
}
|
|
1248
|
+
IsLoadingMoveTargets = false;
|
|
1249
|
+
/** @deprecated Use {@link IsLoadingMoveTargets}. */
|
|
1250
|
+
get isLoadingMoveTargets() {
|
|
1251
|
+
return this.IsLoadingMoveTargets;
|
|
1252
|
+
}
|
|
1253
|
+
/** @deprecated Use {@link IsLoadingMoveTargets}. */
|
|
1254
|
+
set isLoadingMoveTargets(value) {
|
|
1255
|
+
this.IsLoadingMoveTargets = value;
|
|
1256
|
+
}
|
|
1257
|
+
MoveTargets = [];
|
|
1258
|
+
/** @deprecated Use {@link MoveTargets}. */
|
|
1259
|
+
get moveTargets() {
|
|
1260
|
+
return this.MoveTargets;
|
|
1261
|
+
}
|
|
1262
|
+
/** @deprecated Use {@link MoveTargets}. */
|
|
1263
|
+
set moveTargets(value) {
|
|
1264
|
+
this.MoveTargets = value;
|
|
1265
|
+
}
|
|
1010
1266
|
/** Anchor index (into unifiedItems) for shift-click range selection. */
|
|
1011
1267
|
lastSelectedIndex = null;
|
|
1012
1268
|
/** Drag-and-drop state. draggedItemIds = the item ids being dragged (1 or the whole selection). */
|
|
1013
|
-
|
|
1269
|
+
DraggedItemIds = [];
|
|
1270
|
+
/** @deprecated Use {@link DraggedItemIds}. */
|
|
1271
|
+
get draggedItemIds() {
|
|
1272
|
+
return this.DraggedItemIds;
|
|
1273
|
+
}
|
|
1274
|
+
/** @deprecated Use {@link DraggedItemIds}. */
|
|
1275
|
+
set draggedItemIds(value) {
|
|
1276
|
+
this.DraggedItemIds = value;
|
|
1277
|
+
}
|
|
1014
1278
|
/** Tag of the current drop target for highlight: item id, 'root', 'crumb:<id>', or 'nav:<id>'. */
|
|
1015
|
-
|
|
1279
|
+
DragOverTargetId = null;
|
|
1280
|
+
/** @deprecated Use {@link DragOverTargetId}. */
|
|
1281
|
+
get dragOverTargetId() {
|
|
1282
|
+
return this.DragOverTargetId;
|
|
1283
|
+
}
|
|
1284
|
+
/** @deprecated Use {@link DragOverTargetId}. */
|
|
1285
|
+
set dragOverTargetId(value) {
|
|
1286
|
+
this.DragOverTargetId = value;
|
|
1287
|
+
}
|
|
1016
1288
|
/** Bulk "Move to…" popover (selection toolbar). */
|
|
1017
|
-
|
|
1289
|
+
ShowBulkMovePopover = false;
|
|
1290
|
+
/** @deprecated Use {@link ShowBulkMovePopover}. */
|
|
1291
|
+
get showBulkMovePopover() {
|
|
1292
|
+
return this.ShowBulkMovePopover;
|
|
1293
|
+
}
|
|
1294
|
+
/** @deprecated Use {@link ShowBulkMovePopover}. */
|
|
1295
|
+
set showBulkMovePopover(value) {
|
|
1296
|
+
this.ShowBulkMovePopover = value;
|
|
1297
|
+
}
|
|
1018
1298
|
/** All accessible collections (navigator pane + move targets + folder-cycle checks). */
|
|
1019
|
-
|
|
1299
|
+
AllCollections = [];
|
|
1300
|
+
/** @deprecated Use {@link AllCollections}. */
|
|
1301
|
+
get allCollections() {
|
|
1302
|
+
return this.AllCollections;
|
|
1303
|
+
}
|
|
1304
|
+
/** @deprecated Use {@link AllCollections}. */
|
|
1305
|
+
set allCollections(value) {
|
|
1306
|
+
this.AllCollections = value;
|
|
1307
|
+
}
|
|
1020
1308
|
allCollectionsById = new Map();
|
|
1021
|
-
|
|
1022
|
-
|
|
1309
|
+
NavigatorNodes = [];
|
|
1310
|
+
/** @deprecated Use {@link NavigatorNodes}. */
|
|
1311
|
+
get navigatorNodes() {
|
|
1312
|
+
return this.NavigatorNodes;
|
|
1313
|
+
}
|
|
1314
|
+
/** @deprecated Use {@link NavigatorNodes}. */
|
|
1315
|
+
set navigatorNodes(value) {
|
|
1316
|
+
this.NavigatorNodes = value;
|
|
1317
|
+
}
|
|
1318
|
+
ShowNavigator = true;
|
|
1319
|
+
/** @deprecated Use {@link ShowNavigator}. */
|
|
1320
|
+
get showNavigator() {
|
|
1321
|
+
return this.ShowNavigator;
|
|
1322
|
+
}
|
|
1323
|
+
/** @deprecated Use {@link ShowNavigator}. */
|
|
1324
|
+
set showNavigator(value) {
|
|
1325
|
+
this.ShowNavigator = value;
|
|
1326
|
+
}
|
|
1023
1327
|
/** Staging shelf: items held across navigation, then dropped into a destination collection. */
|
|
1024
|
-
|
|
1328
|
+
Shelf = [];
|
|
1329
|
+
/** @deprecated Use {@link Shelf}. */
|
|
1330
|
+
get shelf() {
|
|
1331
|
+
return this.Shelf;
|
|
1332
|
+
}
|
|
1333
|
+
/** @deprecated Use {@link Shelf}. */
|
|
1334
|
+
set shelf(value) {
|
|
1335
|
+
this.Shelf = value;
|
|
1336
|
+
}
|
|
1025
1337
|
destroy$ = new Subject();
|
|
1026
1338
|
isNavigatingProgrammatically = false;
|
|
1027
1339
|
constructor(dialogService, artifactState, collectionState, permissionService, artifactIconService, cdr) {
|
|
@@ -1044,13 +1356,13 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1044
1356
|
// Subscribe to artifact state changes to track active artifact
|
|
1045
1357
|
this.subscribeToArtifactState();
|
|
1046
1358
|
// Load the full collection set for the navigator pane + drag targets + cycle checks
|
|
1047
|
-
void this.
|
|
1359
|
+
void this.LoadAllCollections();
|
|
1048
1360
|
// Check if there's an active collection from URL params (set by parent component)
|
|
1049
1361
|
const activeCollectionId = this.collectionState.activeCollectionId;
|
|
1050
1362
|
if (activeCollectionId) {
|
|
1051
1363
|
// If there's an active collection, navigate to it (which will call loadData)
|
|
1052
1364
|
console.log('📁 Initial load with active collection:', activeCollectionId);
|
|
1053
|
-
this.
|
|
1365
|
+
this.NavigateToCollectionById(activeCollectionId);
|
|
1054
1366
|
}
|
|
1055
1367
|
else {
|
|
1056
1368
|
// Otherwise, just load the root level
|
|
@@ -1075,14 +1387,14 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1075
1387
|
}
|
|
1076
1388
|
// Only navigate if the state is different from our current state
|
|
1077
1389
|
// This prevents double-loading during initialization
|
|
1078
|
-
if (collectionId !== this.
|
|
1390
|
+
if (collectionId !== this.CurrentCollectionId) {
|
|
1079
1391
|
if (collectionId) {
|
|
1080
1392
|
console.log('📁 Collection state changed externally, navigating to:', collectionId);
|
|
1081
|
-
this.
|
|
1393
|
+
this.NavigateToCollectionById(collectionId);
|
|
1082
1394
|
}
|
|
1083
1395
|
else {
|
|
1084
1396
|
console.log('📁 Collection state cleared externally, navigating to root');
|
|
1085
|
-
this.
|
|
1397
|
+
this.NavigateToRoot();
|
|
1086
1398
|
}
|
|
1087
1399
|
}
|
|
1088
1400
|
});
|
|
@@ -1095,13 +1407,13 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1095
1407
|
.pipe(takeUntil(this.destroy$))
|
|
1096
1408
|
.subscribe(artifact => {
|
|
1097
1409
|
// Update active artifact ID for highlighting
|
|
1098
|
-
this.
|
|
1410
|
+
this.ActiveArtifactId = artifact?.ID || null;
|
|
1099
1411
|
});
|
|
1100
1412
|
}
|
|
1101
1413
|
async loadData() {
|
|
1102
1414
|
// Only show loading spinner if we don't have data yet
|
|
1103
1415
|
// This prevents flash of loading when navigating between collections
|
|
1104
|
-
const hasData = this.
|
|
1416
|
+
const hasData = this.Collections.length > 0 || this.UnifiedItems.length > 0;
|
|
1105
1417
|
if (!hasData) {
|
|
1106
1418
|
this.isLoading = true;
|
|
1107
1419
|
}
|
|
@@ -1109,15 +1421,15 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1109
1421
|
// Load saved view preferences from localStorage
|
|
1110
1422
|
const savedMode = localStorage.getItem('collections-view-mode');
|
|
1111
1423
|
if (savedMode === 'grid' || savedMode === 'list') {
|
|
1112
|
-
this.
|
|
1424
|
+
this.ViewMode = savedMode;
|
|
1113
1425
|
}
|
|
1114
1426
|
const savedSortBy = localStorage.getItem('collections-sort-by');
|
|
1115
1427
|
if (savedSortBy === 'name' || savedSortBy === 'date' || savedSortBy === 'type') {
|
|
1116
|
-
this.
|
|
1428
|
+
this.SortBy = savedSortBy;
|
|
1117
1429
|
}
|
|
1118
1430
|
const savedSortOrder = localStorage.getItem('collections-sort-order');
|
|
1119
1431
|
if (savedSortOrder === 'asc' || savedSortOrder === 'desc') {
|
|
1120
|
-
this.
|
|
1432
|
+
this.SortOrder = savedSortOrder;
|
|
1121
1433
|
}
|
|
1122
1434
|
await Promise.all([
|
|
1123
1435
|
this.loadCollections(),
|
|
@@ -1136,14 +1448,14 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1136
1448
|
try {
|
|
1137
1449
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1138
1450
|
// Load collections where user is owner OR has permissions
|
|
1139
|
-
const ownerFilter = `OwnerID='${this.
|
|
1451
|
+
const ownerFilter = `OwnerID='${this.CurrentUser.ID}'`;
|
|
1140
1452
|
const permissionSubquery = `ID IN (
|
|
1141
1453
|
SELECT CollectionID
|
|
1142
1454
|
FROM [__mj].[vwCollectionPermissions]
|
|
1143
|
-
WHERE UserID='${this.
|
|
1455
|
+
WHERE UserID='${this.CurrentUser.ID}'
|
|
1144
1456
|
)`;
|
|
1145
|
-
const baseFilter = `EnvironmentID='${this.
|
|
1146
|
-
(this.
|
|
1457
|
+
const baseFilter = `EnvironmentID='${this.EnvironmentId}'` +
|
|
1458
|
+
(this.CurrentCollectionId ? ` AND ParentID='${this.CurrentCollectionId}'` : ' AND ParentID IS NULL');
|
|
1147
1459
|
const filter = `${baseFilter} AND (OwnerID IS NULL OR ${ownerFilter} OR ${permissionSubquery})`;
|
|
1148
1460
|
const result = await rv.RunView({
|
|
1149
1461
|
EntityName: 'MJ: Collections',
|
|
@@ -1152,15 +1464,15 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1152
1464
|
MaxRows: 1000,
|
|
1153
1465
|
ResultType: 'entity_object',
|
|
1154
1466
|
BypassCache: bypassCache
|
|
1155
|
-
}, this.
|
|
1467
|
+
}, this.CurrentUser);
|
|
1156
1468
|
if (result.Success) {
|
|
1157
|
-
this.
|
|
1469
|
+
this.Collections = result.Results || [];
|
|
1158
1470
|
await Promise.all([
|
|
1159
1471
|
this.loadUserPermissions(),
|
|
1160
1472
|
this.loadItemCounts(bypassCache),
|
|
1161
1473
|
this.loadOwnerNames()
|
|
1162
1474
|
]);
|
|
1163
|
-
this.
|
|
1475
|
+
this.FilteredCollections = [...this.Collections];
|
|
1164
1476
|
}
|
|
1165
1477
|
}
|
|
1166
1478
|
catch (error) {
|
|
@@ -1174,9 +1486,9 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1174
1486
|
*/
|
|
1175
1487
|
async loadItemCounts(bypassCache = false) {
|
|
1176
1488
|
this.itemCountMap.clear();
|
|
1177
|
-
if (this.
|
|
1489
|
+
if (this.Collections.length === 0)
|
|
1178
1490
|
return;
|
|
1179
|
-
const collectionIds = this.
|
|
1491
|
+
const collectionIds = this.Collections.map(c => c.ID);
|
|
1180
1492
|
const inClause = collectionIds.map(id => `'${id}'`).join(',');
|
|
1181
1493
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1182
1494
|
const [childResult, artifactResult] = await rv.RunViews([
|
|
@@ -1194,7 +1506,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1194
1506
|
ResultType: 'simple',
|
|
1195
1507
|
BypassCache: bypassCache
|
|
1196
1508
|
}
|
|
1197
|
-
], this.
|
|
1509
|
+
], this.CurrentUser);
|
|
1198
1510
|
// Count children per parent
|
|
1199
1511
|
if (childResult.Success && childResult.Results) {
|
|
1200
1512
|
for (const child of childResult.Results) {
|
|
@@ -1219,7 +1531,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1219
1531
|
// Clear up front so a failed reload falls back to denormalized names
|
|
1220
1532
|
// instead of serving a previous run's stale entries
|
|
1221
1533
|
this.ownerNameMap.clear();
|
|
1222
|
-
const ownerIds = [...new Set(this.
|
|
1534
|
+
const ownerIds = [...new Set(this.Collections
|
|
1223
1535
|
.filter(c => c.OwnerID)
|
|
1224
1536
|
.map(c => NormalizeUUID(c.OwnerID)))];
|
|
1225
1537
|
if (ownerIds.length === 0)
|
|
@@ -1231,7 +1543,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1231
1543
|
ExtraFilter: `ID IN (${ownerIds.map(id => `'${id}'`).join(',')})`,
|
|
1232
1544
|
Fields: ['ID', 'Name', 'FirstName', 'LastName'],
|
|
1233
1545
|
ResultType: 'simple'
|
|
1234
|
-
}, this.
|
|
1546
|
+
}, this.CurrentUser);
|
|
1235
1547
|
if (result.Success) {
|
|
1236
1548
|
for (const user of result.Results || []) {
|
|
1237
1549
|
const friendly = [user.FirstName, user.LastName].filter(Boolean).join(' ').trim();
|
|
@@ -1253,49 +1565,49 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1253
1565
|
return collection.Owner || undefined;
|
|
1254
1566
|
}
|
|
1255
1567
|
async loadUserPermissions() {
|
|
1256
|
-
this.
|
|
1257
|
-
for (const collection of this.
|
|
1258
|
-
const permission = await this.permissionService.checkPermission(collection.ID, this.
|
|
1568
|
+
this.UserPermissions.clear();
|
|
1569
|
+
for (const collection of this.Collections) {
|
|
1570
|
+
const permission = await this.permissionService.checkPermission(collection.ID, this.CurrentUser.ID, this.CurrentUser);
|
|
1259
1571
|
if (permission) {
|
|
1260
|
-
this.
|
|
1572
|
+
this.UserPermissions.set(collection.ID, permission);
|
|
1261
1573
|
}
|
|
1262
1574
|
}
|
|
1263
1575
|
}
|
|
1264
1576
|
async loadCurrentCollectionPermission() {
|
|
1265
|
-
if (!this.
|
|
1577
|
+
if (!this.CurrentCollectionId || !this.CurrentCollection) {
|
|
1266
1578
|
return;
|
|
1267
1579
|
}
|
|
1268
|
-
const permission = await this.permissionService.checkPermission(this.
|
|
1580
|
+
const permission = await this.permissionService.checkPermission(this.CurrentCollectionId, this.CurrentUser.ID, this.CurrentUser);
|
|
1269
1581
|
if (permission) {
|
|
1270
|
-
this.
|
|
1582
|
+
this.UserPermissions.set(this.CurrentCollectionId, permission);
|
|
1271
1583
|
}
|
|
1272
1584
|
}
|
|
1273
1585
|
async loadArtifacts(bypassCache = false) {
|
|
1274
|
-
if (!this.
|
|
1275
|
-
this.
|
|
1276
|
-
this.
|
|
1586
|
+
if (!this.CurrentCollectionId) {
|
|
1587
|
+
this.ArtifactVersions = [];
|
|
1588
|
+
this.FilteredArtifactVersions = [];
|
|
1277
1589
|
return;
|
|
1278
1590
|
}
|
|
1279
1591
|
try {
|
|
1280
|
-
this.
|
|
1281
|
-
this.
|
|
1592
|
+
this.ArtifactVersions = await this.artifactState.loadArtifactVersionsForCollection(this.CurrentCollectionId, this.CurrentUser, bypassCache);
|
|
1593
|
+
this.FilteredArtifactVersions = [...this.ArtifactVersions];
|
|
1282
1594
|
}
|
|
1283
1595
|
catch (error) {
|
|
1284
1596
|
console.error('Failed to load artifact versions:', error);
|
|
1285
1597
|
}
|
|
1286
1598
|
}
|
|
1287
|
-
async
|
|
1599
|
+
async OpenCollection(collection) {
|
|
1288
1600
|
this.isNavigatingProgrammatically = true;
|
|
1289
1601
|
try {
|
|
1290
|
-
this.
|
|
1291
|
-
this.
|
|
1292
|
-
this.
|
|
1293
|
-
this.
|
|
1602
|
+
this.Breadcrumbs.push({ id: collection.ID, name: collection.Name });
|
|
1603
|
+
this.CurrentCollectionId = collection.ID;
|
|
1604
|
+
this.CurrentCollection = collection;
|
|
1605
|
+
this.ActiveArtifactId = null; // Clear active artifact when switching collections
|
|
1294
1606
|
await this.loadData();
|
|
1295
1607
|
// Update state service
|
|
1296
1608
|
this.collectionState.setActiveCollection(collection.ID);
|
|
1297
1609
|
// Close any open artifact when switching collections
|
|
1298
|
-
this.
|
|
1610
|
+
this.CollectionNavigated.emit({
|
|
1299
1611
|
collectionId: collection.ID,
|
|
1300
1612
|
versionId: null
|
|
1301
1613
|
});
|
|
@@ -1304,22 +1616,26 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1304
1616
|
this.isNavigatingProgrammatically = false;
|
|
1305
1617
|
}
|
|
1306
1618
|
}
|
|
1307
|
-
|
|
1619
|
+
/** @deprecated Use {@link OpenCollection}. */
|
|
1620
|
+
async openCollection(collection) {
|
|
1621
|
+
return this.OpenCollection(collection);
|
|
1622
|
+
}
|
|
1623
|
+
async NavigateTo(crumb) {
|
|
1308
1624
|
this.isNavigatingProgrammatically = true;
|
|
1309
1625
|
try {
|
|
1310
|
-
const index = this.
|
|
1626
|
+
const index = this.Breadcrumbs.findIndex(b => b.id === crumb.id);
|
|
1311
1627
|
if (index !== -1) {
|
|
1312
|
-
this.
|
|
1313
|
-
this.
|
|
1628
|
+
this.Breadcrumbs = this.Breadcrumbs.slice(0, index + 1);
|
|
1629
|
+
this.CurrentCollectionId = crumb.id;
|
|
1314
1630
|
// Load the collection entity
|
|
1315
1631
|
const md = this.ProviderToUse;
|
|
1316
|
-
this.
|
|
1317
|
-
await this.
|
|
1632
|
+
this.CurrentCollection = await md.GetEntityObject('MJ: Collections', this.CurrentUser);
|
|
1633
|
+
await this.CurrentCollection.Load(crumb.id);
|
|
1318
1634
|
await this.loadData();
|
|
1319
1635
|
// Update state service
|
|
1320
1636
|
this.collectionState.setActiveCollection(crumb.id);
|
|
1321
1637
|
// Close any open artifact when navigating collections
|
|
1322
|
-
this.
|
|
1638
|
+
this.CollectionNavigated.emit({
|
|
1323
1639
|
collectionId: crumb.id,
|
|
1324
1640
|
versionId: null
|
|
1325
1641
|
});
|
|
@@ -1329,17 +1645,21 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1329
1645
|
this.isNavigatingProgrammatically = false;
|
|
1330
1646
|
}
|
|
1331
1647
|
}
|
|
1332
|
-
|
|
1648
|
+
/** @deprecated Use {@link NavigateTo}. */
|
|
1649
|
+
async navigateTo(crumb) {
|
|
1650
|
+
return this.NavigateTo(crumb);
|
|
1651
|
+
}
|
|
1652
|
+
async NavigateToRoot() {
|
|
1333
1653
|
this.isNavigatingProgrammatically = true;
|
|
1334
1654
|
try {
|
|
1335
|
-
this.
|
|
1336
|
-
this.
|
|
1337
|
-
this.
|
|
1655
|
+
this.Breadcrumbs = [];
|
|
1656
|
+
this.CurrentCollectionId = null;
|
|
1657
|
+
this.CurrentCollection = null;
|
|
1338
1658
|
await this.loadData();
|
|
1339
1659
|
// Update state service
|
|
1340
1660
|
this.collectionState.setActiveCollection(null);
|
|
1341
1661
|
// Close any open artifact when navigating to root
|
|
1342
|
-
this.
|
|
1662
|
+
this.CollectionNavigated.emit({
|
|
1343
1663
|
collectionId: null,
|
|
1344
1664
|
versionId: null
|
|
1345
1665
|
});
|
|
@@ -1348,11 +1668,15 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1348
1668
|
this.isNavigatingProgrammatically = false;
|
|
1349
1669
|
}
|
|
1350
1670
|
}
|
|
1671
|
+
/** @deprecated Use {@link NavigateToRoot}. */
|
|
1672
|
+
async navigateToRoot() {
|
|
1673
|
+
return this.NavigateToRoot();
|
|
1674
|
+
}
|
|
1351
1675
|
/**
|
|
1352
1676
|
* Update a breadcrumb entry's name in place (e.g., after rename)
|
|
1353
1677
|
*/
|
|
1354
1678
|
updateBreadcrumbName(collectionId, newName) {
|
|
1355
|
-
const crumb = this.
|
|
1679
|
+
const crumb = this.Breadcrumbs.find(b => UUIDsEqual(b.id, collectionId));
|
|
1356
1680
|
if (crumb) {
|
|
1357
1681
|
crumb.name = newName;
|
|
1358
1682
|
}
|
|
@@ -1361,13 +1685,13 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1361
1685
|
* Navigate to a collection by ID, building the breadcrumb trail
|
|
1362
1686
|
* Used for deep linking from search results or URL parameters
|
|
1363
1687
|
*/
|
|
1364
|
-
async
|
|
1688
|
+
async NavigateToCollectionById(collectionId) {
|
|
1365
1689
|
this.isNavigatingProgrammatically = true;
|
|
1366
1690
|
try {
|
|
1367
1691
|
console.log('📁 Navigating to collection by ID:', collectionId);
|
|
1368
1692
|
// Load the target collection
|
|
1369
1693
|
const md = this.ProviderToUse;
|
|
1370
|
-
const targetCollection = await md.GetEntityObject('MJ: Collections', this.
|
|
1694
|
+
const targetCollection = await md.GetEntityObject('MJ: Collections', this.CurrentUser);
|
|
1371
1695
|
await targetCollection.Load(collectionId);
|
|
1372
1696
|
if (!targetCollection || !targetCollection.ID) {
|
|
1373
1697
|
console.error('❌ Failed to load collection:', collectionId);
|
|
@@ -1378,7 +1702,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1378
1702
|
const trail = [];
|
|
1379
1703
|
let currentId = targetCollection.ParentID;
|
|
1380
1704
|
while (currentId) {
|
|
1381
|
-
const parentCollection = await md.GetEntityObject('MJ: Collections', this.
|
|
1705
|
+
const parentCollection = await md.GetEntityObject('MJ: Collections', this.CurrentUser);
|
|
1382
1706
|
await parentCollection.Load(currentId);
|
|
1383
1707
|
if (parentCollection && parentCollection.ID) {
|
|
1384
1708
|
// Add to front of trail (we're working backwards)
|
|
@@ -1398,9 +1722,9 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1398
1722
|
name: targetCollection.Name
|
|
1399
1723
|
});
|
|
1400
1724
|
// Update component state
|
|
1401
|
-
this.
|
|
1402
|
-
this.
|
|
1403
|
-
this.
|
|
1725
|
+
this.Breadcrumbs = trail;
|
|
1726
|
+
this.CurrentCollectionId = targetCollection.ID;
|
|
1727
|
+
this.CurrentCollection = targetCollection;
|
|
1404
1728
|
// Load collections and artifacts for this collection
|
|
1405
1729
|
await this.loadData();
|
|
1406
1730
|
// Update state service
|
|
@@ -1408,7 +1732,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1408
1732
|
// Emit navigation event
|
|
1409
1733
|
// NOTE: We don't emit artifactId here because this is for deep linking/programmatic navigation
|
|
1410
1734
|
// Artifact state is managed separately by the artifact state service
|
|
1411
|
-
this.
|
|
1735
|
+
this.CollectionNavigated.emit({
|
|
1412
1736
|
collectionId: targetCollection.ID
|
|
1413
1737
|
});
|
|
1414
1738
|
console.log('✅ Successfully navigated to collection with breadcrumb trail:', trail);
|
|
@@ -1420,28 +1744,44 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1420
1744
|
this.isNavigatingProgrammatically = false;
|
|
1421
1745
|
}
|
|
1422
1746
|
}
|
|
1423
|
-
|
|
1747
|
+
/** @deprecated Use {@link NavigateToCollectionById}. */
|
|
1748
|
+
async navigateToCollectionById(collectionId) {
|
|
1749
|
+
return this.NavigateToCollectionById(collectionId);
|
|
1750
|
+
}
|
|
1751
|
+
Refresh() {
|
|
1424
1752
|
this.loadData();
|
|
1425
1753
|
}
|
|
1426
|
-
|
|
1754
|
+
/** @deprecated Use {@link Refresh}. */
|
|
1755
|
+
refresh() {
|
|
1756
|
+
return this.Refresh();
|
|
1757
|
+
}
|
|
1758
|
+
async CreateCollection() {
|
|
1427
1759
|
// Validate user can edit current collection (or at root level)
|
|
1428
|
-
if (this.
|
|
1429
|
-
const canEdit = await this.validatePermission(this.
|
|
1760
|
+
if (this.CurrentCollection) {
|
|
1761
|
+
const canEdit = await this.validatePermission(this.CurrentCollection, 'edit');
|
|
1430
1762
|
if (!canEdit)
|
|
1431
1763
|
return;
|
|
1432
1764
|
}
|
|
1433
|
-
this.
|
|
1765
|
+
this.ShowNewDropdown = false;
|
|
1434
1766
|
this.editingCollection = undefined;
|
|
1435
|
-
this.
|
|
1767
|
+
this.IsFormModalOpen = true;
|
|
1436
1768
|
}
|
|
1437
|
-
|
|
1769
|
+
/** @deprecated Use {@link CreateCollection}. */
|
|
1770
|
+
async createCollection() {
|
|
1771
|
+
return this.CreateCollection();
|
|
1772
|
+
}
|
|
1773
|
+
async EditCollection(collection) {
|
|
1438
1774
|
const canEdit = await this.validatePermission(collection, 'edit');
|
|
1439
1775
|
if (!canEdit)
|
|
1440
1776
|
return;
|
|
1441
1777
|
this.editingCollection = collection;
|
|
1442
|
-
this.
|
|
1778
|
+
this.IsFormModalOpen = true;
|
|
1443
1779
|
}
|
|
1444
|
-
|
|
1780
|
+
/** @deprecated Use {@link EditCollection}. */
|
|
1781
|
+
async editCollection(collection) {
|
|
1782
|
+
return this.EditCollection(collection);
|
|
1783
|
+
}
|
|
1784
|
+
async DeleteCollection(collection) {
|
|
1445
1785
|
console.log('deleteCollection called for:', collection.Name, collection.ID);
|
|
1446
1786
|
// Validate user has delete permission
|
|
1447
1787
|
const canDelete = await this.validatePermission(collection, 'delete');
|
|
@@ -1460,7 +1800,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1460
1800
|
console.log('Attempting to delete collection and all children...');
|
|
1461
1801
|
await this.deleteCollectionRecursive(collection.ID);
|
|
1462
1802
|
await this.loadCollections(true);
|
|
1463
|
-
await this.
|
|
1803
|
+
await this.LoadAllCollections(true);
|
|
1464
1804
|
}
|
|
1465
1805
|
catch (error) {
|
|
1466
1806
|
console.error('Error deleting collection:', error);
|
|
@@ -1468,6 +1808,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1468
1808
|
}
|
|
1469
1809
|
}
|
|
1470
1810
|
}
|
|
1811
|
+
/** @deprecated Use {@link DeleteCollection}. */
|
|
1812
|
+
async deleteCollection(collection) {
|
|
1813
|
+
return this.DeleteCollection(collection);
|
|
1814
|
+
}
|
|
1471
1815
|
async deleteCollectionRecursive(collectionId) {
|
|
1472
1816
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1473
1817
|
// Step 1: Find and delete all child collections recursively
|
|
@@ -1476,21 +1820,21 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1476
1820
|
ExtraFilter: `ParentID='${collectionId}'`,
|
|
1477
1821
|
MaxRows: 1000,
|
|
1478
1822
|
ResultType: 'entity_object'
|
|
1479
|
-
}, this.
|
|
1823
|
+
}, this.CurrentUser);
|
|
1480
1824
|
if (childrenResult.Success && childrenResult.Results) {
|
|
1481
1825
|
for (const child of childrenResult.Results) {
|
|
1482
1826
|
await this.deleteCollectionRecursive(child.ID);
|
|
1483
1827
|
}
|
|
1484
1828
|
}
|
|
1485
1829
|
// Step 2: Delete all permissions for this collection
|
|
1486
|
-
await this.permissionService.deleteAllPermissions(collectionId, this.
|
|
1830
|
+
await this.permissionService.deleteAllPermissions(collectionId, this.CurrentUser);
|
|
1487
1831
|
// Step 3: Delete all artifact links for this collection
|
|
1488
1832
|
const artifactsResult = await rv.RunView({
|
|
1489
1833
|
EntityName: 'MJ: Collection Artifacts',
|
|
1490
1834
|
ExtraFilter: `CollectionID='${collectionId}'`,
|
|
1491
1835
|
MaxRows: 1000,
|
|
1492
1836
|
ResultType: 'entity_object'
|
|
1493
|
-
}, this.
|
|
1837
|
+
}, this.CurrentUser);
|
|
1494
1838
|
if (artifactsResult.Success && artifactsResult.Results) {
|
|
1495
1839
|
for (const ca of artifactsResult.Results) {
|
|
1496
1840
|
await ca.Delete();
|
|
@@ -1498,57 +1842,77 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1498
1842
|
}
|
|
1499
1843
|
// Step 4: Delete the collection itself
|
|
1500
1844
|
const md = this.ProviderToUse;
|
|
1501
|
-
const collection = await md.GetEntityObject('MJ: Collections', this.
|
|
1845
|
+
const collection = await md.GetEntityObject('MJ: Collections', this.CurrentUser);
|
|
1502
1846
|
await collection.Load(collectionId);
|
|
1503
1847
|
const deleted = await collection.Delete();
|
|
1504
1848
|
if (!deleted) {
|
|
1505
1849
|
throw new Error(`Failed to delete collection: ${collection.LatestResult?.Message || 'Unknown error'}`);
|
|
1506
1850
|
}
|
|
1507
1851
|
}
|
|
1508
|
-
async
|
|
1509
|
-
this.
|
|
1852
|
+
async OnCollectionSaved(collection) {
|
|
1853
|
+
this.IsFormModalOpen = false;
|
|
1510
1854
|
this.editingCollection = undefined;
|
|
1511
1855
|
await this.loadCollections(true);
|
|
1512
|
-
await this.
|
|
1856
|
+
await this.LoadAllCollections(true);
|
|
1513
1857
|
// Reload current collection permission (it was cleared by loadUserPermissions)
|
|
1514
1858
|
await this.loadCurrentCollectionPermission();
|
|
1515
1859
|
// Update breadcrumb and currentCollection if the saved collection is in the trail
|
|
1516
1860
|
this.updateBreadcrumbName(collection.ID, collection.Name);
|
|
1517
|
-
if (this.
|
|
1518
|
-
this.
|
|
1861
|
+
if (this.CurrentCollection && UUIDsEqual(this.CurrentCollection.ID, collection.ID)) {
|
|
1862
|
+
this.CurrentCollection = collection;
|
|
1519
1863
|
}
|
|
1520
1864
|
// Rebuild unified list to show new collection
|
|
1521
1865
|
this.buildUnifiedItemList();
|
|
1522
1866
|
this.cdr.detectChanges();
|
|
1523
1867
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1868
|
+
/** @deprecated Use {@link OnCollectionSaved}. */
|
|
1869
|
+
async onCollectionSaved(collection) {
|
|
1870
|
+
return this.OnCollectionSaved(collection);
|
|
1871
|
+
}
|
|
1872
|
+
OnFormCancelled() {
|
|
1873
|
+
this.IsFormModalOpen = false;
|
|
1526
1874
|
this.editingCollection = undefined;
|
|
1527
1875
|
}
|
|
1528
|
-
|
|
1876
|
+
/** @deprecated Use {@link OnFormCancelled}. */
|
|
1877
|
+
onFormCancelled() {
|
|
1878
|
+
return this.OnFormCancelled();
|
|
1879
|
+
}
|
|
1880
|
+
async AddArtifact() {
|
|
1529
1881
|
// Validate user can edit current collection
|
|
1530
|
-
if (this.
|
|
1531
|
-
const canEdit = await this.validatePermission(this.
|
|
1882
|
+
if (this.CurrentCollection) {
|
|
1883
|
+
const canEdit = await this.validatePermission(this.CurrentCollection, 'edit');
|
|
1532
1884
|
if (!canEdit)
|
|
1533
1885
|
return;
|
|
1534
1886
|
}
|
|
1535
|
-
this.
|
|
1536
|
-
this.
|
|
1887
|
+
this.ShowNewDropdown = false;
|
|
1888
|
+
this.IsArtifactModalOpen = true;
|
|
1537
1889
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1890
|
+
/** @deprecated Use {@link AddArtifact}. */
|
|
1891
|
+
async addArtifact() {
|
|
1892
|
+
return this.AddArtifact();
|
|
1893
|
+
}
|
|
1894
|
+
async OnArtifactSaved(artifact) {
|
|
1895
|
+
this.IsArtifactModalOpen = false;
|
|
1540
1896
|
await this.loadArtifacts(true);
|
|
1541
1897
|
this.cdr.detectChanges();
|
|
1542
1898
|
}
|
|
1899
|
+
/** @deprecated Use {@link OnArtifactSaved}. */
|
|
1900
|
+
async onArtifactSaved(artifact) {
|
|
1901
|
+
return this.OnArtifactSaved(artifact);
|
|
1902
|
+
}
|
|
1903
|
+
OnArtifactModalCancelled() {
|
|
1904
|
+
this.IsArtifactModalOpen = false;
|
|
1905
|
+
}
|
|
1906
|
+
/** @deprecated Use {@link OnArtifactModalCancelled}. */
|
|
1543
1907
|
onArtifactModalCancelled() {
|
|
1544
|
-
this.
|
|
1908
|
+
return this.OnArtifactModalCancelled();
|
|
1545
1909
|
}
|
|
1546
|
-
async
|
|
1547
|
-
if (!this.
|
|
1910
|
+
async RemoveArtifact(item) {
|
|
1911
|
+
if (!this.CurrentCollectionId)
|
|
1548
1912
|
return;
|
|
1549
1913
|
// Validate user has delete permission on current collection
|
|
1550
|
-
if (this.
|
|
1551
|
-
const canDelete = await this.validatePermission(this.
|
|
1914
|
+
if (this.CurrentCollection) {
|
|
1915
|
+
const canDelete = await this.validatePermission(this.CurrentCollection, 'delete');
|
|
1552
1916
|
if (!canDelete)
|
|
1553
1917
|
return;
|
|
1554
1918
|
}
|
|
@@ -1565,9 +1929,9 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1565
1929
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1566
1930
|
const result = await rv.RunView({
|
|
1567
1931
|
EntityName: 'MJ: Collection Artifacts',
|
|
1568
|
-
ExtraFilter: `CollectionID='${this.
|
|
1932
|
+
ExtraFilter: `CollectionID='${this.CurrentCollectionId}' AND ArtifactVersionID='${item.version.ID}'`,
|
|
1569
1933
|
ResultType: 'entity_object'
|
|
1570
|
-
}, this.
|
|
1934
|
+
}, this.CurrentUser);
|
|
1571
1935
|
if (result.Success && result.Results && result.Results.length > 0) {
|
|
1572
1936
|
// Delete this version association
|
|
1573
1937
|
for (const joinRecord of result.Results) {
|
|
@@ -1586,10 +1950,18 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1586
1950
|
}
|
|
1587
1951
|
}
|
|
1588
1952
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1953
|
+
/** @deprecated Use {@link RemoveArtifact}. */
|
|
1954
|
+
async removeArtifact(item) {
|
|
1955
|
+
return this.RemoveArtifact(item);
|
|
1956
|
+
}
|
|
1957
|
+
ViewArtifact(item) {
|
|
1958
|
+
this.ActiveArtifactId = item.artifact.ID;
|
|
1591
1959
|
this.artifactState.openArtifact(item.artifact.ID, item.version.VersionNumber);
|
|
1592
1960
|
}
|
|
1961
|
+
/** @deprecated Use {@link ViewArtifact}. */
|
|
1962
|
+
viewArtifact(item) {
|
|
1963
|
+
return this.ViewArtifact(item);
|
|
1964
|
+
}
|
|
1593
1965
|
// Permission validation and checking methods
|
|
1594
1966
|
async validatePermission(collection, requiredPermission) {
|
|
1595
1967
|
// Owner has all permissions. Null OwnerID (legacy collection) still counts as
|
|
@@ -1599,11 +1971,11 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1599
1971
|
return true;
|
|
1600
1972
|
}
|
|
1601
1973
|
if (collection.OwnerID
|
|
1602
|
-
? UUIDsEqual(collection.OwnerID, this.
|
|
1974
|
+
? UUIDsEqual(collection.OwnerID, this.CurrentUser.ID)
|
|
1603
1975
|
: requiredPermission !== 'share') {
|
|
1604
1976
|
return true;
|
|
1605
1977
|
}
|
|
1606
|
-
const permission = this.
|
|
1978
|
+
const permission = this.UserPermissions.get(collection.ID);
|
|
1607
1979
|
if (!permission) {
|
|
1608
1980
|
await this.dialogService.alert('Permission Denied', 'You do not have permission to perform this action.');
|
|
1609
1981
|
return false;
|
|
@@ -1620,18 +1992,18 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1620
1992
|
}
|
|
1621
1993
|
canEdit(collection) {
|
|
1622
1994
|
// Backwards compatibility: treat null OwnerID as owned by current user
|
|
1623
|
-
if (!collection.OwnerID || UUIDsEqual(collection.OwnerID, this.
|
|
1995
|
+
if (!collection.OwnerID || UUIDsEqual(collection.OwnerID, this.CurrentUser.ID))
|
|
1624
1996
|
return true;
|
|
1625
1997
|
// Check permission record
|
|
1626
|
-
const permission = this.
|
|
1998
|
+
const permission = this.UserPermissions.get(collection.ID);
|
|
1627
1999
|
return permission?.canEdit || false;
|
|
1628
2000
|
}
|
|
1629
2001
|
canDelete(collection) {
|
|
1630
2002
|
// Backwards compatibility: treat null OwnerID as owned by current user
|
|
1631
|
-
if (!collection.OwnerID || UUIDsEqual(collection.OwnerID, this.
|
|
2003
|
+
if (!collection.OwnerID || UUIDsEqual(collection.OwnerID, this.CurrentUser.ID))
|
|
1632
2004
|
return true;
|
|
1633
2005
|
// Check permission record
|
|
1634
|
-
const permission = this.
|
|
2006
|
+
const permission = this.UserPermissions.get(collection.ID);
|
|
1635
2007
|
return permission?.canDelete || false;
|
|
1636
2008
|
}
|
|
1637
2009
|
canShare(collection) {
|
|
@@ -1639,79 +2011,123 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1639
2011
|
// treatment: the server-side create gate requires a real owner or an explicit
|
|
1640
2012
|
// Share grant, so offering Share on a legacy null-owner collection would
|
|
1641
2013
|
// always be rejected server-side (permit-then-deny UX).
|
|
1642
|
-
if (collection.OwnerID && UUIDsEqual(collection.OwnerID, this.
|
|
2014
|
+
if (collection.OwnerID && UUIDsEqual(collection.OwnerID, this.CurrentUser.ID))
|
|
1643
2015
|
return true;
|
|
1644
2016
|
// Check permission record
|
|
1645
|
-
const permission = this.
|
|
2017
|
+
const permission = this.UserPermissions.get(collection.ID);
|
|
1646
2018
|
return permission?.canShare || false;
|
|
1647
2019
|
}
|
|
1648
|
-
|
|
2020
|
+
CanEditCurrent() {
|
|
1649
2021
|
// At root level, anyone can create
|
|
1650
|
-
if (!this.
|
|
2022
|
+
if (!this.CurrentCollectionId || !this.CurrentCollection) {
|
|
1651
2023
|
return true;
|
|
1652
2024
|
}
|
|
1653
|
-
return this.canEdit(this.
|
|
2025
|
+
return this.canEdit(this.CurrentCollection);
|
|
1654
2026
|
}
|
|
1655
|
-
|
|
2027
|
+
/** @deprecated Use {@link CanEditCurrent}. */
|
|
2028
|
+
canEditCurrent() {
|
|
2029
|
+
return this.CanEditCurrent();
|
|
2030
|
+
}
|
|
2031
|
+
CanDeleteCurrent() {
|
|
1656
2032
|
// At root level, no delete needed
|
|
1657
|
-
if (!this.
|
|
2033
|
+
if (!this.CurrentCollectionId || !this.CurrentCollection) {
|
|
1658
2034
|
return false;
|
|
1659
2035
|
}
|
|
1660
|
-
return this.canDelete(this.
|
|
2036
|
+
return this.canDelete(this.CurrentCollection);
|
|
1661
2037
|
}
|
|
1662
|
-
|
|
2038
|
+
/** @deprecated Use {@link CanDeleteCurrent}. */
|
|
2039
|
+
canDeleteCurrent() {
|
|
2040
|
+
return this.CanDeleteCurrent();
|
|
2041
|
+
}
|
|
2042
|
+
CanShareCurrent() {
|
|
1663
2043
|
// At root level, no share needed
|
|
1664
|
-
if (!this.
|
|
2044
|
+
if (!this.CurrentCollectionId || !this.CurrentCollection) {
|
|
1665
2045
|
return false;
|
|
1666
2046
|
}
|
|
1667
|
-
return this.canShare(this.
|
|
2047
|
+
return this.canShare(this.CurrentCollection);
|
|
1668
2048
|
}
|
|
1669
|
-
|
|
2049
|
+
/** @deprecated Use {@link CanShareCurrent}. */
|
|
2050
|
+
canShareCurrent() {
|
|
2051
|
+
return this.CanShareCurrent();
|
|
2052
|
+
}
|
|
2053
|
+
IsShared(collection) {
|
|
1670
2054
|
// Collection is shared if user is not the owner and OwnerID is set
|
|
1671
|
-
return collection.OwnerID != null && !UUIDsEqual(collection.OwnerID, this.
|
|
2055
|
+
return collection.OwnerID != null && !UUIDsEqual(collection.OwnerID, this.CurrentUser.ID);
|
|
2056
|
+
}
|
|
2057
|
+
/** @deprecated Use {@link IsShared}. */
|
|
2058
|
+
isShared(collection) {
|
|
2059
|
+
return this.IsShared(collection);
|
|
1672
2060
|
}
|
|
1673
2061
|
// Sharing methods
|
|
1674
|
-
async
|
|
2062
|
+
async ShareCollection(collection) {
|
|
1675
2063
|
// Validate user has share permission
|
|
1676
2064
|
const canShare = await this.validatePermission(collection, 'share');
|
|
1677
2065
|
if (!canShare)
|
|
1678
2066
|
return;
|
|
1679
|
-
this.
|
|
1680
|
-
this.
|
|
2067
|
+
this.SharingCollection = collection;
|
|
2068
|
+
this.IsShareModalOpen = true;
|
|
1681
2069
|
}
|
|
1682
|
-
|
|
2070
|
+
/** @deprecated Use {@link ShareCollection}. */
|
|
2071
|
+
async shareCollection(collection) {
|
|
2072
|
+
return this.ShareCollection(collection);
|
|
2073
|
+
}
|
|
2074
|
+
async OnPermissionsChanged() {
|
|
1683
2075
|
// Reload collections and permissions after sharing changes
|
|
1684
2076
|
await this.loadCollections(true);
|
|
1685
|
-
await this.
|
|
2077
|
+
await this.LoadAllCollections(true);
|
|
1686
2078
|
this.cdr.detectChanges();
|
|
1687
2079
|
}
|
|
2080
|
+
/** @deprecated Use {@link OnPermissionsChanged}. */
|
|
2081
|
+
async onPermissionsChanged() {
|
|
2082
|
+
return this.OnPermissionsChanged();
|
|
2083
|
+
}
|
|
2084
|
+
OnShareModalCancelled() {
|
|
2085
|
+
this.IsShareModalOpen = false;
|
|
2086
|
+
this.SharingCollection = null;
|
|
2087
|
+
}
|
|
2088
|
+
/** @deprecated Use {@link OnShareModalCancelled}. */
|
|
1688
2089
|
onShareModalCancelled() {
|
|
1689
|
-
this.
|
|
1690
|
-
this.sharingCollection = null;
|
|
2090
|
+
return this.OnShareModalCancelled();
|
|
1691
2091
|
}
|
|
1692
2092
|
// Header toolbar action methods
|
|
2093
|
+
ShareCurrentCollection() {
|
|
2094
|
+
if (this.CurrentCollection) {
|
|
2095
|
+
this.ShareCollection(this.CurrentCollection);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
/** @deprecated Use {@link ShareCurrentCollection}. */
|
|
1693
2099
|
shareCurrentCollection() {
|
|
1694
|
-
|
|
1695
|
-
|
|
2100
|
+
return this.ShareCurrentCollection();
|
|
2101
|
+
}
|
|
2102
|
+
EditCurrentCollection() {
|
|
2103
|
+
if (this.CurrentCollection) {
|
|
2104
|
+
this.EditCollection(this.CurrentCollection);
|
|
1696
2105
|
}
|
|
1697
2106
|
}
|
|
2107
|
+
/** @deprecated Use {@link EditCurrentCollection}. */
|
|
1698
2108
|
editCurrentCollection() {
|
|
1699
|
-
|
|
1700
|
-
|
|
2109
|
+
return this.EditCurrentCollection();
|
|
2110
|
+
}
|
|
2111
|
+
DeleteCurrentCollection() {
|
|
2112
|
+
if (this.CurrentCollection) {
|
|
2113
|
+
this.DeleteCollection(this.CurrentCollection);
|
|
1701
2114
|
}
|
|
1702
2115
|
}
|
|
2116
|
+
/** @deprecated Use {@link DeleteCurrentCollection}. */
|
|
1703
2117
|
deleteCurrentCollection() {
|
|
1704
|
-
|
|
1705
|
-
this.deleteCollection(this.currentCollection);
|
|
1706
|
-
}
|
|
2118
|
+
return this.DeleteCurrentCollection();
|
|
1707
2119
|
}
|
|
1708
2120
|
/**
|
|
1709
2121
|
* Get the icon for an artifact using the centralized icon service.
|
|
1710
2122
|
* Fallback priority: Plugin icon > Metadata icon > Hardcoded mapping > Generic icon
|
|
1711
2123
|
*/
|
|
1712
|
-
|
|
2124
|
+
GetArtifactIcon(artifact) {
|
|
1713
2125
|
return this.artifactIconService.getArtifactIcon(artifact);
|
|
1714
2126
|
}
|
|
2127
|
+
/** @deprecated Use {@link GetArtifactIcon}. */
|
|
2128
|
+
getArtifactIcon(artifact) {
|
|
2129
|
+
return this.GetArtifactIcon(artifact);
|
|
2130
|
+
}
|
|
1715
2131
|
// ==================== NEW MAC FINDER-STYLE METHODS ====================
|
|
1716
2132
|
/**
|
|
1717
2133
|
* Build unified list of folders and artifacts (Phase 1)
|
|
@@ -1719,7 +2135,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1719
2135
|
buildUnifiedItemList() {
|
|
1720
2136
|
const items = [];
|
|
1721
2137
|
// Add folders first (collections)
|
|
1722
|
-
for (const collection of this.
|
|
2138
|
+
for (const collection of this.FilteredCollections) {
|
|
1723
2139
|
items.push({
|
|
1724
2140
|
type: 'folder',
|
|
1725
2141
|
id: collection.ID,
|
|
@@ -1728,29 +2144,29 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1728
2144
|
icon: 'fa-folder',
|
|
1729
2145
|
itemCount: this.itemCountMap.get(collection.ID) || 0,
|
|
1730
2146
|
owner: this.getOwnerDisplayName(collection),
|
|
1731
|
-
isShared: this.
|
|
1732
|
-
selected: this.
|
|
2147
|
+
isShared: this.IsShared(collection),
|
|
2148
|
+
selected: this.SelectedItems.has(collection.ID),
|
|
1733
2149
|
collection: collection
|
|
1734
2150
|
});
|
|
1735
2151
|
}
|
|
1736
2152
|
// Then add artifacts
|
|
1737
|
-
for (const item of this.
|
|
2153
|
+
for (const item of this.FilteredArtifactVersions) {
|
|
1738
2154
|
items.push({
|
|
1739
2155
|
type: 'artifact',
|
|
1740
2156
|
id: item.version.ID,
|
|
1741
2157
|
name: item.artifact.Name,
|
|
1742
2158
|
description: item.artifact.Description || undefined,
|
|
1743
|
-
icon: this.
|
|
2159
|
+
icon: this.GetArtifactIcon(item.artifact),
|
|
1744
2160
|
versionNumber: item.version.VersionNumber,
|
|
1745
2161
|
artifactType: item.artifact.Type,
|
|
1746
2162
|
lastModified: item.version.__mj_UpdatedAt,
|
|
1747
|
-
selected: this.
|
|
2163
|
+
selected: this.SelectedItems.has(item.version.ID),
|
|
1748
2164
|
artifact: item.artifact,
|
|
1749
2165
|
version: item.version
|
|
1750
2166
|
});
|
|
1751
2167
|
}
|
|
1752
2168
|
// Apply sorting and reset pagination
|
|
1753
|
-
this.
|
|
2169
|
+
this.UnifiedItems = this.sortItems(items);
|
|
1754
2170
|
this.CurrentPage = 1;
|
|
1755
2171
|
this.cdr.detectChanges();
|
|
1756
2172
|
}
|
|
@@ -1765,7 +2181,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1765
2181
|
return a.type === 'folder' ? -1 : 1;
|
|
1766
2182
|
}
|
|
1767
2183
|
// Then sort by selected criteria
|
|
1768
|
-
switch (this.
|
|
2184
|
+
switch (this.SortBy) {
|
|
1769
2185
|
case 'name':
|
|
1770
2186
|
comparison = a.name.localeCompare(b.name);
|
|
1771
2187
|
break;
|
|
@@ -1778,137 +2194,169 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1778
2194
|
comparison = (a.artifactType || '').localeCompare(b.artifactType || '');
|
|
1779
2195
|
break;
|
|
1780
2196
|
}
|
|
1781
|
-
return this.
|
|
2197
|
+
return this.SortOrder === 'asc' ? comparison : -comparison;
|
|
1782
2198
|
});
|
|
1783
2199
|
}
|
|
1784
2200
|
/**
|
|
1785
2201
|
* Toggle between grid and list view
|
|
1786
2202
|
*/
|
|
1787
|
-
|
|
1788
|
-
this.
|
|
2203
|
+
ToggleViewMode() {
|
|
2204
|
+
this.ViewMode = this.ViewMode === 'grid' ? 'list' : 'grid';
|
|
1789
2205
|
// Save preference to localStorage
|
|
1790
|
-
localStorage.setItem('collections-view-mode', this.
|
|
2206
|
+
localStorage.setItem('collections-view-mode', this.ViewMode);
|
|
2207
|
+
}
|
|
2208
|
+
/** @deprecated Use {@link ToggleViewMode}. */
|
|
2209
|
+
toggleViewMode() {
|
|
2210
|
+
return this.ToggleViewMode();
|
|
1791
2211
|
}
|
|
1792
2212
|
/**
|
|
1793
2213
|
* Set view mode explicitly
|
|
1794
2214
|
*/
|
|
1795
|
-
|
|
1796
|
-
this.
|
|
2215
|
+
SetViewMode(mode) {
|
|
2216
|
+
this.ViewMode = mode;
|
|
1797
2217
|
// Save preference to localStorage
|
|
1798
2218
|
localStorage.setItem('collections-view-mode', mode);
|
|
1799
2219
|
}
|
|
2220
|
+
/** @deprecated Use {@link SetViewMode}. */
|
|
2221
|
+
setViewMode(mode) {
|
|
2222
|
+
return this.SetViewMode(mode);
|
|
2223
|
+
}
|
|
1800
2224
|
/**
|
|
1801
2225
|
* Toggle selection mode on/off
|
|
1802
2226
|
* When entering select mode, clicks toggle selection instead of opening items
|
|
1803
2227
|
* When exiting select mode, clears any selections
|
|
1804
2228
|
*/
|
|
1805
|
-
|
|
1806
|
-
this.
|
|
1807
|
-
if (!this.
|
|
2229
|
+
ToggleSelectMode() {
|
|
2230
|
+
this.IsSelectMode = !this.IsSelectMode;
|
|
2231
|
+
if (!this.IsSelectMode) {
|
|
1808
2232
|
// Clear selection when exiting select mode (clearSelection calls buildUnifiedItemList which calls cdr)
|
|
1809
|
-
this.
|
|
2233
|
+
this.ClearSelection();
|
|
1810
2234
|
}
|
|
1811
2235
|
else {
|
|
1812
2236
|
this.cdr.detectChanges();
|
|
1813
2237
|
}
|
|
1814
2238
|
}
|
|
2239
|
+
/** @deprecated Use {@link ToggleSelectMode}. */
|
|
2240
|
+
toggleSelectMode() {
|
|
2241
|
+
return this.ToggleSelectMode();
|
|
2242
|
+
}
|
|
1815
2243
|
/**
|
|
1816
2244
|
* Exit selection mode (called when navigating to a new folder)
|
|
1817
2245
|
*/
|
|
1818
2246
|
exitSelectMode() {
|
|
1819
|
-
if (this.
|
|
1820
|
-
this.
|
|
1821
|
-
this.
|
|
2247
|
+
if (this.IsSelectMode) {
|
|
2248
|
+
this.IsSelectMode = false;
|
|
2249
|
+
this.ClearSelection();
|
|
1822
2250
|
}
|
|
1823
2251
|
}
|
|
1824
2252
|
/**
|
|
1825
2253
|
* Set sort order - toggles asc/desc if clicking same column
|
|
1826
2254
|
*/
|
|
1827
|
-
|
|
1828
|
-
if (this.
|
|
2255
|
+
SetSortBy(sortBy) {
|
|
2256
|
+
if (this.SortBy === sortBy) {
|
|
1829
2257
|
// Toggle order if same sort
|
|
1830
|
-
this.
|
|
2258
|
+
this.SortOrder = this.SortOrder === 'asc' ? 'desc' : 'asc';
|
|
1831
2259
|
}
|
|
1832
2260
|
else {
|
|
1833
|
-
this.
|
|
1834
|
-
this.
|
|
2261
|
+
this.SortBy = sortBy;
|
|
2262
|
+
this.SortOrder = 'asc';
|
|
1835
2263
|
}
|
|
1836
2264
|
// Save sort preferences to localStorage
|
|
1837
|
-
localStorage.setItem('collections-sort-by', this.
|
|
1838
|
-
localStorage.setItem('collections-sort-order', this.
|
|
2265
|
+
localStorage.setItem('collections-sort-by', this.SortBy);
|
|
2266
|
+
localStorage.setItem('collections-sort-order', this.SortOrder);
|
|
1839
2267
|
// Close dropdown and rebuild list
|
|
1840
|
-
this.
|
|
2268
|
+
this.ShowSortDropdown = false;
|
|
1841
2269
|
this.buildUnifiedItemList();
|
|
1842
2270
|
}
|
|
2271
|
+
/** @deprecated Use {@link SetSortBy}. */
|
|
2272
|
+
setSortBy(sortBy) {
|
|
2273
|
+
return this.SetSortBy(sortBy);
|
|
2274
|
+
}
|
|
1843
2275
|
/**
|
|
1844
2276
|
* Filter items by search query (Phase 2)
|
|
1845
2277
|
*/
|
|
1846
|
-
|
|
2278
|
+
OnSearchChange(query) {
|
|
1847
2279
|
// If query parameter provided, use it; otherwise use searchQuery property
|
|
1848
|
-
const searchText = query !== undefined ? query : this.
|
|
2280
|
+
const searchText = query !== undefined ? query : this.SearchQuery;
|
|
1849
2281
|
if (!searchText.trim()) {
|
|
1850
2282
|
// Reset to all items
|
|
1851
2283
|
this.buildUnifiedItemList();
|
|
1852
2284
|
return;
|
|
1853
2285
|
}
|
|
1854
2286
|
const lowerQuery = searchText.toLowerCase();
|
|
1855
|
-
this.
|
|
2287
|
+
this.UnifiedItems = this.UnifiedItems.filter(item => item.name.toLowerCase().includes(lowerQuery) ||
|
|
1856
2288
|
item.description?.toLowerCase().includes(lowerQuery));
|
|
1857
2289
|
}
|
|
2290
|
+
/** @deprecated Use {@link OnSearchChange}. */
|
|
2291
|
+
onSearchChange(query) {
|
|
2292
|
+
return this.OnSearchChange(query);
|
|
2293
|
+
}
|
|
1858
2294
|
/**
|
|
1859
2295
|
* Multi-select: Toggle item selection (Phase 3)
|
|
1860
2296
|
*/
|
|
1861
|
-
|
|
2297
|
+
ToggleItemSelection(item, event) {
|
|
1862
2298
|
event.stopPropagation();
|
|
1863
2299
|
// Checkbox click: additive toggle by default, shift = range, cmd/ctrl = toggle.
|
|
1864
2300
|
this.applySelectionGesture(item, event);
|
|
1865
2301
|
}
|
|
2302
|
+
/** @deprecated Use {@link ToggleItemSelection}. */
|
|
2303
|
+
toggleItemSelection(item, event) {
|
|
2304
|
+
return this.ToggleItemSelection(item, event);
|
|
2305
|
+
}
|
|
1866
2306
|
/**
|
|
1867
2307
|
* Multi-select: Select all items (Phase 3)
|
|
1868
2308
|
*/
|
|
1869
|
-
|
|
1870
|
-
this.
|
|
1871
|
-
for (const item of this.
|
|
1872
|
-
this.
|
|
2309
|
+
SelectAll() {
|
|
2310
|
+
this.SelectedItems.clear();
|
|
2311
|
+
for (const item of this.UnifiedItems) {
|
|
2312
|
+
this.SelectedItems.add(item.id);
|
|
1873
2313
|
}
|
|
1874
2314
|
this.refreshSelectionFlags();
|
|
1875
2315
|
}
|
|
2316
|
+
/** @deprecated Use {@link SelectAll}. */
|
|
2317
|
+
selectAll() {
|
|
2318
|
+
return this.SelectAll();
|
|
2319
|
+
}
|
|
1876
2320
|
/**
|
|
1877
2321
|
* Multi-select: Clear selection (Phase 3)
|
|
1878
2322
|
*/
|
|
1879
|
-
|
|
1880
|
-
this.
|
|
2323
|
+
ClearSelection() {
|
|
2324
|
+
this.SelectedItems.clear();
|
|
1881
2325
|
this.lastSelectedIndex = null;
|
|
1882
2326
|
this.refreshSelectionFlags();
|
|
1883
2327
|
}
|
|
2328
|
+
/** @deprecated Use {@link ClearSelection}. */
|
|
2329
|
+
clearSelection() {
|
|
2330
|
+
return this.ClearSelection();
|
|
2331
|
+
}
|
|
1884
2332
|
/**
|
|
1885
2333
|
* Multi-select: Delete selected items
|
|
1886
2334
|
*/
|
|
1887
|
-
async
|
|
1888
|
-
if (this.
|
|
2335
|
+
async DeleteSelected() {
|
|
2336
|
+
if (this.SelectedItems.size === 0)
|
|
1889
2337
|
return;
|
|
1890
2338
|
const confirmed = await this.dialogService.confirm({
|
|
1891
|
-
title: `Delete ${this.
|
|
2339
|
+
title: `Delete ${this.SelectedItems.size} item(s)?`,
|
|
1892
2340
|
message: 'This action cannot be undone.',
|
|
1893
2341
|
dangerous: true
|
|
1894
2342
|
});
|
|
1895
2343
|
if (!confirmed)
|
|
1896
2344
|
return;
|
|
1897
|
-
const selectedViewItems = this.
|
|
2345
|
+
const selectedViewItems = this.UnifiedItems.filter(item => this.SelectedItems.has(item.id));
|
|
1898
2346
|
const folderItems = selectedViewItems.filter(item => item.type === 'folder' && item.collection);
|
|
1899
2347
|
const artifactItems = selectedViewItems.filter(item => item.type === 'artifact' && item.version);
|
|
1900
2348
|
try {
|
|
1901
2349
|
for (const item of folderItems) {
|
|
1902
2350
|
await this.deleteCollectionRecursive(item.collection.ID);
|
|
1903
2351
|
}
|
|
1904
|
-
if (artifactItems.length > 0 && this.
|
|
2352
|
+
if (artifactItems.length > 0 && this.CurrentCollectionId) {
|
|
1905
2353
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1906
2354
|
for (const item of artifactItems) {
|
|
1907
2355
|
const result = await rv.RunView({
|
|
1908
2356
|
EntityName: 'MJ: Collection Artifacts',
|
|
1909
|
-
ExtraFilter: `CollectionID='${this.
|
|
2357
|
+
ExtraFilter: `CollectionID='${this.CurrentCollectionId}' AND ArtifactVersionID='${item.version.ID}'`,
|
|
1910
2358
|
ResultType: 'entity_object'
|
|
1911
|
-
}, this.
|
|
2359
|
+
}, this.CurrentUser);
|
|
1912
2360
|
if (result.Success && result.Results) {
|
|
1913
2361
|
for (const joinRecord of result.Results) {
|
|
1914
2362
|
await joinRecord.Delete();
|
|
@@ -1916,9 +2364,9 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1916
2364
|
}
|
|
1917
2365
|
}
|
|
1918
2366
|
}
|
|
1919
|
-
this.
|
|
2367
|
+
this.ClearSelection();
|
|
1920
2368
|
await this.loadCollections(true);
|
|
1921
|
-
await this.
|
|
2369
|
+
await this.LoadAllCollections(true);
|
|
1922
2370
|
if (artifactItems.length > 0) {
|
|
1923
2371
|
await this.loadArtifacts(true);
|
|
1924
2372
|
}
|
|
@@ -1929,6 +2377,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1929
2377
|
await this.dialogService.alert('Error', `An error occurred while deleting: ${error}`);
|
|
1930
2378
|
}
|
|
1931
2379
|
}
|
|
2380
|
+
/** @deprecated Use {@link DeleteSelected}. */
|
|
2381
|
+
async deleteSelected() {
|
|
2382
|
+
return this.DeleteSelected();
|
|
2383
|
+
}
|
|
1932
2384
|
/**
|
|
1933
2385
|
* Get count of items in folder (Phase 1)
|
|
1934
2386
|
*/
|
|
@@ -1940,28 +2392,36 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1940
2392
|
* In select mode: toggles selection
|
|
1941
2393
|
* In normal mode: opens item (folder or artifact)
|
|
1942
2394
|
*/
|
|
1943
|
-
|
|
2395
|
+
OnItemClick(item, event) {
|
|
1944
2396
|
// Modifier-click selects without needing select mode (shift = range, cmd/ctrl = toggle)
|
|
1945
2397
|
if (event && (event.shiftKey || event.metaKey || event.ctrlKey)) {
|
|
1946
2398
|
this.applySelectionGesture(item, event, true);
|
|
1947
2399
|
return;
|
|
1948
2400
|
}
|
|
1949
2401
|
// In sticky select mode, a plain click toggles selection
|
|
1950
|
-
if (this.
|
|
2402
|
+
if (this.IsSelectMode) {
|
|
1951
2403
|
this.toggleItemSelectionSimple(item);
|
|
1952
2404
|
return;
|
|
1953
2405
|
}
|
|
1954
2406
|
// Normal mode: open the item
|
|
1955
2407
|
this.openItem(item);
|
|
1956
2408
|
}
|
|
2409
|
+
/** @deprecated Use {@link OnItemClick}. */
|
|
2410
|
+
onItemClick(item, event) {
|
|
2411
|
+
return this.OnItemClick(item, event);
|
|
2412
|
+
}
|
|
1957
2413
|
/**
|
|
1958
2414
|
* Handle double-clicking on unified item
|
|
1959
2415
|
* Always opens the item, even in select mode
|
|
1960
2416
|
*/
|
|
1961
|
-
|
|
2417
|
+
OnItemDoubleClick(item, event) {
|
|
1962
2418
|
event?.preventDefault();
|
|
1963
2419
|
this.openItem(item);
|
|
1964
2420
|
}
|
|
2421
|
+
/** @deprecated Use {@link OnItemDoubleClick}. */
|
|
2422
|
+
onItemDoubleClick(item, event) {
|
|
2423
|
+
return this.OnItemDoubleClick(item, event);
|
|
2424
|
+
}
|
|
1965
2425
|
/**
|
|
1966
2426
|
* Open an item (folder or artifact)
|
|
1967
2427
|
*/
|
|
@@ -1969,25 +2429,25 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1969
2429
|
if (item.type === 'folder' && item.collection) {
|
|
1970
2430
|
// Exit select mode when navigating to a new folder
|
|
1971
2431
|
this.exitSelectMode();
|
|
1972
|
-
this.
|
|
2432
|
+
this.OpenCollection(item.collection);
|
|
1973
2433
|
}
|
|
1974
2434
|
else if (item.type === 'artifact') {
|
|
1975
2435
|
if (!item.artifact || !item.version) {
|
|
1976
2436
|
console.error('Artifact or version is missing for item:', item.id);
|
|
1977
2437
|
return;
|
|
1978
2438
|
}
|
|
1979
|
-
this.
|
|
2439
|
+
this.ViewArtifact({ artifact: item.artifact, version: item.version });
|
|
1980
2440
|
}
|
|
1981
2441
|
}
|
|
1982
2442
|
/**
|
|
1983
2443
|
* Simple toggle for item selection (used in select mode)
|
|
1984
2444
|
*/
|
|
1985
2445
|
toggleItemSelectionSimple(item) {
|
|
1986
|
-
if (this.
|
|
1987
|
-
this.
|
|
2446
|
+
if (this.SelectedItems.has(item.id)) {
|
|
2447
|
+
this.SelectedItems.delete(item.id);
|
|
1988
2448
|
}
|
|
1989
2449
|
else {
|
|
1990
|
-
this.
|
|
2450
|
+
this.SelectedItems.add(item.id);
|
|
1991
2451
|
}
|
|
1992
2452
|
this.lastSelectedIndex = this.indexOfItem(item.id);
|
|
1993
2453
|
this.refreshSelectionFlags();
|
|
@@ -1995,7 +2455,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
1995
2455
|
/**
|
|
1996
2456
|
* Get item count text for display
|
|
1997
2457
|
*/
|
|
1998
|
-
|
|
2458
|
+
GetItemCountText(itemCount) {
|
|
1999
2459
|
if (itemCount !== undefined) {
|
|
2000
2460
|
if (itemCount === 0)
|
|
2001
2461
|
return 'Empty';
|
|
@@ -2003,8 +2463,8 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2003
2463
|
return '1 item';
|
|
2004
2464
|
return `${itemCount} items`;
|
|
2005
2465
|
}
|
|
2006
|
-
const folders = this.
|
|
2007
|
-
const artifacts = this.
|
|
2466
|
+
const folders = this.UnifiedItems.filter(i => i.type === 'folder').length;
|
|
2467
|
+
const artifacts = this.UnifiedItems.filter(i => i.type === 'artifact').length;
|
|
2008
2468
|
const total = folders + artifacts;
|
|
2009
2469
|
if (total === 0)
|
|
2010
2470
|
return 'No items';
|
|
@@ -2017,54 +2477,66 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2017
2477
|
parts.push(`${artifacts} artifact${artifacts > 1 ? 's' : ''}`);
|
|
2018
2478
|
return parts.join(', ');
|
|
2019
2479
|
}
|
|
2480
|
+
/** @deprecated Use {@link GetItemCountText}. */
|
|
2481
|
+
getItemCountText(itemCount) {
|
|
2482
|
+
return this.GetItemCountText(itemCount);
|
|
2483
|
+
}
|
|
2020
2484
|
/**
|
|
2021
2485
|
* Handle keyboard shortcuts
|
|
2022
2486
|
* - Cmd/Ctrl+A: Select all (enters select mode if not already)
|
|
2023
2487
|
* - Escape: Exit select mode and clear selection
|
|
2024
2488
|
* - Delete/Backspace: Delete selected items
|
|
2025
2489
|
*/
|
|
2026
|
-
|
|
2490
|
+
HandleKeyboardShortcut(event) {
|
|
2027
2491
|
// Cmd+A / Ctrl+A: Select all (enters select mode)
|
|
2028
2492
|
if ((event.metaKey || event.ctrlKey) && event.key === 'a') {
|
|
2029
2493
|
event.preventDefault();
|
|
2030
|
-
if (!this.
|
|
2031
|
-
this.
|
|
2494
|
+
if (!this.IsSelectMode) {
|
|
2495
|
+
this.IsSelectMode = true;
|
|
2032
2496
|
}
|
|
2033
|
-
this.
|
|
2497
|
+
this.SelectAll();
|
|
2034
2498
|
return;
|
|
2035
2499
|
}
|
|
2036
2500
|
// Escape: Exit select mode
|
|
2037
|
-
if (event.key === 'Escape' && this.
|
|
2501
|
+
if (event.key === 'Escape' && this.IsSelectMode) {
|
|
2038
2502
|
event.preventDefault();
|
|
2039
2503
|
this.exitSelectMode();
|
|
2040
2504
|
return;
|
|
2041
2505
|
}
|
|
2042
2506
|
// Delete/Backspace: Delete selected items
|
|
2043
|
-
if ((event.key === 'Delete' || event.key === 'Backspace') && this.
|
|
2507
|
+
if ((event.key === 'Delete' || event.key === 'Backspace') && this.SelectedItems.size > 0) {
|
|
2044
2508
|
// Only if not focused on an input
|
|
2045
2509
|
const target = event.target;
|
|
2046
2510
|
if (target.tagName !== 'INPUT' && target.tagName !== 'TEXTAREA') {
|
|
2047
2511
|
event.preventDefault();
|
|
2048
|
-
this.
|
|
2512
|
+
this.DeleteSelected();
|
|
2049
2513
|
}
|
|
2050
2514
|
return;
|
|
2051
2515
|
}
|
|
2052
2516
|
}
|
|
2517
|
+
/** @deprecated Use {@link HandleKeyboardShortcut}. */
|
|
2518
|
+
handleKeyboardShortcut(event) {
|
|
2519
|
+
return this.HandleKeyboardShortcut(event);
|
|
2520
|
+
}
|
|
2053
2521
|
/**
|
|
2054
2522
|
* Handle right-click context menu - shows custom context menu with permission-gated actions
|
|
2055
2523
|
*/
|
|
2056
|
-
|
|
2524
|
+
OnItemContextMenu(item, event) {
|
|
2057
2525
|
event.preventDefault();
|
|
2058
2526
|
event.stopPropagation();
|
|
2059
2527
|
// Close any open dropdowns
|
|
2060
|
-
this.
|
|
2061
|
-
this.
|
|
2062
|
-
this.
|
|
2063
|
-
this.
|
|
2064
|
-
this.
|
|
2065
|
-
this.
|
|
2528
|
+
this.ShowNewDropdown = false;
|
|
2529
|
+
this.ShowSortDropdown = false;
|
|
2530
|
+
this.ContextMenuItem = item;
|
|
2531
|
+
this.ContextMenuPosition = this.clampContextMenuPosition(event.clientX, event.clientY);
|
|
2532
|
+
this.ShowContextMenu = true;
|
|
2533
|
+
this.ShowMoveSubmenu = false;
|
|
2066
2534
|
this.cdr.detectChanges();
|
|
2067
2535
|
}
|
|
2536
|
+
/** @deprecated Use {@link OnItemContextMenu}. */
|
|
2537
|
+
onItemContextMenu(item, event) {
|
|
2538
|
+
return this.OnItemContextMenu(item, event);
|
|
2539
|
+
}
|
|
2068
2540
|
/** Clamp menu position to keep it within the viewport */
|
|
2069
2541
|
clampContextMenuPosition(x, y) {
|
|
2070
2542
|
const menuWidth = 200;
|
|
@@ -2076,54 +2548,66 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2076
2548
|
y: Math.min(y, viewportHeight - menuHeight)
|
|
2077
2549
|
};
|
|
2078
2550
|
}
|
|
2079
|
-
|
|
2080
|
-
this.
|
|
2081
|
-
this.
|
|
2082
|
-
this.
|
|
2551
|
+
CloseContextMenu() {
|
|
2552
|
+
this.ShowContextMenu = false;
|
|
2553
|
+
this.ContextMenuItem = null;
|
|
2554
|
+
this.ShowMoveSubmenu = false;
|
|
2083
2555
|
this.cdr.detectChanges();
|
|
2084
2556
|
}
|
|
2557
|
+
/** @deprecated Use {@link CloseContextMenu}. */
|
|
2558
|
+
closeContextMenu() {
|
|
2559
|
+
return this.CloseContextMenu();
|
|
2560
|
+
}
|
|
2085
2561
|
/** Opens the inline "Move to Collection" submenu and loads candidate target collections. */
|
|
2086
|
-
|
|
2562
|
+
OpenMoveSubmenu(event) {
|
|
2087
2563
|
event.stopPropagation();
|
|
2088
|
-
this.
|
|
2564
|
+
this.ShowMoveSubmenu = true;
|
|
2089
2565
|
void this.loadMoveTargets();
|
|
2090
2566
|
}
|
|
2091
|
-
|
|
2567
|
+
/** @deprecated Use {@link OpenMoveSubmenu}. */
|
|
2568
|
+
openMoveSubmenu(event) {
|
|
2569
|
+
return this.OpenMoveSubmenu(event);
|
|
2570
|
+
}
|
|
2571
|
+
CloseMoveSubmenu(event) {
|
|
2092
2572
|
event.stopPropagation();
|
|
2093
|
-
this.
|
|
2573
|
+
this.ShowMoveSubmenu = false;
|
|
2094
2574
|
this.cdr.detectChanges();
|
|
2095
2575
|
}
|
|
2576
|
+
/** @deprecated Use {@link CloseMoveSubmenu}. */
|
|
2577
|
+
closeMoveSubmenu(event) {
|
|
2578
|
+
return this.CloseMoveSubmenu(event);
|
|
2579
|
+
}
|
|
2096
2580
|
/** Loads every collection the user can access in this environment (flattened, indented), minus the current one. */
|
|
2097
2581
|
async loadMoveTargets() {
|
|
2098
|
-
this.
|
|
2099
|
-
this.
|
|
2582
|
+
this.IsLoadingMoveTargets = true;
|
|
2583
|
+
this.MoveTargets = [];
|
|
2100
2584
|
this.cdr.detectChanges();
|
|
2101
2585
|
try {
|
|
2102
2586
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2103
|
-
const ownerFilter = `OwnerID='${this.
|
|
2587
|
+
const ownerFilter = `OwnerID='${this.CurrentUser.ID}'`;
|
|
2104
2588
|
const permissionSubquery = `ID IN (
|
|
2105
|
-
SELECT CollectionID FROM [__mj].[vwCollectionPermissions] WHERE UserID='${this.
|
|
2589
|
+
SELECT CollectionID FROM [__mj].[vwCollectionPermissions] WHERE UserID='${this.CurrentUser.ID}'
|
|
2106
2590
|
)`;
|
|
2107
|
-
const filter = `EnvironmentID='${this.
|
|
2591
|
+
const filter = `EnvironmentID='${this.EnvironmentId}' AND (OwnerID IS NULL OR ${ownerFilter} OR ${permissionSubquery})`;
|
|
2108
2592
|
const result = await rv.RunView({
|
|
2109
2593
|
EntityName: 'MJ: Collections',
|
|
2110
2594
|
ExtraFilter: filter,
|
|
2111
2595
|
OrderBy: 'Name ASC',
|
|
2112
2596
|
MaxRows: 1000,
|
|
2113
2597
|
ResultType: 'entity_object'
|
|
2114
|
-
}, this.
|
|
2598
|
+
}, this.CurrentUser);
|
|
2115
2599
|
const all = result.Success ? (result.Results || []) : [];
|
|
2116
2600
|
const flattened = this.flattenCollectionTree(all);
|
|
2117
|
-
this.
|
|
2118
|
-
? flattened.filter(t => !UUIDsEqual(t.collection.ID, this.
|
|
2601
|
+
this.MoveTargets = this.CurrentCollectionId
|
|
2602
|
+
? flattened.filter(t => !UUIDsEqual(t.collection.ID, this.CurrentCollectionId))
|
|
2119
2603
|
: flattened;
|
|
2120
2604
|
}
|
|
2121
2605
|
catch (error) {
|
|
2122
2606
|
console.error('Failed to load move targets:', error);
|
|
2123
|
-
this.
|
|
2607
|
+
this.MoveTargets = [];
|
|
2124
2608
|
}
|
|
2125
2609
|
finally {
|
|
2126
|
-
this.
|
|
2610
|
+
this.IsLoadingMoveTargets = false;
|
|
2127
2611
|
this.cdr.detectChanges();
|
|
2128
2612
|
}
|
|
2129
2613
|
}
|
|
@@ -2153,10 +2637,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2153
2637
|
* Adds to the target first (so a failure never drops it from the source), then removes
|
|
2154
2638
|
* the version's join row from the source collection.
|
|
2155
2639
|
*/
|
|
2156
|
-
async
|
|
2157
|
-
const item = this.
|
|
2158
|
-
const fromCollectionId = this.
|
|
2159
|
-
this.
|
|
2640
|
+
async MoveArtifactToCollection(target) {
|
|
2641
|
+
const item = this.ContextMenuItem;
|
|
2642
|
+
const fromCollectionId = this.CurrentCollectionId;
|
|
2643
|
+
this.CloseContextMenu();
|
|
2160
2644
|
if (!item?.artifact || !item.version || !fromCollectionId)
|
|
2161
2645
|
return;
|
|
2162
2646
|
if (UUIDsEqual(target.ID, fromCollectionId))
|
|
@@ -2170,9 +2654,9 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2170
2654
|
ExtraFilter: `CollectionID='${target.ID}' AND ArtifactVersionID='${item.version.ID}'`,
|
|
2171
2655
|
ResultType: 'simple',
|
|
2172
2656
|
Fields: ['ID']
|
|
2173
|
-
}, this.
|
|
2657
|
+
}, this.CurrentUser);
|
|
2174
2658
|
if (!(existing.Success && (existing.Results?.length ?? 0) > 0)) {
|
|
2175
|
-
const junction = await p.GetEntityObject('MJ: Collection Artifacts', this.
|
|
2659
|
+
const junction = await p.GetEntityObject('MJ: Collection Artifacts', this.CurrentUser);
|
|
2176
2660
|
junction.CollectionID = target.ID;
|
|
2177
2661
|
junction.ArtifactVersionID = item.version.ID;
|
|
2178
2662
|
junction.Sequence = 0;
|
|
@@ -2186,7 +2670,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2186
2670
|
EntityName: 'MJ: Collection Artifacts',
|
|
2187
2671
|
ExtraFilter: `CollectionID='${fromCollectionId}' AND ArtifactVersionID='${item.version.ID}'`,
|
|
2188
2672
|
ResultType: 'entity_object'
|
|
2189
|
-
}, this.
|
|
2673
|
+
}, this.CurrentUser);
|
|
2190
2674
|
if (sourceRows.Success && sourceRows.Results) {
|
|
2191
2675
|
for (const row of sourceRows.Results) {
|
|
2192
2676
|
await row.Delete();
|
|
@@ -2194,7 +2678,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2194
2678
|
}
|
|
2195
2679
|
await this.loadArtifacts(true);
|
|
2196
2680
|
await this.loadCollections(true);
|
|
2197
|
-
await this.
|
|
2681
|
+
await this.LoadAllCollections(true);
|
|
2198
2682
|
this.buildUnifiedItemList();
|
|
2199
2683
|
}
|
|
2200
2684
|
catch (error) {
|
|
@@ -2202,10 +2686,14 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2202
2686
|
await this.dialogService.alert('Error', 'Failed to move artifact. Please try again.');
|
|
2203
2687
|
}
|
|
2204
2688
|
}
|
|
2689
|
+
/** @deprecated Use {@link MoveArtifactToCollection}. */
|
|
2690
|
+
async moveArtifactToCollection(target) {
|
|
2691
|
+
return this.MoveArtifactToCollection(target);
|
|
2692
|
+
}
|
|
2205
2693
|
/** Handle context menu action dispatch */
|
|
2206
|
-
|
|
2207
|
-
const item = this.
|
|
2208
|
-
this.
|
|
2694
|
+
OnContextMenuAction(action) {
|
|
2695
|
+
const item = this.ContextMenuItem;
|
|
2696
|
+
this.CloseContextMenu();
|
|
2209
2697
|
if (!item)
|
|
2210
2698
|
return;
|
|
2211
2699
|
switch (action) {
|
|
@@ -2217,22 +2705,22 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2217
2705
|
break;
|
|
2218
2706
|
case 'share':
|
|
2219
2707
|
if (item.collection) {
|
|
2220
|
-
this.
|
|
2708
|
+
this.ShareCollection(item.collection);
|
|
2221
2709
|
}
|
|
2222
2710
|
break;
|
|
2223
2711
|
case 'edit':
|
|
2224
2712
|
if (item.collection) {
|
|
2225
|
-
this.
|
|
2713
|
+
this.EditCollection(item.collection);
|
|
2226
2714
|
}
|
|
2227
2715
|
break;
|
|
2228
2716
|
case 'delete':
|
|
2229
2717
|
if (item.collection) {
|
|
2230
|
-
this.
|
|
2718
|
+
this.DeleteCollection(item.collection);
|
|
2231
2719
|
}
|
|
2232
2720
|
break;
|
|
2233
2721
|
case 'remove':
|
|
2234
2722
|
if (item.artifact && item.version) {
|
|
2235
|
-
this.
|
|
2723
|
+
this.RemoveArtifact({ artifact: item.artifact, version: item.version });
|
|
2236
2724
|
}
|
|
2237
2725
|
break;
|
|
2238
2726
|
case 'openConversation':
|
|
@@ -2242,6 +2730,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2242
2730
|
break;
|
|
2243
2731
|
}
|
|
2244
2732
|
}
|
|
2733
|
+
/** @deprecated Use {@link OnContextMenuAction}. */
|
|
2734
|
+
onContextMenuAction(action) {
|
|
2735
|
+
return this.OnContextMenuAction(action);
|
|
2736
|
+
}
|
|
2245
2737
|
/**
|
|
2246
2738
|
* Resolves the artifact version the user right-clicked to the conversation it was produced in,
|
|
2247
2739
|
* then asks the host to open it. Chain: Artifact Version → Conversation Detail Artifacts
|
|
@@ -2252,7 +2744,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2252
2744
|
return;
|
|
2253
2745
|
const conversationId = await this.resolveArtifactToConversation(item.version.ID);
|
|
2254
2746
|
if (conversationId) {
|
|
2255
|
-
this.
|
|
2747
|
+
this.OpenConversationRequested.emit({ conversationId });
|
|
2256
2748
|
}
|
|
2257
2749
|
else {
|
|
2258
2750
|
await this.dialogService.alert('No Source Conversation', 'This artifact is not linked to a conversation.');
|
|
@@ -2267,7 +2759,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2267
2759
|
ExtraFilter: `ArtifactVersionID='${artifactVersionId}'`,
|
|
2268
2760
|
Fields: ['ConversationDetailID', 'Direction'],
|
|
2269
2761
|
ResultType: 'simple'
|
|
2270
|
-
}, this.
|
|
2762
|
+
}, this.CurrentUser);
|
|
2271
2763
|
const links = linkResult.Success ? (linkResult.Results ?? []) : [];
|
|
2272
2764
|
if (links.length === 0)
|
|
2273
2765
|
return null;
|
|
@@ -2277,25 +2769,25 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2277
2769
|
ExtraFilter: `ID='${link.ConversationDetailID}'`,
|
|
2278
2770
|
Fields: ['ConversationID'],
|
|
2279
2771
|
ResultType: 'simple'
|
|
2280
|
-
}, this.
|
|
2772
|
+
}, this.CurrentUser);
|
|
2281
2773
|
return detailResult.Success ? (detailResult.Results?.[0]?.ConversationID ?? null) : null;
|
|
2282
2774
|
}
|
|
2283
2775
|
/** Close context menu on Escape key */
|
|
2284
2776
|
onEscapeKey() {
|
|
2285
|
-
if (this.
|
|
2286
|
-
this.
|
|
2777
|
+
if (this.ShowContextMenu) {
|
|
2778
|
+
this.CloseContextMenu();
|
|
2287
2779
|
}
|
|
2288
2780
|
}
|
|
2289
2781
|
// ============================================================
|
|
2290
2782
|
// Selection gestures (#4 — frictionless multi-select)
|
|
2291
2783
|
// ============================================================
|
|
2292
2784
|
indexOfItem(id) {
|
|
2293
|
-
return this.
|
|
2785
|
+
return this.UnifiedItems.findIndex(i => i.id === id);
|
|
2294
2786
|
}
|
|
2295
2787
|
/** Re-sync each item's `selected` flag from the set without rebuilding (preserves page). */
|
|
2296
2788
|
refreshSelectionFlags() {
|
|
2297
|
-
for (const it of this.
|
|
2298
|
-
it.selected = this.
|
|
2789
|
+
for (const it of this.UnifiedItems) {
|
|
2790
|
+
it.selected = this.SelectedItems.has(it.id);
|
|
2299
2791
|
}
|
|
2300
2792
|
this.cdr.detectChanges();
|
|
2301
2793
|
}
|
|
@@ -2311,74 +2803,94 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2311
2803
|
const lo = Math.min(this.lastSelectedIndex, idx);
|
|
2312
2804
|
const hi = Math.max(this.lastSelectedIndex, idx);
|
|
2313
2805
|
for (let i = lo; i <= hi; i++) {
|
|
2314
|
-
const it = this.
|
|
2806
|
+
const it = this.UnifiedItems[i];
|
|
2315
2807
|
if (it)
|
|
2316
|
-
this.
|
|
2808
|
+
this.SelectedItems.add(it.id);
|
|
2317
2809
|
}
|
|
2318
2810
|
}
|
|
2319
2811
|
else if (event.metaKey || event.ctrlKey || !plainReplaces) {
|
|
2320
|
-
if (this.
|
|
2321
|
-
this.
|
|
2812
|
+
if (this.SelectedItems.has(item.id)) {
|
|
2813
|
+
this.SelectedItems.delete(item.id);
|
|
2322
2814
|
}
|
|
2323
2815
|
else {
|
|
2324
|
-
this.
|
|
2816
|
+
this.SelectedItems.add(item.id);
|
|
2325
2817
|
}
|
|
2326
2818
|
this.lastSelectedIndex = idx;
|
|
2327
2819
|
}
|
|
2328
2820
|
else {
|
|
2329
|
-
this.
|
|
2330
|
-
this.
|
|
2821
|
+
this.SelectedItems.clear();
|
|
2822
|
+
this.SelectedItems.add(item.id);
|
|
2331
2823
|
this.lastSelectedIndex = idx;
|
|
2332
2824
|
}
|
|
2333
2825
|
this.refreshSelectionFlags();
|
|
2334
2826
|
}
|
|
2335
2827
|
/** Hover-checkbox click — selects without requiring an explicit "select mode". */
|
|
2336
|
-
|
|
2828
|
+
OnCheckboxClick(item, event) {
|
|
2337
2829
|
event.stopPropagation();
|
|
2338
2830
|
this.applySelectionGesture(item, event);
|
|
2339
2831
|
}
|
|
2832
|
+
/** @deprecated Use {@link OnCheckboxClick}. */
|
|
2833
|
+
onCheckboxClick(item, event) {
|
|
2834
|
+
return this.OnCheckboxClick(item, event);
|
|
2835
|
+
}
|
|
2340
2836
|
// ============================================================
|
|
2341
2837
|
// Drag-and-drop (#1, #2 — drag items onto folders / breadcrumbs / navigator)
|
|
2342
2838
|
// ============================================================
|
|
2343
|
-
|
|
2839
|
+
OnItemDragStart(item, event) {
|
|
2344
2840
|
// If the dragged item is part of the current selection, drag the whole selection;
|
|
2345
2841
|
// otherwise drag just this item.
|
|
2346
|
-
this.
|
|
2347
|
-
? Array.from(this.
|
|
2842
|
+
this.DraggedItemIds = (this.SelectedItems.has(item.id) && this.SelectedItems.size > 0)
|
|
2843
|
+
? Array.from(this.SelectedItems)
|
|
2348
2844
|
: [item.id];
|
|
2349
2845
|
if (event.dataTransfer) {
|
|
2350
2846
|
event.dataTransfer.effectAllowed = 'move';
|
|
2351
|
-
event.dataTransfer.setData('text/plain', this.
|
|
2847
|
+
event.dataTransfer.setData('text/plain', this.DraggedItemIds.join(','));
|
|
2352
2848
|
}
|
|
2353
2849
|
}
|
|
2850
|
+
/** @deprecated Use {@link OnItemDragStart}. */
|
|
2851
|
+
onItemDragStart(item, event) {
|
|
2852
|
+
return this.OnItemDragStart(item, event);
|
|
2853
|
+
}
|
|
2854
|
+
OnItemDragEnd() {
|
|
2855
|
+
this.DraggedItemIds = [];
|
|
2856
|
+
this.DragOverTargetId = null;
|
|
2857
|
+
}
|
|
2858
|
+
/** @deprecated Use {@link OnItemDragEnd}. */
|
|
2354
2859
|
onItemDragEnd() {
|
|
2355
|
-
this.
|
|
2356
|
-
this.dragOverTargetId = null;
|
|
2860
|
+
return this.OnItemDragEnd();
|
|
2357
2861
|
}
|
|
2358
2862
|
draggedItems() {
|
|
2359
|
-
return this.
|
|
2863
|
+
return this.UnifiedItems.filter(i => this.DraggedItemIds.includes(i.id));
|
|
2360
2864
|
}
|
|
2361
2865
|
/** Folder grid card / list row as a drop target. */
|
|
2362
|
-
|
|
2866
|
+
OnFolderItemDragOver(folderItem, event) {
|
|
2363
2867
|
const targetId = folderItem.collection?.ID;
|
|
2364
|
-
if (this.
|
|
2868
|
+
if (this.DraggedItemIds.length === 0 || this.DraggedItemIds.includes(folderItem.id))
|
|
2365
2869
|
return;
|
|
2366
2870
|
if (!this.canDropOnCollection(targetId))
|
|
2367
2871
|
return;
|
|
2368
2872
|
event.preventDefault();
|
|
2369
2873
|
if (event.dataTransfer)
|
|
2370
2874
|
event.dataTransfer.dropEffect = 'move';
|
|
2371
|
-
this.
|
|
2875
|
+
this.DragOverTargetId = folderItem.id;
|
|
2372
2876
|
}
|
|
2373
|
-
|
|
2877
|
+
/** @deprecated Use {@link OnFolderItemDragOver}. */
|
|
2878
|
+
onFolderItemDragOver(folderItem, event) {
|
|
2879
|
+
return this.OnFolderItemDragOver(folderItem, event);
|
|
2880
|
+
}
|
|
2881
|
+
OnFolderItemDrop(folderItem, event) {
|
|
2374
2882
|
event.preventDefault();
|
|
2375
2883
|
const targetId = folderItem.collection?.ID ?? null;
|
|
2376
|
-
this.
|
|
2884
|
+
this.DragOverTargetId = null;
|
|
2377
2885
|
void this.moveDraggedItemsTo(targetId);
|
|
2378
2886
|
}
|
|
2887
|
+
/** @deprecated Use {@link OnFolderItemDrop}. */
|
|
2888
|
+
onFolderItemDrop(folderItem, event) {
|
|
2889
|
+
return this.OnFolderItemDrop(folderItem, event);
|
|
2890
|
+
}
|
|
2379
2891
|
/** Breadcrumb crumb / Home root as a drop target. crumbId null = top level. */
|
|
2380
|
-
|
|
2381
|
-
if (this.
|
|
2892
|
+
OnCrumbDragOver(crumbId, event) {
|
|
2893
|
+
if (this.DraggedItemIds.length === 0)
|
|
2382
2894
|
return;
|
|
2383
2895
|
// Artifacts can't live at the top level (no collection)
|
|
2384
2896
|
if (crumbId === null && this.draggedItems().some(i => i.type === 'artifact'))
|
|
@@ -2388,13 +2900,21 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2388
2900
|
event.preventDefault();
|
|
2389
2901
|
if (event.dataTransfer)
|
|
2390
2902
|
event.dataTransfer.dropEffect = 'move';
|
|
2391
|
-
this.
|
|
2903
|
+
this.DragOverTargetId = crumbId === null ? 'root' : 'crumb:' + crumbId;
|
|
2392
2904
|
}
|
|
2393
|
-
|
|
2905
|
+
/** @deprecated Use {@link OnCrumbDragOver}. */
|
|
2906
|
+
onCrumbDragOver(crumbId, event) {
|
|
2907
|
+
return this.OnCrumbDragOver(crumbId, event);
|
|
2908
|
+
}
|
|
2909
|
+
OnCrumbDrop(crumbId, event) {
|
|
2394
2910
|
event.preventDefault();
|
|
2395
|
-
this.
|
|
2911
|
+
this.DragOverTargetId = null;
|
|
2396
2912
|
void this.moveDraggedItemsTo(crumbId);
|
|
2397
2913
|
}
|
|
2914
|
+
/** @deprecated Use {@link OnCrumbDrop}. */
|
|
2915
|
+
onCrumbDrop(crumbId, event) {
|
|
2916
|
+
return this.OnCrumbDrop(crumbId, event);
|
|
2917
|
+
}
|
|
2398
2918
|
/** True when the dragged set may be dropped on the target collection (blocks folder cycles). */
|
|
2399
2919
|
canDropOnCollection(targetCollectionId) {
|
|
2400
2920
|
if (targetCollectionId === undefined)
|
|
@@ -2425,8 +2945,8 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2425
2945
|
}
|
|
2426
2946
|
async moveDraggedItemsTo(targetCollectionId) {
|
|
2427
2947
|
const items = this.draggedItems();
|
|
2428
|
-
this.
|
|
2429
|
-
await this.moveItemsTo(items, targetCollectionId, this.
|
|
2948
|
+
this.DraggedItemIds = [];
|
|
2949
|
+
await this.moveItemsTo(items, targetCollectionId, this.CurrentCollectionId);
|
|
2430
2950
|
}
|
|
2431
2951
|
// ============================================================
|
|
2432
2952
|
// Move primitives (shared by drag, bulk move, and shelf)
|
|
@@ -2460,10 +2980,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2460
2980
|
await this.reparentCollection(fid, targetCollectionId);
|
|
2461
2981
|
}
|
|
2462
2982
|
}
|
|
2463
|
-
this.
|
|
2983
|
+
this.ClearSelection();
|
|
2464
2984
|
await this.loadCollections(true);
|
|
2465
2985
|
await this.loadArtifacts(true);
|
|
2466
|
-
await this.
|
|
2986
|
+
await this.LoadAllCollections(true);
|
|
2467
2987
|
this.buildUnifiedItemList();
|
|
2468
2988
|
}
|
|
2469
2989
|
catch (error) {
|
|
@@ -2477,10 +2997,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2477
2997
|
ExtraFilter: `CollectionID='${collectionId}' AND ArtifactVersionID='${versionId}'`,
|
|
2478
2998
|
ResultType: 'simple',
|
|
2479
2999
|
Fields: ['ID']
|
|
2480
|
-
}, this.
|
|
3000
|
+
}, this.CurrentUser);
|
|
2481
3001
|
if (existing.Success && (existing.Results?.length ?? 0) > 0)
|
|
2482
3002
|
return;
|
|
2483
|
-
const junction = await p.GetEntityObject('MJ: Collection Artifacts', this.
|
|
3003
|
+
const junction = await p.GetEntityObject('MJ: Collection Artifacts', this.CurrentUser);
|
|
2484
3004
|
junction.CollectionID = collectionId;
|
|
2485
3005
|
junction.ArtifactVersionID = versionId;
|
|
2486
3006
|
junction.Sequence = 0;
|
|
@@ -2493,7 +3013,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2493
3013
|
EntityName: 'MJ: Collection Artifacts',
|
|
2494
3014
|
ExtraFilter: `CollectionID='${collectionId}' AND ArtifactVersionID='${versionId}'`,
|
|
2495
3015
|
ResultType: 'entity_object'
|
|
2496
|
-
}, this.
|
|
3016
|
+
}, this.CurrentUser);
|
|
2497
3017
|
if (rows.Success && rows.Results) {
|
|
2498
3018
|
for (const row of rows.Results)
|
|
2499
3019
|
await row.Delete();
|
|
@@ -2501,7 +3021,7 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2501
3021
|
}
|
|
2502
3022
|
async reparentCollection(collectionId, newParentId) {
|
|
2503
3023
|
const p = this.ProviderToUse;
|
|
2504
|
-
const collection = await p.GetEntityObject('MJ: Collections', this.
|
|
3024
|
+
const collection = await p.GetEntityObject('MJ: Collections', this.CurrentUser);
|
|
2505
3025
|
await collection.Load(collectionId);
|
|
2506
3026
|
collection.ParentID = newParentId;
|
|
2507
3027
|
const ok = await collection.Save();
|
|
@@ -2511,13 +3031,13 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2511
3031
|
// ============================================================
|
|
2512
3032
|
// All-collections cache (navigator + cycle checks + bulk move)
|
|
2513
3033
|
// ============================================================
|
|
2514
|
-
async
|
|
3034
|
+
async LoadAllCollections(bypassCache = false) {
|
|
2515
3035
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2516
|
-
const ownerFilter = `OwnerID='${this.
|
|
3036
|
+
const ownerFilter = `OwnerID='${this.CurrentUser.ID}'`;
|
|
2517
3037
|
const permissionSubquery = `ID IN (
|
|
2518
|
-
SELECT CollectionID FROM [__mj].[vwCollectionPermissions] WHERE UserID='${this.
|
|
3038
|
+
SELECT CollectionID FROM [__mj].[vwCollectionPermissions] WHERE UserID='${this.CurrentUser.ID}'
|
|
2519
3039
|
)`;
|
|
2520
|
-
const filter = `EnvironmentID='${this.
|
|
3040
|
+
const filter = `EnvironmentID='${this.EnvironmentId}' AND (OwnerID IS NULL OR ${ownerFilter} OR ${permissionSubquery})`;
|
|
2521
3041
|
const result = await rv.RunView({
|
|
2522
3042
|
EntityName: 'MJ: Collections',
|
|
2523
3043
|
ExtraFilter: filter,
|
|
@@ -2525,87 +3045,139 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2525
3045
|
MaxRows: 1000,
|
|
2526
3046
|
ResultType: 'entity_object',
|
|
2527
3047
|
BypassCache: bypassCache
|
|
2528
|
-
}, this.
|
|
2529
|
-
this.
|
|
2530
|
-
this.allCollectionsById = new Map(this.
|
|
2531
|
-
this.
|
|
3048
|
+
}, this.CurrentUser);
|
|
3049
|
+
this.AllCollections = result.Success ? (result.Results || []) : [];
|
|
3050
|
+
this.allCollectionsById = new Map(this.AllCollections.map(c => [NormalizeUUID(c.ID), c]));
|
|
3051
|
+
this.NavigatorNodes = this.flattenCollectionTree(this.AllCollections);
|
|
2532
3052
|
this.cdr.detectChanges();
|
|
2533
3053
|
}
|
|
3054
|
+
/** @deprecated Use {@link LoadAllCollections}. */
|
|
3055
|
+
async loadAllCollections(bypassCache = false) {
|
|
3056
|
+
return this.LoadAllCollections(bypassCache);
|
|
3057
|
+
}
|
|
3058
|
+
ToggleNavigator() {
|
|
3059
|
+
this.ShowNavigator = !this.ShowNavigator;
|
|
3060
|
+
}
|
|
3061
|
+
/** @deprecated Use {@link ToggleNavigator}. */
|
|
2534
3062
|
toggleNavigator() {
|
|
2535
|
-
|
|
3063
|
+
return this.ToggleNavigator();
|
|
3064
|
+
}
|
|
3065
|
+
NavigatorClick(collection) {
|
|
3066
|
+
void this.NavigateToCollectionById(collection.ID);
|
|
2536
3067
|
}
|
|
3068
|
+
/** @deprecated Use {@link NavigatorClick}. */
|
|
2537
3069
|
navigatorClick(collection) {
|
|
2538
|
-
|
|
3070
|
+
return this.NavigatorClick(collection);
|
|
3071
|
+
}
|
|
3072
|
+
IsCurrentNavigator(collection) {
|
|
3073
|
+
return !!this.CurrentCollectionId && UUIDsEqual(collection.ID, this.CurrentCollectionId);
|
|
2539
3074
|
}
|
|
3075
|
+
/** @deprecated Use {@link IsCurrentNavigator}. */
|
|
2540
3076
|
isCurrentNavigator(collection) {
|
|
2541
|
-
return
|
|
3077
|
+
return this.IsCurrentNavigator(collection);
|
|
2542
3078
|
}
|
|
2543
|
-
|
|
2544
|
-
if (this.
|
|
3079
|
+
OnNavigatorDragOver(collection, event) {
|
|
3080
|
+
if (this.DraggedItemIds.length === 0 || this.DraggedItemIds.some(id => UUIDsEqual(id, collection.ID)))
|
|
2545
3081
|
return;
|
|
2546
3082
|
if (!this.canDropOnCollection(collection.ID))
|
|
2547
3083
|
return;
|
|
2548
3084
|
event.preventDefault();
|
|
2549
3085
|
if (event.dataTransfer)
|
|
2550
3086
|
event.dataTransfer.dropEffect = 'move';
|
|
2551
|
-
this.
|
|
3087
|
+
this.DragOverTargetId = 'nav:' + collection.ID;
|
|
2552
3088
|
}
|
|
2553
|
-
|
|
3089
|
+
/** @deprecated Use {@link OnNavigatorDragOver}. */
|
|
3090
|
+
onNavigatorDragOver(collection, event) {
|
|
3091
|
+
return this.OnNavigatorDragOver(collection, event);
|
|
3092
|
+
}
|
|
3093
|
+
OnNavigatorDrop(collection, event) {
|
|
2554
3094
|
event.preventDefault();
|
|
2555
|
-
this.
|
|
3095
|
+
this.DragOverTargetId = null;
|
|
2556
3096
|
void this.moveDraggedItemsTo(collection.ID);
|
|
2557
3097
|
}
|
|
3098
|
+
/** @deprecated Use {@link OnNavigatorDrop}. */
|
|
3099
|
+
onNavigatorDrop(collection, event) {
|
|
3100
|
+
return this.OnNavigatorDrop(collection, event);
|
|
3101
|
+
}
|
|
3102
|
+
OnDragLeave(tag) {
|
|
3103
|
+
if (this.DragOverTargetId === tag)
|
|
3104
|
+
this.DragOverTargetId = null;
|
|
3105
|
+
}
|
|
3106
|
+
/** @deprecated Use {@link OnDragLeave}. */
|
|
2558
3107
|
onDragLeave(tag) {
|
|
2559
|
-
|
|
2560
|
-
this.dragOverTargetId = null;
|
|
3108
|
+
return this.OnDragLeave(tag);
|
|
2561
3109
|
}
|
|
2562
3110
|
// ============================================================
|
|
2563
3111
|
// Bulk "Move to…" (#3)
|
|
2564
3112
|
// ============================================================
|
|
2565
|
-
|
|
3113
|
+
OpenBulkMove(event) {
|
|
2566
3114
|
event.stopPropagation();
|
|
2567
|
-
if (this.
|
|
2568
|
-
void this.
|
|
2569
|
-
this.
|
|
3115
|
+
if (this.NavigatorNodes.length === 0)
|
|
3116
|
+
void this.LoadAllCollections();
|
|
3117
|
+
this.ShowBulkMovePopover = true;
|
|
3118
|
+
}
|
|
3119
|
+
/** @deprecated Use {@link OpenBulkMove}. */
|
|
3120
|
+
openBulkMove(event) {
|
|
3121
|
+
return this.OpenBulkMove(event);
|
|
2570
3122
|
}
|
|
3123
|
+
CloseBulkMove() {
|
|
3124
|
+
this.ShowBulkMovePopover = false;
|
|
3125
|
+
}
|
|
3126
|
+
/** @deprecated Use {@link CloseBulkMove}. */
|
|
2571
3127
|
closeBulkMove() {
|
|
2572
|
-
this.
|
|
3128
|
+
return this.CloseBulkMove();
|
|
3129
|
+
}
|
|
3130
|
+
async BulkMoveTo(collection) {
|
|
3131
|
+
const items = this.UnifiedItems.filter(i => this.SelectedItems.has(i.id));
|
|
3132
|
+
this.ShowBulkMovePopover = false;
|
|
3133
|
+
await this.moveItemsTo(items, collection.ID, this.CurrentCollectionId);
|
|
2573
3134
|
}
|
|
3135
|
+
/** @deprecated Use {@link BulkMoveTo}. */
|
|
2574
3136
|
async bulkMoveTo(collection) {
|
|
2575
|
-
|
|
2576
|
-
this.showBulkMovePopover = false;
|
|
2577
|
-
await this.moveItemsTo(items, collection.ID, this.currentCollectionId);
|
|
3137
|
+
return this.BulkMoveTo(collection);
|
|
2578
3138
|
}
|
|
2579
3139
|
// ============================================================
|
|
2580
3140
|
// Staging shelf (#5)
|
|
2581
3141
|
// ============================================================
|
|
2582
|
-
|
|
2583
|
-
const items = this.
|
|
3142
|
+
StageSelected() {
|
|
3143
|
+
const items = this.UnifiedItems.filter(i => this.SelectedItems.has(i.id));
|
|
2584
3144
|
for (const it of items) {
|
|
2585
|
-
if (!this.
|
|
2586
|
-
this.
|
|
3145
|
+
if (!this.Shelf.some(s => s.item.id === it.id)) {
|
|
3146
|
+
this.Shelf.push({ item: it, sourceCollectionId: this.CurrentCollectionId });
|
|
2587
3147
|
}
|
|
2588
3148
|
}
|
|
2589
|
-
this.
|
|
3149
|
+
this.ClearSelection();
|
|
2590
3150
|
this.cdr.detectChanges();
|
|
2591
3151
|
}
|
|
3152
|
+
/** @deprecated Use {@link StageSelected}. */
|
|
3153
|
+
stageSelected() {
|
|
3154
|
+
return this.StageSelected();
|
|
3155
|
+
}
|
|
3156
|
+
RemoveFromShelf(id) {
|
|
3157
|
+
this.Shelf = this.Shelf.filter(s => s.item.id !== id);
|
|
3158
|
+
this.cdr.detectChanges();
|
|
3159
|
+
}
|
|
3160
|
+
/** @deprecated Use {@link RemoveFromShelf}. */
|
|
2592
3161
|
removeFromShelf(id) {
|
|
2593
|
-
|
|
3162
|
+
return this.RemoveFromShelf(id);
|
|
3163
|
+
}
|
|
3164
|
+
ClearShelf() {
|
|
3165
|
+
this.Shelf = [];
|
|
2594
3166
|
this.cdr.detectChanges();
|
|
2595
3167
|
}
|
|
3168
|
+
/** @deprecated Use {@link ClearShelf}. */
|
|
2596
3169
|
clearShelf() {
|
|
2597
|
-
this.
|
|
2598
|
-
this.cdr.detectChanges();
|
|
3170
|
+
return this.ClearShelf();
|
|
2599
3171
|
}
|
|
2600
3172
|
/** Moves all staged items into the currently-open collection. */
|
|
2601
|
-
async
|
|
2602
|
-
if (this.
|
|
3173
|
+
async DropShelfHere() {
|
|
3174
|
+
if (this.Shelf.length === 0 || !this.CurrentCollectionId)
|
|
2603
3175
|
return;
|
|
2604
|
-
const target = this.
|
|
3176
|
+
const target = this.CurrentCollectionId;
|
|
2605
3177
|
try {
|
|
2606
3178
|
const p = this.ProviderToUse;
|
|
2607
3179
|
const rv = RunView.FromMetadataProvider(p);
|
|
2608
|
-
for (const entry of this.
|
|
3180
|
+
for (const entry of this.Shelf) {
|
|
2609
3181
|
const it = entry.item;
|
|
2610
3182
|
if (it.type === 'artifact' && it.version) {
|
|
2611
3183
|
if (entry.sourceCollectionId && UUIDsEqual(entry.sourceCollectionId, target))
|
|
@@ -2622,10 +3194,10 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2622
3194
|
await this.reparentCollection(fid, target);
|
|
2623
3195
|
}
|
|
2624
3196
|
}
|
|
2625
|
-
this.
|
|
3197
|
+
this.Shelf = [];
|
|
2626
3198
|
await this.loadCollections(true);
|
|
2627
3199
|
await this.loadArtifacts(true);
|
|
2628
|
-
await this.
|
|
3200
|
+
await this.LoadAllCollections(true);
|
|
2629
3201
|
this.buildUnifiedItemList();
|
|
2630
3202
|
}
|
|
2631
3203
|
catch (error) {
|
|
@@ -2633,10 +3205,14 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
2633
3205
|
await this.dialogService.alert('Error', 'Failed to move staged items. Please try again.');
|
|
2634
3206
|
}
|
|
2635
3207
|
}
|
|
3208
|
+
/** @deprecated Use {@link DropShelfHere}. */
|
|
3209
|
+
async dropShelfHere() {
|
|
3210
|
+
return this.DropShelfHere();
|
|
3211
|
+
}
|
|
2636
3212
|
static ɵfac = function CollectionsFullViewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CollectionsFullViewComponent)(i0.ɵɵdirectiveInject(i1.DialogService), i0.ɵɵdirectiveInject(i2.ArtifactStateService), i0.ɵɵdirectiveInject(i3.CollectionStateService), i0.ɵɵdirectiveInject(i4.CollectionPermissionService), i0.ɵɵdirectiveInject(i5.ArtifactIconService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
2637
3213
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CollectionsFullViewComponent, selectors: [["mj-collections-full-view"]], hostBindings: function CollectionsFullViewComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
2638
3214
|
i0.ɵɵlistener("keydown.escape", function CollectionsFullViewComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, i0.ɵɵresolveDocument);
|
|
2639
|
-
} }, inputs: { environmentId: "environmentId", currentUser: "currentUser" }, outputs: { collectionNavigated: "collectionNavigated", openConversationRequested: "openConversationRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 37, vars: 36, consts: [[1, "collections-view", 3, "keydown"], [1, "collections-header"], [1, "collections-breadcrumb"], ["title", "Toggle collections panel", 1, "btn-icon", "nav-toggle", 3, "click"], [1, "fas", "fa-bars"], [1, "breadcrumb-item", 3, "dragover", "dragleave", "drop"], [1, "fas", "fa-home"], [1, "breadcrumb-link", 3, "click"], [1, "breadcrumb-path"], [1, "collections-actions"], [1, "btn-icon", 3, "click", "title"], [1, "fas", 3, "ngClass"], [1, "fas", "fa-check-square"], [1, "dropdown-container"], [1, "search-container"], [1, "fas", "fa-search"], ["type", "text", "placeholder", "Search...", 1, "search-input", 3, "ngModelChange", "ngModel"], ["title", "Clear search", 1, "search-clear"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fas", "fa-sync"], [1, "selection-toolbar"], [1, "collections-body"], [1, "collections-navigator"], [1, "collections-content"], [1, "loading-state"], ["Icon", "fa-solid fa-folder-open", "ActionIcon", "fa-solid fa-plus", 3, "Variant", "Title", "Message", "ActionText"], [1, "staging-shelf"], [3, "saved", "cancelled", "isOpen", "collection", "parentCollection", "environmentId", "currentUser"], [3, "saved", "cancelled", "isOpen", "collectionId", "environmentId", "currentUser"], [3, "saved", "cancelled", "isOpen", "collection", "currentUser", "currentUserPermissions"], [1, "fas", "fa-chevron-right", "breadcrumb-separator"], [1, "breadcrumb-link", 3, "dragover", "dragleave", "drop", "click"], ["title", "Sort options", 1, "btn-icon", 3, "click"], [1, "fas", "fa-sort"], [1, "dropdown-menu"], [1, "dropdown-item", 3, "click"], [1, "fas", "fa-sort-alpha-down"], [1, "fas", "fa-calendar"], [1, "fas", "fa-tag"], ["title", "Clear search", 1, "search-clear", 3, "click"], [1, "fas", "fa-times"], [1, "toolbar-separator"], [1, "toolbar-actions-group"], [1, "btn-icon", 3, "title"], [1, "btn-icon", "btn-icon-danger", 3, "title"], [1, "fas", "fa-share-nodes"], [1, "fas", "fa-pen-to-square"], [1, "btn-icon", "btn-icon-danger", 3, "click", "title"], [1, "fas", "fa-trash"], [1, "btn-primary", 3, "click"], [1, "fas", "fa-plus"], [1, "fas", "fa-chevron-down"], [1, "dropdown-menu", "dropdown-menu-right"], [1, "fas", "fa-folder-plus"], [1, "dropdown-item", 3, "click", "disabled"], [1, "fas", "fa-file-plus"], [1, "selection-info"], [1, "selection-count"], [1, "selection-actions"], [1, "btn-toolbar", 3, "click"], [1, "fas", "fa-folder-tree"], ["title", "Add to the staging shelf to move later", 1, "btn-toolbar", 3, "click"], [1, "fas", "fa-layer-group"], [1, "btn-toolbar", "btn-danger", 3, "click"], [1, "bulk-move-backdrop", 3, "click"], [1, "dropdown-menu", "bulk-move-menu"], [1, "dropdown-note"], [1, "dropdown-item", 3, "paddingLeft"], [1, "fas", "fa-folder"], [1, "nav-header"], [1, "nav-list"], [1, "nav-row", 3, "click", "dragover", "dragleave", "drop"], [1, "nav-row", 3, "active", "drag-over", "paddingLeft", "title"], [1, "nav-row", 3, "click", "dragover", "dragleave", "drop", "title"], [1, "nav-row-name"], ["text", "Loading collections...", "size", "large"], ["Icon", "fa-solid fa-folder-open", "ActionIcon", "fa-solid fa-plus", 3, "Action", "Variant", "Title", "Message", "ActionText"], [1, "empty-collection-hint"], [1, "unified-grid"], [1, "grid-item", 3, "selected", "active", "dragging", "drag-over", "draggable"], [1, "pagination-bar"], [1, "grid-item", 3, "dragstart", "dragend", "dragover", "dragleave", "drop", "click", "dblclick", "contextmenu", "draggable"], [1, "item-checkbox", 3, "click"], [1, "grid-item-content", 3, "title"], [1, "grid-icon", "folder-icon"], ["title", "Shared", 1, "shared-badge"], [1, "grid-info"], [1, "grid-name"], [1, "grid-description"], [1, "grid-meta"], [1, "grid-owner"], [1, "fas", "fa-users"], [1, "fas", "fa-user"], [1, "grid-icon", "artifact-icon"], [1, "version-badge"], [1, "artifact-type-badge"], [1, "pagination-info"], [1, "pagination-controls"], ["title", "First page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-angles-left"], ["title", "Previous page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-chevron-left"], [1, "pagination-page-info"], ["title", "Next page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-chevron-right"], ["title", "Last page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-angles-right"], [1, "unified-list"], [1, "list-table"], [1, "col-checkbox"], [1, "fas", 3, "click", "ngClass"], [1, "col-name", "sortable", 3, "click"], [1, "col-type", "sortable", 3, "click"], [1, "col-modified", "sortable", 3, "click"], [1, "col-owner"], [1, "list-item", 3, "selected", "active", "dragging", "drag-over", "draggable"], [1, "list-item", 3, "dragstart", "dragend", "dragover", "dragleave", "drop", "click", "dblclick", "contextmenu", "draggable"], [1, "col-name"], [1, "list-name-cell"], ["title", "Shared", 1, "shared-indicator"], [1, "col-type"], [1, "col-modified"], [1, "shelf-info"], [1, "shelf-chips"], [1, "shelf-chip", 3, "title"], [1, "shelf-actions"], [1, "btn-toolbar", "btn-primary-toolbar", 3, "click", "disabled", "title"], [1, "fas", "fa-arrow-down"], [1, "shelf-chip-name"], ["title", "Remove", 1, "shelf-chip-x", 3, "click"], [1, "context-menu-backdrop", 3, "click"], [1, "context-menu"], [1, "context-menu-item", 3, "click"], [1, "fas", "fa-folder-open"], [1, "context-menu-divider"], [1, "context-menu-item"], [1, "context-menu-item", "context-menu-danger", 3, "click"], [1, "context-menu-note"], [1, "move-target-list"], [1, "fas", "fa-spinner", "fa-spin"], [1, "context-menu-item", 3, "paddingLeft"], [1, "fas", "fa-eye"], [1, "fas", "fa-comments"], [1, "fas", "fa-chevron-right", "submenu-arrow"], [1, "fas", "fa-times-circle"]], template: function CollectionsFullViewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
3215
|
+
} }, inputs: { EnvironmentId: "EnvironmentId", environmentId: "environmentId", CurrentUser: "CurrentUser", currentUser: "currentUser" }, outputs: { CollectionNavigated: "CollectionNavigated", collectionNavigated: "collectionNavigated", OpenConversationRequested: "OpenConversationRequested", openConversationRequested: "openConversationRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 37, vars: 36, consts: [[1, "collections-view", 3, "keydown"], [1, "collections-header"], [1, "collections-breadcrumb"], ["title", "Toggle collections panel", 1, "btn-icon", "nav-toggle", 3, "click"], [1, "fas", "fa-bars"], [1, "breadcrumb-item", 3, "dragover", "dragleave", "drop"], [1, "fas", "fa-home"], [1, "breadcrumb-link", 3, "click"], [1, "breadcrumb-path"], [1, "collections-actions"], [1, "btn-icon", 3, "click", "title"], [1, "fas", 3, "ngClass"], [1, "fas", "fa-check-square"], [1, "dropdown-container"], [1, "search-container"], [1, "fas", "fa-search"], ["type", "text", "placeholder", "Search...", 1, "search-input", 3, "ngModelChange", "ngModel"], ["title", "Clear search", 1, "search-clear"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fas", "fa-sync"], [1, "selection-toolbar"], [1, "collections-body"], [1, "collections-navigator"], [1, "collections-content"], [1, "loading-state"], ["Icon", "fa-solid fa-folder-open", "ActionIcon", "fa-solid fa-plus", 3, "Variant", "Title", "Message", "ActionText"], [1, "staging-shelf"], [3, "saved", "cancelled", "isOpen", "collection", "parentCollection", "environmentId", "currentUser"], [3, "saved", "cancelled", "isOpen", "collectionId", "environmentId", "currentUser"], [3, "saved", "cancelled", "isOpen", "collection", "currentUser", "currentUserPermissions"], [1, "fas", "fa-chevron-right", "breadcrumb-separator"], [1, "breadcrumb-link", 3, "dragover", "dragleave", "drop", "click"], ["title", "Sort options", 1, "btn-icon", 3, "click"], [1, "fas", "fa-sort"], [1, "dropdown-menu"], [1, "dropdown-item", 3, "click"], [1, "fas", "fa-sort-alpha-down"], [1, "fas", "fa-calendar"], [1, "fas", "fa-tag"], ["title", "Clear search", 1, "search-clear", 3, "click"], [1, "fas", "fa-times"], [1, "toolbar-separator"], [1, "toolbar-actions-group"], [1, "btn-icon", 3, "title"], [1, "btn-icon", "btn-icon-danger", 3, "title"], [1, "fas", "fa-share-nodes"], [1, "fas", "fa-pen-to-square"], [1, "btn-icon", "btn-icon-danger", 3, "click", "title"], [1, "fas", "fa-trash"], [1, "btn-primary", 3, "click"], [1, "fas", "fa-plus"], [1, "fas", "fa-chevron-down"], [1, "dropdown-menu", "dropdown-menu-right"], [1, "fas", "fa-folder-plus"], [1, "dropdown-item", 3, "click", "disabled"], [1, "fas", "fa-file-plus"], [1, "selection-info"], [1, "selection-count"], [1, "selection-actions"], [1, "btn-toolbar", 3, "click"], [1, "fas", "fa-folder-tree"], ["title", "Add to the staging shelf to move later", 1, "btn-toolbar", 3, "click"], [1, "fas", "fa-layer-group"], [1, "btn-toolbar", "btn-danger", 3, "click"], [1, "bulk-move-backdrop", 3, "click"], [1, "dropdown-menu", "bulk-move-menu"], [1, "dropdown-note"], [1, "dropdown-item", 3, "paddingLeft"], [1, "fas", "fa-folder"], [1, "nav-header"], [1, "nav-list"], [1, "nav-row", 3, "click", "dragover", "dragleave", "drop"], [1, "nav-row", 3, "active", "drag-over", "paddingLeft", "title"], [1, "nav-row", 3, "click", "dragover", "dragleave", "drop", "title"], [1, "nav-row-name"], ["text", "Loading collections...", "size", "large"], ["Icon", "fa-solid fa-folder-open", "ActionIcon", "fa-solid fa-plus", 3, "Action", "Variant", "Title", "Message", "ActionText"], [1, "empty-collection-hint"], [1, "unified-grid"], [1, "grid-item", 3, "selected", "active", "dragging", "drag-over", "draggable"], [1, "pagination-bar"], [1, "grid-item", 3, "dragstart", "dragend", "dragover", "dragleave", "drop", "click", "dblclick", "contextmenu", "draggable"], [1, "item-checkbox", 3, "click"], [1, "grid-item-content", 3, "title"], [1, "grid-icon", "folder-icon"], ["title", "Shared", 1, "shared-badge"], [1, "grid-info"], [1, "grid-name"], [1, "grid-description"], [1, "grid-meta"], [1, "grid-owner"], [1, "fas", "fa-users"], [1, "fas", "fa-user"], [1, "grid-icon", "artifact-icon"], [1, "version-badge"], [1, "artifact-type-badge"], [1, "pagination-info"], [1, "pagination-controls"], ["title", "First page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-angles-left"], ["title", "Previous page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-chevron-left"], [1, "pagination-page-info"], ["title", "Next page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-chevron-right"], ["title", "Last page", 1, "pagination-btn", 3, "click", "disabled"], [1, "fas", "fa-angles-right"], [1, "unified-list"], [1, "list-table"], [1, "col-checkbox"], [1, "fas", 3, "click", "ngClass"], [1, "col-name", "sortable", 3, "click"], [1, "col-type", "sortable", 3, "click"], [1, "col-modified", "sortable", 3, "click"], [1, "col-owner"], [1, "list-item", 3, "selected", "active", "dragging", "drag-over", "draggable"], [1, "list-item", 3, "dragstart", "dragend", "dragover", "dragleave", "drop", "click", "dblclick", "contextmenu", "draggable"], [1, "col-name"], [1, "list-name-cell"], ["title", "Shared", 1, "shared-indicator"], [1, "col-type"], [1, "col-modified"], [1, "shelf-info"], [1, "shelf-chips"], [1, "shelf-chip", 3, "title"], [1, "shelf-actions"], [1, "btn-toolbar", "btn-primary-toolbar", 3, "click", "disabled", "title"], [1, "fas", "fa-arrow-down"], [1, "shelf-chip-name"], ["title", "Remove", 1, "shelf-chip-x", 3, "click"], [1, "context-menu-backdrop", 3, "click"], [1, "context-menu"], [1, "context-menu-item", 3, "click"], [1, "fas", "fa-folder-open"], [1, "context-menu-divider"], [1, "context-menu-item"], [1, "context-menu-item", "context-menu-danger", 3, "click"], [1, "context-menu-note"], [1, "move-target-list"], [1, "fas", "fa-spinner", "fa-spin"], [1, "context-menu-item", 3, "paddingLeft"], [1, "fas", "fa-eye"], [1, "fas", "fa-comments"], [1, "fas", "fa-chevron-right", "submenu-arrow"], [1, "fas", "fa-times-circle"]], template: function CollectionsFullViewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2640
3216
|
i0.ɵɵelementStart(0, "div", 0);
|
|
2641
3217
|
i0.ɵɵlistener("keydown", function CollectionsFullViewComponent_Template_div_keydown_0_listener($event) { return ctx.handleKeyboardShortcut($event); });
|
|
2642
3218
|
i0.ɵɵelementStart(1, "div", 1)(2, "div", 2)(3, "button", 3);
|
|
@@ -3441,12 +4017,20 @@ export class CollectionsFullViewComponent extends BaseAngularComponent {
|
|
|
3441
4017
|
(cancelled)="onShareModalCancelled()">
|
|
3442
4018
|
</mj-collection-share-modal>
|
|
3443
4019
|
`, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n }\n\n /* Main container */\n .collections-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n position: relative;\n }\n\n /* Header */\n .collections-header {\n display: flex;\n align-items: center;\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n gap: 16px;\n background: var(--mj-bg-surface);\n }\n\n .collections-breadcrumb {\n display: flex;\n align-items: center;\n gap: 6px;\n flex: 1;\n min-width: 0;\n }\n\n .breadcrumb-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .breadcrumb-item i {\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .breadcrumb-link {\n color: var(--mj-text-primary);\n font-weight: 500;\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n transition: color 150ms ease;\n font-size: 14px;\n }\n\n .breadcrumb-link:hover {\n color: var(--mj-brand-primary);\n }\n\n .breadcrumb-link.active {\n color: var(--mj-text-muted);\n cursor: default;\n }\n\n .breadcrumb-path {\n display: flex;\n align-items: center;\n gap: 6px;\n overflow-x: auto;\n }\n\n .breadcrumb-separator {\n color: var(--mj-border-strong);\n font-size: 10px;\n }\n\n .collections-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n /* Button styles */\n .btn-primary {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 6px;\n color: var(--mj-text-inverse);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 150ms ease;\n }\n\n .btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n }\n\n .btn-primary i.fa-chevron-down {\n font-size: 10px;\n margin-left: 2px;\n }\n\n .btn-icon {\n padding: 6px 10px;\n background: transparent;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 150ms ease;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .btn-icon:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n border-color: var(--mj-text-disabled);\n }\n\n .btn-icon.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n\n .btn-icon.active:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n }\n\n /* Dropdown menus */\n .dropdown-container {\n position: relative;\n }\n\n .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n min-width: 200px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n padding: 4px;\n z-index: 1000;\n }\n\n .dropdown-menu-right {\n left: auto;\n right: 0;\n }\n\n .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 12px;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n transition: background 100ms ease;\n }\n\n .dropdown-item:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n }\n\n .dropdown-item:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .dropdown-item.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .dropdown-item i {\n font-size: 14px;\n width: 16px;\n text-align: center;\n color: var(--mj-text-muted);\n }\n\n .dropdown-item.active i {\n color: var(--mj-brand-primary);\n }\n\n .dropdown-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n }\n\n /* Search */\n .search-container {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 200px;\n }\n\n .search-container i.fa-search {\n position: absolute;\n left: 10px;\n color: var(--mj-text-disabled);\n font-size: 13px;\n pointer-events: none;\n }\n\n .search-input {\n width: 100%;\n padding: 6px 32px 6px 32px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n font-size: 13px;\n outline: none;\n transition: all 150ms ease;\n }\n\n .search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n\n .search-clear {\n position: absolute;\n right: 6px;\n padding: 4px;\n background: transparent;\n border: none;\n color: var(--mj-text-disabled);\n cursor: pointer;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .search-clear:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n }\n\n /* Selection toolbar */\n .selection-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 20px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n }\n\n .selection-info {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .selection-count {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n }\n\n .selection-actions {\n display: flex;\n gap: 8px;\n }\n\n .btn-toolbar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n }\n\n .btn-toolbar:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n }\n\n .btn-toolbar.btn-danger {\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n }\n\n .btn-toolbar.btn-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-color: var(--mj-status-error);\n }\n\n /* Content area */\n .collections-content {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n }\n\n /* Loading and empty states */\n .loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 0;\n color: var(--mj-text-disabled);\n text-align: center;\n padding: 24px;\n }\n\n .collections-content mj-empty-state {\n flex: 1;\n min-height: 0;\n }\n\n .empty-collection-hint {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n }\n\n /* Grid view */\n .unified-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\n gap: 16px;\n padding: 4px;\n flex-shrink: 0;\n }\n\n .grid-item {\n display: flex;\n flex-direction: column;\n padding: 12px;\n background: var(--mj-bg-surface);\n border: 2px solid transparent;\n border-radius: 8px;\n cursor: pointer;\n transition: all 150ms ease;\n position: relative;\n user-select: none;\n }\n\n .grid-item:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n }\n\n .grid-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n }\n\n .grid-item.active {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-color: var(--mj-status-warning);\n box-shadow: 0 0 0 1px var(--mj-status-warning);\n }\n\n .grid-item.active:hover {\n background: color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n }\n\n /* Select mode styling for grid */\n .unified-grid.select-mode .grid-item {\n cursor: pointer;\n }\n\n .unified-grid.select-mode .grid-item:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n }\n\n .item-checkbox {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: 10;\n }\n\n .item-checkbox i {\n font-size: 16px;\n color: var(--mj-text-disabled);\n transition: color 150ms ease;\n }\n\n .grid-item.selected .item-checkbox i,\n .item-checkbox:hover i {\n color: var(--mj-brand-primary);\n }\n\n .grid-item-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .grid-icon {\n width: 64px;\n height: 64px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n position: relative;\n }\n\n .grid-icon.folder-icon {\n background: var(--mj-brand-primary);\n }\n\n /* Direct child only \u2014 the nested .shared-badge icon must keep its own sizing */\n .grid-icon.folder-icon > i {\n font-size: 36px;\n color: var(--mj-text-inverse);\n }\n\n .grid-icon.artifact-icon {\n background: var(--mj-bg-surface-sunken);\n }\n\n .grid-icon.artifact-icon i {\n font-size: 32px;\n color: var(--mj-text-muted);\n }\n\n .shared-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 22px;\n height: 22px;\n background: var(--mj-bg-surface);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n }\n\n .shared-badge i {\n font-size: 10px;\n color: var(--mj-brand-primary);\n }\n\n .grid-info {\n width: 100%;\n text-align: center;\n }\n\n .grid-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n line-height: 1.3;\n margin-bottom: 4px;\n /* Allow wrapping to 2 lines max */\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n }\n\n .grid-description {\n font-size: 11px;\n color: var(--mj-text-muted);\n line-height: 1.3;\n margin-bottom: 4px;\n /* Allow wrapping to 2 lines max */\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n }\n\n .grid-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n }\n\n .grid-owner {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n max-width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .grid-owner i {\n font-size: 10px;\n margin-right: 3px;\n }\n\n .version-badge {\n display: inline-block;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border-radius: 3px;\n font-size: 10px;\n font-weight: 600;\n font-family: monospace;\n margin-right: 4px;\n }\n\n .artifact-type-badge {\n display: inline-block;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n /* List view */\n .unified-list {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .list-table {\n width: 100%;\n border-collapse: collapse;\n }\n\n .list-table thead {\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .list-table th {\n padding: 10px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .list-table th.sortable {\n cursor: pointer;\n user-select: none;\n transition: color 150ms ease;\n }\n\n .list-table th.sortable:hover {\n color: var(--mj-brand-primary);\n }\n\n .list-table th.sortable span {\n display: inline-block;\n margin-right: 6px;\n }\n\n .list-table th.sortable i {\n font-size: 10px;\n opacity: 0.5;\n }\n\n .list-table th.sortable:hover i {\n opacity: 1;\n }\n\n .list-table tbody tr {\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n transition: background 150ms ease;\n cursor: pointer;\n user-select: none;\n }\n\n .list-table tbody tr:last-child {\n border-bottom: none;\n }\n\n .list-table tbody tr:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .list-table tbody tr.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n }\n\n .list-table tbody tr.active {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-status-warning);\n }\n\n .list-table tbody tr.active:hover {\n background: color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n }\n\n .list-table td {\n padding: 12px 16px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n }\n\n .col-checkbox {\n width: 40px;\n text-align: center;\n }\n\n .col-checkbox i {\n font-size: 16px;\n color: var(--mj-text-disabled);\n cursor: pointer;\n transition: color 150ms ease;\n }\n\n .col-checkbox i:hover,\n .list-table tbody tr.selected .col-checkbox i {\n color: var(--mj-brand-primary);\n }\n\n .col-name {\n min-width: 300px;\n }\n\n .list-name-cell {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .list-name-cell i {\n font-size: 16px;\n color: var(--mj-text-muted);\n width: 20px;\n text-align: center;\n }\n\n .list-name-cell .fa-folder {\n color: var(--mj-brand-primary);\n }\n\n .shared-indicator {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 10px;\n font-weight: 600;\n flex-shrink: 0;\n }\n\n /* Beat the generic .list-name-cell i sizing for the chip's icon */\n .list-name-cell .shared-indicator i {\n font-size: 10px;\n color: inherit;\n width: auto;\n }\n\n .col-type {\n width: 150px;\n }\n\n .col-modified {\n width: 180px;\n }\n\n .col-owner {\n width: 150px;\n }\n\n /* Pagination */\n .pagination-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 16px;\n margin-top: 8px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n }\n\n .pagination-info {\n white-space: nowrap;\n }\n\n .pagination-controls {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .pagination-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 12px;\n }\n\n .pagination-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n }\n\n .pagination-btn:disabled {\n opacity: 0.35;\n cursor: default;\n }\n\n .pagination-page-info {\n padding: 0 8px;\n white-space: nowrap;\n font-weight: 500;\n }\n\n /* Toolbar separator and action group */\n .toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--mj-border-strong);\n margin: 0 4px;\n }\n\n .toolbar-actions-group {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .btn-icon-danger {\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n }\n\n .btn-icon-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-color: var(--mj-status-error);\n }\n\n /* Context menu */\n .context-menu-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 1999;\n }\n\n .context-menu {\n position: fixed;\n min-width: 180px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);\n padding: 4px;\n z-index: 2000;\n }\n\n .context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 12px;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n transition: background 100ms ease;\n }\n\n .context-menu-item:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .context-menu-item i {\n font-size: 14px;\n width: 16px;\n text-align: center;\n color: var(--mj-text-muted);\n }\n\n .context-menu-danger {\n color: var(--mj-status-error);\n }\n\n .context-menu-danger i {\n color: var(--mj-status-error);\n }\n\n .context-menu-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n }\n\n .context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n }\n .submenu-arrow {\n margin-left: auto;\n font-size: 10px;\n opacity: 0.6;\n }\n .move-target-list {\n max-height: 240px;\n overflow-y: auto;\n }\n .context-menu-note {\n padding: 8px 14px;\n font-size: 12px;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n /* ===== Body: navigator pane + content (#6) ===== */\n .collections-body {\n flex: 1;\n display: flex;\n flex-direction: row;\n min-height: 0;\n overflow: hidden;\n }\n .collections-navigator {\n width: 240px;\n flex-shrink: 0;\n border-right: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n }\n .nav-header {\n padding: 12px 14px 8px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n }\n .nav-list { display: flex; flex-direction: column; padding: 0 6px 12px; gap: 1px; }\n .nav-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 7px 10px;\n border: 1px solid transparent;\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n transition: background 0.12s ease;\n }\n .nav-row:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .nav-row.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 600;\n }\n .nav-row.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 22%, transparent);\n border-color: var(--mj-brand-primary);\n }\n .nav-row i { font-size: 13px; width: 16px; flex-shrink: 0; }\n .nav-row-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .nav-toggle.active { color: var(--mj-brand-primary); }\n\n /* ===== Drag-and-drop visuals (#1/#2) ===== */\n .grid-item.dragging, .list-item.dragging { opacity: 0.4; }\n .grid-item.drag-over {\n border-color: var(--mj-brand-primary) !important;\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface)) !important;\n }\n .list-item.drag-over td {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n box-shadow: inset 0 0 0 1px var(--mj-brand-primary);\n }\n .breadcrumb-item.drag-over, .breadcrumb-link.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 6px;\n outline: 1px solid var(--mj-brand-primary);\n }\n\n /* Hover-reveal checkboxes (frictionless selection #4) */\n .item-checkbox { opacity: 0; transition: opacity 150ms ease; }\n .grid-item:hover .item-checkbox,\n .grid-item.selected .item-checkbox,\n .unified-grid.select-mode .item-checkbox { opacity: 1; }\n .list-item .col-checkbox i { opacity: 0; transition: opacity 150ms ease; }\n .list-item:hover .col-checkbox i,\n .list-item.selected .col-checkbox i,\n .unified-list.select-mode .col-checkbox i { opacity: 1; }\n .list-item.selected .col-checkbox i { color: var(--mj-brand-primary); }\n\n /* ===== Bulk \"Move to\u2026\" popover (#3) ===== */\n .bulk-move-backdrop {\n position: fixed; inset: 0; z-index: 1000;\n }\n .bulk-move-menu {\n max-height: 320px;\n overflow-y: auto;\n z-index: 1001;\n }\n .dropdown-note { padding: 10px 14px; font-size: 12px; color: var(--mj-text-muted); }\n\n /* ===== Staging shelf (#5) ===== */\n .staging-shelf {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 10px 16px;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n box-shadow: 0 -2px 8px color-mix(in srgb, var(--mj-text-primary) 6%, transparent);\n }\n .shelf-info {\n display: flex; align-items: center; gap: 8px;\n font-weight: 600; font-size: 13px; color: var(--mj-text-primary);\n flex-shrink: 0;\n }\n .shelf-info i { color: var(--mj-brand-primary); }\n .shelf-chips {\n flex: 1; min-width: 0;\n display: flex; gap: 6px; overflow-x: auto; padding: 2px 0;\n }\n .shelf-chip {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 4px 6px 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n font-size: 12px; color: var(--mj-text-secondary);\n flex-shrink: 0;\n }\n .shelf-chip-name { max-width: 120px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .shelf-chip-x {\n width: 18px; height: 18px; border: 0; background: transparent;\n color: var(--mj-text-muted); cursor: pointer; border-radius: 50%;\n display: flex; align-items: center; justify-content: center; font-size: 10px;\n }\n .shelf-chip-x:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .shelf-actions { display: flex; gap: 8px; flex-shrink: 0; }\n .btn-toolbar.btn-primary-toolbar {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n }\n .btn-toolbar.btn-primary-toolbar:hover:not(:disabled) { background: var(--mj-brand-primary-hover); }\n .btn-toolbar:disabled { opacity: 0.5; cursor: not-allowed; }\n "] }]
|
|
3444
|
-
}], () => [{ type: i1.DialogService }, { type: i2.ArtifactStateService }, { type: i3.CollectionStateService }, { type: i4.CollectionPermissionService }, { type: i5.ArtifactIconService }, { type: i0.ChangeDetectorRef }], {
|
|
4020
|
+
}], () => [{ type: i1.DialogService }, { type: i2.ArtifactStateService }, { type: i3.CollectionStateService }, { type: i4.CollectionPermissionService }, { type: i5.ArtifactIconService }, { type: i0.ChangeDetectorRef }], { EnvironmentId: [{
|
|
4021
|
+
type: Input
|
|
4022
|
+
}], environmentId: [{
|
|
4023
|
+
type: Input
|
|
4024
|
+
}], CurrentUser: [{
|
|
3445
4025
|
type: Input
|
|
3446
4026
|
}], currentUser: [{
|
|
3447
4027
|
type: Input
|
|
4028
|
+
}], CollectionNavigated: [{
|
|
4029
|
+
type: Output
|
|
3448
4030
|
}], collectionNavigated: [{
|
|
3449
4031
|
type: Output
|
|
4032
|
+
}], OpenConversationRequested: [{
|
|
4033
|
+
type: Output
|
|
3450
4034
|
}], openConversationRequested: [{
|
|
3451
4035
|
type: Output
|
|
3452
4036
|
}], onEscapeKey: [{
|