@chat21/chat21-web-widget 5.1.34-rc1 → 5.1.34

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.
Files changed (193) hide show
  1. package/.github/workflows/docker-community-push-latest.yml +13 -23
  2. package/.github/workflows/docker-image-tag-community-tag-push.yml +12 -22
  3. package/CHANGELOG.md +8 -129
  4. package/Dockerfile +5 -4
  5. package/angular.json +3 -21
  6. package/docs/changelog/this-branch.md +0 -36
  7. package/env.sample +2 -3
  8. package/nginx.conf +2 -22
  9. package/package.json +3 -10
  10. package/src/app/app.component.html +2 -2
  11. package/src/app/app.component.scss +14 -25
  12. package/src/app/app.component.spec.ts +6 -21
  13. package/src/app/app.component.ts +9 -10
  14. package/src/app/app.module.ts +0 -13
  15. package/src/app/component/conversation-detail/conversation/conversation.component.html +11 -25
  16. package/src/app/component/conversation-detail/conversation/conversation.component.scss +2 -40
  17. package/src/app/component/conversation-detail/conversation/conversation.component.spec.ts +75 -644
  18. package/src/app/component/conversation-detail/conversation/conversation.component.ts +14 -100
  19. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.html +13 -25
  20. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.spec.ts +5 -123
  21. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.ts +0 -1
  22. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +10 -23
  23. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +1 -19
  24. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.spec.ts +149 -242
  25. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +5 -8
  26. package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.spec.ts +3 -53
  27. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +96 -200
  28. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +6 -211
  29. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.spec.ts +78 -452
  30. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +76 -291
  31. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.html +53 -113
  32. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.scss +4 -12
  33. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.spec.ts +29 -274
  34. package/src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.html +9 -23
  35. package/src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.spec.ts +8 -80
  36. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.html +23 -29
  37. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.spec.ts +16 -185
  38. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.ts +14 -34
  39. package/src/app/component/error-alert/error-alert.component.spec.ts +5 -65
  40. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.html +7 -16
  41. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.scss +0 -21
  42. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.spec.ts +7 -89
  43. package/src/app/component/form/form-builder/form-builder.component.html +1 -1
  44. package/src/app/component/form/form-builder/form-builder.component.spec.ts +21 -163
  45. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.html +4 -8
  46. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.scss +5 -10
  47. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.spec.ts +16 -90
  48. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.ts +0 -26
  49. package/src/app/component/form/inputs/form-label/form-label.component.spec.ts +11 -45
  50. package/src/app/component/form/inputs/form-radio-button/form-radio-button.component.spec.ts +6 -24
  51. package/src/app/component/form/inputs/form-select/form-select.component.spec.ts +5 -14
  52. package/src/app/component/form/inputs/form-text/form-text.component.html +12 -14
  53. package/src/app/component/form/inputs/form-text/form-text.component.scss +1 -11
  54. package/src/app/component/form/inputs/form-text/form-text.component.spec.ts +17 -113
  55. package/src/app/component/form/inputs/form-text/form-text.component.ts +3 -35
  56. package/src/app/component/form/inputs/form-textarea/form-textarea.component.html +11 -13
  57. package/src/app/component/form/inputs/form-textarea/form-textarea.component.scss +5 -6
  58. package/src/app/component/form/inputs/form-textarea/form-textarea.component.spec.ts +13 -149
  59. package/src/app/component/form/inputs/form-textarea/form-textarea.component.ts +0 -26
  60. package/src/app/component/form/prechat-form/prechat-form.component.html +11 -14
  61. package/src/app/component/form/prechat-form/prechat-form.component.spec.ts +10 -102
  62. package/src/app/component/form/prechat-form/prechat-form.component.ts +1 -8
  63. package/src/app/component/home/home.component.html +31 -38
  64. package/src/app/component/home/home.component.scss +2 -4
  65. package/src/app/component/home/home.component.spec.ts +11 -226
  66. package/src/app/component/home-conversations/home-conversations.component.html +26 -30
  67. package/src/app/component/home-conversations/home-conversations.component.scss +0 -3
  68. package/src/app/component/home-conversations/home-conversations.component.spec.ts +36 -212
  69. package/src/app/component/last-message/last-message.component.html +9 -15
  70. package/src/app/component/last-message/last-message.component.scss +2 -16
  71. package/src/app/component/last-message/last-message.component.spec.ts +23 -204
  72. package/src/app/component/last-message/last-message.component.ts +1 -4
  73. package/src/app/component/launcher-button/launcher-button.component.html +13 -8
  74. package/src/app/component/launcher-button/launcher-button.component.spec.ts +8 -104
  75. package/src/app/component/list-all-conversations/list-all-conversations.component.html +17 -12
  76. package/src/app/component/list-all-conversations/list-all-conversations.component.scss +0 -2
  77. package/src/app/component/list-conversations/list-conversations.component.html +22 -22
  78. package/src/app/component/menu-options/menu-options.component.html +20 -30
  79. package/src/app/component/menu-options/menu-options.component.spec.ts +9 -125
  80. package/src/app/component/message/audio/audio.component.html +15 -13
  81. package/src/app/component/message/audio/audio.component.spec.ts +5 -140
  82. package/src/app/component/message/audio/audio.component.ts +5 -1
  83. package/src/app/component/message/avatar/avatar.component.html +2 -2
  84. package/src/app/component/message/avatar/avatar.component.spec.ts +7 -99
  85. package/src/app/component/message/bubble-message/bubble-message.component.html +51 -38
  86. package/src/app/component/message/bubble-message/bubble-message.component.scss +1 -54
  87. package/src/app/component/message/bubble-message/bubble-message.component.spec.ts +57 -154
  88. package/src/app/component/message/bubble-message/bubble-message.component.ts +11 -89
  89. package/src/app/component/message/buttons/action-button/action-button.component.html +4 -3
  90. package/src/app/component/message/buttons/action-button/action-button.component.spec.ts +5 -49
  91. package/src/app/component/message/buttons/link-button/link-button.component.scss +8 -5
  92. package/src/app/component/message/buttons/link-button/link-button.component.spec.ts +5 -50
  93. package/src/app/component/message/buttons/text-button/text-button.component.spec.ts +5 -44
  94. package/src/app/component/message/carousel/carousel.component.html +16 -29
  95. package/src/app/component/message/carousel/carousel.component.scss +8 -20
  96. package/src/app/component/message/carousel/carousel.component.spec.ts +3 -80
  97. package/src/app/component/message/carousel/carousel.component.ts +0 -16
  98. package/src/app/component/message/frame/frame.component.html +4 -9
  99. package/src/app/component/message/frame/frame.component.spec.ts +15 -34
  100. package/src/app/component/message/frame/frame.component.ts +2 -7
  101. package/src/app/component/message/html/html.component.html +1 -1
  102. package/src/app/component/message/html/html.component.scss +1 -1
  103. package/src/app/component/message/html/html.component.spec.ts +7 -24
  104. package/src/app/component/message/image/image.component.html +10 -12
  105. package/src/app/component/message/image/image.component.scss +0 -16
  106. package/src/app/component/message/image/image.component.spec.ts +15 -101
  107. package/src/app/component/message/image/image.component.ts +51 -90
  108. package/src/app/component/message/info-message/info-message.component.spec.ts +14 -26
  109. package/src/app/component/message/like-unlike/like-unlike.component.html +9 -7
  110. package/src/app/component/message/like-unlike/like-unlike.component.spec.ts +3 -31
  111. package/src/app/component/message/return-receipt/return-receipt.component.spec.ts +17 -38
  112. package/src/app/component/message/text/text.component.html +3 -3
  113. package/src/app/component/message/text/text.component.scss +86 -80
  114. package/src/app/component/message/text/text.component.spec.ts +13 -106
  115. package/src/app/component/message-attachment/message-attachment.component.spec.ts +13 -134
  116. package/src/app/component/selection-department/selection-department.component.html +23 -21
  117. package/src/app/component/selection-department/selection-department.component.spec.ts +14 -159
  118. package/src/app/component/selection-department/selection-department.component.ts +1 -8
  119. package/src/app/component/send-button/send-button.component.html +13 -5
  120. package/src/app/component/send-button/send-button.component.spec.ts +2 -2
  121. package/src/app/component/star-rating-widget/star-rating-widget.component.html +81 -51
  122. package/src/app/directives/tooltip.directive.spec.ts +4 -8
  123. package/src/app/modals/confirm-close/confirm-close.component.html +8 -20
  124. package/src/app/modals/confirm-close/confirm-close.component.scss +0 -3
  125. package/src/app/modals/confirm-close/confirm-close.component.spec.ts +4 -13
  126. package/src/app/modals/confirm-close/confirm-close.component.ts +1 -8
  127. package/src/app/pipe/html-entites-encode.pipe.spec.ts +2 -35
  128. package/src/app/pipe/marked.pipe.spec.ts +2 -38
  129. package/src/app/pipe/marked.pipe.ts +41 -51
  130. package/src/app/providers/app-config.service.ts +2 -4
  131. package/src/app/providers/brand.service.spec.ts +2 -23
  132. package/src/app/providers/brand.service.ts +1 -1
  133. package/src/app/providers/global-settings.service.spec.ts +14 -1009
  134. package/src/app/providers/global-settings.service.ts +2 -82
  135. package/src/app/providers/translator.service.ts +6 -26
  136. package/src/app/sass/_variables.scss +0 -3
  137. package/src/app/sass/animations.scss +1 -19
  138. package/src/app/utils/globals.ts +1 -21
  139. package/src/app/utils/utils-resources.ts +1 -1
  140. package/src/assets/i18n/en.json +99 -106
  141. package/src/assets/i18n/es.json +100 -107
  142. package/src/assets/i18n/fr.json +100 -107
  143. package/src/assets/i18n/it.json +98 -107
  144. package/src/assets/twp/index-dev.html +0 -18
  145. package/src/chat21-core/models/message.ts +1 -2
  146. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +2 -3
  147. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +0 -12
  148. package/src/chat21-core/providers/scripts/script.service.spec.ts +2 -12
  149. package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
  150. package/src/chat21-core/utils/utils-message.ts +0 -7
  151. package/src/chat21-core/utils/utils.ts +2 -5
  152. package/src/widget-config-template.json +1 -4
  153. package/src/widget-config.json +1 -4
  154. package/tsconfig.json +0 -5
  155. package/.angular-mcp-cache/package.json +0 -1
  156. package/.cursor/angular18-accessibility-auditor-skill.md +0 -442
  157. package/.cursor/mcp.json +0 -15
  158. package/.github/workflows/build.yml +0 -22
  159. package/.github/workflows/playwright.yml +0 -27
  160. package/mocks/voice-websocket-mock/server.cjs +0 -245
  161. package/playwright.config.ts +0 -41
  162. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.html +0 -46
  163. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.scss +0 -83
  164. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.ts +0 -192
  165. package/src/app/component/form/prechat-form-test-mock.ts +0 -35
  166. package/src/app/component/message/audio-sync/audio-sync.component.html +0 -18
  167. package/src/app/component/message/audio-sync/audio-sync.component.scss +0 -65
  168. package/src/app/component/message/audio-sync/audio-sync.component.spec.ts +0 -103
  169. package/src/app/component/message/audio-sync/audio-sync.component.ts +0 -643
  170. package/src/app/providers/tts-audio-playback-coordinator.service.spec.ts +0 -117
  171. package/src/app/providers/tts-audio-playback-coordinator.service.ts +0 -109
  172. package/src/app/providers/voice/STT&TTS/openai-voice.config.ts +0 -12
  173. package/src/app/providers/voice/STT&TTS/openai-voice.provider.ts +0 -171
  174. package/src/app/providers/voice/STT&TTS/speech-provider.abstract.ts +0 -39
  175. package/src/app/providers/voice/audio.types.ts +0 -40
  176. package/src/app/providers/voice/vad.service.spec.ts +0 -28
  177. package/src/app/providers/voice/vad.service.ts +0 -70
  178. package/src/app/providers/voice/voice-streaming.service.spec.ts +0 -23
  179. package/src/app/providers/voice/voice-streaming.service.ts +0 -702
  180. package/src/app/providers/voice/voice-streaming.types.ts +0 -112
  181. package/src/app/providers/voice/voice.service.spec.ts +0 -227
  182. package/src/app/providers/voice/voice.service.ts +0 -973
  183. package/src/app/shims/onnxruntime-web-wasm.ts +0 -4
  184. package/src/assets/onnx/ort-wasm-simd-threaded.mjs +0 -59
  185. package/src/assets/onnx/ort-wasm-simd-threaded.wasm +0 -0
  186. package/src/assets/sounds/keyboard.mp3 +0 -0
  187. package/src/assets/twp/tiledesk_widget_files/widget-css-override-example.css +0 -14
  188. package/src/assets/vad/silero_vad_legacy.onnx +0 -0
  189. package/src/assets/vad/vad.worklet.bundle.min.js +0 -1
  190. package/src/chat21-core/providers/chat-manager.spec.ts +0 -72
  191. package/tests/widget-form-rich.spec.ts +0 -67
  192. package/tests/widget-index-dev-settings.spec.ts +0 -52
  193. package/tests/widget-twp-iframe.spec.ts +0 -39
