@chat21/chat21-web-widget 5.1.18 → 5.1.20-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.
Files changed (40) hide show
  1. package/.github/workflows/docker-community-push-latest.yml +23 -13
  2. package/.github/workflows/docker-image-tag-community-tag-push.yml +22 -12
  3. package/CHANGELOG.md +64 -2
  4. package/Dockerfile +4 -5
  5. package/angular.json +2 -1
  6. package/deploy_amazon_beta.sh +17 -7
  7. package/deploy_amazon_prod.sh +4 -4
  8. package/package.json +1 -1
  9. package/src/app/app.component.html +8 -1
  10. package/src/app/app.component.scss +60 -4
  11. package/src/app/app.component.ts +63 -28
  12. package/src/app/component/conversation-detail/conversation/conversation.component.ts +84 -10
  13. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +4 -0
  14. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +27 -1
  15. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +5 -5
  16. package/src/app/component/home-conversations/home-conversations.component.html +16 -6
  17. package/src/app/component/home-conversations/home-conversations.component.ts +29 -0
  18. package/src/app/component/launcher-button/launcher-button.component.html +1 -1
  19. package/src/app/component/launcher-button/launcher-button.component.ts +3 -2
  20. package/src/app/component/list-conversations/list-conversations.component.html +8 -3
  21. package/src/app/component/list-conversations/list-conversations.component.ts +29 -0
  22. package/src/app/component/message/html/html.component.html +5 -1
  23. package/src/app/component/message/html/html.component.scss +9 -0
  24. package/src/app/component/message/text/text.component.scss +4 -0
  25. package/src/app/pipe/marked.pipe.ts +15 -4
  26. package/src/app/providers/translator.service.ts +2 -0
  27. package/src/app/sass/normalize.scss +1 -0
  28. package/src/app/utils/globals.ts +1 -1
  29. package/src/assets/i18n/en.json +1 -0
  30. package/src/assets/i18n/es.json +1 -0
  31. package/src/assets/i18n/fr.json +1 -0
  32. package/src/assets/i18n/it.json +1 -0
  33. package/src/chat21-core/providers/abstract/upload.service.ts +1 -1
  34. package/src/chat21-core/providers/firebase/firebase-upload.service.ts +1 -1
  35. package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
  36. package/src/chat21-core/providers/native/native-upload-service.ts +76 -54
  37. package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
  38. package/src/chat21-core/utils/utils.ts +5 -2
  39. package/src/iframe-style.css +36 -12
  40. package/.vscode/settings.json +0 -3
@@ -1,7 +1,7 @@
1
1
  import { UploadService } from '../abstract/upload.service';
2
2
  import { HttpClient, HttpHeaders } from '@angular/common/http';
3
3
  import { Injectable } from '@angular/core';
4
- import { BehaviorSubject } from 'rxjs';
4
+ import { BehaviorSubject, first } from 'rxjs';
5
5
  import { UploadModel } from '../../models/upload';
6
6
  import { AppStorageService } from '../abstract/app-storage.service';
7
7
  import { LoggerService } from '../abstract/logger.service';
