@chat21/chat21-web-widget 5.1.26 → 5.1.30-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/.github/workflows/docker-community-push-latest.yml +23 -13
- package/.github/workflows/docker-image-tag-community-tag-push.yml +22 -12
- package/CHANGELOG.md +97 -13
- package/Dockerfile +4 -5
- package/angular.json +2 -1
- package/deploy_amazon_beta.sh +17 -7
- package/docs/changelog/badge_Bot_Umano.md +85 -0
- package/docs/changelog/this-branch.md +36 -0
- package/package.json +1 -1
- package/src/app/app.component.html +9 -2
- package/src/app/app.component.scss +59 -0
- package/src/app/app.component.ts +144 -36
- package/src/app/component/conversation-detail/conversation/conversation.component.html +13 -2
- package/src/app/component/conversation-detail/conversation/conversation.component.scss +30 -2
- package/src/app/component/conversation-detail/conversation/conversation.component.ts +85 -5
- package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.ts +16 -3
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +12 -9
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +15 -1
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +1 -1
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +103 -80
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +40 -13
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +40 -1
- package/src/app/component/conversation-detail/conversation-header/conversation-header.component.html +3 -3
- package/src/app/component/conversation-detail/conversation-header/conversation-header.component.ts +1 -0
- package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.ts +0 -18
- package/src/app/component/home/home.component.html +3 -3
- package/src/app/component/last-message/last-message.component.ts +4 -1
- package/src/app/component/launcher-button/launcher-button.component.html +1 -1
- package/src/app/component/launcher-button/launcher-button.component.ts +3 -2
- package/src/app/providers/global-settings.service.ts +26 -0
- package/src/app/providers/translator.service.ts +2 -0
- package/src/app/sass/_variables.scss +1 -0
- package/src/app/utils/conversation-sender-classifier.ts +116 -0
- package/src/app/utils/globals.ts +33 -5
- package/src/assets/i18n/en.json +2 -0
- package/src/assets/i18n/es.json +2 -0
- package/src/assets/i18n/fr.json +2 -0
- package/src/assets/i18n/it.json +2 -0
- package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
- package/src/chat21-core/utils/utils.ts +5 -2
- package/src/iframe-style.css +5 -5
- package/deploy_amazon_prod.sh +0 -41
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- tabindex="000"-->
|
|
2
2
|
|
|
3
3
|
<button aflauncherbutton #aflauncherbutton id="c21-launcher-button" class="c21-button-clean scale-in-center"
|
|
4
|
-
*ngIf="g.
|
|
4
|
+
*ngIf="g.isOpen == false"
|
|
5
5
|
[ngClass]="{'c21-align-left' : g.align === 'left', 'c21-align-right' : g.align !== 'left'}"
|
|
6
6
|
[ngStyle]="{ 'background-color': g.baloonImage? null: g.themeColor, 'bottom': g.marginY+'px!important', 'left':(g.align==='left')?g.marginX+'px!important':'', 'right':(g.align==='right')?g.marginX+'px!important':'', 'width': g.launcherWidth, 'height': g.launcherHeight, 'border-radius': g.baloonShape}"
|
|
7
7
|
(click)="openCloseWidget()"
|
|
@@ -67,8 +67,9 @@ export class LauncherButtonComponent implements OnInit, AfterViewInit {
|
|
|
67
67
|
// this.g.isOpen = !this.g.isOpen;
|
|
68
68
|
// this.g.setIsOpen(!this.g.isOpen);
|
|
69
69
|
// this.appStorageService.setItem('isOpen', this.g.isOpen);
|
|
70
|
-
|
|
71
|
-
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
this.onButtonClicked.emit( this.g.isOpen );
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
}
|
|
@@ -324,6 +324,8 @@ export class GlobalSettingsService {
|
|
|
324
324
|
}
|
|
325
325
|
/** set button colors */
|
|
326
326
|
this.setButtonColors();
|
|
327
|
+
// Detect mobile before loading persisted values so storage policies can depend on it.
|
|
328
|
+
this.globals.setParameter('isMobile', detectIfIsMobile(this.globals.windowContext));
|
|
327
329
|
|
|
328
330
|
this.setVariableFromStorage(this.globals);
|
|
329
331
|
this.setVariablesFromSettings(this.globals);
|
|
@@ -464,6 +466,10 @@ export class GlobalSettingsService {
|
|
|
464
466
|
try {
|
|
465
467
|
const variables = response.project.widget;
|
|
466
468
|
if (typeof variables !== 'undefined') {
|
|
469
|
+
const hasCalloutTimer = Object.prototype.hasOwnProperty.call(variables, 'calloutTimer');
|
|
470
|
+
const hasCalloutTitle = Object.prototype.hasOwnProperty.call(variables, 'calloutTitle');
|
|
471
|
+
const hasCalloutMsg = Object.prototype.hasOwnProperty.call(variables, 'calloutMsg');
|
|
472
|
+
this.globals.hasCalloutInWidgetConfig = hasCalloutTimer || hasCalloutTitle || hasCalloutMsg;
|
|
467
473
|
for (const key of Object.keys(variables)) {
|
|
468
474
|
if (key === 'align' && variables[key] === 'left') {
|
|
469
475
|
const divWidgetContainer = globals.windowContext.document.getElementById('tiledeskdiv');
|
|
@@ -1124,6 +1130,12 @@ export class GlobalSettingsService {
|
|
|
1124
1130
|
if (TEMP !== undefined) {
|
|
1125
1131
|
globals.size = TEMP;
|
|
1126
1132
|
}
|
|
1133
|
+
|
|
1134
|
+
TEMP = tiledeskSettings['closeChatInConversation'];
|
|
1135
|
+
// this.logger.debug('[GLOBAL-SET] setVariablesFromSettings > closeChatInConversation:: ', TEMP]);
|
|
1136
|
+
if (TEMP !== undefined) {
|
|
1137
|
+
globals.closeChatInConversation = (TEMP === true) ? true : false;
|
|
1138
|
+
}
|
|
1127
1139
|
}
|
|
1128
1140
|
|
|
1129
1141
|
/**
|
|
@@ -1870,6 +1882,11 @@ export class GlobalSettingsService {
|
|
|
1870
1882
|
if (TEMP) {
|
|
1871
1883
|
globals.size = TEMP;
|
|
1872
1884
|
}
|
|
1885
|
+
|
|
1886
|
+
TEMP = getParameterByName(windowContext, 'tiledesk_closeChatInConversation');
|
|
1887
|
+
if (TEMP) {
|
|
1888
|
+
globals.closeChatInConversation = stringToBoolean(TEMP);
|
|
1889
|
+
}
|
|
1873
1890
|
|
|
1874
1891
|
}
|
|
1875
1892
|
|
|
@@ -1882,6 +1899,15 @@ export class GlobalSettingsService {
|
|
|
1882
1899
|
setVariableFromStorage(globals: Globals) {
|
|
1883
1900
|
this.logger.debug('[GLOBAL-SET] setVariableFromStorage :::::::: SET VARIABLE ---------->', Object.keys(globals));
|
|
1884
1901
|
for (const key of Object.keys(globals)) {
|
|
1902
|
+
if (globals.isMobile === true && key === 'size') {
|
|
1903
|
+
// On mobile we always open fullscreen, so legacy/persisted widget size must be ignored.
|
|
1904
|
+
try {
|
|
1905
|
+
this.appStorageService.removeItem('size');
|
|
1906
|
+
} catch (e) {
|
|
1907
|
+
this.logger.warn('[GLOBAL-SET] setVariableFromStorage > cannot remove size from storage', e);
|
|
1908
|
+
}
|
|
1909
|
+
continue;
|
|
1910
|
+
}
|
|
1885
1911
|
const val = this.appStorageService.getItem(key);
|
|
1886
1912
|
// this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals KEY ---------->', key);
|
|
1887
1913
|
// this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals VAL ---------->', val);
|
|
@@ -302,6 +302,7 @@ export class TranslatorService {
|
|
|
302
302
|
'CLOSED',
|
|
303
303
|
'LABEL_PREVIEW',
|
|
304
304
|
'MAX_ATTACHMENT',
|
|
305
|
+
'MAX_ATTACHMENT_ERROR',
|
|
305
306
|
'EMOJI'
|
|
306
307
|
];
|
|
307
308
|
|
|
@@ -358,6 +359,7 @@ export class TranslatorService {
|
|
|
358
359
|
globals.LABEL_PREVIEW = res['LABEL_PREVIEW']
|
|
359
360
|
globals.LABEL_ERROR_FIELD_REQUIRED= res['LABEL_ERROR_FIELD_REQUIRED']
|
|
360
361
|
globals.MAX_ATTACHMENT = res['MAX_ATTACHMENT']
|
|
362
|
+
globals.MAX_ATTACHMENT_ERROR = res['MAX_ATTACHMENT_ERROR']
|
|
361
363
|
globals.EMOJI = res['EMOJI']
|
|
362
364
|
|
|
363
365
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { MessageModel } from 'src/chat21-core/models/message';
|
|
2
|
+
|
|
3
|
+
export type SenderKind = 'bot' | 'human' | 'system' | 'unknown';
|
|
4
|
+
export type Confidence = 'high' | 'medium' | 'low';
|
|
5
|
+
|
|
6
|
+
export interface SenderClassification {
|
|
7
|
+
kind: SenderKind;
|
|
8
|
+
confidence: Confidence;
|
|
9
|
+
reasons: string[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ConversationBadgeState {
|
|
13
|
+
/** Kind of the latest server message (including system). */
|
|
14
|
+
latestServerMessageKind: SenderKind;
|
|
15
|
+
/** Kind of the latest non-system server responder, used for Bot/Umano badge. */
|
|
16
|
+
latestNonSystemResponderKind: 'bot' | 'human' | null;
|
|
17
|
+
showBadge: boolean;
|
|
18
|
+
badgeText: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function classifyMessageSender(msg: MessageModel | null | undefined): SenderClassification {
|
|
22
|
+
if (!msg) return { kind: 'unknown', confidence: 'low', reasons: ['msg=null'] };
|
|
23
|
+
|
|
24
|
+
const sender = (msg as any).sender;
|
|
25
|
+
const senderFullname = (msg as any).sender_fullname;
|
|
26
|
+
const senderFullnameLower = (senderFullname || '').toString().toLowerCase();
|
|
27
|
+
|
|
28
|
+
if (sender === 'system' || senderFullnameLower === 'system') {
|
|
29
|
+
return { kind: 'system', confidence: 'high', reasons: ['sender=system'] };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const chatbotId = (msg as any)?.attributes?.flowAttributes?.chatbot_id;
|
|
33
|
+
if (chatbotId) {
|
|
34
|
+
return { kind: 'bot', confidence: 'high', reasons: ['flowAttributes.chatbot_id'] };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (sender && String(sender).includes('bot_')) {
|
|
38
|
+
return { kind: 'bot', confidence: 'medium', reasons: ['sender includes bot_'] };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (senderFullnameLower.includes('bot')) {
|
|
42
|
+
return { kind: 'bot', confidence: 'low', reasons: ['sender_fullname includes bot'] };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { kind: 'human', confidence: 'low', reasons: ['fallback human'] };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function isHumanHandoffSystemMessage(msg: MessageModel | null | undefined, clientSenderId?: string): boolean {
|
|
49
|
+
if (!msg) return false;
|
|
50
|
+
if ((msg as any).sender !== 'system') return false;
|
|
51
|
+
|
|
52
|
+
const attrs: any = (msg as any).attributes || {};
|
|
53
|
+
const key = attrs?.messagelabel?.key;
|
|
54
|
+
const memberId = attrs?.messagelabel?.parameters?.member_id;
|
|
55
|
+
|
|
56
|
+
if (attrs?.subtype !== 'info') return false;
|
|
57
|
+
if (attrs?.updateconversation !== true) return false;
|
|
58
|
+
if (key !== 'MEMBER_JOINED_GROUP') return false;
|
|
59
|
+
if (!memberId || typeof memberId !== 'string') return false;
|
|
60
|
+
|
|
61
|
+
// Exclude system/bot/self joins.
|
|
62
|
+
if (memberId === 'system') return false;
|
|
63
|
+
if (memberId.startsWith('bot_')) return false;
|
|
64
|
+
if (clientSenderId && memberId === clientSenderId) return false;
|
|
65
|
+
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getTimestamp(msg: MessageModel | null | undefined): number {
|
|
70
|
+
const ts = msg && (msg as any).timestamp;
|
|
71
|
+
const n = ts != null ? Number(ts) : 0;
|
|
72
|
+
return Number.isFinite(n) ? n : 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function maxByTimestamp<T extends MessageModel>(items: T[]): T {
|
|
76
|
+
return items.reduce((acc, cur) => (getTimestamp(cur) >= getTimestamp(acc) ? cur : acc), items[0]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isSystemMessage(msg: MessageModel | null | undefined): boolean {
|
|
80
|
+
if (!msg) return false;
|
|
81
|
+
const sender = (msg as any).sender;
|
|
82
|
+
const senderFullname = (msg as any).sender_fullname;
|
|
83
|
+
const senderFullnameLower = (senderFullname || '').toString().toLowerCase();
|
|
84
|
+
return sender === 'system' || senderFullnameLower === 'system';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function computeConversationBadgeState(messages: MessageModel[], clientSenderId?: string): ConversationBadgeState {
|
|
88
|
+
const msgs = messages || [];
|
|
89
|
+
const serverMsgs = msgs.filter(m => !!m && (!clientSenderId || (m as any).sender !== clientSenderId));
|
|
90
|
+
|
|
91
|
+
const latestServerMsg = serverMsgs.length > 0 ? maxByTimestamp(serverMsgs) : null;
|
|
92
|
+
const latestServerMessageKind = classifyMessageSender(latestServerMsg).kind;
|
|
93
|
+
|
|
94
|
+
let latestNonSystemResponderKind: 'bot' | 'human' | null = null;
|
|
95
|
+
|
|
96
|
+
// Priority rule: if the latest server message is a system handoff to a human, force "human".
|
|
97
|
+
if (isHumanHandoffSystemMessage(latestServerMsg, clientSenderId)) {
|
|
98
|
+
latestNonSystemResponderKind = 'human';
|
|
99
|
+
} else {
|
|
100
|
+
// Otherwise, use the latest non-system server message (by timestamp) as responder.
|
|
101
|
+
const nonSystemServerMsgs = serverMsgs.filter(m => !isSystemMessage(m));
|
|
102
|
+
const latestNonSystem = nonSystemServerMsgs.length > 0 ? maxByTimestamp(nonSystemServerMsgs) : null;
|
|
103
|
+
const kind = classifyMessageSender(latestNonSystem).kind;
|
|
104
|
+
if (kind === 'bot' || kind === 'human') {
|
|
105
|
+
latestNonSystemResponderKind = kind;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
latestServerMessageKind,
|
|
111
|
+
latestNonSystemResponderKind,
|
|
112
|
+
showBadge: latestNonSystemResponderKind !== null,
|
|
113
|
+
badgeText: latestNonSystemResponderKind === 'bot' ? 'Bot' : (latestNonSystemResponderKind === 'human' ? 'Umano' : ''),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
package/src/app/utils/globals.ts
CHANGED
|
@@ -222,10 +222,13 @@ export class Globals {
|
|
|
222
222
|
|
|
223
223
|
allowedOnSpecificUrl: boolean // ******* new ********
|
|
224
224
|
allowedOnSpecificUrlList: Array<string> // ******* new ********
|
|
225
|
+
hasCalloutInWidgetConfig: boolean; // ******* new ********
|
|
225
226
|
|
|
226
227
|
fontFamilySource: string; // ******* new ********
|
|
227
228
|
|
|
228
229
|
size: 'min' | 'max' | 'top'; // ******* new ********
|
|
230
|
+
|
|
231
|
+
closeChatInConversation: boolean; // ******* new ********
|
|
229
232
|
constructor(
|
|
230
233
|
) { }
|
|
231
234
|
|
|
@@ -247,7 +250,7 @@ export class Globals {
|
|
|
247
250
|
|
|
248
251
|
// ============ BEGIN: SET EXTERNAL PARAMETERS ==============//
|
|
249
252
|
this.baseLocation = 'https://widget.tiledesk.com/v2';
|
|
250
|
-
this.autoStart =
|
|
253
|
+
this.autoStart = false;
|
|
251
254
|
/** start Authentication and startUI */
|
|
252
255
|
this.startHidden = false;
|
|
253
256
|
/** show/hide all widget -> js call: showAllWidget */
|
|
@@ -438,9 +441,12 @@ export class Globals {
|
|
|
438
441
|
this.allowedOnSpecificUrl = false
|
|
439
442
|
/** set a list of pattern url able to load the widget */
|
|
440
443
|
this.allowedOnSpecificUrlList = [];
|
|
444
|
+
/** true when server widget config has `callout` node */
|
|
445
|
+
this.hasCalloutInWidgetConfig = false;
|
|
441
446
|
/** set widget size from 3 different positions: min, max, top */
|
|
442
447
|
this.size = 'min';
|
|
443
|
-
|
|
448
|
+
/** enable to close the chat in conversation */
|
|
449
|
+
this.closeChatInConversation = false;
|
|
444
450
|
// ============ END: SET EXTERNAL PARAMETERS ==============//
|
|
445
451
|
|
|
446
452
|
|
|
@@ -610,13 +616,35 @@ export class Globals {
|
|
|
610
616
|
}
|
|
611
617
|
|
|
612
618
|
|
|
613
|
-
//
|
|
619
|
+
// On mobile, force fullscreen while open regardless of stored `size`.
|
|
614
620
|
if(isOpen && this.isMobile && divTiledeskWidget){
|
|
621
|
+
divTiledeskWidget.classList.remove('min-size')
|
|
622
|
+
divTiledeskWidget.classList.remove('max-size')
|
|
623
|
+
divTiledeskWidget.classList.remove('top-size')
|
|
624
|
+
divTiledeskWidget.classList.add('fullscreen')
|
|
625
|
+
divTiledeskWidget.style.left = '0px'
|
|
615
626
|
divTiledeskWidget.style.right = '0px'
|
|
627
|
+
divTiledeskWidget.style.top = '0px'
|
|
616
628
|
divTiledeskWidget.style.bottom = '0px'
|
|
629
|
+
divTiledeskWidget.style.width = '100%'
|
|
630
|
+
divTiledeskWidget.style.height = '100%'
|
|
631
|
+
divTiledeskWidget.style.maxWidth = 'none'
|
|
632
|
+
divTiledeskWidget.style.maxHeight = 'none'
|
|
617
633
|
} else if(!isOpen && this.isMobile && divTiledeskWidget){
|
|
618
|
-
divTiledeskWidget.
|
|
619
|
-
|
|
634
|
+
divTiledeskWidget.classList.remove('fullscreen')
|
|
635
|
+
divTiledeskWidget.style.removeProperty('top')
|
|
636
|
+
divTiledeskWidget.style.removeProperty('width')
|
|
637
|
+
divTiledeskWidget.style.removeProperty('height')
|
|
638
|
+
divTiledeskWidget.style.removeProperty('max-width')
|
|
639
|
+
divTiledeskWidget.style.removeProperty('max-height')
|
|
640
|
+
divTiledeskWidget.style.bottom = this.mobileMarginY
|
|
641
|
+
if (this.align === 'left') {
|
|
642
|
+
divTiledeskWidget.style.left = this.mobileMarginX
|
|
643
|
+
divTiledeskWidget.style.removeProperty('right')
|
|
644
|
+
} else {
|
|
645
|
+
divTiledeskWidget.style.right = this.mobileMarginX
|
|
646
|
+
divTiledeskWidget.style.removeProperty('left')
|
|
647
|
+
}
|
|
620
648
|
}
|
|
621
649
|
|
|
622
650
|
//customize position for 'tiledeskdiv' for desktop if fullscreenMode is not active
|
package/src/assets/i18n/en.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"GUEST_LABEL": "Guest",
|
|
17
17
|
"ALL_AGENTS_OFFLINE_LABEL": "All operators are offline at the moment",
|
|
18
18
|
"LABEL_LOADING": "Loading...",
|
|
19
|
+
"LABEL_THINKING": "thinking",
|
|
19
20
|
"CALLOUT_TITLE_PLACEHOLDER": "🖐 Need Help?",
|
|
20
21
|
"CALLOUT_MSG_PLACEHOLDER": "Click here and start chatting with us!",
|
|
21
22
|
"CUSTOMER_SATISFACTION": "Customer satisfaction",
|
|
@@ -96,5 +97,6 @@
|
|
|
96
97
|
"EMOJI_NOT_ELLOWED":"Emoji not allowed",
|
|
97
98
|
"DOMAIN_NOT_ALLOWED":"URL contains a non-allowed domain",
|
|
98
99
|
"MAX_ATTACHMENT": "Max allowed size {{FILE_SIZE_LIMIT}}Mb",
|
|
100
|
+
"MAX_ATTACHMENT_ERROR": "The file exceeds the maximum allowed size",
|
|
99
101
|
"EMOJI": "Emoji"
|
|
100
102
|
}
|
package/src/assets/i18n/es.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"GUEST_LABEL": "Huésped",
|
|
17
17
|
"ALL_AGENTS_OFFLINE_LABEL": "Todos los operadores están desconectados en este momento.",
|
|
18
18
|
"LABEL_LOADING": "Cargando...",
|
|
19
|
+
"LABEL_THINKING": "pensando",
|
|
19
20
|
"CALLOUT_TITLE_PLACEHOLDER": "🖐 ¿Necesitas ayuda?",
|
|
20
21
|
"CALLOUT_MSG_PLACEHOLDER": "¡Haz clic aquí y comienza a chatear con nosotros!",
|
|
21
22
|
"CUSTOMER_SATISFACTION": "La satisfacción del cliente",
|
|
@@ -96,5 +97,6 @@
|
|
|
96
97
|
"EMOJI_NOT_ELLOWED":"Emoji no permitido",
|
|
97
98
|
"DOMAIN_NOT_ALLOWED":"La URL contiene un dominio no permitido",
|
|
98
99
|
"MAX_ATTACHMENT": "Tamaño máximo permitido {{FILE_SIZE_LIMIT}}Mb",
|
|
100
|
+
"MAX_ATTACHMENT_ERROR": "El archivo supera el tamaño máximo permitido",
|
|
99
101
|
"EMOJI": "Emoji"
|
|
100
102
|
}
|
package/src/assets/i18n/fr.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"GUEST_LABEL": "Hôte",
|
|
17
17
|
"ALL_AGENTS_OFFLINE_LABEL": "Tous les opérateurs sont actuellement hors ligne",
|
|
18
18
|
"LABEL_LOADING": "Chargement en cours ...",
|
|
19
|
+
"LABEL_THINKING": "en train de reflechir",
|
|
19
20
|
"CALLOUT_TITLE_PLACEHOLDER": "🖐 Besoin d'aide?",
|
|
20
21
|
"CALLOUT_MSG_PLACEHOLDER": "Cliquez ici et commencez à discuter avec nous!",
|
|
21
22
|
"CUSTOMER_SATISFACTION": "Évaluation des services",
|
|
@@ -96,5 +97,6 @@
|
|
|
96
97
|
"EMOJI_NOT_ELLOWED":"Emoji non autorisé",
|
|
97
98
|
"DOMAIN_NOT_ALLOWED":"L'URL contient un domaine non autorisé",
|
|
98
99
|
"MAX_ATTACHMENT": "Taille maximale autorisée {{FILE_SIZE_LIMIT}}Mo",
|
|
100
|
+
"MAX_ATTACHMENT_ERROR": "Le fichier dépasse la taille maximale autorisée",
|
|
99
101
|
"EMOJI": "Emoji"
|
|
100
102
|
}
|
package/src/assets/i18n/it.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"GUEST_LABEL": "Ospite",
|
|
17
17
|
"ALL_AGENTS_OFFLINE_LABEL": "Tutti gli operatori sono offline al momento",
|
|
18
18
|
"LABEL_LOADING": "Caricamento...",
|
|
19
|
+
"LABEL_THINKING": "sto pensando",
|
|
19
20
|
"CALLOUT_TITLE_PLACEHOLDER": "🖐 Bisogno di aiuto?",
|
|
20
21
|
"CALLOUT_MSG_PLACEHOLDER": "Clicca qui e inizia a chattare con noi!",
|
|
21
22
|
"CUSTOMER_SATISFACTION": "Valutazione servizio",
|
|
@@ -94,5 +95,6 @@
|
|
|
94
95
|
"EMOJI_NOT_ELLOWED":"Emoji non consentiti",
|
|
95
96
|
"DOMAIN_NOT_ALLOWED":"L'URL contiene un dominio non consentito",
|
|
96
97
|
"MAX_ATTACHMENT": "Dimensione massima consentita {{FILE_SIZE_LIMIT}}Mb",
|
|
98
|
+
"MAX_ATTACHMENT_ERROR": "Il file supera la dimensione massima consentita",
|
|
97
99
|
"EMOJI": "Emoji"
|
|
98
100
|
}
|
|
@@ -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 + '
|
|
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
|
-
|
package/src/iframe-style.css
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
bottom: 0px;
|
|
14
14
|
width: auto;
|
|
15
15
|
height: auto;
|
|
16
|
-
display:
|
|
16
|
+
display: block;
|
|
17
17
|
z-index: 3000000000; /*999999*/;
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
max-width: 1024px;
|
|
85
85
|
max-height: 100%;
|
|
86
86
|
|
|
87
|
-
transition:
|
|
87
|
+
/* transition:
|
|
88
88
|
width 300ms,
|
|
89
89
|
height 300ms,
|
|
90
90
|
max-height 300ms,
|
|
91
91
|
transform 300ms cubic-bezier(0, 1.2, 1, 1),
|
|
92
|
-
opacity 300ms ease-out;
|
|
92
|
+
opacity 300ms ease-out; */
|
|
93
93
|
/* per migliorare le prestazioni quando si usa transform */
|
|
94
94
|
will-change: transform, opacity, width, height;
|
|
95
95
|
}
|
|
@@ -175,14 +175,14 @@
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
#tiledesk-container.open #tiledeskdiv.min-size {
|
|
178
|
-
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; */
|
|
179
179
|
width: var(--iframeMinWidth);
|
|
180
180
|
height: var(--iframeMinHeight);
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
#tiledesk-container.open #tiledeskdiv.max-size {
|
|
184
184
|
/* transition: width 1s, height 1s; */
|
|
185
|
-
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; */
|
|
186
186
|
width: var(--iframeMaxWidth);
|
|
187
187
|
height: var(--iframeMaxHeight);
|
|
188
188
|
}
|
package/deploy_amazon_prod.sh
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# npm version patch
|
|
2
|
-
version=`node -e 'console.log(require("./package.json").version)'`
|
|
3
|
-
echo "version $version"
|
|
4
|
-
|
|
5
|
-
npm i
|
|
6
|
-
|
|
7
|
-
cp src/environments/real_data/environment.prod.ts src/environments/environment.prod.ts
|
|
8
|
-
|
|
9
|
-
# --build-optimizer=false if localstorage is disabled (webview) appears https://github.com/firebase/angularfire/issues/970
|
|
10
|
-
ng build --configuration="prod" --aot=true
|
|
11
|
-
##--base-href='./v5/' --output-hashing none
|
|
12
|
-
|
|
13
|
-
### SET HASHING : START ###
|
|
14
|
-
cp ./src/launch_template.js ./dist/browser/launch.js
|
|
15
|
-
node ./src/build_launch.js
|
|
16
|
-
### SET HASHING : END ###
|
|
17
|
-
|
|
18
|
-
#### FIREBASE #####
|
|
19
|
-
# cd dist
|
|
20
|
-
# # aws s3 sync . s3://tiledesk-widget/v5/latest/
|
|
21
|
-
# aws s3 sync . s3://tiledesk-widget/v5/$version/ --cache-control max-age=300
|
|
22
|
-
# aws s3 sync . s3://tiledesk-widget/v5/ --cache-control max-age=300
|
|
23
|
-
# cd ..
|
|
24
|
-
|
|
25
|
-
# #### MQTT #####
|
|
26
|
-
cd dist/browser
|
|
27
|
-
# aws s3 sync . s3://tiledesk-widget/v5/latest/
|
|
28
|
-
aws s3 sync . s3://tiledesk-widget/v6/$version/ --cache-control max-age=86400 --exclude='launch.js' #8days
|
|
29
|
-
aws s3 sync . s3://tiledesk-widget/v6/$version/ --cache-control "no-store,no-cache,private" --exclude='*' --include='launch.js'
|
|
30
|
-
aws s3 sync . s3://tiledesk-widget/v6/ --cache-control max-age=86400 --exclude='launch.js' #8days
|
|
31
|
-
aws s3 sync . s3://tiledesk-widget/v6/ --cache-control "no-store,no-cache,private" --exclude='*' --include='launch.js'
|
|
32
|
-
cd ../..
|
|
33
|
-
|
|
34
|
-
aws cloudfront create-invalidation --distribution-id E3EJDWEHY08CZZ --paths "/*"
|
|
35
|
-
|
|
36
|
-
git restore src/environments/environment.prod.ts
|
|
37
|
-
|
|
38
|
-
echo new version deployed $version on s3://tiledesk-widget/v6
|
|
39
|
-
echo available on https://s3.eu-west-1.amazonaws.com/tiledesk-widget/v6/index.html
|
|
40
|
-
echo https://widget.tiledesk.com/v6/index.html
|
|
41
|
-
echo https://widget.tiledesk.com/v6/$version/index.html
|