@@ -1,34 +1,32 @@
1
1
  <div id='c21-app-list-conversations'>
2
+ <!-- tabindex="1100"-->
2
3
 
3
4
  <div class="c21-header">
4
5
  <div *ngIf="checkShowAllConversation()">
5
6
  <div class="c21-title">{{g.PREV_CONVERSATIONS}}</div>
6
7
 
7
- <button *ngIf="g.showAllConversations == true"
8
- type="button"
9
- class="c21-button c21-button-clean"
10
- [attr.aria-label]="g.SHOW_ALL_CONV"
11
- (click)="returnOpenAllConversation()">
12
- <span style="display:inline-block; line-height: 40px; margin-right: 10px;">{{g.SHOW_ALL_CONV}} </span>
13
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
14
- <path d="M1.9,15.4h16.2v-1.8H1.9V15.4z M1.9,10.9h16.2V9.1H1.9V10.9z M1.9,4.6v1.8h16.2V4.6H1.9z"/>
15
- </svg>
16
- </button>
8
+ <div *ngIf="g.showAllConversations == true" class="c21-button" (click)="returnOpenAllConversation()">
9
+ <div style="display:inline-block; line-height: 40px; margin-right: 10px;" (click)="returnOpenAllConversation()">{{g.SHOW_ALL_CONV}} </div>
10
+ <button tabindex="1101" aria-label=" tutte le conversazioni" class="c21-button-clean">
11
+ <!-- <svg xmlns="http://www.w3.org/2000/svg" [ngStyle]="{'fill': g.themeColor }" width="18" height="18" viewBox="0 0 24 24">
12
+ <path fill="none" d="M0 0h24v24H0V0z" />
13
+ <path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7zm-4 6h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/>
14
+ </svg> -->
15
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
16
+ <path d="M1.9,15.4h16.2v-1.8H1.9V15.4z M1.9,10.9h16.2V9.1H1.9V10.9z M1.9,4.6v1.8h16.2V4.6H1.9z"/>
17
+ </svg>
18
+ </button>
19
+ </div>
17
20
 