@@ -14,7 +14,6 @@ export class NativeUploadService extends UploadService {
14
14
  BSStateUpload: BehaviorSubject<any> = new BehaviorSubject<any>(null)
15
15
 
16
16
  private tiledeskToken: string;
17
- private URL_TILEDESK_IMAGES: string;
18
17
  private URL_TILEDESK_FILE: string;
19
18
  private logger: LoggerService = LoggerInstance.getInstance()
20
19
 
@@ -25,16 +24,15 @@ export class NativeUploadService extends UploadService {
25
24
  super();
26
25
  }
27
26
 
28
- initialize(): void {
29
- this.logger.debug('[NATIVE UPLOAD] initialize')
30
- this.URL_TILEDESK_FILE = this.getBaseUrl() + 'files'
31
- this.URL_TILEDESK_IMAGES = this.getBaseUrl() + 'images'
27
+ initialize(projectId: string): void {
28
+ this.logger.info('[NATIVE UPLOAD] initialize', this.getBaseUrl())
29
+ this.URL_TILEDESK_FILE = this.getBaseUrl() + projectId + '/files'
32
30
  this.tiledeskToken = this.appStorage.getItem('tiledeskToken')
33
31
  }
34
32
 
35
33
 
36
34
  upload(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: string}> {
37
- this.logger.debug('[NATIVE UPLOAD] - upload new image/file ... upload', upload)
35
+ this.logger.log('[NATIVE UPLOAD] - upload new image/file ... upload', upload)
38
36
  const headers = new HttpHeaders({
39
37
  Authorization: this.tiledeskToken,
40
38
  //'Content-Type': 'multipart/form-data',
@@ -44,35 +42,49 @@ export class NativeUploadService extends UploadService {
44
42
  formData.append('file', upload.file);
45
43
 
46
44
  const that = this;
47
- if ((upload.file.type.startsWith('image') && (!upload.file.type.includes('svg')))) {
48
- this.logger.debug('[NATIVE UPLOAD] - upload new image')
49
- //USE IMAGE API
50
- const url = this.URL_TILEDESK_IMAGES + '/users'
51
- return new Promise((resolve, reject) => {
52
- that.http.post(url, formData, requestOptions).subscribe(data => {
53
- const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
45
+ const url = this.URL_TILEDESK_FILE + '/chat'
46
+ return new Promise((resolve, reject) => {
47
+ that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
48
+ next: (data) => {
49
+ const downloadURL = this.getBaseUrl() + 'files' + '?path=' + data['filename'];
54
50
  resolve({downloadURL : downloadURL, src: downloadURL})
55
- // that.BSStateUpload.next({upload: upload});
56
- }, (error) => {
51
+ },
52
+ error: (error) => {
57
53
  reject(error)
58
- });
54
+ }
59
55
  });
60
- } else {
61
- this.logger.debug('[NATIVE UPLOAD] - upload new file')
62
- //USE FILE API
63
- const url = this.URL_TILEDESK_FILE + '/users'
64
- return new Promise((resolve, reject) => {
65
- that.http.post(url, formData, requestOptions).subscribe(data => {
66
- const src = this.URL_TILEDESK_FILE + '?path=' + encodeURI(data['filename']);
67
- const downloadURL = this.URL_TILEDESK_FILE + '/download' + '?path=' + encodeURI(data['filename']);
68
- resolve({downloadURL : downloadURL, src: src})
69
- // that.BSStateUpload.next({upload: upload});
70
- }, (error) => {
71
- this.logger.error('[NATIVE UPLOAD] - ERROR upload new file ', error)
72
- reject(error)
73
- });
74
- });
75
- }
56
+ });
57
+
58
+ //old_implemenation
59
+ // if ((upload.file.type.startsWith('image') && (!upload.file.type.includes('svg')))) {
60
+ // this.logger.log('[NATIVE UPLOAD] - upload new image', this.URL_TILEDESK_IMAGES)
61
+ // //USE IMAGE API
62
+ // const url = this.URL_TILEDESK_IMAGES + '/users'
63
+ // return new Promise((resolve, reject) => {
64
+ // that.http.post(url, formData, requestOptions).subscribe(data => {
65
+ // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
66
+ // resolve({downloadURL : downloadURL, src: downloadURL})
67
+ // // that.BSStateUpload.next({upload: upload});
68
+ // }, (error) => {
69
+ // reject(error)
70
+ // });
71
+ // });
72
+ // } else {
73
+ // this.logger.log('[NATIVE UPLOAD] - upload new file', this.URL_TILEDESK_FILE)
74
+ // //USE FILE API
75
+ // const url = this.URL_TILEDESK_FILE + '/users'
76
+ // return new Promise((resolve, reject) => {
77
+ // that.http.post(url, formData, requestOptions).subscribe(data => {
78
+ // const src = this.URL_TILEDESK_FILE + '?path=' + encodeURI(data['filename']);
79
+ // const downloadURL = this.URL_TILEDESK_FILE + '/download' + '?path=' + encodeURI(data['filename']);
80
+ // resolve({downloadURL : downloadURL, src: src})
81
+ // // that.BSStateUpload.next({upload: upload});
82
+ // }, (error) => {
83
+ // this.logger.error('[NATIVE UPLOAD] - ERROR upload new file ', error)
84
+ // reject(error)
85
+ // });
86
+ // });
87
+ // }
76
88
 
77
89
  }
78
90
 
@@ -88,14 +100,18 @@ export class NativeUploadService extends UploadService {
88
100
 
89
101
  // USE IMAGE API
90
102
  const that = this;
91
- const url = this.URL_TILEDESK_IMAGES + `/users/photo?force=true&user_id=${userId}`
103
+ const botId = userId?.startsWith('bot_') ? userId.substring('bot_'.length) : userId
104
+ const url = this.URL_TILEDESK_FILE + `/users/photo?bot_id=${botId}`
92
105
  return new Promise((resolve, reject) => {
93
- that.http.put(url, formData, requestOptions).subscribe(data => {
94
- const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['thumbnail'];
95
- resolve(downloadURL)
96
- // that.BSStateUpload.next({upload: upload});
97
- }, (error) => {
98
- reject(error)
106
+ that.http.put(url, formData, requestOptions).pipe(first()).subscribe({
107
+ next: (data) => {
108
+ const downloadURL = this.getBaseUrl() + 'files?path=' + data['thumbnail'];
109
+ resolve(downloadURL)
110
+ // that.BSStateUpload.next({upload: upload});
111
+ },
112
+ error: (error) => {
113
+ reject(error)
114
+ }
99
115
  });
100
116
  });
101
117
  }
@@ -110,14 +126,17 @@ export class NativeUploadService extends UploadService {
110
126
 
111
127
  //USE IMAGE API
112
128
  const that = this;
113
- const url = this.URL_TILEDESK_IMAGES + '/users' + '?path=' + path.split('path=')[1]
129
+ const url = this.URL_TILEDESK_FILE + '?path=' + path.split('path=')[1]
114
130
  return new Promise((resolve, reject) => {
115
- that.http.delete(url, requestOptions).subscribe(data => {
116
- // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
117
- resolve(true)
118
- // that.BSStateUpload.next({upload: upload});
119
- }, (error) => {
120
- reject(error)
131
+ that.http.delete(url, requestOptions).pipe(first()).subscribe({
132
+ next: (data) => {
133
+ // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
134
+ resolve(true)
135
+ // that.BSStateUpload.next({upload: upload});
136
+ },
137
+ error: (error) => {
138
+ reject(error)
139
+ }
121
140
  });
122
141
  });
123
142
  }
@@ -132,14 +151,17 @@ export class NativeUploadService extends UploadService {
132
151
 
133
152
  //USE IMAGE API
134
153
  const that = this;
135
- const url = this.URL_TILEDESK_IMAGES + '/users' + '?path=' + "uploads/users/"+ userId + "/images/photo.jpg"
154
+ const url = this.URL_TILEDESK_FILE + '?path=' + "uploads/users/"+ userId + "/images/photo.jpg"
136
155
  return new Promise((resolve, reject) => {
137
- that.http.delete(url, requestOptions).subscribe(data => {
138
- // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
139
- resolve(true)
140
- // that.BSStateUpload.next({upload: upload});
141
- }, (error) => {
142
- reject(error)
156
+ that.http.delete(url, requestOptions).pipe(first()).subscribe({
157
+ next: (data) => {
158
+ // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
159
+ resolve(true)
160
+ // that.BSStateUpload.next({upload: upload});
161
+ },
162
+ error: (error) => {
163
+ reject(error)
164
+ }
143
165
  });
144
166
  });
145
167
  }
@@ -71,7 +71,7 @@ export class TiledeskRequestsService {
71
71
 
72
72
  public getMyRequests(): Promise<{ requests: Array<any>}> {
73
73
  this.tiledeskToken = this.appStorage.getItem('tiledeskToken')
74
- const url = this.URL_TILEDESK_REQUEST + '/me?preflight=true'
74
+ const url = this.URL_TILEDESK_REQUEST + 'me?preflight=true'
75
75
  this.logger.log('[TILEDESK-SERVICE] - GET REQUEST url ', url);
76
76
  const httpOptions = {
77
77
  headers: new HttpHeaders({
@@ -773,6 +773,11 @@ export function isAllowedUrlInText(text: string, allowedUrls: string[]) {
773
773
  return nonWhitelistedDomains.length === 0;
774
774
  }
775
775
 
776
+ // function extractUrls(text: string): string[] {
777
+ // const urlRegex = /https?:\/\/[^\s]+/g;
778
+ // return text.match(urlRegex) || [];
779
+ // }
780
+
776
781
  function extractUrls(text: string): string[] {
777
782
  // Rileva URL con o senza protocollo (http/https)
778
783
  const urlRegex = /\b((https?:\/\/)?(www\.)?[a-z0-9.-]+\.[a-z]{2,})(\/[^\s]*)?/gi;
@@ -787,5 +792,3 @@ function extractUrls(text: string): string[] {
787
792
  }
788
793
 
789
794
 
790
-
791
-
@@ -13,10 +13,28 @@
13
13
  bottom: 0px;
14
14
  width: auto;
15
15
  height: auto;
16
- display: none;
16
+ display: block;
17
17
  z-index: 3000000000; /*999999*/;
18
18
  }
19
19
 
20
+ #tiledesk-container.open {
21
+ /*
22
+ Fade-in the whole container when the "open" class is added.
23
+ This avoids the initial "flash" while the widget is still small.
24
+ */
25
+ opacity: 0;
26
+ animation: tiledesk-container-fade-in 400ms ease-in both;
27
+ will-change: opacity;
28
+ }
29
+
30
+ @keyframes tiledesk-container-fade-in {
31
+ /* Stay invisible, then become visible very fast at the end */
32
+ 0% { opacity: 0; }
33
+ 80% { opacity: 0.15; }
34
+ 92% { opacity: 0.30; }
35
+ 100% { opacity: 1; }
36
+ }
37
+
20
38
  #tiledesk-container.open.overlay--popup {
21
39
  background-color: rgba(0, 0, 0, 0.4);
22
40
  position: fixed;
@@ -57,8 +75,8 @@
57
75
  margin: auto;
58
76
  top: 0;
59
77
  bottom: 0;
60
- left: 0!important;
61
- right: 0!important;
78
+ left: 0;
79
+ right: 0;
62
80
  height: 100%; /*var(--iframeMaxHeight);*/
63
81
  /* transform: translate(-50%, -50%); */
64
82
  /* transform: translate(-50%, 0%); */
@@ -66,12 +84,12 @@
66
84
  max-width: 1024px;
67
85
  max-height: 100%;
68
86
 
69
- transition:
87
+ /* transition:
70
88
  width 300ms,
71
89
  height 300ms,
72
90
  max-height 300ms,
73
91
  transform 300ms cubic-bezier(0, 1.2, 1, 1),
74
- opacity 300ms ease-out;
92
+ opacity 300ms ease-out; */
75
93
  /* per migliorare le prestazioni quando si usa transform */
76
94
  will-change: transform, opacity, width, height;
77
95
  }
@@ -130,9 +148,20 @@
130
148
  display: block;
131
149
  /*width: 376px;*/
132
150
  border-radius: 16px;
151
+ /*
152
+ Fade-in: keep content transparent while the widget grows (width/height transition
153
+ lives on #tiledeskdiv.{min-size|max-size|top-size}), then show it near full size.
154
+ */
155
+ opacity: 0;
156
+ animation: tiledesk-iframe-fade-in 220ms ease-out 140ms both;
133
157
  transition: box-shadow 0.8s ease-in;
134
158
  box-shadow: rgba(0, 0, 0, 0.16) 0px 8px 36px 0px; /*NEW GAB*/
135
159
  }
160
+
161
+ @keyframes tiledesk-iframe-fade-in {
162
+ from { opacity: 0; }
163
+ to { opacity: 1; }
164
+ }
136
165
  /*
137
166
  #tiledesk-container.open #tiledeskdiv.shadow {
138
167
  transition: box-shadow 0.8s ease-in;
@@ -140,25 +169,20 @@
140
169
  }
141
170
  */
142
171
 
143
- #tiledesk-container.open #tiledeskdiv {
144
- /* transition: box-shadow 0.8s ease-in;
145
- box-shadow: rgba(0, 0, 0, 0.16) 0px 8px 36px 0px; */
146
- }
147
-
148
172
  #tiledesk-container.closed #tiledeskiframe {
149
173
  display: block;
150
174
  box-shadow: none;
151
175
  }
152
176
 
153
177
  #tiledesk-container.open #tiledeskdiv.min-size {
154
- transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out;
178
+ /* transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out; */
155
179
  width: var(--iframeMinWidth);
156
180
  height: var(--iframeMinHeight);
157
181
  }
158
182
 
159
183
  #tiledesk-container.open #tiledeskdiv.max-size {
160
184
  /* transition: width 1s, height 1s; */
161
- transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out;
185
+ /* transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out; */
162
186
  width: var(--iframeMaxWidth);
163
187
  height: var(--iframeMaxHeight);
164
188
  }
@@ -1,3 +0,0 @@
1
- {
2
- "git.ignoreLimitWarning": true
3
- }