@chat21/chat21-web-widget 5.1.12-ar → 5.1.14
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 +13 -23
- package/.github/workflows/docker-image-tag-community-tag-push.yml +12 -22
- package/CHANGELOG.md +10 -20
- package/Dockerfile +5 -4
- package/angular.json +1 -2
- package/deploy_prod.sh +0 -3
- package/package.json +1 -1
- package/src/app/app.component.html +1 -8
- package/src/app/app.component.scss +0 -59
- package/src/app/app.component.ts +32 -72
- package/src/app/app.module.ts +15 -12
- package/src/app/component/conversation-detail/conversation/conversation.component.ts +6 -19
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +0 -25
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +0 -1
- package/src/app/component/launcher-button/launcher-button.component.html +1 -1
- package/src/app/component/launcher-button/launcher-button.component.ts +2 -3
- package/src/app/component/message/buttons/action-button/action-button.component.ts +3 -1
- package/src/app/providers/global-settings.service.ts +15 -3
- package/src/app/providers/translator.service.ts +0 -2
- package/src/app/utils/globals.ts +1 -1
- package/src/assets/i18n/en.json +0 -1
- package/src/assets/i18n/es.json +0 -1
- package/src/assets/i18n/fr.json +0 -1
- package/src/assets/i18n/it.json +0 -1
- package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
- package/src/chat21-core/utils/utils.ts +111 -5
- package/src/iframe-style.css +5 -5
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
name: Docker Image Community latest CI
|
|
2
2
|
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
5
|
branches: [ master ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ master ]
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
push_to_registry:
|
|
@@ -12,22 +12,12 @@ jobs:
|
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
|
|
14
14
|
steps:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
25
|
-
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
26
|
-
|
|
27
|
-
- name: Build and push multiarch Docker image
|
|
28
|
-
uses: docker/build-push-action@v3
|
|
29
|
-
with:
|
|
30
|
-
context: .
|
|
31
|
-
push: true
|
|
32
|
-
platforms: linux/amd64,linux/arm64
|
|
33
|
-
tags: chat21/chat21-web-widget:latest
|
|
15
|
+
- uses: actions/checkout@v2
|
|
16
|
+
name: Check out the repo
|
|
17
|
+
- uses: docker/build-push-action@v1
|
|
18
|
+
with:
|
|
19
|
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
20
|
+
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
21
|
+
repository: chat21/chat21-web-widget
|
|
22
|
+
push: true
|
|
23
|
+
tags: latest
|
|
@@ -3,30 +3,20 @@ name: Publish Docker Community image tags
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
tags:
|
|
6
|
-
- '**'
|
|
7
|
-
|
|
6
|
+
- '**' # Push events to every tag including hierarchical tags like
|
|
8
7
|
jobs:
|
|
8
|
+
|
|
9
9
|
push_to_registry:
|
|
10
10
|
name: Push Docker image to Docker Hub
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
12
|
steps:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
25
|
-
|
|
26
|
-
- name: Build and push multiarch Docker image
|
|
27
|
-
uses: docker/build-push-action@v3
|
|
28
|
-
with:
|
|
29
|
-
context: .
|
|
30
|
-
push: true
|
|
31
|
-
platforms: linux/amd64,linux/arm64
|
|
32
|
-
tags: chat21/chat21-web-widget:${{ github.ref_name }}
|
|
13
|
+
- name: Check out the repo
|
|
14
|
+
uses: actions/checkout@v2
|
|
15
|
+
- name: Push to Docker Hub
|
|
16
|
+
uses: docker/build-push-action@v1
|
|
17
|
+
with:
|
|
18
|
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
19
|
+
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
20
|
+
repository: chat21/chat21-web-widget
|
|
21
|
+
push: true
|
|
22
|
+
tag_with_ref: true
|
package/CHANGELOG.md
CHANGED
|
@@ -6,32 +6,20 @@
|
|
|
6
6
|
### **Copyrigth**:
|
|
7
7
|
*Tiledesk SRL*
|
|
8
8
|
|
|
9
|
-
# 5.1.12-ar
|
|
10
|
-
- **bug-fixed**: check showEmojiFooterButton to enable/disable emojii
|
|
11
|
-
- **bug-fixed**: markdown is fired as an emojii and blocked by isEmojii check fn
|
|
12
|
-
|
|
13
|
-
# 5.1.11
|
|
14
|
-
- **bug-fixed**: departmentId and departmentName is incorrect in attributes
|
|
15
|
-
|
|
16
|
-
# 5.1.10
|
|
17
|
-
- **changed**: Force authentication if ageChangeVisibilityDesktop or PageChangeVisibilityMobile is OPEN
|
|
18
9
|
|
|
19
|
-
# 5.1.
|
|
20
|
-
- **
|
|
21
|
-
- **added**: Added the open widget loading spinner
|
|
22
|
-
- **changed**: Load the widget without authentication and display the speech bubble
|
|
10
|
+
# 5.1.14
|
|
11
|
+
- **bug-fixed**: stopped loading local language json file
|
|
23
12
|
|
|
24
|
-
# 5.1.
|
|
25
|
-
|
|
26
|
-
# 5.1.7-rc8
|
|
13
|
+
# 5.1.13
|
|
14
|
+
- **bug-fixed**: set default widget size
|
|
27
15
|
- **changed**: Updated the translations of the tooltips in the footer-component
|
|
28
16
|
- **changed**: Refactored the network-offline component and made it generic for displaying errors (now error-alert.component)
|
|
17
|
+
- **bug-fixed**: set the color of the buttons with visibility control to the font color (setButtonColors function)
|
|
29
18
|
|
|
30
|
-
# 5.1.
|
|
31
|
-
- **bug-fixed**:
|
|
19
|
+
# 5.1.12
|
|
20
|
+
- **bug-fixed**: check showEmojiFooterButton to enable/disable emojii
|
|
21
|
+
- **bug-fixed**: markdown is fired as an emojii and blocked by isEmojii check fn
|
|
32
22
|
|
|
33
|
-
# 5.1.7-rc6
|
|
34
|
-
- **added**: Added MAX_ATTACHMENT_ERROR error message when uploading a file larger than 10 MB
|
|
35
23
|
|
|
36
24
|
# 5.1.7-rc5
|
|
37
25
|
- **bug-fixed**: bug fixed BUTTON STYLES
|
|
@@ -53,6 +41,8 @@
|
|
|
53
41
|
- **bug-fixed**: bug fixed min-height message-receive
|
|
54
42
|
- **bug-fixed**: bug-fixed css footer
|
|
55
43
|
|
|
44
|
+
# 5.1.7
|
|
45
|
+
|
|
56
46
|
# 5.1.6
|
|
57
47
|
|
|
58
48
|
# 5.1.5
|
package/Dockerfile
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
### STAGE 1: Build ###
|
|
2
2
|
|
|
3
3
|
# We label our stage as ‘builder’
|
|
4
|
-
FROM
|
|
4
|
+
FROM node:20.12.2-alpine3.19 as builder
|
|
5
5
|
|
|
6
6
|
COPY package.json package-lock.json ./
|
|
7
7
|
|
|
@@ -15,11 +15,12 @@ COPY . .
|
|
|
15
15
|
|
|
16
16
|
## Build the angular app in production mode and store the artifacts in dist folder
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
RUN npx ng build --configuration="prod" --output-path=dist --base-href=./ --output-hashing=none
|
|
20
19
|
|
|
20
|
+
|
|
21
21
|
### STAGE 2: Setup ###
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
FROM nginx:1.14.1-alpine
|
|
23
24
|
|
|
24
25
|
## Copy our default nginx config
|
|
25
26
|
COPY nginx.conf /etc/nginx/nginx.conf
|
|
@@ -32,4 +33,4 @@ COPY --from=builder /ng-app/dist/browser /usr/share/nginx/html
|
|
|
32
33
|
|
|
33
34
|
RUN echo "Chat21 Web Widget Started!!"
|
|
34
35
|
|
|
35
|
-
CMD ["/bin/sh",
|
|
36
|
+
CMD ["/bin/sh", "-c", "envsubst < /usr/share/nginx/html/widget-config-template.json > /usr/share/nginx/html/widget-config.json && exec nginx -g 'daemon off;'"]
|
package/angular.json
CHANGED
|
@@ -44,8 +44,7 @@
|
|
|
44
44
|
"src/environments/real_data/widget-config-docker.json",
|
|
45
45
|
"src/environments/real_data/widget-config-native-mqtt.json",
|
|
46
46
|
"src/environments/real_data/widget-config-native-prod.json",
|
|
47
|
-
"src/environments/real_data/widget-config-aws-stage.json"
|
|
48
|
-
"src/environments/real_data/widget-config-aws-aruba.json"
|
|
47
|
+
"src/environments/real_data/widget-config-aws-stage.json"
|
|
49
48
|
],
|
|
50
49
|
"styles": [
|
|
51
50
|
"src/app/sass/styles.scss"
|
package/deploy_prod.sh
CHANGED
|
@@ -8,9 +8,6 @@ echo "CREATING TAG ON GIT FOR version: $version"
|
|
|
8
8
|
current_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
9
9
|
remote_name=$(git config --get branch.$current_branch.remote)
|
|
10
10
|
|
|
11
|
-
# Update dependencies
|
|
12
|
-
npm i
|
|
13
|
-
|
|
14
11
|
## Push commit to git
|
|
15
12
|
git add .
|
|
16
13
|
git commit -m "version added: ### $version"
|
package/package.json
CHANGED
|
@@ -145,12 +145,5 @@
|
|
|
145
145
|
<chat-launcher-button *ngIf="isInitialized"
|
|
146
146
|
(onButtonClicked)="onOpenCloseWidget($event)">
|
|
147
147
|
</chat-launcher-button>
|
|
148
|
-
|
|
149
|
-
<!-- Loading Spinner -->
|
|
150
|
-
<div *ngIf="loading" class="tiledesk-loading-overlay">
|
|
151
|
-
<div class="tiledesk-loading-spinner">
|
|
152
|
-
<div class="spinner-circle"></div>
|
|
153
|
-
<div class="loading-text">{{ translationMap.get('LABEL_LOADING') }}</div>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
148
|
+
|
|
156
149
|
</div>
|
|
@@ -764,63 +764,4 @@ chat-root {
|
|
|
764
764
|
}
|
|
765
765
|
}
|
|
766
766
|
|
|
767
|
-
// ========= BEGIN: LOADING SPINNER ========= //
|
|
768
|
-
.tiledesk-loading-overlay {
|
|
769
|
-
position: absolute;
|
|
770
|
-
top: 0;
|
|
771
|
-
left: 0;
|
|
772
|
-
width: 100%;
|
|
773
|
-
height: 100%;
|
|
774
|
-
background-color: rgba(248, 249, 250, 0.95);
|
|
775
|
-
display: flex;
|
|
776
|
-
justify-content: center;
|
|
777
|
-
align-items: center;
|
|
778
|
-
z-index: 9999;
|
|
779
|
-
backdrop-filter: blur(2px);
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
.tiledesk-loading-spinner {
|
|
783
|
-
display: flex;
|
|
784
|
-
flex-direction: column;
|
|
785
|
-
align-items: center;
|
|
786
|
-
gap: 16px;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
.spinner-circle {
|
|
790
|
-
width: 50px;
|
|
791
|
-
height: 50px;
|
|
792
|
-
border: 4px solid rgba(59, 130, 246, 0.2);
|
|
793
|
-
border-top-color: #3b82f6;
|
|
794
|
-
border-radius: 50%;
|
|
795
|
-
animation: spin 0.8s linear infinite;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
@keyframes spin {
|
|
799
|
-
0% {
|
|
800
|
-
transform: rotate(0deg);
|
|
801
|
-
}
|
|
802
|
-
100% {
|
|
803
|
-
transform: rotate(360deg);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
.loading-text {
|
|
808
|
-
font-family: var(--font-family-bubble-message, 'Roboto', 'Google Sans', Helvetica, Arial, sans-serif);
|
|
809
|
-
font-size: 14px;
|
|
810
|
-
font-weight: 500;
|
|
811
|
-
color: #3b82f6;
|
|
812
|
-
letter-spacing: 0.5px;
|
|
813
|
-
animation: pulse 1.5s ease-in-out infinite;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
@keyframes pulse {
|
|
817
|
-
0%, 100% {
|
|
818
|
-
opacity: 1;
|
|
819
|
-
}
|
|
820
|
-
50% {
|
|
821
|
-
opacity: 0.5;
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
// ========= END: LOADING SPINNER ========= //
|
|
825
|
-
|
|
826
767
|
}
|
package/src/app/app.component.ts
CHANGED
|
@@ -106,10 +106,6 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
106
106
|
|
|
107
107
|
forceDisconnect: boolean = false;
|
|
108
108
|
|
|
109
|
-
//network status
|
|
110
|
-
isOnline: boolean = true;
|
|
111
|
-
loading: boolean = false;
|
|
112
|
-
|
|
113
109
|
// alert error message
|
|
114
110
|
isShowErrorMessage: boolean = false;
|
|
115
111
|
errorMessage: string = '';
|
|
@@ -153,7 +149,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
153
149
|
this.logger.info('[APP-CONF]---------------- ngAfterViewInit: APP.COMPONENT ---------------- ')
|
|
154
150
|
|
|
155
151
|
// Initialize translation map and enable buttons
|
|
156
|
-
const keys = ['MAXIMIZE', 'MINIMIZE', 'CENTER', 'BUTTON_CLOSE_TO_ICON'
|
|
152
|
+
const keys = ['MAXIMIZE', 'MINIMIZE', 'CENTER', 'BUTTON_CLOSE_TO_ICON'];
|
|
157
153
|
this.translationMap = this.translateService.translateLanguage(keys);
|
|
158
154
|
this.isButtonsDisabled = false;
|
|
159
155
|
|
|
@@ -320,15 +316,8 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
320
316
|
this.g.setIsOpen(isOpen)
|
|
321
317
|
this.appStorageService.setItem('isOpen', isOpen)
|
|
322
318
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this.logger.debug('[APP-COMP2] ------this.g.isOpen: ', this.g.isOpen)
|
|
326
|
-
if(this.g.isOpen){
|
|
327
|
-
this.g.autoStart = true;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
319
|
+
|
|
320
|
+
|
|
332
321
|
/**CHECK IF JWT IS IN URL PARAMETERS */
|
|
333
322
|
this.logger.debug('[APP-COMP] check if token is passed throw url: ', this.g.jwt);
|
|
334
323
|
if (this.g.jwt) {
|
|
@@ -365,10 +354,13 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
365
354
|
this.subscriptions.push(obsSettingsService);
|
|
366
355
|
this.globalSettingsService.initWidgetParamiters(this.g, this.el);
|
|
367
356
|
|
|
357
|
+
// SET AUDIO
|
|
358
|
+
this.audio = new Audio();
|
|
359
|
+
this.audio.src = this.g.baseLocation + URL_SOUND_LIST_CONVERSATION;
|
|
360
|
+
this.audio.load();
|
|
368
361
|
}
|
|
369
362
|
|
|
370
363
|
private initAll() {
|
|
371
|
-
this.logger.debug('[APP-COMP] initAll : ');
|
|
372
364
|
this.addComponentToWindow(this.ngZone);
|
|
373
365
|
|
|
374
366
|
//INIT TRIGGER-HANDLER
|
|
@@ -409,10 +401,12 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
409
401
|
this.triggerLoadParamsEvent(); // first trigger
|
|
410
402
|
//this.setAvailableAgentsStatus();
|
|
411
403
|
|
|
412
|
-
|
|
413
404
|
/** NETWORK STATUS */
|
|
414
405
|
this.listenToNetworkStatus();
|
|
415
406
|
|
|
407
|
+
/** SET WIDGET SIZE */
|
|
408
|
+
this.onWidgetSizeChange(this.g.size);
|
|
409
|
+
|
|
416
410
|
}
|
|
417
411
|
|
|
418
412
|
// ========= begin:: SUBSCRIPTIONS ============//
|
|
@@ -454,7 +448,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
454
448
|
that.triggerOnAuthStateChanged(that.stateLoggedUser);
|
|
455
449
|
that.logger.debug('[APP-COMP] 1 - IMPOSTO STATO CONNESSO UTENTE ', autoStart);
|
|
456
450
|
|
|
457
|
-
|
|
451
|
+
|
|
458
452
|
|
|
459
453
|
new Promise(async (resolve, reject)=> {
|
|
460
454
|
that.typingService.initialize(this.g.tenant);
|
|
@@ -480,35 +474,26 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
480
474
|
that.listenToWidgetClick()
|
|
481
475
|
}
|
|
482
476
|
|
|
483
|
-
/** DDP IF AUTOSTART IS FALSE, SHOW WIDGET */
|
|
484
|
-
if(!autoStart){
|
|
485
|
-
that.logger.info('[APP-COMP] AUTOSTART IS FALSE AND LOGGED SUCCESSFULLY ');
|
|
486
|
-
this.g.setParameter('isShown', true, true);
|
|
487
|
-
}
|
|
488
477
|
|
|
489
|
-
/** DDP IF AUTOSTART IS FALSE, SHOW WIDGET */
|
|
490
|
-
if(!autoStart){
|
|
491
|
-
that.logger.info('[APP-COMP] AUTOSTART IS FALSE AND LOGGED SUCCESSFULLY ');
|
|
492
|
-
this.g.setParameter('isShown', true, true);
|
|
493
|
-
}
|
|
494
478
|
|
|
495
479
|
} else if (state && state === AUTH_STATE_OFFLINE && !this.forceDisconnect) {
|
|
496
480
|
/** non sono loggato */
|
|
497
481
|
that.logger.info('[APP-COMP] OFFLINE - NO CURRENT USER AUTENTICATE: ');
|
|
498
482
|
that.g.setParameter('isLogged', false);
|
|
499
|
-
|
|
483
|
+
that.hideWidget();
|
|
500
484
|
// that.g.setParameter('isShown', false, true);
|
|
501
485
|
that.triggerOnAuthStateChanged(that.stateLoggedUser);
|
|
502
|
-
if (autoStart
|
|
486
|
+
if (autoStart) {
|
|
503
487
|
that.authenticate();
|
|
504
488
|
}
|
|
505
|
-
}
|
|
489
|
+
}else if(state && state === AUTH_STATE_CLOSE ){
|
|
506
490
|
that.logger.info('[APP-COMP] CLOSE - CHANNEL CLOSED: ', this.chatManager);
|
|
507
491
|
if(this.g.recipientId){
|
|
508
492
|
this.chatManager.removeConversationHandler(this.g.recipientId)
|
|
509
493
|
this.g.recipientId = null;
|
|
510
494
|
}
|
|
511
|
-
}
|
|
495
|
+
}
|
|
496
|
+
|
|
512
497
|
|
|
513
498
|
});
|
|
514
499
|
this.subscriptions.push(subAuthStateChanged);
|
|
@@ -744,7 +729,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
744
729
|
// visualizzo l'iframe!!!
|
|
745
730
|
this.triggerOnViewInit();
|
|
746
731
|
this.g.setParentBodyStyleMobile(this.g.isOpen, this.g.isMobile);
|
|
747
|
-
this.g.setElementStyle(this.g.isOpen)
|
|
732
|
+
this.g.setElementStyle(this.g.isOpen);
|
|
748
733
|
// this.triggerOnAuthStateChanged(true)
|
|
749
734
|
// mostro il widget
|
|
750
735
|
// setTimeout(() => {
|
|
@@ -753,7 +738,6 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
753
738
|
// divWidgetContainer.style.display = 'block';
|
|
754
739
|
// }
|
|
755
740
|
// }, 500);
|
|
756
|
-
this.loading = false;
|
|
757
741
|
}
|
|
758
742
|
// ========= end:: START UI ============//
|
|
759
743
|
|
|
@@ -862,13 +846,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
862
846
|
this.appStorageService.setItem('attributes', JSON.stringify(attributes));
|
|
863
847
|
return attributes;
|
|
864
848
|
}
|
|
865
|
-
|
|
866
|
-
// SET AUDIO
|
|
867
|
-
private initAudioNotification(){
|
|
868
|
-
this.audio = new Audio();
|
|
869
|
-
this.audio.src = this.g.baseLocation + URL_SOUND_LIST_CONVERSATION;
|
|
870
|
-
this.audio.load();
|
|
871
|
-
}
|
|
849
|
+
|
|
872
850
|
|
|
873
851
|
private async initConversationsHandler(tenant: string, senderId: string) {
|
|
874
852
|
this.logger.debug('[APP-COMP] initialize: ListConversationsComponent');
|
|
@@ -1141,7 +1119,6 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1141
1119
|
* 3 - reinit widget
|
|
1142
1120
|
*/
|
|
1143
1121
|
private reInit() {
|
|
1144
|
-
this.logger.debug('[APP-COMP] reInit');
|
|
1145
1122
|
// if (!firebase.auth().currentUser) {
|
|
1146
1123
|
if (!this.tiledeskAuthService.getCurrentUser()) {
|
|
1147
1124
|
this.logger.debug('[APP-COMP] reInit ma NON SONO LOGGATO!');
|
|
@@ -1175,7 +1152,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1175
1152
|
*/
|
|
1176
1153
|
private restart() {
|
|
1177
1154
|
// if (!firebase.auth().currentUser) {
|
|
1178
|
-
|
|
1155
|
+
|
|
1179
1156
|
this.hideWidget();
|
|
1180
1157
|
// that.triggerOnAuthStateChanged(resp);
|
|
1181
1158
|
if (this.g.autoStart !== false) {
|
|
@@ -1628,47 +1605,23 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1628
1605
|
this.f21_close();
|
|
1629
1606
|
}
|
|
1630
1607
|
|
|
1631
|
-
|
|
1632
|
-
/** DDP reload widget */
|
|
1633
|
-
async reloadWidget() {
|
|
1634
|
-
// prima deve aprire il widget e poi mostrare il loading
|
|
1635
|
-
this.openCloseWidget();
|
|
1636
|
-
this.logger.debug('[APP-COMP-1] AAA - hideWidget');
|
|
1637
|
-
await Promise.all([
|
|
1638
|
-
this.authenticate(),
|
|
1639
|
-
// this.initAll()
|
|
1640
|
-
]);
|
|
1641
|
-
this.logger.debug('[APP-COMP-1] CCC - showWidget');
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
1608
|
/**
|
|
1646
1609
|
* LAUNCHER BUTTON:
|
|
1647
1610
|
* onClick button open/close widget
|
|
1648
1611
|
*/
|
|
1649
1612
|
onOpenCloseWidget($event) {
|
|
1650
|
-
this.logger.debug('[APP-COMP] onOpenCloseWidget', $event, this.g.isLogged);
|
|
1651
|
-
if(!this.g.isLogged){
|
|
1652
|
-
this.reloadWidget();
|
|
1653
|
-
} else {
|
|
1654
|
-
this.openCloseWidget();
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
/** DDP show widget */
|
|
1659
|
-
openCloseWidget() {
|
|
1660
1613
|
this.g.setParameter('displayEyeCatcherCard', 'none');
|
|
1661
1614
|
// const conversationActive: ConversationModel = JSON.parse(this.appStorageService.getItem('activeConversation'));
|
|
1662
1615
|
const recipientId : string = this.appStorageService.getItem('recipientId')
|
|
1663
1616
|
this.g.setParameter('recipientId', recipientId);
|
|
1664
1617
|
this.logger.debug('[APP-COMP] openCloseWidget', recipientId, this.g.isOpen, this.g.startFromHome);
|
|
1665
|
-
|
|
1666
1618
|
if (this.g.isOpen === false) {
|
|
1667
1619
|
if(this.forceDisconnect){
|
|
1668
1620
|
this.logger.log('[FORCE] onOpenCloseWidget --> reconnect', this.forceDisconnect)
|
|
1669
1621
|
this.messagingAuthService.createCustomToken(this.g.tiledeskToken)
|
|
1670
1622
|
this.forceDisconnect = false;
|
|
1671
1623
|
}
|
|
1624
|
+
|
|
1672
1625
|
if (!recipientId) {
|
|
1673
1626
|
if(this.g.singleConversation){
|
|
1674
1627
|
this.isOpenHome = false;
|
|
@@ -1688,22 +1641,29 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1688
1641
|
this.isOpenHome = false;
|
|
1689
1642
|
this.isOpenConversation = true;
|
|
1690
1643
|
this.startUI()
|
|
1644
|
+
// this.isOpenSelectionDepartment = false;
|
|
1691
1645
|
}
|
|
1646
|
+
// if (!conversationActive && !this.g.startFromHome) {
|
|
1647
|
+
// this.isOpenHome = false;
|
|
1648
|
+
// this.isOpenConversation = true;
|
|
1649
|
+
// this.startNwConversation();
|
|
1650
|
+
// } else if (conversationActive) {
|
|
1651
|
+
// this.isOpenHome = false;
|
|
1652
|
+
// this.isOpenConversation = true;
|
|
1653
|
+
// }
|
|
1654
|
+
// this.g.startFromHome = true;
|
|
1692
1655
|
this.triggerOnOpenEvent();
|
|
1656
|
+
|
|
1693
1657
|
} else {
|
|
1694
1658
|
this.triggerOnCloseEvent();
|
|
1695
1659
|
}
|
|
1696
1660
|
//change status to the widget
|
|
1697
1661
|
this.g.setIsOpen(!this.g.isOpen);
|
|
1698
1662
|
this.appStorageService.setItem('isOpen', this.g.isOpen);
|
|
1699
|
-
|
|
1700
|
-
if(this.g.isOpen === true && !this.g.isLogged){
|
|
1701
|
-
this.loading = true;
|
|
1702
|
-
}
|
|
1663
|
+
|
|
1703
1664
|
// this.saveBadgeNewConverstionNumber();
|
|
1704
1665
|
}
|
|
1705
1666
|
|
|
1706
|
-
|
|
1707
1667
|
/**
|
|
1708
1668
|
* MODAL SELECTION DEPARTMENT:
|
|
1709
1669
|
* selected department
|
package/src/app/app.module.ts
CHANGED
|
@@ -59,8 +59,9 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
|
59
59
|
import { environment } from 'src/environments/environment';
|
|
60
60
|
|
|
61
61
|
//THIRD-PART MODULES
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
62
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
63
|
+
// import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
|
64
|
+
// import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
|
64
65
|
// import { MomentModule } from 'ngx-moment';
|
|
65
66
|
import { PickerModule } from '@ctrl/ngx-emoji-mart';
|
|
66
67
|
import { LoggerModule, NGXLogger, NgxLoggerLevel } from "ngx-logger";
|
|
@@ -205,10 +206,12 @@ export function conversationHandlerFactory(chat21Service: Chat21Service, appConf
|
|
|
205
206
|
}
|
|
206
207
|
}
|
|
207
208
|
|
|
209
|
+
|
|
210
|
+
|
|
208
211
|
// ngx-translate Http loader factory
|
|
209
|
-
export function createTranslateLoader(http: HttpClient) {
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
+
// export function createTranslateLoader(http: HttpClient) {
|
|
213
|
+
// return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
|
214
|
+
// }
|
|
212
215
|
|
|
213
216
|
export function typingFactory(chat21Service: Chat21Service, appConfig: AppConfigService) {
|
|
214
217
|
const config = appConfig.getConfig()
|
|
@@ -314,13 +317,13 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
|
|
|
314
317
|
FormsModule,
|
|
315
318
|
ReactiveFormsModule,
|
|
316
319
|
PickerModule,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
320
|
+
TranslateModule.forRoot({
|
|
321
|
+
// defaultLanguage: 'en',
|
|
322
|
+
// loader: {
|
|
323
|
+
// provide: TranslateLoader,
|
|
324
|
+
// useFactory: (createTranslateLoader),
|
|
325
|
+
// deps: [HttpClient]
|
|
326
|
+
// }
|
|
324
327
|
}),
|
|
325
328
|
LoggerModule.forRoot({
|
|
326
329
|
level: NgxLoggerLevel.DEBUG,
|
|
@@ -457,7 +457,7 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
457
457
|
return this.isConversationArchived;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
//
|
|
460
|
+
//FALLBACK TO TILEDESK
|
|
461
461
|
const requests_list = await this.tiledeskRequestService.getMyRequests().catch(err => {
|
|
462
462
|
this.logger.error('[CONV-COMP] getConversationDetail: error getting request from Tiledesk', err);
|
|
463
463
|
this.isConversationArchived=true
|
|
@@ -475,9 +475,9 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
475
475
|
return this.isConversationArchived
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
478
|
+
this.isConversationArchived = true;
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
481
|
|
|
482
482
|
/**
|
|
483
483
|
* this.g.recipientId:
|
|
@@ -827,20 +827,6 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
827
827
|
this.subscriptions.push(subscribe);
|
|
828
828
|
}
|
|
829
829
|
|
|
830
|
-
subscribtionKey = 'conversationsAdded';
|
|
831
|
-
subscribtion = this.subscriptions.find(item => item.key === subscribtionKey);
|
|
832
|
-
if(!subscribtion){
|
|
833
|
-
|
|
834
|
-
subscribtion = this.chatManager.conversationsHandlerService.conversationChanged.pipe(takeUntil(this.unsubscribe$)).subscribe((conversation) => {
|
|
835
|
-
this.logger.debug('[CONV-COMP] ***** DATAIL conversationsChanged *****', conversation, this.conversationWith, this.isConversationArchived);
|
|
836
|
-
if(conversation && conversation.recipient === this.conversationId){
|
|
837
|
-
this.isConversationArchived = false
|
|
838
|
-
}
|
|
839
|
-
});
|
|
840
|
-
const subscribe = {key: subscribtionKey, value: subscribtion };
|
|
841
|
-
this.subscriptions.push(subscribe);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
830
|
subscribtionKey = 'messageWait';
|
|
845
831
|
subscribtion = this.subscriptions.find(item => item.key === subscribtionKey);
|
|
846
832
|
if (!subscribtion) {
|
|
@@ -1441,4 +1427,5 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
1441
1427
|
this.isHovering = false
|
|
1442
1428
|
}
|
|
1443
1429
|
|
|
1444
|
-
}
|
|
1430
|
+
}
|
|
1431
|
+
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss
CHANGED
|
@@ -418,28 +418,3 @@ textarea:active{
|
|
|
418
418
|
border: none;
|
|
419
419
|
// margin: -2px -2px 0px;
|
|
420
420
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
// aggiungi un'animazione di fade in e fade out quando .star-rating-widget è visibile con transition
|
|
424
|
-
.star-rating-widget {
|
|
425
|
-
transition: all 0.5s ease-in-out;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.star-rating-widget {
|
|
429
|
-
position: absolute;
|
|
430
|
-
left: 0;
|
|
431
|
-
right: 0;
|
|
432
|
-
bottom: -52px;
|
|
433
|
-
height: 100%;
|
|
434
|
-
width: 100%;
|
|
435
|
-
flex-direction: row;
|
|
436
|
-
justify-content: center;
|
|
437
|
-
background-color: rgb(255, 255, 255);
|
|
438
|
-
flex-wrap: nowrap;
|
|
439
|
-
&.active {
|
|
440
|
-
bottom: 0px;
|
|
441
|
-
}
|
|
442
|
-
&.inactive {
|
|
443
|
-
bottom: -52px;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
@@ -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.isOpen == false"
|
|
4
|
+
*ngIf="g.isLogged == true && 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,9 +67,8 @@ 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
|
-
}
|
|
72
|
-
this.onButtonClicked.emit( this.g.isOpen );
|
|
70
|
+
this.onButtonClicked.emit( this.g.isOpen );
|
|
71
|
+
}
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, ElementRef, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { getColorBck } from 'src/chat21-core/utils/utils-user';
|
|
2
3
|
|
|
3
4
|
@Component({
|
|
4
5
|
selector: 'chat-action-button-attachment',
|
|
@@ -26,9 +27,10 @@ export class ActionButtonComponent implements OnInit {
|
|
|
26
27
|
//decomment if element should have same color of themeColor and fregroundColor
|
|
27
28
|
if(this.fontSize) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonFontSize', this.fontSize);
|
|
28
29
|
if(this.backgroundColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonBackgroundColor', this.backgroundColor);
|
|
29
|
-
if(this.textColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--
|
|
30
|
+
if(this.textColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonTextColor', this.textColor);
|
|
30
31
|
if(this.hoverBackgroundColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--hoverBackgroundColor', this.hoverBackgroundColor);
|
|
31
32
|
if(this.hoverTextColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--hoverTextColor', this.hoverTextColor);
|
|
33
|
+
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
onMouseOver(event){
|
|
@@ -10,7 +10,7 @@ import { TemplateBindingParseResult } from '@angular/compiler';
|
|
|
10
10
|
import { AppStorageService } from '../../chat21-core/providers/abstract/app-storage.service';
|
|
11
11
|
import { LoggerService } from '../../chat21-core/providers/abstract/logger.service';
|
|
12
12
|
import { LoggerInstance } from '../../chat21-core/providers/logger/loggerInstance';
|
|
13
|
-
import { invertColor, isAllowedUrlInText, isJsonArray } from '../../chat21-core/utils/utils';
|
|
13
|
+
import { ensureAccessibleTextColor, invertColor, isAllowedUrlInText, isJsonArray, normalizeColorToHex } from '../../chat21-core/utils/utils';
|
|
14
14
|
import { AppConfigService } from './app-config.service';
|
|
15
15
|
|
|
16
16
|
|
|
@@ -322,10 +322,14 @@ export class GlobalSettingsService {
|
|
|
322
322
|
if (response !== null) {
|
|
323
323
|
this.setVariablesFromService(this.globals, response);
|
|
324
324
|
}
|
|
325
|
+
/** set button colors */
|
|
326
|
+
this.setButtonColors();
|
|
327
|
+
|
|
325
328
|
this.setVariableFromStorage(this.globals);
|
|
326
329
|
this.setVariablesFromSettings(this.globals);
|
|
327
330
|
this.setVariablesFromAttributeHtml(this.globals, this.el);
|
|
328
331
|
this.setVariablesFromUrlParameters(this.globals);
|
|
332
|
+
|
|
329
333
|
this.setDepartmentFromExternal();
|
|
330
334
|
/** set color with gradient from theme's colors */
|
|
331
335
|
this.globals.setColorWithGradient();
|
|
@@ -333,11 +337,19 @@ export class GlobalSettingsService {
|
|
|
333
337
|
this.setCssIframe();
|
|
334
338
|
/** set main style */
|
|
335
339
|
this.setStyle();
|
|
336
|
-
|
|
337
|
-
this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****');
|
|
338
340
|
this.obsSettingsService.next(true);
|
|
339
341
|
}
|
|
340
342
|
|
|
343
|
+
private setButtonColors() {
|
|
344
|
+
this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****', this.globals);
|
|
345
|
+
const bubbleSentBackground = this.globals?.bubbleSentBackground;
|
|
346
|
+
const buttonBackgroundColor = this.globals?.buttonBackgroundColor;
|
|
347
|
+
|
|
348
|
+
this.globals.buttonTextColor = ensureAccessibleTextColor(buttonBackgroundColor, bubbleSentBackground);
|
|
349
|
+
this.globals.buttonHoverTextColor = ensureAccessibleTextColor(bubbleSentBackground, buttonBackgroundColor);
|
|
350
|
+
|
|
351
|
+
}
|
|
352
|
+
|
|
341
353
|
/**
|
|
342
354
|
*
|
|
343
355
|
*/
|
|
@@ -263,7 +263,6 @@ export class TranslatorService {
|
|
|
263
263
|
'CLOSED',
|
|
264
264
|
'LABEL_PREVIEW',
|
|
265
265
|
'MAX_ATTACHMENT',
|
|
266
|
-
'MAX_ATTACHMENT_ERROR',
|
|
267
266
|
'EMOJI'
|
|
268
267
|
];
|
|
269
268
|
|
|
@@ -320,7 +319,6 @@ export class TranslatorService {
|
|
|
320
319
|
globals.LABEL_PREVIEW = res['LABEL_PREVIEW']
|
|
321
320
|
globals.LABEL_ERROR_FIELD_REQUIRED= res['LABEL_ERROR_FIELD_REQUIRED']
|
|
322
321
|
globals.MAX_ATTACHMENT = res['MAX_ATTACHMENT']
|
|
323
|
-
globals.MAX_ATTACHMENT_ERROR = res['MAX_ATTACHMENT_ERROR']
|
|
324
322
|
globals.EMOJI = res['EMOJI']
|
|
325
323
|
|
|
326
324
|
|
package/src/app/utils/globals.ts
CHANGED
|
@@ -247,7 +247,7 @@ export class Globals {
|
|
|
247
247
|
|
|
248
248
|
// ============ BEGIN: SET EXTERNAL PARAMETERS ==============//
|
|
249
249
|
this.baseLocation = 'https://widget.tiledesk.com/v2';
|
|
250
|
-
this.autoStart =
|
|
250
|
+
this.autoStart = true;
|
|
251
251
|
/** start Authentication and startUI */
|
|
252
252
|
this.startHidden = false;
|
|
253
253
|
/** show/hide all widget -> js call: showAllWidget */
|
package/src/assets/i18n/en.json
CHANGED
|
@@ -96,6 +96,5 @@
|
|
|
96
96
|
"EMOJI_NOT_ELLOWED":"Emoji not allowed",
|
|
97
97
|
"DOMAIN_NOT_ALLOWED":"URL contains a non-allowed domain",
|
|
98
98
|
"MAX_ATTACHMENT": "Max allowed size {{FILE_SIZE_LIMIT}}Mb",
|
|
99
|
-
"MAX_ATTACHMENT_ERROR": "The file exceeds the maximum allowed size",
|
|
100
99
|
"EMOJI": "Emoji"
|
|
101
100
|
}
|
package/src/assets/i18n/es.json
CHANGED
|
@@ -96,6 +96,5 @@
|
|
|
96
96
|
"EMOJI_NOT_ELLOWED":"Emoji no permitido",
|
|
97
97
|
"DOMAIN_NOT_ALLOWED":"La URL contiene un dominio no permitido",
|
|
98
98
|
"MAX_ATTACHMENT": "Tamaño máximo permitido {{FILE_SIZE_LIMIT}}Mb",
|
|
99
|
-
"MAX_ATTACHMENT_ERROR": "El archivo supera el tamaño máximo permitido",
|
|
100
99
|
"EMOJI": "Emoji"
|
|
101
100
|
}
|
package/src/assets/i18n/fr.json
CHANGED
|
@@ -96,6 +96,5 @@
|
|
|
96
96
|
"EMOJI_NOT_ELLOWED":"Emoji non autorisé",
|
|
97
97
|
"DOMAIN_NOT_ALLOWED":"L'URL contient un domaine non autorisé",
|
|
98
98
|
"MAX_ATTACHMENT": "Taille maximale autorisée {{FILE_SIZE_LIMIT}}Mo",
|
|
99
|
-
"MAX_ATTACHMENT_ERROR": "Le fichier dépasse la taille maximale autorisée",
|
|
100
99
|
"EMOJI": "Emoji"
|
|
101
100
|
}
|
package/src/assets/i18n/it.json
CHANGED
|
@@ -94,6 +94,5 @@
|
|
|
94
94
|
"EMOJI_NOT_ELLOWED":"Emoji non consentiti",
|
|
95
95
|
"DOMAIN_NOT_ALLOWED":"L'URL contiene un dominio non consentito",
|
|
96
96
|
"MAX_ATTACHMENT": "Dimensione massima consentita {{FILE_SIZE_LIMIT}}Mb",
|
|
97
|
-
"MAX_ATTACHMENT_ERROR": "Il file supera la dimensione massima consentita",
|
|
98
97
|
"EMOJI": "Emoji"
|
|
99
98
|
}
|
|
@@ -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({
|
|
@@ -389,6 +389,115 @@ export function convertColorToRGBA(color, opacity) {
|
|
|
389
389
|
return result;
|
|
390
390
|
}
|
|
391
391
|
|
|
392
|
+
export function normalizeColorToHex(input?: string): string | null {
|
|
393
|
+
if (!input) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
let color = input.trim();
|
|
397
|
+
if (color.toLowerCase().includes('gradient')) {
|
|
398
|
+
const match = color.match(/(#[0-9a-fA-F]{3,8}|rgba?\([^)]*\))/);
|
|
399
|
+
if (!match) {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
color = match[0];
|
|
403
|
+
}
|
|
404
|
+
if (color.startsWith('#')) {
|
|
405
|
+
const hex = color.slice(1);
|
|
406
|
+
if (hex.length === 3) {
|
|
407
|
+
return (
|
|
408
|
+
'#' +
|
|
409
|
+
hex
|
|
410
|
+
.split('')
|
|
411
|
+
.map((char) => char + char)
|
|
412
|
+
.join('')
|
|
413
|
+
.toLowerCase()
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
if (hex.length === 4) {
|
|
417
|
+
return (
|
|
418
|
+
'#' +
|
|
419
|
+
hex
|
|
420
|
+
.slice(0, 3)
|
|
421
|
+
.split('')
|
|
422
|
+
.map((char) => char + char)
|
|
423
|
+
.join('')
|
|
424
|
+
.toLowerCase()
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
428
|
+
return '#' + hex.slice(0, 6).toLowerCase();
|
|
429
|
+
}
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
const rgbaMatch = color.match(/rgba?\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)/i);
|
|
433
|
+
if (rgbaMatch) {
|
|
434
|
+
const [, r, g, b] = rgbaMatch;
|
|
435
|
+
const toHex = (value: number) => {
|
|
436
|
+
const clamped = Math.max(0, Math.min(255, Math.round(value)));
|
|
437
|
+
return clamped.toString(16).padStart(2, '0');
|
|
438
|
+
};
|
|
439
|
+
return `#${toHex(parseFloat(r))}${toHex(parseFloat(g))}${toHex(parseFloat(b))}`;
|
|
440
|
+
}
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export function ensureAccessibleTextColor(backgroundColor?: string, fontColor?: string, minContrast = 4.5): string | null {
|
|
445
|
+
const bgHex = normalizeColorToHex(backgroundColor);
|
|
446
|
+
if (!bgHex) {
|
|
447
|
+
return normalizeColorToHex(fontColor);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const fontHex = normalizeColorToHex(fontColor);
|
|
451
|
+
if (fontHex && getContrastRatio(bgHex, fontHex) >= minContrast) {
|
|
452
|
+
return fontHex;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const blackContrast = getContrastRatio(bgHex, '#000000');
|
|
456
|
+
const whiteContrast = getContrastRatio(bgHex, '#ffffff');
|
|
457
|
+
return blackContrast >= whiteContrast ? '#000000' : '#ffffff';
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function getContrastRatio(backgroundHex: string, foregroundHex: string): number {
|
|
461
|
+
const bg = hexToRgb(backgroundHex);
|
|
462
|
+
const fg = hexToRgb(foregroundHex);
|
|
463
|
+
if (!bg || !fg) {
|
|
464
|
+
return 1;
|
|
465
|
+
}
|
|
466
|
+
const l1 = relativeLuminance(bg);
|
|
467
|
+
const l2 = relativeLuminance(fg);
|
|
468
|
+
const lighter = Math.max(l1, l2);
|
|
469
|
+
const darker = Math.min(l1, l2);
|
|
470
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function relativeLuminance({ r, g, b }: { r: number; g: number; b: number }): number {
|
|
474
|
+
const srgb = [r, g, b].map((value) => {
|
|
475
|
+
const channel = value / 255;
|
|
476
|
+
return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
|
|
477
|
+
});
|
|
478
|
+
return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
|
|
482
|
+
let value = hex.replace('#', '');
|
|
483
|
+
if (value.length === 3) {
|
|
484
|
+
value = value
|
|
485
|
+
.split('')
|
|
486
|
+
.map((char) => char + char)
|
|
487
|
+
.join('');
|
|
488
|
+
}
|
|
489
|
+
if (value.length !== 6) {
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
const r = parseInt(value.slice(0, 2), 16);
|
|
493
|
+
const g = parseInt(value.slice(2, 4), 16);
|
|
494
|
+
const b = parseInt(value.slice(4, 6), 16);
|
|
495
|
+
if ([r, g, b].some((channel) => Number.isNaN(channel))) {
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
return { r, g, b };
|
|
499
|
+
}
|
|
500
|
+
|
|
392
501
|
|
|
393
502
|
// export function setLanguage(windowContext, translatorService) {
|
|
394
503
|
// if (translatorService.getBrowserLanguage(windowContext)) {
|
|
@@ -664,11 +773,6 @@ export function isAllowedUrlInText(text: string, allowedUrls: string[]) {
|
|
|
664
773
|
return nonWhitelistedDomains.length === 0;
|
|
665
774
|
}
|
|
666
775
|
|
|
667
|
-
// function extractUrls(text: string): string[] {
|
|
668
|
-
// const urlRegex = /https?:\/\/[^\s]+/g;
|
|
669
|
-
// return text.match(urlRegex) || [];
|
|
670
|
-
// }
|
|
671
|
-
|
|
672
776
|
function extractUrls(text: string): string[] {
|
|
673
777
|
// Rileva URL con o senza protocollo (http/https)
|
|
674
778
|
const urlRegex = /\b((https?:\/\/)?(www\.)?[a-z0-9.-]+\.[a-z]{2,})(\/[^\s]*)?/gi;
|
|
@@ -683,3 +787,5 @@ function extractUrls(text: string): string[] {
|
|
|
683
787
|
}
|
|
684
788
|
|
|
685
789
|
|
|
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: none;
|
|
17
17
|
z-index: 3000000000; /*999999*/;
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -66,12 +66,12 @@
|
|
|
66
66
|
max-width: 1024px;
|
|
67
67
|
max-height: 100%;
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
transition:
|
|
70
70
|
width 300ms,
|
|
71
71
|
height 300ms,
|
|
72
72
|
max-height 300ms,
|
|
73
73
|
transform 300ms cubic-bezier(0, 1.2, 1, 1),
|
|
74
|
-
opacity 300ms ease-out;
|
|
74
|
+
opacity 300ms ease-out;
|
|
75
75
|
/* per migliorare le prestazioni quando si usa transform */
|
|
76
76
|
will-change: transform, opacity, width, height;
|
|
77
77
|
}
|
|
@@ -151,14 +151,14 @@
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
#tiledesk-container.open #tiledeskdiv.min-size {
|
|
154
|
-
|
|
154
|
+
transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out;
|
|
155
155
|
width: var(--iframeMinWidth);
|
|
156
156
|
height: var(--iframeMinHeight);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
#tiledesk-container.open #tiledeskdiv.max-size {
|
|
160
160
|
/* transition: width 1s, height 1s; */
|
|
161
|
-
|
|
161
|
+
transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out;
|
|
162
162
|
width: var(--iframeMaxWidth);
|
|
163
163
|
height: var(--iframeMaxHeight);
|
|
164
164
|
}
|