18
21
  </div>
19
22
  <div *ngIf="!checkShowAllConversation()">
20
23
  <div class="c21-title">{{g.NO_CONVERSATION}}</div>
21
- <div *ngIf="listConversations && listConversations.length > 0">
22
- <button type="button"
23
- class="c21-button c21-button-clean"
24
- [attr.aria-label]="g.SHOW_ALL_CONV"
25
- (click)="returnOpenAllConversation()">
26
- <span style="display:inline-block; line-height: 40px; margin-right: 10px;">{{g.SHOW_ALL_CONV}}</span>
27
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
24
+ <div *ngIf="listConversations && listConversations.length > 0" class="c21-button" (click)="returnOpenAllConversation()">
25
+ <div style="display:inline-block; line-height: 40px; margin-right: 10px;">{{g.SHOW_ALL_CONV}}</div>
26
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
28
27
  <path fill="none" d="M0 0h24v24H0V0z" />
29
28
  <path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7zm-4 6h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/>
30
29
  </svg>
31
- </button>
32
30
  </div>
33
31
  </div>
34
32
  </div>
@@ -65,18 +63,15 @@
65
63
  <div *ngIf="isImageLoaded(agent)" #avatarImage class="c21-avatar-image" [style.background-image]="'url(' + agent.imageurl + ')'"></div>
