@memberjunction/ng-skip-chat 2.94.0 → 2.96.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.
@@ -227,59 +227,57 @@ function SkipChatComponent_span_16_Template(rf, ctx) { if (rf & 1) {
227
227
  const ctx_r2 = i0.ɵɵnextContext();
228
228
  i0.ɵɵstyleProp("left", ctx_r2.getScrollToBottomIconPosition(), "px");
229
229
  } }
230
- function SkipChatComponent_Conditional_17_Conditional_5_Template(rf, ctx) { if (rf & 1) {
230
+ function SkipChatComponent_Conditional_17_Conditional_6_Template(rf, ctx) { if (rf & 1) {
231
231
  const _r16 = i0.ɵɵgetCurrentView();
232
- i0.ɵɵelementStart(0, "button", 64)(1, "span", 68);
233
- i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_5_Template_span_click_1_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.showDataContextDialog()); });
232
+ i0.ɵɵelementStart(0, "button", 65)(1, "span", 69);
233
+ i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_6_Template_span_click_1_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.showDataContextDialog()); });
234
234
  i0.ɵɵelementEnd()();
235
235
  } }
236
- function SkipChatComponent_Conditional_17_Conditional_6_Template(rf, ctx) { if (rf & 1) {
236
+ function SkipChatComponent_Conditional_17_Conditional_7_Template(rf, ctx) { if (rf & 1) {
237
237
  const _r17 = i0.ɵɵgetCurrentView();
238
- i0.ɵɵelementStart(0, "button", 69);
239
- i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.stopProcessing()); });
240
- i0.ɵɵelement(1, "span", 70);
238
+ i0.ɵɵelementStart(0, "button", 70);
239
+ i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.stopProcessing()); });
240
+ i0.ɵɵelement(1, "span", 71);
241
241
  i0.ɵɵelementEnd();
242
242
  } }
243
- function SkipChatComponent_Conditional_17_Conditional_7_Template(rf, ctx) { if (rf & 1) {
243
+ function SkipChatComponent_Conditional_17_Conditional_8_Template(rf, ctx) { if (rf & 1) {
244
244
  const _r18 = i0.ɵɵgetCurrentView();
245
- i0.ɵɵelementStart(0, "button", 71);
246
- i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.sendSkipMessage()); });
247
- i0.ɵɵelement(1, "span", 72);
245
+ i0.ɵɵelementStart(0, "button", 72);
246
+ i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_8_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.sendSkipMessage()); });
247
+ i0.ɵɵelement(1, "span", 73);
248
248
  i0.ɵɵelementEnd();
249
249
  } if (rf & 2) {
250
250
  const ctx_r2 = i0.ɵɵnextContext(2);
251
251
  i0.ɵɵproperty("disabled", ctx_r2.IsTextAreaEmpty());
252
252
  } }
253
- function SkipChatComponent_Conditional_17_Conditional_8_Template(rf, ctx) { if (rf & 1) {
253
+ function SkipChatComponent_Conditional_17_Conditional_9_Template(rf, ctx) { if (rf & 1) {
254
254
  const _r19 = i0.ɵɵgetCurrentView();
255
- i0.ɵɵelementStart(0, "button", 67)(1, "span", 73);
256
- i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_8_Template_span_click_1_listener() { i0.ɵɵrestoreView(_r19); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.showSharingDialog()); });
255
+ i0.ɵɵelementStart(0, "button", 68)(1, "span", 74);
256
+ i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Conditional_9_Template_span_click_1_listener() { i0.ɵɵrestoreView(_r19); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.showSharingDialog()); });
257
257
  i0.ɵɵelementEnd()();
258
258
  } }
259
259
  function SkipChatComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
260
260
  const _r15 = i0.ɵɵgetCurrentView();
261
- i0.ɵɵelementStart(0, "div", 20)(1, "div", 61)(2, "textarea", 62, 5);
262
- i0.ɵɵlistener("keyup.enter", function SkipChatComponent_Conditional_17_Template_textarea_keyup_enter_2_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onEnter($event)); })("input", function SkipChatComponent_Conditional_17_Template_textarea_input_2_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onInputChange($event)); });
263
- i0.ɵɵelementEnd()();
264
- i0.ɵɵelementStart(4, "div", 63);
265
- i0.ɵɵtemplate(5, SkipChatComponent_Conditional_17_Conditional_5_Template, 2, 0, "button", 64)(6, SkipChatComponent_Conditional_17_Conditional_6_Template, 2, 0, "button", 65)(7, SkipChatComponent_Conditional_17_Conditional_7_Template, 2, 1, "button", 66)(8, SkipChatComponent_Conditional_17_Conditional_8_Template, 2, 0, "button", 67);
266
- i0.ɵɵelementEnd()();
261
+ i0.ɵɵelementStart(0, "div", 20)(1, "div", 61)(2, "div", 62)(3, "textarea", 63, 5);
262
+ i0.ɵɵlistener("keyup.enter", function SkipChatComponent_Conditional_17_Template_textarea_keyup_enter_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onEnter($event)); })("input", function SkipChatComponent_Conditional_17_Template_textarea_input_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onInputChange($event)); });
263
+ i0.ɵɵelementEnd();
264
+ i0.ɵɵelementStart(5, "div", 64);
265
+ i0.ɵɵtemplate(6, SkipChatComponent_Conditional_17_Conditional_6_Template, 2, 0, "button", 65)(7, SkipChatComponent_Conditional_17_Conditional_7_Template, 2, 0, "button", 66)(8, SkipChatComponent_Conditional_17_Conditional_8_Template, 2, 1, "button", 67)(9, SkipChatComponent_Conditional_17_Conditional_9_Template, 2, 0, "button", 68);
266
+ i0.ɵɵelementEnd()()()();
267
267
  } if (rf & 2) {
268
268
  const ctx_r2 = i0.ɵɵnextContext();
269
- i0.ɵɵadvance(2);
269
+ i0.ɵɵadvance(3);
270
270
  i0.ɵɵproperty("disabled", ctx_r2.SelectedConversation && ctx_r2.IsSkipProcessing(ctx_r2.SelectedConversation))("placeholder", ctx_r2._AskSkipTextboxPlaceholder);
271
- i0.ɵɵadvance(2);
272
- i0.ɵɵstyleProp("margin-left", -35 * ctx_r2.NumVisibleButtons, "px");
273
- i0.ɵɵadvance();
274
- i0.ɵɵconditional(ctx_r2.ShowDataContextButton ? 5 : -1);
271
+ i0.ɵɵadvance(3);
272
+ i0.ɵɵconditional(ctx_r2.ShowDataContextButton ? 6 : -1);
275
273
  i0.ɵɵadvance();
276
- i0.ɵɵconditional(ctx_r2.SelectedConversation && ctx_r2.IsSkipProcessing(ctx_r2.SelectedConversation) ? 6 : 7);
274
+ i0.ɵɵconditional(ctx_r2.SelectedConversation && ctx_r2.IsSkipProcessing(ctx_r2.SelectedConversation) ? 7 : 8);
277
275
  i0.ɵɵadvance(2);
278
- i0.ɵɵconditional(ctx_r2.ShowSharingButton && ctx_r2.SelectedConversationCurrentUserPermissionLevel === "Owner" ? 8 : -1);
276
+ i0.ɵɵconditional(ctx_r2.ShowSharingButton && ctx_r2.SelectedConversationCurrentUserPermissionLevel === "Owner" ? 9 : -1);
279
277
  } }
280
278
  function SkipChatComponent_skip_artifact_viewer_19_Template(rf, ctx) { if (rf & 1) {
281
279
  const _r20 = i0.ɵɵgetCurrentView();
282
- i0.ɵɵelementStart(0, "skip-artifact-viewer", 74);
280
+ i0.ɵɵelementStart(0, "skip-artifact-viewer", 75);
283
281
  i0.ɵɵlistener("NavigateToMatchingReport", function SkipChatComponent_skip_artifact_viewer_19_Template_skip_artifact_viewer_NavigateToMatchingReport_0_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.NavigateToMatchingReport.emit($event)); })("NewReportCreated", function SkipChatComponent_skip_artifact_viewer_19_Template_skip_artifact_viewer_NewReportCreated_0_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.NewReportCreated.emit($event)); })("DrillDownEvent", function SkipChatComponent_skip_artifact_viewer_19_Template_skip_artifact_viewer_DrillDownEvent_0_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.DrillDownEvent.emit($event)); })("ArtifactInfoChanged", function SkipChatComponent_skip_artifact_viewer_19_Template_skip_artifact_viewer_ArtifactInfoChanged_0_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onArtifactInfoChanged($event)); });
284
282
  i0.ɵɵelementEnd();
285
283
  } if (rf & 2) {
@@ -288,7 +286,7 @@ function SkipChatComponent_skip_artifact_viewer_19_Template(rf, ctx) { if (rf &
288
286
  } }
289
287
  function SkipChatComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
290
288
  const _r21 = i0.ɵɵgetCurrentView();
291
- i0.ɵɵelementStart(0, "mj-data-context-dialog", 75);
289
+ i0.ɵɵelementStart(0, "mj-data-context-dialog", 76);
292
290
  i0.ɵɵlistener("dialogClosed", function SkipChatComponent_Conditional_20_Template_mj_data_context_dialog_dialogClosed_0_listener() { i0.ɵɵrestoreView(_r21); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDataContextDialog()); });
293
291
  i0.ɵɵelementEnd();
294
292
  } if (rf & 2) {
@@ -297,14 +295,14 @@ function SkipChatComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
297
295
  } }
298
296
  function SkipChatComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
299
297
  const _r22 = i0.ɵɵgetCurrentView();
300
- i0.ɵɵelementStart(0, "kendo-dialog", 76);
298
+ i0.ɵɵelementStart(0, "kendo-dialog", 77);
301
299
  i0.ɵɵlistener("close", function SkipChatComponent_Conditional_21_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeSharingDialog("no")); });
302
- i0.ɵɵelement(1, "mj-resource-permissions", 77, 6);
303
- i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 78);
300
+ i0.ɵɵelement(1, "mj-resource-permissions", 78, 6);
301
+ i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 79);
304
302
  i0.ɵɵlistener("click", function SkipChatComponent_Conditional_21_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r22); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeSharingDialog("yes")); });
305
303
  i0.ɵɵtext(5, " Save ");
306
304
  i0.ɵɵelementEnd();
307
- i0.ɵɵelementStart(6, "button", 79);
305
+ i0.ɵɵelementStart(6, "button", 80);
308
306
  i0.ɵɵlistener("click", function SkipChatComponent_Conditional_21_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r22); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeSharingDialog("no")); });
309
307
  i0.ɵɵtext(7, " Cancel ");
310
308
  i0.ɵɵelementEnd()()();
@@ -316,16 +314,16 @@ function SkipChatComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
316
314
  } }
317
315
  function SkipChatComponent_kendo_dialog_22_Template(rf, ctx) { if (rf & 1) {
318
316
  const _r23 = i0.ɵɵgetCurrentView();
319
- i0.ɵɵelementStart(0, "kendo-dialog", 80);
317
+ i0.ɵɵelementStart(0, "kendo-dialog", 81);
320
318
  i0.ɵɵlistener("close", function SkipChatComponent_kendo_dialog_22_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDeleteConversation("no")); });
321
- i0.ɵɵelementStart(1, "p", 81);
319
+ i0.ɵɵelementStart(1, "p", 82);
322
320
  i0.ɵɵtext(2);
323
321
  i0.ɵɵelementEnd();
324
- i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 78);
322
+ i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 79);
325
323
  i0.ɵɵlistener("click", function SkipChatComponent_kendo_dialog_22_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r23); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDeleteConversation("yes")); });
326
324
  i0.ɵɵtext(5, " Yes ");
327
325
  i0.ɵɵelementEnd();
328
- i0.ɵɵelementStart(6, "button", 79);
326
+ i0.ɵɵelementStart(6, "button", 80);
329
327
  i0.ɵɵlistener("click", function SkipChatComponent_kendo_dialog_22_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r23); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDeleteConversation("no")); });
330
328
  i0.ɵɵtext(7, " No ");
331
329
  i0.ɵɵelementEnd()()();
@@ -337,16 +335,16 @@ function SkipChatComponent_kendo_dialog_22_Template(rf, ctx) { if (rf & 1) {
337
335
  } }
338
336
  function SkipChatComponent_kendo_dialog_23_Template(rf, ctx) { if (rf & 1) {
339
337
  const _r24 = i0.ɵɵgetCurrentView();
340
- i0.ɵɵelementStart(0, "kendo-dialog", 80);
338
+ i0.ɵɵelementStart(0, "kendo-dialog", 81);
341
339
  i0.ɵɵlistener("close", function SkipChatComponent_kendo_dialog_23_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r24); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeMessageEditOrDeleteDialog("no")); });
342
- i0.ɵɵelementStart(1, "p", 81);
340
+ i0.ɵɵelementStart(1, "p", 82);
343
341
  i0.ɵɵtext(2);
344
342
  i0.ɵɵelementEnd();
345
- i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 78);
343
+ i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 79);
346
344
  i0.ɵɵlistener("click", function SkipChatComponent_kendo_dialog_23_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r24); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeMessageEditOrDeleteDialog("yes")); });
347
345
  i0.ɵɵtext(5, " Yes ");
348
346
  i0.ɵɵelementEnd();
349
- i0.ɵɵelementStart(6, "button", 79);
347
+ i0.ɵɵelementStart(6, "button", 80);
350
348
  i0.ɵɵlistener("click", function SkipChatComponent_kendo_dialog_23_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r24); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeMessageEditOrDeleteDialog("no")); });
351
349
  i0.ɵɵtext(7, " No ");
352
350
  i0.ɵɵelementEnd()()();
@@ -482,6 +480,9 @@ export class SkipChatComponent extends BaseManagedComponent {
482
480
  _intersectionObserver;
483
481
  static __skipChatWindowsCurrentlyVisible = 0;
484
482
  sub;
483
+ // Per-conversation status message tracking
484
+ _statusMessagesByConversation = {};
485
+ _temporaryMessagesByConversation = {};
485
486
  /**
486
487
  * Currently selected artifact for viewing in the split panel
487
488
  */
@@ -568,6 +569,24 @@ export class SkipChatComponent extends BaseManagedComponent {
568
569
  this.HandlePushStatusUpdate(event.args);
569
570
  }
570
571
  });
572
+ // Set up the push status subscription
573
+ this.setupPushStatusSubscription();
574
+ }
575
+ catch (e) {
576
+ LogError(e);
577
+ }
578
+ }
579
+ LogVerbose(message) {
580
+ if (this.VerboseLogging) {
581
+ LogStatus(message);
582
+ }
583
+ }
584
+ /**
585
+ * Sets up or re-establishes the push status subscription
586
+ * This is extracted as a separate method so it can be called after page reloads
587
+ */
588
+ setupPushStatusSubscription() {
589
+ try {
571
590
  // Directly subscribe to the push status updates from the GraphQLDataProvider. If SkipChat is running in an environment where someone else is NOT
572
591
  // picking them up and broadcasting via MJ Events, we need this. If we get both, that's okay too as the update will not look any different and be
573
592
  // near instant from the user's perspective.
@@ -587,38 +606,78 @@ export class SkipChatComponent extends BaseManagedComponent {
587
606
  this.LogVerbose('Push status update received in Skip Chat: ' + JSON.stringify(status));
588
607
  if (status && status.message) {
589
608
  const statusObj = SafeJSONParse(status.message);
590
- if (statusObj && statusObj.type === 'AskSkip') {
591
- this.HandlePushStatusUpdate(statusObj);
609
+ if (statusObj) {
610
+ if (statusObj.type === 'AskSkip' || statusObj.type === 'ConversationStatusUpdate') {
611
+ this.HandlePushStatusUpdate(statusObj);
612
+ }
592
613
  }
593
614
  }
594
615
  });
595
616
  }
596
617
  catch (e) {
597
- LogError(e);
598
- }
599
- }
600
- LogVerbose(message) {
601
- if (this.VerboseLogging) {
602
- LogStatus(message);
618
+ LogError(`Error setting up push status subscription: ${e}`);
603
619
  }
604
620
  }
