@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.
@@ -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
- - name: Check out the repo
16
- uses: actions/checkout@v2
17
-
18
- - name: Set up Docker Buildx
19
- uses: docker/setup-buildx-action@v2
20
-
21
- - name: Log in to Docker Hub
22
- uses: docker/login-action@v2
23
- with:
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
- - '**' # Trigger su qualsiasi tag
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
- - name: Check out the repo
15
- uses: actions/checkout@v2
16
-
17
- - name: Set up Docker Buildx
18
- uses: docker/setup-buildx-action@v2
19
-
20
- - name: Log in to Docker Hub
21
- uses: docker/login-action@v2
22
- with:
23
- username: ${{ secrets.DOCKERHUB_USERNAME }}
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.9
20
- - **changed**: Set the default autoStart value to false
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.8
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.7-rc7
31
- - **bug-fixed**: button new_conversation always appear. added subscription to conversationAdded
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 --platform=$BUILDPLATFORM node:20.12.2-alpine3.19 as builder
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
- FROM --platform=$BUILDPLATFORM nginx:1.14.1-alpine
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", "-c", "envsubst < /usr/share/nginx/html/widget-config-template.json > /usr/share/nginx/html/widget-config.json && exec nginx -g 'daemon off;'"]
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-web-widget",
3
3
  "author": "Tiledesk SRL",
4
- "version": "5.1.12-ar",
4
+ "version": "5.1.14",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -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
  }
@@ -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', 'LABEL_LOADING'];
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
- if(this.g.onPageChangeVisibilityDesktop === 'last'){
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
- this.initAudioNotification()
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
- // that.hideWidget();
483
+ that.hideWidget();
500
484
  // that.g.setParameter('isShown', false, true);
501
485
  that.triggerOnAuthStateChanged(that.stateLoggedUser);
502
- if (autoStart || this.g.onPageChangeVisibilityDesktop === 'open' || this.g.onPageChangeVisibilityMobile === 'open') {
486
+ if (autoStart) {
503
487
  that.authenticate();
504
488
  }
505
- } else if(state && state === AUTH_STATE_CLOSE ){
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
- this.logger.debug('[APP-COMP] restart');
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
- //show loading if widget is open and user is not logged
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
@@ -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 { TranslateLoader, TranslateModule } from '@ngx-translate/core';
63
- import { TranslateHttpLoader } from '@ngx-translate/http-loader';
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
- return new TranslateHttpLoader(http, './assets/i18n/', '.json');
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
- TranslateModule.forRoot({
318
- defaultLanguage: 'en',
319
- loader: {
320
- provide: TranslateLoader,
321
- useFactory: (createTranslateLoader),
322
- deps: [HttpClient]
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
- // //FALLBACK TO TILEDESK
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
- this.isConversationArchived = false;
479
- return null;
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
+
@@ -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
- }
@@ -87,7 +87,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
87
87
 
88
88
  file_size_limit = FILE_SIZE_LIMIT;
89
89
  attachmentTooltip: string = '';
90
- isErrorNetwork: boolean = false;
91
90
 
92
91
 
93
92
  convertColorToRGBA = convertColorToRGBA;
@@ -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('--textColor', this.textColor);
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
 
@@ -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 = false;
250
+ this.autoStart = true;
251
251
  /** start Authentication and startUI */
252
252
  this.startHidden = false;
253
253
  /** show/hide all widget -> js call: showAllWidget */
@@ -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
  }
@@ -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
  }
@@ -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
  }
@@ -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
+
@@ -13,7 +13,7 @@
13
13
  bottom: 0px;
14
14
  width: auto;
15
15
  height: auto;
16
- display: block;
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
- /* transition:
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
- /* transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out; */
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
- /* transition: width 200ms, height 200ms, max-height 200ms, transform 300ms cubic-bezier(0, 1.2, 1, 1), opacity 83ms ease-out; */
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
  }