@chat21/chat21-web-widget 5.1.26-rc1 → 5.1.27-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 +22 -0
- package/docs/changelog/this-branch.md +36 -0
- package/package.json +1 -1
- package/src/app/app.component.html +1 -1
- package/src/app/app.component.ts +67 -7
- 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 +172 -1
- 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 +15 -13
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +6 -0
- package/src/app/component/conversation-detail/conversation-header/conversation-header.component.html +4 -4
- 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/providers/global-settings.service.ts +38 -0
- package/src/app/sass/_variables.scss +1 -0
- package/src/app/utils/globals.ts +7 -1
- package/src/assets/i18n/en.json +1 -0
- package/src/assets/i18n/es.json +1 -0
- package/src/assets/i18n/fr.json +1 -0
- package/src/assets/i18n/it.json +1 -0
- package/src/launch.js +61 -6
- package/src/launch_template.js +61 -6
package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts
CHANGED
|
@@ -23,6 +23,7 @@ export class ConversationContentComponent implements OnInit {
|
|
|
23
23
|
@Input() idUserTypingNow: string;
|
|
24
24
|
@Input() nameUserTypingNow: string;
|
|
25
25
|
@Input() typingLocation: string;
|
|
26
|
+
@Input() showThinkingMessage: boolean;
|
|
26
27
|
@Input() fullscreenMode: boolean;
|
|
27
28
|
@Input() translationMap: Map< string, string>;
|
|
28
29
|
@Input() stylesMap: Map<string, string>;
|
|
@@ -224,7 +225,6 @@ export class ConversationContentComponent implements OnInit {
|
|
|
224
225
|
// return false;
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
|
|
228
228
|
hideOutsideElements(){
|
|
229
229
|
this.onMenuOptionShow.emit(false)
|
|
230
230
|
this.onEmojiiPickerShow.emit(false)
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html
CHANGED
|
@@ -14,94 +14,117 @@
|
|
|
14
14
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
17
|
+
<div class="textarea-container-wrapper" *ngIf="!hideTextAreaContent && !hideTextReply">
|
|
18
|
+
<!-- TEXTAREA + ICONS: conv active-->
|
|
19
|
+
<div class="textarea-container">
|
|
20
|
+
|
|
21
|
+
<div *ngIf="!isStopRec" class="icons-container">
|
|
22
|
+
<!-- ICON ATTACHMENT -->
|
|
23
|
+
<label *ngIf="showAttachmentFooterButton" tabindex="1502" aria-label="allegati" for="chat21-file" class="chat21-textarea-button" [class.active]="!isFilePendingToUpload && !hideTextReply" id="chat21-start-upload-doc">
|
|
24
|
+
<span class="v-align-center">
|
|
25
|
+
<svg role="img" aria-labelledby="altIconTitle" xmlns="http://www.w3.org/2000/svg" width="24px" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
26
|
+
<path d="M9.9,22.7c0,0-.1,0-.2,0-1.9.3-3.7-.2-5.2-1.4-3-2.3-3.6-6.4-1.4-9.5L9.5,2.5c.4-.5,1.1-.6,1.6-.3.5.4.6,1.1.3,1.6l-6.5,9.4c-1.4,2-1,4.8.9,6.3,1,.8,2.2,1.1,3.5.9,1.3-.2,2.4-.9,3.1-1.9l6-8.7c.9-1.2.6-3-.6-3.9-.6-.5-1.4-.6-2.1-.5-.8.1-1.4.5-1.9,1.1l-5.8,8.2c-.3.5-.2,1.1.2,1.5.2.2.5.3.8.2.3,0,.6-.2.7-.4l4.7-6.2c.4-.5,1.1-.6,1.6-.2.5.4.6,1.1.2,1.6l-4.7,6.2c-.5.7-1.4,1.2-2.3,1.3-.9.1-1.8-.2-2.5-.7-1.4-1.1-1.6-3.1-.6-4.6l5.8-8.2c.8-1.1,2-1.9,3.4-2.1,1.4-.2,2.7.1,3.8,1,2.2,1.7,2.7,4.8,1.1,7.1l-6,8.7c-1.1,1.5-2.6,2.5-4.4,2.8h0Z"/>
|
|
27
|
+
<title id="altIconTitle">{{ 'MAX_ATTACHMENT' | translate: { FILE_SIZE_LIMIT: file_size_limit } }}</title>
|
|
28
|
+
</svg>
|
|
29
|
+
|
|
30
|
+
</span>
|
|
31
|
+
<input
|
|
32
|
+
[attr.disabled] = "(isFilePendingToUpload || isConversationArchived || hideTextReply)? true : null"
|
|
33
|
+
tabindex="1503"
|
|
34
|
+
type="file"
|
|
35
|
+
aria-label="seleziona allegato"
|
|
36
|
+
[accept]="fileUploadAccept"
|
|
37
|
+
name="chat21-file"
|
|
38
|
+
id="chat21-file"
|
|
39
|
+
#chat21_file
|
|
40
|
+
class="inputfile"
|
|
41
|
+
[ngStyle]="{'display': 'block', height:'1px', width:'1px', overflow: 'hidden' }"
|
|
42
|
+
(change)="detectFiles($event)"/>
|
|
43
|
+
</label>
|
|
44
|
+
<!-- ICON EMOJII -->
|
|
45
|
+
<label *ngIf="showEmojiFooterButton" tabindex="1504" aria-label="emojii" for="chat21-emojii" class="chat21-textarea-button" [class.active]="!isFilePendingToUpload && !hideTextReply" id="chat21-emoticon-picker" (click)="onEmojiiPickerClicked()">
|
|
46
|
+
<span class="v-align-center">
|
|
47
|
+
<svg role="img" aria-labelledby="altIconTitle" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
|
|
48
|
+
<path stroke-width=".4px" stroke="currentColor" d="M12,20.8c-5.1,0-9.3-4.2-9.3-9.3S6.9,2.2,12,2.2s9.3,4.2,9.3,9.3-4.2,9.3-9.3,9.3ZM12,3.6c-4.4,0-7.9,3.6-7.9,7.9s3.6,7.9,7.9,7.9,7.9-3.6,7.9-7.9-3.6-7.9-7.9-7.9Z"/>
|
|
49
|
+
<path stroke-width=".4px" stroke="currentColor" d="M12,17.2c-2.7,0-4.3-1.9-4.6-2.3-.2-.3-.2-.7.1-1s.7-.2,1,.1c.1.2,1.4,1.8,3.5,1.8s2.2,0,3.5-1.8c.2-.3.7-.4,1-.1s.4.7.1,1c-1.7,2.2-4.1,2.3-4.6,2.3Z"/>
|
|
50
|
+
<path d="M8.7,10.9c-.9,0-1.6-.7-1.6-1.6s.7-1.6,1.6-1.6,1.6.7,1.6,1.6-.7,1.6-1.6,1.6Z"/>
|
|
51
|
+
<path d="M15.5,10.9c-.9,0-1.6-.7-1.6-1.6s.7-1.6,1.6-1.6,1.6.7,1.6,1.6-.7,1.6-1.6,1.6Z"/>
|
|
52
|
+
<title id="altIconTitle">{{ translationMap?.get('EMOJI') }}</title>
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
<!-- <path d="M0,0H20.57V20.57H0V0Z" fill="none"/>
|
|
55
|
+
<circle cx="15.02" cy="9.86" r="1.29"/>
|
|
56
|
+
<circle cx="9.02" cy="9.86" r="1.29"/>
|
|
57
|
+
<path d="M12.02,15.43c-1.27,0-2.36-.69-2.96-1.71h-1.43c.69,1.76,2.39,3,4.39,3s3.7-1.24,4.39-3h-1.43c-.6,1.02-1.69,1.71-2.96,1.71Zm0-12C7.28,3.43,3.45,7.27,3.45,12s3.83,8.57,8.56,8.57,8.58-3.84,8.58-8.57S16.75,3.43,12.01,3.43Zm0,15.43c-3.79,0-6.86-3.07-6.86-6.86s3.07-6.86,6.86-6.86,6.86,3.07,6.86,6.86-3.07,6.86-6.86,6.86Z"/> -->
|
|
58
|
+
</svg>
|
|
59
|
+
</span>
|
|
60
|
+
</label>
|
|
61
|
+
</div>
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
66
|
+
<div *ngIf="!isStopRec" class="visible-text-area" [class.hasError]="showAlertEmoji" [class.disabled] = "( isConversationArchived || hideTextReply)? true : null">
|
|
67
|
+
<!-- isFilePendingToUpload || -->
|
|
68
|
+
<textarea
|
|
69
|
+
[attr.disabled] = "(hideTextReply)? true : null"
|
|
70
|
+
[attr.placeholder] ="(footerMessagePlaceholder)? footerMessagePlaceholder : translationMap?.get('LABEL_PLACEHOLDER')"
|
|
71
|
+
start-focus-chat21-conversation-component
|
|
72
|
+
inputTextArea
|
|
73
|
+
#textbox
|
|
74
|
+
tabindex="1501"
|
|
75
|
+
aria-labelledby="altTextArea"
|
|
76
|
+
rows="1"
|
|
77
|
+
id="chat21-main-message-context"
|
|
78
|
+
class='f21textarea c21-button-clean'
|
|
79
|
+
[(ngModel)]="textInputTextArea"
|
|
80
|
+
(ngModelChange)="onTextAreaChange()"
|
|
81
|
+
(keypress)="onkeypress($event)"
|
|
82
|
+
(keydown)="onkeydown($event)"
|
|
83
|
+
(paste)="onPaste($event)">
|
|
84
|
+
</textarea>
|
|
85
|
+
|
|
86
|
+
</div>
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
<!-- ICON SEND -->
|
|
89
|
+
<div *ngIf="(textInputTextArea !== '' && !isStopRec) || !showAudioRecorderFooterButton" tabindex="-1" class="chat21-textarea-button" [class.disabled]="showAlertEmoji" [class.active]="textInputTextArea && !hideTextReply" id="chat21-button-send" (click)="onSendPressed($event)">
|
|
90
|
+
<span class="v-align-center">
|
|
91
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="24" width="24" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve" fill="currentColor">
|
|
92
|
+
<path d="M1.8,20.6V3.4l20.2,8.6L1.8,20.6ZM3.9,17.3l12.6-5.4L3.9,6.6v3.7l6.4,1.6-6.4,1.6v3.8ZM3.9,17.3V6.6v10.7Z"/>
|
|
93
|
+
</svg>
|
|
94
|
+
</span>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<!-- ICON REC -->
|
|
98
|
+
<div *ngIf="showAudioRecorderFooterButton && !textInputTextArea" tabindex="-1" class="chat21-audio-button" [class.active]="isStopRec" id="chat21-button-rec">
|
|
99
|
+
<chat-audio-recorder
|
|
100
|
+
(startRecordingEvent)="onStartRecording()"
|
|
101
|
+
(deleteRecordingEvent)="onDeleteRecording()"
|
|
102
|
+
(endRecordingEvent)="onEndRecording($event)"
|
|
103
|
+
(sendRecordingEvent)="onSendRecording($event)"
|
|
104
|
+
[stylesMap]="stylesMap">
|
|
105
|
+
</chat-audio-recorder>
|
|
106
|
+
</div>
|
|
94
107
|
</div>
|
|
95
108
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
<div class="close-chat-container" *ngIf="closeChatInConversation">
|
|
110
|
+
<button tabindex="1040" aflistconv #aflistconv class="c21-button-primary c21-close" (click)="onCloseChat($event)" [ngStyle]="{'background-color': stylesMap.get('themeColor'), 'border-color': stylesMap.get('themeColor'), 'color': stylesMap?.get('foregroundColor')}">
|
|
111
|
+
<span class="v-align-center">
|
|
112
|
+
<!-- <svg [ngStyle]="{'fill': 'yellow' }" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
|
|
113
|
+
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}"/>
|
|
114
|
+
</svg> -->
|
|
115
|
+
<svg [ngStyle]="{'stroke': stylesMap?.get('foregroundColor'), 'fill': stylesMap?.get('foregroundColor') }" role="img" id="archive" aria-labelledby="altIconTitle" class="icon-menu" xmlns="http://www.w3.org/2000/svg"
|
|
116
|
+
width="15px" height="15px" viewBox="0 0 512 512">
|
|
117
|
+
<path d="M80 152v256a40.12 40.12 0 0040 40h272a40.12 40.12 0 0040-40V152" stroke-linecap="round" stroke-linejoin="round" stroke-width="50px" fill="none"></path>
|
|
118
|
+
<rect x="48" y="64" width="416" height="80" rx="28" ry="28" stroke-linejoin="round" stroke-width="50px" fill="none" ></rect>
|
|
119
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M320 304l-64 64-64-64M256 345.89V224" stroke-width="50px" fill="none"></path>
|
|
120
|
+
<title id="altIconTitle">{{ translationMap?.get('CLOSE_CHAT') }}</title>
|
|
121
|
+
</svg>
|
|
122
|
+
</span>
|
|
123
|
+
<span class="v-align-center c21-label-button">
|
|
124
|
+
{{translationMap?.get('CLOSE_CHAT')}}
|
|
125
|
+
</span>
|
|
126
|
+
<div class="clear"></div>
|
|
127
|
+
</button>
|
|
105
128
|
</div>
|
|
106
129
|
</div>
|
|
107
130
|
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
.textarea-container-wrapper{
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 8px;
|
|
5
|
+
}
|
|
2
6
|
.textarea-container{
|
|
3
|
-
// padding: 8px 34px;
|
|
4
|
-
// padding-left: 70px;
|
|
5
|
-
// padding-right: 45px;
|
|
6
7
|
display: flex;
|
|
7
|
-
// width: 100%;
|
|
8
8
|
align-items: center;
|
|
9
9
|
justify-content: space-between;
|
|
10
10
|
gap: 8px;
|
|
11
|
+
}
|
|
12
|
+
.close-chat-container{
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
gap: 8px;
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
.c21-close{
|
|
20
|
+
height: 30px !important;
|
|
21
|
+
margin: 0px !important;
|
|
15
22
|
}
|
|
16
|
-
//if attachment icon AND emoji icon is not in DOM -> increment textarea width
|
|
17
|
-
&:has(:not(#chat21-start-upload-doc)):has(:not(#chat21-emoticon-picker)) .visible-text-area {
|
|
18
|
-
width: 90%;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
.icons-container{
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
CHANGED
|
@@ -42,6 +42,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
42
42
|
@Input() isEmojiiPickerShow: boolean;
|
|
43
43
|
@Input() footerMessagePlaceholder: string;
|
|
44
44
|
@Input() fileUploadAccept: string;
|
|
45
|
+
@Input() closeChatInConversation: boolean;
|
|
45
46
|
@Input() dropEvent: Event;
|
|
46
47
|
@Input() poweredBy: string;
|
|
47
48
|
@Input() stylesMap: Map<string, string>
|
|
@@ -52,6 +53,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
52
53
|
@Output() onChangeTextArea = new EventEmitter<any>();
|
|
53
54
|
@Output() onAttachmentFileButtonClicked = new EventEmitter<any>();
|
|
54
55
|
@Output() onNewConversationButtonClicked = new EventEmitter();
|
|
56
|
+
@Output() onCloseChatButtonClicked = new EventEmitter();
|
|
55
57
|
|
|
56
58
|
@ViewChild('chat21_file') public chat21_file: ElementRef;
|
|
57
59
|
// @ViewChild('emojii_container', {read: ViewContainerRef}) selector;
|
|
@@ -710,6 +712,10 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
710
712
|
this.onNewConversationButtonClicked.emit();
|
|
711
713
|
}
|
|
712
714
|
|
|
715
|
+
onCloseChat(event){
|
|
716
|
+
this.onCloseChatButtonClicked.emit();
|
|
717
|
+
}
|
|
718
|
+
|
|
713
719
|
// onContinueConversation(){
|
|
714
720
|
// this.hideTextAreaContent = false;
|
|
715
721
|
// this.onBackButton.emit(false)
|
package/src/app/component/conversation-detail/conversation-header/conversation-header.component.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
</button>
|
|
17
17
|
|
|
18
18
|
<!-- ICON MENU OPTION -->
|
|
19
|
-
<button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="toggleMenu()" >
|
|
19
|
+
<button *ngIf="!isMobile" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="toggleMenu()" >
|
|
20
20
|
<svg aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor') }" xmlns="http://www.w3.org/2000/svg"
|
|
21
21
|
width="24" height="24" viewBox="0 0 24 24">
|
|
22
22
|
<path fill="none" d="M0 0h24v24H0V0z" />
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
<!-- ICON MAXIMIZE -->
|
|
30
|
-
<button *ngIf="size === 'min' && !fullscreenMode" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('max')" >
|
|
30
|
+
<button *ngIf="size === 'min' && !fullscreenMode && !isMobile" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('max')" >
|
|
31
31
|
<svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor') }" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
|
|
32
32
|
width="17" height="17" viewBox="0 0 17 17">
|
|
33
33
|
<path d="M6.49001 8.30999L3.69 11.11V9.40999C3.69 8.93999 3.31 8.55999 2.84 8.55999C2.37 8.55999 1.99001 8.93999 1.99001 9.40999V14.01H6.59C7.06 14.01 7.44 13.63 7.44 13.16C7.44 12.69 7.06 12.31 6.59 12.31H4.89L7.69 9.50999L6.49001 8.30999ZM9.41 1.98999C8.94 1.98999 8.56001 2.36999 8.56001 2.83999C8.56001 3.30999 8.94 3.68999 9.41 3.68999H11.11L8.31001 6.48999L9.51 7.68999L12.31 4.88999V6.58999C12.31 7.05999 12.69 7.43999 13.16 7.43999C13.63 7.43999 14.01 7.05999 14.01 6.58999V1.98999H9.41Z"></path>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
</button>
|
|
37
37
|
|
|
38
38
|
<!-- ICON MINIMIZE -->
|
|
39
|
-
<button *ngIf="size==='top' && !fullscreenMode" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('min')" >
|
|
39
|
+
<button *ngIf="size==='top' && !fullscreenMode && !isMobile" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('min')" >
|
|
40
40
|
<svg role="img" aria-labelledby="altIconTitle" class="icon-menu" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
|
|
41
41
|
width="17" height="17" viewBox="0 0 17 17">
|
|
42
42
|
<path d="M13.59 5.31h-1.7l3.3-3.3-1.2-1.2-3.3 3.3v-1.7a.85.85 0 1 0-1.7 0v4.6h4.6a.85.85 0 1 0 0-1.7M1.57 9.84c0 .47.38.85.85.85h1.7l-3.3 3.3 1.2 1.2 3.3-3.3v1.7a.85.85 0 1 0 1.7 0v-4.6h-4.6a.85.85 0 0 0-.85.85"></path>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
</button>
|
|
46
46
|
|
|
47
47
|
<!-- ICON TOP -->
|
|
48
|
-
<button *ngIf="size==='max' && !fullscreenMode" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('top')" >
|
|
48
|
+
<button *ngIf="size==='max' && !fullscreenMode && !isMobile" [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-header-button c21-right c21-button-clean" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('top')" >
|
|
49
49
|
<svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
|
|
50
50
|
width="17" height="17" viewBox="0 0 17 17">
|
|
51
51
|
<path d="M3.7,7.6L2.5,6.4C2.2,6,2.2,5.5,2.5,5.2s0.9-0.4,1.2-0.1L7,8.4l-3.3,3.3c-0.4,0.4-0.8,0.3-1.1,0s-0.4-0.9-0.1-1.2l1.2-1.2 H1.5l0-1.7H3.7z"/>
|
package/src/app/component/conversation-detail/conversation-header/conversation-header.component.ts
CHANGED
|
@@ -21,6 +21,7 @@ export class ConversationHeaderComponent implements OnInit, OnChanges {
|
|
|
21
21
|
@Input() isTypings: boolean;
|
|
22
22
|
@Input() nameUserTypingNow: string;
|
|
23
23
|
@Input() typingLocation: string;
|
|
24
|
+
@Input() isMobile: boolean;
|
|
24
25
|
@Input() isTrascriptDownloadEnabled: boolean;
|
|
25
26
|
@Input() fullscreenMode: boolean;
|
|
26
27
|
@Input() size: 'min' | 'max' | 'top';
|
|
@@ -50,24 +50,6 @@ export class EyeeyeCatcherCardComponent implements OnInit {
|
|
|
50
50
|
this.displayEyeCatcherCardCloseBtnWrapper = 'none';
|
|
51
51
|
this.displayEyeCatcherCardCloseBtnIsMobileWrapper = 'none';
|
|
52
52
|
this.displayEyeCatcherCardCloseBtn = 'none';
|
|
53
|
-
/* EYE-CATCHER CLOSE BUTTON SWITCH */
|
|
54
|
-
this.openIfCallOutTimer();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* OPEN THE EYE-CATCHER CARD
|
|
60
|
-
* if calloutTimer >= 0
|
|
61
|
-
*/
|
|
62
|
-
private openIfCallOutTimer() {
|
|
63
|
-
const that = this;
|
|
64
|
-
const calloutTimer = this.g.calloutTimer;
|
|
65
|
-
if (calloutTimer >= 0) {
|
|
66
|
-
const waitingTime = calloutTimer * 1000;
|
|
67
|
-
setTimeout(function () {
|
|
68
|
-
that.openEyeCatcher();
|
|
69
|
-
}, waitingTime);
|
|
70
|
-
}
|
|
71
53
|
}
|
|
72
54
|
|
|
73
55
|
/**
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<div class="c21-header-button" [ngStyle]="{'display': (g.hideHeaderCloseButton)?'none':'block'}">
|
|
15
15
|
|
|
16
16
|
<!-- ICON MAXIMIZE -->
|
|
17
|
-
<div *ngIf="size === 'min' && !fullscreenMode" class="c21-size-button">
|
|
17
|
+
<div *ngIf="size === 'min' && !fullscreenMode && !g?.isMobile" class="c21-size-button">
|
|
18
18
|
<button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-close-button-body" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('max')" >
|
|
19
19
|
<svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor') }" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
|
|
20
20
|
width="17" height="17" viewBox="0 0 17 17">
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
27
|
<!-- ICON MINIMIZE -->
|
|
28
|
-
<div *ngIf="size==='top' && !fullscreenMode" class="c21-size-button">
|
|
28
|
+
<div *ngIf="size==='top' && !fullscreenMode && !g?.isMobile" class="c21-size-button">
|
|
29
29
|
<button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-close-button-body" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('min')" >
|
|
30
30
|
<svg role="img" aria-labelledby="altIconTitle" class="icon-menu" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
|
|
31
31
|
width="17" height="17" viewBox="0 0 17 17">
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
<!-- ICON TOP -->
|
|
39
|
-
<div *ngIf="size==='max' && !fullscreenMode" class="c21-size-button">
|
|
39
|
+
<div *ngIf="size==='max' && !fullscreenMode && !g?.isMobile" class="c21-size-button">
|
|
40
40
|
<button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-close-button-body" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('top')" >
|
|
41
41
|
<svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
|
|
42
42
|
width="17" height="17" viewBox="0 0 17 17">
|
|
@@ -324,11 +324,13 @@ export class GlobalSettingsService {
|
|
|
324
324
|
}
|
|
325
325
|
/** set button colors */
|
|
326
326
|
this.setButtonColors();
|
|
327
|
+
this.globals.setParameter('isMobile', detectIfIsMobile(this.globals.windowContext));
|
|
327
328
|
|
|
328
329
|
this.setVariableFromStorage(this.globals);
|
|
329
330
|
this.setVariablesFromSettings(this.globals);
|
|
330
331
|
this.setVariablesFromAttributeHtml(this.globals, this.el);
|
|
331
332
|
this.setVariablesFromUrlParameters(this.globals);
|
|
333
|
+
this.enforceMobileFullscreenPolicy(this.globals);
|
|
332
334
|
|
|
333
335
|
this.setDepartmentFromExternal();
|
|
334
336
|
/** set color with gradient from theme's colors */
|
|
@@ -340,6 +342,18 @@ export class GlobalSettingsService {
|
|
|
340
342
|
this.obsSettingsService.next(true);
|
|
341
343
|
}
|
|
342
344
|
|
|
345
|
+
/**
|
|
346
|
+
* On mobile devices we always open the widget fullscreen.
|
|
347
|
+
* This also neutralizes any legacy `size` stored from previous sessions.
|
|
348
|
+
*/
|
|
349
|
+
private enforceMobileFullscreenPolicy(globals: Globals) {
|
|
350
|
+
if (!globals || globals.isMobile !== true) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
globals.fullscreenMode = true;
|
|
354
|
+
globals.size = 'max';
|
|
355
|
+
}
|
|
356
|
+
|
|
343
357
|
private setButtonColors() {
|
|
344
358
|
this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****', this.globals);
|
|
345
359
|
const bubbleSentBackground = this.globals?.bubbleSentBackground;
|
|
@@ -464,6 +478,10 @@ export class GlobalSettingsService {
|
|
|
464
478
|
try {
|
|
465
479
|
const variables = response.project.widget;
|
|
466
480
|
if (typeof variables !== 'undefined') {
|
|
481
|
+
const hasCalloutTimer = Object.prototype.hasOwnProperty.call(variables, 'calloutTimer');
|
|
482
|
+
const hasCalloutTitle = Object.prototype.hasOwnProperty.call(variables, 'calloutTitle');
|
|
483
|
+
const hasCalloutMsg = Object.prototype.hasOwnProperty.call(variables, 'calloutMsg');
|
|
484
|
+
this.globals.hasCalloutInWidgetConfig = hasCalloutTimer || hasCalloutTitle || hasCalloutMsg;
|
|
467
485
|
for (const key of Object.keys(variables)) {
|
|
468
486
|
if (key === 'align' && variables[key] === 'left') {
|
|
469
487
|
const divWidgetContainer = globals.windowContext.document.getElementById('tiledeskdiv');
|
|
@@ -1124,6 +1142,12 @@ export class GlobalSettingsService {
|
|
|
1124
1142
|
if (TEMP !== undefined) {
|
|
1125
1143
|
globals.size = TEMP;
|
|
1126
1144
|
}
|
|
1145
|
+
|
|
1146
|
+
TEMP = tiledeskSettings['closeChatInConversation'];
|
|
1147
|
+
// this.logger.debug('[GLOBAL-SET] setVariablesFromSettings > closeChatInConversation:: ', TEMP]);
|
|
1148
|
+
if (TEMP !== undefined) {
|
|
1149
|
+
globals.closeChatInConversation = (TEMP === true) ? true : false;
|
|
1150
|
+
}
|
|
1127
1151
|
}
|
|
1128
1152
|
|
|
1129
1153
|
/**
|
|
@@ -1870,6 +1894,11 @@ export class GlobalSettingsService {
|
|
|
1870
1894
|
if (TEMP) {
|
|
1871
1895
|
globals.size = TEMP;
|
|
1872
1896
|
}
|
|
1897
|
+
|
|
1898
|
+
TEMP = getParameterByName(windowContext, 'tiledesk_closeChatInConversation');
|
|
1899
|
+
if (TEMP) {
|
|
1900
|
+
globals.closeChatInConversation = stringToBoolean(TEMP);
|
|
1901
|
+
}
|
|
1873
1902
|
|
|
1874
1903
|
}
|
|
1875
1904
|
|
|
@@ -1882,6 +1911,15 @@ export class GlobalSettingsService {
|
|
|
1882
1911
|
setVariableFromStorage(globals: Globals) {
|
|
1883
1912
|
this.logger.debug('[GLOBAL-SET] setVariableFromStorage :::::::: SET VARIABLE ---------->', Object.keys(globals));
|
|
1884
1913
|
for (const key of Object.keys(globals)) {
|
|
1914
|
+
if (globals.isMobile === true && key === 'size') {
|
|
1915
|
+
// Backward compatibility: ignore legacy stored size on mobile.
|
|
1916
|
+
try {
|
|
1917
|
+
this.appStorageService.removeItem('size');
|
|
1918
|
+
} catch (e) {
|
|
1919
|
+
this.logger.warn('[GLOBAL-SET] setVariableFromStorage > cannot remove size from storage', e);
|
|
1920
|
+
}
|
|
1921
|
+
continue;
|
|
1922
|
+
}
|
|
1885
1923
|
const val = this.appStorageService.getItem(key);
|
|
1886
1924
|
// this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals KEY ---------->', key);
|
|
1887
1925
|
// this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals VAL ---------->', val);
|
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
|
|
|
@@ -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
|
|
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",
|
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",
|
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",
|
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",
|