66
64
  </div>
67
65
  </div>
68
- <button type="button" aflistconv #aflistconv class="c21-button-primary"
69
- [attr.aria-label]="g.LABEL_START_NW_CONV"
70
- (click)="openNewConversation()"
71
- [ngStyle]="{'background-color': g.themeColor, 'border-color': g.themeColor, 'color': g.themeForegroundColor }">
66
+ <button tabindex="1040" aflistconv #aflistconv class="c21-button-primary" (click)="openNewConversation()" [ngStyle]="{'background-color': g.themeColor, 'border-color': g.themeColor, 'color': g.themeForegroundColor }">
72
67
  <span class="v-align-center">
73
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
68
+ <svg [ngStyle]="{'fill': 'yellow' }" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
74
69
  <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" [ngStyle]="{'fill': g.themeForegroundColor}"/>
75
70
  </svg>
76
71
  </span>
77
72
  <span class="v-align-center c21-label-button">
78
73
  {{g.LABEL_START_NW_CONV}}
79
- </span>
74
+ </span>
80
75
  <div class="clear"></div>
81
76
  </button>
82
77
  </div>
@@ -93,15 +88,16 @@
93
88
  (onConversationLoaded)="onConversationLoadedFN($event)">
94
89
  </chat-list-conversations>
95
90
 
