@chat21/chat21-web-widget 5.1.0-rc6 → 5.1.0-rc7
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/package.json +1 -1
- package/src/app/component/conversation-detail/conversation/conversation.component.html +1 -1
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +16 -7
- package/src/app/component/message/audio/audio.component.ts +30 -16
- package/src/assets/twp/chatbot-panel.html +8 -1
- package/src/assets/twp/index-dev.html +8 -1
- package/src/assets/twp/index.html +13 -3
- package/src/chat21-core/utils/utils-message.ts +20 -0
- package/src/models/project.ts +4 -1
package/CHANGELOG.md
CHANGED
package/Dockerfile
CHANGED
|
@@ -15,7 +15,7 @@ COPY . .
|
|
|
15
15
|
|
|
16
16
|
## Build the angular app in production mode and store the artifacts in dist folder
|
|
17
17
|
|
|
18
|
-
RUN
|
|
18
|
+
RUN npx ng build --configuration="prod" --output-path=dist --base-href=./ --output-hashing=none
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
### STAGE 2: Setup ###
|
package/package.json
CHANGED
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
CHANGED
|
@@ -11,7 +11,8 @@ import { ChatManager } from 'src/chat21-core/providers/chat-manager';
|
|
|
11
11
|
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
12
12
|
import { TYPE_MSG_FILE, TYPE_MSG_IMAGE, TYPE_MSG_TEXT } from 'src/chat21-core/utils/constants';
|
|
13
13
|
import { convertColorToRGBA } from 'src/chat21-core/utils/utils';
|
|
14
|
-
import { isImage } from 'src/chat21-core/utils/utils-message';
|
|
14
|
+
import { findAndRemoveEmoji, isImage } from 'src/chat21-core/utils/utils-message';
|
|
15
|
+
import { ProjectModel } from 'src/models/project';
|
|
15
16
|
|
|
16
17
|
@Component({
|
|
17
18
|
selector: 'chat-conversation-footer',
|
|
@@ -24,7 +25,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
24
25
|
@Input() attributes: string;
|
|
25
26
|
@Input() senderId: string;
|
|
26
27
|
@Input() tenant: string;
|
|
27
|
-
@Input()
|
|
28
|
+
@Input() project: ProjectModel;
|
|
28
29
|
@Input() channelType: string;
|
|
29
30
|
@Input() userFullname: string;
|
|
30
31
|
@Input() userEmail: string;
|
|
@@ -83,8 +84,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
83
84
|
|
|
84
85
|
convertColorToRGBA = convertColorToRGBA;
|
|
85
86
|
private logger: LoggerService = LoggerInstance.getInstance()
|
|
86
|
-
constructor(
|
|
87
|
-
private chatManager: ChatManager,
|
|
87
|
+
constructor(private chatManager: ChatManager,
|
|
88
88
|
private typingService: TypingService,
|
|
89
89
|
private uploadService: UploadService) { }
|
|
90
90
|
|
|
@@ -253,7 +253,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
253
253
|
// return snapshot.ref.getDownloadURL(); // Will return a promise with the download link
|
|
254
254
|
// }).then(downloadURL => {
|
|
255
255
|
// that.logger.log('[CONV-FOOTER] AppComponent::uploadSingle:: downloadURL', downloadURL]);
|
|
256
|
-
// that.g.wdLog([`Successfully uploaded file and got download link - ${downloadURL}`]);
|
|
257
256
|
|
|
258
257
|
// metadata.src = downloadURL;
|
|
259
258
|
// let type_message = TYPE_MSG_TEXT;
|
|
@@ -321,6 +320,8 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
321
320
|
(metadata) ? metadata = metadata : metadata = '';
|
|
322
321
|
this.onEmojiiPickerShow.emit(false)
|
|
323
322
|
this.logger.log('[CONV-FOOTER] SEND MESSAGE: ', msg, type, metadata, additional_attributes);
|
|
323
|
+
|
|
324
|
+
msg = this.checkForEmojii(msg)
|
|
324
325
|
if (msg && msg.trim() !== '' || type === TYPE_MSG_IMAGE || type === TYPE_MSG_FILE ) {
|
|
325
326
|
|
|
326
327
|
// msg = htmlEntities(msg);
|
|
@@ -345,7 +346,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
345
346
|
// fine-sponziello
|
|
346
347
|
// this.conversationHandlerService = this.chatManager.getConversationHandlerByConversationId(this.conversationWith)
|
|
347
348
|
const senderId = this.senderId;
|
|
348
|
-
const projectid = this.
|
|
349
|
+
const projectid = this.project.id;
|
|
349
350
|
const channelType = this.channelType;
|
|
350
351
|
const userFullname = this.userFullname;
|
|
351
352
|
const userEmail = this.userEmail;
|
|
@@ -514,6 +515,15 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
514
515
|
//}, false);
|
|
515
516
|
}
|
|
516
517
|
|
|
518
|
+
|
|
519
|
+
checkForEmojii(text){
|
|
520
|
+
//remove emojii only if "emojii" exist and is set to false
|
|
521
|
+
if(this.project && this.project.settings?.allow_send_emoji === false){
|
|
522
|
+
return findAndRemoveEmoji(text)
|
|
523
|
+
}
|
|
524
|
+
return text
|
|
525
|
+
}
|
|
526
|
+
|
|
517
527
|
|
|
518
528
|
|
|
519
529
|
onTextAreaChange(){
|
|
@@ -632,7 +642,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
632
642
|
* @param str
|
|
633
643
|
*/
|
|
634
644
|
setWritingMessages(str) {
|
|
635
|
-
//this.messagingService.setWritingMessages(str, this.g.channelType);
|
|
636
645
|
this.typingService.setTyping(this.conversationWith, str, this.senderId, this.userFullname )
|
|
637
646
|
}
|
|
638
647
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Component, ElementRef, AfterViewInit, Input, ViewChild } from '@angular/core';
|
|
2
2
|
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
|
3
|
+
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
4
|
+
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
3
5
|
import { convertColorToRGBA } from 'src/chat21-core/utils/utils';
|
|
4
6
|
|
|
5
7
|
@Component({
|
|
@@ -26,13 +28,13 @@ export class AudioComponent implements AfterViewInit {
|
|
|
26
28
|
currentTime: number = 0;
|
|
27
29
|
isPlaying: boolean = false;
|
|
28
30
|
|
|
31
|
+
private logger: LoggerService = LoggerInstance.getInstance();
|
|
29
32
|
constructor(
|
|
30
33
|
private sanitizer: DomSanitizer,
|
|
31
34
|
private elementRef: ElementRef
|
|
32
35
|
) {}
|
|
33
36
|
|
|
34
37
|
ngAfterViewInit() {
|
|
35
|
-
console.log('stylesssss', this.stylesMap)
|
|
36
38
|
if (this.audioBlob) {
|
|
37
39
|
this.rawAudioUrl = URL.createObjectURL(this.audioBlob);
|
|
38
40
|
this.audioUrl = this.sanitizer.bypassSecurityTrustUrl(this.rawAudioUrl);
|
|
@@ -136,21 +138,33 @@ export class AudioComponent implements AfterViewInit {
|
|
|
136
138
|
return `${minutes}:${sec < 10 ? '0' + sec : sec}`;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
getAudioDuration() {
|
|
140
|
-
const audio = new Audio();
|
|
141
|
-
audio.src = this.rawAudioUrl!;
|
|
142
|
-
audio.addEventListener('loadedmetadata', () => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
});
|
|
141
|
+
async getAudioDuration() {
|
|
142
|
+
// const audio = new Audio();
|
|
143
|
+
// audio.src = this.rawAudioUrl!;
|
|
144
|
+
// audio.addEventListener('loadedmetadata', () => {
|
|
145
|
+
// if (audio.duration === Infinity) {
|
|
146
|
+
// audio.currentTime = Number.MAX_SAFE_INTEGER;
|
|
147
|
+
// audio.ontimeupdate = () => {
|
|
148
|
+
// audio.ontimeupdate = null;
|
|
149
|
+
// audio.currentTime = 0;
|
|
150
|
+
// this.audioDuration = audio.duration;
|
|
151
|
+
// };
|
|
152
|
+
// } else {
|
|
153
|
+
// this.audioDuration = audio.duration;
|
|
154
|
+
// }
|
|
155
|
+
// });
|
|
156
|
+
|
|
157
|
+
const response = await fetch(this.rawAudioUrl!);
|
|
158
|
+
this.logger.debug('getAudioDuration: response ---> ', response)
|
|
159
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
160
|
+
this.logger.debug('getAudioDuration: arrayBuffer ---> ', arrayBuffer)
|
|
161
|
+
const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
|
|
162
|
+
this.logger.debug('getAudioDuration: audioContext ---> ', audioContext)
|
|
163
|
+
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
164
|
+
this.logger.debug('getAudioDuration: audioBuffer ---> ', audioBuffer)
|
|
165
|
+
this.audioDuration = audioBuffer.duration;
|
|
166
|
+
this.logger.debug('getAudioDuration: audioDuration ---> ', this.audioDuration)
|
|
167
|
+
|
|
154
168
|
}
|
|
155
169
|
|
|
156
170
|
extractFirstColor(gradient: string): string | null {
|
|
@@ -613,7 +613,7 @@
|
|
|
613
613
|
var brandJson = JSON.parse(xhr.response)
|
|
614
614
|
if(brandJson){
|
|
615
615
|
/** TITLE AND FAVICON **/
|
|
616
|
-
brandJson['WIDGET'].META_TITLE? document.
|
|
616
|
+
brandJson['WIDGET'].META_TITLE? document.title = brandJson['WIDGET'].META_TITLE : null;
|
|
617
617
|
brandJson['WIDGET'].FAVICON_URL? document.querySelector("link[rel~='icon']").setAttribute('href', brandJson['WIDGET'].FAVICON_URL) : null;
|
|
618
618
|
/** FOOTER-LOGO **/
|
|
619
619
|
brandJson['COMMON'].COMPANY_LOGO? document.getElementById('footer-logo').src = brandJson['COMMON'].COMPANY_LOGO : null;
|
|
@@ -624,6 +624,13 @@
|
|
|
624
624
|
brandJson['COMMON'].BRAND_PRIMARY_COLOR? document.body.style.setProperty('--base-company-logo', brandJson['COMMON'].BRAND_PRIMARY_COLOR): null;
|
|
625
625
|
/** IFRAME TITLE**/
|
|
626
626
|
brandJson['COMMON'].COMPANY_NAME? document.getElementById('tiledeskiframe').title = brandJson['COMMON'].COMPANY_NAME + ' Widget' : null;
|
|
627
|
+
/** META sharing ELEMENTS */
|
|
628
|
+
if(brandJson['WIDGET'].META_SHARE_INFO && Object.keys(brandJson['WIDGET'].META_SHARE_INFO).length > 0){
|
|
629
|
+
Object.keys(brandJson['WIDGET'].META_SHARE_INFO).forEach(key => {
|
|
630
|
+
var meta = document.querySelector("meta[property^='og:"+key.toLowerCase()+"']");
|
|
631
|
+
meta.setAttribute('content', brandJson['WIDGET'].META_SHARE_INFO[key])
|
|
632
|
+
})
|
|
633
|
+
}
|
|
627
634
|
}
|
|
628
635
|
}
|
|
629
636
|
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
var brandJson = JSON.parse(xhr.response)
|
|
720
720
|
if(brandJson){
|
|
721
721
|
/** TITLE AND FAVICON **/
|
|
722
|
-
brandJson['WIDGET'].META_TITLE? document.
|
|
722
|
+
brandJson['WIDGET'].META_TITLE? document.title = brandJson['WIDGET'].META_TITLE : null;
|
|
723
723
|
brandJson['WIDGET'].FAVICON_URL? document.querySelector("link[rel~='icon']").setAttribute('href', brandJson['WIDGET'].FAVICON_URL) : null;
|
|
724
724
|
/** FOOTER-LOGO **/
|
|
725
725
|
brandJson['COMMON'].COMPANY_LOGO? document.getElementById('footer-logo').src = brandJson['COMMON'].COMPANY_LOGO : null;
|
|
@@ -737,6 +737,13 @@
|
|
|
737
737
|
}
|
|
738
738
|
/** IFRAME TITLE**/
|
|
739
739
|
brandJson['COMMON'].COMPANY_LOGO? document.getElementById('tiledeskiframe').title = brandJson['COMMON'].COMPANY_NAME + ' Widget' : null;
|
|
740
|
+
/** META sharing ELEMENTS */
|
|
741
|
+
if(brandJson['WIDGET'].META_SHARE_INFO && Object.keys(brandJson['WIDGET'].META_SHARE_INFO).length > 0){
|
|
742
|
+
Object.keys(brandJson['WIDGET'].META_SHARE_INFO).forEach(key => {
|
|
743
|
+
var meta = document.querySelector("meta[property^='og:"+key.toLowerCase()+"']");
|
|
744
|
+
meta.setAttribute('content', brandJson['WIDGET'].META_SHARE_INFO[key])
|
|
745
|
+
})
|
|
746
|
+
}
|
|
740
747
|
}
|
|
741
748
|
}
|
|
742
749
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8">
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
8
8
|
|
|
9
|
-
<title>Widget test page
|
|
9
|
+
<title>Widget test page</title>
|
|
10
10
|
<style>
|
|
11
11
|
|
|
12
12
|
@-moz-keyframes blink {0%{opacity:1;} 50%{opacity:0;} 100%{opacity:1;}} /* Firefox */
|
|
@@ -295,7 +295,10 @@
|
|
|
295
295
|
window.Tiledesk('onBeforeInit', function(event_data) {
|
|
296
296
|
console.log("onBeforeInit Tiledesk FN", event_data);
|
|
297
297
|
|
|
298
|
-
|
|
298
|
+
if(event_data.detail.appConfigs.brandSrc){
|
|
299
|
+
getBrandResources(event_data.detail.appConfigs.brandSrc)
|
|
300
|
+
}
|
|
301
|
+
// var brandSrc = event_data.detail.appConfigs.brandSrc? : null;
|
|
299
302
|
|
|
300
303
|
setTimeout(() => {
|
|
301
304
|
if(event_data && event_data.detail && event_data.detail.appConfigs){
|
|
@@ -408,7 +411,7 @@
|
|
|
408
411
|
var brandJson = JSON.parse(xhr.response)
|
|
409
412
|
if(brandJson){
|
|
410
413
|
/** TITLE AND FAVICON **/
|
|
411
|
-
brandJson['WIDGET'].META_TITLE? document.
|
|
414
|
+
brandJson['WIDGET'].META_TITLE? document.title = brandJson['WIDGET'].META_TITLE : null;
|
|
412
415
|
brandJson['WIDGET'].FAVICON_URL? document.querySelector("link[rel~='icon']").setAttribute('href', brandJson['WIDGET'].FAVICON_URL) : null;
|
|
413
416
|
/** FOOTER-LOGO **/
|
|
414
417
|
brandJson['COMMON'].COMPANY_LOGO? document.getElementById('footer-logo').src = brandJson['COMMON'].COMPANY_LOGO : null;
|
|
@@ -421,6 +424,13 @@
|
|
|
421
424
|
brandJson['COMMON'].DOCS? null: document.getElementById('share').style.display = 'none'
|
|
422
425
|
/** IFRAME TITLE**/
|
|
423
426
|
brandJson['COMMON'].COMPANY_LOGO? document.getElementById('tiledeskiframe').title = brandJson['COMMON'].COMPANY_NAME + ' Widget' : null;
|
|
427
|
+
/** META sharing ELEMENTS */
|
|
428
|
+
if(brandJson['WIDGET'].META_SHARE_INFO && Object.keys(brandJson['WIDGET'].META_SHARE_INFO).length > 0){
|
|
429
|
+
Object.keys(brandJson['WIDGET'].META_SHARE_INFO).forEach(key => {
|
|
430
|
+
var meta = document.querySelector("meta[property^='og:"+key.toLowerCase()+"']");
|
|
431
|
+
meta.setAttribute('content', brandJson['WIDGET'].META_SHARE_INFO[key])
|
|
432
|
+
})
|
|
433
|
+
}
|
|
424
434
|
}
|
|
425
435
|
|
|
426
436
|
}
|
|
@@ -194,9 +194,13 @@ export function isEmojii(message: any){
|
|
|
194
194
|
// https://localcoder.org/javascript-detect-if-a-string-contains-only-unicode-emojis
|
|
195
195
|
try {
|
|
196
196
|
if(!message) return false;
|
|
197
|
+
// Removes all characters that are NOT emojis (unicode > \u1eeff)
|
|
197
198
|
const onlyEmojis = message.replace(new RegExp('[\u0000-\u1eeff]', 'g'), '')
|
|
199
|
+
// Removes spaces, line breaks, and carriage returns from the string
|
|
198
200
|
const visibleChars = message.replace(new RegExp('[\n\r\s]+|( )+', 'g'), '')
|
|
201
|
+
// Removes Chinese characters from the string
|
|
199
202
|
const chineseChars = message.replace(new RegExp('[\u4e00-\u9fa5]', 'g'), '')
|
|
203
|
+
|
|
200
204
|
if(onlyEmojis === '' || visibleChars == '' || chineseChars=='') return false
|
|
201
205
|
return (onlyEmojis.length === visibleChars.length && onlyEmojis.length <= 2)
|
|
202
206
|
} catch(e) {
|
|
@@ -204,6 +208,22 @@ export function isEmojii(message: any){
|
|
|
204
208
|
}
|
|
205
209
|
}
|
|
206
210
|
|
|
211
|
+
export function findAndRemoveEmoji(text): string{
|
|
212
|
+
|
|
213
|
+
if (!text) return text;
|
|
214
|
+
|
|
215
|
+
// Regex to find most unicode emojis
|
|
216
|
+
// Source: https://thekevinscott.com/emojis-in-javascript/
|
|
217
|
+
const emojiRegex = /([\u2700-\u27BF]|[\uE000-\uF8FF]|[\uD83C-\uDBFF][\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83D[\uDE00-\uDE4F])/g;
|
|
218
|
+
|
|
219
|
+
// Removes all found emojis
|
|
220
|
+
text = text.replace(emojiRegex, '');
|
|
221
|
+
|
|
222
|
+
// Removes any multiple spaces left by the removal of emojis
|
|
223
|
+
text = text.replace(/\s{2,}/g, ' ').trim();
|
|
224
|
+
return text
|
|
225
|
+
}
|
|
226
|
+
|
|
207
227
|
export function isJustRecived(startedAt, time) {
|
|
208
228
|
if (time > startedAt) {
|
|
209
229
|
return true;
|
package/src/models/project.ts
CHANGED
|
@@ -24,7 +24,8 @@ export class ProjectModel {
|
|
|
24
24
|
public color?: string,
|
|
25
25
|
public welcomeTitle?: string,
|
|
26
26
|
public welcomeMsg?: string,
|
|
27
|
-
public attributes?: IRules
|
|
27
|
+
public attributes?: IRules,
|
|
28
|
+
public settings?:{ [key: string]: any },
|
|
28
29
|
) { }
|
|
29
30
|
|
|
30
31
|
initialize (
|
|
@@ -43,6 +44,7 @@ export class ProjectModel {
|
|
|
43
44
|
trialDaysLeft?: number,
|
|
44
45
|
trialExpired?: boolean,
|
|
45
46
|
updatedAt?: string,
|
|
47
|
+
settings?: { [key: string]: any },
|
|
46
48
|
versions?: string,
|
|
47
49
|
) {
|
|
48
50
|
this.id = id;
|
|
@@ -60,6 +62,7 @@ export class ProjectModel {
|
|
|
60
62
|
this.trialDaysLeft = trialDaysLeft;
|
|
61
63
|
this.trialExpired = trialExpired;
|
|
62
64
|
this.updatedAt = updatedAt;
|
|
65
|
+
this.settings = settings;
|
|
63
66
|
this.versions = versions;
|
|
64
67
|
}
|
|
65
68
|
|