@memberjunction/ng-skip-chat 2.13.3 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/drill-down-info.d.ts +14 -0
- package/dist/lib/drill-down-info.d.ts.map +1 -0
- package/dist/lib/drill-down-info.js +19 -0
- package/dist/lib/drill-down-info.js.map +1 -0
- package/dist/lib/dynamic-report/base-report.d.ts +67 -0
- package/dist/lib/dynamic-report/base-report.d.ts.map +1 -0
- package/dist/lib/dynamic-report/base-report.js +246 -0
- package/dist/lib/dynamic-report/base-report.js.map +1 -0
- package/dist/lib/dynamic-report/dynamic-chart.d.ts +32 -0
- package/dist/lib/dynamic-report/dynamic-chart.d.ts.map +1 -0
- package/dist/lib/dynamic-report/dynamic-chart.js +202 -0
- package/dist/lib/dynamic-report/dynamic-chart.js.map +1 -0
- package/dist/lib/dynamic-report/dynamic-grid.d.ts +36 -0
- package/dist/lib/dynamic-report/dynamic-grid.d.ts.map +1 -0
- package/dist/lib/dynamic-report/dynamic-grid.js +397 -0
- package/dist/lib/dynamic-report/dynamic-grid.js.map +1 -0
- package/dist/lib/dynamic-report/linear-report.d.ts +23 -0
- package/dist/lib/dynamic-report/linear-report.d.ts.map +1 -0
- package/dist/lib/dynamic-report/linear-report.js +174 -0
- package/dist/lib/dynamic-report/linear-report.js.map +1 -0
- package/dist/lib/dynamic-report/skip-dynamic-report-wrapper.d.ts +14 -0
- package/dist/lib/dynamic-report/skip-dynamic-report-wrapper.d.ts.map +1 -0
- package/dist/lib/dynamic-report/skip-dynamic-report-wrapper.js +50 -0
- package/dist/lib/dynamic-report/skip-dynamic-report-wrapper.js.map +1 -0
- package/dist/lib/module.d.ts +26 -9
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/module.js +110 -22
- package/dist/lib/module.js.map +1 -1
- package/dist/lib/skip-chat/skip-chat.component.d.ts +131 -0
- package/dist/lib/skip-chat/skip-chat.component.d.ts.map +1 -0
- package/dist/lib/skip-chat/skip-chat.component.js +1317 -0
- package/dist/lib/skip-chat/skip-chat.component.js.map +1 -0
- package/dist/lib/skip-single-message/skip-single-message.component.d.ts +49 -0
- package/dist/lib/skip-single-message/skip-single-message.component.d.ts.map +1 -0
- package/dist/lib/skip-single-message/skip-single-message.component.js +262 -0
- package/dist/lib/skip-single-message/skip-single-message.component.js.map +1 -0
- package/dist/public-api.d.ts +7 -4
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +7 -4
- package/dist/public-api.js.map +1 -1
- package/package.json +23 -4
- package/dist/lib/tab/tab.component.d.ts +0 -55
- package/dist/lib/tab/tab.component.d.ts.map +0 -1
- package/dist/lib/tab/tab.component.js +0 -138
- package/dist/lib/tab/tab.component.js.map +0 -1
- package/dist/lib/tab-body/tab-body.component.d.ts +0 -13
- package/dist/lib/tab-body/tab-body.component.d.ts.map +0 -1
- package/dist/lib/tab-body/tab-body.component.js +0 -38
- package/dist/lib/tab-body/tab-body.component.js.map +0 -1
- package/dist/lib/tab-strip/tab-strip.component.d.ts +0 -117
- package/dist/lib/tab-strip/tab-strip.component.d.ts.map +0 -1
- package/dist/lib/tab-strip/tab-strip.component.js +0 -404
- package/dist/lib/tab-strip/tab-strip.component.js.map +0 -1
- package/dist/lib/tab.base.d.ts +0 -4
- package/dist/lib/tab.base.d.ts.map +0 -1
- package/dist/lib/tab.base.js +0 -3
- package/dist/lib/tab.base.js.map +0 -1
|
@@ -0,0 +1,1317 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var SkipChatComponent_1;
|
|
17
|
+
import { Component, ViewChild, ViewContainerRef, Input, } from '@angular/core';
|
|
18
|
+
import { ActivationEnd } from '@angular/router';
|
|
19
|
+
import { LogError, Metadata, CompositeKey } from '@memberjunction/core';
|
|
20
|
+
import { Container } from '@memberjunction/ng-container-directives';
|
|
21
|
+
import { BaseNavigationComponent, SharedService } from '@memberjunction/ng-shared';
|
|
22
|
+
import { take, filter } from 'rxjs/operators';
|
|
23
|
+
import { SkipResponsePhase, } from '@memberjunction/skip-types';
|
|
24
|
+
import { DataContext } from '@memberjunction/data-context';
|
|
25
|
+
import { MJEventType, MJGlobal, RegisterClass } from '@memberjunction/global';
|
|
26
|
+
import { SkipSingleMessageComponent } from '../skip-single-message/skip-single-message.component';
|
|
27
|
+
import * as i0 from "@angular/core";
|
|
28
|
+
import * as i1 from "@memberjunction/ng-shared";
|
|
29
|
+
import * as i2 from "@angular/router";
|
|
30
|
+
import * as i3 from "@angular/common";
|
|
31
|
+
import * as i4 from "@progress/kendo-angular-layout";
|
|
32
|
+
import * as i5 from "@angular/forms";
|
|
33
|
+
import * as i6 from "@progress/kendo-angular-indicators";
|
|
34
|
+
import * as i7 from "@memberjunction/ng-container-directives";
|
|
35
|
+
import * as i8 from "@progress/kendo-angular-listview";
|
|
36
|
+
import * as i9 from "@progress/kendo-angular-buttons";
|
|
37
|
+
import * as i10 from "@memberjunction/ng-data-context";
|
|
38
|
+
const _c0 = ["AskSkipPanel"];
|
|
39
|
+
const _c1 = ["mjContainer"];
|
|
40
|
+
const _c2 = ["conversationList"];
|
|
41
|
+
const _c3 = ["AskSkipInput"];
|
|
42
|
+
const _c4 = ["scrollContainer"];
|
|
43
|
+
const _c5 = ["topLevelDiv"];
|
|
44
|
+
const _c6 = () => ({ "item-border": true });
|
|
45
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_button_3_Template(rf, ctx) { if (rf & 1) {
|
|
46
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
47
|
+
i0.ɵɵelementStart(0, "button", 28);
|
|
48
|
+
i0.ɵɵlistener("click", function SkipChatComponent_kendo_splitter_pane_3_div_1_button_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.CreateNewConversation()); });
|
|
49
|
+
i0.ɵɵtext(1, "+");
|
|
50
|
+
i0.ɵɵelementEnd();
|
|
51
|
+
} }
|
|
52
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_span_1_Template(rf, ctx) { if (rf & 1) {
|
|
53
|
+
i0.ɵɵelement(0, "span", 34);
|
|
54
|
+
} }
|
|
55
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_span_3_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelementStart(0, "span");
|
|
57
|
+
i0.ɵɵtext(1);
|
|
58
|
+
i0.ɵɵelementEnd();
|
|
59
|
+
} if (rf & 2) {
|
|
60
|
+
const dataItem_r6 = i0.ɵɵnextContext().dataItem;
|
|
61
|
+
i0.ɵɵadvance();
|
|
62
|
+
i0.ɵɵtextInterpolate(dataItem_r6.Name);
|
|
63
|
+
} }
|
|
64
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_textarea_4_Template(rf, ctx) { if (rf & 1) {
|
|
65
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
66
|
+
i0.ɵɵelementStart(0, "textarea", 35);
|
|
67
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_textarea_4_Template_textarea_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r7); const dataItem_r6 = i0.ɵɵnextContext().dataItem; i0.ɵɵtwoWayBindingSet(dataItem_r6.Name, $event) || (dataItem_r6.Name = $event); return i0.ɵɵresetView($event); });
|
|
68
|
+
i0.ɵɵelementEnd();
|
|
69
|
+
} if (rf & 2) {
|
|
70
|
+
const dataItem_r6 = i0.ɵɵnextContext().dataItem;
|
|
71
|
+
i0.ɵɵtwoWayProperty("ngModel", dataItem_r6.Name);
|
|
72
|
+
} }
|
|
73
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_1_Template(rf, ctx) { if (rf & 1) {
|
|
74
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
75
|
+
i0.ɵɵelementStart(0, "span", 41);
|
|
76
|
+
i0.ɵɵlistener("click", function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_1_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r8); const dataItem_r6 = i0.ɵɵnextContext(2).dataItem; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editConvo(dataItem_r6)); });
|
|
77
|
+
i0.ɵɵelementEnd();
|
|
78
|
+
} }
|
|
79
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_2_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
81
|
+
i0.ɵɵelementStart(0, "span", 42);
|
|
82
|
+
i0.ɵɵlistener("click", function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_2_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r9); const dataItem_r6 = i0.ɵɵnextContext(2).dataItem; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.deleteConvo(dataItem_r6)); });
|
|
83
|
+
i0.ɵɵelementEnd();
|
|
84
|
+
} }
|
|
85
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_3_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
87
|
+
i0.ɵɵelementStart(0, "span", 43);
|
|
88
|
+
i0.ɵɵlistener("click", function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_3_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r10); const dataItem_r6 = i0.ɵɵnextContext(2).dataItem; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.saveConvoName(dataItem_r6)); });
|
|
89
|
+
i0.ɵɵelementEnd();
|
|
90
|
+
} }
|
|
91
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_4_Template(rf, ctx) { if (rf & 1) {
|
|
92
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
93
|
+
i0.ɵɵelementStart(0, "span", 44);
|
|
94
|
+
i0.ɵɵlistener("click", function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_4_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r11); const dataItem_r6 = i0.ɵɵnextContext(2).dataItem; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.cancelConvoEdit(dataItem_r6)); });
|
|
95
|
+
i0.ɵɵelementEnd();
|
|
96
|
+
} }
|
|
97
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_Template(rf, ctx) { if (rf & 1) {
|
|
98
|
+
i0.ɵɵelementStart(0, "div", 36);
|
|
99
|
+
i0.ɵɵtemplate(1, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_1_Template, 1, 0, "span", 37)(2, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_2_Template, 1, 0, "span", 38)(3, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_3_Template, 1, 0, "span", 39)(4, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_span_4_Template, 1, 0, "span", 40);
|
|
100
|
+
i0.ɵɵelementEnd();
|
|
101
|
+
} if (rf & 2) {
|
|
102
|
+
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
103
|
+
i0.ɵɵadvance();
|
|
104
|
+
i0.ɵɵproperty("ngIf", !ctx_r2.ConversationEditMode);
|
|
105
|
+
i0.ɵɵadvance();
|
|
106
|
+
i0.ɵɵproperty("ngIf", !ctx_r2.ConversationEditMode);
|
|
107
|
+
i0.ɵɵadvance();
|
|
108
|
+
i0.ɵɵproperty("ngIf", ctx_r2.ConversationEditMode);
|
|
109
|
+
i0.ɵɵadvance();
|
|
110
|
+
i0.ɵɵproperty("ngIf", ctx_r2.ConversationEditMode);
|
|
111
|
+
} }
|
|
112
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_Template(rf, ctx) { if (rf & 1) {
|
|
113
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
114
|
+
i0.ɵɵelementStart(0, "div", 29);
|
|
115
|
+
i0.ɵɵlistener("click", function SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_Template_div_click_0_listener() { const dataItem_r6 = i0.ɵɵrestoreView(_r5).dataItem; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SelectConversation(dataItem_r6)); });
|
|
116
|
+
i0.ɵɵtemplate(1, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_span_1_Template, 1, 0, "span", 30);
|
|
117
|
+
i0.ɵɵelementStart(2, "div", 31);
|
|
118
|
+
i0.ɵɵtemplate(3, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_span_3_Template, 2, 1, "span", 19)(4, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_textarea_4_Template, 1, 1, "textarea", 32);
|
|
119
|
+
i0.ɵɵelementEnd();
|
|
120
|
+
i0.ɵɵtemplate(5, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_div_5_Template, 5, 4, "div", 33);
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
} if (rf & 2) {
|
|
123
|
+
const dataItem_r6 = ctx.dataItem;
|
|
124
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
125
|
+
i0.ɵɵproperty("ngClass", ctx_r2.GetConversationItemClass(dataItem_r6))("title", dataItem_r6.Name);
|
|
126
|
+
i0.ɵɵadvance();
|
|
127
|
+
i0.ɵɵproperty("ngIf", ctx_r2.SelectedConversation && ctx_r2.IsSkipProcessing(dataItem_r6));
|
|
128
|
+
i0.ɵɵadvance(2);
|
|
129
|
+
i0.ɵɵproperty("ngIf", dataItem_r6.ID !== (ctx_r2.SelectedConversation == null ? null : ctx_r2.SelectedConversation.ID) || !ctx_r2.ConversationEditMode);
|
|
130
|
+
i0.ɵɵadvance();
|
|
131
|
+
i0.ɵɵproperty("ngIf", dataItem_r6.ID === (ctx_r2.SelectedConversation == null ? null : ctx_r2.SelectedConversation.ID) && ctx_r2.ConversationEditMode);
|
|
132
|
+
i0.ɵɵadvance();
|
|
133
|
+
i0.ɵɵproperty("ngIf", (ctx_r2.SelectedConversation == null ? null : ctx_r2.SelectedConversation.ID) === dataItem_r6.ID);
|
|
134
|
+
} }
|
|
135
|
+
function SkipChatComponent_kendo_splitter_pane_3_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
136
|
+
i0.ɵɵelementStart(0, "div", 22)(1, "div", 23);
|
|
137
|
+
i0.ɵɵelement(2, "img", 24);
|
|
138
|
+
i0.ɵɵtemplate(3, SkipChatComponent_kendo_splitter_pane_3_div_1_button_3_Template, 2, 0, "button", 25);
|
|
139
|
+
i0.ɵɵelementEnd();
|
|
140
|
+
i0.ɵɵelementStart(4, "kendo-listview", 26, 3);
|
|
141
|
+
i0.ɵɵtemplate(6, SkipChatComponent_kendo_splitter_pane_3_div_1_ng_template_6_Template, 6, 6, "ng-template", 27);
|
|
142
|
+
i0.ɵɵelementEnd()();
|
|
143
|
+
} if (rf & 2) {
|
|
144
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
145
|
+
i0.ɵɵadvance(3);
|
|
146
|
+
i0.ɵɵproperty("ngIf", ctx_r2.AllowNewConversations);
|
|
147
|
+
i0.ɵɵadvance();
|
|
148
|
+
i0.ɵɵstyleProp("height", 280, "px");
|
|
149
|
+
i0.ɵɵproperty("data", ctx_r2.Conversations)("itemClass", i0.ɵɵpureFunction0(7, _c6))("fillWidth", false)("bottomMargin", 20);
|
|
150
|
+
} }
|
|
151
|
+
function SkipChatComponent_kendo_splitter_pane_3_Template(rf, ctx) { if (rf & 1) {
|
|
152
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
153
|
+
i0.ɵɵelementStart(0, "kendo-splitter-pane", 20);
|
|
154
|
+
i0.ɵɵlistener("collapsedChange", function SkipChatComponent_kendo_splitter_pane_3_Template_kendo_splitter_pane_collapsedChange_0_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.splitterCollapseStateChanged($event)); });
|
|
155
|
+
i0.ɵɵtemplate(1, SkipChatComponent_kendo_splitter_pane_3_div_1_Template, 7, 8, "div", 21);
|
|
156
|
+
i0.ɵɵelementEnd();
|
|
157
|
+
} if (rf & 2) {
|
|
158
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
159
|
+
i0.ɵɵproperty("collapsible", true)("scrollable", false)("resizable", false);
|
|
160
|
+
i0.ɵɵadvance();
|
|
161
|
+
i0.ɵɵproperty("ngIf", ctx_r2.ShowConversationList);
|
|
162
|
+
} }
|
|
163
|
+
function SkipChatComponent_div_9_Template(rf, ctx) { if (rf & 1) {
|
|
164
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
165
|
+
i0.ɵɵelement(1, "kendo-loader");
|
|
166
|
+
i0.ɵɵelementEnd();
|
|
167
|
+
} }
|
|
168
|
+
function SkipChatComponent_div_10_Template(rf, ctx) { if (rf & 1) {
|
|
169
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
170
|
+
i0.ɵɵelementStart(0, "div", 46)(1, "div", 47);
|
|
171
|
+
i0.ɵɵelement(2, "img", 48);
|
|
172
|
+
i0.ɵɵelementStart(3, "div", 49);
|
|
173
|
+
i0.ɵɵtext(4, "What can I help with today?");
|
|
174
|
+
i0.ɵɵelementEnd()();
|
|
175
|
+
i0.ɵɵelementStart(5, "div", 50)(6, "div", 51)(7, "div", 52);
|
|
176
|
+
i0.ɵɵlistener("click", function SkipChatComponent_div_10_Template_div_click_7_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.sendPrompt(ctx_r2.WelcomeQuestions[0].prompt)); });
|
|
177
|
+
i0.ɵɵelementStart(8, "span", 53);
|
|
178
|
+
i0.ɵɵtext(9);
|
|
179
|
+
i0.ɵɵelementEnd();
|
|
180
|
+
i0.ɵɵelementStart(10, "span");
|
|
181
|
+
i0.ɵɵtext(11);
|
|
182
|
+
i0.ɵɵelementEnd()();
|
|
183
|
+
i0.ɵɵelementStart(12, "div", 52);
|
|
184
|
+
i0.ɵɵlistener("click", function SkipChatComponent_div_10_Template_div_click_12_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.sendPrompt(ctx_r2.WelcomeQuestions[1].prompt)); });
|
|
185
|
+
i0.ɵɵelementStart(13, "span", 53);
|
|
186
|
+
i0.ɵɵtext(14);
|
|
187
|
+
i0.ɵɵelementEnd();
|
|
188
|
+
i0.ɵɵelementStart(15, "span");
|
|
189
|
+
i0.ɵɵtext(16);
|
|
190
|
+
i0.ɵɵelementEnd()()();
|
|
191
|
+
i0.ɵɵelementStart(17, "div", 51)(18, "div", 52);
|
|
192
|
+
i0.ɵɵlistener("click", function SkipChatComponent_div_10_Template_div_click_18_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.sendPrompt(ctx_r2.WelcomeQuestions[2].prompt)); });
|
|
193
|
+
i0.ɵɵelementStart(19, "span", 53);
|
|
194
|
+
i0.ɵɵtext(20);
|
|
195
|
+
i0.ɵɵelementEnd();
|
|
196
|
+
i0.ɵɵelementStart(21, "span");
|
|
197
|
+
i0.ɵɵtext(22);
|
|
198
|
+
i0.ɵɵelementEnd()();
|
|
199
|
+
i0.ɵɵelementStart(23, "div", 52);
|
|
200
|
+
i0.ɵɵlistener("click", function SkipChatComponent_div_10_Template_div_click_23_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.sendPrompt(ctx_r2.WelcomeQuestions[3].prompt)); });
|
|
201
|
+
i0.ɵɵelementStart(24, "span", 53);
|
|
202
|
+
i0.ɵɵtext(25);
|
|
203
|
+
i0.ɵɵelementEnd();
|
|
204
|
+
i0.ɵɵelementStart(26, "span");
|
|
205
|
+
i0.ɵɵtext(27);
|
|
206
|
+
i0.ɵɵelementEnd()()()()();
|
|
207
|
+
} if (rf & 2) {
|
|
208
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
209
|
+
i0.ɵɵadvance(9);
|
|
210
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[0].topLine);
|
|
211
|
+
i0.ɵɵadvance(2);
|
|
212
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[0].bottomLine);
|
|
213
|
+
i0.ɵɵadvance(3);
|
|
214
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[1].topLine);
|
|
215
|
+
i0.ɵɵadvance(2);
|
|
216
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[1].bottomLine);
|
|
217
|
+
i0.ɵɵadvance(4);
|
|
218
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[2].topLine);
|
|
219
|
+
i0.ɵɵadvance(2);
|
|
220
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[2].bottomLine);
|
|
221
|
+
i0.ɵɵadvance(3);
|
|
222
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[3].topLine);
|
|
223
|
+
i0.ɵɵadvance(2);
|
|
224
|
+
i0.ɵɵtextInterpolate(ctx_r2.WelcomeQuestions[3].bottomLine);
|
|
225
|
+
} }
|
|
226
|
+
function SkipChatComponent_span_12_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
228
|
+
i0.ɵɵelementStart(0, "span", 54);
|
|
229
|
+
i0.ɵɵlistener("click", function SkipChatComponent_span_12_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.scrollToBottomAnimate()); });
|
|
230
|
+
i0.ɵɵelement(1, "i", 55);
|
|
231
|
+
i0.ɵɵelementEnd();
|
|
232
|
+
} }
|
|
233
|
+
function SkipChatComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
234
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
235
|
+
i0.ɵɵelementStart(0, "button", 16)(1, "span", 56);
|
|
236
|
+
i0.ɵɵlistener("click", function SkipChatComponent_Conditional_17_Template_span_click_1_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showDataContext()); });
|
|
237
|
+
i0.ɵɵelementEnd()();
|
|
238
|
+
} }
|
|
239
|
+
function SkipChatComponent_div_20_Template(rf, ctx) { if (rf & 1) {
|
|
240
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
241
|
+
i0.ɵɵelementStart(0, "div")(1, "mj-data-context-dialog", 57);
|
|
242
|
+
i0.ɵɵlistener("dialogClosed", function SkipChatComponent_div_20_Template_mj_data_context_dialog_dialogClosed_1_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDataContextDialog()); });
|
|
243
|
+
i0.ɵɵelementEnd()();
|
|
244
|
+
} if (rf & 2) {
|
|
245
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
246
|
+
i0.ɵɵadvance();
|
|
247
|
+
i0.ɵɵproperty("dataContextId", ctx_r2.DataContextID);
|
|
248
|
+
} }
|
|
249
|
+
let SkipChatComponent = SkipChatComponent_1 = class SkipChatComponent extends BaseNavigationComponent {
|
|
250
|
+
constructor(el, sharedService, renderer, route, router, location, cdRef) {
|
|
251
|
+
super();
|
|
252
|
+
this.el = el;
|
|
253
|
+
this.sharedService = sharedService;
|
|
254
|
+
this.renderer = renderer;
|
|
255
|
+
this.route = route;
|
|
256
|
+
this.router = router;
|
|
257
|
+
this.location = location;
|
|
258
|
+
this.cdRef = cdRef;
|
|
259
|
+
this.AllowSend = true;
|
|
260
|
+
this.Messages = [];
|
|
261
|
+
this.Conversations = [];
|
|
262
|
+
this.ConversationEditMode = false;
|
|
263
|
+
this.ShowConversationList = true;
|
|
264
|
+
this.AllowNewConversations = true;
|
|
265
|
+
this.Title = 'Ask Skip';
|
|
266
|
+
this.DataContextID = '';
|
|
267
|
+
this.LinkedEntity = '';
|
|
268
|
+
this.LinkedEntityCompositeKey = new CompositeKey();
|
|
269
|
+
this.ShowDataContextButton = true;
|
|
270
|
+
this.IncludeLinkedConversationsInList = false;
|
|
271
|
+
/**
|
|
272
|
+
* If true, the component will update the browser URL when the conversation changes. If false, it will not update the URL. Default is true.
|
|
273
|
+
*/
|
|
274
|
+
this.UpdateAppRoute = true;
|
|
275
|
+
this._showScrollToBottomIcon = false;
|
|
276
|
+
this._messageInProgress = false;
|
|
277
|
+
this.refreshOnAttach = false;
|
|
278
|
+
this._conversationsInProgress = {};
|
|
279
|
+
this._conversationsToReload = {};
|
|
280
|
+
this._conversationLoadComplete = false;
|
|
281
|
+
/**
|
|
282
|
+
* The questions that will be displayed in the welcome screen.
|
|
283
|
+
*/
|
|
284
|
+
this.WelcomeQuestions = [
|
|
285
|
+
{
|
|
286
|
+
topLine: 'Create a report',
|
|
287
|
+
bottomLine: 'with any of your data in it, just ask',
|
|
288
|
+
prompt: "I'd like help creating a new report with data in my system. Can you help me get started?",
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
topLine: 'Learn more about',
|
|
292
|
+
bottomLine: 'specific records in the database',
|
|
293
|
+
prompt: 'I would like to dig deeper into my database and get you to analyze a specific record in the database, can you help me with that?',
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
topLine: 'Get business advice',
|
|
297
|
+
bottomLine: 'to improve operating results and more',
|
|
298
|
+
prompt: 'I need some advice on how to improve my business operations, can you help me analyze my data and then think about ways to improve my operating results?',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
topLine: 'Seek marketing help',
|
|
302
|
+
bottomLine: 'to segment your audience or build campaigns',
|
|
303
|
+
prompt: 'I need help with marketing, can you help me analyze my data and then think about ways to segment my audience and build campaigns to improve revenue and retention?',
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
this._loaded = false;
|
|
307
|
+
this._scrollToBottom = false;
|
|
308
|
+
this._oldConvoName = '';
|
|
309
|
+
this._usedStartMessages = [];
|
|
310
|
+
this._processingStatus = {};
|
|
311
|
+
this.isDataContextDialogVisible = false;
|
|
312
|
+
}
|
|
313
|
+
ngOnInit() {
|
|
314
|
+
this.SubscribeToNotifications();
|
|
315
|
+
}
|
|
316
|
+
static get SkipChatWindowsCurrentlyVisible() {
|
|
317
|
+
return SkipChatComponent_1.__skipChatWindowsCurrentlyVisible;
|
|
318
|
+
}
|
|
319
|
+
SubscribeToNotifications() {
|
|
320
|
+
try {
|
|
321
|
+
MJGlobal.Instance.GetEventListener().subscribe((event) => {
|
|
322
|
+
var _a, _b, _c;
|
|
323
|
+
if (event.event === MJEventType.ComponentEvent) {
|
|
324
|
+
if (!event.args) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const obj = event.args;
|
|
328
|
+
if (((_a = obj.type) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()) === 'askskip' && ((_b = obj.status) === null || _b === void 0 ? void 0 : _b.trim().toLowerCase()) === 'ok') {
|
|
329
|
+
if (obj.conversationID && this._conversationsInProgress[obj.conversationID]) {
|
|
330
|
+
if (obj.conversationID === ((_c = this.SelectedConversation) === null || _c === void 0 ? void 0 : _c.ID)) {
|
|
331
|
+
if (obj.message && obj.message.length > 0) {
|
|
332
|
+
// 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
|
|
333
|
+
this.SetSkipStatusMessage(obj.message, 0);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
catch (e) {
|
|
342
|
+
LogError(e);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
splitterCollapseStateChanged(e) {
|
|
346
|
+
this.sharedService.InvokeManualResize();
|
|
347
|
+
}
|
|
348
|
+
GetConversationItemClass(item) {
|
|
349
|
+
var _a;
|
|
350
|
+
let classInfo = '';
|
|
351
|
+
if (((_a = this.SelectedConversation) === null || _a === void 0 ? void 0 : _a.ID) === item.ID)
|
|
352
|
+
classInfo += 'conversation-item-selected';
|
|
353
|
+
if (item.LinkedEntityID && item.LinkedRecordID) {
|
|
354
|
+
// an embedded conversation
|
|
355
|
+
classInfo += ' conversation-item-linked';
|
|
356
|
+
}
|
|
357
|
+
return classInfo;
|
|
358
|
+
}
|
|
359
|
+
SetSkipStatusMessage(message, delay) {
|
|
360
|
+
if (delay && delay > 0) {
|
|
361
|
+
setTimeout(() => {
|
|
362
|
+
this.InnerSetSkipStatusMessage(message);
|
|
363
|
+
}, delay);
|
|
364
|
+
}
|
|
365
|
+
else
|
|
366
|
+
this.InnerSetSkipStatusMessage(message);
|
|
367
|
+
}
|
|
368
|
+
InnerSetSkipStatusMessage(message) {
|
|
369
|
+
if (message && message.length > 0) {
|
|
370
|
+
if (!this._temporaryMessage) {
|
|
371
|
+
this._temporaryMessage = { ID: -1, Message: message, Role: 'ai' }; // create a new object
|
|
372
|
+
this.AddMessageToCurrentConversation(this._temporaryMessage, true, false);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
this._temporaryMessage.Message = message;
|
|
376
|
+
// we need to send a refresh signal to the component linked to this detail record
|
|
377
|
+
const ref = this._temporaryMessage._componentRef;
|
|
378
|
+
if (ref) {
|
|
379
|
+
const obj = ref.instance;
|
|
380
|
+
if (obj && obj.RefreshMessage)
|
|
381
|
+
obj.RefreshMessage();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
if (this._temporaryMessage) {
|
|
387
|
+
// get rid of the temporary message
|
|
388
|
+
this.RemoveMessageFromCurrentConversation(this._temporaryMessage);
|
|
389
|
+
this._temporaryMessage = undefined;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
SetSelectedConversationUser() {
|
|
394
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
395
|
+
var _a;
|
|
396
|
+
if ((_a = this.SelectedConversation) === null || _a === void 0 ? void 0 : _a.UserID) {
|
|
397
|
+
const p = this.ProviderToUse;
|
|
398
|
+
if (p.CurrentUser.ID !== this.SelectedConversation.UserID) {
|
|
399
|
+
const result = yield this.RunViewToUse.RunView({
|
|
400
|
+
EntityName: 'Users',
|
|
401
|
+
ExtraFilter: `ID='${this.SelectedConversation.UserID}'`,
|
|
402
|
+
});
|
|
403
|
+
this.SelectedConversationUser = result && result.Success ? result.Results[0] : undefined;
|
|
404
|
+
}
|
|
405
|
+
else
|
|
406
|
+
this.SelectedConversationUser = p.CurrentUser; // current user is the one for this convo, just use that to avoid the extra query
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
get ProviderToUse() {
|
|
411
|
+
return this.Provider ? this.Provider : Metadata.Provider;
|
|
412
|
+
}
|
|
413
|
+
get RunViewToUse() {
|
|
414
|
+
return this.ProviderToUse;
|
|
415
|
+
}
|
|
416
|
+
get LinkedEntityID() {
|
|
417
|
+
if (this.LinkedEntity && this.LinkedEntity.length > 0) {
|
|
418
|
+
// lookup the entity id from the linkedentity provided to us as a property
|
|
419
|
+
const e = this.ProviderToUse.Entities.find((e) => e.Name === this.LinkedEntity);
|
|
420
|
+
if (e)
|
|
421
|
+
return e.ID;
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
ngOnDestroy() {
|
|
426
|
+
// Unsubscribe to prevent memory leaks
|
|
427
|
+
if (this.paramsSubscription) {
|
|
428
|
+
this.paramsSubscription.unsubscribe();
|
|
429
|
+
}
|
|
430
|
+
if (this._intersectionObserver) {
|
|
431
|
+
this._intersectionObserver.disconnect();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
updateParentTabPanelStyling() {
|
|
435
|
+
// this will update the ancestor above us that is a tabpanel to remove padding so we can control our own padding/margin and handle colors properly within the tab
|
|
436
|
+
// apply a class to our parent if it is a kendo tab, to get rid of padding so we can control our
|
|
437
|
+
// own padding/margin and handle colors properly within the tab
|
|
438
|
+
// Find the closest ancestor with the .k-tabstrip-content class
|
|
439
|
+
const ancestor = this.el.nativeElement.closest('.k-tabstrip-content');
|
|
440
|
+
if (ancestor) {
|
|
441
|
+
try {
|
|
442
|
+
// Modify the ancestor's style as needed
|
|
443
|
+
const htmlElement = ancestor;
|
|
444
|
+
htmlElement.style.padding = '0';
|
|
445
|
+
htmlElement.style.paddingBlock = '0';
|
|
446
|
+
htmlElement.style.overflow = 'hidden';
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
// ignore this, it's not a big deal
|
|
450
|
+
console.log(e);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
ngAfterViewInit() {
|
|
455
|
+
this.updateParentTabPanelStyling();
|
|
456
|
+
// create an intersection observer to see if we are visible
|
|
457
|
+
this._intersectionObserver = new IntersectionObserver((entries) => {
|
|
458
|
+
const [entry] = entries;
|
|
459
|
+
if (!entry.isIntersecting) {
|
|
460
|
+
// we are NOT visible, so decrement the count of visible instances, but only if we were ever visible, meaning sometimes we get this situation before we are ever shown
|
|
461
|
+
if (this._loaded) {
|
|
462
|
+
// don't go below 0
|
|
463
|
+
SkipChatComponent_1.__skipChatWindowsCurrentlyVisible = Math.max(0, SkipChatComponent_1.__skipChatWindowsCurrentlyVisible - 1);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
// we are now visible, increment the count of visible instances
|
|
468
|
+
SkipChatComponent_1.__skipChatWindowsCurrentlyVisible++;
|
|
469
|
+
if (!this._loaded) {
|
|
470
|
+
// we are now visible, for the first time, first fire off an InvokeManualResize to ensure the parent container is resized properly
|
|
471
|
+
this.sharedService.InvokeManualResize();
|
|
472
|
+
// first do stuff if we're on "global" skip chat mode...
|
|
473
|
+
if (this.ShowConversationList && !this.LinkedEntity && this.LinkedEntity.trim().length === 0 && !this.CompositeKeyIsPopulated()) {
|
|
474
|
+
// only subscribe to the route params if we don't have a linked entity and record id, meaning we're in the context of the top level Skip Chat UI, not embedded somewhere
|
|
475
|
+
this.paramsSubscription = this.route.params.subscribe((params) => {
|
|
476
|
+
if (!this._loaded) {
|
|
477
|
+
this._loaded = true; // do this once
|
|
478
|
+
const conversationId = params.conversationId;
|
|
479
|
+
if (conversationId) {
|
|
480
|
+
this.loadConversations(conversationId); // Load the conversation based on the conversationId
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
this.loadConversations();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
else if (this.LinkedEntity && this.CompositeKeyIsPopulated()) {
|
|
489
|
+
// now, do stuff if we are embedded in another component with a LinkedEntity/LinkedEntityRecordID
|
|
490
|
+
if (!this._loaded) {
|
|
491
|
+
this._loaded = true; // do this once
|
|
492
|
+
this.loadConversations(); // Load the conversation which will filter by the linked entity and record id
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
this.checkScroll();
|
|
496
|
+
}
|
|
497
|
+
// Only care about the first time we are visible, so unobserve here to save resources
|
|
498
|
+
//this._intersectionObserver!.unobserve(this.topLevelDiv.nativeElement);
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
// now fire up the observer on the top level div
|
|
502
|
+
this._intersectionObserver.observe(this.topLevelDiv.nativeElement);
|
|
503
|
+
}
|
|
504
|
+
ngAfterViewChecked() {
|
|
505
|
+
if (this._scrollToBottom) {
|
|
506
|
+
this._scrollToBottom = false;
|
|
507
|
+
// have a short delay to make sure view is fully rendered via event cycle going through its queue
|
|
508
|
+
// NOTE - we only do this setTimeout if we have a scroll to bottom request, otherwise we don't need to do this, and
|
|
509
|
+
// REMEMBER setTimeout() causes Angular to do a change detection cycle, so we don't want to do this unless we need to
|
|
510
|
+
setTimeout(() => {
|
|
511
|
+
this.scrollToBottom();
|
|
512
|
+
}, 200);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
FlipEmbeddedConversationState() {
|
|
516
|
+
this.IncludeLinkedConversationsInList = !this.IncludeLinkedConversationsInList;
|
|
517
|
+
this.loadConversations();
|
|
518
|
+
}
|
|
519
|
+
loadConversations() {
|
|
520
|
+
return __awaiter(this, arguments, void 0, function* (conversationIdToLoad = undefined) {
|
|
521
|
+
let cachedConversations = MJGlobal.Instance.ObjectCache.Find('Conversations');
|
|
522
|
+
if (!cachedConversations) {
|
|
523
|
+
// load up from the database as we don't have any cached conversations
|
|
524
|
+
const result = yield this.RunViewToUse.RunView({
|
|
525
|
+
EntityName: 'Conversations',
|
|
526
|
+
ExtraFilter: `UserID='${this.ProviderToUse.CurrentUser.ID}'`,
|
|
527
|
+
OrderBy: '__mj_CreatedAt DESC', // get in reverse order so we have latest on top
|
|
528
|
+
});
|
|
529
|
+
if (result && result.Success) {
|
|
530
|
+
// now, cache the conversations for future use
|
|
531
|
+
MJGlobal.Instance.ObjectCache.Add('Conversations', result.Results);
|
|
532
|
+
// also set the local variable so we can use it below
|
|
533
|
+
cachedConversations = result.Results;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (!cachedConversations) {
|
|
537
|
+
LogError('Error loading conversations from the database');
|
|
538
|
+
return; // we couldn't load the conversations, so just return
|
|
539
|
+
}
|
|
540
|
+
// now setup the array we use to bind to the UI
|
|
541
|
+
if (this.IncludeLinkedConversationsInList) {
|
|
542
|
+
this.Conversations = cachedConversations; // dont filter out linked conversations
|
|
543
|
+
}
|
|
544
|
+
else if (this.LinkedEntity && this.LinkedEntity.length > 0 && this.CompositeKeyIsPopulated()) {
|
|
545
|
+
this.Conversations = cachedConversations.filter((c) => c.LinkedEntity === this.LinkedEntity && c.LinkedRecordID === this.LinkedEntityCompositeKey.Values()); // ONLY include the linked conversations
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
this.Conversations = cachedConversations.filter((c) => !(c.LinkedEntity && c.LinkedEntity.length > 0 && c.LinkedRecordID && c.LinkedRecordID.length > 0)); // filter OUT linked conversations
|
|
549
|
+
}
|
|
550
|
+
if (this.Conversations.length === 0) {
|
|
551
|
+
// no conversations, so create a new one
|
|
552
|
+
this.CreateNewConversation();
|
|
553
|
+
this.sharedService.InvokeManualResize(1);
|
|
554
|
+
}
|
|
555
|
+
else if (conversationIdToLoad) {
|
|
556
|
+
// we have > 0 convos and we were asked to load a specific one
|
|
557
|
+
const convo = this.Conversations.find((c) => c.ID == conversationIdToLoad);
|
|
558
|
+
if (convo) {
|
|
559
|
+
this.SelectConversation(convo);
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
// we didn't find the conversation so just select the first one
|
|
563
|
+
this.SelectConversation(this.Conversations[0]);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
// select the first conversation since no param was provided and we have > 0 convos
|
|
568
|
+
this.SelectConversation(this.Conversations[0]);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
editConvo(conversation) {
|
|
573
|
+
this._oldConvoName = conversation.Name ? conversation.Name : '';
|
|
574
|
+
this.ConversationEditMode = true;
|
|
575
|
+
}
|
|
576
|
+
cancelConvoEdit(conversation) {
|
|
577
|
+
conversation.Name = this._oldConvoName;
|
|
578
|
+
this.ConversationEditMode = false;
|
|
579
|
+
}
|
|
580
|
+
saveConvoName(conversation) {
|
|
581
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
582
|
+
let newConvoObject;
|
|
583
|
+
if (conversation.Save !== undefined) {
|
|
584
|
+
newConvoObject = conversation;
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
const p = this.ProviderToUse;
|
|
588
|
+
newConvoObject = yield p.GetEntityObject('Conversations', p.CurrentUser);
|
|
589
|
+
yield newConvoObject.Load(conversation.ID);
|
|
590
|
+
// now replace conversation in the list with the new object
|
|
591
|
+
this.Conversations = this.Conversations.map((c) => (c.ID == conversation.ID ? newConvoObject : c));
|
|
592
|
+
}
|
|
593
|
+
newConvoObject.Name = conversation.Name;
|
|
594
|
+
if (yield newConvoObject.Save()) {
|
|
595
|
+
this.ConversationEditMode = false;
|
|
596
|
+
// we've already updated the bound UI element, but let's make sure to update the cache as well
|
|
597
|
+
const cachedConversations = MJGlobal.Instance.ObjectCache.Find('Conversations');
|
|
598
|
+
if (cachedConversations) {
|
|
599
|
+
// find the item in the cache
|
|
600
|
+
const idx = cachedConversations.findIndex((c) => c.ID === conversation.ID);
|
|
601
|
+
if (idx >= 0) {
|
|
602
|
+
// replace the item in the cache with the new one, we are pointing to the same object in the cache here since
|
|
603
|
+
// we are just updating an element within the array so don't need to tell the cache
|
|
604
|
+
cachedConversations[idx] = newConvoObject;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
else
|
|
609
|
+
this.sharedService.CreateSimpleNotification('Error saving conversation name', 'error', 5000);
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
deleteConvo(conversation) {
|
|
613
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
614
|
+
if (confirm('Are you sure you want to delete this conversation?')) {
|
|
615
|
+
// delete the conversation - we might need to load the entity if the current object isn't a "real object"
|
|
616
|
+
if (yield this.DeleteConversation(conversation.ID)) {
|
|
617
|
+
// get the index of the conversation
|
|
618
|
+
const idx = this.Conversations.findIndex((c) => c.ID === conversation.ID);
|
|
619
|
+
// remove the conversation from the list that is bound to the UI
|
|
620
|
+
this.Conversations = this.Conversations.filter((c) => c.ID != conversation.ID);
|
|
621
|
+
// also, remove the conversation from the cache
|
|
622
|
+
const cachedConversations = MJGlobal.Instance.ObjectCache.Find('Conversations');
|
|
623
|
+
if (cachedConversations) {
|
|
624
|
+
MJGlobal.Instance.ObjectCache.Replace('Conversations', cachedConversations.filter((c) => c.ID != conversation.ID));
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
MJGlobal.Instance.ObjectCache.Add('Conversations', this.Conversations);
|
|
628
|
+
}
|
|
629
|
+
if (this.Conversations.length > 0) {
|
|
630
|
+
const newIdx = idx > 0 ? idx - 1 : 0;
|
|
631
|
+
this.SelectConversation(this.Conversations[newIdx]);
|
|
632
|
+
}
|
|
633
|
+
else
|
|
634
|
+
this.Messages = [];
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
this.sharedService.CreateSimpleNotification('Error deleting conversation', 'error', 5000);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
CreateNewConversation() {
|
|
643
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
644
|
+
const p = this.ProviderToUse;
|
|
645
|
+
const convo = yield p.GetEntityObject('Conversations', p.CurrentUser);
|
|
646
|
+
convo.NewRecord();
|
|
647
|
+
convo.Name = 'New Chat'; // default value
|
|
648
|
+
convo.UserID = p.CurrentUser.ID;
|
|
649
|
+
convo.Type = 'skip';
|
|
650
|
+
convo.IsArchived = false;
|
|
651
|
+
const linkedEntityID = this.LinkedEntityID;
|
|
652
|
+
if (linkedEntityID && linkedEntityID.length > 0 && this.CompositeKeyIsPopulated()) {
|
|
653
|
+
convo.LinkedEntityID = linkedEntityID;
|
|
654
|
+
convo.LinkedRecordID = this.LinkedEntityCompositeKey.Values();
|
|
655
|
+
}
|
|
656
|
+
// next, create a new data context for this conversation
|
|
657
|
+
const dc = yield p.GetEntityObject('Data Contexts', p.CurrentUser);
|
|
658
|
+
dc.NewRecord();
|
|
659
|
+
dc.Name = 'Data Context for Skip Conversation';
|
|
660
|
+
dc.UserID = p.CurrentUser.ID;
|
|
661
|
+
if (yield dc.Save()) {
|
|
662
|
+
// now create a data context item for the linked record if we have one
|
|
663
|
+
if (this.LinkedEntityID && this.LinkedEntityID.length > 0 && this.CompositeKeyIsPopulated()) {
|
|
664
|
+
const dci = yield p.GetEntityObject('Data Context Items', p.CurrentUser);
|
|
665
|
+
dci.NewRecord();
|
|
666
|
+
dci.DataContextID = dc.ID;
|
|
667
|
+
if (this.LinkedEntity === 'User Views') {
|
|
668
|
+
dci.Type = 'view';
|
|
669
|
+
dci.ViewID = this.LinkedEntityCompositeKey.GetValueByIndex(0);
|
|
670
|
+
}
|
|
671
|
+
else if (this.LinkedEntity === 'Queries') {
|
|
672
|
+
dci.Type = 'query';
|
|
673
|
+
dci.QueryID = this.LinkedEntityCompositeKey.GetValueByIndex(0);
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
dci.Type = 'single_record';
|
|
677
|
+
dci.RecordID = this.LinkedEntityCompositeKey.Values();
|
|
678
|
+
dci.EntityID = this.LinkedEntityID;
|
|
679
|
+
}
|
|
680
|
+
let dciSaveResult = yield dci.Save();
|
|
681
|
+
if (!dciSaveResult) {
|
|
682
|
+
this.sharedService.CreateSimpleNotification('Error creating data context item', 'error', 5000);
|
|
683
|
+
LogError('Error creating data context item', undefined, dci.LatestResult);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
convo.DataContextID = dc.ID;
|
|
687
|
+
this.DataContextID = dc.ID;
|
|
688
|
+
const convoSaveResult = yield convo.Save();
|
|
689
|
+
if (!convoSaveResult) {
|
|
690
|
+
this.sharedService.CreateSimpleNotification('Error creating conversation', 'error', 5000);
|
|
691
|
+
LogError('Error creating conversation', undefined, convo.LatestResult);
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
this.DataContext = new DataContext();
|
|
695
|
+
yield this.DataContext.LoadMetadata(this.DataContextID, p.CurrentUser, p);
|
|
696
|
+
this.Conversations = [convo, ...this.Conversations]; // do this way instead of unshift to ensure that binding refreshes
|
|
697
|
+
// also update the cache
|
|
698
|
+
const cachedConversations = MJGlobal.Instance.ObjectCache.Find('Conversations');
|
|
699
|
+
if (cachedConversations) {
|
|
700
|
+
MJGlobal.Instance.ObjectCache.Replace('Conversations', [convo, ...cachedConversations]);
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
MJGlobal.Instance.ObjectCache.Add('Conversations', [convo, ...this.Conversations]);
|
|
704
|
+
}
|
|
705
|
+
yield this.SelectConversation(convo);
|
|
706
|
+
this._scrollToBottom = true; // this results in the angular after Viewchecked scrolling to bottom when it's done
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
this.sharedService.CreateSimpleNotification('Error creating data context', 'error', 5000);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
onEnter(event) {
|
|
714
|
+
this.sendSkipMessage();
|
|
715
|
+
}
|
|
716
|
+
SelectConversation(conversation) {
|
|
717
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
718
|
+
var _a;
|
|
719
|
+
if (conversation && conversation.ID !== ((_a = this.SelectedConversation) === null || _a === void 0 ? void 0 : _a.ID)) {
|
|
720
|
+
// load up the conversation if not already the one that's loaded
|
|
721
|
+
this._conversationLoadComplete = false;
|
|
722
|
+
this.ClearMessages();
|
|
723
|
+
const oldStatus = this._processingStatus[conversation.ID];
|
|
724
|
+
this._processingStatus[conversation.ID] = true;
|
|
725
|
+
this.SelectedConversation = conversation;
|
|
726
|
+
this.SetSelectedConversationUser();
|
|
727
|
+
this.DataContextID = conversation.DataContextID ? conversation.DataContextID : '';
|
|
728
|
+
const convoAny = conversation;
|
|
729
|
+
if (convoAny._DataContext) {
|
|
730
|
+
// we have cached data context, so just use it
|
|
731
|
+
this.DataContext = convoAny._DataContext;
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
this.DataContext = new DataContext();
|
|
735
|
+
yield this.DataContext.LoadMetadata(this.DataContextID, this.ProviderToUse.CurrentUser, this.ProviderToUse);
|
|
736
|
+
// cache it for later
|
|
737
|
+
convoAny._DataContext = this.DataContext;
|
|
738
|
+
}
|
|
739
|
+
const convoShouldReload = this._conversationsToReload[conversation.ID];
|
|
740
|
+
if (convoAny._Messages && !convoShouldReload) {
|
|
741
|
+
// we have cached messages, so just use them, but don't point directly to the array, create new array with the same objects
|
|
742
|
+
this.Messages = [...convoAny._Messages];
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
this._conversationsToReload[conversation.ID] = true;
|
|
746
|
+
const result = yield this.RunViewToUse.RunView({
|
|
747
|
+
EntityName: 'Conversation Details',
|
|
748
|
+
ExtraFilter: `ConversationID='${conversation.ID}'`,
|
|
749
|
+
OrderBy: '__mj_CreatedAt ASC', // show messages in order of creation
|
|
750
|
+
});
|
|
751
|
+
if (result && result.Success) {
|
|
752
|
+
// copy the results into NEW objects into the array, we don't want to modify the original objects
|
|
753
|
+
this.Messages = [...result.Results];
|
|
754
|
+
// also, cache the messages within the conversation, but create new array with the same objects
|
|
755
|
+
convoAny._Messages = [...this.Messages];
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
if (this.Messages && this.Messages.length > 0) {
|
|
759
|
+
//this.Messages = <ConversationDetailEntity[]>result.Results;
|
|
760
|
+
this.cdRef.detach(); // temporarily stop change detection to improve performance
|
|
761
|
+
for (const m of this.Messages) {
|
|
762
|
+
this.AddMessageToPanel(m, false);
|
|
763
|
+
}
|
|
764
|
+
this._scrollToBottom = true; // this results in the angular after Viewchecked scrolling to bottom when it's done
|
|
765
|
+
this.cdRef.reattach(); // resume change detection
|
|
766
|
+
}
|
|
767
|
+
this._processingStatus[conversation.ID] = oldStatus; // set back to old status as it might have been processing
|
|
768
|
+
this.sharedService.InvokeManualResize(500);
|
|
769
|
+
// ensure the list box has the conversation in view
|
|
770
|
+
this.scrollToConversation(conversation.ID);
|
|
771
|
+
this._conversationLoadComplete = true;
|
|
772
|
+
if (this.UpdateAppRoute) {
|
|
773
|
+
// finally update the browser URL since we've changed the conversation ID
|
|
774
|
+
this.location.go('/askskip/' + conversation.ID);
|
|
775
|
+
// this.router.navigate(['askskip', conversation.ID]);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
scrollToConversation(conversationId) {
|
|
781
|
+
if (this.conversationList) {
|
|
782
|
+
const convoElement = this.conversationList.element.nativeElement;
|
|
783
|
+
const itemIndex = this.Conversations.findIndex((c) => c.ID === conversationId);
|
|
784
|
+
// Find the item element within the container based on its index
|
|
785
|
+
const itemElement = Array.from(convoElement.querySelectorAll('[data-kendo-listview-item-index]')).find((el) => parseInt(el.getAttribute('data-kendo-listview-item-index'), 10) === itemIndex);
|
|
786
|
+
if (itemElement) {
|
|
787
|
+
setTimeout(() => {
|
|
788
|
+
// do this within a timeout to ensure rendering is completed
|
|
789
|
+
itemElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
|
|
790
|
+
}, 100);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
onInputChange(event) {
|
|
795
|
+
const val = this.askSkipInput.nativeElement.value;
|
|
796
|
+
this.AllowSend = val && val.length > 0;
|
|
797
|
+
this.resizeTextInput();
|
|
798
|
+
}
|
|
799
|
+
resizeTextInput() {
|
|
800
|
+
try {
|
|
801
|
+
const textarea = this.askSkipInput.nativeElement;
|
|
802
|
+
textarea.style.height = 'auto'; // Reset height to recalculate
|
|
803
|
+
textarea.style.height = `${textarea.scrollHeight}px`; // Set to scrollHeight
|
|
804
|
+
}
|
|
805
|
+
catch (e) {
|
|
806
|
+
LogError(e);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
pickSkipStartMessage() {
|
|
810
|
+
// goal here is to randomly select one of the above _startMessages, however we want to track for our instance of the class the ones we use so that we don't reuse any of them until we use them all
|
|
811
|
+
if (this._usedStartMessages.length === SkipChatComponent_1._startMessages.length) {
|
|
812
|
+
this._usedStartMessages = []; // reset the used messages
|
|
813
|
+
}
|
|
814
|
+
let idx = -1;
|
|
815
|
+
do {
|
|
816
|
+
idx = Math.floor(Math.random() * SkipChatComponent_1._startMessages.length);
|
|
817
|
+
} while (this._usedStartMessages.indexOf(SkipChatComponent_1._startMessages[idx]) >= 0);
|
|
818
|
+
this._usedStartMessages.push(SkipChatComponent_1._startMessages[idx]);
|
|
819
|
+
return SkipChatComponent_1._startMessages[idx];
|
|
820
|
+
}
|
|
821
|
+
sendPrompt(val) {
|
|
822
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
823
|
+
var _a, _b, _c;
|
|
824
|
+
const convoID = this.SelectedConversation ? this.SelectedConversation.ID : '';
|
|
825
|
+
if (this._conversationsInProgress[convoID]) {
|
|
826
|
+
// don't allow sending another message if we're in the midst of sending one
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (this.SelectedConversation) {
|
|
830
|
+
this._processingStatus[(_a = this.SelectedConversation) === null || _a === void 0 ? void 0 : _a.ID] = true;
|
|
831
|
+
}
|
|
832
|
+
if (val && val.length > 0) {
|
|
833
|
+
this._conversationsInProgress[convoID] = true;
|
|
834
|
+
this._messageInProgress = true;
|
|
835
|
+
this.AllowSend = false;
|
|
836
|
+
const p = this.ProviderToUse;
|
|
837
|
+
const convoDetail = yield p.GetEntityObject('Conversation Details', p.CurrentUser);
|
|
838
|
+
convoDetail.NewRecord();
|
|
839
|
+
convoDetail.Message = val;
|
|
840
|
+
convoDetail.Role = 'User';
|
|
841
|
+
// this is NOT saved here because it is saved on the server side. Later on in this code after the save we will update the object with the ID from the server, and below
|
|
842
|
+
this.AddMessageToCurrentConversation(convoDetail, true, true);
|
|
843
|
+
this.SetSkipStatusMessage(this.pickSkipStartMessage(), 850);
|
|
844
|
+
this.askSkipInput.nativeElement.value = '';
|
|
845
|
+
this.resizeTextInput();
|
|
846
|
+
this._scrollToBottom = true; // this results in the angular after Viewchecked scrolling to bottom when it's done
|
|
847
|
+
const graphQLRawResult = yield this.ExecuteAskSkipQuery(val, yield this.GetCreateDataContextID(), this.SelectedConversation);
|
|
848
|
+
const skipResult = graphQLRawResult === null || graphQLRawResult === void 0 ? void 0 : graphQLRawResult.ExecuteAskSkipAnalysisQuery;
|
|
849
|
+
// temporarily ask Angular to stop its change detection as many of the ops below are slow and async, we don't want flicker in the UI as stuff happens
|
|
850
|
+
this.cdRef.detach();
|
|
851
|
+
if (skipResult === null || skipResult === void 0 ? void 0 : skipResult.Success) {
|
|
852
|
+
if (convoID !== ((_b = this.SelectedConversation) === null || _b === void 0 ? void 0 : _b.ID)) {
|
|
853
|
+
// this scenario arises when we have a selected convo change after we submitted our request to skip
|
|
854
|
+
// so we do nothing here other than update the status.
|
|
855
|
+
this._processingStatus[convoID] = false;
|
|
856
|
+
//the next time the user selects this convo, we will fetch messages
|
|
857
|
+
//from the server rather than using the ones in cache
|
|
858
|
+
this._conversationsToReload[convoID] = true;
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
this._processingStatus[convoID] = false;
|
|
862
|
+
const innerResult = JSON.parse(skipResult.Result);
|
|
863
|
+
if (!this.SelectedConversation) {
|
|
864
|
+
const convo = yield p.GetEntityObject('Conversations', p.CurrentUser);
|
|
865
|
+
yield convo.Load(skipResult.ConversationId);
|
|
866
|
+
this._processingStatus[skipResult.ConversationId] = true;
|
|
867
|
+
this.Conversations.push(convo);
|
|
868
|
+
this.SelectedConversation = convo;
|
|
869
|
+
this.SetSelectedConversationUser();
|
|
870
|
+
}
|
|
871
|
+
else if (innerResult.responsePhase === SkipResponsePhase.analysis_complete) {
|
|
872
|
+
// we are on the first message so skip renamed the convo, use that
|
|
873
|
+
this.SelectedConversation.Name = innerResult.reportTitle; // this will update the UI
|
|
874
|
+
// the below LOOKS redundant to just updating this.SelectedConversation.Name, but it is needed to ensure that the list box is updated
|
|
875
|
+
// otherwise Angular binding doesn't pick up the change without the below.
|
|
876
|
+
const idx = this.Conversations.findIndex((c) => { var _a; return c.ID === ((_a = this.SelectedConversation) === null || _a === void 0 ? void 0 : _a.ID); });
|
|
877
|
+
if (idx >= 0) {
|
|
878
|
+
// update our this.Conversations array to reflect the new name. First find the index of the conversation and then get that item and update it
|
|
879
|
+
this.Conversations[idx].Name = this.SelectedConversation.Name;
|
|
880
|
+
//reredner the list box
|
|
881
|
+
this.Conversations = [...this.Conversations];
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
yield convoDetail.Load(skipResult.UserMessageConversationDetailId); // update the object to load from DB
|
|
885
|
+
const aiDetail = yield p.GetEntityObject('Conversation Details', p.CurrentUser);
|
|
886
|
+
yield aiDetail.Load(skipResult.AIMessageConversationDetailId); // get record from the database
|
|
887
|
+
this.AddMessageToCurrentConversation(aiDetail, true, true);
|
|
888
|
+
// 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...
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
this._scrollToBottom = true; // this results in the angular after Viewchecked scrolling to bottom when it's done
|
|
892
|
+
if (this.SelectedConversation)
|
|
893
|
+
this._processingStatus[(_c = this.SelectedConversation) === null || _c === void 0 ? void 0 : _c.ID] = false;
|
|
894
|
+
this.AllowSend = true;
|
|
895
|
+
this._conversationsInProgress[convoID] = false;
|
|
896
|
+
this._messageInProgress = false;
|
|
897
|
+
// now tell Angular to resume its change detection
|
|
898
|
+
this.cdRef.reattach();
|
|
899
|
+
this.cdRef.detectChanges();
|
|
900
|
+
// invoke manual resize with a delay to ensure that the scroll to bottom has taken place
|
|
901
|
+
//this.sharedService.InvokeManualResize();
|
|
902
|
+
this.SetSkipStatusMessage('', 3500); // slight delay to ensure that the message is removed after the UI has updated with the new response message
|
|
903
|
+
// now set focus on the input box
|
|
904
|
+
this.askSkipInput.nativeElement.focus();
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
sendSkipMessage() {
|
|
909
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
910
|
+
if (this.IsTextAreaEmpty()) {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const input = this.askSkipInput.nativeElement.value;
|
|
914
|
+
yield this.sendPrompt(input);
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
ClearMessages() {
|
|
918
|
+
this.Messages = []; // clear out the messages
|
|
919
|
+
// remove everything from the panel now
|
|
920
|
+
this.askSkip.viewContainerRef.clear();
|
|
921
|
+
}
|
|
922
|
+
AddMessageToCurrentConversation(detail, stopChangeDetection, cacheMessage) {
|
|
923
|
+
// update the local binding for the UI
|
|
924
|
+
this.Messages.push(detail);
|
|
925
|
+
if (cacheMessage) {
|
|
926
|
+
// update the cache of messages for the selected conversation
|
|
927
|
+
const convo = this.SelectedConversation;
|
|
928
|
+
if (convo) {
|
|
929
|
+
const convoAny = convo;
|
|
930
|
+
if (convoAny._Messages) {
|
|
931
|
+
convoAny._Messages.push(detail);
|
|
932
|
+
}
|
|
933
|
+
else {
|
|
934
|
+
convoAny._Messages = [detail];
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
// dynamically add the message to the panel
|
|
939
|
+
this.AddMessageToPanel(detail, stopChangeDetection);
|
|
940
|
+
}
|
|
941
|
+
RemoveMessageFromCurrentConversation(detail) {
|
|
942
|
+
// update the local binding for the UI
|
|
943
|
+
this.Messages = this.Messages.filter((m) => m !== detail);
|
|
944
|
+
// update the cache of messages for the selected conversation
|
|
945
|
+
const convo = this.SelectedConversation;
|
|
946
|
+
if (convo) {
|
|
947
|
+
const convoAny = convo;
|
|
948
|
+
if (convoAny._Messages) {
|
|
949
|
+
convoAny._Messages = convoAny._Messages.filter((m) => m.ID !== detail.ID);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
// dynamically remove the message from the panel
|
|
953
|
+
this.RemoveMessageFromPanel(detail);
|
|
954
|
+
}
|
|
955
|
+
// method to dynamically remove a message
|
|
956
|
+
RemoveMessageFromPanel(messageDetail) {
|
|
957
|
+
const ref = messageDetail._componentRef;
|
|
958
|
+
if (ref) {
|
|
959
|
+
// Temporarily stop change detection for performance
|
|
960
|
+
this.cdRef.detach();
|
|
961
|
+
const index = this.askSkip.viewContainerRef.indexOf(ref.hostView);
|
|
962
|
+
if (index !== -1) {
|
|
963
|
+
this.askSkip.viewContainerRef.remove(index);
|
|
964
|
+
}
|
|
965
|
+
// Resume change detection
|
|
966
|
+
this.cdRef.reattach();
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
// Method to dynamically add a message
|
|
970
|
+
AddMessageToPanel(messageDetail, stopChangeDetection) {
|
|
971
|
+
// Temporarily stop change detection for performance
|
|
972
|
+
if (stopChangeDetection)
|
|
973
|
+
this.cdRef.detach();
|
|
974
|
+
const componentRef = this.askSkip.viewContainerRef.createComponent(SkipSingleMessageComponent);
|
|
975
|
+
// Pass the message details to the component instance
|
|
976
|
+
const obj = componentRef.instance;
|
|
977
|
+
obj.ConversationRecord = this.SelectedConversation;
|
|
978
|
+
obj.ConversationDetailRecord = messageDetail;
|
|
979
|
+
obj.DataContext = this.DataContext;
|
|
980
|
+
obj.ConversationUser = this.SelectedConversationUser;
|
|
981
|
+
obj.ConversationMessages = this.Messages; // pass this on so that the single message has access to the full conversation, for example to know if it is the first/last/only message in the conversation/etc
|
|
982
|
+
// 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
|
|
983
|
+
obj.SuggestedQuestionSelected.subscribe((question) => {
|
|
984
|
+
this.sendPrompt(question);
|
|
985
|
+
});
|
|
986
|
+
// 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
|
|
987
|
+
obj.SuggestedAnswerSelected.subscribe((answer) => {
|
|
988
|
+
this.sendPrompt(answer);
|
|
989
|
+
});
|
|
990
|
+
// now, stash a link to our newly created componentRef inside the messageDetail so we know which componentRef to remove when we delete the message
|
|
991
|
+
messageDetail._componentRef = componentRef;
|
|
992
|
+
// set flag to scroll to the bottom of the chat panel
|
|
993
|
+
this._scrollToBottom = true;
|
|
994
|
+
// Resume change detection
|
|
995
|
+
if (stopChangeDetection)
|
|
996
|
+
this.cdRef.reattach();
|
|
997
|
+
}
|
|
998
|
+
checkScroll() {
|
|
999
|
+
if (this.scrollContainer) {
|
|
1000
|
+
const element = this.scrollContainer.nativeElement;
|
|
1001
|
+
const buffer = 15; // Tolerance in pixels
|
|
1002
|
+
// Calculate the difference between the scroll height and the sum of scroll top and client height
|
|
1003
|
+
const scrollDifference = element.scrollHeight - (element.scrollTop + element.clientHeight);
|
|
1004
|
+
// Consider it at the bottom if the difference is less than or equal to the buffer
|
|
1005
|
+
const atBottom = scrollDifference <= buffer;
|
|
1006
|
+
this._showScrollToBottomIcon = !atBottom;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
scrollToBottom() {
|
|
1010
|
+
try {
|
|
1011
|
+
this.askSkipPanel.nativeElement.scrollTop = this.askSkipPanel.nativeElement.scrollHeight;
|
|
1012
|
+
}
|
|
1013
|
+
catch (err) { }
|
|
1014
|
+
}
|
|
1015
|
+
scrollToBottomAnimate() {
|
|
1016
|
+
if (this.scrollContainer) {
|
|
1017
|
+
const element = this.scrollContainer.nativeElement;
|
|
1018
|
+
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
GetCreateDataContextID() {
|
|
1022
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1023
|
+
// temporary hack for now, we will have more functionality to do robust UX around DataCOntext viewing and editing soon
|
|
1024
|
+
// and get rid of this
|
|
1025
|
+
if (!this.DataContextID && this.SelectedConversation) {
|
|
1026
|
+
// need to create a data context
|
|
1027
|
+
// add to the new data context a single item for the passed in linked record, which could be a query, view, or something else
|
|
1028
|
+
const p = this.ProviderToUse;
|
|
1029
|
+
const dc = yield p.GetEntityObject('Data Contexts', p.CurrentUser);
|
|
1030
|
+
dc.NewRecord();
|
|
1031
|
+
const e = p.Entities.find((e) => e.Name === this.LinkedEntity);
|
|
1032
|
+
dc.Name =
|
|
1033
|
+
'Data Context for Skip Conversation ' + (e ? ' for ' + e.Name + ' - Record ID: ' + this.LinkedEntityCompositeKey.Values() : '');
|
|
1034
|
+
dc.UserID = p.CurrentUser.ID;
|
|
1035
|
+
if (yield dc.Save()) {
|
|
1036
|
+
this.DataContextID = dc.ID;
|
|
1037
|
+
// update the conversation with the data context id
|
|
1038
|
+
const convo = yield p.GetEntityObject('Conversations', p.CurrentUser);
|
|
1039
|
+
yield convo.Load(this.SelectedConversation.ID);
|
|
1040
|
+
yield convo.Save(); // save to the database
|
|
1041
|
+
this.SelectedConversation.DataContextID = dc.ID; // update the in-memory object
|
|
1042
|
+
if (this.LinkedEntity && this.CompositeKeyIsPopulated() && e) {
|
|
1043
|
+
// now create a single data context item for the new data context
|
|
1044
|
+
let type;
|
|
1045
|
+
switch (e.Name.trim().toLowerCase()) {
|
|
1046
|
+
case 'user views':
|
|
1047
|
+
type = 'view';
|
|
1048
|
+
break;
|
|
1049
|
+
case 'queries':
|
|
1050
|
+
type = 'query';
|
|
1051
|
+
break;
|
|
1052
|
+
default:
|
|
1053
|
+
if (this.CompositeKeyIsPopulated()) {
|
|
1054
|
+
type = 'single_record';
|
|
1055
|
+
}
|
|
1056
|
+
else
|
|
1057
|
+
type = 'full_entity';
|
|
1058
|
+
break;
|
|
1059
|
+
}
|
|
1060
|
+
const dci = yield p.GetEntityObject('Data Context Items', p.CurrentUser);
|
|
1061
|
+
dci.NewRecord();
|
|
1062
|
+
dci.DataContextID = dc.ID;
|
|
1063
|
+
dci.Type = type;
|
|
1064
|
+
if (type === 'view')
|
|
1065
|
+
dci.ViewID = this.LinkedEntityCompositeKey.GetValueByIndex(0);
|
|
1066
|
+
else if (type === 'query')
|
|
1067
|
+
dci.QueryID = this.LinkedEntityCompositeKey.GetValueByIndex(0);
|
|
1068
|
+
else if (type === 'single_record') {
|
|
1069
|
+
dci.RecordID = this.LinkedEntityCompositeKey.Values();
|
|
1070
|
+
dci.EntityID = e.ID;
|
|
1071
|
+
}
|
|
1072
|
+
else if (type === 'full_entity')
|
|
1073
|
+
dci.EntityID = e.ID;
|
|
1074
|
+
if (!(yield dci.Save())) {
|
|
1075
|
+
SharedService.Instance.CreateSimpleNotification('Error creating data context item', 'error', 5000);
|
|
1076
|
+
console.log('AskSkipComponent: Error creating data context item');
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
else {
|
|
1081
|
+
SharedService.Instance.CreateSimpleNotification('Error creating data context', 'error', 5000);
|
|
1082
|
+
console.log('AskSkipComponent: Error creating data context');
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
if (!this.DataContext) {
|
|
1086
|
+
// load the actual data context object
|
|
1087
|
+
this.DataContext = new DataContext();
|
|
1088
|
+
yield this.DataContext.LoadMetadata(this.DataContextID, this.ProviderToUse.CurrentUser, this.ProviderToUse);
|
|
1089
|
+
}
|
|
1090
|
+
return this.DataContextID;
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
ExecuteAskSkipQuery(question, dataContextId, SelectedConversation) {
|
|
1094
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1095
|
+
try {
|
|
1096
|
+
const gql = `query ExecuteAskSkipAnalysisQuery($userQuestion: String!, $dataContextId: String!, $conversationId: String!) {
|
|
1097
|
+
ExecuteAskSkipAnalysisQuery(UserQuestion: $userQuestion, DataContextId: $dataContextId, ConversationId: $conversationId) {
|
|
1098
|
+
Success
|
|
1099
|
+
Status
|
|
1100
|
+
Result
|
|
1101
|
+
ConversationId
|
|
1102
|
+
UserMessageConversationDetailId
|
|
1103
|
+
AIMessageConversationDetailId
|
|
1104
|
+
}
|
|
1105
|
+
}`;
|
|
1106
|
+
const gqlProvider = this.ProviderToUse;
|
|
1107
|
+
const result = yield gqlProvider.ExecuteGQL(gql, {
|
|
1108
|
+
userQuestion: question,
|
|
1109
|
+
conversationId: SelectedConversation ? SelectedConversation.ID : '',
|
|
1110
|
+
dataContextId: dataContextId,
|
|
1111
|
+
});
|
|
1112
|
+
return result;
|
|
1113
|
+
}
|
|
1114
|
+
catch (err) {
|
|
1115
|
+
LogError('Error executing AskSkip query', undefined, err);
|
|
1116
|
+
const p = this.ProviderToUse;
|
|
1117
|
+
const errorMessage = yield p.GetEntityObject('Conversation Details', p.CurrentUser);
|
|
1118
|
+
errorMessage.NewRecord();
|
|
1119
|
+
errorMessage.Role = 'Error';
|
|
1120
|
+
errorMessage.Message = 'Error took place' + err;
|
|
1121
|
+
this.AddMessageToCurrentConversation(errorMessage, true, false);
|
|
1122
|
+
this.AllowSend = true;
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
DeleteConversation(ConversationID) {
|
|
1127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1128
|
+
const p = this.ProviderToUse;
|
|
1129
|
+
const convEntity = yield p.GetEntityObject('Conversations', p.CurrentUser);
|
|
1130
|
+
yield convEntity.Load(ConversationID);
|
|
1131
|
+
return yield convEntity.Delete();
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
IsSkipProcessing(Conversation) {
|
|
1135
|
+
if (this._processingStatus[Conversation.ID]) {
|
|
1136
|
+
return this._processingStatus[Conversation.ID];
|
|
1137
|
+
}
|
|
1138
|
+
else
|
|
1139
|
+
return false;
|
|
1140
|
+
}
|
|
1141
|
+
IsTextAreaEmpty() {
|
|
1142
|
+
if (this.askSkipInput && this.askSkipInput.nativeElement) {
|
|
1143
|
+
const input = this.askSkipInput.nativeElement.value;
|
|
1144
|
+
if (!input) {
|
|
1145
|
+
return true;
|
|
1146
|
+
}
|
|
1147
|
+
const trimmedInput = input.trim();
|
|
1148
|
+
if (trimmedInput.length === 0 || trimmedInput === '') {
|
|
1149
|
+
return true;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return false;
|
|
1153
|
+
}
|
|
1154
|
+
showDataContext() {
|
|
1155
|
+
this.isDataContextDialogVisible = true;
|
|
1156
|
+
}
|
|
1157
|
+
closeDataContextDialog() {
|
|
1158
|
+
this.isDataContextDialogVisible = false;
|
|
1159
|
+
}
|
|
1160
|
+
CompositeKeyIsPopulated() {
|
|
1161
|
+
return this.LinkedEntityCompositeKey.KeyValuePairs && this.LinkedEntityCompositeKey.KeyValuePairs.length > 0;
|
|
1162
|
+
}
|
|
1163
|
+
ngOnDetach() {
|
|
1164
|
+
if (this.sub) {
|
|
1165
|
+
this.sub.unsubscribe();
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
ngOnAttach() {
|
|
1169
|
+
if (this.sub && !this.sub.closed) {
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
this.sub = this.router.events
|
|
1173
|
+
.pipe(filter((e) => e instanceof ActivationEnd), take(1))
|
|
1174
|
+
.subscribe((e) => {
|
|
1175
|
+
this.onNavBackToCachedComponent();
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
onNavBackToCachedComponent() {
|
|
1179
|
+
if (this.paramsSubscription) {
|
|
1180
|
+
this.paramsSubscription.unsubscribe();
|
|
1181
|
+
}
|
|
1182
|
+
this.paramsSubscription = this.route.params.subscribe((params) => {
|
|
1183
|
+
const convoIDParam = params.conversationId;
|
|
1184
|
+
this.loadConversations(convoIDParam);
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
SkipChatComponent.__skipChatWindowsCurrentlyVisible = 0;
|
|
1189
|
+
SkipChatComponent._startMessages = [
|
|
1190
|
+
'On it, let me get back to you in a moment with the results!🤖',
|
|
1191
|
+
"I'm on it, just a moment! 🙂",
|
|
1192
|
+
"I'll get started in a jiffy!",
|
|
1193
|
+
"You bet, I'd love to help, give me a moment!",
|
|
1194
|
+
"I understand, I'll start running in that direction 👟",
|
|
1195
|
+
"No problem, I'll get started right away!",
|
|
1196
|
+
"Ok, heard loud and clear, I'll jump right on it! 👂",
|
|
1197
|
+
"Aye aye captain, I'll get started right away! ⚓",
|
|
1198
|
+
];
|
|
1199
|
+
SkipChatComponent.ɵfac = function SkipChatComponent_Factory(t) { return new (t || SkipChatComponent)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i2.ActivatedRoute), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i3.Location), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
1200
|
+
SkipChatComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SkipChatComponent, selectors: [["skip-chat"]], viewQuery: function SkipChatComponent_Query(rf, ctx) { if (rf & 1) {
|
|
1201
|
+
i0.ɵɵviewQuery(Container, 7);
|
|
1202
|
+
i0.ɵɵviewQuery(_c0, 7);
|
|
1203
|
+
i0.ɵɵviewQuery(_c1, 5, ViewContainerRef);
|
|
1204
|
+
i0.ɵɵviewQuery(_c2, 5);
|
|
1205
|
+
i0.ɵɵviewQuery(_c3, 5);
|
|
1206
|
+
i0.ɵɵviewQuery(_c4, 5);
|
|
1207
|
+
i0.ɵɵviewQuery(_c5, 5);
|
|
1208
|
+
} if (rf & 2) {
|
|
1209
|
+
let _t;
|
|
1210
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.askSkip = _t.first);
|
|
1211
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.askSkipPanel = _t.first);
|
|
1212
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.mjContainerRef = _t.first);
|
|
1213
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.conversationList = _t.first);
|
|
1214
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.askSkipInput = _t.first);
|
|
1215
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.scrollContainer = _t.first);
|
|
1216
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.topLevelDiv = _t.first);
|
|
1217
|
+
} }, 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", UpdateAppRoute: "UpdateAppRoute", Provider: "Provider", WelcomeQuestions: "WelcomeQuestions" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 21, vars: 10, consts: [["topLevelDiv", ""], ["AskSkipPanel", "", "scrollContainer", ""], ["AskSkipInput", ""], ["conversationList", ""], ["mjFillContainer", "", 1, "chat-container", 3, "bottomMargin", "rightMargin"], ["orientation", "horizontal"], ["size", "272px", 3, "collapsible", "scrollable", "resizable", "collapsedChange", 4, "ngIf"], ["mjFillContainer", "", 1, "conversation-wrapper"], [1, "messages", 3, "scroll"], ["class", "waiting-for-ai", 4, "ngIf"], ["class", "welcome-wrapper", 4, "ngIf"], ["mjContainer", "", "mjSkipResize", "true"], ["class", "scroll-to-bottom-icon", 3, "click", 4, "ngIf"], [1, "input-area"], [1, "text-area-wrapper"], ["type", "text", "placeholder", "Ask Skip a question", 3, "keyup.enter", "input", "disabled"], ["kendoButton", ""], ["kendoButton", "", 3, "click", "disabled"], [1, "fas", "fa-solid", "fa-arrow-up"], [4, "ngIf"], ["size", "272px", 3, "collapsedChange", "collapsible", "scrollable", "resizable"], ["class", "conversation-history", 4, "ngIf"], [1, "conversation-history"], [1, "new-chat-area"], ["src", "assets/Skip Full Logo - Transparent.png", 1, "avatar"], ["kendoButton", "", 3, "click", 4, "ngIf"], ["mjFillContainer", "", 1, "conversation-list", 3, "data", "itemClass", "fillWidth", "bottomMargin"], ["kendoListViewItemTemplate", ""], ["kendoButton", "", 3, "click"], [1, "conversation-item", 3, "click", "ngClass", "title"], ["class", "fa-regular fa-clock", 4, "ngIf"], [1, "text-container"], ["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, "waiting-for-ai"], [1, "welcome-wrapper"], [1, "welcome-message"], ["src", "assets/Skip Full Logo - Transparent.png"], [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, "fa-solid", "fa-gear", 3, "click"], [3, "dialogClosed", "dataContextId"]], template: function SkipChatComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1218
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
1219
|
+
i0.ɵɵelementStart(0, "div", 4, 0)(2, "kendo-splitter", 5);
|
|
1220
|
+
i0.ɵɵtemplate(3, SkipChatComponent_kendo_splitter_pane_3_Template, 2, 4, "kendo-splitter-pane", 6);
|
|
1221
|
+
i0.ɵɵelementStart(4, "kendo-splitter-pane")(5, "div", 7)(6, "div", 8, 1);
|
|
1222
|
+
i0.ɵɵlistener("scroll", function SkipChatComponent_Template_div_scroll_6_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.checkScroll()); });
|
|
1223
|
+
i0.ɵɵtemplate(9, SkipChatComponent_div_9_Template, 2, 0, "div", 9)(10, SkipChatComponent_div_10_Template, 28, 8, "div", 10);
|
|
1224
|
+
i0.ɵɵelement(11, "div", 11);
|
|
1225
|
+
i0.ɵɵtemplate(12, SkipChatComponent_span_12_Template, 2, 0, "span", 12);
|
|
1226
|
+
i0.ɵɵelementEnd();
|
|
1227
|
+
i0.ɵɵelementStart(13, "div", 13)(14, "div", 14)(15, "textarea", 15, 2);
|
|
1228
|
+
i0.ɵɵlistener("keyup.enter", function SkipChatComponent_Template_textarea_keyup_enter_15_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onEnter($event)); })("input", function SkipChatComponent_Template_textarea_input_15_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onInputChange($event)); });
|
|
1229
|
+
i0.ɵɵelementEnd()();
|
|
1230
|
+
i0.ɵɵtemplate(17, SkipChatComponent_Conditional_17_Template, 2, 0, "button", 16);
|
|
1231
|
+
i0.ɵɵelementStart(18, "button", 17);
|
|
1232
|
+
i0.ɵɵlistener("click", function SkipChatComponent_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.sendSkipMessage()); });
|
|
1233
|
+
i0.ɵɵelement(19, "span", 18);
|
|
1234
|
+
i0.ɵɵelementEnd()()()()()();
|
|
1235
|
+
i0.ɵɵtemplate(20, SkipChatComponent_div_20_Template, 2, 1, "div", 19);
|
|
1236
|
+
} if (rf & 2) {
|
|
1237
|
+
i0.ɵɵproperty("bottomMargin", 10)("rightMargin", 10);
|
|
1238
|
+
i0.ɵɵadvance(3);
|
|
1239
|
+
i0.ɵɵproperty("ngIf", ctx.ShowConversationList);
|
|
1240
|
+
i0.ɵɵadvance(6);
|
|
1241
|
+
i0.ɵɵproperty("ngIf", ctx.Messages && ctx.Messages.length > 0 && ctx.SelectedConversation && ctx.IsSkipProcessing(ctx.SelectedConversation));
|
|
1242
|
+
i0.ɵɵadvance();
|
|
1243
|
+
i0.ɵɵproperty("ngIf", (!ctx.Messages || ctx.Messages.length === 0) && ctx._conversationLoadComplete);
|
|
1244
|
+
i0.ɵɵadvance(2);
|
|
1245
|
+
i0.ɵɵproperty("ngIf", ctx._showScrollToBottomIcon && ctx.Messages && ctx.Messages.length > 0);
|
|
1246
|
+
i0.ɵɵadvance(3);
|
|
1247
|
+
i0.ɵɵproperty("disabled", ctx.SelectedConversation && ctx.IsSkipProcessing(ctx.SelectedConversation));
|
|
1248
|
+
i0.ɵɵadvance(2);
|
|
1249
|
+
i0.ɵɵconditional(ctx.ShowDataContextButton ? 17 : -1);
|
|
1250
|
+
i0.ɵɵadvance();
|
|
1251
|
+
i0.ɵɵproperty("disabled", ctx.IsTextAreaEmpty() || ctx.SelectedConversation !== undefined && ctx.IsSkipProcessing(ctx.SelectedConversation));
|
|
1252
|
+
i0.ɵɵadvance(2);
|
|
1253
|
+
i0.ɵɵproperty("ngIf", ctx.isDataContextDialogVisible);
|
|
1254
|
+
} }, dependencies: [i3.NgClass, i3.NgIf, i4.SplitterComponent, i4.SplitterPaneComponent, i5.DefaultValueAccessor, i5.NgControlStatus, i5.MaxLengthValidator, i5.NgModel, i6.LoaderComponent, i7.FillContainer, i7.Container, i8.ItemTemplateDirective, i8.ListViewComponent, i9.ButtonComponent, i10.DataContextDialogComponent], styles: [".chat-container[_ngcontent-%COMP%] {\n padding: 5px;\n display: flex;\n flex-direction: row;\n height: 100%;\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\n width: 100%;\n height: 100%;\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}\n\n.new-conversation[_ngcontent-%COMP%] {\n height: 30px;\n font-size: large;\n}\n\n.conversation-history[_ngcontent-%COMP%] {\n width: 260px;\n min-width: 260px;\n height: 100%;\n overflow-y: auto; \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}\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}\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}\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}\n.welcome-suggested-questions-col[_ngcontent-%COMP%] {\n display: flex;\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; \n\n overflow-x: hidden; \n\n \n\n margin-bottom: 5px;\n\n margin-top: 2px; \n\n\n background-color: #f9f9f9;\n flex: 1;\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 width: 100%; \n\n display: flex;\n justify-content: flex-end; \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}\n\n.input-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%] {\n vertical-align: top;\n width: 30px;\n height: 30px;\n margin-top: 3px;\n border-radius: 12px;\n}\n.input-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%]:first-of-type {\n margin-left: -40px;\n}\n.input-area[_ngcontent-%COMP%] > button[_ngcontent-%COMP%]:last-child {\n margin-left: -65px;\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.text-area-wrapper[_ngcontent-%COMP%] > textarea[_ngcontent-%COMP%]:disabled {\n background-color: white;\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: absolute;\n bottom: 100px; \n\n left: 50%; \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}\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}"] });
|
|
1255
|
+
SkipChatComponent = SkipChatComponent_1 = __decorate([
|
|
1256
|
+
RegisterClass(BaseNavigationComponent, 'Ask Skip')
|
|
1257
|
+
], SkipChatComponent);
|
|
1258
|
+
export { SkipChatComponent };
|
|
1259
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SkipChatComponent, [{
|
|
1260
|
+
type: Component,
|
|
1261
|
+
args: [{ selector: 'skip-chat', template: "<div class = \"chat-container\" mjFillContainer #topLevelDiv [bottomMargin]=\"10\" [rightMargin]=\"10\">\n <kendo-splitter orientation=\"horizontal\">\n <kendo-splitter-pane *ngIf=\"ShowConversationList\" [collapsible]=\"true\" [scrollable]=\"false\" [resizable]=\"false\" size=\"272px\" (collapsedChange)=\"splitterCollapseStateChanged($event)\">\n <div class=\"conversation-history\" *ngIf=\"ShowConversationList\">\n <div class=\"new-chat-area\">\n <img src=\"assets/Skip Full Logo - Transparent.png\" class=\"avatar\" />\n <button kendoButton *ngIf=\"AllowNewConversations\" (click)=\"CreateNewConversation()\">+</button>\n </div>\n <kendo-listview\n class=\"conversation-list\"\n [data]=\"Conversations\"\n [style.height.px]=\"280\"\n [itemClass]=\"{ 'item-border': true }\" \n mjFillContainer \n [fillWidth]=\"false\"\n [bottomMargin]=\"20\"\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)=\"deleteConvo(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 </kendo-splitter-pane>\n <kendo-splitter-pane>\n <div class=\"conversation-wrapper\" mjFillContainer>\n <div #AskSkipPanel class=\"messages\" #scrollContainer (scroll)=\"checkScroll()\">\n <div class=\"waiting-for-ai\" *ngIf=\"Messages && Messages.length > 0 && SelectedConversation && IsSkipProcessing(SelectedConversation)\">\n <kendo-loader></kendo-loader>\n </div>\n <div class=\"welcome-wrapper\" *ngIf=\"(!Messages || Messages.length ===0) && _conversationLoadComplete\">\n <div class='welcome-message'>\n <img src=\"assets/Skip Full Logo - Transparent.png\"/>\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 <div 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\" *ngIf=\"_showScrollToBottomIcon && Messages && Messages.length > 0\" (click)=\"scrollToBottomAnimate()\"><i class=\"fas fa-arrow-down\"></i></span>\n </div>\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=\"Ask Skip a question\"></textarea>\n </div>\n @if (ShowDataContextButton) {\n <button kendoButton >\n <span class=\"fa-solid fa-gear\" \n (click)=\"showDataContext()\"></span>\n </button> \n }\n <button kendoButton \n [disabled]=\"IsTextAreaEmpty() || (SelectedConversation !== undefined && IsSkipProcessing(SelectedConversation))\" \n (click)=\"sendSkipMessage()\">\n <span class=\"fas fa-solid fa-arrow-up\"></span>\n </button>\n </div>\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div> \n\n<div *ngIf=\"isDataContextDialogVisible\">\n <mj-data-context-dialog [dataContextId]=\"DataContextID\" (dialogClosed)=\"closeDataContextDialog()\"></mj-data-context-dialog>\n</div>", styles: [".chat-container {\n padding: 5px;\n display: flex;\n flex-direction: row;\n height: 100%;\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 /*initial sizes*/\n width: 100%;\n height: 100%;\n\n background-color: #f9f9f9;\n}\n\n.conversation-wrapper {\n display: flex;\n flex-direction: column;\n position: relative; /* Add this line if the wrapper needs to be a reference point */\n background-color: #f9f9f9;\n}\n\n.new-conversation {\n height: 30px;\n font-size: large;\n}\n\n.conversation-history {\n width: 260px;\n min-width: 260px;\n height: 100%;\n overflow-y: auto; /* Add scroll if the content exceeds the height */\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}\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}\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}\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}\n.welcome-suggested-questions-col {\n display: flex;\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; /* enable scrolling if the content overflows */\n overflow-x: hidden; /* 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;\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 width: 100%; /* Take up the full width */\n display: flex;\n justify-content: flex-end; /* Align icons 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}\n\n.input-area > button {\n vertical-align: top;\n width: 30px;\n height: 30px;\n margin-top: 3px;\n border-radius: 12px;\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\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: absolute;\n bottom: 100px; /* Adjust as needed to position away from the bottom edge */\n left: 50%; /* Start at the exact horizontal center */\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 - adjust as needed */\n color: black; /* Icon color - adjust as needed */\n border-radius: 50%; /* Makes the background a circle */\n width: 40px; /* Circle size - adjust as needed */\n height: 40px; /* Circle size - adjust as needed */\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: 0px 0px 5px rgba(0,0,0,0.3); /* Optional: Adds a subtle shadow for better visibility */\n cursor: pointer;\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 "] }]
|
|
1262
|
+
}], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i0.Renderer2 }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i3.Location }, { type: i0.ChangeDetectorRef }], { AllowSend: [{
|
|
1263
|
+
type: Input
|
|
1264
|
+
}], Messages: [{
|
|
1265
|
+
type: Input
|
|
1266
|
+
}], Conversations: [{
|
|
1267
|
+
type: Input
|
|
1268
|
+
}], SelectedConversation: [{
|
|
1269
|
+
type: Input
|
|
1270
|
+
}], ConversationEditMode: [{
|
|
1271
|
+
type: Input
|
|
1272
|
+
}], ShowConversationList: [{
|
|
1273
|
+
type: Input
|
|
1274
|
+
}], AllowNewConversations: [{
|
|
1275
|
+
type: Input
|
|
1276
|
+
}], Title: [{
|
|
1277
|
+
type: Input
|
|
1278
|
+
}], DataContextID: [{
|
|
1279
|
+
type: Input
|
|
1280
|
+
}], LinkedEntity: [{
|
|
1281
|
+
type: Input
|
|
1282
|
+
}], LinkedEntityCompositeKey: [{
|
|
1283
|
+
type: Input
|
|
1284
|
+
}], ShowDataContextButton: [{
|
|
1285
|
+
type: Input
|
|
1286
|
+
}], IncludeLinkedConversationsInList: [{
|
|
1287
|
+
type: Input
|
|
1288
|
+
}], UpdateAppRoute: [{
|
|
1289
|
+
type: Input
|
|
1290
|
+
}], Provider: [{
|
|
1291
|
+
type: Input
|
|
1292
|
+
}], askSkip: [{
|
|
1293
|
+
type: ViewChild,
|
|
1294
|
+
args: [Container, { static: true }]
|
|
1295
|
+
}], askSkipPanel: [{
|
|
1296
|
+
type: ViewChild,
|
|
1297
|
+
args: ['AskSkipPanel', { static: true }]
|
|
1298
|
+
}], mjContainerRef: [{
|
|
1299
|
+
type: ViewChild,
|
|
1300
|
+
args: ['mjContainer', { read: ViewContainerRef }]
|
|
1301
|
+
}], conversationList: [{
|
|
1302
|
+
type: ViewChild,
|
|
1303
|
+
args: ['conversationList', { static: false }]
|
|
1304
|
+
}], askSkipInput: [{
|
|
1305
|
+
type: ViewChild,
|
|
1306
|
+
args: ['AskSkipInput']
|
|
1307
|
+
}], scrollContainer: [{
|
|
1308
|
+
type: ViewChild,
|
|
1309
|
+
args: ['scrollContainer']
|
|
1310
|
+
}], topLevelDiv: [{
|
|
1311
|
+
type: ViewChild,
|
|
1312
|
+
args: ['topLevelDiv']
|
|
1313
|
+
}], WelcomeQuestions: [{
|
|
1314
|
+
type: Input
|
|
1315
|
+
}] }); })();
|
|
1316
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SkipChatComponent, { className: "SkipChatComponent", filePath: "src/lib/skip-chat/skip-chat.component.ts", lineNumber: 41 }); })();
|
|
1317
|
+
//# sourceMappingURL=skip-chat.component.js.map
|