96
- <div class="c21-new-conversation">
97
- <button type="button" aflistconv #aflistconv class="c21-button-primary"
98
- [attr.aria-label]="g.LABEL_START_NW_CONV"
99
- (click)="openNewConversation()"
100
- [ngStyle]="{'background-color': g.themeColor, 'border-color': g.themeColor, 'color': g.themeForegroundColor }">
91
+ <div class="c21-new-conversation" >
92
+ <!-- *ngIf="this.g.supportMode" -->
93
+ <button tabindex="1040" aflistconv #aflistconv class="c21-button-primary" (click)="openNewConversation()" [ngStyle]="{'background-color': g.themeColor, 'border-color': g.themeColor, 'color': g.themeForegroundColor }">
101
94
  <span class="v-align-center">
102
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
95
+ <svg [ngStyle]="{'fill': 'yellow' }" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
103
96
  <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" [ngStyle]="{'fill': g.themeForegroundColor}"/>
104
97
  </svg>
98
+ <!-- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20" width="20" height="20" style="enable-background:new 0 0 20 20;" xml:space="preserve" >
99
+ <path d="M16.3,10.9h-5.4v5.4H9.1v-5.4H3.7V9.1h5.4V3.7h1.8v5.4h5.4V10.9z" [ngStyle]="{'fill': g.themeForegroundColor}"/>
100
+ </svg> -->
105
101
  </span>
106
102
  <span class="v-align-center c21-label-button">
107
103
  <!-- {{LABEL_START_NW_CONV}} -->
@@ -31,9 +31,6 @@
31
31
  padding: 0px 5px;
32
32
  float: right;
33
33
  fill: var(--blue);