605
621
  HandlePushStatusUpdate(statusObj) {
606
622
  try {
607
623
  const obj = statusObj;
608
- if (obj.type?.trim().toLowerCase() === 'askskip' && obj.status?.trim().toLowerCase() === 'ok') {
624
+ // Handle conversation status updates from the backend
625
+ if (obj.type === 'ConversationStatusUpdate' && obj.conversationID) {
626
+ // Find and update the conversation in our cached list
627
+ const conversation = this.Conversations.find(c => c.ID === obj.conversationID);
628
+ if (conversation && (obj.status === 'Processing' || obj.status === 'Available')) {
629
+ conversation.Status = obj.status;
630
+ // Handle status changes
631
+ if (obj.status === 'Processing') {
632
+ // Conversation started processing
633
+ if (obj.conversationID === this.SelectedConversation?.ID) {
634
+ // If this is the currently selected conversation, ensure we show status message
635
+ const cachedStatus = this._statusMessagesByConversation[obj.conversationID];
636
+ if (cachedStatus) {
637
+ this.SetSkipStatusMessage(cachedStatus.message, 0, cachedStatus.startTime);
638
+ }
639
+ }
640
+ }
641
+ else if (obj.status === 'Available') {
642
+ // Conversation finished processing - clear its tracking data
643
+ delete this._conversationsInProgress[obj.conversationID];
644
+ this._processingStatus[obj.conversationID] = false; // Set to false instead of deleting
645
+ delete this._statusMessagesByConversation[obj.conversationID];
646
+ delete this._temporaryMessagesByConversation[obj.conversationID];
647
+ // Only clear the UI status message if this is the currently selected conversation
648
+ if (obj.conversationID === this.SelectedConversation?.ID) {
649
+ this.SetSkipStatusMessage('', 0);
650
+ }
651
+ }
652
+ }
653
+ }
654
+ else if (obj.type?.trim().toLowerCase() === 'askskip' && obj.status?.trim().toLowerCase() === 'ok') {
609
655
  if (obj.conversationID && this._conversationsInProgress[obj.conversationID]) {
656
+ // Cache the status message for this conversation regardless of whether it's selected
657
+ if (obj.message && obj.message.length > 0) {
658
+ // Keep the original start time if it exists, otherwise use now
659
+ const existingStatus = this._statusMessagesByConversation[obj.conversationID];
660
+ this._statusMessagesByConversation[obj.conversationID] = {
661
+ message: obj.message,
662
+ startTime: existingStatus?.startTime || new Date()
663
+ };
664
+ this.LogVerbose(`Skip Chat: Cached status message for conversation ${obj.conversationID}: ${obj.message}`);
665
+ }
666
+ // If this is the currently selected conversation, update the display
610
667
  if (obj.conversationID === this.SelectedConversation?.ID) {
611
668
  if (obj.message && obj.message.length > 0) {
612
669
  // we are in the midst of a possibly long running process for Skip, and we got a message here, so go ahead and display it in the temporary message
613
- this.LogVerbose(`Skip Chat: Received Push Status for conversation ${obj.conversationID} with message: ${obj.message}`);
614
- this.SetSkipStatusMessage(obj.message, 0);
670
+ this.LogVerbose(`Skip Chat: Displaying Push Status for conversation ${obj.conversationID} with message: ${obj.message}`);
671
+ // Use the cached start time to preserve the timer
672
+ const cachedStatus = this._statusMessagesByConversation[obj.conversationID];
673
+ this.SetSkipStatusMessage(obj.message, 0, cachedStatus?.startTime);
615
674
  }
616
675
  else {
617
676
  this.LogVerbose(`Skip Chat: Received Push Status but no message for conversation ${obj.conversationID}`);
618
677
  }
619
678
  }
620
679
  else {
621
- this.LogVerbose(`Skip Chat: Received Push Status for conversation ${obj.conversationID} but it's not the current conversation`);
680
+ this.LogVerbose(`Skip Chat: Received Push Status for conversation ${obj.conversationID} but it's not the current conversation - cached for later`);
622
681
  }
623
682
  }
624
683
  else {
@@ -666,10 +725,25 @@ export class SkipChatComponent extends BaseManagedComponent {
666
725
  this.InnerSetSkipStatusMessage(message, startTime);
667
726
  }
668
727
  InnerSetSkipStatusMessage(message, startTime) {
728
+ const conversationId = this.SelectedConversation?.ID;
669
729
  if (message && message.length > 0) {
730
+ // Store the status message for the current conversation
731
+ if (conversationId) {
732
+ // Preserve existing start time if we have one
733
+ const existingStatus = this._statusMessagesByConversation[conversationId];
734
+ this._statusMessagesByConversation[conversationId] = {
735
+ message,
736
+ startTime: startTime || existingStatus?.startTime || new Date()
737
+ };
738
+ }
670
739
  if (!this._temporaryMessage) {
671
- this._temporaryMessage = { ID: -1, Message: message, Role: 'ai', __mj_CreatedAt: startTime }; // create a new object
740
+ const actualStartTime = startTime || (conversationId ? this._statusMessagesByConversation[conversationId]?.startTime : undefined) || new Date();
741
+ this._temporaryMessage = { ID: -1, Message: message, Role: 'ai', __mj_CreatedAt: actualStartTime }; // create a new object
672
742
  this.AddMessageToCurrentConversation(this._temporaryMessage, true, false);
743
+ // Store the temporary message for this conversation
744
+ if (conversationId) {
745
+ this._temporaryMessagesByConversation[conversationId] = this._temporaryMessage;
746
+ }
673
747
  }
674
748
  else {
675
749
  this._temporaryMessage.Message = message;
@@ -688,6 +762,14 @@ export class SkipChatComponent extends BaseManagedComponent {
688
762
  // get rid of the temporary message
689
763
  this.RemoveMessageFromCurrentConversation(this._temporaryMessage);
690
764
  this._temporaryMessage = undefined;
765
+ // Clear the cached temporary message for this conversation
766
+ if (conversationId && this._temporaryMessagesByConversation[conversationId]) {
767
+ delete this._temporaryMessagesByConversation[conversationId];
768
+ }
769
+ }
770
+ // Clear the status message cache when clearing the message
771
+ if (conversationId && this._statusMessagesByConversation[conversationId]) {
772
+ delete this._statusMessagesByConversation[conversationId];
691
773
  }
692
774
  this._AskSkipTextboxPlaceholder = this.DefaultTextboxPlaceholder;
693
775
  }
@@ -721,21 +803,37 @@ export class SkipChatComponent extends BaseManagedComponent {
721
803
  checkForProcessingConversations() {
722
804
  try {
723
805
  if (this.Conversations && this.Conversations.length > 0) {
806
+ let hasProcessingConversations = false;
724
807
  // Check each conversation's status
725
808
  for (const convo of this.Conversations) {
726
809
  if (convo.Status === 'Processing') {
727
- // This conversation is currently being processed
810
+ hasProcessingConversations = true;
811
+ // Mark as in progress
812
+ this._conversationsInProgress[convo.ID] = true;
813
+ this._processingStatus[convo.ID] = true; // Also update processing status for UI
814
+ this._messageInProgress = true;
815
+ this.AllowSend = false;
728
816
  // If this is the currently selected conversation, update the UI
729
817
  if (this.SelectedConversation && this.SelectedConversation.ID === convo.ID) {
730
818
  this.setProcessingStatus(convo.ID, true);
731
819
  this.startRequestStatusPolling(convo.ID);
732
- this.SetSkipStatusMessage("Processing...", 0, convo.__mj_UpdatedAt);
820
+ // Don't overwrite if we're already handling this conversation
821
+ if (!this._temporaryMessage) {
822
+ // Restore the cached status message if available
823
+ const cachedStatus = this._statusMessagesByConversation[convo.ID];
824
+ const statusMessage = cachedStatus?.message || "Processing...";
825
+ const statusStartTime = cachedStatus?.startTime || convo.__mj_UpdatedAt;
826
+ this.SetSkipStatusMessage(statusMessage, 0, statusStartTime);
827
+ // Note: We don't request status here as SelectConversation will handle it
828
+ // This avoids duplicate requests to the backend
829
+ }
733
830
  }
734
- this._conversationsInProgress[convo.ID] = true;
735
- this._messageInProgress = true;
736
- this.AllowSend = false;
737
831
  }
738
832
  }
833
+ // If we have processing conversations and no push subscription, set it up
834
+ if (hasProcessingConversations && !this._providerPushStatusSub) {
835
+ this.setupPushStatusSubscription();
836
+ }
739
837
  }
740
838
  }
741
839
  catch (error) {
@@ -766,6 +864,55 @@ export class SkipChatComponent extends BaseManagedComponent {
766
864
  delete this._requestStatusPollingIntervals[conversationId];
767
865
  }
768
866
  }
867
+ /**
868
+ * Requests the current status message from the backend for a processing conversation
869
+ * This is needed after page reloads when we lose the cached status messages
870
+ */
871
+ async requestCurrentConversationStatus(conversationId) {
872
+ try {
873
+ // Make sure we're subscribed to push updates if we aren't already
874
+ // This ensures we'll receive any ongoing status updates
875
+ if (!this._providerPushStatusSub) {
876
+ this.setupPushStatusSubscription();
877
+ }
878
+ // Mark this conversation as in progress so we handle future updates properly
879
+ this._conversationsInProgress[conversationId] = true;
880
+ // Call the backend to re-attach this session to the processing conversation
881
+ const gql = `query ReattachToProcessingConversation($conversationId: String!) {
882
+ ReattachToProcessingConversation(ConversationId: $conversationId) {
883
+ lastStatusMessage
884
+ startTime
885
+ }
886
+ }`;
887
+ const gqlProvider = this.ProviderToUse;
888
+ const result = await gqlProvider.ExecuteGQL(gql, {
889
+ conversationId: conversationId
890
+ });
891
+ if (result && result.ReattachToProcessingConversation) {
892
+ const response = result.ReattachToProcessingConversation;
893
+ const lastStatusMessage = response.lastStatusMessage;
894
+ const startTime = response.startTime ? new Date(response.startTime) : null;
895
+ // Update the cached status message with what we got from the backend
896
+ if (lastStatusMessage && lastStatusMessage !== 'Processing your request...') {
897
+ this._statusMessagesByConversation[conversationId] = {
898
+ message: lastStatusMessage,
899
+ startTime: startTime || this._statusMessagesByConversation[conversationId]?.startTime || new Date()
900
+ };
901
+ // Update the display if this is the current conversation
902
+ if (conversationId === this.SelectedConversation?.ID) {
903
+ const cachedStatus = this._statusMessagesByConversation[conversationId];
904
+ this.SetSkipStatusMessage(lastStatusMessage, 0, cachedStatus?.startTime);
905
+ }
906
+ }
907
+ }
908
+ else {
909
+ // Could not re-attach - conversation may no longer be processing
910
+ }
911
+ }
912
+ catch (error) {
913
+ LogError(`Error requesting conversation status: ${error}`);
914
+ }
915
+ }
769
916
  /**
770
917
  * Loads conversation details for a specific conversation and role
771
918
  * @param conversationId The ID of the conversation
@@ -816,13 +963,13 @@ export class SkipChatComponent extends BaseManagedComponent {
816
963
  this.cdRef.detach();
817
964
  if (convoID !== this.SelectedConversation?.ID) {
818
965
  // this scenario arises when we have a selected convo change after we submitted our request to skip
819
- // so we do nothing here other than update the status.
820
- this.setProcessingStatus(convoID, false);
966
+ // so we just mark it for reload, don't update processing status
821
967
  //the next time the user selects this convo, we will fetch messages
822
968
  //from the server rather than using the ones in cache
823
969
  this._conversationsToReload[convoID] = true;
824
970
  }
825
971
  else {
972
+ // Only update processing status for the selected conversation
826
973
  this.setProcessingStatus(convoID, false);
827
974
  if (this.SelectedConversation.Name === 'New Chat' || this.SelectedConversation.Name?.trim().length === 0 || this.SelectedConversation.Name !== conversation.Name) {
828
975
  // we are on the first message so skip renamed the convo, use that
@@ -838,6 +985,10 @@ export class SkipChatComponent extends BaseManagedComponent {
838
985
  }, 100, { purpose: 'scroll-after-ai-message' });
839
986
  // Automatically show artifact if the new AI message has one
840
987
  this.autoShowArtifactIfPresent(aiDetail);
988
+ // Check if the conversation name was updated on the server (especially when artifacts are created)
989
+ if (aiDetail.ArtifactID) {
990
+ await this.syncConversationNameFromServer(conversation.ID);
991
+ }
841
992
  }
842
993
  // NOTE: we don't create a user notification at this point, that is done on the server and via GraphQL subscriptions it tells us and we update the UI automatically...
843
994
  }
@@ -853,15 +1004,20 @@ export class SkipChatComponent extends BaseManagedComponent {
853
1004
  }
854
1005
  this.AllowSend = true;
855
1006
  this._conversationsInProgress[convoID] = false;
1007
+ // Set processing status to false for this conversation
1008
+ this._processingStatus[convoID] = false;
856
1009
  this._messageInProgress = false;
857
1010
  // now tell Angular to resume its change detection
858
1011
  this.cdRef.reattach();
859
1012
  this.cdRef.detectChanges();
860
1013
  // invoke manual resize with a delay to ensure that the scroll to bottom has taken place
861
1014
  //InvokeManualResize();
862
- this.SetSkipStatusMessage('', 500); // slight delay to ensure that the message is removed after the UI has updated with the new response message
863
- // now set focus on the input box
864
- this.askSkipInput.nativeElement.focus();
1015
+ // Only clear the status message if this is the currently selected conversation
1016
+ if (convoID === this.SelectedConversation?.ID) {
1017
+ this.SetSkipStatusMessage('', 500); // slight delay to ensure that the message is removed after the UI has updated with the new response message
1018
+ // now set focus on the input box
1019
+ this.askSkipInput.nativeElement.focus();
1020
+ }
865
1021
  }
866
1022
  }
867
1023
  catch (error) {
@@ -869,6 +1025,8 @@ export class SkipChatComponent extends BaseManagedComponent {
869
1025
  }
870
1026
  }
871
1027
  ngOnDestroy() {
1028
+ // Clean up all message subscriptions
1029
+ this.ClearMessages();
872
1030
  // Unsubscribe to prevent memory leaks
873
1031
  if (this.paramsSubscription) {
874
1032
  this.paramsSubscription.unsubscribe();
@@ -1346,9 +1504,7 @@ export class SkipChatComponent extends BaseManagedComponent {
1346
1504
  }
1347
1505
  else {
1348
1506
  this.DataContext = new DataContext();
1349
- const start = new Date().getTime();
1350
1507
  await this.DataContext.LoadMetadata(this.DataContextID, this.ProviderToUse.CurrentUser, this.ProviderToUse);
1351
- LogStatus('Skip Chat: Time to load data context: ' + (new Date().getTime() - start) + 'ms');
1352
1508
  // cache it for later
1353
1509
  convoAny._DataContext = this.DataContext;
1354
1510
  }
@@ -1385,19 +1541,42 @@ export class SkipChatComponent extends BaseManagedComponent {
1385
1541
  }, 300, { purpose: 'scroll-after-messages-render' }); // Give DOM time to render all messages
1386
1542
  }
1387
1543
  this.setProcessingStatus(conversation.ID, oldStatus); // set back to old status as it might have been processing
1388
- // Check if this conversation is in 'Processing' status and restore the streaming state
1389
- if (conversation.Status === 'Processing') {
1544
+ // Check if this conversation is actually processing (regardless of DB status)
1545
+ if (conversation.Status === 'Processing' || this._conversationsInProgress[conversation.ID]) {
1390
1546
  // This conversation is currently being processed
1391
1547
  this.setProcessingStatus(conversation.ID, true);
1392
1548
  this._conversationsInProgress[conversation.ID] = true;
1393
1549
  this._messageInProgress = true;
1394
1550
  this.AllowSend = false;
1395
- // Create the temporary status message after a brief delay to ensure DOM is ready
1396
- this.setTimeout(() => {
1551
+ // Check if we have a cached status message (from before reload)
1552
+ const cachedStatus = this._statusMessagesByConversation[conversation.ID];
1553
+ if (!cachedStatus && conversation.Status === 'Processing') {
1554
+ // Show a default message immediately while we fetch the real status
1397
1555
  this.SetSkipStatusMessage("Processing...", 0, conversation.__mj_UpdatedAt);
1398
- // Start polling after the temporary message is created
1556
+ // After a page reload or when switching to a conversation without cached status,
1557
+ // request the current status from the backend and update when ready
1558
+ this.requestCurrentConversationStatus(conversation.ID).then(() => {
1559
+ // After getting the status from backend, update the message with the correct start time
1560
+ const updatedStatus = this._statusMessagesByConversation[conversation.ID];
1561
+ if (updatedStatus) {
1562
+ this.SetSkipStatusMessage(updatedStatus.message, 0, updatedStatus.startTime);
1563
+ }
1564
+ // Start polling after getting the real status
1565
+ this.startRequestStatusPolling(conversation.ID);
1566
+ });
1567
+ }
1568
+ else {
1569
+ // We have cached status, use it directly and immediately
1570
+ const statusMessage = cachedStatus?.message || "Processing...";
1571
+ const statusStartTime = cachedStatus?.startTime || conversation.__mj_UpdatedAt;
1572
+ // Set the status message immediately since we have cached data
1573
+ this.SetSkipStatusMessage(statusMessage, 0, statusStartTime);
1574
+ // Start polling immediately
1399
1575
  this.startRequestStatusPolling(conversation.ID);
1400
- }, 100);
1576
+ }
1577
+ }
1578
+ else {
1579
+ // Conversation is not processing
1401
1580
  }
1402
1581
  InvokeManualResize(500);
1403
1582
  // ensure the list box has the conversation in view
@@ -1494,7 +1673,16 @@ export class SkipChatComponent extends BaseManagedComponent {
1494
1673
  this.AddMessageToCurrentConversation(convoDetail, true, true);
1495
1674
  this.askSkipInput.nativeElement.value = '';
1496
1675
  this.resizeTextInput();
1497
- this.SetSkipStatusMessage(this.pickSkipStartMessage(), 850);
1676
+ // Store the start time when first creating the status message
1677
+ const startTime = new Date();
1678
+ const statusMessage = this.pickSkipStartMessage();
1679
+ if (convoID) {
1680
+ this._statusMessagesByConversation[convoID] = {
1681
+ message: statusMessage,
1682
+ startTime: startTime
1683
+ };
1684
+ }
1685
+ this.SetSkipStatusMessage(statusMessage, 850, startTime);
1498
1686
  // Ensure scroll to bottom after adding user message AND progress message
1499
1687
  this.setTimeout(() => {
1500
1688
  this.scrollToBottom();
@@ -1506,13 +1694,13 @@ export class SkipChatComponent extends BaseManagedComponent {
1506
1694
  if (skipResult?.Success) {
1507
1695
  if (convoID !== this.SelectedConversation?.ID) {
1508
1696
  // this scenario arises when we have a selected convo change after we submitted our request to skip
1509
- // so we do nothing here other than update the status.
1510
- this.setProcessingStatus(convoID, false);
1697
+ // so we just mark it for reload, don't update processing status
1511
1698
  //the next time the user selects this convo, we will fetch messages
1512
1699
  //from the server rather than using the ones in cache
1513
1700
  this._conversationsToReload[convoID] = true;
1514
1701
  }
1515
1702
  else {
1703
+ // Only update processing status for the selected conversation
1516
1704
  this.setProcessingStatus(convoID, false);
1517
1705
  const innerResult = JSON.parse(skipResult.Result);
1518
1706
  if (!this.SelectedConversation) {
@@ -1549,23 +1737,33 @@ export class SkipChatComponent extends BaseManagedComponent {
1549
1737
  }, 100, { purpose: 'scroll-after-ai-response' });
1550
1738
  // Automatically show artifact if the new AI message has one
1551
1739
  this.autoShowArtifactIfPresent(aiDetail);
1740
+ // Check if the conversation name was updated on the server (especially when artifacts are created)
1741
+ if (aiDetail.ArtifactID) {
1742
+ await this.syncConversationNameFromServer(this.SelectedConversation.ID);
1743
+ }
1552
1744
  // NOTE: we don't create a user notification at this point, that is done on the server and via GraphQL subscriptions it tells us and we update the UI automatically...
1553
1745
  }
1554
1746
  }
1555
- if (this.SelectedConversation) {
1747
+ // Only update processing status if this is the currently selected conversation
1748
+ if (this.SelectedConversation && this.SelectedConversation.ID === convoID) {
1556
1749
  this.setProcessingStatus(this.SelectedConversation.ID, false);
1557
1750
  }
1558
1751
  this.AllowSend = true;
1559
1752
  this._conversationsInProgress[convoID] = false;
1753
+ // Set processing status to false for this conversation
1754
+ this._processingStatus[convoID] = false;
1560
1755
  this._messageInProgress = false;
1561
1756
  // now tell Angular to resume its change detection
1562
1757
  this.cdRef.reattach();
1563
1758
  this.cdRef.detectChanges();
1564
1759
  // invoke manual resize with a delay to ensure that the scroll to bottom has taken place
1565
1760
  //InvokeManualResize();
1566
- this.SetSkipStatusMessage('', 500); // slight delay to ensure that the message is removed after the UI has updated with the new response message
1567
- // now set focus on the input box
1568
- this.askSkipInput.nativeElement.focus();
1761
+ // Only clear the status message if this is the currently selected conversation
1762
+ if (convoID === this.SelectedConversation?.ID) {
1763
+ this.SetSkipStatusMessage('', 500); // slight delay to ensure that the message is removed after the UI has updated with the new response message
1764
+ // now set focus on the input box
1765
+ this.askSkipInput.nativeElement.focus();
1766
+ }
1569
1767
  }
1570
1768
  }
1571
1769
  async sendSkipMessage() {
@@ -1576,8 +1774,22 @@ export class SkipChatComponent extends BaseManagedComponent {
1576
1774
  await this.sendPrompt(input);
1577
1775
  }
1578
1776
  ClearMessages() {
1777
+ // Clean up all message subscriptions before clearing
1778
+ if (this.Messages && this.Messages.length > 0) {
1779
+ this.Messages.forEach((message) => {
1780
+ const subscriptions = message._subscriptions;
1781
+ if (subscriptions && Array.isArray(subscriptions)) {
1782
+ subscriptions.forEach((sub) => {
1783
+ if (sub && sub.unsubscribe) {
1784
+ sub.unsubscribe();
1785
+ }
1786
+ });
1787
+ message._subscriptions = [];
1788
+ }
1789
+ });
1790
+ }
1579
1791
  this.Messages = []; // clear out the messages
1580
- // Clear the temporary message reference
1792
+ // Clear the temporary message reference (but keep the cached ones)
1581
1793
  this._temporaryMessage = undefined;
1582
1794
  // Get the first mjContainer in the DOM which is the one we're injecting into
1583
1795
  const containerElements = document.querySelectorAll('div[mjContainer]');
@@ -1634,6 +1846,16 @@ export class SkipChatComponent extends BaseManagedComponent {
1634
1846
  if (ref) {
1635
1847
  // Temporarily stop change detection for performance
1636
1848
  this.cdRef.detach();
1849
+ // Clean up subscriptions before destroying the component
1850
+ const subscriptions = messageDetail._subscriptions;
1851
+ if (subscriptions && Array.isArray(subscriptions)) {
1852
+ subscriptions.forEach((sub) => {
1853
+ if (sub && sub.unsubscribe) {
1854
+ sub.unsubscribe();
1855
+ }
1856
+ });
1857
+ messageDetail._subscriptions = [];
1858
+ }
1637
1859
  const index = this.askSkip.viewContainerRef.indexOf(ref.hostView);
1638
1860
  if (index !== -1) {
1639
1861
  this.askSkip.viewContainerRef.remove(index);
@@ -1669,25 +1891,27 @@ export class SkipChatComponent extends BaseManagedComponent {
1669
1891
  const componentRef = this.askSkip.viewContainerRef.createComponent(SkipSingleMessageComponent);
1670
1892
  // Pass the message details to the component instance
1671
1893
  const obj = componentRef.instance;
1894
+ // Store subscriptions so we can clean them up later
1895
+ const subscriptions = [];
1672
1896
  // bubble up events from the single message component to the parent component
1673
- obj.NavigateToMatchingReport.subscribe((reportId) => {
1897
+ subscriptions.push(obj.NavigateToMatchingReport.subscribe((reportId) => {
1674
1898
  this.NavigateToMatchingReport.emit(reportId);
1675
- });
1676
- obj.NewReportCreated.subscribe((reportId) => {
1899
+ }));
1900
+ subscriptions.push(obj.NewReportCreated.subscribe((reportId) => {
1677
1901
  this.NewReportCreated.emit(reportId);
1678
- });
1679
- obj.DeleteMessageRequested.subscribe((message) => {
1902
+ }));
1903
+ subscriptions.push(obj.DeleteMessageRequested.subscribe((message) => {
1680
1904
  this.HandleMessageDeleteRequest(message);
1681
- });
1682
- obj.EditMessageRequested.subscribe((message) => {
1905
+ }));
1906
+ subscriptions.push(obj.EditMessageRequested.subscribe((message) => {
1683
1907
  this.HandleMessageEditRequest(message);
1684
- });
1685
- obj.DrillDownEvent.subscribe((drillDownInfo) => {
1908
+ }));
1909
+ subscriptions.push(obj.DrillDownEvent.subscribe((drillDownInfo) => {
1686
1910
  this.DrillDownEvent.emit(drillDownInfo);
1687
- });
1688
- obj.ArtifactSelected.subscribe((artifact) => {
1911
+ }));
1912
+ subscriptions.push(obj.ArtifactSelected.subscribe((artifact) => {
1689
1913
  this.onArtifactSelected(artifact);
1690
- });
1914
+ }));
1691
1915
  obj.Provider = this.ProviderToUse;
1692
1916
  obj.SkipMarkOnlyLogoURL = this.SkipMarkOnlyLogoURL;
1693
1917
  obj.UserImage = this.UserImage;
@@ -1702,15 +1926,17 @@ export class SkipChatComponent extends BaseManagedComponent {
1702
1926
  // bind the processing status to the component
1703
1927
  obj.ConversationProcessing = this.IsSkipProcessing(this.SelectedConversation);
1704
1928
  // Whenever the suggested question is clicked on by the user in the single message component, we want to bubble that up here and send the prompt
1705
- obj.SuggestedQuestionSelected.subscribe((question) => {
1929
+ subscriptions.push(obj.SuggestedQuestionSelected.subscribe((question) => {
1706
1930
  this.sendPrompt(question);
1707
- });
1931
+ }));
1708
1932
  // Whenever the suggested answer is clicked on by the user in the single message component, we want to bubble that up here and send the prompt
1709
- obj.SuggestedAnswerSelected.subscribe((answer) => {
1933
+ subscriptions.push(obj.SuggestedAnswerSelected.subscribe((answer) => {
1710
1934
  this.sendPrompt(answer);
1711
- });
1935
+ }));
1712
1936
  // now, stash a link to our newly created componentRef inside the messageDetail so we know which componentRef to remove when we delete the message
1713
1937
  messageDetail._componentRef = componentRef;
1938
+ // Store subscriptions so we can clean them up when the message is removed
1939
+ messageDetail._subscriptions = subscriptions;
1714
1940
  // Resume change detection
1715
1941
  if (stopChangeDetection)
1716
1942
  this.cdRef.reattach();
@@ -1889,6 +2115,10 @@ export class SkipChatComponent extends BaseManagedComponent {
1889
2115
  else if (this._processingStatus[Conversation.ID]) {
1890
2116
  return this._processingStatus[Conversation.ID];
1891
2117
  }
2118
+ else if (Conversation.Status === 'Processing') {
2119
+ // Check the database status field as well (important for page refreshes)
2120
+ return true;
2121
+ }
1892
2122
  else {
1893
2123
  return false;
1894
2124
  }
@@ -2290,6 +2520,7 @@ export class SkipChatComponent extends BaseManagedComponent {
2290
2520
  // Clear processing state
2291
2521
  this.setProcessingStatus(this.SelectedConversation.ID, false);
2292
2522
  this._conversationsInProgress[this.SelectedConversation.ID] = false;
2523
+ this._processingStatus[this.SelectedConversation.ID] = false;
2293
2524
  this._messageInProgress = false;
2294
2525
  this.AllowSend = true;
2295
2526
  // Stop polling
@@ -2308,6 +2539,27 @@ export class SkipChatComponent extends BaseManagedComponent {
2308
2539
  this.notificationService.CreateSimpleNotification('Failed to stop processing', 'error', 3000);
2309
2540
  }
2310
2541
  }
2542
+ /**
2543
+ * Checks if the conversation name was updated on the server and syncs it to the UI
2544
+ * This typically happens when artifacts are created and Skip renames the conversation
2545
+ * @param conversationId The ID of the conversation to check
2546
+ */
2547
+ async syncConversationNameFromServer(conversationId) {
2548
+ const p = this.ProviderToUse;
2549
+ const updatedConvo = await p.GetEntityObject('Conversations', p.CurrentUser);
2550
+ await updatedConvo.Load(conversationId);
2551
+ if (this.SelectedConversation && updatedConvo.Name !== this.SelectedConversation.Name) {
2552
+ // Update the conversation name in memory
2553
+ this.SelectedConversation.Name = updatedConvo.Name;
2554
+ // Update the conversation in the list
2555
+ const idx = this.Conversations.findIndex((c) => c.ID === conversationId);
2556
+ if (idx >= 0) {
2557
+ this.Conversations[idx].Name = updatedConvo.Name;
2558
+ // Trigger change detection for the list
2559
+ this.Conversations = [...this.Conversations];
2560
+ }
2561
+ }
2562
+ }
2311
2563
  /**
2312
2564
  * Automatically shows an artifact if the provided AI message has one
2313
2565
  * This is called when new AI messages are received to automatically display artifacts
@@ -2422,7 +2674,7 @@ export class SkipChatComponent extends BaseManagedComponent {
2422
2674
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.topLevelDiv = _t.first);
2423
2675
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.resourcePermissionsRef = _t.first);
2424
2676
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.splitPanel = _t.first);
2425
- } }, inputs: { AllowSend: "AllowSend", Messages: "Messages", Conversations: "Conversations", SelectedConversation: "SelectedConversation", ConversationEditMode: "ConversationEditMode", ShowConversationList: "ShowConversationList", AllowNewConversations: "AllowNewConversations", Title: "Title", DataContextID: "DataContextID", LinkedEntity: "LinkedEntity", LinkedEntityCompositeKey: "LinkedEntityCompositeKey", ShowDataContextButton: "ShowDataContextButton", IncludeLinkedConversationsInList: "IncludeLinkedConversationsInList", SkipLogoURL: "SkipLogoURL", SkipMarkOnlyLogoURL: "SkipMarkOnlyLogoURL", UserImage: "UserImage", VerboseLogging: "VerboseLogging", UpdateAppRoute: "UpdateAppRoute", ShowSkipLogoInConversationList: "ShowSkipLogoInConversationList", ShowSharingButton: "ShowSharingButton", SharingExcludeRoleNames: "SharingExcludeRoleNames", SharingExcludeEmails: "SharingExcludeEmails", EnableArtifactSplitView: "EnableArtifactSplitView", DefaultSplitRatio: "DefaultSplitRatio", DefaultTextboxPlaceholder: "DefaultTextboxPlaceholder", ProcessingTextBoxPlaceholder: "ProcessingTextBoxPlaceholder", WelcomeQuestions: "WelcomeQuestions", AutoLoad: "AutoLoad" }, outputs: { NavigateToMatchingReport: "NavigateToMatchingReport", ConversationSelected: "ConversationSelected", NewReportCreated: "NewReportCreated", DrillDownEvent: "DrillDownEvent", ArtifactSelected: "ArtifactSelected", ArtifactViewed: "ArtifactViewed" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 24, vars: 18, consts: [["topLevelDiv", ""], ["splitPanel", ""], ["AskSkipPanel", ""], ["scrollContainer", ""], ["conversationList", ""], ["AskSkipInput", ""], ["resourcePermissions", ""], ["kendoDialogContainer", "", 1, "chat-container"], [1, "layout"], [1, "left-panel"], [1, "fa-solid", "fa-table-columns", "toggle-icon"], [1, "right-panel"], ["mjFillContainer", "", 3, "SplitRatioChanged", "VersionSelected", "Mode", "SplitRatio", "RightPanelHeaderContent", "VersionList", "SelectedVersionId", "fillWidth", "fillHeight"], ["left-panel", "", 1, "conversation-wrapper"], [2, "width", "0", "height", "0", "overflow", "hidden", "position", "absolute"], [1, "messages", 3, "scroll"], ["class", "welcome-wrapper", 4, "ngIf"], [1, "loading-convo-messages-wrapper"], ["mjContainer", "", "mjSkipResize", "true", 1, "messages-container"], ["class", "scroll-to-bottom-icon", 3, "left", "click", 4, "ngIf"], [1, "input-area"], ["right-panel", ""], [3, "ArtifactID", "ArtifactVersionID", "DataContext", "NavigateToMatchingReport", "NewReportCreated", "DrillDownEvent", "ArtifactInfoChanged", 4, "ngIf"], [3, "dataContextId", "Provider"], ["title", "Share Conversation", 3, "width", "height"], ["title", "Please confirm", 3, "minWidth", "width", "close", 4, "ngIf"], [1, "conversation-history"], [1, "new-chat-area"], [1, "fa-solid", "fa-table-columns", "toggle-icon", 3, "click"], [1, "avatar", 3, "src"], [1, "fa-solid", "fa-pen-to-square", "new-convo-icon"], [1, "conversation-list", 3, "data", "itemClass"], ["kendoListViewItemTemplate", ""], [1, "fa-solid", "fa-pen-to-square", "new-convo-icon", 3, "click"], [1, "conversation-item", 3, "click", "ngClass", "title"], ["class", "fa-regular fa-clock", 4, "ngIf"], [1, "text-container"], [4, "ngIf"], ["maxlength", "100", 3, "ngModel", "ngModelChange", 4, "ngIf"], ["class", "edit-conversation-panel", 4, "ngIf"], [1, "fa-regular", "fa-clock"], ["maxlength", "100", 3, "ngModelChange", "ngModel"], [1, "edit-conversation-panel"], ["class", "fa-solid fa-pen-to-square", 3, "click", 4, "ngIf"], ["class", "fa-regular fa-trash-can", 3, "click", 4, "ngIf"], ["class", "fa-solid fa-check", 3, "click", 4, "ngIf"], ["class", "fa-solid fa-xmark", 3, "click", 4, "ngIf"], [1, "fa-solid", "fa-pen-to-square", 3, "click"], [1, "fa-regular", "fa-trash-can", 3, "click"], [1, "fa-solid", "fa-check", 3, "click"], [1, "fa-solid", "fa-xmark", 3, "click"], [1, "welcome-wrapper"], [1, "welcome-message"], [3, "src"], [1, "welcome-header-text"], [1, "welcome-suggested-questions"], [1, "welcome-suggested-questions-col"], [1, "welcome-question", 3, "click"], [1, "welcome-question-header"], [1, "scroll-to-bottom-icon", 3, "click"], [1, "fas", "fa-arrow-down"], [1, "text-area-wrapper"], ["type", "text", 3, "keyup.enter", "input", "disabled", "placeholder"], [1, "button-area"], ["kendoButton", ""], ["kendoButton", "", 1, "stop-button"], ["kendoButton", "", 3, "disabled"], ["kendoButton", "", 1, "share-button"], [1, "fa-solid", "fa-gear", 3, "click"], ["kendoButton", "", 1, "stop-button", 3, "click"], [1, "fas", "fa-solid", "fa-stop"], ["kendoButton", "", 3, "click", "disabled"], [1, "fas", "fa-solid", "fa-arrow-up"], [1, "fa-solid", "fa-share", 3, "click"], [3, "NavigateToMatchingReport", "NewReportCreated", "DrillDownEvent", "ArtifactInfoChanged", "ArtifactID", "ArtifactVersionID", "DataContext"], [3, "dialogClosed", "dataContextId", "Provider"], ["title", "Share Conversation", 3, "close", "width", "height"], [3, "Provider", "ResourceTypeID", "ResourceRecordID", "ExcludedRoleNames", "ExcludedUserEmails"], ["kendoButton", "", "themeColor", "primary", 3, "click"], ["kendoButton", "", 3, "click"], ["title", "Please confirm", 3, "close", "minWidth", "width"], [2, "margin", "30px", "text-align", "center"]], template: function SkipChatComponent_Template(rf, ctx) { if (rf & 1) {
2677
+ } }, inputs: { AllowSend: "AllowSend", Messages: "Messages", Conversations: "Conversations", SelectedConversation: "SelectedConversation", ConversationEditMode: "ConversationEditMode", ShowConversationList: "ShowConversationList", AllowNewConversations: "AllowNewConversations", Title: "Title", DataContextID: "DataContextID", LinkedEntity: "LinkedEntity", LinkedEntityCompositeKey: "LinkedEntityCompositeKey", ShowDataContextButton: "ShowDataContextButton", IncludeLinkedConversationsInList: "IncludeLinkedConversationsInList", SkipLogoURL: "SkipLogoURL", SkipMarkOnlyLogoURL: "SkipMarkOnlyLogoURL", UserImage: "UserImage", VerboseLogging: "VerboseLogging", UpdateAppRoute: "UpdateAppRoute", ShowSkipLogoInConversationList: "ShowSkipLogoInConversationList", ShowSharingButton: "ShowSharingButton", SharingExcludeRoleNames: "SharingExcludeRoleNames", SharingExcludeEmails: "SharingExcludeEmails", EnableArtifactSplitView: "EnableArtifactSplitView", DefaultSplitRatio: "DefaultSplitRatio", DefaultTextboxPlaceholder: "DefaultTextboxPlaceholder", ProcessingTextBoxPlaceholder: "ProcessingTextBoxPlaceholder", WelcomeQuestions: "WelcomeQuestions", AutoLoad: "AutoLoad" }, outputs: { NavigateToMatchingReport: "NavigateToMatchingReport", ConversationSelected: "ConversationSelected", NewReportCreated: "NewReportCreated", DrillDownEvent: "DrillDownEvent", ArtifactSelected: "ArtifactSelected", ArtifactViewed: "ArtifactViewed" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 24, vars: 18, consts: [["topLevelDiv", ""], ["splitPanel", ""], ["AskSkipPanel", ""], ["scrollContainer", ""], ["conversationList", ""], ["AskSkipInput", ""], ["resourcePermissions", ""], ["kendoDialogContainer", "", 1, "chat-container"], [1, "layout"], [1, "left-panel"], [1, "fa-solid", "fa-table-columns", "toggle-icon"], [1, "right-panel"], ["mjFillContainer", "", 3, "SplitRatioChanged", "VersionSelected", "Mode", "SplitRatio", "RightPanelHeaderContent", "VersionList", "SelectedVersionId", "fillWidth", "fillHeight"], ["left-panel", "", 1, "conversation-wrapper"], [2, "width", "0", "height", "0", "overflow", "hidden", "position", "absolute"], [1, "messages", 3, "scroll"], ["class", "welcome-wrapper", 4, "ngIf"], [1, "loading-convo-messages-wrapper"], ["mjContainer", "", "mjSkipResize", "true", 1, "messages-container"], ["class", "scroll-to-bottom-icon", 3, "left", "click", 4, "ngIf"], [1, "input-area"], ["right-panel", ""], [3, "ArtifactID", "ArtifactVersionID", "DataContext", "NavigateToMatchingReport", "NewReportCreated", "DrillDownEvent", "ArtifactInfoChanged", 4, "ngIf"], [3, "dataContextId", "Provider"], ["title", "Share Conversation", 3, "width", "height"], ["title", "Please confirm", 3, "minWidth", "width", "close", 4, "ngIf"], [1, "conversation-history"], [1, "new-chat-area"], [1, "fa-solid", "fa-table-columns", "toggle-icon", 3, "click"], [1, "avatar", 3, "src"], [1, "fa-solid", "fa-pen-to-square", "new-convo-icon"], [1, "conversation-list", 3, "data", "itemClass"], ["kendoListViewItemTemplate", ""], [1, "fa-solid", "fa-pen-to-square", "new-convo-icon", 3, "click"], [1, "conversation-item", 3, "click", "ngClass", "title"], ["class", "fa-regular fa-clock", 4, "ngIf"], [1, "text-container"], [4, "ngIf"], ["maxlength", "100", 3, "ngModel", "ngModelChange", 4, "ngIf"], ["class", "edit-conversation-panel", 4, "ngIf"], [1, "fa-regular", "fa-clock"], ["maxlength", "100", 3, "ngModelChange", "ngModel"], [1, "edit-conversation-panel"], ["class", "fa-solid fa-pen-to-square", 3, "click", 4, "ngIf"], ["class", "fa-regular fa-trash-can", 3, "click", 4, "ngIf"], ["class", "fa-solid fa-check", 3, "click", 4, "ngIf"], ["class", "fa-solid fa-xmark", 3, "click", 4, "ngIf"], [1, "fa-solid", "fa-pen-to-square", 3, "click"], [1, "fa-regular", "fa-trash-can", 3, "click"], [1, "fa-solid", "fa-check", 3, "click"], [1, "fa-solid", "fa-xmark", 3, "click"], [1, "welcome-wrapper"], [1, "welcome-message"], [3, "src"], [1, "welcome-header-text"], [1, "welcome-suggested-questions"], [1, "welcome-suggested-questions-col"], [1, "welcome-question", 3, "click"], [1, "welcome-question-header"], [1, "scroll-to-bottom-icon", 3, "click"], [1, "fas", "fa-arrow-down"], [1, "input-container"], [1, "text-area-wrapper"], ["type", "text", 3, "keyup.enter", "input", "disabled", "placeholder"], [1, "button-area"], ["kendoButton", ""], ["kendoButton", "", 1, "stop-button"], ["kendoButton", "", 3, "disabled"], ["kendoButton", "", 1, "share-button"], [1, "fa-solid", "fa-gear", 3, "click"], ["kendoButton", "", 1, "stop-button", 3, "click"], [1, "fas", "fa-solid", "fa-stop"], ["kendoButton", "", 3, "click", "disabled"], [1, "fas", "fa-solid", "fa-arrow-up"], [1, "fa-solid", "fa-share", 3, "click"], [3, "NavigateToMatchingReport", "NewReportCreated", "DrillDownEvent", "ArtifactInfoChanged", "ArtifactID", "ArtifactVersionID", "DataContext"], [3, "dialogClosed", "dataContextId", "Provider"], ["title", "Share Conversation", 3, "close", "width", "height"], [3, "Provider", "ResourceTypeID", "ResourceRecordID", "ExcludedRoleNames", "ExcludedUserEmails"], ["kendoButton", "", "themeColor", "primary", 3, "click"], ["kendoButton", "", 3, "click"], ["title", "Please confirm", 3, "close", "minWidth", "width"], [2, "margin", "30px", "text-align", "center"]], template: function SkipChatComponent_Template(rf, ctx) { if (rf & 1) {
2426
2678
  const _r1 = i0.ɵɵgetCurrentView();
2427
2679
  i0.ɵɵelementStart(0, "div", 7, 0)(2, "div", 8);
2428
2680
  i0.ɵɵtemplate(3, SkipChatComponent_Conditional_3_Template, 9, 5, "div", 9)(4, SkipChatComponent_Conditional_4_Template, 1, 0, "span", 10);
@@ -2436,7 +2688,7 @@ export class SkipChatComponent extends BaseManagedComponent {
2436
2688
  i0.ɵɵelement(15, "div", 18);
2437
2689
  i0.ɵɵtemplate(16, SkipChatComponent_span_16_Template, 2, 2, "span", 19);
2438
2690
  i0.ɵɵelementEnd();
2439
- i0.ɵɵtemplate(17, SkipChatComponent_Conditional_17_Template, 9, 7, "div", 20);
2691
+ i0.ɵɵtemplate(17, SkipChatComponent_Conditional_17_Template, 10, 5, "div", 20);
2440
2692
  i0.ɵɵelementEnd();
2441
2693
  i0.ɵɵelementStart(18, "div", 21);
2442
2694
  i0.ɵɵtemplate(19, SkipChatComponent_skip_artifact_viewer_19_Template, 1, 3, "skip-artifact-viewer", 22);
@@ -2467,11 +2719,11 @@ export class SkipChatComponent extends BaseManagedComponent {
2467
2719
  i0.ɵɵproperty("ngIf", ctx.confirmDeleteConversationDialogOpen);
2468
2720
  i0.ɵɵadvance();
2469
2721
  i0.ɵɵproperty("ngIf", ctx.confirmMessageEditOrDeleteDialogOpen);
2470
- } }, dependencies: [i2.NgClass, i2.NgIf, i5.DefaultValueAccessor, i5.NgControlStatus, i5.MaxLengthValidator, i5.NgModel, i6.LoaderComponent, i4.DialogComponent, i4.DialogActionsComponent, i4.DialogContainerDirective, i7.FillContainer, i7.Container, i8.ItemTemplateDirective, i8.ListViewComponent, i9.ButtonComponent, i10.DataContextDialogComponent, i11.ResourcePermissionsComponent, i12.SkipSplitPanelComponent, i13.SkipArtifactViewerComponent], styles: [".layout[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row; \n\n height: 100%; \n\n width: 100%; \n\n position: relative;\n overflow: hidden; \n\n}\n\n.left-panel[_ngcontent-%COMP%] {\n width: 272px; \n\n background-color: #f8f9fa; \n\n border-right: 1px solid #ddd; \n\n overflow-y: auto; \n\n overflow-x: hidden; \n\n position: relative;\n\n scrollbar-width: thin; \n\n scrollbar-color: #d3d3d3 #f8f9fa; \n\n}\n\n\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px; \n\n background-color: #f8f9fa; \n\n}\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; \n\n border-radius: 4px; \n\n}\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; \n\n}\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: #f8f9fa; \n\n}\n\n.right-panel[_ngcontent-%COMP%] {\n flex: 1; \n\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%; \n\n overflow: hidden; \n\n}\n\n.conversation-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 16px;\n background-color: #f5f7f9;\n border-bottom: 1px solid #dde4ee;\n height: 40px;\n flex-shrink: 0;\n}\n\n.conversation-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 500;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 70%;\n}\n\n.artifact-counter-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n}\n\n\n.new-convo-icon[_ngcontent-%COMP%] {\n color: #808080; \n\n font-size: 18px; \n\n cursor: pointer; \n\n z-index: 10; \n\n padding: 5px;\n border-radius: 4px;\n}\n\n.toggle-icon[_ngcontent-%COMP%] {\n color: #808080; \n\n font-size: 18px; \n\n cursor: pointer; \n\n z-index: 10; \n\n margin-left: 6px;\n padding: 3px;\n border-radius: 3px;\n}\n \n\n.right-panel[_ngcontent-%COMP%] .toggle-icon[_ngcontent-%COMP%] {\n margin-left: 3px;\n margin-top: 2px;\n position: absolute;\n top: 10px;\n left: auto;\n right: 10px; \n\n}\n\n\n.chat-container[_ngcontent-%COMP%] {\n padding: 5px;\n display: flex;\n flex-direction: row;\n height: calc(100vh - 111px);\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n \n\n width: 100%;\n overflow: hidden; \n\n background-color: #f9f9f9;\n}\n\n.conversation-wrapper[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n position: relative; \n\n background-color: #f9f9f9;\n height: 100%; \n\n max-height: 100%; \n\n flex: 1;\n overflow: auto; \n\n}\n\n.new-conversation[_ngcontent-%COMP%] {\n height: 30px;\n font-size: large;\n}\n\n.conversation-history[_ngcontent-%COMP%] {\n width: 240px;\n min-width: 240px;\n height: 95%;\n overflow-y: auto; \n\n overflow-x: hidden; \n\n margin-right: 10px;\n padding-top: 5px;\n background-color: #f9f9f9;\n margin-top: 0px; \n padding: 12px; \n}\n\n.k-tabstrip-content-for-skip[_ngcontent-%COMP%] {\n padding: 0;\n padding-block: 0;\n}\n\n\n.conversation-history[_ngcontent-%COMP%] > button[_ngcontent-%COMP%] {\n height: 25px;\n}\n\n.skip-title[_ngcontent-%COMP%] {\n font-size: larger;\n margin-bottom: 5px;\n height: 20px;\n margin-top: 5px;\n}\n\n.conversation-list[_ngcontent-%COMP%] {\n margin-top: 5px;\n padding-top: 5px;\n \n border: 0;\n background-color: #f9f9f9;\n}\n\n\n\n\n\n.welcome-wrapper[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 5;\n}\n\n.welcome-message[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow: hidden;\n height: 100%;\n padding-bottom: 100px; \n\n}\n\n.embedded-conversations[_ngcontent-%COMP%] {\n margin-left: 3px;\n margin-top: 5px;\n font-size: 10pt;\n color: rgb(48, 48, 235);\n}\n.embedded-conversations[_ngcontent-%COMP%] > span[_ngcontent-%COMP%] {\n margin-top: 4px;\n margin-left: 5px;\n cursor: pointer;\n}\n.conversation-item-linked[_ngcontent-%COMP%] {\n color: rgb(48, 48, 235);\n}\n\n.welcome-message[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n width: 120px;\n height: 50px;\n margin-bottom: 20px; \n\n position: relative;\n z-index: 10;\n}\n\n.welcome-header-text[_ngcontent-%COMP%] {\n font-size: larger;\n font-weight: bold;\n}\n\n\n\n.welcome-suggested-questions[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-content: center;\n margin-top: 30px; \n\n}\n.welcome-suggested-questions-col[_ngcontent-%COMP%] {\n display: flex;\n margin-bottom: 10px; \n\n}\n\n\n\n.welcome-question[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column; \n\n align-items: left;;\n width: 300px; \n justify-content: space-between;\n margin: 5px; \n\n border: solid 1px rgba(41, 28, 28, 0.08);\n border-radius: 15px;\n padding: 10px;\n cursor: pointer;\n}\n\n.welcome-question[_ngcontent-%COMP%]:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n\n.welcome-question-header[_ngcontent-%COMP%] {\n font-size: 12pt;\n font-weight: bold;\n display: block; \n\n}\n\n\n\n.welcome-question[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:not(.welcome-question-header) {\n font-weight: normal;\n font-size: 10pt;\n}\n\n\n.messages[_ngcontent-%COMP%] {\n overflow-y: auto !important; \n\n overflow-x: hidden !important; \n\n \n\n margin-bottom: 5px;\n\n margin-top: 2px; \n\n\n background-color: #f9f9f9;\n flex: 1 1 auto; \n\n height: calc(100% - 50px); \n\n max-height: 100%; \n\n scrollbar-width: thin; \n\n scrollbar-color: #d3d3d3 #f8f9fa; \n\n position: relative; \n\n}\n\n\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px; \n\n background-color: #f8f9fa; \n\n}\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; \n\n border-radius: 4px; \n\n}\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; \n\n}\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: #f8f9fa; \n\n}\n\n\n\n.messages-container[_ngcontent-%COMP%] {\n min-height: 20px; \n\n}\n\n\n\n.new-chat-area[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between; \n\n align-items: center; \n\n}\n.avatar[_ngcontent-%COMP%] {\n max-height: 24px;\n margin-right: 10px;\n margin-left: 5px;\n margin-bottom: 3px;\n \n\n margin-right: auto; \n\n}\n\n.conversation-item[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-right: 5px;\n padding-top: 10px;\n padding-bottom: 10px;\n padding-left: 5px;\n padding-right: 5px;\n border-radius: 5px;\n cursor: pointer;\n overflow: hidden;\n max-height: 150px;\n font-size: 14px;\n\n display: flex;\n align-items: flex-start; \n\n\n flex-wrap: wrap; \n\n}\n\n.text-container[_ngcontent-%COMP%] {\n flex: 1; \n\n display: flex;\n flex-direction: column; \n\n}\n\n.text-container[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%] {\n resize: none; \n\n \n\n}\n\n.conversation-item[_ngcontent-%COMP%] > .conversation-icon[_ngcontent-%COMP%] {\n margin-top: 3px;\n}\n\n.conversation-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-block;\n white-space: pre-wrap; \n\n overflow: auto;\n word-wrap: break-word;\n margin-left: 3px; \n\n}\n\n.conversation-item[_ngcontent-%COMP%]:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n.conversation-item-selected[_ngcontent-%COMP%] {\n background-color: rgba(0, 0, 0, 0.15);\n}\n\n\n.conversation-item[_ngcontent-%COMP%] > .conversation-icon[_ngcontent-%COMP%] {\n margin-right: 11px;\n}\n.edit-conversation-panel[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end; \n\n margin-top: 2px; \n\n margin-right: 2px; \n\n}\n.edit-conversation-panel[_ngcontent-%COMP%] > .k-icon[_ngcontent-%COMP%] {\n margin-left: 5px;\n cursor: pointer;\n}\n.edit-conversation-panel[_ngcontent-%COMP%] > .k-icon[_ngcontent-%COMP%]:hover {\n color: #ff0000;\n}\n\n\n\n.input-area[_ngcontent-%COMP%] {\n min-height: 35px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 15px;\n position: sticky;\n bottom: 0;\n background-color: #f9f9f9;\n z-index: 10;\n}\n\n.input-area[_ngcontent-%COMP%] > .button-area[_ngcontent-%COMP%] {\n vertical-align: top;\n margin-top: 3px;\n margin-left: -65px;\n}\n\n\n.button-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%] {\n width: 30px;\n height: 30px;\n border-radius: 12px;\n margin-left: 3px;\n}\n\n\n\n.button-area[_ngcontent-%COMP%] > button.stop-button[_ngcontent-%COMP%] {\n background-color: #dc3545;\n color: white;\n}\n\n.button-area[_ngcontent-%COMP%] > button.stop-button[_ngcontent-%COMP%]:hover {\n background-color: #c82333;\n}\n\n\n\n\n\n\n\n\n\n\n\n.text-area-wrapper[_ngcontent-%COMP%] {\n padding: 3px;\n border: solid 1px rgba(0, 0, 0, 0.08) ;\n border-radius: 15px;\n\n margin-top: 4px;\n margin-right: -1px;\n min-height: 42px;\n max-height: 100%; \n\n\n overflow: hidden; \n align-items: center;\n\n \n\n width: 710px; \n padding-right: 90px\n} \n.text-area-wrapper[_ngcontent-%COMP%] > textarea[_ngcontent-%COMP%] {\n border: 0;\n outline: 0;\n resize: none;\n\n min-height: 20px; \n\n\n width: 100%;\n overflow-y: hidden; \n\n\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n\n margin-left: 7px;\n margin-top: 7px;\n margin-bottom: 5px;\n\n background-color: #f9f9f9;\n}\n\n\n\n\n\n\n.input-wrapper[_ngcontent-%COMP%] {\n flex-grow: 1; \n\n height: 100%;\n}\n\n.waiting-for-ai[_ngcontent-%COMP%] {\n position: absolute;\n display: flex; \n\n bottom: 100px;\n z-index: 999;\n left: 10px; \n}\n \n.scroll-to-bottom-icon[_ngcontent-%COMP%] {\n position: fixed; \n\n bottom: 120px; \n\n \n\n transform: translateX(-50%); \n\n z-index: 1000; \n\n background-color: white; \n\n color: black; \n\n border-radius: 50%; \n\n width: 40px; \n\n height: 40px; \n\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: 0px 0px 5px rgba(0,0,0,0.3); \n\n cursor: pointer;\n opacity: 0.9; \n\n}\n\n.loading-convo-messages-wrapper[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n position: absolute;\n z-index: 1000;\n}\n\n@media (min-width: 600px) {\n .welcome-suggested-questions[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap; \n\n align-content: flex-end; \n\n }\n}"] });
2722
+ } }, dependencies: [i2.NgClass, i2.NgIf, i5.DefaultValueAccessor, i5.NgControlStatus, i5.MaxLengthValidator, i5.NgModel, i6.LoaderComponent, i4.DialogComponent, i4.DialogActionsComponent, i4.DialogContainerDirective, i7.FillContainer, i7.Container, i8.ItemTemplateDirective, i8.ListViewComponent, i9.ButtonComponent, i10.DataContextDialogComponent, i11.ResourcePermissionsComponent, i12.SkipSplitPanelComponent, i13.SkipArtifactViewerComponent], styles: [".layout[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row; \n\n height: 100%; \n\n width: 100%; \n\n position: relative;\n overflow: hidden; \n\n}\n\n.left-panel[_ngcontent-%COMP%] {\n width: 272px; \n\n background-color: #f8f9fa; \n\n border-right: 1px solid #ddd; \n\n overflow-y: auto; \n\n overflow-x: hidden; \n\n position: relative;\n\n scrollbar-width: thin; \n\n scrollbar-color: #d3d3d3 #f8f9fa; \n\n}\n\n\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px; \n\n background-color: #f8f9fa; \n\n}\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; \n\n border-radius: 4px; \n\n}\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; \n\n}\n\n.left-panel[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: #f8f9fa; \n\n}\n\n.right-panel[_ngcontent-%COMP%] {\n flex: 1; \n\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%; \n\n overflow: hidden; \n\n}\n\n.conversation-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 16px;\n background-color: #f5f7f9;\n border-bottom: 1px solid #dde4ee;\n height: 40px;\n flex-shrink: 0;\n}\n\n.conversation-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 500;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 70%;\n}\n\n.artifact-counter-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n}\n\n\n.new-convo-icon[_ngcontent-%COMP%] {\n color: #808080; \n\n font-size: 18px; \n\n cursor: pointer; \n\n z-index: 10; \n\n padding: 5px;\n border-radius: 4px;\n}\n\n.toggle-icon[_ngcontent-%COMP%] {\n color: #808080; \n\n font-size: 18px; \n\n cursor: pointer; \n\n z-index: 10; \n\n margin-left: 6px;\n padding: 3px;\n border-radius: 3px;\n}\n \n\n.right-panel[_ngcontent-%COMP%] .toggle-icon[_ngcontent-%COMP%] {\n margin-left: 3px;\n margin-top: 2px;\n position: absolute;\n top: 10px;\n left: auto;\n right: 10px; \n\n}\n\n\n.chat-container[_ngcontent-%COMP%] {\n padding: 5px;\n display: flex;\n flex-direction: row;\n height: calc(100vh - 111px);\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n \n\n width: 100%;\n overflow: hidden; \n\n background-color: #f9f9f9;\n}\n\n.conversation-wrapper[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n position: relative; \n\n background-color: #f9f9f9;\n height: 100%; \n\n max-height: 100%; \n\n flex: 1;\n overflow: auto; \n\n}\n\n.new-conversation[_ngcontent-%COMP%] {\n height: 30px;\n font-size: large;\n}\n\n.conversation-history[_ngcontent-%COMP%] {\n width: 240px;\n min-width: 240px;\n height: 95%;\n overflow-y: auto; \n\n overflow-x: hidden; \n\n margin-right: 10px;\n padding-top: 5px;\n background-color: #f9f9f9;\n margin-top: 0px; \n padding: 12px; \n}\n\n.k-tabstrip-content-for-skip[_ngcontent-%COMP%] {\n padding: 0;\n padding-block: 0;\n}\n\n\n.conversation-history[_ngcontent-%COMP%] > button[_ngcontent-%COMP%] {\n height: 25px;\n}\n\n.skip-title[_ngcontent-%COMP%] {\n font-size: larger;\n margin-bottom: 5px;\n height: 20px;\n margin-top: 5px;\n}\n\n.conversation-list[_ngcontent-%COMP%] {\n margin-top: 5px;\n padding-top: 5px;\n \n border: 0;\n background-color: #f9f9f9;\n}\n\n\n\n\n\n.welcome-wrapper[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 5;\n}\n\n.welcome-message[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow: hidden;\n height: 100%;\n padding-bottom: 100px; \n\n}\n\n.embedded-conversations[_ngcontent-%COMP%] {\n margin-left: 3px;\n margin-top: 5px;\n font-size: 10pt;\n color: rgb(48, 48, 235);\n}\n.embedded-conversations[_ngcontent-%COMP%] > span[_ngcontent-%COMP%] {\n margin-top: 4px;\n margin-left: 5px;\n cursor: pointer;\n}\n.conversation-item-linked[_ngcontent-%COMP%] {\n color: rgb(48, 48, 235);\n}\n\n.welcome-message[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n width: 120px;\n height: 50px;\n margin-bottom: 20px; \n\n position: relative;\n z-index: 10;\n}\n\n.welcome-header-text[_ngcontent-%COMP%] {\n font-size: larger;\n font-weight: bold;\n}\n\n\n\n.welcome-suggested-questions[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-content: center;\n margin-top: 30px; \n\n}\n.welcome-suggested-questions-col[_ngcontent-%COMP%] {\n display: flex;\n margin-bottom: 10px; \n\n}\n\n\n\n.welcome-question[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column; \n\n align-items: left;;\n width: 300px; \n justify-content: space-between;\n margin: 5px; \n\n border: solid 1px rgba(41, 28, 28, 0.08);\n border-radius: 15px;\n padding: 10px;\n cursor: pointer;\n}\n\n.welcome-question[_ngcontent-%COMP%]:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n\n.welcome-question-header[_ngcontent-%COMP%] {\n font-size: 12pt;\n font-weight: bold;\n display: block; \n\n}\n\n\n\n.welcome-question[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:not(.welcome-question-header) {\n font-weight: normal;\n font-size: 10pt;\n}\n\n\n.messages[_ngcontent-%COMP%] {\n overflow-y: auto !important; \n\n overflow-x: hidden !important; \n\n \n\n margin-bottom: 5px;\n\n margin-top: 2px; \n\n\n background-color: #f9f9f9;\n flex: 1 1 auto; \n\n height: calc(100% - 50px); \n\n max-height: 100%; \n\n scrollbar-width: thin; \n\n scrollbar-color: #d3d3d3 #f8f9fa; \n\n position: relative; \n\n}\n\n\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px; \n\n background-color: #f8f9fa; \n\n}\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; \n\n border-radius: 4px; \n\n}\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; \n\n}\n\n.messages[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: #f8f9fa; \n\n}\n\n\n\n.messages-container[_ngcontent-%COMP%] {\n min-height: 20px; \n\n}\n\n\n\n.new-chat-area[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between; \n\n align-items: center; \n\n}\n.avatar[_ngcontent-%COMP%] {\n max-height: 24px;\n margin-right: 10px;\n margin-left: 5px;\n margin-bottom: 3px;\n \n\n margin-right: auto; \n\n}\n\n.conversation-item[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-right: 5px;\n padding-top: 10px;\n padding-bottom: 10px;\n padding-left: 5px;\n padding-right: 5px;\n border-radius: 5px;\n cursor: pointer;\n overflow: hidden;\n max-height: 150px;\n font-size: 14px;\n\n display: flex;\n align-items: flex-start; \n\n\n flex-wrap: wrap; \n\n}\n\n.text-container[_ngcontent-%COMP%] {\n flex: 1; \n\n display: flex;\n flex-direction: column; \n\n}\n\n.text-container[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%] {\n resize: none; \n\n \n\n}\n\n.conversation-item[_ngcontent-%COMP%] > .conversation-icon[_ngcontent-%COMP%] {\n margin-top: 3px;\n}\n\n.conversation-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-block;\n white-space: pre-wrap; \n\n overflow: auto;\n word-wrap: break-word;\n margin-left: 3px; \n\n}\n\n.conversation-item[_ngcontent-%COMP%]:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n.conversation-item-selected[_ngcontent-%COMP%] {\n background-color: rgba(0, 0, 0, 0.15);\n}\n\n\n.conversation-item[_ngcontent-%COMP%] > .conversation-icon[_ngcontent-%COMP%] {\n margin-right: 11px;\n}\n.edit-conversation-panel[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end; \n\n margin-top: 2px; \n\n margin-right: 2px; \n\n}\n.edit-conversation-panel[_ngcontent-%COMP%] > .k-icon[_ngcontent-%COMP%] {\n margin-left: 5px;\n cursor: pointer;\n}\n.edit-conversation-panel[_ngcontent-%COMP%] > .k-icon[_ngcontent-%COMP%]:hover {\n color: #ff0000;\n}\n\n\n\n.input-area[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 15px;\n padding: 10px 20px;\n position: sticky;\n bottom: 0;\n background-color: #f9f9f9;\n z-index: 10;\n}\n\n.input-container[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 800px;\n}\n\n.button-area[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n\n.button-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n min-width: 28px;\n background-color: transparent;\n border: 1px solid transparent;\n}\n\n.button-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.button-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.button-area[_ngcontent-%COMP%] > button.stop-button[_ngcontent-%COMP%] {\n background-color: #dc3545;\n color: white;\n border-color: #dc3545;\n}\n\n.button-area[_ngcontent-%COMP%] > button.stop-button[_ngcontent-%COMP%]:hover {\n background-color: #c82333;\n border-color: #c82333;\n}\n\n.text-area-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n padding: 10px 12px;\n padding-right: 120px; \n\n border: solid 1px rgba(0, 0, 0, 0.08);\n border-radius: 15px;\n min-height: 44px;\n max-height: 200px;\n overflow-y: auto;\n background-color: white;\n align-items: flex-end;\n} \n.text-area-wrapper[_ngcontent-%COMP%] > textarea[_ngcontent-%COMP%] {\n border: 0;\n outline: 0;\n resize: none;\n width: 100%;\n min-height: 24px;\n max-height: 180px;\n overflow-y: auto;\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n line-height: 1.5;\n background-color: transparent;\n padding: 0;\n margin: 0;\n}\n\n\n\n\n\n\n.input-wrapper[_ngcontent-%COMP%] {\n flex-grow: 1; \n\n height: 100%;\n}\n\n.waiting-for-ai[_ngcontent-%COMP%] {\n position: absolute;\n display: flex; \n\n bottom: 100px;\n z-index: 999;\n left: 10px; \n}\n \n.scroll-to-bottom-icon[_ngcontent-%COMP%] {\n position: fixed; \n\n bottom: 120px; \n\n \n\n transform: translateX(-50%); \n\n z-index: 1000; \n\n background-color: white; \n\n color: black; \n\n border-radius: 50%; \n\n width: 40px; \n\n height: 40px; \n\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: 0px 0px 5px rgba(0,0,0,0.3); \n\n cursor: pointer;\n opacity: 0.9; \n\n}\n\n.loading-convo-messages-wrapper[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n position: absolute;\n z-index: 1000;\n}\n\n@media (min-width: 600px) {\n .welcome-suggested-questions[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap; \n\n align-content: flex-end; \n\n }\n}"] });
2471
2723
  }
2472
2724
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SkipChatComponent, [{
2473
2725
  type: Component,
2474
- args: [{ selector: 'skip-chat', template: "<div class=\"chat-container\" kendoDialogContainer #topLevelDiv>\n <div class=\"layout\">\n @if (IsConversationListVisible) {\n <div class=\"left-panel\">\n <div class=\"conversation-history\">\n <div class=\"new-chat-area\">\n <span class=\"fa-solid fa-table-columns toggle-icon\" (click)=\"DisplayConversationList(false)\"></span>\n @if (ShowSkipLogoInConversationList) {\n <img [src]=\"SkipLogoURL\" class=\"avatar\" />\n }\n @if (AllowNewConversations) {\n <span class=\"fa-solid fa-pen-to-square new-convo-icon\" (click)=\"CreateNewConversation()\"></span> \n }\n </div>\n <kendo-listview\n class=\"conversation-list\"\n [data]=\"Conversations\"\n [itemClass]=\"{ 'item-border': true }\" \n #conversationList\n >\n <ng-template kendoListViewItemTemplate let-dataItem=\"dataItem\">\n <div class=\"conversation-item\" \n [ngClass]=\"GetConversationItemClass(dataItem)\"\n [title]=\"dataItem.Name\" \n (click)=\"SelectConversation(dataItem)\"> \n <span *ngIf=\"SelectedConversation && IsSkipProcessing(dataItem)\" class=\"fa-regular fa-clock\"></span>\n <div class=\"text-container\">\n <span *ngIf=\"dataItem.ID !== SelectedConversation?.ID || !ConversationEditMode\">{{ dataItem.Name }}</span>\n <textarea *ngIf=\"dataItem.ID === SelectedConversation?.ID && ConversationEditMode\" [(ngModel)]=\"dataItem.Name\" maxlength=\"100\"></textarea>\n </div>\n <div *ngIf=\"SelectedConversation?.ID === dataItem.ID\" class=\"edit-conversation-panel\">\n <span *ngIf=\"!ConversationEditMode\" class=\"fa-solid fa-pen-to-square\" (click)=\"editConvo(dataItem)\"></span>\n <span *ngIf=\"!ConversationEditMode\" class=\"fa-regular fa-trash-can\" (click)=\"showDeleteConvoDialog(dataItem)\"></span>\n <span *ngIf=\"ConversationEditMode\" class=\"fa-solid fa-check\" (click)=\"saveConvoName(dataItem)\"></span>\n <span *ngIf=\"ConversationEditMode\" class=\"fa-solid fa-xmark\" (click)=\"cancelConvoEdit(dataItem)\"></span>\n </div>\n </div>\n </ng-template>\n </kendo-listview>\n <!-- COMMENTED OUT as we don't want to support embedded conversations in the UI for now\n <div class=\"embedded-conversations\"><input kendoCheckBox type=\"checkbox\" [(ngModel)]=\"IncludeLinkedConversationsInList\" (ngModelChange)=\"loadConversations()\"/> <span (click)=\"FlipEmbeddedConversationState()\">Show Linked Conversations</span></div> -->\n </div> \n </div>\n }\n @if (!IsConversationListVisible) {\n <span class=\"fa-solid fa-table-columns toggle-icon\" (click)=\"DisplayConversationList(true)\"></span>\n }\n\n <div class=\"right-panel\">\n <skip-split-panel \n #splitPanel\n [Mode]=\"EnableArtifactSplitView && selectedArtifact ? 'BothSides' : 'LeftOnly'\" \n [SplitRatio]=\"SplitRatio\" \n (SplitRatioChanged)=\"onSplitRatioChanged($event)\"\n [RightPanelHeaderContent]=\"artifactHeaderInfo\"\n [VersionList]=\"artifactVersionList\"\n [SelectedVersionId]=\"selectedArtifactVersionId\"\n (VersionSelected)=\"onArtifactVersionSelected($event)\"\n mjFillContainer [fillWidth]=\"false\" [fillHeight]=\"true\">\n \n <!-- Left Panel (Chat) -->\n <div left-panel class=\"conversation-wrapper\">\n <!-- Use this for reference only, but don't display - hidden via width:0, height:0 -->\n <div #AskSkipPanel style=\"width:0; height:0; overflow:hidden; position:absolute;\"></div>\n \n <div class=\"messages\" #scrollContainer (scroll)=\"checkScroll()\">\n <div class=\"welcome-wrapper\" *ngIf=\"(!Messages || Messages.length ===0) && _conversationLoadComplete\">\n <div class='welcome-message'>\n <img [src]=\"SkipLogoURL\" />\n <div class=\"welcome-header-text\">What can I help with today?</div>\n </div>\n <div class='welcome-suggested-questions'>\n <div class=\"welcome-suggested-questions-col\">\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[0].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[0].topLine}}</span>\n <span>{{WelcomeQuestions[0].bottomLine}}</span>\n </div>\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[1].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[1].topLine}}</span>\n <span>{{WelcomeQuestions[1].bottomLine}}</span>\n </div> \n </div>\n <div class=\"welcome-suggested-questions-col\">\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[2].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[2].topLine}}</span>\n <span>{{WelcomeQuestions[2].bottomLine}}</span>\n </div>\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[3].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[3].topLine}}</span>\n <span>{{WelcomeQuestions[3].bottomLine}}</span>\n </div> \n </div>\n </div> \n </div>\n @if (!_conversationLoadComplete) {\n <div class=\"loading-convo-messages-wrapper\">\n <kendo-loader></kendo-loader>\n </div>\n } \n <div class=\"messages-container\" mjContainer mjSkipResize=\"true\"><!--mjSkipResize results in everything below this level NOT being resized, performance optimization-->\n <!-- Dynamic messages will be injected here -->\n </div>\n <span class=\"scroll-to-bottom-icon\" \n *ngIf=\"_showScrollToBottomIcon && Messages && Messages.length > 0\" \n [style.left.px]=\"getScrollToBottomIconPosition()\"\n (click)=\"scrollToBottomAnimate()\">\n <i class=\"fas fa-arrow-down\"></i>\n </span>\n </div>\n @if (SelectedConversationCurrentUserPermissionLevel === 'Owner' || \n SelectedConversationCurrentUserPermissionLevel === 'Edit') {\n <div class=\"input-area\">\n <div class=\"text-area-wrapper\">\n <textarea\n #AskSkipInput \n [disabled]=\"SelectedConversation && IsSkipProcessing(SelectedConversation)\" \n (keyup.enter)=\"onEnter($event)\" \n (input)=\"onInputChange($event)\"\n type=\"text\" \n [placeholder]=\"_AskSkipTextboxPlaceholder\"></textarea>\n </div>\n <div class=\"button-area\" [style.marginLeft.px]=\"-35 * NumVisibleButtons\">\n @if (ShowDataContextButton) {\n <button kendoButton >\n <span class=\"fa-solid fa-gear\" \n (click)=\"showDataContextDialog()\"></span>\n </button> \n }\n @if (SelectedConversation && IsSkipProcessing(SelectedConversation)) {\n <button kendoButton \n class=\"stop-button\"\n (click)=\"stopProcessing()\">\n <span class=\"fas fa-solid fa-stop\"></span>\n </button>\n }\n @else {\n <button kendoButton \n [disabled]=\"IsTextAreaEmpty()\" \n (click)=\"sendSkipMessage()\">\n <span class=\"fas fa-solid fa-arrow-up\"></span>\n </button>\n }\n @if (ShowSharingButton && SelectedConversationCurrentUserPermissionLevel === 'Owner') {\n <button kendoButton class=\"share-button\">\n <span class=\"fa-solid fa-share\"\n (click)=\"showSharingDialog()\"></span>\n </button> \n }\n </div>\n </div>\n }\n </div>\n \n <!-- Right Panel (Artifact Viewer) -->\n <div right-panel>\n <skip-artifact-viewer\n *ngIf=\"selectedArtifact\"\n [ArtifactID]=\"selectedArtifact.artifactId\"\n [ArtifactVersionID]=\"selectedArtifact.artifactVersionId\"\n [DataContext]=\"DataContext\"\n (NavigateToMatchingReport)=\"NavigateToMatchingReport.emit($event)\"\n (NewReportCreated)=\"NewReportCreated.emit($event)\"\n (DrillDownEvent)=\"DrillDownEvent.emit($event)\"\n (ArtifactInfoChanged)=\"onArtifactInfoChanged($event)\">\n </skip-artifact-viewer>\n </div>\n </skip-split-panel>\n </div> \n </div> \n</div> \n\n@if(isDataContextDialogVisible) {\n <mj-data-context-dialog [dataContextId]=\"DataContextID\" (dialogClosed)=\"closeDataContextDialog()\" [Provider]=\"ProviderToUse\"></mj-data-context-dialog>\n}\n@if(isSharingDialogVisible && SelectedConversation && conversationResourceTypeID) {\n <kendo-dialog\n title=\"Share Conversation\"\n (close)=\"closeSharingDialog('no')\"\n [width]=\"650\"\n [height]=\"400\"\n >\n <mj-resource-permissions \n [Provider]=\"Provider\"\n [ResourceTypeID]=\"conversationResourceTypeID\"\n [ResourceRecordID]=\"SelectedConversation.ID\"\n [ExcludedRoleNames]=\"SharingExcludeRoleNames\"\n [ExcludedUserEmails]=\"SharingExcludeEmails\"\n #resourcePermissions\n >\n </mj-resource-permissions>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeSharingDialog('yes')\" themeColor=\"primary\">\n Save\n </button>\n <button kendoButton (click)=\"closeSharingDialog('no')\">\n Cancel\n </button>\n </kendo-dialog-actions>\n </kendo-dialog> \n}\n\n<kendo-dialog\n title=\"Please confirm\"\n *ngIf=\"confirmDeleteConversationDialogOpen\"\n (close)=\"closeDeleteConversation('no')\"\n [minWidth]=\"250\"\n [width]=\"450\"\n>\n <p style=\"margin: 30px; text-align: center;\">\n Would you like to delete {{SelectedConversation?.Name}}?\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeDeleteConversation('yes')\" themeColor=\"primary\">\n Yes\n </button>\n <button kendoButton (click)=\"closeDeleteConversation('no')\">\n No\n </button>\n </kendo-dialog-actions>\n</kendo-dialog> \n\n<kendo-dialog\n title=\"Please confirm\"\n *ngIf=\"confirmMessageEditOrDeleteDialogOpen\"\n (close)=\"closeMessageEditOrDeleteDialog('no')\"\n [minWidth]=\"250\"\n [width]=\"450\"\n>\n <p style=\"margin: 30px; text-align: center;\">\n Would you like to {{messageEditOrDeleteType}} this message? Doing so will result in any subsequent messages in the conversation being deleted.\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeMessageEditOrDeleteDialog('yes')\" themeColor=\"primary\">\n Yes\n </button>\n <button kendoButton (click)=\"closeMessageEditOrDeleteDialog('no')\">\n No\n </button>\n </kendo-dialog-actions>\n</kendo-dialog> ", styles: [".layout {\n display: flex;\n flex-direction: row; /* Ensures left and right panels are side by side */\n height: 100%; /* Fill the available height */\n width: 100%; /* Fill the available width */\n position: relative;\n overflow: hidden; /* Prevent content from expanding beyond container */\n}\n\n.left-panel {\n width: 272px; /* Fixed width for the conversation list */\n background-color: #f8f9fa; /* Optional: Background color */\n border-right: 1px solid #ddd; /* Optional: Add a divider */\n overflow-y: auto; /* Enable scrolling if content overflows */\n overflow-x: hidden; /* Hide horizontal scrollbar */\n position: relative;\n\n scrollbar-width: thin; /* For Firefox */\n scrollbar-color: #d3d3d3 #f8f9fa; /* Thumb color and track color */\n}\n\n/* For WebKit-based browsers (Chrome, Edge, Safari) */\n.left-panel::-webkit-scrollbar {\n width: 8px; /* Narrower scrollbar */\n background-color: #f8f9fa; /* Scrollbar track color */\n}\n\n.left-panel::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; /* Lighter gray scrollbar thumb */\n border-radius: 4px; /* Rounded corners for the thumb */\n}\n\n.left-panel::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; /* Slightly darker gray on hover */\n}\n\n.left-panel::-webkit-scrollbar-track {\n background-color: #f8f9fa; /* Background of the scrollbar track */\n}\n\n.right-panel {\n flex: 1; /* Take up the remaining space */\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%; /* Don't exceed parent container height */\n overflow: hidden; /* Hide overflow to prevent double scrollbars */\n}\n\n.conversation-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 16px;\n background-color: #f5f7f9;\n border-bottom: 1px solid #dde4ee;\n height: 40px;\n flex-shrink: 0;\n}\n\n.conversation-title {\n font-size: 15px;\n font-weight: 500;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 70%;\n}\n\n.artifact-counter-container {\n display: flex;\n align-items: center;\n}\n\n\n.new-convo-icon {\n color: #808080; /* Mid-gray */\n font-size: 18px; /* Adjust icon size */\n cursor: pointer; /* Make it clear the icon is clickable */\n z-index: 10; /* Ensure the icon is above other content */\n padding: 5px;\n border-radius: 4px;\n}\n\n.toggle-icon {\n color: #808080; /* Mid-gray */\n font-size: 18px; /* Adjust icon size */\n cursor: pointer; /* Make it clear the icon is clickable */\n z-index: 10; /* Ensure the icon is above other content */\n margin-left: 6px;\n padding: 3px;\n border-radius: 3px;\n}\n \n\n.right-panel .toggle-icon {\n margin-left: 3px;\n margin-top: 2px;\n position: absolute;\n top: 10px;\n left: auto;\n right: 10px; /* For the right panel toggle */\n}\n\n\n.chat-container {\n padding: 5px;\n display: flex;\n flex-direction: row;\n height: calc(100vh - 111px);\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n /*initial sizes*/\n width: 100%;\n overflow: hidden; /* Prevent container from growing beyond viewport */\n background-color: #f9f9f9;\n}\n\n.conversation-wrapper {\n display: flex;\n flex-direction: column;\n position: relative; /* This ensures child absolute elements position relative to this container */\n background-color: #f9f9f9;\n height: 100%; /* Ensure it takes full height */\n max-height: 100%; /* Don't exceed parent container height */\n flex: 1;\n overflow: auto; /* Allow content to scroll */\n}\n\n.new-conversation {\n height: 30px;\n font-size: large;\n}\n\n.conversation-history {\n width: 240px;\n min-width: 240px;\n height: 95%;\n overflow-y: auto; /* Add scroll if the content exceeds the height */\n overflow-x: hidden; /* Hide horizontal scrollbar */\n margin-right: 10px;\n padding-top: 5px;\n background-color: #f9f9f9;\n margin-top: 0px; \n padding: 12px; \n}\n\n.k-tabstrip-content-for-skip {\n padding: 0;\n padding-block: 0;\n}\n\n\n.conversation-history > button {\n height: 25px;\n}\n\n.skip-title {\n font-size: larger;\n margin-bottom: 5px;\n height: 20px;\n margin-top: 5px;\n}\n\n.conversation-list {\n margin-top: 5px;\n padding-top: 5px;\n \n border: 0;\n background-color: #f9f9f9;\n}\n\n\n\n/* Center the welcome message vertically and horizontally */\n.welcome-wrapper {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 5;\n}\n\n.welcome-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow: hidden;\n height: 100%;\n padding-bottom: 100px; /* Push the content up a bit */\n}\n\n.embedded-conversations {\n margin-left: 3px;\n margin-top: 5px;\n font-size: 10pt;\n color: rgb(48, 48, 235);\n}\n.embedded-conversations > span {\n margin-top: 4px;\n margin-left: 5px;\n cursor: pointer;\n}\n.conversation-item-linked {\n color: rgb(48, 48, 235);\n}\n\n.welcome-message img {\n width: 120px;\n height: 50px;\n margin-bottom: 20px; /* Adds some space between the image and the text below */\n position: relative;\n z-index: 10;\n}\n\n.welcome-header-text {\n font-size: larger;\n font-weight: bold;\n}\n\n/* Position the welcome-suggested-questions at the bottom of its container */\n.welcome-suggested-questions {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-content: center;\n margin-top: 30px; /* Push questions down for spacing */\n}\n.welcome-suggested-questions-col {\n display: flex;\n margin-bottom: 10px; /* Space between rows */\n}\n\n/* Flex layout for questions, two per row */\n.welcome-question {\n display: flex;\n flex-direction: column; /* Stack the header and text vertically */\n align-items: left;;\n width: 300px; \n justify-content: space-between;\n margin: 5px; /* Adds some space around each question */\n border: solid 1px rgba(41, 28, 28, 0.08);\n border-radius: 15px;\n padding: 10px;\n cursor: pointer;\n}\n\n.welcome-question:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n\n.welcome-question-header {\n font-size: 12pt;\n font-weight: bold;\n display: block; /* Ensures the header is on its own line */\n}\n\n/* Non-bold text for the content below the header */\n.welcome-question span:not(.welcome-question-header) {\n font-weight: normal;\n font-size: 10pt;\n}\n\n\n.messages {\n overflow-y: auto !important; /* enable scrolling if the content overflows */\n overflow-x: hidden !important; /* hide horizontal scrollbar */\n /* border: solid 1px rgba(0, 0, 0, 0.08); */\n margin-bottom: 5px;\n\n margin-top: 2px; /* align it with the top of converation history exactly*/\n\n background-color: #f9f9f9;\n flex: 1 1 auto; /* Take up available space but don't push parent beyond size */\n height: calc(100% - 50px); /* Ensure messages container has a height */\n max-height: 100%; /* Don't exceed parent height */\n scrollbar-width: thin; /* For Firefox */\n scrollbar-color: #d3d3d3 #f8f9fa; /* Thumb color and track color */\n position: relative; /* For proper positioning of scroll icon */\n}\n\n/* For WebKit-based browsers (Chrome, Edge, Safari) */\n.messages::-webkit-scrollbar {\n width: 8px; /* Narrower scrollbar */\n background-color: #f8f9fa; /* Scrollbar track color */\n}\n\n.messages::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; /* Lighter gray scrollbar thumb */\n border-radius: 4px; /* Rounded corners for the thumb */\n}\n\n.messages::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; /* Slightly darker gray on hover */\n}\n\n.messages::-webkit-scrollbar-track {\n background-color: #f8f9fa; /* Background of the scrollbar track */\n}\n\n/* Class for the messages container */\n.messages-container {\n min-height: 20px; /* Ensure container takes space even when empty */\n}\n\n\n\n.new-chat-area {\n display: flex;\n justify-content: space-between; /* Aligns children (img and button) to each end */\n align-items: center; /* Centers children vertically */\n}\n.avatar {\n max-height: 24px;\n margin-right: 10px;\n margin-left: 5px;\n margin-bottom: 3px;\n /* Ensure the image aligns to the left */\n margin-right: auto; /* Pushes everything else to the right */\n}\n\n.conversation-item {\n margin-left: 5px;\n margin-right: 5px;\n padding-top: 10px;\n padding-bottom: 10px;\n padding-left: 5px;\n padding-right: 5px;\n border-radius: 5px;\n cursor: pointer;\n overflow: hidden;\n max-height: 150px;\n font-size: 14px;\n\n display: flex;\n align-items: flex-start; /* Align items to the top */\n\n flex-wrap: wrap; /* Allow items to wrap to the next line */\n}\n\n.text-container {\n flex: 1; /* Take up remaining space */\n display: flex;\n flex-direction: column; /* Stack children vertically */\n}\n\n.text-container textarea {\n resize: none; /* Disable resizing */\n /* Add more styles for the textarea if needed */\n}\n\n.conversation-item > .conversation-icon {\n margin-top: 3px;\n}\n\n.conversation-item span {\n display: inline-block;\n white-space: pre-wrap; /* Allow text to wrap */\n overflow: auto;\n word-wrap: break-word;\n margin-left: 3px; /* Move the text to the right */\n}\n\n.conversation-item:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n.conversation-item-selected {\n background-color: rgba(0, 0, 0, 0.15);\n}\n\n\n.conversation-item > .conversation-icon {\n margin-right: 11px;\n}\n.edit-conversation-panel {\n display: flex;\n justify-content: flex-end; /* Align icons to the right */\n margin-top: 2px; /* litle buffer on top */\n margin-right: 2px; /* litle buffer to the right */\n}\n.edit-conversation-panel > .k-icon {\n margin-left: 5px;\n cursor: pointer;\n}\n.edit-conversation-panel > .k-icon:hover {\n color: #ff0000;\n}\n\n\n\n.input-area {\n min-height: 35px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 15px;\n position: sticky;\n bottom: 0;\n background-color: #f9f9f9;\n z-index: 10;\n}\n\n.input-area > .button-area {\n vertical-align: top;\n margin-top: 3px;\n margin-left: -65px;\n}\n/*all buttons in the button area within the input area*/\n.button-area > button {\n width: 30px;\n height: 30px;\n border-radius: 12px;\n margin-left: 3px;\n}\n\n/* Stop button styling */\n.button-area > button.stop-button {\n background-color: #dc3545;\n color: white;\n}\n\n.button-area > button.stop-button:hover {\n background-color: #c82333;\n}\n/* .input-area > button:first-of-type {\n margin-left: -40px;\n}\n.input-area > button:last-child {\n margin-left: -65px;\n}\n.input-area > .share-button {\n margin-left: 10px;\n} */\n\n.text-area-wrapper {\n padding: 3px;\n border: solid 1px rgba(0, 0, 0, 0.08) ;\n border-radius: 15px;\n\n margin-top: 4px;\n margin-right: -1px;\n min-height: 42px;\n max-height: 100%; /* Prevent it from growing beyond the container */\n\n overflow: hidden; \n align-items: center;\n\n /*combined width and padding is 800*/\n width: 710px; \n padding-right: 90px\n} \n.text-area-wrapper > textarea {\n border: 0;\n outline: 0;\n resize: none;\n\n min-height: 20px; /* Initial height */\n\n width: 100%;\n overflow-y: hidden; /* Hide scrollbar */\n\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n\n margin-left: 7px;\n margin-top: 7px;\n margin-bottom: 5px;\n\n background-color: #f9f9f9;\n}\n\n/* .text-area-wrapper > textarea:disabled {\n background-color: white;\n} */\n\n.input-wrapper {\n flex-grow: 1; /* This will make the input-wrapper take the remaining space */\n height: 100%;\n}\n\n.waiting-for-ai {\n position: absolute;\n display: flex; /* Use flexbox layout */\n bottom: 100px;\n z-index: 999;\n left: 10px; \n}\n \n.scroll-to-bottom-icon {\n position: fixed; /* Fixed positioning to float over content */\n bottom: 120px; /* Position relative to the viewport */\n /* left position will be set dynamically via inline style */\n transform: translateX(-50%); /* Shift it back by half its width to center it */\n z-index: 1000; /* Ensure it stays on top */\n background-color: white; /* Circle background color */\n color: black; /* Icon color */\n border-radius: 50%; /* Makes the background a circle */\n width: 40px; /* Circle size */\n height: 40px; /* Circle size */\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: 0px 0px 5px rgba(0,0,0,0.3); /* Subtle shadow for better visibility */\n cursor: pointer;\n opacity: 0.9; /* Slightly transparent */\n}\n\n.loading-convo-messages-wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n position: absolute;\n z-index: 1000;\n}\n\n@media (min-width: 600px) {\n .welcome-suggested-questions {\n display: flex;\n flex-wrap: wrap; /* Allows questions to wrap to the next line */\n align-content: flex-end; /* Aligns the content to the bottom */\n }\n}\n \n"] }]
2726
+ args: [{ selector: 'skip-chat', template: "<div class=\"chat-container\" kendoDialogContainer #topLevelDiv>\n <div class=\"layout\">\n @if (IsConversationListVisible) {\n <div class=\"left-panel\">\n <div class=\"conversation-history\">\n <div class=\"new-chat-area\">\n <span class=\"fa-solid fa-table-columns toggle-icon\" (click)=\"DisplayConversationList(false)\"></span>\n @if (ShowSkipLogoInConversationList) {\n <img [src]=\"SkipLogoURL\" class=\"avatar\" />\n }\n @if (AllowNewConversations) {\n <span class=\"fa-solid fa-pen-to-square new-convo-icon\" (click)=\"CreateNewConversation()\"></span> \n }\n </div>\n <kendo-listview\n class=\"conversation-list\"\n [data]=\"Conversations\"\n [itemClass]=\"{ 'item-border': true }\" \n #conversationList\n >\n <ng-template kendoListViewItemTemplate let-dataItem=\"dataItem\">\n <div class=\"conversation-item\" \n [ngClass]=\"GetConversationItemClass(dataItem)\"\n [title]=\"dataItem.Name\" \n (click)=\"SelectConversation(dataItem)\"> \n <span *ngIf=\"SelectedConversation && IsSkipProcessing(dataItem)\" class=\"fa-regular fa-clock\"></span>\n <div class=\"text-container\">\n <span *ngIf=\"dataItem.ID !== SelectedConversation?.ID || !ConversationEditMode\">{{ dataItem.Name }}</span>\n <textarea *ngIf=\"dataItem.ID === SelectedConversation?.ID && ConversationEditMode\" [(ngModel)]=\"dataItem.Name\" maxlength=\"100\"></textarea>\n </div>\n <div *ngIf=\"SelectedConversation?.ID === dataItem.ID\" class=\"edit-conversation-panel\">\n <span *ngIf=\"!ConversationEditMode\" class=\"fa-solid fa-pen-to-square\" (click)=\"editConvo(dataItem)\"></span>\n <span *ngIf=\"!ConversationEditMode\" class=\"fa-regular fa-trash-can\" (click)=\"showDeleteConvoDialog(dataItem)\"></span>\n <span *ngIf=\"ConversationEditMode\" class=\"fa-solid fa-check\" (click)=\"saveConvoName(dataItem)\"></span>\n <span *ngIf=\"ConversationEditMode\" class=\"fa-solid fa-xmark\" (click)=\"cancelConvoEdit(dataItem)\"></span>\n </div>\n </div>\n </ng-template>\n </kendo-listview>\n <!-- COMMENTED OUT as we don't want to support embedded conversations in the UI for now\n <div class=\"embedded-conversations\"><input kendoCheckBox type=\"checkbox\" [(ngModel)]=\"IncludeLinkedConversationsInList\" (ngModelChange)=\"loadConversations()\"/> <span (click)=\"FlipEmbeddedConversationState()\">Show Linked Conversations</span></div> -->\n </div> \n </div>\n }\n @if (!IsConversationListVisible) {\n <span class=\"fa-solid fa-table-columns toggle-icon\" (click)=\"DisplayConversationList(true)\"></span>\n }\n\n <div class=\"right-panel\">\n <skip-split-panel \n #splitPanel\n [Mode]=\"EnableArtifactSplitView && selectedArtifact ? 'BothSides' : 'LeftOnly'\" \n [SplitRatio]=\"SplitRatio\" \n (SplitRatioChanged)=\"onSplitRatioChanged($event)\"\n [RightPanelHeaderContent]=\"artifactHeaderInfo\"\n [VersionList]=\"artifactVersionList\"\n [SelectedVersionId]=\"selectedArtifactVersionId\"\n (VersionSelected)=\"onArtifactVersionSelected($event)\"\n mjFillContainer [fillWidth]=\"false\" [fillHeight]=\"true\">\n \n <!-- Left Panel (Chat) -->\n <div left-panel class=\"conversation-wrapper\">\n <!-- Use this for reference only, but don't display - hidden via width:0, height:0 -->\n <div #AskSkipPanel style=\"width:0; height:0; overflow:hidden; position:absolute;\"></div>\n \n <div class=\"messages\" #scrollContainer (scroll)=\"checkScroll()\">\n <div class=\"welcome-wrapper\" *ngIf=\"(!Messages || Messages.length ===0) && _conversationLoadComplete\">\n <div class='welcome-message'>\n <img [src]=\"SkipLogoURL\" />\n <div class=\"welcome-header-text\">What can I help with today?</div>\n </div>\n <div class='welcome-suggested-questions'>\n <div class=\"welcome-suggested-questions-col\">\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[0].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[0].topLine}}</span>\n <span>{{WelcomeQuestions[0].bottomLine}}</span>\n </div>\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[1].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[1].topLine}}</span>\n <span>{{WelcomeQuestions[1].bottomLine}}</span>\n </div> \n </div>\n <div class=\"welcome-suggested-questions-col\">\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[2].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[2].topLine}}</span>\n <span>{{WelcomeQuestions[2].bottomLine}}</span>\n </div>\n <div class=\"welcome-question\" (click)=\"sendPrompt(WelcomeQuestions[3].prompt)\">\n <span class=\"welcome-question-header\">{{WelcomeQuestions[3].topLine}}</span>\n <span>{{WelcomeQuestions[3].bottomLine}}</span>\n </div> \n </div>\n </div> \n </div>\n @if (!_conversationLoadComplete) {\n <div class=\"loading-convo-messages-wrapper\">\n <kendo-loader></kendo-loader>\n </div>\n } \n <div class=\"messages-container\" mjContainer mjSkipResize=\"true\"><!--mjSkipResize results in everything below this level NOT being resized, performance optimization-->\n <!-- Dynamic messages will be injected here -->\n </div>\n <span class=\"scroll-to-bottom-icon\" \n *ngIf=\"_showScrollToBottomIcon && Messages && Messages.length > 0\" \n [style.left.px]=\"getScrollToBottomIconPosition()\"\n (click)=\"scrollToBottomAnimate()\">\n <i class=\"fas fa-arrow-down\"></i>\n </span>\n </div>\n @if (SelectedConversationCurrentUserPermissionLevel === 'Owner' || \n SelectedConversationCurrentUserPermissionLevel === 'Edit') {\n <div class=\"input-area\">\n <div class=\"input-container\">\n <div class=\"text-area-wrapper\">\n <textarea\n #AskSkipInput \n [disabled]=\"SelectedConversation && IsSkipProcessing(SelectedConversation)\" \n (keyup.enter)=\"onEnter($event)\" \n (input)=\"onInputChange($event)\"\n type=\"text\" \n [placeholder]=\"_AskSkipTextboxPlaceholder\"></textarea>\n <div class=\"button-area\">\n @if (ShowDataContextButton) {\n <button kendoButton >\n <span class=\"fa-solid fa-gear\" \n (click)=\"showDataContextDialog()\"></span>\n </button> \n }\n @if (SelectedConversation && IsSkipProcessing(SelectedConversation)) {\n <button kendoButton \n class=\"stop-button\"\n (click)=\"stopProcessing()\">\n <span class=\"fas fa-solid fa-stop\"></span>\n </button>\n }\n @else {\n <button kendoButton \n [disabled]=\"IsTextAreaEmpty()\" \n (click)=\"sendSkipMessage()\">\n <span class=\"fas fa-solid fa-arrow-up\"></span>\n </button>\n }\n @if (ShowSharingButton && SelectedConversationCurrentUserPermissionLevel === 'Owner') {\n <button kendoButton class=\"share-button\">\n <span class=\"fa-solid fa-share\"\n (click)=\"showSharingDialog()\"></span>\n </button> \n }\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n \n <!-- Right Panel (Artifact Viewer) -->\n <div right-panel>\n <skip-artifact-viewer\n *ngIf=\"selectedArtifact\"\n [ArtifactID]=\"selectedArtifact.artifactId\"\n [ArtifactVersionID]=\"selectedArtifact.artifactVersionId\"\n [DataContext]=\"DataContext\"\n (NavigateToMatchingReport)=\"NavigateToMatchingReport.emit($event)\"\n (NewReportCreated)=\"NewReportCreated.emit($event)\"\n (DrillDownEvent)=\"DrillDownEvent.emit($event)\"\n (ArtifactInfoChanged)=\"onArtifactInfoChanged($event)\">\n </skip-artifact-viewer>\n </div>\n </skip-split-panel>\n </div> \n </div> \n</div> \n\n@if(isDataContextDialogVisible) {\n <mj-data-context-dialog [dataContextId]=\"DataContextID\" (dialogClosed)=\"closeDataContextDialog()\" [Provider]=\"ProviderToUse\"></mj-data-context-dialog>\n}\n@if(isSharingDialogVisible && SelectedConversation && conversationResourceTypeID) {\n <kendo-dialog\n title=\"Share Conversation\"\n (close)=\"closeSharingDialog('no')\"\n [width]=\"650\"\n [height]=\"400\"\n >\n <mj-resource-permissions \n [Provider]=\"Provider\"\n [ResourceTypeID]=\"conversationResourceTypeID\"\n [ResourceRecordID]=\"SelectedConversation.ID\"\n [ExcludedRoleNames]=\"SharingExcludeRoleNames\"\n [ExcludedUserEmails]=\"SharingExcludeEmails\"\n #resourcePermissions\n >\n </mj-resource-permissions>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeSharingDialog('yes')\" themeColor=\"primary\">\n Save\n </button>\n <button kendoButton (click)=\"closeSharingDialog('no')\">\n Cancel\n </button>\n </kendo-dialog-actions>\n </kendo-dialog> \n}\n\n<kendo-dialog\n title=\"Please confirm\"\n *ngIf=\"confirmDeleteConversationDialogOpen\"\n (close)=\"closeDeleteConversation('no')\"\n [minWidth]=\"250\"\n [width]=\"450\"\n>\n <p style=\"margin: 30px; text-align: center;\">\n Would you like to delete {{SelectedConversation?.Name}}?\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeDeleteConversation('yes')\" themeColor=\"primary\">\n Yes\n </button>\n <button kendoButton (click)=\"closeDeleteConversation('no')\">\n No\n </button>\n </kendo-dialog-actions>\n</kendo-dialog> \n\n<kendo-dialog\n title=\"Please confirm\"\n *ngIf=\"confirmMessageEditOrDeleteDialogOpen\"\n (close)=\"closeMessageEditOrDeleteDialog('no')\"\n [minWidth]=\"250\"\n [width]=\"450\"\n>\n <p style=\"margin: 30px; text-align: center;\">\n Would you like to {{messageEditOrDeleteType}} this message? Doing so will result in any subsequent messages in the conversation being deleted.\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeMessageEditOrDeleteDialog('yes')\" themeColor=\"primary\">\n Yes\n </button>\n <button kendoButton (click)=\"closeMessageEditOrDeleteDialog('no')\">\n No\n </button>\n </kendo-dialog-actions>\n</kendo-dialog> ", styles: [".layout {\n display: flex;\n flex-direction: row; /* Ensures left and right panels are side by side */\n height: 100%; /* Fill the available height */\n width: 100%; /* Fill the available width */\n position: relative;\n overflow: hidden; /* Prevent content from expanding beyond container */\n}\n\n.left-panel {\n width: 272px; /* Fixed width for the conversation list */\n background-color: #f8f9fa; /* Optional: Background color */\n border-right: 1px solid #ddd; /* Optional: Add a divider */\n overflow-y: auto; /* Enable scrolling if content overflows */\n overflow-x: hidden; /* Hide horizontal scrollbar */\n position: relative;\n\n scrollbar-width: thin; /* For Firefox */\n scrollbar-color: #d3d3d3 #f8f9fa; /* Thumb color and track color */\n}\n\n/* For WebKit-based browsers (Chrome, Edge, Safari) */\n.left-panel::-webkit-scrollbar {\n width: 8px; /* Narrower scrollbar */\n background-color: #f8f9fa; /* Scrollbar track color */\n}\n\n.left-panel::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; /* Lighter gray scrollbar thumb */\n border-radius: 4px; /* Rounded corners for the thumb */\n}\n\n.left-panel::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; /* Slightly darker gray on hover */\n}\n\n.left-panel::-webkit-scrollbar-track {\n background-color: #f8f9fa; /* Background of the scrollbar track */\n}\n\n.right-panel {\n flex: 1; /* Take up the remaining space */\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%; /* Don't exceed parent container height */\n overflow: hidden; /* Hide overflow to prevent double scrollbars */\n}\n\n.conversation-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 16px;\n background-color: #f5f7f9;\n border-bottom: 1px solid #dde4ee;\n height: 40px;\n flex-shrink: 0;\n}\n\n.conversation-title {\n font-size: 15px;\n font-weight: 500;\n color: #333;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 70%;\n}\n\n.artifact-counter-container {\n display: flex;\n align-items: center;\n}\n\n\n.new-convo-icon {\n color: #808080; /* Mid-gray */\n font-size: 18px; /* Adjust icon size */\n cursor: pointer; /* Make it clear the icon is clickable */\n z-index: 10; /* Ensure the icon is above other content */\n padding: 5px;\n border-radius: 4px;\n}\n\n.toggle-icon {\n color: #808080; /* Mid-gray */\n font-size: 18px; /* Adjust icon size */\n cursor: pointer; /* Make it clear the icon is clickable */\n z-index: 10; /* Ensure the icon is above other content */\n margin-left: 6px;\n padding: 3px;\n border-radius: 3px;\n}\n \n\n.right-panel .toggle-icon {\n margin-left: 3px;\n margin-top: 2px;\n position: absolute;\n top: 10px;\n left: auto;\n right: 10px; /* For the right panel toggle */\n}\n\n\n.chat-container {\n padding: 5px;\n display: flex;\n flex-direction: row;\n height: calc(100vh - 111px);\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n /*initial sizes*/\n width: 100%;\n overflow: hidden; /* Prevent container from growing beyond viewport */\n background-color: #f9f9f9;\n}\n\n.conversation-wrapper {\n display: flex;\n flex-direction: column;\n position: relative; /* This ensures child absolute elements position relative to this container */\n background-color: #f9f9f9;\n height: 100%; /* Ensure it takes full height */\n max-height: 100%; /* Don't exceed parent container height */\n flex: 1;\n overflow: auto; /* Allow content to scroll */\n}\n\n.new-conversation {\n height: 30px;\n font-size: large;\n}\n\n.conversation-history {\n width: 240px;\n min-width: 240px;\n height: 95%;\n overflow-y: auto; /* Add scroll if the content exceeds the height */\n overflow-x: hidden; /* Hide horizontal scrollbar */\n margin-right: 10px;\n padding-top: 5px;\n background-color: #f9f9f9;\n margin-top: 0px; \n padding: 12px; \n}\n\n.k-tabstrip-content-for-skip {\n padding: 0;\n padding-block: 0;\n}\n\n\n.conversation-history > button {\n height: 25px;\n}\n\n.skip-title {\n font-size: larger;\n margin-bottom: 5px;\n height: 20px;\n margin-top: 5px;\n}\n\n.conversation-list {\n margin-top: 5px;\n padding-top: 5px;\n \n border: 0;\n background-color: #f9f9f9;\n}\n\n\n\n/* Center the welcome message vertically and horizontally */\n.welcome-wrapper {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 5;\n}\n\n.welcome-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow: hidden;\n height: 100%;\n padding-bottom: 100px; /* Push the content up a bit */\n}\n\n.embedded-conversations {\n margin-left: 3px;\n margin-top: 5px;\n font-size: 10pt;\n color: rgb(48, 48, 235);\n}\n.embedded-conversations > span {\n margin-top: 4px;\n margin-left: 5px;\n cursor: pointer;\n}\n.conversation-item-linked {\n color: rgb(48, 48, 235);\n}\n\n.welcome-message img {\n width: 120px;\n height: 50px;\n margin-bottom: 20px; /* Adds some space between the image and the text below */\n position: relative;\n z-index: 10;\n}\n\n.welcome-header-text {\n font-size: larger;\n font-weight: bold;\n}\n\n/* Position the welcome-suggested-questions at the bottom of its container */\n.welcome-suggested-questions {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-content: center;\n margin-top: 30px; /* Push questions down for spacing */\n}\n.welcome-suggested-questions-col {\n display: flex;\n margin-bottom: 10px; /* Space between rows */\n}\n\n/* Flex layout for questions, two per row */\n.welcome-question {\n display: flex;\n flex-direction: column; /* Stack the header and text vertically */\n align-items: left;;\n width: 300px; \n justify-content: space-between;\n margin: 5px; /* Adds some space around each question */\n border: solid 1px rgba(41, 28, 28, 0.08);\n border-radius: 15px;\n padding: 10px;\n cursor: pointer;\n}\n\n.welcome-question:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n\n.welcome-question-header {\n font-size: 12pt;\n font-weight: bold;\n display: block; /* Ensures the header is on its own line */\n}\n\n/* Non-bold text for the content below the header */\n.welcome-question span:not(.welcome-question-header) {\n font-weight: normal;\n font-size: 10pt;\n}\n\n\n.messages {\n overflow-y: auto !important; /* enable scrolling if the content overflows */\n overflow-x: hidden !important; /* hide horizontal scrollbar */\n /* border: solid 1px rgba(0, 0, 0, 0.08); */\n margin-bottom: 5px;\n\n margin-top: 2px; /* align it with the top of converation history exactly*/\n\n background-color: #f9f9f9;\n flex: 1 1 auto; /* Take up available space but don't push parent beyond size */\n height: calc(100% - 50px); /* Ensure messages container has a height */\n max-height: 100%; /* Don't exceed parent height */\n scrollbar-width: thin; /* For Firefox */\n scrollbar-color: #d3d3d3 #f8f9fa; /* Thumb color and track color */\n position: relative; /* For proper positioning of scroll icon */\n}\n\n/* For WebKit-based browsers (Chrome, Edge, Safari) */\n.messages::-webkit-scrollbar {\n width: 8px; /* Narrower scrollbar */\n background-color: #f8f9fa; /* Scrollbar track color */\n}\n\n.messages::-webkit-scrollbar-thumb {\n background-color: #d3d3d3; /* Lighter gray scrollbar thumb */\n border-radius: 4px; /* Rounded corners for the thumb */\n}\n\n.messages::-webkit-scrollbar-thumb:hover {\n background-color: #c0c0c0; /* Slightly darker gray on hover */\n}\n\n.messages::-webkit-scrollbar-track {\n background-color: #f8f9fa; /* Background of the scrollbar track */\n}\n\n/* Class for the messages container */\n.messages-container {\n min-height: 20px; /* Ensure container takes space even when empty */\n}\n\n\n\n.new-chat-area {\n display: flex;\n justify-content: space-between; /* Aligns children (img and button) to each end */\n align-items: center; /* Centers children vertically */\n}\n.avatar {\n max-height: 24px;\n margin-right: 10px;\n margin-left: 5px;\n margin-bottom: 3px;\n /* Ensure the image aligns to the left */\n margin-right: auto; /* Pushes everything else to the right */\n}\n\n.conversation-item {\n margin-left: 5px;\n margin-right: 5px;\n padding-top: 10px;\n padding-bottom: 10px;\n padding-left: 5px;\n padding-right: 5px;\n border-radius: 5px;\n cursor: pointer;\n overflow: hidden;\n max-height: 150px;\n font-size: 14px;\n\n display: flex;\n align-items: flex-start; /* Align items to the top */\n\n flex-wrap: wrap; /* Allow items to wrap to the next line */\n}\n\n.text-container {\n flex: 1; /* Take up remaining space */\n display: flex;\n flex-direction: column; /* Stack children vertically */\n}\n\n.text-container textarea {\n resize: none; /* Disable resizing */\n /* Add more styles for the textarea if needed */\n}\n\n.conversation-item > .conversation-icon {\n margin-top: 3px;\n}\n\n.conversation-item span {\n display: inline-block;\n white-space: pre-wrap; /* Allow text to wrap */\n overflow: auto;\n word-wrap: break-word;\n margin-left: 3px; /* Move the text to the right */\n}\n\n.conversation-item:hover {\n background-color: rgba(0, 0, 0, 0.05);\n}\n.conversation-item-selected {\n background-color: rgba(0, 0, 0, 0.15);\n}\n\n\n.conversation-item > .conversation-icon {\n margin-right: 11px;\n}\n.edit-conversation-panel {\n display: flex;\n justify-content: flex-end; /* Align icons to the right */\n margin-top: 2px; /* litle buffer on top */\n margin-right: 2px; /* litle buffer to the right */\n}\n.edit-conversation-panel > .k-icon {\n margin-left: 5px;\n cursor: pointer;\n}\n.edit-conversation-panel > .k-icon:hover {\n color: #ff0000;\n}\n\n\n\n.input-area {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 15px;\n padding: 10px 20px;\n position: sticky;\n bottom: 0;\n background-color: #f9f9f9;\n z-index: 10;\n}\n\n.input-container {\n width: 100%;\n max-width: 800px;\n}\n\n.button-area {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n/* All buttons in the button area */\n.button-area > button {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n min-width: 28px;\n background-color: transparent;\n border: 1px solid transparent;\n}\n\n.button-area > button:hover:not(:disabled) {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.button-area > button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Stop button styling */\n.button-area > button.stop-button {\n background-color: #dc3545;\n color: white;\n border-color: #dc3545;\n}\n\n.button-area > button.stop-button:hover {\n background-color: #c82333;\n border-color: #c82333;\n}\n\n.text-area-wrapper {\n position: relative;\n display: flex;\n padding: 10px 12px;\n padding-right: 120px; /* Space for buttons */\n border: solid 1px rgba(0, 0, 0, 0.08);\n border-radius: 15px;\n min-height: 44px;\n max-height: 200px;\n overflow-y: auto;\n background-color: white;\n align-items: flex-end;\n} \n.text-area-wrapper > textarea {\n border: 0;\n outline: 0;\n resize: none;\n width: 100%;\n min-height: 24px;\n max-height: 180px;\n overflow-y: auto;\n font-family: S\u00F6hne, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Ubuntu, Cantarell, \"Noto Sans\", sans-serif, \"Helvetica Neue\", Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n line-height: 1.5;\n background-color: transparent;\n padding: 0;\n margin: 0;\n}\n\n/* .text-area-wrapper > textarea:disabled {\n background-color: white;\n} */\n\n.input-wrapper {\n flex-grow: 1; /* This will make the input-wrapper take the remaining space */\n height: 100%;\n}\n\n.waiting-for-ai {\n position: absolute;\n display: flex; /* Use flexbox layout */\n bottom: 100px;\n z-index: 999;\n left: 10px; \n}\n \n.scroll-to-bottom-icon {\n position: fixed; /* Fixed positioning to float over content */\n bottom: 120px; /* Position relative to the viewport */\n /* left position will be set dynamically via inline style */\n transform: translateX(-50%); /* Shift it back by half its width to center it */\n z-index: 1000; /* Ensure it stays on top */\n background-color: white; /* Circle background color */\n color: black; /* Icon color */\n border-radius: 50%; /* Makes the background a circle */\n width: 40px; /* Circle size */\n height: 40px; /* Circle size */\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: 0px 0px 5px rgba(0,0,0,0.3); /* Subtle shadow for better visibility */\n cursor: pointer;\n opacity: 0.9; /* Slightly transparent */\n}\n\n.loading-convo-messages-wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n position: absolute;\n z-index: 1000;\n}\n\n@media (min-width: 600px) {\n .welcome-suggested-questions {\n display: flex;\n flex-wrap: wrap; /* Allows questions to wrap to the next line */\n align-content: flex-end; /* Aligns the content to the bottom */\n }\n}\n \n"] }]
2475
2727
  }], () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.ActivatedRoute }, { type: i1.Router }, { type: i2.Location }, { type: i0.ChangeDetectorRef }, { type: i3.MJNotificationService }, { type: i4.DialogService }], { AllowSend: [{
2476
2728
  type: Input
2477
2729
  }], Messages: [{