@chat21/chat21-ionic 3.4.12 → 3.4.13-rc1
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/CHANGELOG.md +3 -0
- package/Dockerfile +1 -1
- package/config.xml +0 -1
- package/package.json +4 -4
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +35 -23
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +8 -1
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +5 -1
- package/src/app/components/copilot-suggestions/copilot-suggestions.component.html +36 -0
- package/src/app/components/copilot-suggestions/copilot-suggestions.component.scss +205 -0
- package/src/app/components/copilot-suggestions/copilot-suggestions.component.spec.ts +24 -0
- package/src/app/components/copilot-suggestions/copilot-suggestions.component.ts +163 -0
- package/src/app/pages/conversation-detail/conversation-detail.module.ts +2 -0
- package/src/app/pages/conversation-detail/conversation-detail.page.html +12 -1
- package/src/app/pages/conversation-detail/conversation-detail.page.scss +2 -1
- package/src/app/pages/conversation-detail/conversation-detail.page.ts +53 -14
- package/src/app/services/copilot/copilot.service.spec.ts +16 -0
- package/src/app/services/copilot/copilot.service.ts +44 -0
- package/src/assets/i18n/en.json +3 -0
- package/src/assets/i18n/it.json +4 -1
- package/src/assets/images/icons/copilot.svg +3 -0
package/CHANGELOG.md
CHANGED
package/Dockerfile
CHANGED
package/config.xml
CHANGED
|
@@ -106,7 +106,6 @@
|
|
|
106
106
|
<platform name="browser">
|
|
107
107
|
<preference name="ShowSplashScreen" value="false" />
|
|
108
108
|
</platform>
|
|
109
|
-
<engine name="browser" spec="^5.0.4" />
|
|
110
109
|
<plugin name="cordova-android-support-gradle-release" spec="^3.0.1">
|
|
111
110
|
<variable name="ANDROID_SUPPORT_VERSION" value="27.+" />
|
|
112
111
|
</plugin>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chat21/chat21-ionic",
|
|
3
3
|
"author": "Tiledesk SRL",
|
|
4
|
-
"version": "3.4.
|
|
4
|
+
"version": "3.4.13-rc1",
|
|
5
5
|
"license": "MIT License",
|
|
6
6
|
"homepage": "https://tiledesk.com/",
|
|
7
7
|
"repository": {
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
"autolinker": "^3.14.2",
|
|
49
49
|
"cordova": "^11.1.0",
|
|
50
50
|
"cordova-android-support-gradle-release": "^3.0.1",
|
|
51
|
-
"cordova-browser": "^5.0.4",
|
|
52
51
|
"cordova-plugin-chooser": "^1.3.2",
|
|
53
52
|
"cordova-plugin-ionic-keyboard": "^2.2.0",
|
|
54
53
|
"cordova-plugin-ionic-webview": "^4.2.1",
|
|
@@ -86,6 +85,7 @@
|
|
|
86
85
|
"@types/node": "^12.20.55",
|
|
87
86
|
"codelyzer": "^6.0.0",
|
|
88
87
|
"cordova-android": "^10.1.2",
|
|
88
|
+
"cordova-browser": "^6.0.0",
|
|
89
89
|
"cordova-ios": "^6.3.0",
|
|
90
90
|
"cordova-plugin-add-swift-support": "^2.0.2",
|
|
91
91
|
"cordova-plugin-fcm-with-dependecy-updated": "^7.8.0",
|
|
@@ -147,9 +147,9 @@
|
|
|
147
147
|
}
|
|
148
148
|
},
|
|
149
149
|
"platforms": [
|
|
150
|
-
"browser",
|
|
151
150
|
"android",
|
|
152
|
-
"ios"
|
|
151
|
+
"ios",
|
|
152
|
+
"browser"
|
|
153
153
|
]
|
|
154
154
|
}
|
|
155
155
|
}
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
<ion-grid>
|
|
2
2
|
<div class="footer-options-container">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
<ion-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
<ion-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
<div>
|
|
4
|
+
<!-- CHAT-OPTION -->
|
|
5
|
+
<div class="section-option" id="chat" tooltip="{{translationMap?.get('LABEL_CHAT')}}" placement="top">
|
|
6
|
+
<ion-button fill="clear" (click)="onOpenSection('chat')" [class.active]="section==='chat'">
|
|
7
|
+
<ion-icon name="chatbubbles"></ion-icon>
|
|
8
|
+
{{translationMap.get('LABEL_CHAT')}}
|
|
9
|
+
</ion-button>
|
|
10
|
+
</div>
|
|
11
|
+
<!-- EMAIL-OPTION -->
|
|
12
|
+
<div *ngIf="emailSection" class="section-option" id="email" tooltip="{{translationMap?.get('EMAIL.LABEL_TOOLTIP')}}" placement="top">
|
|
13
|
+
<ion-button fill="clear" [class.active]="section==='email'" (click)="onOpenSection('email')" [disabled]="channelType === 'direct' || channel == CHANNEL_TYPE.WHATSAPP || channel == CHANNEL_TYPE.MESSENGER">
|
|
14
|
+
<ion-icon name="mail-open"></ion-icon>
|
|
15
|
+
{{translationMap.get('LABEL_EMAIL')}}
|
|
16
|
+
</ion-button>
|
|
17
|
+
</div>
|
|
18
|
+
<!-- WHATSAPP TEMPLATE -->
|
|
19
|
+
<div *ngIf="whatsappTemplatesSection" class="section-option" id="template" tooltip="{{translationMap?.get('WHATSAPP.LABEL_TOOLTIP')}}" placement="top">
|
|
20
|
+
<ion-button fill="clear" [class.active]="section==='templates'" (click)="onOpenSection('templates');onOpenTemplateModal()" [disabled]="channel !== CHANNEL_TYPE.WHATSAPP">
|
|
21
|
+
<ion-icon name="logo-whatsapp"></ion-icon>
|
|
22
|
+
{{translationMap?.get('WHATSAPP.LABEL_TEMPLATES')}}
|
|
23
|
+
</ion-button>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div *ngIf="offlineMsgEmail && section==='chat' && channel !== CHANNEL_TYPE.WHATSAPP && messageString && (leadInfo?.presence['status']==='offline' && leadInfo?.hasEmail)" class="section-option offline-lead-tip" >
|
|
27
|
+
{{translationMap.get('EMAIL.EMAIL_OFFLINE_TIP')}}
|
|
28
|
+
</div>
|
|
16
29
|
</div>
|
|
17
30
|
|
|
18
|
-
<div
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{{translationMap.get('EMAIL.EMAIL_OFFLINE_TIP')}}
|
|
31
|
+
<div>
|
|
32
|
+
<!-- COPILOT-OPTION -->
|
|
33
|
+
<div class="section-option" id="copilot" tooltip="{{translationMap?.get('COPILOT.ASK_AI')}}" placement="top">
|
|
34
|
+
<ion-button fill="clear" [class.active]="section ==='copilot'" (click)="onOpenSection('copilot')">
|
|
35
|
+
<ion-icon class="channel-icon" src="assets/images/icons/copilot.svg"></ion-icon>
|
|
36
|
+
{{translationMap?.get('COPILOT.ASK_AI')}}
|
|
37
|
+
</ion-button>
|
|
38
|
+
</div>
|
|
27
39
|
</div>
|
|
28
40
|
|
|
29
41
|
</div>
|
|
@@ -35,7 +47,7 @@
|
|
|
35
47
|
</ion-col>
|
|
36
48
|
</ion-row>
|
|
37
49
|
|
|
38
|
-
<ion-row id="message-text-area" [style.display]="section==='chat' || section ==='templates'? 'flex': 'none'">
|
|
50
|
+
<ion-row id="message-text-area" [style.display]="section==='chat' || section ==='templates' || section ==='copilot'? 'flex': 'none'">
|
|
39
51
|
|
|
40
52
|
<ion-col col-auto style="display: flex;">
|
|
41
53
|
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
padding: 0px 16px 0px;
|
|
6
6
|
border-bottom: 1px solid var(--border-color-base);
|
|
7
7
|
border-top: 3px solid var(--basic-blue);
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
|
|
10
|
+
& > div{
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
.section-option{
|
|
10
16
|
line-height: 16px;
|
|
@@ -26,6 +32,7 @@
|
|
|
26
32
|
height: 25px;
|
|
27
33
|
&.active{
|
|
28
34
|
color: var(--basic-blue);
|
|
35
|
+
fill: var(--basic-blue);
|
|
29
36
|
}
|
|
30
37
|
ion-icon{
|
|
31
38
|
margin-right: 4px;
|
|
@@ -35,7 +42,7 @@
|
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
.offline-lead-tip{
|
|
38
|
-
font-size:
|
|
45
|
+
font-size: 9px;
|
|
39
46
|
width: 100%;
|
|
40
47
|
display: block;
|
|
41
48
|
text-align: right;
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts
CHANGED
|
@@ -22,6 +22,8 @@ import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance'
|
|
|
22
22
|
import { EventsService } from 'src/app/services/events-service';
|
|
23
23
|
import { isOnMobileDevice } from 'src/chat21-core/utils/utils';
|
|
24
24
|
import { checkAcceptedFile } from 'src/chat21-core/utils/utils';
|
|
25
|
+
import { CopilotService } from 'src/app/services/copilot/copilot.service';
|
|
26
|
+
import { BRAND_BASE_INFO } from 'src/app/utils/utils-resources';
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
@Component({
|
|
@@ -106,6 +108,9 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
106
108
|
imageUrl: 'https://tiledesk.com/wp-content/uploads/2022/11/FAQ-Chatbot.png',
|
|
107
109
|
}
|
|
108
110
|
];
|
|
111
|
+
|
|
112
|
+
BRAND_BASE_INFO = BRAND_BASE_INFO
|
|
113
|
+
|
|
109
114
|
/**
|
|
110
115
|
* Constructor
|
|
111
116
|
* @param chooser
|
|
@@ -118,7 +123,6 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
118
123
|
public modalController: ModalController,
|
|
119
124
|
public uploadService: UploadService,
|
|
120
125
|
public toastController: ToastController,
|
|
121
|
-
private renderer: Renderer2,
|
|
122
126
|
public eventsService: EventsService
|
|
123
127
|
) { }
|
|
124
128
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<div class="canned-list" *ngIf="suggestions.length > 0">
|
|
3
|
+
<ion-item button="true" [ngClass]="{'is_active_item': i == arrowkeyLocation}" lines="none"
|
|
4
|
+
class="canned-item no-ripple border" id="{{'canned-item_'+ i }}"
|
|
5
|
+
*ngFor="let suggestion of suggestions; let i = index;"
|
|
6
|
+
(click)="onClickSuggestionFN(suggestion, $event)">
|
|
7
|
+
<div class="cannedContent">
|
|
8
|
+
<!-- <ion-input [class.readonly]="suggestion?.disabled" [readonly]="suggestion?.disabled" type="text" [(ngModel)]="suggestion.title" class="title" id="{{'titleCanned_'+suggestion._id}}" #title></ion-input> -->
|
|
9
|
+
<!-- <ion-input [class.readonly]="suggestion?.disabled" [readonly]="suggestion?.disabled" type="text" [(ngModel)]="suggestion.text" class="text"></ion-input> -->
|
|
10
|
+
<ion-label [class.readonly]="suggestion?.disabled" class="title" id="{{'titleCanned_'+suggestion._id}}" #title >{{suggestion?.title}}</ion-label>
|
|
11
|
+
<ion-label [class.readonly]="suggestion?.disabled" class="text">{{suggestion?.text}}</ion-label>
|
|
12
|
+
</div>
|
|
13
|
+
</ion-item>
|
|
14
|
+
<!-- <ion-item class="canned-item add-canned-response-wpr" button="true" lines="none" (click)="onClickAddCannedResponseFN()">
|
|
15
|
+
<ion-icon class="add-canned-response-icon" name="flash-outline"></ion-icon>
|
|
16
|
+
<span class="add-canned-response-add-icon">+</span>
|
|
17
|
+
<label class="add-canned-response-label" >{{translationMap?.get('AddNewCannedResponse')}}</label>
|
|
18
|
+
</ion-item> -->
|
|
19
|
+
</div>
|
|
20
|
+
<!-- LOADER -->
|
|
21
|
+
<div class="loader" *ngIf="suggestions.length === 0">
|
|
22
|
+
<div class="box">
|
|
23
|
+
<!-- <div class="container">
|
|
24
|
+
<span class="circle" [ngStyle]="{'background-color': stylesMap?.get('themeColor')}"></span>
|
|
25
|
+
<span class="circle" [ngStyle]="{'background-color': stylesMap?.get('themeColor')}"></span>
|
|
26
|
+
<span class="circle" [ngStyle]="{'background-color': stylesMap?.get('themeColor')}"></span>
|
|
27
|
+
<span class="circle" [ngStyle]="{'background-color': stylesMap?.get('themeColor')}"></span>
|
|
28
|
+
</div> -->
|
|
29
|
+
<div class="spinner" [ngStyle]="{'border-top-color': stylesMap?.get('themeColor')}"></div>
|
|
30
|
+
<div class="label">{{translationMap.get('LABEL_LOADING')}}</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<!-- <div *ngIf="!canShowCanned">
|
|
34
|
+
|
|
35
|
+
</div> -->
|
|
36
|
+
</div>
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
.canned-list {
|
|
2
|
+
// position: absolute;
|
|
3
|
+
// bottom: 0;
|
|
4
|
+
background-color: white !important;
|
|
5
|
+
width: 100%;
|
|
6
|
+
max-height: 310px;
|
|
7
|
+
overflow-y: auto;
|
|
8
|
+
// padding: 10px 0;
|
|
9
|
+
// margin: 0;
|
|
10
|
+
margin-bottom: 1px;
|
|
11
|
+
font-size: 14px;
|
|
12
|
+
line-height: 1.42857143;
|
|
13
|
+
color: #080f1a;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
-webkit-font-smoothing: antialiased;
|
|
16
|
+
// list-style: none;
|
|
17
|
+
z-index: 999999;
|
|
18
|
+
|
|
19
|
+
&::-webkit-scrollbar {
|
|
20
|
+
width: 6px;
|
|
21
|
+
height: 8px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&::-webkit-scrollbar-track {
|
|
25
|
+
background: #f9f9f9;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&::-webkit-scrollbar-thumb {
|
|
29
|
+
background-color: #b9b9b9;
|
|
30
|
+
border-radius: 0px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
34
|
+
background-color: #727272;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.cannedContent{
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
ion-label{
|
|
43
|
+
white-space: pre-wrap;
|
|
44
|
+
word-wrap: break-word;
|
|
45
|
+
|
|
46
|
+
--padding-bottom: 0px;
|
|
47
|
+
--padding-top: 0px;
|
|
48
|
+
&.text{
|
|
49
|
+
font-style: italic;
|
|
50
|
+
margin-top: 2px;
|
|
51
|
+
}
|
|
52
|
+
&.title {
|
|
53
|
+
font-weight: 500;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
&.readonly{
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
pointer-events: none;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// .native-input[disabled] {
|
|
62
|
+
// opacity: 10 !important;
|
|
63
|
+
// cursor: pointer;
|
|
64
|
+
// }
|
|
65
|
+
// .native-textarea[disabled] {
|
|
66
|
+
// opacity: 10 !important;
|
|
67
|
+
// cursor: pointer;
|
|
68
|
+
// }
|
|
69
|
+
ion-icon {
|
|
70
|
+
zoom: 0.7;
|
|
71
|
+
color: var(--icon-color);
|
|
72
|
+
|
|
73
|
+
&:hover{
|
|
74
|
+
opacity: 0.8;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
.no-ripple {
|
|
78
|
+
--ripple-color: transparent;
|
|
79
|
+
--background-activated: transparent;
|
|
80
|
+
--background: transparent;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.border{
|
|
84
|
+
border-bottom: 1px dashed rgb(211, 219, 229) !important;
|
|
85
|
+
margin: 0px 4px
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.canned-item {
|
|
92
|
+
-webkit-tap-highlight-color: transparent;
|
|
93
|
+
font-family: Lato, sans-serif;
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
line-height: 1.42857143;
|
|
96
|
+
list-style: none;
|
|
97
|
+
box-sizing: border-box;
|
|
98
|
+
-webkit-font-smoothing: antialiased;
|
|
99
|
+
// margin: 0 10px;
|
|
100
|
+
position: relative;
|
|
101
|
+
outline: none;
|
|
102
|
+
color: #434a54;
|
|
103
|
+
// padding: 10px;
|
|
104
|
+
padding: 5px;
|
|
105
|
+
width: auto;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
// .item-inner{
|
|
108
|
+
// border: none!important;
|
|
109
|
+
// }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
ion-item {
|
|
113
|
+
--background-hover: var(--canned-hover-background) !important;
|
|
114
|
+
--color-hover: var(--canned-hover-color);
|
|
115
|
+
--background: transparent;
|
|
116
|
+
.nocannedTitle {
|
|
117
|
+
color: #f44336;
|
|
118
|
+
}
|
|
119
|
+
.no-canned-available-text {
|
|
120
|
+
color: #1877f2 !important;
|
|
121
|
+
}
|
|
122
|
+
.no-canned-available-text:hover {
|
|
123
|
+
text-decoration: underline;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.loader {
|
|
128
|
+
height: 310px;
|
|
129
|
+
|
|
130
|
+
.box{
|
|
131
|
+
top: 50%;
|
|
132
|
+
left: 50%;
|
|
133
|
+
transform: translate(-50%, -50%);
|
|
134
|
+
position: absolute;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.container{
|
|
138
|
+
height: 15px;
|
|
139
|
+
width: 105px;
|
|
140
|
+
display: flex;
|
|
141
|
+
position: relative;
|
|
142
|
+
|
|
143
|
+
.circle{
|
|
144
|
+
width: 15px;
|
|
145
|
+
height: 15px;
|
|
146
|
+
border-radius: 50%;
|
|
147
|
+
background-color: var(--basic-blue);
|
|
148
|
+
animation: move 500ms linear 0ms infinite;
|
|
149
|
+
margin-right: 30px;
|
|
150
|
+
|
|
151
|
+
&:first-child{
|
|
152
|
+
position: absolute;
|
|
153
|
+
top:0;
|
|
154
|
+
left:0;
|
|
155
|
+
animation: grow 500ms linear 0ms infinite;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&:last-child{
|
|
159
|
+
position: absolute;
|
|
160
|
+
top: 0;
|
|
161
|
+
right: 0;
|
|
162
|
+
margin-right: 0;
|
|
163
|
+
animation: grow 500ms linear 0s infinite reverse;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.spinner {
|
|
170
|
+
margin: auto;
|
|
171
|
+
border: 8px solid #EAF0F6;
|
|
172
|
+
border-radius: 50%;
|
|
173
|
+
border-top: 8px solid var(--basic-blue);
|
|
174
|
+
width: 50px;
|
|
175
|
+
height: 50px;
|
|
176
|
+
animation: spinner 1s linear infinite;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@keyframes spinner {
|
|
180
|
+
0% { transform: rotate(0deg); }
|
|
181
|
+
100% { transform: rotate(360deg); }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.label{
|
|
185
|
+
text-align: center;
|
|
186
|
+
margin-top: 10px;
|
|
187
|
+
animation: blinker 1s linear infinite;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@keyframes grow {
|
|
191
|
+
from {transform: scale(0,0); opacity: 0;}
|
|
192
|
+
to {transform: scale(1,1); opacity: 1;}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@keyframes move {
|
|
196
|
+
from {transform: translateX(0px)}
|
|
197
|
+
to {transform: translateX(45px)}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@keyframes blinker {
|
|
201
|
+
50% {
|
|
202
|
+
opacity: 0;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
2
|
+
import { IonicModule } from '@ionic/angular';
|
|
3
|
+
|
|
4
|
+
import { CopilotSuggestionsComponent } from './copilot-suggestions.component';
|
|
5
|
+
|
|
6
|
+
describe('CopilotSuggestionsComponent', () => {
|
|
7
|
+
let component: CopilotSuggestionsComponent;
|
|
8
|
+
let fixture: ComponentFixture<CopilotSuggestionsComponent>;
|
|
9
|
+
|
|
10
|
+
beforeEach(waitForAsync(() => {
|
|
11
|
+
TestBed.configureTestingModule({
|
|
12
|
+
declarations: [ CopilotSuggestionsComponent ],
|
|
13
|
+
imports: [IonicModule.forRoot()]
|
|
14
|
+
}).compileComponents();
|
|
15
|
+
|
|
16
|
+
fixture = TestBed.createComponent(CopilotSuggestionsComponent);
|
|
17
|
+
component = fixture.componentInstance;
|
|
18
|
+
fixture.detectChanges();
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
it('should create', () => {
|
|
22
|
+
expect(component).toBeTruthy();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { filter } from 'rxjs/operators';
|
|
2
|
+
import { Component, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, SimpleChange } from '@angular/core';
|
|
3
|
+
import { CopilotService } from 'src/app/services/copilot/copilot.service';
|
|
4
|
+
import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
|
|
5
|
+
import { UserModel } from 'src/chat21-core/models/user';
|
|
6
|
+
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
7
|
+
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
8
|
+
import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk-auth.service';
|
|
9
|
+
import { getProjectIdSelectedConversation } from 'src/chat21-core/utils/utils';
|
|
10
|
+
|
|
11
|
+
@Component({
|
|
12
|
+
selector: 'copilot-suggestions',
|
|
13
|
+
templateUrl: './copilot-suggestions.component.html',
|
|
14
|
+
styleUrls: ['./copilot-suggestions.component.scss'],
|
|
15
|
+
})
|
|
16
|
+
export class CopilotSuggestionsComponent implements OnInit {
|
|
17
|
+
|
|
18
|
+
// @Input() tagsCannedFilter: any = []
|
|
19
|
+
@Input() conversationWith: string;
|
|
20
|
+
@Input() conversationWithFullname: string;
|
|
21
|
+
@Input() currentString: string;
|
|
22
|
+
@Input() stylesMap: Map<string, string>;
|
|
23
|
+
@Input() translationMap: Map<string, string>;
|
|
24
|
+
@Output() onLoadedSuggestions = new EventEmitter<[any]>();
|
|
25
|
+
@Output() onClickSuggestion = new EventEmitter<any>();
|
|
26
|
+
|
|
27
|
+
public loggedUser: UserModel
|
|
28
|
+
public projectID: string;
|
|
29
|
+
|
|
30
|
+
public suggestions: any = []
|
|
31
|
+
public suggestionsCount: number
|
|
32
|
+
|
|
33
|
+
public arrowkeyLocation = -1
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
private logger: LoggerService = LoggerInstance.getInstance();
|
|
37
|
+
constructor(
|
|
38
|
+
public tiledeskAuthService: TiledeskAuthService,
|
|
39
|
+
public tiledeskService: TiledeskService,
|
|
40
|
+
public copilotService: CopilotService,
|
|
41
|
+
public el: ElementRef
|
|
42
|
+
) { }
|
|
43
|
+
|
|
44
|
+
ngOnInit() {
|
|
45
|
+
this.loggedUser = this.tiledeskAuthService.getCurrentUser()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ngOnChanges(changes: SimpleChange){
|
|
49
|
+
this.logger.debug('[COPILOT] - loadTagsCanned strSearch ', this.currentString)
|
|
50
|
+
if(changes && changes['conversationWith'] && (changes['conversationWith'].previousValue !== changes['conversationWith'].currentValue)){
|
|
51
|
+
this.projectID = getProjectIdSelectedConversation(this.conversationWith)
|
|
52
|
+
}
|
|
53
|
+
this.loadSuggestions(this.conversationWith)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
// ----------------------------------------------------------
|
|
58
|
+
// @ CANNED RESPONSES methods
|
|
59
|
+
// ----------------------------------------------------------
|
|
60
|
+
loadSuggestions(conversationWith) {
|
|
61
|
+
this.logger.log('[COPILOT] - loadTagsCanned conversationWith ', conversationWith)
|
|
62
|
+
|
|
63
|
+
if (this.projectID) {
|
|
64
|
+
this.logger.log('[COPILOT] - loadTagsCanned projectId ', this.projectID)
|
|
65
|
+
this.getAndShowSuggestions(this.projectID)
|
|
66
|
+
} else {
|
|
67
|
+
this.getProjectIdByConversationWith(this.conversationWith)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getProjectIdByConversationWith(conversationWith: string) {
|
|
72
|
+
const tiledeskToken = this.tiledeskAuthService.getTiledeskToken()
|
|
73
|
+
|
|
74
|
+
this.tiledeskService.getProjectIdByConvRecipient(tiledeskToken, conversationWith).subscribe((res) => {
|
|
75
|
+
this.logger.log('[COPILOT] - loadTagsCanned - GET PROJECTID BY CONV RECIPIENT RES', res)
|
|
76
|
+
if (res) {
|
|
77
|
+
const projectId = res.id_project
|
|
78
|
+
this.logger.log('[COPILOT] - loadTagsCanned - GET PROJECTID BY CONV RECIPIENT projectId ', projectId)
|
|
79
|
+
if (projectId) {
|
|
80
|
+
this.getAndShowSuggestions(projectId)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}, (error) => {
|
|
84
|
+
this.logger.error('[COPILOT] - loadTagsCanned - GET PROJECTID BY CONV RECIPIENT - ERROR ', error)
|
|
85
|
+
}, () => {
|
|
86
|
+
this.logger.log('[COPILOT] - loadTagsCanned - GET PROJECTID BY CONV RECIPIENT * COMPLETE *')
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
getAndShowSuggestions(projectId) {
|
|
92
|
+
const tiledeskToken = this.tiledeskAuthService.getTiledeskToken()
|
|
93
|
+
this.logger.log('[COPILOT] - loadTagsCanned tagsCanned.length', this.suggestions.length)
|
|
94
|
+
//if(this.tagsCanned.length <= 0 ){
|
|
95
|
+
this.suggestions = []
|
|
96
|
+
this.copilotService.getAll(tiledeskToken, projectId, this.conversationWith).subscribe((res) => {
|
|
97
|
+
this.logger.log('[COPILOT] - loadTagsCanned getCannedResponses RES', res)
|
|
98
|
+
this.suggestions = res.map(el => ({ ...el, disabled : true }))
|
|
99
|
+
this.suggestionsCount = res.length
|
|
100
|
+
this.logger.log('[COPILOT] - loadTagsCanned getCannedResponses tagsCannedCount', this.suggestions)
|
|
101
|
+
}, (error) => {
|
|
102
|
+
this.logger.error('[COPILOT] - loadTagsCanned getCannedResponses - ERROR ', error)
|
|
103
|
+
}, () => {
|
|
104
|
+
this.logger.log('[COPILOT] - loadTagsCanned getCannedResponses * COMPLETE *')
|
|
105
|
+
this.onLoadedSuggestions.emit(this.suggestions)
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
onClickSuggestionFN(suggestion, event){
|
|
111
|
+
if(!suggestion.disabled){
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
event.stopPropagation();
|
|
114
|
+
} else if(this.suggestionsCount > 0){
|
|
115
|
+
this.onClickSuggestion.emit(suggestion)
|
|
116
|
+
} else {
|
|
117
|
+
this.logger.log('[CANNED] THERE IS NOT CANNED ', suggestion.text)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@HostListener('document:keydown', ['$event'])
|
|
122
|
+
handleKeyboardEvent(event: KeyboardEvent) {
|
|
123
|
+
// this.logger.log("CONVERSATION-DETAIL handleKeyboardEvent event.key ", event);
|
|
124
|
+
|
|
125
|
+
if (this.suggestions.length > 0) {
|
|
126
|
+
if (event.key === 'ArrowDown') {
|
|
127
|
+
this.arrowkeyLocation++
|
|
128
|
+
if (this.arrowkeyLocation === this.suggestions.length) {
|
|
129
|
+
this.arrowkeyLocation--
|
|
130
|
+
}
|
|
131
|
+
// this.replaceTagInMessage(this.tagsCannedFilter[this.arrowkeyLocation])
|
|
132
|
+
} else if (event.key === 'ArrowUp') {
|
|
133
|
+
if (this.arrowkeyLocation > 0) {
|
|
134
|
+
this.arrowkeyLocation--
|
|
135
|
+
} else if (this.arrowkeyLocation < 0) {
|
|
136
|
+
this.arrowkeyLocation++
|
|
137
|
+
}
|
|
138
|
+
// this.replaceTagInMessage(this.tagsCannedFilter[this.arrowkeyLocation])
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// set the focus on current canned
|
|
142
|
+
setTimeout(() => {
|
|
143
|
+
this.el.nativeElement.querySelector('.canned-list').scrollTop = this.arrowkeyLocation * 59 // 59px is the height of the single element
|
|
144
|
+
// this.el.nativeElement.querySelector('#canned-item_'+this.arrowkeyLocation).scrollIntoView({ behavior: 'smooth' })
|
|
145
|
+
}, 0);
|
|
146
|
+
|
|
147
|
+
if (event.key === 'Enter') {
|
|
148
|
+
const canned_selected = this.suggestions[this.arrowkeyLocation]
|
|
149
|
+
this.logger.log('[CONVS-DETAIL] replaceTagInMessage canned_selected ',canned_selected)
|
|
150
|
+
if (canned_selected) {
|
|
151
|
+
this.arrowkeyLocation = -1
|
|
152
|
+
this.onClickSuggestion.emit(canned_selected)
|
|
153
|
+
// event.preventDefault();
|
|
154
|
+
// return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
}
|
|
@@ -43,6 +43,7 @@ import { ReturnReceiptComponent } from 'src/app/chatlib/conversation-detail/mess
|
|
|
43
43
|
import { OptionsComponent } from 'src/app/chatlib/conversation-detail/message/options/options.component';
|
|
44
44
|
import { UserTypingComponent } from 'src/chat21-core/utils/user-typing/user-typing.component';
|
|
45
45
|
import { AvatarProfileComponent } from 'src/app/components/utils/avatar-profile/avatar-profile.component';
|
|
46
|
+
import { CopilotSuggestionsComponent } from 'src/app/components/copilot-suggestions/copilot-suggestions.component';
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
@NgModule({
|
|
@@ -93,6 +94,7 @@ import { AvatarProfileComponent } from 'src/app/components/utils/avatar-profile/
|
|
|
93
94
|
// --------- footer --------- //
|
|
94
95
|
MessageTextAreaComponent,
|
|
95
96
|
CannedResponseComponent,
|
|
97
|
+
CopilotSuggestionsComponent,
|
|
96
98
|
|
|
97
99
|
|
|
98
100
|
TruncatePipe
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
here is ignored
|
|
62
62
|
</span>
|
|
63
63
|
|
|
64
|
-
<div class="overlay" *ngIf="!HIDE_CANNED_RESPONSES"></div>
|
|
64
|
+
<div class="overlay" *ngIf="!HIDE_CANNED_RESPONSES || SHOW_COPILOT_SUGGESTIONS"></div>
|
|
65
65
|
|
|
66
66
|
<ng-template #content_welcome>
|
|
67
67
|
<!-- <div class="messageFirst">
|
|
@@ -180,6 +180,17 @@
|
|
|
180
180
|
(onClickCanned)="replaceTagInMessage($event)"
|
|
181
181
|
(onClickAddCannedResponse)="presentCreateCannedResponseModal()">
|
|
182
182
|
</app-canned-response>
|
|
183
|
+
|
|
184
|
+
<copilot-suggestions *ngIf="SHOW_COPILOT_SUGGESTIONS"
|
|
185
|
+
id="copilot"
|
|
186
|
+
[conversationWith]="conversationWith"
|
|
187
|
+
[conversationWithFullname]="conversationWithFullname"
|
|
188
|
+
[currentString]="messageStr"
|
|
189
|
+
[stylesMap]="styleMap"
|
|
190
|
+
[translationMap]="translationsMap"
|
|
191
|
+
(onLoadedSuggestions)="onLoadedSuggestions($event)"
|
|
192
|
+
(onClickSuggestion)="replaceSuggestionInMessage($event)">
|
|
193
|
+
</copilot-suggestions>
|
|
183
194
|
|
|
184
195
|
|
|
185
196
|
<!-- <div id="canned" *ngIf="tagsCannedFilter.length > 0 && HIDE_CANNED_RESPONSES === false">
|
|
@@ -6,24 +6,15 @@ import {
|
|
|
6
6
|
AfterViewInit,
|
|
7
7
|
ViewChild,
|
|
8
8
|
ElementRef,
|
|
9
|
-
Directive,
|
|
10
9
|
HostListener,
|
|
11
|
-
ChangeDetectorRef,
|
|
12
|
-
Renderer2,
|
|
13
|
-
isDevMode
|
|
14
10
|
} from '@angular/core'
|
|
15
11
|
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'
|
|
16
12
|
import {
|
|
17
13
|
ModalController,
|
|
18
14
|
ToastController,
|
|
19
|
-
PopoverController,
|
|
20
15
|
Platform,
|
|
21
16
|
ActionSheetController,
|
|
22
|
-
NavController,
|
|
23
17
|
IonContent,
|
|
24
|
-
IonTextarea,
|
|
25
|
-
IonButton,
|
|
26
|
-
IonInput,
|
|
27
18
|
} from '@ionic/angular'
|
|
28
19
|
|
|
29
20
|
// models
|
|
@@ -56,7 +47,6 @@ import {
|
|
|
56
47
|
MESSAGE_TYPE_INFO,
|
|
57
48
|
MESSAGE_TYPE_MINE,
|
|
58
49
|
MESSAGE_TYPE_OTHERS,
|
|
59
|
-
URL_SOUND_LIST_CONVERSATION,
|
|
60
50
|
TYPE_DIRECT,
|
|
61
51
|
TYPE_MSG_EMAIL,
|
|
62
52
|
TYPE_MSG_FORM,
|
|
@@ -88,12 +78,9 @@ import { takeUntil } from 'rxjs/operators'
|
|
|
88
78
|
import { TiledeskService } from '../../services/tiledesk/tiledesk.service'
|
|
89
79
|
import { NetworkService } from '../../services/network-service/network.service'
|
|
90
80
|
import { EventsService } from '../../services/events-service'
|
|
91
|
-
import { ScrollbarThemeDirective } from 'src/app/utils/scrollbar-theme.directive'
|
|
92
81
|
import { WebsocketService } from 'src/app/services/websocket/websocket.service';
|
|
93
82
|
import { Project } from 'src/chat21-core/models/projects';
|
|
94
|
-
import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
|
|
95
83
|
import { Globals } from 'src/app/utils/globals';
|
|
96
|
-
import { TriggerEvents } from 'src/app/services/triggerEvents/triggerEvents';
|
|
97
84
|
|
|
98
85
|
@Component({
|
|
99
86
|
selector: 'app-conversation-detail',
|
|
@@ -149,6 +136,8 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
149
136
|
public HIDE_CANNED_RESPONSES: boolean = true
|
|
150
137
|
public canShowCanned: boolean = true
|
|
151
138
|
|
|
139
|
+
public SHOW_COPILOT_SUGGESTIONS: boolean = false;
|
|
140
|
+
|
|
152
141
|
public window: any = window
|
|
153
142
|
public styleMap: Map<string, string> = new Map()
|
|
154
143
|
|
|
@@ -695,7 +684,9 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
695
684
|
"WHATSAPP.LABEL_TOOLTIP",
|
|
696
685
|
"WHATSAPP.SELECT_MESSAGE_TEMPLATE",
|
|
697
686
|
"WHATSAPP.ERROR_WHATSAPP_NOT_INSTALLED",
|
|
698
|
-
"WHATSAPP.ERROR_WHATSAPP_GENERIC_ERROR"
|
|
687
|
+
"WHATSAPP.ERROR_WHATSAPP_GENERIC_ERROR",
|
|
688
|
+
|
|
689
|
+
"COPILOT.ASK_AI"
|
|
699
690
|
|
|
700
691
|
]
|
|
701
692
|
|
|
@@ -1676,6 +1667,51 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
1676
1667
|
}
|
|
1677
1668
|
}
|
|
1678
1669
|
|
|
1670
|
+
|
|
1671
|
+
/** COPILOT SUGGGESTIONS : start */
|
|
1672
|
+
onLoadedSuggestions(event){
|
|
1673
|
+
this.logger.log('[CONVS-DETAIL] onLoadedSuggestions --> ', event)
|
|
1674
|
+
if (event && event.length > 0) {
|
|
1675
|
+
// this.tagsCannedFilter = event
|
|
1676
|
+
// this.tagsCannedCount = event.length
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
replaceSuggestionInMessage(suggestion, event?) {
|
|
1681
|
+
const elTextArea = this.rowTextArea['el']
|
|
1682
|
+
const textArea = elTextArea.getElementsByTagName('ion-textarea')[0] as HTMLInputElement;
|
|
1683
|
+
// console.log('[CONVS-DETAIL] replaceTagInMessage textArea ', textArea)
|
|
1684
|
+
// console.log('[CONVS-DETAIL] replaceTagInMessage textArea value', textArea.value,)
|
|
1685
|
+
|
|
1686
|
+
// var lastChar = textArea.value.substr(-1); // Selects the last character
|
|
1687
|
+
// if (lastChar === '/') {
|
|
1688
|
+
// textArea.value = textArea.value.substring(0, textArea.value.length() - 1);
|
|
1689
|
+
// }
|
|
1690
|
+
// this.insertAtCursor(this.textArea, textArea.value)
|
|
1691
|
+
|
|
1692
|
+
this.logger.log('[CONVS-DETAIL] replaceTagInMessage canned text ', suggestion.text)
|
|
1693
|
+
|
|
1694
|
+
// replace text
|
|
1695
|
+
var strTEMP = textArea.value + ' ' + suggestion.text
|
|
1696
|
+
strTEMP = this.replacePlaceholderInCanned(strTEMP)
|
|
1697
|
+
this.logger.log('[CONVS-DETAIL] replaceTagInMessage strSearch ', strTEMP)
|
|
1698
|
+
// strTEMP = this.replacePlaceholderInCanned(strTEMP);
|
|
1699
|
+
// textArea.value = '';
|
|
1700
|
+
// that.messageString = strTEMP;
|
|
1701
|
+
textArea.value = strTEMP
|
|
1702
|
+
this.insertAtCursor(textArea, '')
|
|
1703
|
+
this.setCaretPosition(textArea)
|
|
1704
|
+
// setTimeout(() => {
|
|
1705
|
+
// // textArea.focus();
|
|
1706
|
+
// textArea.setFocus()
|
|
1707
|
+
// // this.resizeTextArea()
|
|
1708
|
+
// }, 200)
|
|
1709
|
+
this.SHOW_COPILOT_SUGGESTIONS = !this.SHOW_COPILOT_SUGGESTIONS
|
|
1710
|
+
|
|
1711
|
+
}
|
|
1712
|
+
/** COPILOT SUGGGESTIONS : end */
|
|
1713
|
+
|
|
1714
|
+
|
|
1679
1715
|
setCaretPosition(ctrl) {
|
|
1680
1716
|
ctrl.value.trim()
|
|
1681
1717
|
ctrl.setFocus()
|
|
@@ -1868,6 +1904,9 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
1868
1904
|
if (event === 'email' || event === 'templates') {
|
|
1869
1905
|
this.getLeadDetail()
|
|
1870
1906
|
}
|
|
1907
|
+
if(event === 'copilot'){
|
|
1908
|
+
this.SHOW_COPILOT_SUGGESTIONS = !this.SHOW_COPILOT_SUGGESTIONS
|
|
1909
|
+
}
|
|
1871
1910
|
}
|
|
1872
1911
|
|
|
1873
1912
|
// -------------- START SCROLL/RESIZE -------------- //
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { CopilotService } from './copilot.service';
|
|
4
|
+
|
|
5
|
+
describe('CopilotService', () => {
|
|
6
|
+
let service: CopilotService;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
TestBed.configureTestingModule({});
|
|
10
|
+
service = TestBed.inject(CopilotService);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should be created', () => {
|
|
14
|
+
expect(service).toBeTruthy();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
2
|
+
import { Injectable } from '@angular/core';
|
|
3
|
+
import { AppConfigProvider } from '../app-config';
|
|
4
|
+
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
5
|
+
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
6
|
+
import { map, filter } from 'rxjs/operators';
|
|
7
|
+
import * as uuid from 'uuid';
|
|
8
|
+
|
|
9
|
+
@Injectable({
|
|
10
|
+
providedIn: 'root'
|
|
11
|
+
})
|
|
12
|
+
export class CopilotService {
|
|
13
|
+
|
|
14
|
+
private apiUrl: string;
|
|
15
|
+
private logger: LoggerService = LoggerInstance.getInstance();
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
public http: HttpClient,
|
|
19
|
+
public appConfigProvider: AppConfigProvider
|
|
20
|
+
) {
|
|
21
|
+
this.logger.log('[COPILOT-SERVICE] HELLO !');
|
|
22
|
+
this.apiUrl = appConfigProvider.getConfig().apiUrl;
|
|
23
|
+
this.logger.log('[COPILOT-SERVICE] apiUrl ', this.apiUrl);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public getAll(token: string, projectid: string, conversWith: string) {
|
|
27
|
+
const cannedResponsesURL = this.apiUrl + projectid + "/copilot?request_id=" + conversWith;
|
|
28
|
+
this.logger.log('[COPILOT-SERVICE] getAllSuggestions - URL ', cannedResponsesURL);
|
|
29
|
+
|
|
30
|
+
const httpOptions = {
|
|
31
|
+
headers: new HttpHeaders({
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
Authorization: token
|
|
34
|
+
})
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return this.http.get(cannedResponsesURL, httpOptions).pipe(map((res: [any]) => {
|
|
38
|
+
let suggestions = res.filter(el => el !== null).map(el => ({ ...el, _id: uuid.v4()} ));
|
|
39
|
+
this.logger.log('[COPILOT-SERVICE] getCannedResponses - RES ', suggestions);
|
|
40
|
+
return suggestions
|
|
41
|
+
}))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}
|
package/src/assets/i18n/en.json
CHANGED
|
@@ -304,5 +304,8 @@
|
|
|
304
304
|
"SEND_EMAIL_ERROR":"⚠️ ATTENTION ⚠️ Error occurred while sending email. Please retry again",
|
|
305
305
|
"SUBJECT_OFFLINE_MESSAGE":"Tiledesk Offline message 💬",
|
|
306
306
|
"SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Message also sent by email 📩"
|
|
307
|
+
},
|
|
308
|
+
"COPILOT": {
|
|
309
|
+
"ASK_AI":"Ask to AI"
|
|
307
310
|
}
|
|
308
311
|
}
|
package/src/assets/i18n/it.json
CHANGED
|
@@ -304,5 +304,8 @@
|
|
|
304
304
|
"SEND_EMAIL_ERROR":"⚠️ ATTENZIONE ⚠️Si è verificato un errore durante l'invio dell'email. Si prega di riprovare",
|
|
305
305
|
"SUBJECT_OFFLINE_MESSAGE":"Messaggio offline di Tiledesk 💬",
|
|
306
306
|
"SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Messaggio inviato anche via mail 📩"
|
|
307
|
-
}
|
|
307
|
+
},
|
|
308
|
+
"COPILOT": {
|
|
309
|
+
"ASK_AI":"Chiedi all'AI"
|
|
310
|
+
}
|
|
308
311
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" height="15" width="15" fill="currentColor">
|
|
2
|
+
<path d="M8.4,2.8l-.9-2.5-.9,2.5c-.6,1.7-2,3.1-3.7,3.7l-2.5.9,2.5.9c1.7.6,3.1,2,3.7,3.7l.9,2.5.9-2.5c.6-1.7,2-3.1,3.7-3.7l2.5-.9-2.5-.9c-1.7-.6-3.1-2-3.7-3.7Z"/>
|
|
3
|
+
</svg>
|