34
- color: var(--dark-gray);
35
- font-weight: 300;
36
- align-items: center;
37
34
  button {
38
35
  width: 40px;
39
36
  height: 40px;
@@ -1,235 +1,59 @@
1
+ import { CustomTranslateService } from './../../../chat21-core/providers/custom-translate.service';
2
+ import { TranslatorService } from './../../providers/translator.service';
3
+ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
4
+ import { AppConfigService } from './../../providers/app-config.service';
5
+ import { WaitingService } from './../../providers/waiting.service';
6
+ import { ChatManager } from './../../../chat21-core/providers/chat-manager';
7
+ import { Globals } from './../../utils/globals';
1
8
  import { NO_ERRORS_SCHEMA } from '@angular/core';
2
- import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
3
- import { By } from '@angular/platform-browser';
4
- import { of, Subscription } from 'rxjs';
9
+ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
5
10
 
6
- import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
7
- import { TranslatorService } from 'src/app/providers/translator.service';
8
- import { ChatManager } from 'src/chat21-core/providers/chat-manager';
9
- import { ImageRepoService } from 'src/chat21-core/providers/abstract/image-repo.service';
11
+ import { HomeConversationsComponent } from './home-conversations.component';
12
+ import { ImageRepoService } from '../../../chat21-core/providers/abstract/image-repo.service';
13
+ import { ConversationsHandlerService } from '../../../chat21-core/providers/abstract/conversations-handler.service';
14
+ import { ArchivedConversationsHandlerService } from '../../../chat21-core/providers/abstract/archivedconversations-handler.service';
15
+ import { TranslateModule } from '@ngx-translate/core';
16
+ import { NGXLogger } from 'ngx-logger';
10
17
  import { CustomLogger } from 'src/chat21-core/providers/logger/customLogger';
11
18
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
12
- import { ConversationModel } from 'src/chat21-core/models/conversation';
13
- import { UserAgent } from 'src/models/userAgent';
14
-
15
- import { WaitingService } from 'src/app/providers/waiting.service';
16
- import { Globals } from '../../utils/globals';
17
- import { HomeConversationsComponent } from './home-conversations.component';
18
19
 
19
20
  describe('HomeConversationsComponent', () => {
20
21
  let component: HomeConversationsComponent;
21
22
  let fixture: ComponentFixture<HomeConversationsComponent>;
22
- let globals: Globals;
23
- const ngxlogger = jasmine.createSpyObj('NGXLogger', ['log', 'trace', 'debug', 'warn', 'error', 'info']);
24
-
25
- const waitingStub = {
26
- getCurrent: jasmine.createSpy('getCurrent').and.returnValue(of([{ waiting_time_avg: 45000 }])),
27
- };
28
-
29
- const imageRepoStub = {
30
- getImagePhotoUrl: jasmine.createSpy('getImagePhotoUrl').and.returnValue('https://cdn.example/photo.png'),
31
- checkImageExists: jasmine.createSpy('checkImageExists'),
32
- };
33
-
34
- const translateStub = {
35
- translateLanguage: jasmine.createSpy('translateLanguage').and.callFake((keys: string[]) => {
36
- const m = new Map<string, string>();
37
- keys.forEach((k) => m.set(k, `T:${k}`));
38
- return m;
39
- }),
40
- };
41
-
23
+ let ngxlogger: NGXLogger;
24
+ let customLogger = new CustomLogger(ngxlogger)
25
+
42
26
  beforeEach(waitForAsync(() => {
43
- LoggerInstance.setInstance(new CustomLogger(ngxlogger));
44
27
  TestBed.configureTestingModule({
45
- declarations: [HomeConversationsComponent],
46
- schemas: [NO_ERRORS_SCHEMA],
47
- providers: [
28
+ declarations: [HomeConversationsComponent],
29
+ schemas: [NO_ERRORS_SCHEMA],
30
+ imports: [TranslateModule.forRoot()],
31
+ providers: [
48
32
  Globals,
49
- { provide: ImageRepoService, useValue: imageRepoStub },
50
- { provide: ChatManager, useValue: {} },
51
- { provide: TranslatorService, useValue: { getLanguage: () => 'en' } },
52
- { provide: CustomTranslateService, useValue: translateStub },
53
- { provide: WaitingService, useValue: waitingStub },
54
- ],
55
- }).compileComponents();
33
+ ImageRepoService,
34
+ ChatManager,
35
+ ConversationsHandlerService,
36
+ ArchivedConversationsHandlerService,
37
+ WaitingService,
38
+ AppConfigService,
39
+ TranslatorService,
40
+ CustomTranslateService,
41
+ provideHttpClient(withInterceptorsFromDi())
42
+ ]
43
+ })
44
+ .compileComponents();
56
45
  }));
57
46
 
58
47
  beforeEach(() => {
59
- globals = TestBed.inject(Globals);
60
- globals.initDefafultParameters();
61
- globals.projectid = 'proj-1';
62
- globals.WAITING_TIME_FOUND = 'Tempo stimato $reply_time';
63
- globals.dynamicWaitTimeReply = true;
64
- globals.showWaitTime = true;
65
- globals.PREV_CONVERSATIONS = 'Le tue conversazioni';
66
- globals.NO_CONVERSATION = 'Nessuna';
67
- globals.SHOW_ALL_CONV = 'Vedi tutte';
68
- globals.LABEL_START_NW_CONV = 'Nuova';
69
- globals.themeColor = '#00f';
70
- globals.themeForegroundColor = '#fff';
71
- globals.showAllConversations = true;
72
- globals.showAvailableAgents = false;
73
- globals.availableAgents = [{ id: 'a1', firstname: 'Ada', imageurl: '' } as UserAgent];
74
-
75
48
  fixture = TestBed.createComponent(HomeConversationsComponent);
76
49
  component = fixture.componentInstance;
77
- component.stylesMap = new Map();
78
- component.listConversations = [];
79
- component.archivedConversations = [];
80
- component.hideNewConversationButton = false;
81
-
50
+ LoggerInstance.setInstance(customLogger)
51
+ let logger = LoggerInstance.getInstance()
52
+ component['logger']= logger
82
53
  fixture.detectChanges();
83
54
  });
84
55
 
85
56
  it('should create', () => {
86
57
  expect(component).toBeTruthy();
87
58
  });
88
-
89
- describe('initialize and waiting time', () => {
90
- it('should load translations and agent image URLs', () => {
91
- expect(translateStub.translateLanguage).toHaveBeenCalled();
92
- expect(imageRepoStub.getImagePhotoUrl).toHaveBeenCalledWith('a1');
93
- expect(component.availableAgents.length).toBe(1);
94
- });
95
-
96
- it('should set waitingTime and placeholder when API returns averages', fakeAsync(() => {
97
- tick(0);
98
- expect(waitingStub.getCurrent).toHaveBeenCalledWith('proj-1');
99
- expect(component.waitingTime).toBe(45000);
100
- expect(component.humanWaitingTime).toBeTruthy();
101
- expect(component.WAITING_TIME_FOUND_WITH_REPLYTIME_PLACEHOLDER).toContain(component.humanWaitingTime);
102
- }));
103
-
104
- it('should render root container id', () => {
105
- const root = fixture.debugElement.query(By.css('#c21-app-list-conversations'));
106
- expect(root).toBeTruthy();
107
- });
108
- });
109
-
110
- /** Allineato a twp/index + tiledesk_open: lista vuota, CTA primaria, footer tempo attesa */
111
- describe('empty state UI (widget integration)', () => {
112
- beforeEach(() => {
113
- globals.NO_CONVERSATION = 'Nessuna conversazione attiva';
114
- globals.LABEL_START_NW_CONV = 'Nuova conversazione';
115
- globals.showAvailableAgents = false;
116
- globals.availableAgents = [{ id: 'solo', firstname: 'Ada', imageurl: 'https://cdn.example/photo.png' } as UserAgent];
117
- component.listConversations = [];
118
- component.archivedConversations = [];
119
- fixture.detectChanges();
120
- });
121
-
122
- it('should show NO_CONVERSATION title in header when both lists are empty', () => {
123
- const titleEl = fixture.nativeElement.querySelector('.c21-header .c21-title') as HTMLElement;
124
- expect(titleEl.textContent?.trim()).toBe('Nessuna conversazione attiva');
125
- });
126
-
127
- it('should render primary new-conversation button with theme label and paper-plane icon', () => {
128
- const btn = fixture.nativeElement.querySelector('.c21-new-conversation .c21-button-primary') as HTMLButtonElement;
129
- expect(btn).toBeTruthy();
130
- expect(btn.getAttribute('aria-label')).toBe('Nuova conversazione');
131
- expect(btn.textContent).toContain('Nuova conversazione');
132
- expect(btn.querySelector('svg')).toBeTruthy();
133
- });
134
-
135
- it('should surface waiting footer copy when showWaitTime and API returned average', fakeAsync(() => {
136
- tick(0);
137
- fixture.detectChanges();
138
- const footer = fixture.nativeElement.querySelector('.c21-footer .c21-waiting-time') as HTMLElement;
139
- expect(footer).toBeTruthy();
140
- expect(footer.textContent).toContain(component.humanWaitingTime);
141
- }));
142
- });
143
-
144
- describe('checkShowAllConversation', () => {
145
- it('should return true when archived list has items', () => {
146
- component.archivedConversations = [{ uid: 'x' } as ConversationModel];
147
- expect(component.checkShowAllConversation()).toBe(true);
148
- });
149
-
150
- it('should return true when active list has items', () => {
151
- component.archivedConversations = [];
152
- component.listConversations = [{ uid: 'y' } as ConversationModel];
153
- expect(component.checkShowAllConversation()).toBe(true);
154
- });
155
-
156
- it('should return false when both lists are empty', () => {
157
- component.archivedConversations = [];
158
- component.listConversations = [];
159
- expect(component.checkShowAllConversation()).toBe(false);
160
- });
161
- });
162
-
163
- describe('outputs and selection', () => {
164
- it('openNewConversation should emit onNewConversation', () => {
165
- spyOn(component.onNewConversation, 'emit');
166
- component.openNewConversation();
167
- expect(component.onNewConversation.emit).toHaveBeenCalled();
168
- });
169
-
170
- it('returnOpenAllConversation should emit onOpenAllConvesations', () => {
171
- spyOn(component.onOpenAllConvesations, 'emit');
172
- component.returnOpenAllConversation();
173
- expect(component.onOpenAllConvesations.emit).toHaveBeenCalled();
174
- });
175
-
176
- it('onConversationSelectedFN should emit when conversation is defined', () => {
177
- spyOn(component.onConversationSelected, 'emit');
178
- const c = { uid: 'c1' } as ConversationModel;
179
- component.onConversationSelectedFN(c);
180
- expect(component.onConversationSelected.emit).toHaveBeenCalledWith(c);
181
- });
182
-
183
- it('onConversationSelectedFN should not emit for falsy conversation', () => {
184
- spyOn(component.onConversationSelected, 'emit');
185
- component.onConversationSelectedFN(null as any);
186
- expect(component.onConversationSelected.emit).not.toHaveBeenCalled();
187
- });
188
-
189
- it('onImageLoadedFN / onConversationLoadedFN should forward', () => {
190
- spyOn(component.onImageLoaded, 'emit');
191
- spyOn(component.onConversationLoaded, 'emit');
192
- const c = { uid: 'z' } as ConversationModel;
193
- component.onImageLoadedFN(c);
194
- component.onConversationLoadedFN(c);
195
- expect(component.onImageLoaded.emit).toHaveBeenCalledWith(c);
196
- expect(component.onConversationLoaded.emit).toHaveBeenCalledWith(c);
197
- });
198
- });
199
-
200
- describe('agent image map', () => {
201
- it('isImageLoaded should be false without url or before load', () => {
202
- const agent = { id: 'x2', firstname: 'B', imageurl: '' } as UserAgent;
203
- expect(component.isImageLoaded(agent)).toBe(false);
204
- });
205
-
206
- it('onImageLoad should mark agent as loaded', () => {
207
- const agent = { id: 'x3', imageurl: 'https://x' } as UserAgent;
208
- component.onImageLoad(agent);
209
- expect(component.isImageLoaded(agent)).toBe(true);
210
- });
211
-
212
- it('onImageError should mark agent as not loaded', () => {
213
- const agent = { id: 'x4', imageurl: 'https://x' } as UserAgent;
214
- component.onImageError(agent);
215
- expect(component.imageLoadedMap.get('x4')).toBe(false);
216
- });
217
- });
218
-
219
- describe('ngOnDestroy and unsubscribe', () => {
220
- it('unsubscribe should clear subscription list', () => {
221
- const sub = new Subscription();
222
- spyOn(sub, 'unsubscribe');
223
- component.subscriptions.push(sub);
224
- component.unsubscribe();
225
- expect(sub.unsubscribe).toHaveBeenCalled();
226
- expect(component.subscriptions.length).toBe(0);
227
- });
228
-
229
- it('ngOnDestroy should call unsubscribe', () => {
230
- spyOn(component, 'unsubscribe');
231
- component.ngOnDestroy();
232
- expect(component.unsubscribe).toHaveBeenCalled();
233
- });
234
- });
235
59
  });
