@memberjunction/ng-conversations 2.106.0 → 2.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts +67 -0
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -0
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +725 -0
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -0
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts +39 -0
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -0
- package/dist/lib/components/collection/artifact-create-modal.component.js +351 -0
- package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -0
- package/dist/lib/components/collection/collection-form-modal.component.d.ts +3 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.js +60 -10
- package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.d.ts +43 -0
- package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -0
- package/dist/lib/components/collection/collection-share-modal.component.js +728 -0
- package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -0
- package/dist/lib/components/collection/collection-tree.component.d.ts +8 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.js +217 -115
- package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
- package/dist/lib/components/collection/collection-view.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +52 -34
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts +45 -9
- package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.js +586 -220
- package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +53 -20
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +365 -250
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +71 -1
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +303 -104
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +39 -5
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +259 -137
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +8 -6
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +52 -9
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/message/suggested-responses.component.d.ts +55 -0
- package/dist/lib/components/message/suggested-responses.component.d.ts.map +1 -0
- package/dist/lib/components/message/suggested-responses.component.js +207 -0
- package/dist/lib/components/message/suggested-responses.component.js.map +1 -0
- package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
- package/dist/lib/components/search/search-panel.component.js +245 -113
- package/dist/lib/components/search/search-panel.component.js.map +1 -1
- package/dist/lib/components/shared/user-picker.component.d.ts +29 -0
- package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -0
- package/dist/lib/components/shared/user-picker.component.js +229 -0
- package/dist/lib/components/shared/user-picker.component.js.map +1 -0
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +7 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +36 -6
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +19 -2
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +167 -58
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/conversations.module.d.ts +52 -47
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js +27 -4
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/models/conversation-complete-query.model.d.ts +75 -0
- package/dist/lib/models/conversation-complete-query.model.d.ts.map +1 -0
- package/dist/lib/models/conversation-complete-query.model.js +19 -0
- package/dist/lib/models/conversation-complete-query.model.js.map +1 -0
- package/dist/lib/models/conversation-state.model.d.ts +27 -0
- package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
- package/dist/lib/models/lazy-artifact-info.d.ts +68 -0
- package/dist/lib/models/lazy-artifact-info.d.ts.map +1 -0
- package/dist/lib/models/lazy-artifact-info.js +150 -0
- package/dist/lib/models/lazy-artifact-info.js.map +1 -0
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +5 -0
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +14 -9
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/collection-permission.service.d.ts +96 -0
- package/dist/lib/services/collection-permission.service.d.ts.map +1 -0
- package/dist/lib/services/collection-permission.service.js +303 -0
- package/dist/lib/services/collection-permission.service.js.map +1 -0
- package/dist/lib/services/collection-state.service.d.ts +34 -0
- package/dist/lib/services/collection-state.service.d.ts.map +1 -0
- package/dist/lib/services/collection-state.service.js +50 -0
- package/dist/lib/services/collection-state.service.js.map +1 -0
- package/dist/lib/services/conversation-agent.service.d.ts +20 -4
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +179 -17
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +5 -0
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.js +1 -1
- package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
- package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
- package/dist/lib/services/mention-parser.service.js +0 -5
- package/dist/lib/services/mention-parser.service.js.map +1 -1
- package/dist/lib/services/search.service.d.ts +26 -3
- package/dist/lib/services/search.service.d.ts.map +1 -1
- package/dist/lib/services/search.service.js +172 -12
- package/dist/lib/services/search.service.js.map +1 -1
- package/dist/public-api.d.ts +4 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +4 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +12 -12
|
@@ -1,30 +1,35 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { RunQuery, Metadata } from '@memberjunction/core';
|
|
3
|
+
import { LazyArtifactInfo } from '../../models/lazy-artifact-info';
|
|
4
|
+
import { parseConversationDetailComplete } from '../../models/conversation-complete-query.model';
|
|
5
|
+
import { MessageInputComponent } from '../message/message-input.component';
|
|
6
|
+
import { ArtifactViewerPanelComponent } from '@memberjunction/ng-artifacts';
|
|
3
7
|
import { Subject } from 'rxjs';
|
|
4
8
|
import * as i0 from "@angular/core";
|
|
5
9
|
import * as i1 from "../../services/conversation-state.service";
|
|
6
|
-
import * as i2 from "../../services/
|
|
7
|
-
import * as i3 from "../../services/agent
|
|
8
|
-
import * as i4 from "../../services/
|
|
9
|
-
import * as i5 from "../../services/
|
|
10
|
+
import * as i2 from "../../services/agent-state.service";
|
|
11
|
+
import * as i3 from "../../services/conversation-agent.service";
|
|
12
|
+
import * as i4 from "../../services/active-tasks.service";
|
|
13
|
+
import * as i5 from "../../services/mention-autocomplete.service";
|
|
10
14
|
import * as i6 from "@angular/common";
|
|
11
15
|
import * as i7 from "@memberjunction/ng-artifacts";
|
|
12
|
-
import * as i8 from "../
|
|
13
|
-
import * as i9 from "../message/message-
|
|
14
|
-
import * as i10 from "../
|
|
15
|
-
import * as i11 from "../
|
|
16
|
-
import * as i12 from "../
|
|
17
|
-
import * as i13 from "../
|
|
18
|
-
import * as i14 from "../
|
|
19
|
-
import * as i15 from "../
|
|
16
|
+
import * as i8 from "../collection/artifact-collection-picker-modal.component";
|
|
17
|
+
import * as i9 from "../message/message-list.component";
|
|
18
|
+
import * as i10 from "../message/message-input.component";
|
|
19
|
+
import * as i11 from "../thread/thread-panel.component";
|
|
20
|
+
import * as i12 from "../project/project-selector.component";
|
|
21
|
+
import * as i13 from "../tasks/tasks-dropdown.component";
|
|
22
|
+
import * as i14 from "../agent/active-agent-indicator.component";
|
|
23
|
+
import * as i15 from "../members/members-modal.component";
|
|
24
|
+
import * as i16 from "../export/export-modal.component";
|
|
20
25
|
const _c0 = ["scrollContainer"];
|
|
21
26
|
const _forTrack0 = ($index, $item) => $item.artifactId;
|
|
22
27
|
const _forTrack1 = ($index, $item) => $item.versionId;
|
|
23
28
|
function ConversationChatAreaComponent_div_1_button_4_Template(rf, ctx) { if (rf & 1) {
|
|
24
29
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
25
|
-
i0.ɵɵelementStart(0, "button",
|
|
30
|
+
i0.ɵɵelementStart(0, "button", 31);
|
|
26
31
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_div_1_button_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.openProjectSelector()); });
|
|
27
|
-
i0.ɵɵelement(1, "i",
|
|
32
|
+
i0.ɵɵelement(1, "i", 32);
|
|
28
33
|
i0.ɵɵelementStart(2, "span");
|
|
29
34
|
i0.ɵɵtext(3);
|
|
30
35
|
i0.ɵɵelementEnd()();
|
|
@@ -35,9 +40,9 @@ function ConversationChatAreaComponent_div_1_button_4_Template(rf, ctx) { if (rf
|
|
|
35
40
|
} }
|
|
36
41
|
function ConversationChatAreaComponent_div_1_button_9_Template(rf, ctx) { if (rf & 1) {
|
|
37
42
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
38
|
-
i0.ɵɵelementStart(0, "button",
|
|
43
|
+
i0.ɵɵelementStart(0, "button", 33);
|
|
39
44
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_div_1_button_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.viewArtifacts()); });
|
|
40
|
-
i0.ɵɵelement(1, "i",
|
|
45
|
+
i0.ɵɵelement(1, "i", 34);
|
|
41
46
|
i0.ɵɵelementStart(2, "span");
|
|
42
47
|
i0.ɵɵtext(3);
|
|
43
48
|
i0.ɵɵelementEnd()();
|
|
@@ -48,31 +53,31 @@ function ConversationChatAreaComponent_div_1_button_9_Template(rf, ctx) { if (rf
|
|
|
48
53
|
} }
|
|
49
54
|
function ConversationChatAreaComponent_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
50
55
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
51
|
-
i0.ɵɵelementStart(0, "div",
|
|
56
|
+
i0.ɵɵelementStart(0, "div", 17)(1, "div", 18)(2, "div", 19);
|
|
52
57
|
i0.ɵɵtext(3);
|
|
53
58
|
i0.ɵɵelementEnd();
|
|
54
|
-
i0.ɵɵtemplate(4, ConversationChatAreaComponent_div_1_button_4_Template, 4, 1, "button",
|
|
55
|
-
i0.ɵɵelementStart(5, "button",
|
|
59
|
+
i0.ɵɵtemplate(4, ConversationChatAreaComponent_div_1_button_4_Template, 4, 1, "button", 20);
|
|
60
|
+
i0.ɵɵelementStart(5, "button", 21);
|
|
56
61
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_div_1_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.toggleMembersModal()); });
|
|
57
|
-
i0.ɵɵelement(6, "i",
|
|
62
|
+
i0.ɵɵelement(6, "i", 22);
|
|
58
63
|
i0.ɵɵelementStart(7, "span");
|
|
59
64
|
i0.ɵɵtext(8);
|
|
60
65
|
i0.ɵɵelementEnd()();
|
|
61
|
-
i0.ɵɵtemplate(9, ConversationChatAreaComponent_div_1_button_9_Template, 4, 2, "button",
|
|
62
|
-
i0.ɵɵelementStart(10, "mj-active-agent-indicator",
|
|
66
|
+
i0.ɵɵtemplate(9, ConversationChatAreaComponent_div_1_button_9_Template, 4, 2, "button", 23);
|
|
67
|
+
i0.ɵɵelementStart(10, "mj-active-agent-indicator", 24);
|
|
63
68
|
i0.ɵɵlistener("togglePanel", function ConversationChatAreaComponent_div_1_Template_mj_active_agent_indicator_togglePanel_10_listener() { i0.ɵɵrestoreView(_r2); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onToggleAgentPanel()); })("agentSelected", function ConversationChatAreaComponent_div_1_Template_mj_active_agent_indicator_agentSelected_10_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onAgentSelected($event)); });
|
|
64
69
|
i0.ɵɵelementEnd()();
|
|
65
|
-
i0.ɵɵelementStart(11, "div",
|
|
70
|
+
i0.ɵɵelementStart(11, "div", 25)(12, "mj-tasks-dropdown", 26);
|
|
66
71
|
i0.ɵɵlistener("taskClicked", function ConversationChatAreaComponent_div_1_Template_mj_tasks_dropdown_taskClicked_12_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onTaskClicked($event)); });
|
|
67
72
|
i0.ɵɵelementEnd();
|
|
68
|
-
i0.ɵɵelementStart(13, "button",
|
|
73
|
+
i0.ɵɵelementStart(13, "button", 27);
|
|
69
74
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_div_1_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r2); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.exportConversation()); });
|
|
70
|
-
i0.ɵɵelement(14, "i",
|
|
75
|
+
i0.ɵɵelement(14, "i", 28);
|
|
71
76
|
i0.ɵɵtext(15, " Export ");
|
|
72
77
|
i0.ɵɵelementEnd();
|
|
73
|
-
i0.ɵɵelementStart(16, "button",
|
|
78
|
+
i0.ɵɵelementStart(16, "button", 29);
|
|
74
79
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_div_1_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r2); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.shareConversation()); });
|
|
75
|
-
i0.ɵɵelement(17, "i",
|
|
80
|
+
i0.ɵɵelement(17, "i", 30);
|
|
76
81
|
i0.ɵɵtext(18, " Share ");
|
|
77
82
|
i0.ɵɵelementEnd()()();
|
|
78
83
|
} if (rf & 2) {
|
|
@@ -96,21 +101,21 @@ function ConversationChatAreaComponent_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
96
101
|
} }
|
|
97
102
|
function ConversationChatAreaComponent_span_8_Template(rf, ctx) { if (rf & 1) {
|
|
98
103
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
99
|
-
i0.ɵɵelementStart(0, "span",
|
|
104
|
+
i0.ɵɵelementStart(0, "span", 35);
|
|
100
105
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_span_8_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.scrollToBottomAnimate()); });
|
|
101
|
-
i0.ɵɵelement(1, "i",
|
|
106
|
+
i0.ɵɵelement(1, "i", 36);
|
|
102
107
|
i0.ɵɵelementEnd();
|
|
103
108
|
} }
|
|
104
109
|
function ConversationChatAreaComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
105
|
-
i0.ɵɵelementStart(0, "div", 10)(1, "div",
|
|
106
|
-
i0.ɵɵelement(2, "i",
|
|
110
|
+
i0.ɵɵelementStart(0, "div", 10)(1, "div", 37);
|
|
111
|
+
i0.ɵɵelement(2, "i", 38);
|
|
107
112
|
i0.ɵɵelementStart(3, "span");
|
|
108
113
|
i0.ɵɵtext(4, "Loading conversation data...");
|
|
109
114
|
i0.ɵɵelementEnd()()();
|
|
110
115
|
} }
|
|
111
116
|
function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template(rf, ctx) { if (rf & 1) {
|
|
112
117
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
113
|
-
i0.ɵɵelementStart(0, "mj-message-input",
|
|
118
|
+
i0.ɵɵelementStart(0, "mj-message-input", 40);
|
|
114
119
|
i0.ɵɵlistener("messageSent", function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template_mj_message_input_messageSent_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onMessageSent($event)); })("agentResponse", function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template_mj_message_input_agentResponse_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onAgentResponse($event)); })("agentRunDetected", function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template_mj_message_input_agentRunDetected_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onAgentRunDetected($event)); })("artifactCreated", function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template_mj_message_input_artifactCreated_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onArtifactCreated($event)); })("conversationRenamed", function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template_mj_message_input_conversationRenamed_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onConversationRenamed($event)); });
|
|
115
120
|
i0.ɵɵelementEnd();
|
|
116
121
|
} if (rf & 2) {
|
|
@@ -118,18 +123,18 @@ function ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Templat
|
|
|
118
123
|
i0.ɵɵproperty("conversationId", ctx_r3.conversationState.activeConversation.ID)("currentUser", ctx_r3.currentUser)("conversationHistory", ctx_r3.messages)("disabled", ctx_r3.isProcessing);
|
|
119
124
|
} }
|
|
120
125
|
function ConversationChatAreaComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
-
i0.ɵɵtemplate(0, ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template, 1, 4, "mj-message-input",
|
|
126
|
+
i0.ɵɵtemplate(0, ConversationChatAreaComponent_Conditional_11_mj_message_input_0_Template, 1, 4, "mj-message-input", 39);
|
|
122
127
|
} if (rf & 2) {
|
|
123
128
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
124
129
|
i0.ɵɵproperty("ngIf", ctx_r3.conversationState.activeConversation);
|
|
125
130
|
} }
|
|
126
131
|
function ConversationChatAreaComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
127
132
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
128
|
-
i0.ɵɵelementStart(0, "div",
|
|
133
|
+
i0.ɵɵelementStart(0, "div", 41);
|
|
129
134
|
i0.ɵɵlistener("mousedown", function ConversationChatAreaComponent_Conditional_12_Template_div_mousedown_0_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onResizeStart($event)); });
|
|
130
135
|
i0.ɵɵelementEnd();
|
|
131
|
-
i0.ɵɵelementStart(1, "div",
|
|
132
|
-
i0.ɵɵlistener("closed", function ConversationChatAreaComponent_Conditional_12_Template_mj_artifact_viewer_panel_closed_2_listener() { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onCloseArtifactPanel()); });
|
|
136
|
+
i0.ɵɵelementStart(1, "div", 42)(2, "mj-artifact-viewer-panel", 43);
|
|
137
|
+
i0.ɵɵlistener("closed", function ConversationChatAreaComponent_Conditional_12_Template_mj_artifact_viewer_panel_closed_2_listener() { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onCloseArtifactPanel()); })("saveToCollectionRequested", function ConversationChatAreaComponent_Conditional_12_Template_mj_artifact_viewer_panel_saveToCollectionRequested_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSaveToCollectionRequested($event)); });
|
|
133
138
|
i0.ɵɵelementEnd()();
|
|
134
139
|
} if (rf & 2) {
|
|
135
140
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -140,7 +145,7 @@ function ConversationChatAreaComponent_Conditional_12_Template(rf, ctx) { if (rf
|
|
|
140
145
|
} }
|
|
141
146
|
function ConversationChatAreaComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
142
147
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
143
|
-
i0.ɵɵelementStart(0, "mj-thread-panel",
|
|
148
|
+
i0.ɵɵelementStart(0, "mj-thread-panel", 44);
|
|
144
149
|
i0.ɵɵlistener("closed", function ConversationChatAreaComponent_Conditional_13_Template_mj_thread_panel_closed_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onThreadClosed()); })("replyAdded", function ConversationChatAreaComponent_Conditional_13_Template_mj_thread_panel_replyAdded_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onThreadReplyAdded($event)); });
|
|
145
150
|
i0.ɵɵelementEnd();
|
|
146
151
|
} if (rf & 2) {
|
|
@@ -149,18 +154,18 @@ function ConversationChatAreaComponent_Conditional_13_Template(rf, ctx) { if (rf
|
|
|
149
154
|
} }
|
|
150
155
|
function ConversationChatAreaComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
151
156
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
152
|
-
i0.ɵɵelementStart(0, "div",
|
|
157
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
153
158
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_16_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.showProjectSelector = false); });
|
|
154
|
-
i0.ɵɵelementStart(1, "div",
|
|
159
|
+
i0.ɵɵelementStart(1, "div", 46);
|
|
155
160
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_16_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
156
|
-
i0.ɵɵelementStart(2, "div",
|
|
161
|
+
i0.ɵɵelementStart(2, "div", 47)(3, "h3");
|
|
157
162
|
i0.ɵɵtext(4, "Assign Project");
|
|
158
163
|
i0.ɵɵelementEnd();
|
|
159
|
-
i0.ɵɵelementStart(5, "button",
|
|
164
|
+
i0.ɵɵelementStart(5, "button", 48);
|
|
160
165
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_16_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r11); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.showProjectSelector = false); });
|
|
161
|
-
i0.ɵɵelement(6, "i",
|
|
166
|
+
i0.ɵɵelement(6, "i", 49);
|
|
162
167
|
i0.ɵɵelementEnd()();
|
|
163
|
-
i0.ɵɵelementStart(7, "div",
|
|
168
|
+
i0.ɵɵelementStart(7, "div", 50)(8, "mj-project-selector", 51);
|
|
164
169
|
i0.ɵɵlistener("projectSelected", function ConversationChatAreaComponent_Conditional_16_Template_mj_project_selector_projectSelected_8_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onProjectSelected($event)); });
|
|
165
170
|
i0.ɵɵelementEnd()()()();
|
|
166
171
|
} if (rf & 2) {
|
|
@@ -169,9 +174,9 @@ function ConversationChatAreaComponent_Conditional_16_Template(rf, ctx) { if (rf
|
|
|
169
174
|
i0.ɵɵproperty("environmentId", ctx_r3.environmentId)("currentUser", ctx_r3.currentUser)("selectedProjectId", ctx_r3.conversationState.activeConversation.ProjectID);
|
|
170
175
|
} }
|
|
171
176
|
function ConversationChatAreaComponent_Conditional_17_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
172
|
-
i0.ɵɵelementStart(0, "div",
|
|
173
|
-
i0.ɵɵelement(1, "i",
|
|
174
|
-
i0.ɵɵelementStart(2, "p",
|
|
177
|
+
i0.ɵɵelementStart(0, "div", 54);
|
|
178
|
+
i0.ɵɵelement(1, "i", 56);
|
|
179
|
+
i0.ɵɵelementStart(2, "p", 57);
|
|
175
180
|
i0.ɵɵtext(3, "No artifacts in this conversation yet");
|
|
176
181
|
i0.ɵɵelementEnd()();
|
|
177
182
|
} }
|
|
@@ -186,9 +191,9 @@ function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_9_Templ
|
|
|
186
191
|
} }
|
|
187
192
|
function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
188
193
|
const _r15 = i0.ɵɵgetCurrentView();
|
|
189
|
-
i0.ɵɵelementStart(0, "button",
|
|
194
|
+
i0.ɵɵelementStart(0, "button", 69);
|
|
190
195
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_10_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r15); const artifact_r14 = i0.ɵɵnextContext().$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.toggleArtifactExpansion(artifact_r14.artifactId, $event)); });
|
|
191
|
-
i0.ɵɵelement(1, "i",
|
|
196
|
+
i0.ɵɵelement(1, "i", 70);
|
|
192
197
|
i0.ɵɵelementEnd();
|
|
193
198
|
} if (rf & 2) {
|
|
194
199
|
const artifact_r14 = i0.ɵɵnextContext().$implicit;
|
|
@@ -198,15 +203,15 @@ function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_10_Temp
|
|
|
198
203
|
} }
|
|
199
204
|
function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
200
205
|
const _r16 = i0.ɵɵgetCurrentView();
|
|
201
|
-
i0.ɵɵelementStart(0, "div",
|
|
206
|
+
i0.ɵɵelementStart(0, "div", 72);
|
|
202
207
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_For_2_Template_div_click_0_listener($event) { const version_r17 = i0.ɵɵrestoreView(_r16).$implicit; const artifact_r14 = i0.ɵɵnextContext(2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); ctx_r3.openArtifactFromModal(artifact_r14.artifactId, version_r17.versionNumber); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
203
|
-
i0.ɵɵelementStart(1, "span",
|
|
208
|
+
i0.ɵɵelementStart(1, "span", 73);
|
|
204
209
|
i0.ɵɵtext(2);
|
|
205
210
|
i0.ɵɵelementEnd();
|
|
206
|
-
i0.ɵɵelementStart(3, "span",
|
|
211
|
+
i0.ɵɵelementStart(3, "span", 74);
|
|
207
212
|
i0.ɵɵtext(4, "Open this version");
|
|
208
213
|
i0.ɵɵelementEnd();
|
|
209
|
-
i0.ɵɵelement(5, "i",
|
|
214
|
+
i0.ɵɵelement(5, "i", 75);
|
|
210
215
|
i0.ɵɵelementEnd();
|
|
211
216
|
} if (rf & 2) {
|
|
212
217
|
const version_r17 = ctx.$implicit;
|
|
@@ -214,8 +219,8 @@ function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_For_
|
|
|
214
219
|
i0.ɵɵtextInterpolate1("v", version_r17.versionNumber, "");
|
|
215
220
|
} }
|
|
216
221
|
function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
217
|
-
i0.ɵɵelementStart(0, "div",
|
|
218
|
-
i0.ɵɵrepeaterCreate(1, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_For_2_Template, 6, 1, "div",
|
|
222
|
+
i0.ɵɵelementStart(0, "div", 68);
|
|
223
|
+
i0.ɵɵrepeaterCreate(1, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_For_2_Template, 6, 1, "div", 71, _forTrack1);
|
|
219
224
|
i0.ɵɵelementEnd();
|
|
220
225
|
} if (rf & 2) {
|
|
221
226
|
const artifact_r14 = i0.ɵɵnextContext().$implicit;
|
|
@@ -224,22 +229,22 @@ function ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_Temp
|
|
|
224
229
|
} }
|
|
225
230
|
function ConversationChatAreaComponent_Conditional_17_For_10_Template(rf, ctx) { if (rf & 1) {
|
|
226
231
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
227
|
-
i0.ɵɵelementStart(0, "div",
|
|
232
|
+
i0.ɵɵelementStart(0, "div", 58)(1, "div", 59);
|
|
228
233
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_17_For_10_Template_div_click_1_listener() { const artifact_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.openArtifactFromModal(artifact_r14.artifactId)); });
|
|
229
|
-
i0.ɵɵelementStart(2, "div",
|
|
230
|
-
i0.ɵɵelement(3, "i",
|
|
234
|
+
i0.ɵɵelementStart(2, "div", 60);
|
|
235
|
+
i0.ɵɵelement(3, "i", 61);
|
|
231
236
|
i0.ɵɵelementEnd();
|
|
232
|
-
i0.ɵɵelementStart(4, "div",
|
|
237
|
+
i0.ɵɵelementStart(4, "div", 62)(5, "div", 63);
|
|
233
238
|
i0.ɵɵtext(6);
|
|
234
239
|
i0.ɵɵelementEnd();
|
|
235
|
-
i0.ɵɵelementStart(7, "div",
|
|
240
|
+
i0.ɵɵelementStart(7, "div", 64);
|
|
236
241
|
i0.ɵɵtemplate(8, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_8_Template, 1, 1)(9, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_9_Template, 1, 0);
|
|
237
242
|
i0.ɵɵelementEnd()();
|
|
238
|
-
i0.ɵɵtemplate(10, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_10_Template, 2, 4, "button",
|
|
239
|
-
i0.ɵɵelementStart(11, "div",
|
|
240
|
-
i0.ɵɵelement(12, "i",
|
|
243
|
+
i0.ɵɵtemplate(10, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_10_Template, 2, 4, "button", 65);
|
|
244
|
+
i0.ɵɵelementStart(11, "div", 66);
|
|
245
|
+
i0.ɵɵelement(12, "i", 67);
|
|
241
246
|
i0.ɵɵelementEnd()();
|
|
242
|
-
i0.ɵɵtemplate(13, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_Template, 3, 0, "div",
|
|
247
|
+
i0.ɵɵtemplate(13, ConversationChatAreaComponent_Conditional_17_For_10_Conditional_13_Template, 3, 0, "div", 68);
|
|
243
248
|
i0.ɵɵelementEnd();
|
|
244
249
|
} if (rf & 2) {
|
|
245
250
|
const artifact_r14 = ctx.$implicit;
|
|
@@ -256,20 +261,20 @@ function ConversationChatAreaComponent_Conditional_17_For_10_Template(rf, ctx) {
|
|
|
256
261
|
} }
|
|
257
262
|
function ConversationChatAreaComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
258
263
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
259
|
-
i0.ɵɵelementStart(0, "div",
|
|
264
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
260
265
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_17_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.showArtifactsModal = false); });
|
|
261
|
-
i0.ɵɵelementStart(1, "div",
|
|
266
|
+
i0.ɵɵelementStart(1, "div", 52);
|
|
262
267
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_17_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r12); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
263
|
-
i0.ɵɵelementStart(2, "div",
|
|
268
|
+
i0.ɵɵelementStart(2, "div", 47)(3, "h3");
|
|
264
269
|
i0.ɵɵtext(4, "Conversation Artifacts");
|
|
265
270
|
i0.ɵɵelementEnd();
|
|
266
|
-
i0.ɵɵelementStart(5, "button",
|
|
271
|
+
i0.ɵɵelementStart(5, "button", 48);
|
|
267
272
|
i0.ɵɵlistener("click", function ConversationChatAreaComponent_Conditional_17_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r12); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.showArtifactsModal = false); });
|
|
268
|
-
i0.ɵɵelement(6, "i",
|
|
273
|
+
i0.ɵɵelement(6, "i", 49);
|
|
269
274
|
i0.ɵɵelementEnd()();
|
|
270
|
-
i0.ɵɵelementStart(7, "div",
|
|
271
|
-
i0.ɵɵtemplate(8, ConversationChatAreaComponent_Conditional_17_Conditional_8_Template, 4, 0, "div",
|
|
272
|
-
i0.ɵɵrepeaterCreate(9, ConversationChatAreaComponent_Conditional_17_For_10_Template, 14, 6, "div",
|
|
275
|
+
i0.ɵɵelementStart(7, "div", 53);
|
|
276
|
+
i0.ɵɵtemplate(8, ConversationChatAreaComponent_Conditional_17_Conditional_8_Template, 4, 0, "div", 54);
|
|
277
|
+
i0.ɵɵrepeaterCreate(9, ConversationChatAreaComponent_Conditional_17_For_10_Template, 14, 6, "div", 55, _forTrack0);
|
|
273
278
|
i0.ɵɵelementEnd()()();
|
|
274
279
|
} if (rf & 2) {
|
|
275
280
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -278,23 +283,35 @@ function ConversationChatAreaComponent_Conditional_17_Template(rf, ctx) { if (rf
|
|
|
278
283
|
i0.ɵɵadvance();
|
|
279
284
|
i0.ɵɵrepeater(ctx_r3.getArtifactsArray());
|
|
280
285
|
} }
|
|
286
|
+
function ConversationChatAreaComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
287
|
+
const _r18 = i0.ɵɵgetCurrentView();
|
|
288
|
+
i0.ɵɵelementStart(0, "mj-artifact-collection-picker-modal", 76);
|
|
289
|
+
i0.ɵɵlistener("saved", function ConversationChatAreaComponent_Conditional_18_Template_mj_artifact_collection_picker_modal_saved_0_listener($event) { i0.ɵɵrestoreView(_r18); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onCollectionPickerSaved($event)); })("cancelled", function ConversationChatAreaComponent_Conditional_18_Template_mj_artifact_collection_picker_modal_cancelled_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onCollectionPickerCancelled()); });
|
|
290
|
+
i0.ɵɵelementEnd();
|
|
291
|
+
} if (rf & 2) {
|
|
292
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
293
|
+
i0.ɵɵproperty("isOpen", ctx_r3.showCollectionPicker)("environmentId", ctx_r3.environmentId)("currentUser", ctx_r3.currentUser)("excludeCollectionIds", ctx_r3.collectionPickerExcludedIds);
|
|
294
|
+
} }
|
|
281
295
|
export class ConversationChatAreaComponent {
|
|
282
296
|
conversationState;
|
|
283
|
-
dataCache;
|
|
284
297
|
agentStateService;
|
|
285
298
|
conversationAgentService;
|
|
286
299
|
activeTasks;
|
|
287
300
|
cdr;
|
|
301
|
+
mentionAutocompleteService;
|
|
288
302
|
environmentId;
|
|
289
303
|
currentUser;
|
|
290
304
|
conversationRenamed = new EventEmitter();
|
|
291
305
|
openEntityRecord = new EventEmitter();
|
|
292
306
|
taskClicked = new EventEmitter();
|
|
293
307
|
scrollContainer;
|
|
308
|
+
messageInputComponent;
|
|
309
|
+
artifactViewerComponent;
|
|
294
310
|
messages = [];
|
|
295
311
|
showScrollToBottomIcon = false;
|
|
296
312
|
scrollToBottom = false;
|
|
297
313
|
previousConversationId = null;
|
|
314
|
+
lastLoadedConversationId = null; // Track which conversation's peripheral data was loaded
|
|
298
315
|
isProcessing = false;
|
|
299
316
|
memberCount = 1;
|
|
300
317
|
artifactCount = 0;
|
|
@@ -309,8 +326,14 @@ export class ConversationChatAreaComponent {
|
|
|
309
326
|
selectedVersionNumber = undefined; // Version to show in artifact viewer
|
|
310
327
|
artifactPaneWidth = 40; // Default 40% width
|
|
311
328
|
expandedArtifactId = null; // Track which artifact card is expanded in modal
|
|
312
|
-
|
|
313
|
-
|
|
329
|
+
showCollectionPicker = false;
|
|
330
|
+
collectionPickerArtifactId = null;
|
|
331
|
+
collectionPickerExcludedIds = [];
|
|
332
|
+
// Conversation data cache: ConversationID -> Array of ConversationDetailComplete
|
|
333
|
+
// Stores raw query results so we don't need to re-query when switching conversations
|
|
334
|
+
conversationDataCache = new Map();
|
|
335
|
+
// Artifact mapping: ConversationDetailID -> Array of LazyArtifactInfo
|
|
336
|
+
// Uses lazy-loading pattern: display data loaded immediately, full entities on-demand
|
|
314
337
|
// Supports multiple artifacts per conversation detail (0-N relationship)
|
|
315
338
|
artifactsByDetailId = new Map();
|
|
316
339
|
// Agent run mapping: ConversationDetailID -> AIAgentRunEntityExtended
|
|
@@ -326,15 +349,18 @@ export class ConversationChatAreaComponent {
|
|
|
326
349
|
startWidth = 0;
|
|
327
350
|
// LocalStorage key
|
|
328
351
|
ARTIFACT_PANE_WIDTH_KEY = 'mj-conversations-artifact-pane-width';
|
|
329
|
-
constructor(conversationState,
|
|
352
|
+
constructor(conversationState, agentStateService, conversationAgentService, activeTasks, cdr, mentionAutocompleteService) {
|
|
330
353
|
this.conversationState = conversationState;
|
|
331
|
-
this.dataCache = dataCache;
|
|
332
354
|
this.agentStateService = agentStateService;
|
|
333
355
|
this.conversationAgentService = conversationAgentService;
|
|
334
356
|
this.activeTasks = activeTasks;
|
|
335
357
|
this.cdr = cdr;
|
|
358
|
+
this.mentionAutocompleteService = mentionAutocompleteService;
|
|
336
359
|
}
|
|
337
|
-
ngOnInit() {
|
|
360
|
+
async ngOnInit() {
|
|
361
|
+
// Initialize mention service BEFORE loading messages
|
|
362
|
+
// This ensures agents are loaded and available for @mention parsing in existing messages
|
|
363
|
+
await this.mentionAutocompleteService.initialize(this.currentUser);
|
|
338
364
|
// Load saved artifact pane width
|
|
339
365
|
this.loadArtifactPaneWidth();
|
|
340
366
|
// Initial load if there's already an active conversation
|
|
@@ -390,18 +416,41 @@ export class ConversationChatAreaComponent {
|
|
|
390
416
|
}
|
|
391
417
|
async loadMessages(conversationId) {
|
|
392
418
|
try {
|
|
393
|
-
//
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
419
|
+
// Check if we have cached data for this conversation
|
|
420
|
+
const cachedData = this.conversationDataCache.get(conversationId);
|
|
421
|
+
if (cachedData) {
|
|
422
|
+
// Use cached data - instant load!
|
|
423
|
+
console.log(`📦 Loading conversation ${conversationId} from cache - instant!`);
|
|
424
|
+
this.buildMessagesFromCache(cachedData);
|
|
425
|
+
this.loadPeripheralData(conversationId); // Process cached data for maps
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
// Load from database with single optimized query
|
|
429
|
+
console.log(`🔍 Loading conversation ${conversationId} from database - single query`);
|
|
430
|
+
const rq = new RunQuery();
|
|
431
|
+
const result = await rq.RunQuery({
|
|
432
|
+
QueryName: 'GetConversationComplete',
|
|
433
|
+
CategoryPath: 'MJ/Conversations',
|
|
434
|
+
Parameters: { ConversationID: conversationId }
|
|
435
|
+
}, this.currentUser);
|
|
436
|
+
if (!result.Success || !result.Results) {
|
|
437
|
+
console.error('Failed to load conversation data:', result.ErrorMessage);
|
|
438
|
+
this.messages = [];
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
// Cache the raw results for future use
|
|
442
|
+
const conversationData = result.Results;
|
|
443
|
+
this.conversationDataCache.set(conversationId, conversationData);
|
|
444
|
+
console.log(`💾 Cached ${conversationData.length} conversation details for conversation ${conversationId}`);
|
|
445
|
+
// Build messages and show immediately
|
|
446
|
+
this.buildMessagesFromCache(conversationData);
|
|
447
|
+
// Process peripheral data (agent runs & artifacts) in background
|
|
448
|
+
this.isLoadingPeripheralData = true;
|
|
449
|
+
this.loadPeripheralData(conversationId).finally(() => {
|
|
450
|
+
this.isLoadingPeripheralData = false;
|
|
451
|
+
this.cdr.detectChanges();
|
|
452
|
+
});
|
|
453
|
+
}
|
|
405
454
|
}
|
|
406
455
|
catch (error) {
|
|
407
456
|
console.error('Error loading messages:', error);
|
|
@@ -409,105 +458,112 @@ export class ConversationChatAreaComponent {
|
|
|
409
458
|
}
|
|
410
459
|
}
|
|
411
460
|
/**
|
|
412
|
-
*
|
|
413
|
-
*
|
|
461
|
+
* Build message entities from cached conversation data
|
|
462
|
+
* Creates ConversationDetailEntity objects from the raw query results
|
|
463
|
+
*/
|
|
464
|
+
async buildMessagesFromCache(conversationData) {
|
|
465
|
+
const md = new Metadata();
|
|
466
|
+
const messages = [];
|
|
467
|
+
for (const row of conversationData) {
|
|
468
|
+
if (!row.ID)
|
|
469
|
+
continue;
|
|
470
|
+
// Create entity object and load from raw data
|
|
471
|
+
const message = await md.GetEntityObject('Conversation Details', this.currentUser);
|
|
472
|
+
// LoadFromData expects the same structure as the query result
|
|
473
|
+
// Since we're using SELECT *, all fields should be present
|
|
474
|
+
message.LoadFromData(row);
|
|
475
|
+
messages.push(message);
|
|
476
|
+
}
|
|
477
|
+
this.messages = messages;
|
|
478
|
+
this.scrollToBottom = true;
|
|
479
|
+
this.cdr.detectChanges(); // Show messages immediately
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Process peripheral data (agent runs and artifacts) from cached conversation data
|
|
483
|
+
* Parses JSON columns and builds maps for display
|
|
484
|
+
*
|
|
485
|
+
* PERFORMANCE OPTIMIZATION: Uses cached data instead of querying
|
|
486
|
+
* - Data already loaded by loadMessages() - no additional queries needed
|
|
487
|
+
* - Processes cached JSON data to build display maps
|
|
488
|
+
* - Instant when switching between conversations
|
|
414
489
|
*/
|
|
415
490
|
async loadPeripheralData(conversationId) {
|
|
491
|
+
const timestamp = new Date().toISOString();
|
|
492
|
+
// Skip if we've already processed peripheral data for this conversation
|
|
493
|
+
if (this.lastLoadedConversationId === conversationId) {
|
|
494
|
+
console.log(`[${timestamp}] ⏭️ Skipping peripheral data processing - already processed for conversation ${conversationId}`);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
// Mark this conversation as processed to prevent duplicate processing
|
|
498
|
+
this.lastLoadedConversationId = conversationId;
|
|
499
|
+
console.log(`[${timestamp}] 📊 Processing peripheral data for conversation ${conversationId} from cache`);
|
|
416
500
|
try {
|
|
417
|
-
|
|
501
|
+
// Get cached data - should always be present by the time we get here
|
|
502
|
+
const conversationData = this.conversationDataCache.get(conversationId);
|
|
503
|
+
if (!conversationData) {
|
|
504
|
+
console.warn(`No cached data found for conversation ${conversationId}`);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
418
507
|
const md = new Metadata();
|
|
419
|
-
|
|
420
|
-
// Load agent runs and artifacts in parallel
|
|
421
|
-
const [agentRunsResult, conversationDetailArtifacts] = await Promise.all([
|
|
422
|
-
rv.RunView({
|
|
423
|
-
EntityName: 'MJ: AI Agent Runs',
|
|
424
|
-
ExtraFilter: `ConversationDetailID IN (SELECT ID FROM [${convoDetailEntity.SchemaName}].[${convoDetailEntity.BaseView}] WHERE ConversationID='${conversationId}')`,
|
|
425
|
-
ResultType: 'entity_object',
|
|
426
|
-
// Only fetch fields we actually display to reduce payload size
|
|
427
|
-
Fields: ['ID', 'AgentID', 'Agent', 'Status', '__mj_CreatedAt', '__mj_UpdatedAt', 'TotalPromptTokensUsed', 'TotalCompletionTokensUsed', 'TotalCost', 'ConversationDetailID']
|
|
428
|
-
}, this.currentUser),
|
|
429
|
-
rv.RunView({
|
|
430
|
-
EntityName: 'MJ: Conversation Detail Artifacts',
|
|
431
|
-
ExtraFilter: `ConversationDetailID IN (SELECT ID FROM [${convoDetailEntity.SchemaName}].[${convoDetailEntity.BaseView}] WHERE ConversationID='${conversationId}') AND Direction='Output'`,
|
|
432
|
-
ResultType: 'entity_object'
|
|
433
|
-
}, this.currentUser)
|
|
434
|
-
]);
|
|
435
|
-
// Build agent runs map - single query loads all runs for this conversation
|
|
508
|
+
// Clear and rebuild maps from cached data
|
|
436
509
|
this.agentRunsByDetailId.clear();
|
|
437
|
-
if (agentRunsResult.Success && agentRunsResult.Results) {
|
|
438
|
-
for (const run of agentRunsResult.Results) {
|
|
439
|
-
if (run.ConversationDetailID) {
|
|
440
|
-
this.agentRunsByDetailId.set(run.ConversationDetailID, run);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
// Build artifact map from preloaded artifacts
|
|
445
510
|
this.artifactsByDetailId.clear();
|
|
446
|
-
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
if (
|
|
455
|
-
//
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
for (const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
existing.push({
|
|
482
|
-
artifact: artifact, // Full ArtifactEntity
|
|
483
|
-
version: version // Full ArtifactVersionEntity
|
|
484
|
-
});
|
|
485
|
-
this.artifactsByDetailId.set(junctionRecord.ConversationDetailID, existing);
|
|
486
|
-
}
|
|
511
|
+
for (const row of conversationData) {
|
|
512
|
+
// Skip rows without ID (should never happen, but type safety check)
|
|
513
|
+
if (!row.ID) {
|
|
514
|
+
console.warn('Skipping conversation detail row without ID');
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
const parsed = parseConversationDetailComplete(row);
|
|
518
|
+
// Build agent runs map
|
|
519
|
+
if (parsed.agentRuns.length > 0) {
|
|
520
|
+
// Convert AgentRunJSON to AIAgentRunEntityExtended
|
|
521
|
+
const agentRunData = parsed.agentRuns[0]; // Should only be one per detail
|
|
522
|
+
const agentRun = await md.GetEntityObject('MJ: AI Agent Runs', this.currentUser);
|
|
523
|
+
// Convert ISO date strings to Date objects
|
|
524
|
+
agentRun.LoadFromData({
|
|
525
|
+
ID: agentRunData.ID,
|
|
526
|
+
AgentID: agentRunData.AgentID,
|
|
527
|
+
Agent: agentRunData.Agent,
|
|
528
|
+
Status: agentRunData.Status,
|
|
529
|
+
__mj_CreatedAt: new Date(agentRunData.__mj_CreatedAt),
|
|
530
|
+
__mj_UpdatedAt: new Date(agentRunData.__mj_UpdatedAt),
|
|
531
|
+
TotalPromptTokensUsed: agentRunData.TotalPromptTokensUsed,
|
|
532
|
+
TotalCompletionTokensUsed: agentRunData.TotalCompletionTokensUsed,
|
|
533
|
+
TotalCost: agentRunData.TotalCost,
|
|
534
|
+
ConversationDetailID: agentRunData.ConversationDetailID
|
|
535
|
+
});
|
|
536
|
+
this.agentRunsByDetailId.set(row.ID, agentRun);
|
|
537
|
+
}
|
|
538
|
+
// Build artifacts map - no need to load full entities, just create LazyArtifactInfo
|
|
539
|
+
if (parsed.artifacts.length > 0) {
|
|
540
|
+
const artifactList = [];
|
|
541
|
+
for (const artifactData of parsed.artifacts) {
|
|
542
|
+
// Create LazyArtifactInfo with display data from query
|
|
543
|
+
// Full entities will be loaded on-demand when artifact is clicked
|
|
544
|
+
const lazyInfo = new LazyArtifactInfo(artifactData, this.currentUser);
|
|
545
|
+
artifactList.push(lazyInfo);
|
|
487
546
|
}
|
|
488
|
-
|
|
489
|
-
this.artifactsByDetailId = new Map(this.artifactsByDetailId);
|
|
490
|
-
console.log(`📦 Preloaded ${this.artifactsByDetailId.size} artifacts for conversation ${conversationId}`);
|
|
547
|
+
this.artifactsByDetailId.set(row.ID, artifactList);
|
|
491
548
|
}
|
|
492
549
|
}
|
|
550
|
+
// Create new Map references to trigger Angular change detection
|
|
551
|
+
this.agentRunsByDetailId = new Map(this.agentRunsByDetailId);
|
|
552
|
+
this.artifactsByDetailId = new Map(this.artifactsByDetailId);
|
|
493
553
|
// Update artifact count for header display (unique artifacts, not versions)
|
|
494
554
|
this.artifactCount = this.calculateUniqueArtifactCount();
|
|
495
|
-
// Debug: Log
|
|
496
|
-
console.log(`📊
|
|
497
|
-
console.log(`📦 Artifacts by Detail ID:`, Array.from(this.artifactsByDetailId.entries()).flatMap(([detailId, artifactList]) => artifactList.map(info => ({
|
|
498
|
-
conversationDetailId: detailId,
|
|
499
|
-
artifactId: info.artifact.ID,
|
|
500
|
-
artifactName: info.artifact.Name,
|
|
501
|
-
versionId: info.version.ID,
|
|
502
|
-
versionNumber: info.version.VersionNumber
|
|
503
|
-
}))));
|
|
555
|
+
// Debug: Log summary
|
|
556
|
+
console.log(`📊 Processed ${this.agentRunsByDetailId.size} agent runs, ${this.artifactsByDetailId.size} artifact mappings (${this.artifactCount} unique artifacts)`);
|
|
504
557
|
// CRITICAL: Trigger message re-render now that agent runs and artifacts are loaded
|
|
505
558
|
// This updates all message components with the newly loaded agent run data
|
|
506
559
|
this.messages = [...this.messages]; // Create new array reference to trigger change detection
|
|
507
560
|
this.cdr.detectChanges();
|
|
561
|
+
console.log(`✅ Peripheral data processed successfully for conversation ${conversationId} from cache`);
|
|
508
562
|
}
|
|
509
563
|
catch (error) {
|
|
510
|
-
console.error('Failed to
|
|
564
|
+
console.error('Failed to process peripheral data:', error);
|
|
565
|
+
// Don't set lastLoadedConversationId on error so we can retry
|
|
566
|
+
this.lastLoadedConversationId = null;
|
|
511
567
|
}
|
|
512
568
|
}
|
|
513
569
|
/**
|
|
@@ -548,6 +604,11 @@ export class ConversationChatAreaComponent {
|
|
|
548
604
|
async onAgentResponse(event) {
|
|
549
605
|
// Add the agent's response message to the conversation
|
|
550
606
|
this.messages = [...this.messages, event.message];
|
|
607
|
+
// Invalidate cache for this conversation since we have new messages
|
|
608
|
+
const conversationId = this.conversationState.activeConversationId;
|
|
609
|
+
if (conversationId) {
|
|
610
|
+
this.invalidateConversationCache(conversationId);
|
|
611
|
+
}
|
|
551
612
|
// Scroll to bottom when agent responds
|
|
552
613
|
this.scrollToBottom = true;
|
|
553
614
|
// Add agent run to the map if present (fallback if not already loaded from progress)
|
|
@@ -564,24 +625,38 @@ export class ConversationChatAreaComponent {
|
|
|
564
625
|
if (this.artifactsByDetailId.has(event.message.ID) && !this.showArtifactPanel) {
|
|
565
626
|
const artifactList = this.artifactsByDetailId.get(event.message.ID);
|
|
566
627
|
if (artifactList && artifactList.length > 0) {
|
|
567
|
-
// Show the
|
|
568
|
-
this.selectedArtifactId = artifactList[
|
|
628
|
+
// Show the LAST (most recent) artifact - uses display data, no lazy load needed
|
|
629
|
+
this.selectedArtifactId = artifactList[artifactList.length - 1].artifactId;
|
|
569
630
|
this.showArtifactPanel = true;
|
|
570
631
|
}
|
|
571
632
|
}
|
|
572
633
|
// Force change detection to update the UI
|
|
573
634
|
this.cdr.detectChanges();
|
|
574
635
|
}
|
|
636
|
+
/**
|
|
637
|
+
* Invalidate cached conversation data
|
|
638
|
+
* Called when new messages are added or conversation data changes
|
|
639
|
+
*/
|
|
640
|
+
invalidateConversationCache(conversationId) {
|
|
641
|
+
this.conversationDataCache.delete(conversationId);
|
|
642
|
+
console.log(`🗑️ Invalidated cache for conversation ${conversationId}`);
|
|
643
|
+
}
|
|
575
644
|
/**
|
|
576
645
|
* Add or update an agent run in the map
|
|
577
646
|
* Called when a new agent run completes to keep the map in sync
|
|
578
647
|
*/
|
|
579
648
|
async addAgentRunToMap(conversationDetailId, agentRunId) {
|
|
580
649
|
try {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
650
|
+
if (!this.agentRunsByDetailId.has(conversationDetailId)) {
|
|
651
|
+
const md = new Metadata();
|
|
652
|
+
const agentRun = await md.GetEntityObject('MJ: AI Agent Runs', this.currentUser);
|
|
653
|
+
if (await agentRun.Load(agentRunId)) {
|
|
654
|
+
this.agentRunsByDetailId.set(conversationDetailId, agentRun);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
// nothing to do, temp console log to catch how many of these where we were wasting time
|
|
659
|
+
console.log(`⏭️ Agent run for detail ${conversationDetailId} already in map, skipping load`);
|
|
585
660
|
}
|
|
586
661
|
}
|
|
587
662
|
catch (error) {
|
|
@@ -591,68 +666,55 @@ export class ConversationChatAreaComponent {
|
|
|
591
666
|
/**
|
|
592
667
|
* Reload artifacts for a specific message ID
|
|
593
668
|
* Called after an artifact is created to update the UI immediately
|
|
669
|
+
* Invalidates and refreshes the conversation cache
|
|
594
670
|
*/
|
|
595
671
|
async reloadArtifactsForMessage(conversationDetailId) {
|
|
596
672
|
console.log(`🔄 Reloading artifacts for message ${conversationDetailId}`);
|
|
597
673
|
try {
|
|
598
|
-
const
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
674
|
+
const rq = new RunQuery();
|
|
675
|
+
const md = new Metadata();
|
|
676
|
+
// Get the ConversationID for this detail
|
|
677
|
+
const detail = await md.GetEntityObject('Conversation Details', this.currentUser);
|
|
678
|
+
if (!(await detail.Load(conversationDetailId))) {
|
|
679
|
+
console.error('Failed to load conversation detail');
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
// Invalidate cache since artifacts changed
|
|
683
|
+
this.invalidateConversationCache(detail.ConversationID);
|
|
684
|
+
// Use optimized single query to reload all conversation data
|
|
685
|
+
const result = await rq.RunQuery({
|
|
686
|
+
QueryName: 'GetConversationComplete',
|
|
687
|
+
CategoryPath: '/MJ/Conversations',
|
|
688
|
+
Parameters: { ConversationID: detail.ConversationID }
|
|
603
689
|
}, this.currentUser);
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
});
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const artifactIds = versionsResult.Results.map(v => `'${v.ArtifactID}'`).join(',');
|
|
620
|
-
const fullArtifactsResult = await rv.RunView({
|
|
621
|
-
EntityName: 'MJ: Artifacts',
|
|
622
|
-
ExtraFilter: `ID IN (${artifactIds})`,
|
|
623
|
-
ResultType: 'entity_object'
|
|
624
|
-
}, this.currentUser);
|
|
625
|
-
if (fullArtifactsResult.Success && fullArtifactsResult.Results) {
|
|
626
|
-
// Create maps for fast lookup
|
|
627
|
-
const artifactEntities = new Map();
|
|
628
|
-
const versionEntities = new Map();
|
|
629
|
-
for (const artifact of fullArtifactsResult.Results) {
|
|
630
|
-
artifactEntities.set(artifact.ID, artifact);
|
|
631
|
-
}
|
|
632
|
-
for (const version of versionsResult.Results) {
|
|
633
|
-
versionEntities.set(version.ID, version);
|
|
634
|
-
}
|
|
635
|
-
// Update artifact map with full entities (supports multiple artifacts per detail)
|
|
690
|
+
if (!result.Success || !result.Results) {
|
|
691
|
+
console.error('Failed to reload artifacts:', result.ErrorMessage);
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
console.log(`📊 Query result: ${result.Results.length} conversation details loaded`);
|
|
695
|
+
// Update cache with fresh data
|
|
696
|
+
const conversationData = result.Results;
|
|
697
|
+
this.conversationDataCache.set(detail.ConversationID, conversationData);
|
|
698
|
+
// Find the specific conversation detail we're reloading and update its artifacts
|
|
699
|
+
for (const row of conversationData) {
|
|
700
|
+
if (row.ID === conversationDetailId) {
|
|
701
|
+
const parsed = parseConversationDetailComplete(row);
|
|
702
|
+
// Clear existing artifacts for this detail and rebuild
|
|
703
|
+
this.artifactsByDetailId.delete(conversationDetailId);
|
|
704
|
+
if (parsed.artifacts.length > 0) {
|
|
636
705
|
const artifactList = [];
|
|
637
|
-
for (const
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
artifactList.push({
|
|
642
|
-
artifact: artifact,
|
|
643
|
-
version: version
|
|
644
|
-
});
|
|
645
|
-
console.log(`✅ Loaded artifact ${artifact.ID} v${version.VersionNumber} for message ${conversationDetailId}`);
|
|
646
|
-
}
|
|
706
|
+
for (const artifactData of parsed.artifacts) {
|
|
707
|
+
const lazyInfo = new LazyArtifactInfo(artifactData, this.currentUser);
|
|
708
|
+
artifactList.push(lazyInfo);
|
|
709
|
+
console.log(`✅ Loaded artifact ${artifactData.ArtifactID} v${artifactData.VersionNumber} for message ${conversationDetailId}`);
|
|
647
710
|
}
|
|
648
|
-
|
|
649
|
-
this.artifactsByDetailId.set(conversationDetailId, artifactList);
|
|
650
|
-
}
|
|
651
|
-
// Create new Map reference to trigger Angular change detection
|
|
652
|
-
this.artifactsByDetailId = new Map(this.artifactsByDetailId);
|
|
653
|
-
// Update artifact count
|
|
654
|
-
this.artifactCount = this.calculateUniqueArtifactCount();
|
|
711
|
+
this.artifactsByDetailId.set(conversationDetailId, artifactList);
|
|
655
712
|
}
|
|
713
|
+
// Create new Map reference to trigger Angular change detection
|
|
714
|
+
this.artifactsByDetailId = new Map(this.artifactsByDetailId);
|
|
715
|
+
// Update artifact count
|
|
716
|
+
this.artifactCount = this.calculateUniqueArtifactCount();
|
|
717
|
+
break; // Found and updated the target message
|
|
656
718
|
}
|
|
657
719
|
}
|
|
658
720
|
}
|
|
@@ -671,12 +733,13 @@ export class ConversationChatAreaComponent {
|
|
|
671
733
|
}
|
|
672
734
|
/**
|
|
673
735
|
* Calculate count of unique artifacts (not versions)
|
|
736
|
+
* Works with LazyArtifactInfo - uses artifactId from display data
|
|
674
737
|
*/
|
|
675
738
|
calculateUniqueArtifactCount() {
|
|
676
739
|
const uniqueArtifactIds = new Set();
|
|
677
740
|
for (const artifactList of this.artifactsByDetailId.values()) {
|
|
678
741
|
for (const info of artifactList) {
|
|
679
|
-
uniqueArtifactIds.add(info.
|
|
742
|
+
uniqueArtifactIds.add(info.artifactId);
|
|
680
743
|
}
|
|
681
744
|
}
|
|
682
745
|
return uniqueArtifactIds.size;
|
|
@@ -684,16 +747,17 @@ export class ConversationChatAreaComponent {
|
|
|
684
747
|
/**
|
|
685
748
|
* Get unique artifacts grouped by artifact ID (not by conversation detail)
|
|
686
749
|
* Returns the latest version info for each unique artifact with all versions
|
|
750
|
+
* Works with LazyArtifactInfo - uses display data without loading full entities
|
|
687
751
|
*/
|
|
688
752
|
getArtifactsArray() {
|
|
689
753
|
const artifactMap = new Map();
|
|
690
754
|
// Group by artifactId, collecting all version details
|
|
691
755
|
for (const artifactList of this.artifactsByDetailId.values()) {
|
|
692
756
|
for (const info of artifactList) {
|
|
693
|
-
const artifactId = info.
|
|
694
|
-
const versionId = info.
|
|
695
|
-
const versionNumber = info.
|
|
696
|
-
const name = info.
|
|
757
|
+
const artifactId = info.artifactId;
|
|
758
|
+
const versionId = info.artifactVersionId;
|
|
759
|
+
const versionNumber = info.versionNumber || 1;
|
|
760
|
+
const name = info.artifactName || 'Untitled';
|
|
697
761
|
if (!artifactMap.has(artifactId)) {
|
|
698
762
|
artifactMap.set(artifactId, {
|
|
699
763
|
artifactId: artifactId,
|
|
@@ -807,6 +871,19 @@ export class ConversationChatAreaComponent {
|
|
|
807
871
|
// The message entity is already updated in place, so no need to reload
|
|
808
872
|
// Just ensure the UI reflects the changes
|
|
809
873
|
}
|
|
874
|
+
/**
|
|
875
|
+
* Handle suggested response selection from user
|
|
876
|
+
* Sends the selected response as a new user message WITHOUT modifying the visible input
|
|
877
|
+
*/
|
|
878
|
+
async onSuggestedResponseSelected(event) {
|
|
879
|
+
const messageText = event.customInput || event.text;
|
|
880
|
+
if (this.messageInputComponent) {
|
|
881
|
+
await this.messageInputComponent.sendMessageWithText(messageText);
|
|
882
|
+
}
|
|
883
|
+
else {
|
|
884
|
+
console.error('MessageInputComponent not available');
|
|
885
|
+
}
|
|
886
|
+
}
|
|
810
887
|
onRetryMessage(message) {
|
|
811
888
|
// TODO: Implement retry logic
|
|
812
889
|
// This should find the parent user message and re-trigger the agent invocation
|
|
@@ -815,12 +892,12 @@ export class ConversationChatAreaComponent {
|
|
|
815
892
|
}
|
|
816
893
|
onArtifactClicked(data) {
|
|
817
894
|
this.selectedArtifactId = data.artifactId;
|
|
818
|
-
// If versionId is provided, find the version number
|
|
895
|
+
// If versionId is provided, find the version number from display data (no lazy load needed)
|
|
819
896
|
if (data.versionId) {
|
|
820
897
|
for (const [detailId, artifactList] of this.artifactsByDetailId.entries()) {
|
|
821
898
|
for (const artifactInfo of artifactList) {
|
|
822
|
-
if (artifactInfo.
|
|
823
|
-
this.selectedVersionNumber = artifactInfo.
|
|
899
|
+
if (artifactInfo.artifactVersionId === data.versionId) {
|
|
900
|
+
this.selectedVersionNumber = artifactInfo.versionNumber;
|
|
824
901
|
console.log(`📦 Opening artifact viewer for v${this.selectedVersionNumber}`);
|
|
825
902
|
break;
|
|
826
903
|
}
|
|
@@ -853,6 +930,28 @@ export class ConversationChatAreaComponent {
|
|
|
853
930
|
this.showArtifactPanel = false;
|
|
854
931
|
this.selectedArtifactId = null;
|
|
855
932
|
}
|
|
933
|
+
onSaveToCollectionRequested(event) {
|
|
934
|
+
this.collectionPickerArtifactId = event.artifactId;
|
|
935
|
+
this.collectionPickerExcludedIds = event.excludedCollectionIds;
|
|
936
|
+
this.showCollectionPicker = true;
|
|
937
|
+
}
|
|
938
|
+
async onCollectionPickerSaved(collectionIds) {
|
|
939
|
+
if (!this.collectionPickerArtifactId || !this.artifactViewerComponent) {
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
// Call the artifact viewer's save method
|
|
943
|
+
const success = await this.artifactViewerComponent.saveToCollections(collectionIds);
|
|
944
|
+
if (success) {
|
|
945
|
+
this.showCollectionPicker = false;
|
|
946
|
+
this.collectionPickerArtifactId = null;
|
|
947
|
+
this.collectionPickerExcludedIds = [];
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
onCollectionPickerCancelled() {
|
|
951
|
+
this.showCollectionPicker = false;
|
|
952
|
+
this.collectionPickerArtifactId = null;
|
|
953
|
+
this.collectionPickerExcludedIds = [];
|
|
954
|
+
}
|
|
856
955
|
/**
|
|
857
956
|
* Helper method to check if a conversation detail has an artifact
|
|
858
957
|
* Used by message components to determine whether to show artifact card
|
|
@@ -862,15 +961,19 @@ export class ConversationChatAreaComponent {
|
|
|
862
961
|
}
|
|
863
962
|
/**
|
|
864
963
|
* Get artifact info for a conversation detail
|
|
865
|
-
* Returns the
|
|
964
|
+
* Returns the LAST (most recent) artifact if multiple exist
|
|
965
|
+
* Returns LazyArtifactInfo - caller can trigger lazy load if full entities needed
|
|
866
966
|
*/
|
|
867
967
|
getArtifactInfo(conversationDetailId) {
|
|
868
968
|
const artifactList = this.artifactsByDetailId.get(conversationDetailId);
|
|
869
|
-
return artifactList && artifactList.length > 0
|
|
969
|
+
return artifactList && artifactList.length > 0
|
|
970
|
+
? artifactList[artifactList.length - 1]
|
|
971
|
+
: undefined;
|
|
870
972
|
}
|
|
871
973
|
/**
|
|
872
974
|
* Get ALL artifacts for a conversation detail
|
|
873
975
|
* Use this when you need to display all artifacts (e.g., in a list)
|
|
976
|
+
* Returns LazyArtifactInfo array - caller can trigger lazy load if full entities needed
|
|
874
977
|
*/
|
|
875
978
|
getAllArtifactsForDetail(conversationDetailId) {
|
|
876
979
|
return this.artifactsByDetailId.get(conversationDetailId) || [];
|
|
@@ -981,20 +1084,24 @@ export class ConversationChatAreaComponent {
|
|
|
981
1084
|
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
|
|
982
1085
|
}
|
|
983
1086
|
}
|
|
984
|
-
static ɵfac = function ConversationChatAreaComponent_Factory(t) { return new (t || ConversationChatAreaComponent)(i0.ɵɵdirectiveInject(i1.ConversationStateService), i0.ɵɵdirectiveInject(i2.
|
|
1087
|
+
static ɵfac = function ConversationChatAreaComponent_Factory(t) { return new (t || ConversationChatAreaComponent)(i0.ɵɵdirectiveInject(i1.ConversationStateService), i0.ɵɵdirectiveInject(i2.AgentStateService), i0.ɵɵdirectiveInject(i3.ConversationAgentService), i0.ɵɵdirectiveInject(i4.ActiveTasksService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i5.MentionAutocompleteService)); };
|
|
985
1088
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ConversationChatAreaComponent, selectors: [["mj-conversation-chat-area"]], viewQuery: function ConversationChatAreaComponent_Query(rf, ctx) { if (rf & 1) {
|
|
986
1089
|
i0.ɵɵviewQuery(_c0, 5);
|
|
1090
|
+
i0.ɵɵviewQuery(MessageInputComponent, 5);
|
|
1091
|
+
i0.ɵɵviewQuery(ArtifactViewerPanelComponent, 5);
|
|
987
1092
|
} if (rf & 2) {
|
|
988
1093
|
let _t;
|
|
989
1094
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.scrollContainer = _t.first);
|
|
990
|
-
|
|
1095
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.messageInputComponent = _t.first);
|
|
1096
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.artifactViewerComponent = _t.first);
|
|
1097
|
+
} }, inputs: { environmentId: "environmentId", currentUser: "currentUser" }, outputs: { conversationRenamed: "conversationRenamed", openEntityRecord: "openEntityRecord", taskClicked: "taskClicked" }, decls: 19, vars: 22, consts: [["scrollContainer", ""], [1, "chat-area"], ["class", "chat-header", 4, "ngIf"], [1, "chat-content-area"], [1, "chat-messages-pane"], [1, "chat-messages-wrapper"], [1, "chat-messages-container", 3, "scroll"], [3, "replyInThread", "viewThread", "retryMessage", "artifactClicked", "messageEdited", "openEntityRecord", "suggestedResponseSelected", "messages", "conversation", "currentUser", "isProcessing", "artifactMap", "agentRunMap"], ["class", "scroll-to-bottom-icon", "style", "left: 50%;", 3, "click", 4, "ngIf"], [1, "chat-input-container"], [1, "loading-peripheral-placeholder"], [3, "conversationId", "currentUser", "conversationHistory", "disabled"], [3, "parentMessageId", "conversationId", "currentUser"], [3, "cancelled", "exported", "isVisible", "conversation", "currentUser"], [3, "cancelled", "membersChanged", "isVisible", "conversation", "currentUser"], [1, "modal-overlay"], [3, "isOpen", "environmentId", "currentUser", "excludeCollectionIds"], [1, "chat-header"], [1, "chat-info"], [1, "chat-title"], ["class", "project-tag", "title", "Assign to project", 3, "click", 4, "ngIf"], ["title", "View members", 1, "chat-members", 3, "click"], [1, "fas", "fa-users"], ["class", "artifact-indicator", "title", "View artifacts", 3, "click", 4, "ngIf"], [3, "togglePanel", "agentSelected", "conversationId", "currentUser"], [1, "chat-actions"], [3, "taskClicked", "currentUser"], ["title", "Export conversation", 1, "action-btn", 3, "click"], [1, "fas", "fa-download"], [1, "action-btn", "share-btn", 3, "click", "title"], [1, "fas", "fa-share-nodes"], ["title", "Assign to project", 1, "project-tag", 3, "click"], [1, "fas", "fa-folder"], ["title", "View artifacts", 1, "artifact-indicator", 3, "click"], [1, "fas", "fa-cube"], [1, "scroll-to-bottom-icon", 2, "left", "50%", 3, "click"], [1, "fas", "fa-arrow-down"], [1, "loading-peripheral-content"], [1, "fas", "fa-spinner", "fa-spin"], [3, "conversationId", "currentUser", "conversationHistory", "disabled", "messageSent", "agentResponse", "agentRunDetected", "artifactCreated", "conversationRenamed", 4, "ngIf"], [3, "messageSent", "agentResponse", "agentRunDetected", "artifactCreated", "conversationRenamed", "conversationId", "currentUser", "conversationHistory", "disabled"], [1, "resize-handle", 3, "mousedown"], [1, "chat-artifact-pane"], [3, "closed", "saveToCollectionRequested", "artifactId", "currentUser", "environmentId", "versionNumber", "refreshTrigger"], [3, "closed", "replyAdded", "parentMessageId", "conversationId", "currentUser"], [1, "modal-overlay", 3, "click"], [1, "modal-content", "project-selector-modal", 3, "click"], [1, "modal-header"], [1, "modal-close-btn", 3, "click"], [1, "fas", "fa-times"], [1, "modal-body"], [3, "projectSelected", "environmentId", "currentUser", "selectedProjectId"], [1, "modal-content", "artifacts-modal", 3, "click"], [1, "modal-body", "artifacts-grid"], [1, "empty-state"], [1, "artifact-modal-card", 3, "expanded"], [1, "fas", "fa-cube", 2, "font-size", "48px", "color", "#D1D5DB", "margin-bottom", "16px"], [2, "color", "#6B7280", "font-size", "14px"], [1, "artifact-modal-card"], [1, "artifact-card-header", 3, "click"], [1, "artifact-modal-icon"], [1, "fas", "fa-file-code"], [1, "artifact-modal-info"], [1, "artifact-modal-title"], [1, "artifact-modal-meta"], [1, "expand-btn"], [1, "artifact-modal-action"], [1, "fas", "fa-external-link-alt"], [1, "artifact-versions-list"], [1, "expand-btn", 3, "click"], [1, "fas"], [1, "artifact-version-item"], [1, "artifact-version-item", 3, "click"], [1, "version-badge"], [1, "version-open-text"], [1, "fas", "fa-arrow-right"], [3, "saved", "cancelled", "isOpen", "environmentId", "currentUser", "excludeCollectionIds"]], template: function ConversationChatAreaComponent_Template(rf, ctx) { if (rf & 1) {
|
|
991
1098
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
992
1099
|
i0.ɵɵelementStart(0, "div", 1);
|
|
993
1100
|
i0.ɵɵtemplate(1, ConversationChatAreaComponent_div_1_Template, 19, 11, "div", 2);
|
|
994
1101
|
i0.ɵɵelementStart(2, "div", 3)(3, "div", 4)(4, "div", 5)(5, "div", 6, 0);
|
|
995
1102
|
i0.ɵɵlistener("scroll", function ConversationChatAreaComponent_Template_div_scroll_5_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.checkScroll()); });
|
|
996
1103
|
i0.ɵɵelementStart(7, "mj-conversation-message-list", 7);
|
|
997
|
-
i0.ɵɵlistener("replyInThread", function ConversationChatAreaComponent_Template_mj_conversation_message_list_replyInThread_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onReplyInThread($event)); })("viewThread", function ConversationChatAreaComponent_Template_mj_conversation_message_list_viewThread_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onViewThread($event)); })("retryMessage", function ConversationChatAreaComponent_Template_mj_conversation_message_list_retryMessage_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onRetryMessage($event)); })("artifactClicked", function ConversationChatAreaComponent_Template_mj_conversation_message_list_artifactClicked_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onArtifactClicked($event)); })("messageEdited", function ConversationChatAreaComponent_Template_mj_conversation_message_list_messageEdited_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onMessageEdited($event)); })("openEntityRecord", function ConversationChatAreaComponent_Template_mj_conversation_message_list_openEntityRecord_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onOpenEntityRecord($event)); });
|
|
1104
|
+
i0.ɵɵlistener("replyInThread", function ConversationChatAreaComponent_Template_mj_conversation_message_list_replyInThread_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onReplyInThread($event)); })("viewThread", function ConversationChatAreaComponent_Template_mj_conversation_message_list_viewThread_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onViewThread($event)); })("retryMessage", function ConversationChatAreaComponent_Template_mj_conversation_message_list_retryMessage_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onRetryMessage($event)); })("artifactClicked", function ConversationChatAreaComponent_Template_mj_conversation_message_list_artifactClicked_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onArtifactClicked($event)); })("messageEdited", function ConversationChatAreaComponent_Template_mj_conversation_message_list_messageEdited_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onMessageEdited($event)); })("openEntityRecord", function ConversationChatAreaComponent_Template_mj_conversation_message_list_openEntityRecord_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onOpenEntityRecord($event)); })("suggestedResponseSelected", function ConversationChatAreaComponent_Template_mj_conversation_message_list_suggestedResponseSelected_7_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSuggestedResponseSelected($event)); });
|
|
998
1105
|
i0.ɵɵelementEnd();
|
|
999
1106
|
i0.ɵɵtemplate(8, ConversationChatAreaComponent_span_8_Template, 2, 0, "span", 8);
|
|
1000
1107
|
i0.ɵɵelementEnd();
|
|
@@ -1010,7 +1117,7 @@ export class ConversationChatAreaComponent {
|
|
|
1010
1117
|
i0.ɵɵelementStart(15, "mj-members-modal", 14);
|
|
1011
1118
|
i0.ɵɵlistener("cancelled", function ConversationChatAreaComponent_Template_mj_members_modal_cancelled_15_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.showMembersModal = false); })("membersChanged", function ConversationChatAreaComponent_Template_mj_members_modal_membersChanged_15_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.showMembersModal = false); });
|
|
1012
1119
|
i0.ɵɵelementEnd();
|
|
1013
|
-
i0.ɵɵtemplate(16, ConversationChatAreaComponent_Conditional_16_Template, 9, 3, "div", 15)(17, ConversationChatAreaComponent_Conditional_17_Template, 11, 1, "div", 15);
|
|
1120
|
+
i0.ɵɵtemplate(16, ConversationChatAreaComponent_Conditional_16_Template, 9, 3, "div", 15)(17, ConversationChatAreaComponent_Conditional_17_Template, 11, 1, "div", 15)(18, ConversationChatAreaComponent_Conditional_18_Template, 1, 4, "mj-artifact-collection-picker-modal", 16);
|
|
1014
1121
|
} if (rf & 2) {
|
|
1015
1122
|
i0.ɵɵadvance();
|
|
1016
1123
|
i0.ɵɵproperty("ngIf", ctx.conversationState.activeConversation);
|
|
@@ -1034,12 +1141,14 @@ export class ConversationChatAreaComponent {
|
|
|
1034
1141
|
i0.ɵɵconditional(ctx.showProjectSelector && ctx.conversationState.activeConversation ? 16 : -1);
|
|
1035
1142
|
i0.ɵɵadvance();
|
|
1036
1143
|
i0.ɵɵconditional(ctx.showArtifactsModal ? 17 : -1);
|
|
1037
|
-
} }, dependencies: [i6.NgIf, i7.ArtifactViewerPanelComponent, i8.MessageListComponent, i9.MessageInputComponent, i10.ThreadPanelComponent, i11.ProjectSelectorComponent, i12.TasksDropdownComponent, i13.ActiveAgentIndicatorComponent, i14.MembersModalComponent, i15.ExportModalComponent], styles: ["[_nghost-%COMP%] {\n display: flex;\n width: 100%;\n height: 100%;\n}\n.chat-area[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.chat-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n padding: 12px 20px;\n border-bottom: 1px solid #D9D9D9;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n background: #FFF;\n z-index: 10;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n.chat-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n.chat-title[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 600;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.project-tag[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: #F4F4F4;\n border: 1px solid #D9D9D9;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 28px;\n margin-left: 12px;\n}\n.project-tag[_ngcontent-%COMP%]:hover {\n background: #D9D9D9;\n border-color: #AAA;\n}\n.project-tag[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n.chat-members[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #F4F4F4;\n border: none;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 32px;\n}\n.chat-members[_ngcontent-%COMP%]:hover {\n background: #D9D9D9;\n color: #333;\n}\n.chat-members[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n.chat-members[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n}\n.artifact-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #3B82F6;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n color: white;\n cursor: pointer;\n transition: all 150ms ease;\n}\n.artifact-indicator[_ngcontent-%COMP%]:hover {\n background: #2563EB;\n}\n.ambient-agent-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #F3F4F6;\n border: 1px solid #D1D5DB;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n animation: _ngcontent-%COMP%_pulse 2s ease-in-out infinite;\n}\n.ambient-agent-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #0076B6;\n}\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n.chat-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n.action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px solid #E5E7EB;\n cursor: pointer;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n transition: all 150ms ease;\n}\n.action-btn[_ngcontent-%COMP%]:hover {\n background: #F9FAFB;\n color: #111827;\n}\n.share-btn.shared[_ngcontent-%COMP%] {\n background: #EFF6FF;\n border-color: #1e40af;\n color: #1e40af;\n}\n.share-btn.shared[_ngcontent-%COMP%]:hover {\n background: #DBEAFE;\n color: #1e3a8a;\n}\n.chat-content-area[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: row;\n position: relative;\n}\n.chat-messages-pane[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n min-width: 300px;\n overflow: hidden;\n transition: width 0.3s ease;\n}\n.chat-messages-pane.full-width[_ngcontent-%COMP%] {\n width: 100%;\n}\n.chat-messages-pane[_ngcontent-%COMP%]:not(.full-width) {\n flex: 1;\n}\n.resize-handle[_ngcontent-%COMP%] {\n width: 4px;\n background: transparent;\n cursor: col-resize;\n flex-shrink: 0;\n position: relative;\n transition: background-color 0.2s;\n}\n.resize-handle[_ngcontent-%COMP%]:hover {\n background: #3B82F6;\n}\n.resize-handle[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: -4px;\n right: -4px;\n top: 0;\n bottom: 0;\n}\n.chat-artifact-pane[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #FAFAFA;\n overflow: hidden;\n flex-shrink: 0;\n}\n.chat-artifact-pane[_ngcontent-%COMP%] > mj-artifact-viewer-panel[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: #FFF;\n min-height: 0;\n position: relative;\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%] {\n position: sticky;\n bottom: 21px; // 21px from bottom of visible scroll area (moved up 5px from original 16px)\n left: 50%;\n transform: translateX(-50%);\n width: 40px;\n height: 40px;\n margin-top: -40px; // Negative margin to not affect scroll height\n margin-left: auto;\n margin-right: auto;\n background: white;\n border: 1px solid #D1D5DB;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n z-index: 100;\n pointer-events: auto;\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%]:hover {\n background: #F3F4F6;\n border-color: #3B82F6;\n transform: translateX(-50%) translateY(-2px);\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6B7280;\n font-size: 16px;\n transition: color 0.2s;\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: #3B82F6;\n}\n.chat-input-container[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: #FFF;\n border-top: 1px solid #E5E7EB;\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] placeholder[_ngcontent-%COMP%] -[_ngcontent-%COMP%] replaces[_ngcontent-%COMP%] input[_ngcontent-%COMP%] while[_ngcontent-%COMP%] loading\n.loading-peripheral-placeholder[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 140px; // Match typical input area height\n padding: 24px;\n background: rgba(255, 255, 255, 0.5);\n backdrop-filter: blur(2px);\n border-radius: 12px;\n margin: 12px;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-in-out;\n}\n.modal-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n.modal-content[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n.project-selector-modal[_ngcontent-%COMP%] {\n width: 600px;\n height: 500px;\n}\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #E5E7EB;\n}\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n.modal-close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: #6B7280;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.2s;\n}\n.modal-close-btn[_ngcontent-%COMP%]:hover {\n background: #F3F4F6;\n color: #111827;\n}\n.modal-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 20px;\n}\n.artifacts-modal[_ngcontent-%COMP%] {\n width: 700px;\n max-height: 600px;\n}\n.artifacts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n.empty-state[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n.artifact-modal-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n background: white;\n border: 1.5px solid #E5E7EB;\n border-radius: 12px;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n.artifact-modal-card.expanded[_ngcontent-%COMP%] {\n border-color: #3B82F6;\n}\n.artifact-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n cursor: pointer;\n}\n.artifact-card-header[_ngcontent-%COMP%]:hover {\n background: #F9FAFB;\n}\n.artifact-modal-card[_ngcontent-%COMP%]:hover {\n border-color: #3B82F6;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n transform: translateY(-2px);\n}\n.artifact-modal-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%);\n border-radius: 10px;\n color: #3B82F6;\n flex-shrink: 0;\n}\n.artifact-modal-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n.artifact-modal-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.artifact-modal-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.artifact-modal-meta[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6B7280;\n}\n.artifact-modal-action[_ngcontent-%COMP%] {\n color: #9CA3AF;\n transition: color 0.2s;\n}\n.artifact-modal-card[_ngcontent-%COMP%]:hover .artifact-modal-action[_ngcontent-%COMP%] {\n color: #3B82F6;\n}\n.expand-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #6B7280;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #F3F4F6;\n color: #3B82F6;\n }\n}\n.artifact-versions-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n border-top: 1px solid #E5E7EB;\n background: #F9FAFB;\n}\n.artifact-version-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px 12px 68px; // Indent to align with title\n cursor: pointer;\n transition: background 0.15s;\n\n &:hover {\n background: #F3F4F6;\n }\n\n .version-badge {\n display: inline-block;\n padding: 4px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 12px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n }\n\n .version-open-text {\n flex: 1;\n font-size: 13px;\n color: #6B7280;\n }\n\n i {\n color: #9CA3AF;\n font-size: 12px;\n }\n\n &:hover {\n .version-badge {\n background: #4F46E5;\n color: white;\n }\n .version-open-text {\n color: #3B82F6;\n }\n i {\n color: #3B82F6;\n }\n }\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] content[_ngcontent-%COMP%] styling\n.loading-peripheral-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n background: white;\n border: 2px solid #E5E7EB;\n border-radius: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n color: #4B5563;\n font-size: 14px;\n font-weight: 500;\n\n i {\n font-size: 20px;\n color: #9333EA;\n }\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}"] });
|
|
1144
|
+
i0.ɵɵadvance();
|
|
1145
|
+
i0.ɵɵconditional(ctx.showCollectionPicker ? 18 : -1);
|
|
1146
|
+
} }, dependencies: [i6.NgIf, i7.ArtifactViewerPanelComponent, i8.ArtifactCollectionPickerModalComponent, i9.MessageListComponent, i10.MessageInputComponent, i11.ThreadPanelComponent, i12.ProjectSelectorComponent, i13.TasksDropdownComponent, i14.ActiveAgentIndicatorComponent, i15.MembersModalComponent, i16.ExportModalComponent], styles: ["[_nghost-%COMP%] {\n display: flex;\n width: 100%;\n height: 100%;\n}\n.chat-area[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.chat-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n padding: 12px 20px;\n border-bottom: 1px solid #D9D9D9;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n background: #FFF;\n z-index: 10;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n.chat-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n.chat-title[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 600;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.project-tag[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: #F4F4F4;\n border: 1px solid #D9D9D9;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 28px;\n margin-left: 12px;\n}\n.project-tag[_ngcontent-%COMP%]:hover {\n background: #D9D9D9;\n border-color: #AAA;\n}\n.project-tag[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n.chat-members[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #F4F4F4;\n border: none;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 32px;\n}\n.chat-members[_ngcontent-%COMP%]:hover {\n background: #D9D9D9;\n color: #333;\n}\n.chat-members[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n.chat-members[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n}\n.artifact-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #3B82F6;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n color: white;\n cursor: pointer;\n transition: all 150ms ease;\n}\n.artifact-indicator[_ngcontent-%COMP%]:hover {\n background: #2563EB;\n}\n.ambient-agent-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #F3F4F6;\n border: 1px solid #D1D5DB;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n animation: _ngcontent-%COMP%_pulse 2s ease-in-out infinite;\n}\n.ambient-agent-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #0076B6;\n}\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n.chat-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n.action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px solid #E5E7EB;\n cursor: pointer;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n transition: all 150ms ease;\n}\n.action-btn[_ngcontent-%COMP%]:hover {\n background: #F9FAFB;\n color: #111827;\n}\n.share-btn.shared[_ngcontent-%COMP%] {\n background: #EFF6FF;\n border-color: #1e40af;\n color: #1e40af;\n}\n.share-btn.shared[_ngcontent-%COMP%]:hover {\n background: #DBEAFE;\n color: #1e3a8a;\n}\n.chat-content-area[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: row;\n position: relative;\n}\n.chat-messages-pane[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n min-width: 300px;\n overflow: hidden;\n transition: width 0.3s ease;\n}\n.chat-messages-pane.full-width[_ngcontent-%COMP%] {\n width: 100%;\n}\n.chat-messages-pane[_ngcontent-%COMP%]:not(.full-width) {\n flex: 1;\n}\n.resize-handle[_ngcontent-%COMP%] {\n width: 4px;\n background: transparent;\n cursor: col-resize;\n flex-shrink: 0;\n position: relative;\n transition: background-color 0.2s;\n}\n.resize-handle[_ngcontent-%COMP%]:hover {\n background: #3B82F6;\n}\n.resize-handle[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: -4px;\n right: -4px;\n top: 0;\n bottom: 0;\n}\n.chat-artifact-pane[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #FAFAFA;\n overflow: hidden;\n flex-shrink: 0;\n}\n.chat-artifact-pane[_ngcontent-%COMP%] > mj-artifact-viewer-panel[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: #FFF;\n min-height: 0;\n position: relative;\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%] {\n position: sticky;\n bottom: 21px; // 21px from bottom of visible scroll area (moved up 5px from original 16px)\n left: 50%;\n transform: translateX(-50%);\n width: 40px;\n height: 40px;\n margin-top: -40px; // Negative margin to not affect scroll height\n margin-left: auto;\n margin-right: auto;\n background: white;\n border: 1px solid #D1D5DB;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n z-index: 100;\n pointer-events: auto;\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%]:hover {\n background: #F3F4F6;\n border-color: #3B82F6;\n transform: translateX(-50%) translateY(-2px);\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6B7280;\n font-size: 16px;\n transition: color 0.2s;\n}\n.scroll-to-bottom-icon[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: #3B82F6;\n}\n.chat-input-container[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: #FFF;\n border-top: 1px solid #E5E7EB;\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] placeholder[_ngcontent-%COMP%] -[_ngcontent-%COMP%] replaces[_ngcontent-%COMP%] input[_ngcontent-%COMP%] while[_ngcontent-%COMP%] loading\n.loading-peripheral-placeholder[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 140px; // Match typical input area height\n padding: 24px;\n background: rgba(255, 255, 255, 0.5);\n backdrop-filter: blur(2px);\n border-radius: 12px;\n margin: 12px;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-in-out;\n}\n.modal-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n.modal-content[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n.project-selector-modal[_ngcontent-%COMP%] {\n width: 600px;\n height: 500px;\n}\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #E5E7EB;\n}\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n.modal-close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: #6B7280;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.2s;\n}\n.modal-close-btn[_ngcontent-%COMP%]:hover {\n background: #F3F4F6;\n color: #111827;\n}\n.modal-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 20px;\n}\n.artifacts-modal[_ngcontent-%COMP%] {\n width: 700px;\n max-height: 600px;\n}\n.artifacts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n.empty-state[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n.artifact-modal-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n background: white;\n border: 1.5px solid #E5E7EB;\n border-radius: 12px;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n.artifact-modal-card.expanded[_ngcontent-%COMP%] {\n border-color: #3B82F6;\n}\n.artifact-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n cursor: pointer;\n}\n.artifact-card-header[_ngcontent-%COMP%]:hover {\n background: #F9FAFB;\n}\n.artifact-modal-card[_ngcontent-%COMP%]:hover {\n border-color: #3B82F6;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n transform: translateY(-2px);\n}\n.artifact-modal-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%);\n border-radius: 10px;\n color: #3B82F6;\n flex-shrink: 0;\n}\n.artifact-modal-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n.artifact-modal-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.artifact-modal-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.artifact-modal-meta[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6B7280;\n}\n.artifact-modal-action[_ngcontent-%COMP%] {\n color: #9CA3AF;\n transition: color 0.2s;\n}\n.artifact-modal-card[_ngcontent-%COMP%]:hover .artifact-modal-action[_ngcontent-%COMP%] {\n color: #3B82F6;\n}\n.expand-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #6B7280;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #F3F4F6;\n color: #3B82F6;\n }\n}\n.artifact-versions-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n border-top: 1px solid #E5E7EB;\n background: #F9FAFB;\n}\n.artifact-version-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px 12px 68px; // Indent to align with title\n cursor: pointer;\n transition: background 0.15s;\n\n &:hover {\n background: #F3F4F6;\n }\n\n .version-badge {\n display: inline-block;\n padding: 4px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 12px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n }\n\n .version-open-text {\n flex: 1;\n font-size: 13px;\n color: #6B7280;\n }\n\n i {\n color: #9CA3AF;\n font-size: 12px;\n }\n\n &:hover {\n .version-badge {\n background: #4F46E5;\n color: white;\n }\n .version-open-text {\n color: #3B82F6;\n }\n i {\n color: #3B82F6;\n }\n }\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] content[_ngcontent-%COMP%] styling\n.loading-peripheral-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n background: white;\n border: 2px solid #E5E7EB;\n border-radius: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n color: #4B5563;\n font-size: 14px;\n font-weight: 500;\n\n i {\n font-size: 20px;\n color: #9333EA;\n }\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}"] });
|
|
1038
1147
|
}
|
|
1039
1148
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ConversationChatAreaComponent, [{
|
|
1040
1149
|
type: Component,
|
|
1041
|
-
args: [{ selector: 'mj-conversation-chat-area', template: "<div class=\"chat-area\">\n <!-- Fixed Header -->\n <div class=\"chat-header\" *ngIf=\"conversationState.activeConversation as conversation\">\n <div class=\"chat-info\">\n <div class=\"chat-title\">{{ conversation.Name }}</div>\n <button class=\"project-tag\" (click)=\"openProjectSelector()\" title=\"Assign to project\" *ngIf=\"conversation.ProjectID\">\n <i class=\"fas fa-folder\"></i>\n <span>{{ conversation.Project || 'Project' }}</span>\n </button>\n <button class=\"chat-members\" (click)=\"toggleMembersModal()\" title=\"View members\">\n <i class=\"fas fa-users\"></i>\n <span>{{ memberCount }} member{{ memberCount !== 1 ? 's' : '' }}</span>\n </button>\n <button class=\"artifact-indicator\" (click)=\"viewArtifacts()\" title=\"View artifacts\" *ngIf=\"artifactCount > 0\">\n <i class=\"fas fa-cube\"></i>\n <span>{{ artifactCount }} artifact{{ artifactCount !== 1 ? 's' : '' }}</span>\n </button>\n <mj-active-agent-indicator\n [conversationId]=\"conversationState.activeConversation.ID\"\n [currentUser]=\"currentUser\"\n (togglePanel)=\"onToggleAgentPanel()\"\n (agentSelected)=\"onAgentSelected($event)\">\n </mj-active-agent-indicator>\n </div>\n <div class=\"chat-actions\">\n <mj-tasks-dropdown\n [currentUser]=\"currentUser\"\n (taskClicked)=\"onTaskClicked($event)\">\n </mj-tasks-dropdown>\n <button class=\"action-btn\" (click)=\"exportConversation()\" title=\"Export conversation\">\n <i class=\"fas fa-download\"></i>\n Export\n </button>\n <button class=\"action-btn share-btn\"\n [class.shared]=\"isShared\"\n (click)=\"shareConversation()\"\n [title]=\"isShared ? 'Manage sharing' : 'Share conversation'\">\n <i class=\"fas fa-share-nodes\"></i>\n Share\n </button>\n </div>\n </div>\n\n <!-- Messages and Artifact Split Layout -->\n <div class=\"chat-content-area\">\n <!-- Messages Pane -->\n <div class=\"chat-messages-pane\" [class.full-width]=\"!showArtifactPanel\">\n <div class=\"chat-messages-wrapper\">\n <div class=\"chat-messages-container\" #scrollContainer (scroll)=\"checkScroll()\">\n <mj-conversation-message-list\n [messages]=\"messages\"\n [conversation]=\"conversationState.activeConversation\"\n [currentUser]=\"currentUser\"\n [isProcessing]=\"isProcessing\"\n [artifactMap]=\"artifactsByDetailId\"\n [agentRunMap]=\"agentRunsByDetailId\"\n (replyInThread)=\"onReplyInThread($event)\"\n (viewThread)=\"onViewThread($event)\"\n (retryMessage)=\"onRetryMessage($event)\"\n (artifactClicked)=\"onArtifactClicked($event)\"\n (messageEdited)=\"onMessageEdited($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-conversation-message-list>\n\n <!-- Scroll to Bottom Icon (positioned within scroll container for proper centering) -->\n <span class=\"scroll-to-bottom-icon\" style=\"left: 50%;\"\n *ngIf=\"showScrollToBottomIcon && messages && messages.length > 0\"\n (click)=\"scrollToBottomAnimate()\">\n <i class=\"fas fa-arrow-down\"></i>\n </span>\n </div>\n\n <!-- Fixed Input Area -->\n <div class=\"chat-input-container\">\n @if (isLoadingPeripheralData) {\n <!-- Loading State -->\n <div class=\"loading-peripheral-placeholder\">\n <div class=\"loading-peripheral-content\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading conversation data...</span>\n </div>\n </div>\n } @else {\n <!-- Input Component -->\n <mj-message-input\n *ngIf=\"conversationState.activeConversation\"\n [conversationId]=\"conversationState.activeConversation.ID\"\n [currentUser]=\"currentUser\"\n [conversationHistory]=\"messages\"\n [disabled]=\"isProcessing\"\n (messageSent)=\"onMessageSent($event)\"\n (agentResponse)=\"onAgentResponse($event)\"\n (agentRunDetected)=\"onAgentRunDetected($event)\"\n (artifactCreated)=\"onArtifactCreated($event)\"\n (conversationRenamed)=\"onConversationRenamed($event)\">\n </mj-message-input>\n }\n </div>\n </div>\n </div>\n\n <!-- Artifact Viewer Pane -->\n @if (showArtifactPanel && selectedArtifactId) {\n <div class=\"resize-handle\" (mousedown)=\"onResizeStart($event)\"></div>\n <div class=\"chat-artifact-pane\" [style.width.%]=\"artifactPaneWidth\">\n <mj-artifact-viewer-panel\n [artifactId]=\"selectedArtifactId\"\n [currentUser]=\"currentUser\"\n [environmentId]=\"environmentId\"\n [versionNumber]=\"selectedVersionNumber\"\n [refreshTrigger]=\"artifactViewerRefresh$\"\n (closed)=\"onCloseArtifactPanel()\">\n </mj-artifact-viewer-panel>\n </div>\n }\n </div>\n</div>\n\n<!-- Thread Panel -->\n@if (conversationState.activeThreadId) {\n <mj-thread-panel\n [parentMessageId]=\"conversationState.activeThreadId\"\n [conversationId]=\"conversationState.activeConversation?.ID || ''\"\n [currentUser]=\"currentUser\"\n (closed)=\"onThreadClosed()\"\n (replyAdded)=\"onThreadReplyAdded($event)\">\n </mj-thread-panel>\n}\n\n<!-- Export Modal -->\n<mj-export-modal\n [isVisible]=\"showExportModal\"\n [conversation]=\"conversationState.activeConversation || undefined\"\n [currentUser]=\"currentUser\"\n (cancelled)=\"onExportModalCancelled()\"\n (exported)=\"onExportModalComplete()\">\n</mj-export-modal>\n\n<!-- Members Modal -->\n<mj-members-modal\n [isVisible]=\"showMembersModal\"\n [conversation]=\"conversationState.activeConversation || undefined\"\n [currentUser]=\"currentUser\"\n (cancelled)=\"showMembersModal = false\"\n (membersChanged)=\"showMembersModal = false\">\n</mj-members-modal>\n\n<!-- Project Selector Modal -->\n@if (showProjectSelector && conversationState.activeConversation) {\n <div class=\"modal-overlay\" (click)=\"showProjectSelector = false\">\n <div class=\"modal-content project-selector-modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Assign Project</h3>\n <button class=\"modal-close-btn\" (click)=\"showProjectSelector = false\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <mj-project-selector\n [environmentId]=\"environmentId\"\n [currentUser]=\"currentUser\"\n [selectedProjectId]=\"conversationState.activeConversation.ProjectID\"\n (projectSelected)=\"onProjectSelected($event)\">\n </mj-project-selector>\n </div>\n </div>\n </div>\n}\n\n<!-- Artifacts Modal -->\n@if (showArtifactsModal) {\n <div class=\"modal-overlay\" (click)=\"showArtifactsModal = false\">\n <div class=\"modal-content artifacts-modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Conversation Artifacts</h3>\n <button class=\"modal-close-btn\" (click)=\"showArtifactsModal = false\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body artifacts-grid\">\n @if (artifactsByDetailId.size === 0) {\n <div class=\"empty-state\">\n <i class=\"fas fa-cube\" style=\"font-size: 48px; color: #D1D5DB; margin-bottom: 16px;\"></i>\n <p style=\"color: #6B7280; font-size: 14px;\">No artifacts in this conversation yet</p>\n </div>\n }\n @for (artifact of getArtifactsArray(); track artifact.artifactId) {\n <div class=\"artifact-modal-card\" [class.expanded]=\"expandedArtifactId === artifact.artifactId\">\n <!-- Main card header - click to open latest version -->\n <div class=\"artifact-card-header\" (click)=\"openArtifactFromModal(artifact.artifactId)\">\n <div class=\"artifact-modal-icon\">\n <i class=\"fas fa-file-code\"></i>\n </div>\n <div class=\"artifact-modal-info\">\n <div class=\"artifact-modal-title\">{{artifact.name}}</div>\n <div class=\"artifact-modal-meta\">\n @if (artifact.versionCount > 1) {\n {{artifact.versionCount}} versions\n } @else {\n 1 version\n }\n </div>\n </div>\n @if (artifact.versionCount > 1) {\n <button class=\"expand-btn\" (click)=\"toggleArtifactExpansion(artifact.artifactId, $event)\">\n <i class=\"fas\" [class.fa-chevron-down]=\"expandedArtifactId !== artifact.artifactId\"\n [class.fa-chevron-up]=\"expandedArtifactId === artifact.artifactId\"></i>\n </button>\n }\n <div class=\"artifact-modal-action\">\n <i class=\"fas fa-external-link-alt\"></i>\n </div>\n </div>\n\n <!-- Expanded version list -->\n @if (expandedArtifactId === artifact.artifactId && artifact.versionCount > 1) {\n <div class=\"artifact-versions-list\">\n @for (version of artifact.versions; track version.versionId) {\n <div class=\"artifact-version-item\" (click)=\"openArtifactFromModal(artifact.artifactId, version.versionNumber); $event.stopPropagation()\">\n <span class=\"version-badge\">v{{version.versionNumber}}</span>\n <span class=\"version-open-text\">Open this version</span>\n <i class=\"fas fa-arrow-right\"></i>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n}", styles: [":host {\n display: flex;\n width: 100%;\n height: 100%;\n}\n.chat-area {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.chat-header {\n flex-shrink: 0;\n padding: 12px 20px;\n border-bottom: 1px solid #D9D9D9;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n background: #FFF;\n z-index: 10;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n.chat-info {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n.chat-title {\n font-size: 16px;\n font-weight: 600;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.project-tag {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: #F4F4F4;\n border: 1px solid #D9D9D9;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 28px;\n margin-left: 12px;\n}\n.project-tag:hover {\n background: #D9D9D9;\n border-color: #AAA;\n}\n.project-tag i {\n font-size: 10px;\n}\n.chat-members {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #F4F4F4;\n border: none;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 32px;\n}\n.chat-members:hover {\n background: #D9D9D9;\n color: #333;\n}\n.chat-members i {\n font-size: 12px;\n}\n.chat-members span {\n font-size: 12px;\n font-weight: 500;\n}\n.artifact-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #3B82F6;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n color: white;\n cursor: pointer;\n transition: all 150ms ease;\n}\n.artifact-indicator:hover {\n background: #2563EB;\n}\n.ambient-agent-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #F3F4F6;\n border: 1px solid #D1D5DB;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n animation: pulse 2s ease-in-out infinite;\n}\n.ambient-agent-indicator i {\n color: #0076B6;\n}\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n.chat-actions {\n display: flex;\n gap: 8px;\n}\n.action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px solid #E5E7EB;\n cursor: pointer;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n transition: all 150ms ease;\n}\n.action-btn:hover {\n background: #F9FAFB;\n color: #111827;\n}\n.share-btn.shared {\n background: #EFF6FF;\n border-color: #1e40af;\n color: #1e40af;\n}\n.share-btn.shared:hover {\n background: #DBEAFE;\n color: #1e3a8a;\n}\n.chat-content-area {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: row;\n position: relative;\n}\n.chat-messages-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n min-width: 300px;\n overflow: hidden;\n transition: width 0.3s ease;\n}\n.chat-messages-pane.full-width {\n width: 100%;\n}\n.chat-messages-pane:not(.full-width) {\n flex: 1;\n}\n.resize-handle {\n width: 4px;\n background: transparent;\n cursor: col-resize;\n flex-shrink: 0;\n position: relative;\n transition: background-color 0.2s;\n}\n.resize-handle:hover {\n background: #3B82F6;\n}\n.resize-handle::before {\n content: '';\n position: absolute;\n left: -4px;\n right: -4px;\n top: 0;\n bottom: 0;\n}\n.chat-artifact-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #FAFAFA;\n overflow: hidden;\n flex-shrink: 0;\n}\n.chat-artifact-pane > mj-artifact-viewer-panel {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: #FFF;\n min-height: 0;\n position: relative;\n}\n.scroll-to-bottom-icon {\n position: sticky;\n bottom: 21px; // 21px from bottom of visible scroll area (moved up 5px from original 16px)\n left: 50%;\n transform: translateX(-50%);\n width: 40px;\n height: 40px;\n margin-top: -40px; // Negative margin to not affect scroll height\n margin-left: auto;\n margin-right: auto;\n background: white;\n border: 1px solid #D1D5DB;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n z-index: 100;\n pointer-events: auto;\n}\n.scroll-to-bottom-icon:hover {\n background: #F3F4F6;\n border-color: #3B82F6;\n transform: translateX(-50%) translateY(-2px);\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n}\n.scroll-to-bottom-icon i {\n color: #6B7280;\n font-size: 16px;\n transition: color 0.2s;\n}\n.scroll-to-bottom-icon:hover i {\n color: #3B82F6;\n}\n.chat-input-container {\n flex-shrink: 0;\n background: #FFF;\n border-top: 1px solid #E5E7EB;\n}\n\n// Loading placeholder - replaces input while loading\n.loading-peripheral-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 140px; // Match typical input area height\n padding: 24px;\n background: rgba(255, 255, 255, 0.5);\n backdrop-filter: blur(2px);\n border-radius: 12px;\n margin: 12px;\n animation: fadeIn 0.2s ease-in-out;\n}\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n.modal-content {\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n.project-selector-modal {\n width: 600px;\n height: 500px;\n}\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #E5E7EB;\n}\n.modal-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n.modal-close-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: #6B7280;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.2s;\n}\n.modal-close-btn:hover {\n background: #F3F4F6;\n color: #111827;\n}\n.modal-body {\n flex: 1;\n overflow: auto;\n padding: 20px;\n}\n.artifacts-modal {\n width: 700px;\n max-height: 600px;\n}\n.artifacts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n.empty-state {\n grid-column: 1 / -1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n.artifact-modal-card {\n display: flex;\n flex-direction: column;\n background: white;\n border: 1.5px solid #E5E7EB;\n border-radius: 12px;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n.artifact-modal-card.expanded {\n border-color: #3B82F6;\n}\n.artifact-card-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n cursor: pointer;\n}\n.artifact-card-header:hover {\n background: #F9FAFB;\n}\n.artifact-modal-card:hover {\n border-color: #3B82F6;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n transform: translateY(-2px);\n}\n.artifact-modal-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%);\n border-radius: 10px;\n color: #3B82F6;\n flex-shrink: 0;\n}\n.artifact-modal-icon i {\n font-size: 18px;\n}\n.artifact-modal-info {\n flex: 1;\n min-width: 0;\n}\n.artifact-modal-title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.artifact-modal-meta {\n font-size: 12px;\n color: #6B7280;\n}\n.artifact-modal-action {\n color: #9CA3AF;\n transition: color 0.2s;\n}\n.artifact-modal-card:hover .artifact-modal-action {\n color: #3B82F6;\n}\n.expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #6B7280;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #F3F4F6;\n color: #3B82F6;\n }\n}\n.artifact-versions-list {\n display: flex;\n flex-direction: column;\n border-top: 1px solid #E5E7EB;\n background: #F9FAFB;\n}\n.artifact-version-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px 12px 68px; // Indent to align with title\n cursor: pointer;\n transition: background 0.15s;\n\n &:hover {\n background: #F3F4F6;\n }\n\n .version-badge {\n display: inline-block;\n padding: 4px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 12px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n }\n\n .version-open-text {\n flex: 1;\n font-size: 13px;\n color: #6B7280;\n }\n\n i {\n color: #9CA3AF;\n font-size: 12px;\n }\n\n &:hover {\n .version-badge {\n background: #4F46E5;\n color: white;\n }\n .version-open-text {\n color: #3B82F6;\n }\n i {\n color: #3B82F6;\n }\n }\n}\n\n// Loading content styling\n.loading-peripheral-content {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n background: white;\n border: 2px solid #E5E7EB;\n border-radius: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n color: #4B5563;\n font-size: 14px;\n font-weight: 500;\n\n i {\n font-size: 20px;\n color: #9333EA;\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}"] }]
|
|
1042
|
-
}], () => [{ type: i1.ConversationStateService }, { type: i2.
|
|
1150
|
+
args: [{ selector: 'mj-conversation-chat-area', template: "<div class=\"chat-area\">\n <!-- Fixed Header -->\n <div class=\"chat-header\" *ngIf=\"conversationState.activeConversation as conversation\">\n <div class=\"chat-info\">\n <div class=\"chat-title\">{{ conversation.Name }}</div>\n <button class=\"project-tag\" (click)=\"openProjectSelector()\" title=\"Assign to project\" *ngIf=\"conversation.ProjectID\">\n <i class=\"fas fa-folder\"></i>\n <span>{{ conversation.Project || 'Project' }}</span>\n </button>\n <button class=\"chat-members\" (click)=\"toggleMembersModal()\" title=\"View members\">\n <i class=\"fas fa-users\"></i>\n <span>{{ memberCount }} member{{ memberCount !== 1 ? 's' : '' }}</span>\n </button>\n <button class=\"artifact-indicator\" (click)=\"viewArtifacts()\" title=\"View artifacts\" *ngIf=\"artifactCount > 0\">\n <i class=\"fas fa-cube\"></i>\n <span>{{ artifactCount }} artifact{{ artifactCount !== 1 ? 's' : '' }}</span>\n </button>\n <mj-active-agent-indicator\n [conversationId]=\"conversationState.activeConversation.ID\"\n [currentUser]=\"currentUser\"\n (togglePanel)=\"onToggleAgentPanel()\"\n (agentSelected)=\"onAgentSelected($event)\">\n </mj-active-agent-indicator>\n </div>\n <div class=\"chat-actions\">\n <mj-tasks-dropdown\n [currentUser]=\"currentUser\"\n (taskClicked)=\"onTaskClicked($event)\">\n </mj-tasks-dropdown>\n <button class=\"action-btn\" (click)=\"exportConversation()\" title=\"Export conversation\">\n <i class=\"fas fa-download\"></i>\n Export\n </button>\n <button class=\"action-btn share-btn\"\n [class.shared]=\"isShared\"\n (click)=\"shareConversation()\"\n [title]=\"isShared ? 'Manage sharing' : 'Share conversation'\">\n <i class=\"fas fa-share-nodes\"></i>\n Share\n </button>\n </div>\n </div>\n\n <!-- Messages and Artifact Split Layout -->\n <div class=\"chat-content-area\">\n <!-- Messages Pane -->\n <div class=\"chat-messages-pane\" [class.full-width]=\"!showArtifactPanel\">\n <div class=\"chat-messages-wrapper\">\n <div class=\"chat-messages-container\" #scrollContainer (scroll)=\"checkScroll()\">\n <mj-conversation-message-list\n [messages]=\"messages\"\n [conversation]=\"conversationState.activeConversation\"\n [currentUser]=\"currentUser\"\n [isProcessing]=\"isProcessing\"\n [artifactMap]=\"artifactsByDetailId\"\n [agentRunMap]=\"agentRunsByDetailId\"\n (replyInThread)=\"onReplyInThread($event)\"\n (viewThread)=\"onViewThread($event)\"\n (retryMessage)=\"onRetryMessage($event)\"\n (artifactClicked)=\"onArtifactClicked($event)\"\n (messageEdited)=\"onMessageEdited($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\"\n (suggestedResponseSelected)=\"onSuggestedResponseSelected($event)\">\n </mj-conversation-message-list>\n\n <!-- Scroll to Bottom Icon (positioned within scroll container for proper centering) -->\n <span class=\"scroll-to-bottom-icon\" style=\"left: 50%;\"\n *ngIf=\"showScrollToBottomIcon && messages && messages.length > 0\"\n (click)=\"scrollToBottomAnimate()\">\n <i class=\"fas fa-arrow-down\"></i>\n </span>\n </div>\n\n <!-- Fixed Input Area -->\n <div class=\"chat-input-container\">\n @if (isLoadingPeripheralData) {\n <!-- Loading State -->\n <div class=\"loading-peripheral-placeholder\">\n <div class=\"loading-peripheral-content\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading conversation data...</span>\n </div>\n </div>\n } @else {\n <!-- Input Component -->\n <mj-message-input\n *ngIf=\"conversationState.activeConversation\"\n [conversationId]=\"conversationState.activeConversation.ID\"\n [currentUser]=\"currentUser\"\n [conversationHistory]=\"messages\"\n [disabled]=\"isProcessing\"\n (messageSent)=\"onMessageSent($event)\"\n (agentResponse)=\"onAgentResponse($event)\"\n (agentRunDetected)=\"onAgentRunDetected($event)\"\n (artifactCreated)=\"onArtifactCreated($event)\"\n (conversationRenamed)=\"onConversationRenamed($event)\">\n </mj-message-input>\n }\n </div>\n </div>\n </div>\n\n <!-- Artifact Viewer Pane -->\n @if (showArtifactPanel && selectedArtifactId) {\n <div class=\"resize-handle\" (mousedown)=\"onResizeStart($event)\"></div>\n <div class=\"chat-artifact-pane\" [style.width.%]=\"artifactPaneWidth\">\n <mj-artifact-viewer-panel\n [artifactId]=\"selectedArtifactId\"\n [currentUser]=\"currentUser\"\n [environmentId]=\"environmentId\"\n [versionNumber]=\"selectedVersionNumber\"\n [refreshTrigger]=\"artifactViewerRefresh$\"\n (closed)=\"onCloseArtifactPanel()\"\n (saveToCollectionRequested)=\"onSaveToCollectionRequested($event)\">\n </mj-artifact-viewer-panel>\n </div>\n }\n </div>\n</div>\n\n<!-- Thread Panel -->\n@if (conversationState.activeThreadId) {\n <mj-thread-panel\n [parentMessageId]=\"conversationState.activeThreadId\"\n [conversationId]=\"conversationState.activeConversation?.ID || ''\"\n [currentUser]=\"currentUser\"\n (closed)=\"onThreadClosed()\"\n (replyAdded)=\"onThreadReplyAdded($event)\">\n </mj-thread-panel>\n}\n\n<!-- Export Modal -->\n<mj-export-modal\n [isVisible]=\"showExportModal\"\n [conversation]=\"conversationState.activeConversation || undefined\"\n [currentUser]=\"currentUser\"\n (cancelled)=\"onExportModalCancelled()\"\n (exported)=\"onExportModalComplete()\">\n</mj-export-modal>\n\n<!-- Members Modal -->\n<mj-members-modal\n [isVisible]=\"showMembersModal\"\n [conversation]=\"conversationState.activeConversation || undefined\"\n [currentUser]=\"currentUser\"\n (cancelled)=\"showMembersModal = false\"\n (membersChanged)=\"showMembersModal = false\">\n</mj-members-modal>\n\n<!-- Project Selector Modal -->\n@if (showProjectSelector && conversationState.activeConversation) {\n <div class=\"modal-overlay\" (click)=\"showProjectSelector = false\">\n <div class=\"modal-content project-selector-modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Assign Project</h3>\n <button class=\"modal-close-btn\" (click)=\"showProjectSelector = false\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <mj-project-selector\n [environmentId]=\"environmentId\"\n [currentUser]=\"currentUser\"\n [selectedProjectId]=\"conversationState.activeConversation.ProjectID\"\n (projectSelected)=\"onProjectSelected($event)\">\n </mj-project-selector>\n </div>\n </div>\n </div>\n}\n\n<!-- Artifacts Modal -->\n@if (showArtifactsModal) {\n <div class=\"modal-overlay\" (click)=\"showArtifactsModal = false\">\n <div class=\"modal-content artifacts-modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Conversation Artifacts</h3>\n <button class=\"modal-close-btn\" (click)=\"showArtifactsModal = false\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body artifacts-grid\">\n @if (artifactsByDetailId.size === 0) {\n <div class=\"empty-state\">\n <i class=\"fas fa-cube\" style=\"font-size: 48px; color: #D1D5DB; margin-bottom: 16px;\"></i>\n <p style=\"color: #6B7280; font-size: 14px;\">No artifacts in this conversation yet</p>\n </div>\n }\n @for (artifact of getArtifactsArray(); track artifact.artifactId) {\n <div class=\"artifact-modal-card\" [class.expanded]=\"expandedArtifactId === artifact.artifactId\">\n <!-- Main card header - click to open latest version -->\n <div class=\"artifact-card-header\" (click)=\"openArtifactFromModal(artifact.artifactId)\">\n <div class=\"artifact-modal-icon\">\n <i class=\"fas fa-file-code\"></i>\n </div>\n <div class=\"artifact-modal-info\">\n <div class=\"artifact-modal-title\">{{artifact.name}}</div>\n <div class=\"artifact-modal-meta\">\n @if (artifact.versionCount > 1) {\n {{artifact.versionCount}} versions\n } @else {\n 1 version\n }\n </div>\n </div>\n @if (artifact.versionCount > 1) {\n <button class=\"expand-btn\" (click)=\"toggleArtifactExpansion(artifact.artifactId, $event)\">\n <i class=\"fas\" [class.fa-chevron-down]=\"expandedArtifactId !== artifact.artifactId\"\n [class.fa-chevron-up]=\"expandedArtifactId === artifact.artifactId\"></i>\n </button>\n }\n <div class=\"artifact-modal-action\">\n <i class=\"fas fa-external-link-alt\"></i>\n </div>\n </div>\n\n <!-- Expanded version list -->\n @if (expandedArtifactId === artifact.artifactId && artifact.versionCount > 1) {\n <div class=\"artifact-versions-list\">\n @for (version of artifact.versions; track version.versionId) {\n <div class=\"artifact-version-item\" (click)=\"openArtifactFromModal(artifact.artifactId, version.versionNumber); $event.stopPropagation()\">\n <span class=\"version-badge\">v{{version.versionNumber}}</span>\n <span class=\"version-open-text\">Open this version</span>\n <i class=\"fas fa-arrow-right\"></i>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n}\n\n<!-- Collection Picker Modal -->\n@if (showCollectionPicker) {\n <mj-artifact-collection-picker-modal\n [isOpen]=\"showCollectionPicker\"\n [environmentId]=\"environmentId\"\n [currentUser]=\"currentUser\"\n [excludeCollectionIds]=\"collectionPickerExcludedIds\"\n (saved)=\"onCollectionPickerSaved($event)\"\n (cancelled)=\"onCollectionPickerCancelled()\">\n </mj-artifact-collection-picker-modal>\n}", styles: [":host {\n display: flex;\n width: 100%;\n height: 100%;\n}\n.chat-area {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.chat-header {\n flex-shrink: 0;\n padding: 12px 20px;\n border-bottom: 1px solid #D9D9D9;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n background: #FFF;\n z-index: 10;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n.chat-info {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n.chat-title {\n font-size: 16px;\n font-weight: 600;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.project-tag {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: #F4F4F4;\n border: 1px solid #D9D9D9;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 28px;\n margin-left: 12px;\n}\n.project-tag:hover {\n background: #D9D9D9;\n border-color: #AAA;\n}\n.project-tag i {\n font-size: 10px;\n}\n.chat-members {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #F4F4F4;\n border: none;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n color: #AAA;\n cursor: pointer;\n transition: all 0.2s;\n height: 32px;\n}\n.chat-members:hover {\n background: #D9D9D9;\n color: #333;\n}\n.chat-members i {\n font-size: 12px;\n}\n.chat-members span {\n font-size: 12px;\n font-weight: 500;\n}\n.artifact-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #3B82F6;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n color: white;\n cursor: pointer;\n transition: all 150ms ease;\n}\n.artifact-indicator:hover {\n background: #2563EB;\n}\n.ambient-agent-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: #F3F4F6;\n border: 1px solid #D1D5DB;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n animation: pulse 2s ease-in-out infinite;\n}\n.ambient-agent-indicator i {\n color: #0076B6;\n}\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n.chat-actions {\n display: flex;\n gap: 8px;\n}\n.action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px solid #E5E7EB;\n cursor: pointer;\n border-radius: 6px;\n font-size: 13px;\n color: #6B7280;\n transition: all 150ms ease;\n}\n.action-btn:hover {\n background: #F9FAFB;\n color: #111827;\n}\n.share-btn.shared {\n background: #EFF6FF;\n border-color: #1e40af;\n color: #1e40af;\n}\n.share-btn.shared:hover {\n background: #DBEAFE;\n color: #1e3a8a;\n}\n.chat-content-area {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: row;\n position: relative;\n}\n.chat-messages-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n min-width: 300px;\n overflow: hidden;\n transition: width 0.3s ease;\n}\n.chat-messages-pane.full-width {\n width: 100%;\n}\n.chat-messages-pane:not(.full-width) {\n flex: 1;\n}\n.resize-handle {\n width: 4px;\n background: transparent;\n cursor: col-resize;\n flex-shrink: 0;\n position: relative;\n transition: background-color 0.2s;\n}\n.resize-handle:hover {\n background: #3B82F6;\n}\n.resize-handle::before {\n content: '';\n position: absolute;\n left: -4px;\n right: -4px;\n top: 0;\n bottom: 0;\n}\n.chat-artifact-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #FAFAFA;\n overflow: hidden;\n flex-shrink: 0;\n}\n.chat-artifact-pane > mj-artifact-viewer-panel {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n.chat-messages-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: #FFF;\n min-height: 0;\n position: relative;\n}\n.scroll-to-bottom-icon {\n position: sticky;\n bottom: 21px; // 21px from bottom of visible scroll area (moved up 5px from original 16px)\n left: 50%;\n transform: translateX(-50%);\n width: 40px;\n height: 40px;\n margin-top: -40px; // Negative margin to not affect scroll height\n margin-left: auto;\n margin-right: auto;\n background: white;\n border: 1px solid #D1D5DB;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n z-index: 100;\n pointer-events: auto;\n}\n.scroll-to-bottom-icon:hover {\n background: #F3F4F6;\n border-color: #3B82F6;\n transform: translateX(-50%) translateY(-2px);\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n}\n.scroll-to-bottom-icon i {\n color: #6B7280;\n font-size: 16px;\n transition: color 0.2s;\n}\n.scroll-to-bottom-icon:hover i {\n color: #3B82F6;\n}\n.chat-input-container {\n flex-shrink: 0;\n background: #FFF;\n border-top: 1px solid #E5E7EB;\n}\n\n// Loading placeholder - replaces input while loading\n.loading-peripheral-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 140px; // Match typical input area height\n padding: 24px;\n background: rgba(255, 255, 255, 0.5);\n backdrop-filter: blur(2px);\n border-radius: 12px;\n margin: 12px;\n animation: fadeIn 0.2s ease-in-out;\n}\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n.modal-content {\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n.project-selector-modal {\n width: 600px;\n height: 500px;\n}\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #E5E7EB;\n}\n.modal-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n.modal-close-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: #6B7280;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.2s;\n}\n.modal-close-btn:hover {\n background: #F3F4F6;\n color: #111827;\n}\n.modal-body {\n flex: 1;\n overflow: auto;\n padding: 20px;\n}\n.artifacts-modal {\n width: 700px;\n max-height: 600px;\n}\n.artifacts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n.empty-state {\n grid-column: 1 / -1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n.artifact-modal-card {\n display: flex;\n flex-direction: column;\n background: white;\n border: 1.5px solid #E5E7EB;\n border-radius: 12px;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n}\n.artifact-modal-card.expanded {\n border-color: #3B82F6;\n}\n.artifact-card-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n cursor: pointer;\n}\n.artifact-card-header:hover {\n background: #F9FAFB;\n}\n.artifact-modal-card:hover {\n border-color: #3B82F6;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n transform: translateY(-2px);\n}\n.artifact-modal-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%);\n border-radius: 10px;\n color: #3B82F6;\n flex-shrink: 0;\n}\n.artifact-modal-icon i {\n font-size: 18px;\n}\n.artifact-modal-info {\n flex: 1;\n min-width: 0;\n}\n.artifact-modal-title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.artifact-modal-meta {\n font-size: 12px;\n color: #6B7280;\n}\n.artifact-modal-action {\n color: #9CA3AF;\n transition: color 0.2s;\n}\n.artifact-modal-card:hover .artifact-modal-action {\n color: #3B82F6;\n}\n.expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #6B7280;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #F3F4F6;\n color: #3B82F6;\n }\n}\n.artifact-versions-list {\n display: flex;\n flex-direction: column;\n border-top: 1px solid #E5E7EB;\n background: #F9FAFB;\n}\n.artifact-version-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px 12px 68px; // Indent to align with title\n cursor: pointer;\n transition: background 0.15s;\n\n &:hover {\n background: #F3F4F6;\n }\n\n .version-badge {\n display: inline-block;\n padding: 4px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 12px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n }\n\n .version-open-text {\n flex: 1;\n font-size: 13px;\n color: #6B7280;\n }\n\n i {\n color: #9CA3AF;\n font-size: 12px;\n }\n\n &:hover {\n .version-badge {\n background: #4F46E5;\n color: white;\n }\n .version-open-text {\n color: #3B82F6;\n }\n i {\n color: #3B82F6;\n }\n }\n}\n\n// Loading content styling\n.loading-peripheral-content {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n background: white;\n border: 2px solid #E5E7EB;\n border-radius: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n color: #4B5563;\n font-size: 14px;\n font-weight: 500;\n\n i {\n font-size: 20px;\n color: #9333EA;\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}"] }]
|
|
1151
|
+
}], () => [{ type: i1.ConversationStateService }, { type: i2.AgentStateService }, { type: i3.ConversationAgentService }, { type: i4.ActiveTasksService }, { type: i0.ChangeDetectorRef }, { type: i5.MentionAutocompleteService }], { environmentId: [{
|
|
1043
1152
|
type: Input
|
|
1044
1153
|
}], currentUser: [{
|
|
1045
1154
|
type: Input
|
|
@@ -1052,6 +1161,12 @@ export class ConversationChatAreaComponent {
|
|
|
1052
1161
|
}], scrollContainer: [{
|
|
1053
1162
|
type: ViewChild,
|
|
1054
1163
|
args: ['scrollContainer']
|
|
1164
|
+
}], messageInputComponent: [{
|
|
1165
|
+
type: ViewChild,
|
|
1166
|
+
args: [MessageInputComponent]
|
|
1167
|
+
}], artifactViewerComponent: [{
|
|
1168
|
+
type: ViewChild,
|
|
1169
|
+
args: [ArtifactViewerPanelComponent]
|
|
1055
1170
|
}] }); })();
|
|
1056
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationChatAreaComponent, { className: "ConversationChatAreaComponent", filePath: "src/lib/components/conversation/conversation-chat-area.component.ts", lineNumber:
|
|
1171
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationChatAreaComponent, { className: "ConversationChatAreaComponent", filePath: "src/lib/components/conversation/conversation-chat-area.component.ts", lineNumber: 20 }); })();
|
|
1057
1172
|
//# sourceMappingURL=conversation-chat-area.component.js.map
|