@@ -10,17 +10,14 @@
10
10
  <span>View more</span>
11
11
  </div> -->
12
12
 
13
- <button type="button"
14
- aria-label="Dismiss"
15
- class="buttonClose c21-button-clean"
16
- (click)="closeMessagePreview()">
13
+ <div aria-label="Dismiss" role="button" tabindex="0" class="buttonClose" (click)="closeMessagePreview()">
17
14
  <span>
18
- <svg aria-hidden="true" focusable="false" height="20px" viewBox="0 0 24 24" width="20px" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(255, 255, 255);">
15
+ <svg aria-labelledby="altIconTitle" height="20px" role="img" viewBox="0 0 24 24" width="20px" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(255, 255, 255);">
19
16
  <path d="M0 0h24v24H0V0z" fill="none"></path>
20
17
  <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"></path>
21
18
  </svg>
22
19
  </span>
23
- </button>
20
+ </div>
24
21
 
25
22
  </div>
26
23
 
@@ -29,11 +26,8 @@
29
26
 
30
27
  <div class="container">
31
28
 
32
- <button type="button"
33
- class="previewNewMessagge c21-button-clean"
34
- [attr.aria-label]="g.START_A_CONVERSATION"
35
- (click)="openConversationByID(conversation)"
36
- [class.left-indicator]="isFirst && (!isImage(message) || isFrame(message))"
29
+ <div class="previewNewMessagge" (click)="openConversationByID(conversation)"
30
+ [class.left-indicator]="isFirst && (!isImage(message) || isFrame(message))"
37
31
  [class.no-background]="(isImage(message) || isFrame(message)) && message?.text?.trim() === ''">
38
32
 
39
33
  <chat-bubble-message class="messages no-background"
@@ -55,9 +49,9 @@
55
49
  </chat-avatar-image>
56
50
  </div>
57
51
  </div>
58
-
59
- </button>
60
-
52
+
53
+ </div>
54
+
61
55
  <div *ngIf="message?.attributes && message?.attributes?.attachment && last" class="conversations-buttons">
62
56
  <chat-message-attachment
63
57
  style="height: 100%; display: block;"
@@ -70,6 +64,6 @@
70
64
  </div>
71
65
 
72
66
  </div>
73
-
67
+
74
68
  </div>
75
69
  </div>
@@ -7,9 +7,8 @@
7
7
  min-height: 38px;
8
8
  }
9
9
  }
10
- :host .previewNewMessagge ::ng-deep > chat-bubble-message > .bubble-message > div > div > chat-text {
11
- p,
12
- .message_innerhtml {
10
+ :host .previewNewMessagge ::ng-deep > chat-bubble-message > #bubble-message > div > div > chat-text {
11
+ p {
13
12
  overflow: hidden;
14
13
  text-overflow: ellipsis;
15
14
  display: -webkit-box;
@@ -112,19 +111,6 @@
112
111
  padding: 0px 5px;
113
112
  }
114
113
 
115
- button.previewNewMessagge {
116
- display: block;
117
- align-self: stretch;
118
- max-width: 100%;
119
- text-align: left;
120
- font: inherit;
121
- -webkit-appearance: none;
122
- appearance: none;
123
- border: none;
124
- cursor: pointer;
125
- color: inherit;
126
- }
127
-
128
114
  .previewNewMessagge.no-background{
129
115
  background-color: transparent;
130
116
  box-shadow: unset;