@nyaruka/temba-components 0.132.0 → 0.134.0

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 (181) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/demo/components/flow/example.html +1 -0
  3. package/demo/components/webchat/example.html +1 -1
  4. package/demo/static/css/tailwind.css +30019 -0
  5. package/dist/locales/es.js +5 -5
  6. package/dist/locales/es.js.map +1 -1
  7. package/dist/locales/fr.js +5 -5
  8. package/dist/locales/fr.js.map +1 -1
  9. package/dist/locales/locale-codes.js +2 -11
  10. package/dist/locales/locale-codes.js.map +1 -1
  11. package/dist/locales/pt.js +5 -5
  12. package/dist/locales/pt.js.map +1 -1
  13. package/dist/temba-components.js +555 -476
  14. package/dist/temba-components.js.map +1 -1
  15. package/out-tsc/src/display/Chat.js +248 -95
  16. package/out-tsc/src/display/Chat.js.map +1 -1
  17. package/out-tsc/src/display/FloatingTab.js +4 -4
  18. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  19. package/out-tsc/src/display/TembaUser.js +3 -3
  20. package/out-tsc/src/display/TembaUser.js.map +1 -1
  21. package/out-tsc/src/events.js.map +1 -1
  22. package/out-tsc/src/flow/CanvasNode.js +132 -58
  23. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  24. package/out-tsc/src/flow/Editor.js +183 -58
  25. package/out-tsc/src/flow/Editor.js.map +1 -1
  26. package/out-tsc/src/flow/utils.js +141 -0
  27. package/out-tsc/src/flow/utils.js.map +1 -1
  28. package/out-tsc/src/interfaces.js.map +1 -1
  29. package/out-tsc/src/layout/FloatingWindow.js +1 -2
  30. package/out-tsc/src/layout/FloatingWindow.js.map +1 -1
  31. package/out-tsc/src/list/ContentMenu.js +1 -0
  32. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  33. package/out-tsc/src/list/SortableList.js +3 -2
  34. package/out-tsc/src/list/SortableList.js.map +1 -1
  35. package/out-tsc/src/live/ContactChat.js +184 -205
  36. package/out-tsc/src/live/ContactChat.js.map +1 -1
  37. package/out-tsc/src/locales/es.js +5 -5
  38. package/out-tsc/src/locales/es.js.map +1 -1
  39. package/out-tsc/src/locales/fr.js +5 -5
  40. package/out-tsc/src/locales/fr.js.map +1 -1
  41. package/out-tsc/src/locales/locale-codes.js +2 -11
  42. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  43. package/out-tsc/src/locales/pt.js +5 -5
  44. package/out-tsc/src/locales/pt.js.map +1 -1
  45. package/out-tsc/src/store/AppState.js +34 -0
  46. package/out-tsc/src/store/AppState.js.map +1 -1
  47. package/out-tsc/src/store/Store.js +5 -5
  48. package/out-tsc/src/store/Store.js.map +1 -1
  49. package/out-tsc/src/utils.js +3 -3
  50. package/out-tsc/src/utils.js.map +1 -1
  51. package/out-tsc/src/webchat/WebChat.js +22 -9
  52. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  53. package/out-tsc/test/ActionHelper.js +6 -5
  54. package/out-tsc/test/ActionHelper.js.map +1 -1
  55. package/out-tsc/test/actions/send_broadcast.test.js +9 -4
  56. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
  57. package/out-tsc/test/temba-contact-chat.test.js +1 -1
  58. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  59. package/out-tsc/test/temba-floating-window.test.js +0 -2
  60. package/out-tsc/test/temba-floating-window.test.js.map +1 -1
  61. package/out-tsc/test/temba-flow-collision.test.js +673 -0
  62. package/out-tsc/test/temba-flow-collision.test.js.map +1 -0
  63. package/out-tsc/test/temba-flow-editor-node.test.js +195 -0
  64. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  65. package/out-tsc/test/temba-utils-uuid.test.js +45 -1
  66. package/out-tsc/test/temba-utils-uuid.test.js.map +1 -1
  67. package/out-tsc/test/utils.test.js +2 -2
  68. package/out-tsc/test/utils.test.js.map +1 -1
  69. package/package.json +1 -1
  70. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  71. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  72. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  73. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  74. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  75. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  76. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  77. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  78. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  79. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  80. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  81. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  82. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  83. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  84. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  85. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  86. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  87. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  88. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  89. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  90. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  91. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  92. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  93. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  94. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  95. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  96. package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
  97. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  98. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  99. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  100. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  101. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  102. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  103. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  104. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  105. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  106. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  107. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  108. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  109. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  110. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  111. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  112. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  113. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  114. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  115. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  116. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  117. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  118. package/screenshots/truth/contacts/chat-failure.png +0 -0
  119. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  120. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  121. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  122. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  123. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  124. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  125. package/screenshots/truth/floating-tab/default.png +0 -0
  126. package/screenshots/truth/floating-tab/gray.png +0 -0
  127. package/screenshots/truth/floating-tab/green.png +0 -0
  128. package/screenshots/truth/floating-tab/hover.png +0 -0
  129. package/screenshots/truth/floating-tab/purple.png +0 -0
  130. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  131. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  132. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  133. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  134. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  135. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  136. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  137. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  138. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  139. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  140. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  141. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  142. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  143. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  144. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  145. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  146. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  147. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
  148. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  149. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  150. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  151. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  152. package/src/display/Chat.ts +331 -135
  153. package/src/display/FloatingTab.ts +4 -4
  154. package/src/display/TembaUser.ts +3 -2
  155. package/src/events.ts +12 -12
  156. package/src/flow/CanvasNode.ts +140 -57
  157. package/src/flow/Editor.ts +240 -58
  158. package/src/flow/utils.ts +207 -1
  159. package/src/interfaces.ts +7 -0
  160. package/src/layout/FloatingWindow.ts +1 -3
  161. package/src/list/ContentMenu.ts +1 -0
  162. package/src/list/SortableList.ts +3 -2
  163. package/src/live/ContactChat.ts +195 -221
  164. package/src/locales/es.ts +13 -18
  165. package/src/locales/fr.ts +13 -18
  166. package/src/locales/locale-codes.ts +2 -11
  167. package/src/locales/pt.ts +13 -18
  168. package/src/store/AppState.ts +43 -0
  169. package/src/store/Store.ts +5 -5
  170. package/src/utils.ts +3 -3
  171. package/src/webchat/WebChat.ts +24 -10
  172. package/test/ActionHelper.ts +13 -5
  173. package/test/actions/send_broadcast.test.ts +4 -2
  174. package/test/temba-contact-chat.test.ts +1 -1
  175. package/test/temba-floating-window.test.ts +0 -2
  176. package/test/temba-flow-collision.test.ts +833 -0
  177. package/test/temba-flow-editor-node.test.ts +224 -0
  178. package/test/temba-utils-uuid.test.ts +61 -1
  179. package/test/utils.test.ts +7 -2
  180. package/test-assets/contacts/history.json +22 -9
  181. package/web-test-runner.config.mjs +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/display/Chat.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, html, PropertyValueMap, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { hashCode } from '../utils';\n\nconst BATCH_TIME_WINDOW = 60 * 60 * 1000;\nconst SCROLL_FETCH_BUFFER = 0.05;\nconst MIN_FETCH_TIME = 250;\n\nexport enum MessageType {\n Inline = 'inline',\n Error = 'error',\n Collapse = 'collapse',\n Note = 'note',\n MsgIn = 'msg_in',\n MsgOut = 'msg_out'\n}\n\ninterface User {\n avatar?: string;\n email: string;\n name: string;\n}\n\nexport interface ChatEvent {\n id?: string;\n type: MessageType;\n text: TemplateResult;\n date: Date;\n user?: User;\n popup?: TemplateResult;\n}\n\nexport interface Message extends ChatEvent {\n sendError?: boolean;\n attachments?: string[];\n}\n\nconst TIME_FORMAT = { hour: 'numeric', minute: '2-digit' } as any;\nconst VERBOSE_FORMAT = {\n weekday: undefined,\n year: undefined,\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n} as any;\n\nexport class Chat extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n position: relative;\n z-index: 1;\n }\n\n slot[name='header'] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n slot[name='footer'] {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n .block {\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n }\n\n .block.outgoing {\n flex-direction: row-reverse;\n }\n\n .block.collapse {\n margin: 0;\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-bottom: 0.5em;\n }\n\n .block.collapse .messsage {\n transform: scaleY(0);\n margin: 0;\n padding: 0;\n line-height: 0;\n }\n\n .time {\n text-align: center;\n font-size: 0.8em;\n color: #999;\n margin-top: 2em;\n border-top: 1px solid #e9e9e9;\n padding: 1em;\n margin-left: 10%;\n margin-right: 10%;\n }\n\n .time.first {\n border-top: none;\n margin-top: 0;\n border-bottom: 1px solid #e9e9e9;\n margin-bottom: 2em;\n }\n\n .first .time {\n margin-top: 0;\n border-top: none;\n padding-top: 0;\n }\n\n .row {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n margin-bottom: 0.25em;\n }\n\n .input-panel {\n padding: 1em;\n background: #fff;\n }\n\n temba-user {\n margin-right: 0.6em;\n margin-left: 0.6em;\n width: 2em;\n align-self: flex-end;\n }\n\n .toggle {\n flex-shrink: 0;\n width: 4em;\n height: 4em;\n overflow: hidden;\n border-radius: 100%;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.1);\n cursor: pointer;\n transition: box-shadow var(--toggle-speed, 200ms) ease-out;\n position: absolute;\n bottom: 1em;\n right: 1em;\n }\n\n .toggle:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.4) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.2);\n }\n\n .incoming .row {\n flex-direction: row-reverse;\n margin-left: 1em;\n }\n\n .bubble {\n padding: 0.75em;\n padding-bottom: 0.25em;\n background: var(--color-chat-in, #f1f1f1);\n border-radius: var(--curvature);\n border: var(--chat-border-in, none);\n }\n\n .bubble .name {\n font-size: 0.95em;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.4);\n margin-bottom: 0.25em;\n }\n\n .outgoing .latest .bubble {\n border-bottom-left-radius: 0;\n }\n\n .incoming .bubble-wrap {\n align-items: flex-end;\n }\n\n .incoming .bubble {\n background: var(--color-chat-out, #3c92dd);\n border: var(--chat-border-out, none);\n color: white;\n }\n\n .incoming .latest .bubble {\n border-bottom-right-radius: 0;\n }\n\n .incoming .bubble .name {\n color: rgba(255, 255, 255, 0.7);\n }\n\n .note .bubble {\n background: #fffac3;\n color: rgba(0, 0, 0, 0.7);\n }\n\n .note .bubble .name {\n color: rgba(0, 0, 0, 0.5);\n }\n\n .message {\n margin-bottom: 0.5em;\n line-height: 1.2em;\n word-break: break-word;\n }\n\n .message-text {\n white-space: pre-line;\n }\n\n .chat {\n width: 28rem;\n border-radius: var(--curvature);\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, rgba(0, 0, 0, 0.1) 5em 5em 5em 5em;\n position: absolute;\n bottom: 3em;\n right: 1em;\n transition: all var(--toggle-speed, 200ms) ease-out;\n transform: scale(0.9);\n pointer-events: none;\n opacity: 0;\n }\n\n .chat.open {\n bottom: 6em;\n opacity: 1;\n transform: scale(1);\n pointer-events: initial;\n }\n\n .messages {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n }\n\n .scroll {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overflow-scrolling: touch;\n padding: 1em 1em 1em 1em;\n padding-bottom: 2.5em;\n display: flex;\n flex-direction: column-reverse;\n }\n\n .messages:before {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 0,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center top;\n height: 10px;\n display: block;\n position: absolute;\n width: 100%;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .messages:after {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 100%,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center bottom;\n height: 10px;\n display: block;\n position: absolute;\n bottom: 0;\n margin-top: -10px;\n width: 100%;\n margin-right: 5em;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .bubble-wrap {\n position: relative;\n max-width: 70%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-top: -1em;\n padding-top: 1em;\n }\n\n .scroll-at-top.messages:before {\n opacity: 0;\n }\n\n .scroll-at-bottom.messages:after {\n opacity: 0;\n }\n\n .input {\n border: none;\n flex-grow: 1;\n color: #333;\n font-size: 1em;\n }\n\n .input:focus {\n outline: none;\n }\n\n input::placeholder {\n opacity: 0.3;\n }\n\n .input.inactive {\n // pointer-events: none;\n // opacity: 0.3;\n }\n\n .active {\n }\n\n .send-icon {\n color: #eee;\n pointer-events: none;\n transform: rotate(-45deg);\n transition: transform 0.2s ease-out;\n }\n\n .pending .send-icon {\n color: var(--color-primary-dark);\n pointer-events: initial;\n transform: rotate(0deg);\n }\n\n .notice {\n padding: 1em;\n background: #f8f8f8;\n color: #666;\n text-align: center;\n cursor: pointer;\n }\n\n .connecting .notice {\n display: flex;\n justify-content: center;\n }\n\n .connecting .notice temba-icon {\n margin-left: 0.5em;\n }\n\n .reconnect {\n color: var(--color-primary-dark);\n text-decoration: underline;\n font-size: 0.9em;\n }\n\n .input:disabled {\n background: transparent !important;\n }\n\n temba-loading {\n justify-content: center;\n margin: 0.5em auto;\n margin-bottom: 2em;\n }\n\n temba-loading.hidden {\n display: none;\n }\n\n .inline {\n }\n\n .event {\n flex-grow: 1;\n align-self: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .event p {\n margin: 0;\n padding: 0;\n }\n\n .collapse {\n }\n\n a {\n color: var(--color-primary-dark);\n }\n\n .attachments {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n align-self: flex-start;\n }\n\n .incoming .attachments {\n align-self: flex-end;\n }\n\n temba-thumbnail {\n margin: 0.4em;\n border-radius: var(--curvature);\n }\n\n .error .bubble {\n border: 1px solid var(--color-error);\n background: white;\n color: #333;\n }\n\n .error .bubble .name {\n color: #999;\n }\n\n .error temba-thumbnail {\n --thumb-background: var(--color-error);\n --thumb-icon: white;\n }\n\n .outgoing .popup {\n justify-content: left;\n }\n\n .incoming .popup {\n justify-content: right;\n }\n\n .popup {\n display: flex;\n position: absolute;\n background: #fff;\n margin: 0;\n padding: 0.5em 1em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.05) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n border: 1px solid #f3f3f3;\n opacity: 0;\n transform: scale(0.7);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n z-index: 2;\n }\n\n .popup .arrow {\n z-index: 1;\n text-shadow: 0px 3px 3px rgba(0, 0, 0, 0.1);\n position: absolute;\n justify-content: center;\n text-align: center;\n font-size: 1.3em;\n transform: translateY(0.7em) scale(1);\n color: #fff;\n bottom: 0;\n }\n\n .bubble-wrap:hover .popup {\n transform: translateY(-120%);\n opacity: 1;\n transition-delay: 1s;\n }\n `;\n }\n\n @property({ type: Array })\n messageGroups: string[][] = [];\n\n @property({ type: Boolean })\n fetching = false;\n\n @property({ type: Boolean, attribute: false })\n hideTopScroll = true;\n\n @property({ type: Boolean, attribute: false })\n hideBottomScroll = true;\n\n @property({ type: String, attribute: 'avatar' })\n defaultAvatar = DEFAULT_AVATAR;\n\n @property({ type: Boolean })\n agent = false;\n\n private msgMap = new Map<string, ChatEvent>();\n\n public firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const scroll = this.shadowRoot.querySelector('.scroll');\n const hasScroll = scroll.scrollHeight > scroll.clientHeight;\n this.hideBottomScroll = true;\n this.hideTopScroll = !hasScroll;\n }\n\n public addMessages(\n messages: ChatEvent[],\n startTime: Date = null,\n append = false\n ) {\n // make sure our messages have ids\n messages.forEach((m) => {\n if (!m.id) {\n m.id =\n hashCode((m.text.strings || []).join('')) +\n '_' +\n m.date.toISOString();\n }\n });\n\n if (!startTime) {\n startTime = new Date();\n }\n\n const elapsed = new Date().getTime() - startTime.getTime();\n window.setTimeout(\n () => {\n this.fetching = false;\n // first add messages to the map\n const newMessages = [];\n for (const m of messages) {\n if (this.addMessage(m)) {\n newMessages.push(m.id);\n }\n }\n\n if (newMessages.length === 0) {\n return;\n }\n\n const ele = this.shadowRoot.querySelector('.scroll');\n const prevTop = ele.scrollTop;\n\n const grouped = this.groupMessages(newMessages);\n this.insertGroups(grouped, append);\n\n window.setTimeout(() => {\n ele.scrollTop = prevTop;\n\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }, 100);\n },\n // if it's the first load don't wait, otherwise wait a minimum amount of time\n this.messageGroups.length === 0\n ? 0\n : Math.max(0, MIN_FETCH_TIME - elapsed)\n );\n }\n\n private addMessage(msg: ChatEvent): boolean {\n const isNew = !this.messageExists(msg);\n this.msgMap.set(msg.id, msg);\n return isNew;\n }\n\n public messageExists(msg: ChatEvent): boolean {\n return this.msgMap.has(msg.id);\n }\n\n private isSameGroup(msg1: ChatEvent, msg2: ChatEvent): boolean {\n if (msg1 && msg2) {\n return (\n msg1.type === msg2.type &&\n msg1.user?.name === msg2.user?.name &&\n Math.abs(msg1.date.getTime() - msg2.date.getTime()) < BATCH_TIME_WINDOW\n );\n }\n\n return false;\n }\n\n private insertGroups(newGroups: string[][], append = false) {\n if (!append) {\n newGroups.reverse();\n }\n\n for (const newGroup of newGroups) {\n // see if our new group belongs to the most recent group\n const group =\n this.messageGroups[append ? 0 : this.messageGroups.length - 1];\n\n if (group) {\n const lastMsgId = group[group.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup[0]);\n // if our message belongs to the previous group, in we go\n if (this.isSameGroup(lastMsg, newMsg)) {\n group.push(...newGroup);\n } else {\n // otherwise, just add our entire group as a new one\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n } else {\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n }\n\n this.requestUpdate('messageGroups');\n }\n\n private groupMessages(msgIds: string[]): string[][] {\n // group our messages by origin and user\n const groups = [];\n let lastGroup = [];\n let lastMsg = null;\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n if (!this.isSameGroup(msg, lastMsg)) {\n lastGroup = [];\n groups.push(lastGroup);\n }\n lastGroup.push(msgId);\n lastMsg = msg;\n }\n return groups;\n }\n\n private handleScroll(event: any) {\n const ele = event.target;\n const top = ele.scrollHeight - ele.clientHeight;\n const scroll = Math.round(top + ele.scrollTop);\n const scrollPct = scroll / top;\n\n this.hideTopScroll = scrollPct <= 0.01;\n this.hideBottomScroll = scrollPct >= 0.99;\n\n if (scrollPct < SCROLL_FETCH_BUFFER) {\n this.fireCustomEvent(CustomEventType.ScrollThreshold);\n }\n }\n\n private scrollToBottom() {\n const scroll = this.shadowRoot.querySelector('.scroll');\n if (scroll) {\n scroll.scrollTop = scroll.scrollHeight;\n this.hideBottomScroll = true;\n }\n }\n\n private renderMessageGroup(\n msgIds: string[],\n idx: number,\n groups: string[][]\n ): TemplateResult {\n const today = new Date();\n const firstGroup = idx === groups.length - 1;\n\n let prevMsg: ChatEvent;\n if (idx > 0) {\n const lastGroup = groups[idx - 1];\n if (lastGroup && lastGroup.length > 0) {\n prevMsg = this.msgMap.get(lastGroup[0]);\n }\n }\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\n let timeDisplay = null;\n if (\n prevMsg &&\n !this.isSameGroup(prevMsg, currentMsg) &&\n (Math.abs(currentMsg.date.getTime() - prevMsg.date.getTime()) >\n BATCH_TIME_WINDOW ||\n idx === groups.length - 1)\n ) {\n if (\n today.getDate() !== prevMsg.date.getDate() ||\n prevMsg.date.getDate() !== currentMsg.date.getDate()\n ) {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, VERBOSE_FORMAT)}\n </div>`;\n } else {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, TIME_FORMAT)}\n </div>`;\n }\n }\n\n const incoming = this.agent\n ? currentMsg.type !== 'msg_in'\n : currentMsg.type === 'msg_in';\n\n const name = currentMsg.user?.name;\n const email = currentMsg.user?.email;\n\n const showAvatar =\n ((currentMsg.type === 'note' ||\n currentMsg.type === 'msg_in' ||\n currentMsg.type === 'msg_out') &&\n this.agent) ||\n !incoming;\n\n return html`\n ${!firstGroup ? timeDisplay : null}\n <div\n class=\"block ${incoming ? 'incoming' : 'outgoing'} ${currentMsg.type}\"\n >\n <div class=\"group-messages\" style=\"flex-grow:1\">\n ${msgIds.map((msgId, index) => {\n const msg = this.msgMap.get(msgId);\n return html`<div class=\"row message\">\n ${this.renderMessage(msg, index == 0 ? name : null)}\n </div>`;\n })}\n </div>\n ${showAvatar\n ? html`<div class=\"avatar\" style=\"align-self:flex-end\">\n <temba-user\n email=${email}\n name=${name}\n avatar=${currentMsg.user?.avatar}\n ?system=${!email && !name}\n >\n </temba-user>\n </div>`\n : null}\n </div>\n ${firstGroup ? timeDisplay : null}\n `;\n }\n\n private renderMessage(event: ChatEvent, name = null): TemplateResult {\n if (\n event.type === MessageType.Error ||\n event.type === MessageType.Collapse ||\n event.type === MessageType.Inline\n ) {\n return html`<div class=\"event\">${event.text}</div>`;\n }\n\n const message = event as Message;\n return html`\n <div class=\"bubble-wrap ${message.sendError ? 'error' : ''}\">\n ${\n message.popup\n ? html`<div class=\"popup\">\n ${message.popup}\n <div class=\"arrow\">▼</div>\n </div>`\n : null\n }\n \n ${\n message.text\n ? html`\n <div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message message-text\">${message.text}</div>\n\n <!--div>${message.date.toLocaleDateString(\n undefined,\n VERBOSE_FORMAT\n )}</div-->\n </div>\n `\n : null\n }\n\n <div class=\"attachments\">\n ${(message.attachments || []).map(\n (attachment) =>\n html`<temba-thumbnail\n attachment=\"${attachment}\"\n ></temba-thumbnail>`\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n public reset() {\n this.msgMap.clear();\n this.messageGroups = [];\n this.hideBottomScroll = true;\n this.hideTopScroll = true;\n }\n\n public render(): TemplateResult {\n return html` <div\n class=\"\n messages \n ${this.hideBottomScroll ? 'scroll-at-bottom' : ''}\n ${this.hideTopScroll ? 'scroll-at-top' : ''}\"\n >\n <div class=\"scroll\" @scroll=${this.handleScroll}>\n ${this.messageGroups\n ? this.messageGroups.map(\n (msgGroup, idx, groups) =>\n html`${this.renderMessageGroup(msgGroup, idx, groups)}`\n )\n : null}\n\n <temba-loading\n class=\"${!this.fetching ? 'hidden' : ''}\"\n ></temba-loading>\n </div>\n <slot class=\"header\" name=\"header\"></slot>\n <slot class=\"footer\" name=\"footer\"></slot>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/display/Chat.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, html, PropertyValueMap, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { DEFAULT_AVATAR } from '../webchat/assets';\n\nconst BATCH_TIME_WINDOW = 60 * 60 * 1000;\nconst SCROLL_FETCH_BUFFER = 200; // pixels from top\nconst MIN_FETCH_TIME = 250;\n\nconst getUnsendableReasonMessage = (reason: string): string => {\n switch (reason) {\n case 'no_route':\n return 'No channel available to send message';\n case 'contact_blocked':\n return 'Contact has been blocked';\n case 'contact_stopped':\n return 'Contact has been stopped';\n case 'contact_archived':\n return 'Contact is archived';\n case 'org_suspended':\n return 'Workspace is suspended';\n case 'looping':\n return 'Message loop detected';\n default:\n return 'Unable to send message';\n }\n};\n\nconst getStatusReasonMessage = (reason: string): string => {\n switch (reason) {\n case 'error_limit':\n return 'Error limit reached';\n case 'too_old':\n return 'Message is too old to send';\n case 'channel_removed':\n return 'Channel was removed';\n default:\n return 'Message failed to send';\n }\n};\n\nexport enum MessageType {\n Inline = 'inline',\n Error = 'error',\n Collapse = 'collapse',\n Note = 'note'\n}\n\nexport interface ObjectReference {\n uuid: string;\n name: string;\n}\n\ninterface User extends ObjectReference {\n avatar?: string;\n email: string;\n}\n\nexport interface Msg {\n text: string;\n channel: ObjectReference;\n quick_replies: string[];\n urn: string;\n direction: string;\n type: string;\n attachments: string[];\n unsendable_reason?:\n | 'no_route'\n | 'contact_blocked'\n | 'contact_stopped'\n | 'contact_archived'\n | 'org_suspended'\n | 'looping';\n}\n\nexport interface ContactEvent {\n uuid?: string;\n type: string;\n created_on: Date;\n _user?: User;\n _rendered?: { html: TemplateResult; type: MessageType };\n}\n\nexport interface MsgEvent extends ContactEvent {\n msg: Msg;\n optin?: ObjectReference;\n _status?: {\n created_on: string;\n status: 'wired' | 'sent' | 'delivered' | 'read' | 'errored' | 'failed';\n reason: 'error_limit' | 'too_old' | 'channel_removed';\n };\n _deleted?: {\n created_on: string;\n by_contact: boolean;\n user: { name: string; uuid: string };\n };\n _logs_url?: string;\n}\n\nconst TIME_FORMAT = { hour: 'numeric', minute: '2-digit' } as any;\nconst VERBOSE_FORMAT = {\n weekday: undefined,\n year: undefined,\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n} as any;\n\nexport class Chat extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n position: relative;\n z-index: 1;\n }\n\n slot[name='header'] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n slot[name='footer'] {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n .block {\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n }\n\n .block.outgoing {\n flex-direction: row-reverse;\n }\n\n .block.collapse {\n margin: 0;\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-bottom: 0.5em;\n }\n\n .block.collapse .messsage {\n transform: scaleY(0);\n margin: 0;\n padding: 0;\n line-height: 0;\n }\n\n .time {\n text-align: center;\n font-size: 0.8em;\n color: #999;\n margin-bottom: 2em;\n margin-top: 1em;\n border-top: 1px solid #e9e9e9;\n padding: 1em;\n margin-left: 10%;\n margin-right: 10%;\n }\n\n .time.first {\n border-top: none;\n margin-top: 0;\n border-bottom: 1px solid #e9e9e9;\n margin-bottom: 2em;\n }\n\n .first .time {\n margin-top: 0;\n border-top: none;\n padding-top: 0;\n }\n\n .row {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n margin-bottom: 0.25em;\n }\n\n .input-panel {\n padding: 1em;\n background: #fff;\n }\n\n temba-user {\n margin-right: 0.6em;\n margin-left: 0.6em;\n width: 2em;\n align-self: flex-end;\n }\n\n .toggle {\n flex-shrink: 0;\n width: 4em;\n height: 4em;\n overflow: hidden;\n border-radius: 100%;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.1);\n cursor: pointer;\n transition: box-shadow var(--toggle-speed, 200ms) ease-out;\n position: absolute;\n bottom: 1em;\n right: 1em;\n }\n\n .toggle:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.4) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.2);\n }\n\n .incoming .row {\n flex-direction: row-reverse;\n margin-left: 1em;\n }\n\n .bubble {\n padding: 0.75em;\n padding-bottom: 0.25em;\n background: var(--color-chat-in, #f1f1f1);\n border-radius: var(--curvature);\n border: var(--chat-border-in, none);\n }\n\n .bubble .name {\n font-size: 0.95em;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.4);\n margin-bottom: 0.25em;\n }\n\n .outgoing .latest .bubble {\n border-bottom-left-radius: 0;\n }\n\n .incoming .bubble-wrap {\n align-items: flex-end;\n }\n\n .incoming .bubble {\n background: var(--color-chat-out, #3c92dd);\n border: var(--chat-border-out, none);\n color: white;\n }\n\n .incoming .latest .bubble {\n border-bottom-right-radius: 0;\n }\n\n .incoming .bubble .name {\n color: rgba(255, 255, 255, 0.7);\n }\n\n .note .bubble {\n background: #fffac3;\n color: rgba(0, 0, 0, 0.7);\n }\n\n .note .bubble .name {\n color: rgba(0, 0, 0, 0.5);\n }\n\n .failed .bubble,\n .error .bubble {\n border: 1px solid var(--color-error);\n background: #ffe6e6;\n color: #ad4747ff;\n }\n\n .error .bubble .name,\n .failed .bubble .name {\n color: #ad47479a;\n }\n\n .message {\n margin-bottom: 0.5em;\n line-height: 1.2em;\n word-break: break-word;\n }\n\n .chat {\n width: 28rem;\n border-radius: var(--curvature);\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, rgba(0, 0, 0, 0.1) 5em 5em 5em 5em;\n position: absolute;\n bottom: 3em;\n right: 1em;\n transition: all var(--toggle-speed, 200ms) ease-out;\n transform: scale(0.9);\n pointer-events: none;\n opacity: 0;\n }\n\n .chat.open {\n bottom: 6em;\n opacity: 1;\n transform: scale(1);\n pointer-events: initial;\n }\n\n .messages {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n }\n\n .scroll {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overflow-scrolling: touch;\n padding: 1em 1em 1em 1em;\n padding-bottom: 2.5em;\n display: flex;\n flex-direction: column-reverse;\n }\n\n .messages:before {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 0,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center top;\n height: 10px;\n display: block;\n position: absolute;\n width: 100%;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .messages:after {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 100%,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center bottom;\n height: 10px;\n display: block;\n position: absolute;\n bottom: 0;\n margin-top: -10px;\n width: 100%;\n margin-right: 5em;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .bubble-wrap {\n position: relative;\n max-width: 70%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-top: -1em;\n padding-top: 1em;\n }\n\n .scroll-at-top.messages:before {\n opacity: 0;\n }\n\n .scroll-at-bottom.messages:after {\n opacity: 0;\n }\n\n .input {\n border: none;\n flex-grow: 1;\n color: #333;\n font-size: 1em;\n }\n\n .input:focus {\n outline: none;\n }\n\n input::placeholder {\n opacity: 0.3;\n }\n\n .input.inactive {\n // pointer-events: none;\n // opacity: 0.3;\n }\n\n .active {\n }\n\n .send-icon {\n color: #eee;\n pointer-events: none;\n transform: rotate(-45deg);\n transition: transform 0.2s ease-out;\n }\n\n .pending .send-icon {\n color: var(--color-primary-dark);\n pointer-events: initial;\n transform: rotate(0deg);\n }\n\n .notice {\n padding: 1em;\n background: #f8f8f8;\n color: #666;\n text-align: center;\n cursor: pointer;\n }\n\n .connecting .notice {\n display: flex;\n justify-content: center;\n }\n\n .connecting .notice temba-icon {\n margin-left: 0.5em;\n }\n\n .reconnect {\n color: var(--color-primary-dark);\n text-decoration: underline;\n font-size: 0.9em;\n }\n\n .input:disabled {\n background: transparent !important;\n }\n\n temba-loading {\n justify-content: center;\n margin: 0.5em auto;\n margin-bottom: 2em;\n }\n\n temba-loading.hidden {\n display: none;\n }\n\n .inline {\n }\n\n .event {\n flex-grow: 1;\n align-self: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .event p {\n margin: 0;\n padding: 0;\n }\n\n .collapse {\n }\n\n a {\n color: var(--color-primary-dark);\n }\n\n .attachments {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n align-self: flex-start;\n }\n\n .incoming .attachments {\n align-self: flex-end;\n }\n\n temba-thumbnail {\n margin: 0.4em;\n border-radius: var(--curvature);\n }\n\n .failed temba-thumbnail,\n .error temba-thumbnail {\n --thumb-background: #ffe6e6;\n --thumb-border: var(--color-error);\n border: 1px solid var(--color-error);\n color: #ad4747a8;\n }\n\n .outgoing .popup {\n justify-content: left;\n }\n\n .incoming .popup {\n justify-content: right;\n }\n\n .popup {\n display: flex;\n position: absolute;\n background: #fff;\n margin: 0;\n padding: 0.5em 1em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.05) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n border: 1px solid #f3f3f3;\n opacity: 0;\n transform: scale(0.7);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n z-index: 2;\n }\n\n .popup .arrow {\n z-index: 1;\n text-shadow: 0px 3px 3px rgba(0, 0, 0, 0.1);\n position: absolute;\n justify-content: center;\n text-align: center;\n font-size: 1.3em;\n transform: translateY(0.7em) scale(1);\n color: #fff;\n bottom: 0;\n }\n\n .bubble-wrap:hover .popup {\n transform: translateY(-120%);\n opacity: 1;\n transition-delay: 1s;\n }\n\n .new-message-notification {\n position: absolute;\n bottom: 1em;\n left: 50%;\n transform: translateX(-50%) translateY(100px);\n background: var(--color-primary-dark, #3c92dd);\n color: white;\n padding: 0.75em 1.5em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.2) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.3) 0px 1px 2px 0px;\n cursor: pointer;\n opacity: 0;\n transition: all 0.3s ease-out;\n z-index: 100;\n font-weight: 500;\n pointer-events: none;\n }\n\n .new-message-notification.visible {\n transform: translateX(-50%) translateY(0);\n opacity: 1;\n pointer-events: auto;\n }\n\n .new-message-notification:hover {\n background: var(--color-primary-darker, #2b7ac4);\n box-shadow: rgba(0, 0, 0, 0.3) 0px 4px 10px 0px,\n rgba(0, 0, 0, 0.4) 0px 2px 4px 0px;\n }\n `;\n }\n\n @property({ type: Array })\n messageGroups: string[][] = [];\n\n @property({ type: Boolean })\n fetching = false;\n\n @property({ type: Boolean, attribute: false })\n hideTopScroll = true;\n\n @property({ type: Boolean, attribute: false })\n hideBottomScroll = true;\n\n @property({ type: String, attribute: 'avatar' })\n defaultAvatar = DEFAULT_AVATAR;\n\n @property({ type: Boolean })\n agent = false;\n\n @property({ type: Boolean, attribute: false })\n endOfHistory = false;\n\n @property({ type: Object, attribute: false })\n oldestEventDate: Date = null;\n\n @property({ type: Boolean, attribute: false })\n showNewMessageNotification = false;\n\n @property({ type: Boolean })\n hasFooter = false;\n\n private msgMap = new Map<string, ContactEvent>();\n private metadataCache = new Map<string, ContactEvent>();\n\n public firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const scroll = this.shadowRoot.querySelector('.scroll');\n const hasScroll = scroll.scrollHeight > scroll.clientHeight;\n this.hideBottomScroll = true;\n this.hideTopScroll = !hasScroll;\n }\n\n public addMessages(\n messages: ContactEvent[],\n startTime: Date = null,\n append = false\n ) {\n if (!startTime) {\n startTime = new Date();\n }\n\n const elapsed = new Date().getTime() - startTime.getTime();\n window.setTimeout(\n () => {\n this.fetching = false;\n // first add messages to the map\n const newMessages = [];\n for (const m of messages) {\n // filter out metadata events - they aren't rendered but cached for later reference\n if (m.type === 'msg_deleted' || m.type === 'msg_status_changed') {\n const msgUuid = (m as any).msg_uuid;\n if (msgUuid) {\n this.metadataCache.set(msgUuid, m);\n }\n continue;\n }\n\n if (this.addMessage(m)) {\n newMessages.push(m.uuid);\n }\n }\n\n if (newMessages.length === 0) {\n return;\n }\n\n const ele = this.shadowRoot.querySelector('.scroll');\n const prevTop = ele.scrollTop;\n const prevScrollHeight = ele.scrollHeight;\n const scrollableHeight = ele.scrollHeight - ele.clientHeight;\n const isScrolledAway =\n scrollableHeight > 0 && Math.abs(ele.scrollTop) > 50;\n\n const grouped = this.groupMessages(newMessages);\n this.insertGroups(grouped, append);\n\n // show notification if new messages are appended and user is scrolled away from bottom\n if (append && isScrolledAway && newMessages.length > 0) {\n this.showNewMessageNotification = true;\n }\n\n window.setTimeout(() => {\n // when appending (new messages at bottom), adjust scroll to maintain visible content\n // with column-reverse, new content at bottom increases scrollHeight\n if (append && isScrolledAway) {\n const heightDiff = ele.scrollHeight - prevScrollHeight;\n ele.scrollTop = prevTop - heightDiff;\n } else {\n ele.scrollTop = prevTop;\n }\n\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }, 100);\n },\n // if it's the first load don't wait, otherwise wait a minimum amount of time\n this.messageGroups.length === 0\n ? 0\n : Math.max(0, MIN_FETCH_TIME - elapsed)\n );\n }\n\n private addMessage(msg: ContactEvent): boolean {\n const isNew = !this.messageExists(msg);\n this.msgMap.set(msg.uuid, msg);\n return isNew;\n }\n\n public messageExists(msg: ContactEvent): boolean {\n return this.msgMap.has(msg.uuid);\n }\n\n private isSameGroup(msg1: ContactEvent, msg2: ContactEvent): boolean {\n if (msg1 && msg2) {\n const sameGroup =\n msg1.type === msg2.type &&\n msg1._user?.name === msg2._user?.name &&\n Math.abs(msg1.created_on.getTime() - msg2.created_on.getTime()) <\n BATCH_TIME_WINDOW;\n return sameGroup;\n }\n\n return false;\n }\n\n private insertGroups(newGroups: string[][], append = false) {\n if (!append) {\n newGroups.reverse();\n }\n\n for (const newGroup of newGroups) {\n // see if our new group belongs to the most recent group\n const group =\n this.messageGroups[append ? 0 : this.messageGroups.length - 1];\n\n if (group) {\n const lastMsgId = group[group.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup[0]);\n // if our message belongs to the previous group, in we go\n if (this.isSameGroup(lastMsg, newMsg)) {\n group.push(...newGroup);\n } else {\n // otherwise, just add our entire group as a new one\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n } else {\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n }\n\n this.requestUpdate('messageGroups');\n }\n\n private groupMessages(msgIds: string[]): string[][] {\n // group our messages by origin and user\n const groups = [];\n let lastGroup = [];\n let lastMsg = null;\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n if (!this.isSameGroup(msg, lastMsg)) {\n lastGroup = [];\n groups.push(lastGroup);\n }\n lastGroup.push(msgId);\n lastMsg = msg;\n }\n return groups;\n }\n\n private handleScroll(event: any) {\n const ele = event.target;\n const scrollableHeight = ele.scrollHeight - ele.clientHeight;\n\n if (scrollableHeight <= 0) {\n return;\n }\n\n // with column-reverse, scrollTop behavior depends on the browser\n // check if scrollTop is negative (some browsers) or positive (others)\n const absScrollTop = Math.abs(ele.scrollTop);\n\n // when scrolling up to older messages, absScrollTop increases\n // trigger when we're close to the maximum scroll (oldest messages)\n const shouldFetch = absScrollTop >= scrollableHeight - SCROLL_FETCH_BUFFER;\n\n this.hideTopScroll = absScrollTop >= scrollableHeight - 1;\n this.hideBottomScroll = absScrollTop <= 1;\n\n // hide notification when scrolled to bottom\n if (absScrollTop <= 10) {\n this.showNewMessageNotification = false;\n }\n\n if (shouldFetch) {\n this.fireCustomEvent(CustomEventType.ScrollThreshold);\n }\n }\n\n private scrollToBottom() {\n const scroll = this.shadowRoot.querySelector('.scroll');\n if (scroll) {\n scroll.scrollTop = 0;\n this.hideBottomScroll = true;\n this.showNewMessageNotification = false;\n }\n }\n\n private handleNewMessageClick() {\n this.scrollToBottom();\n }\n\n private renderMessageGroup(\n msgIds: string[],\n idx: number,\n groups: string[][]\n ): TemplateResult {\n const today = new Date();\n const firstGroup = idx === groups.length - 1;\n\n let prevMsg: ContactEvent;\n if (idx > 0) {\n const lastGroup = groups[idx - 1];\n if (lastGroup && lastGroup.length > 0) {\n prevMsg = this.msgMap.get(lastGroup[0]);\n }\n }\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\n\n let timeDisplay = null;\n if (\n prevMsg &&\n !this.isSameGroup(prevMsg, currentMsg) &&\n (Math.abs(\n currentMsg.created_on.getTime() - prevMsg.created_on.getTime()\n ) > BATCH_TIME_WINDOW ||\n idx === groups.length - 1)\n ) {\n if (\n today.getDate() !== prevMsg.created_on.getDate() ||\n prevMsg.created_on.getDate() !== currentMsg.created_on.getDate()\n ) {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.created_on.toLocaleTimeString(undefined, VERBOSE_FORMAT)}\n </div>`;\n } else {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.created_on.toLocaleTimeString(undefined, TIME_FORMAT)}\n </div>`;\n }\n }\n\n const incoming = this.agent\n ? currentMsg.type !== 'msg_received'\n : currentMsg.type === 'msg_received';\n\n const name = currentMsg._user?.name;\n\n const showAvatar =\n ((currentMsg.type === 'msg_received' ||\n currentMsg.type === 'msg_created') &&\n this.agent) ||\n !incoming;\n\n const isSystem = !currentMsg._user?.uuid;\n\n return html`\n ${timeDisplay}\n <div class=\"block ${incoming ? 'incoming' : 'outgoing'}\">\n <div class=\"group-messages\" style=\"flex-grow:1\">\n ${repeat(\n msgIds,\n (msgId) => msgId,\n (msgId, index) => {\n const msg = this.msgMap.get(msgId);\n const msgEvent = msg as MsgEvent;\n const statusClass = (msg as any)._status\n ? (msg as any)._status.status\n : '';\n const hasError =\n msgEvent.msg?.unsendable_reason ||\n (msgEvent._status?.reason &&\n (statusClass === 'failed' || statusClass === 'errored'));\n const unsendableClass = hasError ? 'error' : '';\n return html`<div\n class=\"row message ${statusClass} ${unsendableClass}\"\n >\n ${this.renderMessage(msg, index == 0 ? name : null)}\n </div>`;\n }\n )}\n </div>\n ${showAvatar\n ? html`<div class=\"avatar\" style=\"align-self:flex-end\">\n <temba-user\n uuid=${currentMsg._user?.uuid}\n name=${name}\n avatar=${currentMsg._user?.avatar}\n ?system=${isSystem}\n >\n </temba-user>\n </div>`\n : null}\n </div>\n `;\n }\n\n private renderMessage(event: ContactEvent, name = null): TemplateResult {\n if (event._rendered) {\n return html`<div class=\"event\">${event._rendered.html}</div>`;\n }\n\n const message = event as MsgEvent;\n const unsendableReason = message.msg?.unsendable_reason;\n const statusReason = message._status?.reason;\n const errorMessage = unsendableReason\n ? getUnsendableReasonMessage(unsendableReason)\n : statusReason\n ? getStatusReasonMessage(statusReason)\n : null;\n\n return html`\n <div class=\"bubble-wrap\">\n <div class=\"popup\" style=\"white-space: nowrap;\">\n ${errorMessage\n ? html`<div style=\"color: var(--color-error); margin-right: 1em;\">\n ${errorMessage}\n </div>`\n : null}\n <temba-date\n value=\"${message.created_on.toISOString()}\"\n display=\"relative\"\n ></temba-date>\n ${message._logs_url\n ? html`<a\n style=\"margin-left: 1em; color: var(--color-primary-dark);\"\n href=\"${message._logs_url}\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n ><temba-icon name=\"log\"></temba-icon\n ></a>`\n : null}\n\n <div class=\"arrow\">▼</div>\n </div>\n ${message.msg.text\n ? html`<div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message message-text\">${message.msg.text}</div>\n </div>`\n : null}\n\n <div class=\"attachments\">\n ${(message.msg.attachments || []).map(\n (attachment) =>\n html`<temba-thumbnail\n attachment=\"${attachment}\"\n ></temba-thumbnail>`\n )}\n </div>\n </div>\n `;\n }\n\n public reset() {\n this.msgMap.clear();\n this.messageGroups = [];\n this.hideBottomScroll = true;\n this.hideTopScroll = true;\n this.endOfHistory = false;\n this.oldestEventDate = null;\n }\n\n public setEndOfHistory(oldestDate: Date) {\n this.endOfHistory = true;\n this.oldestEventDate = oldestDate;\n }\n\n public render(): TemplateResult {\n return html` <div\n class=\"\n messages \n ${this.hideBottomScroll ? 'scroll-at-bottom' : ''}\n ${this.hideTopScroll ? 'scroll-at-top' : ''}\"\n >\n <div class=\"scroll\" @scroll=${this.handleScroll}>\n ${this.messageGroups\n ? repeat(\n this.messageGroups,\n (msgGroup) => msgGroup.join(','),\n (msgGroup, idx) =>\n html`${this.renderMessageGroup(\n msgGroup,\n idx,\n this.messageGroups\n )}`\n )\n : null}\n\n <temba-loading\n class=\"${!this.fetching ? 'hidden' : ''}\"\n ></temba-loading>\n\n ${this.endOfHistory && this.oldestEventDate\n ? html`<div class=\"time first\">\n ${this.oldestEventDate.toLocaleTimeString(\n undefined,\n VERBOSE_FORMAT\n )}\n </div>`\n : null}\n </div>\n ${!this.hasFooter\n ? html`<div\n class=\"new-message-notification ${this.showNewMessageNotification\n ? 'visible'\n : ''}\"\n @click=${this.handleNewMessageClick}\n >\n New Messages\n </div>`\n : null}\n <slot class=\"header\" name=\"header\"></slot>\n <slot class=\"footer\" name=\"footer\"></slot>\n </div>`;\n }\n}\n"]}
@@ -19,7 +19,7 @@ export class FloatingTab extends RapidElement {
19
19
  .tab {
20
20
  position: fixed;
21
21
  right: 0;
22
- z-index: 9998;
22
+ z-index: 4998;
23
23
  transition: transform var(--transition-duration, 300ms) ease-in-out;
24
24
  display: flex;
25
25
  align-items: center;
@@ -42,8 +42,8 @@ export class FloatingTab extends RapidElement {
42
42
  display: flex;
43
43
  align-items: center;
44
44
  justify-content: center;
45
- width: 32px;
46
- height: 32px;
45
+ width: 16px;
46
+ height: 16px;
47
47
  }
48
48
 
49
49
  temba-icon {
@@ -139,7 +139,7 @@ export class FloatingTab extends RapidElement {
139
139
  <div class="${classes}" style="${tabStyle}" @click=${this.handleClick}>
140
140
  <div class="icon-container">
141
141
  ${this.icon
142
- ? html `<temba-icon size="2" name="${this.icon}"></temba-icon>`
142
+ ? html `<temba-icon size="1.5" name="${this.icon}"></temba-icon>`
143
143
  : ''}
144
144
  </div>
145
145
  <div class="label">${this.label}</div>
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingTab.js","sourceRoot":"","sources":["../../../src/display/FloatingTab.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { getClasses } from '../utils';\n\nexport class FloatingTab extends RapidElement {\n static get styles() {\n return css`\n .tab.hidden {\n transform: translateX(100%);\n }\n .tab {\n position: fixed;\n right: 0;\n z-index: 9998;\n transition: transform var(--transition-duration, 300ms) ease-in-out;\n display: flex;\n align-items: center;\n padding: 12px;\n border-top-left-radius: 8px;\n border-bottom-left-radius: 8px;\n cursor: pointer;\n box-shadow: -2px 2px 8px rgba(0, 0, 0, 0.2);\n transition: all calc(var(--transition-duration, 300ms) * 0.7)\n ease-in-out;\n user-select: none;\n }\n\n .tab:hover {\n padding-right: 16px;\n box-shadow: -4px 4px 12px rgba(0, 0, 0, 0.3);\n }\n\n .icon-container {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n }\n\n temba-icon {\n --icon-color: white;\n }\n\n .label {\n color: white;\n font-weight: 500;\n font-size: 16px;\n max-width: 0;\n overflow: hidden;\n white-space: nowrap;\n margin-left: 0;\n opacity: 0;\n transition: all var(--transition-duration, 300ms) ease-in-out;\n }\n\n .tab:hover .label {\n max-width: 200px;\n margin-left: 12px;\n opacity: 1;\n }\n `;\n }\n\n static TAB_HEIGHT = 56; // height of tab for auto-stacking\n static allTabs: FloatingTab[] = [];\n\n @property({ type: String })\n icon: string;\n\n @property({ type: String })\n label: string;\n\n @property({ type: String })\n color = '#6B7280';\n\n @property({ type: Number })\n top = -1; // -1 means auto-calculate position\n\n @property({ type: Boolean })\n hidden = false;\n\n connectedCallback() {\n super.connectedCallback();\n FloatingTab.allTabs.push(this);\n this.updatePosition();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n const index = FloatingTab.allTabs.indexOf(this);\n if (index > -1) {\n FloatingTab.allTabs.splice(index, 1);\n }\n // update positions of remaining tabs\n FloatingTab.allTabs.forEach((tab) => tab.updatePosition());\n }\n\n private updatePosition() {\n // if top is manually set, use it\n if (this.top !== -1) {\n return;\n }\n\n // auto-calculate position based on index\n const index = FloatingTab.allTabs.indexOf(this);\n if (index === -1) {\n this.top = 100; // default fallback\n } else {\n // start at 100px and stack with 10px gap between tabs\n this.top = 100 + index * (FloatingTab.TAB_HEIGHT + 10);\n }\n }\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('hidden')) {\n this.classList.toggle('hidden', this.hidden);\n }\n if (changes.has('top')) {\n this.updatePosition();\n }\n }\n\n private handleClick() {\n // hide all tabs when one is clicked\n FloatingTab.allTabs.forEach((tab) => {\n tab.hidden = true;\n });\n\n this.fireCustomEvent(CustomEventType.ButtonClicked, {\n action: 'toggle'\n });\n }\n\n public static showAllTabs() {\n FloatingTab.allTabs.forEach((tab) => {\n tab.hidden = false;\n });\n }\n\n public static hideAllTabs() {\n FloatingTab.allTabs.forEach((tab) => {\n tab.hidden = true;\n });\n }\n\n public render(): TemplateResult {\n const tabStyle = `\n background-color: ${this.color};\n top: ${this.top}px;\n `;\n\n const classes = getClasses({\n tab: true,\n hidden: this.hidden\n });\n\n return html`\n <div class=\"${classes}\" style=\"${tabStyle}\" @click=${this.handleClick}>\n <div class=\"icon-container\">\n ${this.icon\n ? html`<temba-icon size=\"2\" name=\"${this.icon}\"></temba-icon>`\n : ''}\n </div>\n <div class=\"label\">${this.label}</div>\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"FloatingTab.js","sourceRoot":"","sources":["../../../src/display/FloatingTab.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { getClasses } from '../utils';\n\nexport class FloatingTab extends RapidElement {\n static get styles() {\n return css`\n .tab.hidden {\n transform: translateX(100%);\n }\n .tab {\n position: fixed;\n right: 0;\n z-index: 4998;\n transition: transform var(--transition-duration, 300ms) ease-in-out;\n display: flex;\n align-items: center;\n padding: 12px;\n border-top-left-radius: 8px;\n border-bottom-left-radius: 8px;\n cursor: pointer;\n box-shadow: -2px 2px 8px rgba(0, 0, 0, 0.2);\n transition: all calc(var(--transition-duration, 300ms) * 0.7)\n ease-in-out;\n user-select: none;\n }\n\n .tab:hover {\n padding-right: 16px;\n box-shadow: -4px 4px 12px rgba(0, 0, 0, 0.3);\n }\n\n .icon-container {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n }\n\n temba-icon {\n --icon-color: white;\n }\n\n .label {\n color: white;\n font-weight: 500;\n font-size: 16px;\n max-width: 0;\n overflow: hidden;\n white-space: nowrap;\n margin-left: 0;\n opacity: 0;\n transition: all var(--transition-duration, 300ms) ease-in-out;\n }\n\n .tab:hover .label {\n max-width: 200px;\n margin-left: 12px;\n opacity: 1;\n }\n `;\n }\n\n static TAB_HEIGHT = 56; // height of tab for auto-stacking\n static allTabs: FloatingTab[] = [];\n\n @property({ type: String })\n icon: string;\n\n @property({ type: String })\n label: string;\n\n @property({ type: String })\n color = '#6B7280';\n\n @property({ type: Number })\n top = -1; // -1 means auto-calculate position\n\n @property({ type: Boolean })\n hidden = false;\n\n connectedCallback() {\n super.connectedCallback();\n FloatingTab.allTabs.push(this);\n this.updatePosition();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n const index = FloatingTab.allTabs.indexOf(this);\n if (index > -1) {\n FloatingTab.allTabs.splice(index, 1);\n }\n // update positions of remaining tabs\n FloatingTab.allTabs.forEach((tab) => tab.updatePosition());\n }\n\n private updatePosition() {\n // if top is manually set, use it\n if (this.top !== -1) {\n return;\n }\n\n // auto-calculate position based on index\n const index = FloatingTab.allTabs.indexOf(this);\n if (index === -1) {\n this.top = 100; // default fallback\n } else {\n // start at 100px and stack with 10px gap between tabs\n this.top = 100 + index * (FloatingTab.TAB_HEIGHT + 10);\n }\n }\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('hidden')) {\n this.classList.toggle('hidden', this.hidden);\n }\n if (changes.has('top')) {\n this.updatePosition();\n }\n }\n\n private handleClick() {\n // hide all tabs when one is clicked\n FloatingTab.allTabs.forEach((tab) => {\n tab.hidden = true;\n });\n\n this.fireCustomEvent(CustomEventType.ButtonClicked, {\n action: 'toggle'\n });\n }\n\n public static showAllTabs() {\n FloatingTab.allTabs.forEach((tab) => {\n tab.hidden = false;\n });\n }\n\n public static hideAllTabs() {\n FloatingTab.allTabs.forEach((tab) => {\n tab.hidden = true;\n });\n }\n\n public render(): TemplateResult {\n const tabStyle = `\n background-color: ${this.color};\n top: ${this.top}px;\n `;\n\n const classes = getClasses({\n tab: true,\n hidden: this.hidden\n });\n\n return html`\n <div class=\"${classes}\" style=\"${tabStyle}\" @click=${this.handleClick}>\n <div class=\"icon-container\">\n ${this.icon\n ? html`<temba-icon size=\"1.5\" name=\"${this.icon}\"></temba-icon>`\n : ''}\n </div>\n <div class=\"label\">${this.label}</div>\n </div>\n `;\n }\n}\n"]}
@@ -33,9 +33,6 @@ export class TembaUser extends RapidElement {
33
33
  if (this.avatar) {
34
34
  this.bgimage = `url('${this.avatar}') center / contain no-repeat`;
35
35
  }
36
- else if (!this.system) {
37
- this.bgimage = null;
38
- }
39
36
  }
40
37
  }
41
38
  render() {
@@ -124,6 +121,9 @@ __decorate([
124
121
  __decorate([
125
122
  property({ type: String })
126
123
  ], TembaUser.prototype, "email", void 0);
124
+ __decorate([
125
+ property({ type: String })
126
+ ], TembaUser.prototype, "uuid", void 0);
127
127
  __decorate([
128
128
  property({ type: String })
129
129
  ], TembaUser.prototype, "avatar", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"TembaUser.js","sourceRoot":"","sources":["../../../src/display/TembaUser.ts"],"names":[],"mappings":"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","sourcesContent":["import { PropertyValueMap, TemplateResult, css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { colorHash, extractInitials } from '../utils';\n\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { RapidElement } from '../RapidElement';\n\nexport const getFullName = (user: {\n name?: string;\n first_name?: string;\n last_name?: string;\n}) => {\n return user.name || [user.first_name, user.last_name].join(' ');\n};\n\nexport class TembaUser extends RapidElement {\n public static styles = css`\n :host {\n display: flex;\n transform: scale(var(--temba-scale, 1));\n box-sizing: border-box;\n }\n\n .wrapper {\n display: flex;\n flex-direction: row;\n align-items: center;\n flex-grow: 1;\n }\n\n .name {\n flex-grow: 1;\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n `;\n\n @property({ type: Number })\n scale: number;\n\n @property({ type: Boolean })\n showName: boolean;\n\n @property({ type: Boolean })\n system: boolean;\n\n @property({ type: String, attribute: false })\n bgimage: string = null;\n\n @property({ type: String, attribute: false })\n bgcolor: string = '#e6e6e6';\n\n @property({ type: String, attribute: false })\n initials: string = '';\n\n @property({ type: String })\n name: string;\n\n @property({ type: String })\n email: string;\n\n @property({ type: String })\n avatar: string;\n\n public updated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changed);\n\n if (changed.has('system') && this.system) {\n this.bgimage = `url('${DEFAULT_AVATAR}') center / contain no-repeat`;\n }\n\n if (changed.has('name')) {\n if (this.name) {\n this.bgcolor = colorHash.hex(this.name);\n this.initials = extractInitials(this.name);\n } else {\n this.bgcolor = '#e6e6e6';\n this.initials = '';\n }\n }\n\n if (changed.has('avatar')) {\n if (this.avatar) {\n this.bgimage = `url('${this.avatar}') center / contain no-repeat`;\n } else if (!this.system) {\n this.bgimage = null;\n }\n }\n }\n\n public render(): TemplateResult {\n return html`<div class=\"wrapper\">\n <div\n class=\"avatar-circle\"\n style=\"\n transform:scale(${this.scale || 1});\n display: flex;\n min-height: 26px;\n min-width: 26px;\n flex-direction: row;\n align-items: center;\n color: #fff;\n border-radius: 100%;\n font-weight: 400;\n overflow: hidden;\n font-size: 0.8em;\n margin-right: 0.75em;\n box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.1);\n background:${this.bgimage || this.bgcolor};\"\n >\n ${this.initials && !this.bgimage\n ? html` <div\n style=\"border: 0px solid red; display:flex; flex-direction: column; align-items:center;flex-grow:1\"\n >\n <div style=\"border:0px solid blue;\">${this.initials}</div>\n </div>`\n : null}\n </div>\n ${this.showName\n ? html`<div\n class=\"name\"\n style=\"margin: 0px ${this.scale - 0.5}em;font-size:${this.scale +\n 0.2}em\"\n >\n ${this.name}\n </div>`\n : null}\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"TembaUser.js","sourceRoot":"","sources":["../../../src/display/TembaUser.ts"],"names":[],"mappings":"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","sourcesContent":["import { PropertyValueMap, TemplateResult, css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { colorHash, extractInitials } from '../utils';\n\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { RapidElement } from '../RapidElement';\n\nexport const getFullName = (user: {\n name?: string;\n first_name?: string;\n last_name?: string;\n}) => {\n return user.name || [user.first_name, user.last_name].join(' ');\n};\n\nexport class TembaUser extends RapidElement {\n public static styles = css`\n :host {\n display: flex;\n transform: scale(var(--temba-scale, 1));\n box-sizing: border-box;\n }\n\n .wrapper {\n display: flex;\n flex-direction: row;\n align-items: center;\n flex-grow: 1;\n }\n\n .name {\n flex-grow: 1;\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n `;\n\n @property({ type: Number })\n scale: number;\n\n @property({ type: Boolean })\n showName: boolean;\n\n @property({ type: Boolean })\n system: boolean;\n\n @property({ type: String, attribute: false })\n bgimage: string = null;\n\n @property({ type: String, attribute: false })\n bgcolor: string = '#e6e6e6';\n\n @property({ type: String, attribute: false })\n initials: string = '';\n\n @property({ type: String })\n name: string;\n\n @property({ type: String })\n email: string;\n\n @property({ type: String })\n uuid: string;\n\n @property({ type: String })\n avatar: string;\n\n public updated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changed);\n\n if (changed.has('system') && this.system) {\n this.bgimage = `url('${DEFAULT_AVATAR}') center / contain no-repeat`;\n }\n\n if (changed.has('name')) {\n if (this.name) {\n this.bgcolor = colorHash.hex(this.name);\n this.initials = extractInitials(this.name);\n } else {\n this.bgcolor = '#e6e6e6';\n this.initials = '';\n }\n }\n\n if (changed.has('avatar')) {\n if (this.avatar) {\n this.bgimage = `url('${this.avatar}') center / contain no-repeat`;\n }\n }\n }\n\n public render(): TemplateResult {\n return html`<div class=\"wrapper\">\n <div\n class=\"avatar-circle\"\n style=\"\n transform:scale(${this.scale || 1});\n display: flex;\n min-height: 26px;\n min-width: 26px;\n flex-direction: row;\n align-items: center;\n color: #fff;\n border-radius: 100%;\n font-weight: 400;\n overflow: hidden;\n font-size: 0.8em;\n margin-right: 0.75em;\n box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.1);\n background:${this.bgimage || this.bgcolor};\"\n >\n ${this.initials && !this.bgimage\n ? html` <div\n style=\"border: 0px solid red; display:flex; flex-direction: column; align-items:center;flex-grow:1\"\n >\n <div style=\"border:0px solid blue;\">${this.initials}</div>\n </div>`\n : null}\n </div>\n ${this.showName\n ? html`<div\n class=\"name\"\n style=\"margin: 0px ${this.scale - 0.5}em;font-size:${this.scale +\n 0.2}em\"\n >\n ${this.name}\n </div>`\n : null}\n </div>`;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"","sourcesContent":["import { Msg, ObjectReference, User } from './interfaces';\n\nexport interface EventGroup {\n type: string;\n events: ContactEvent[];\n open: boolean;\n}\n\nexport interface ContactEvent {\n uuid?: string;\n type: string;\n created_on: string;\n _user?: ObjectReference;\n}\n\nexport interface ChannelEvent extends ContactEvent {\n channel_event_type: string;\n duration: number;\n\n event: {\n type: string;\n channel: { uuid: string; name: string };\n duration?: number;\n optin?: {\n uuid: string;\n name: string;\n };\n };\n}\n\nexport interface ContactLanguageChangedEvent extends ContactEvent {\n language: string;\n}\n\nexport interface ContactStatusChangedEvent extends ContactEvent {\n status: string;\n}\n\nexport interface OptInEvent extends ContactEvent {\n optin: {\n uuid: string;\n name: string;\n };\n}\n\nexport interface CallEvent extends ContactEvent {\n call?: {\n uuid: string;\n urn: string;\n };\n}\n\nexport interface ChatStartedEvent extends ContactEvent {\n params?: object;\n}\n\nexport interface MsgEvent extends ContactEvent {\n msg: Msg;\n optin?: ObjectReference;\n _status?: { created_on: string; status: string; reason: string };\n _logs_url?: string;\n}\n\nexport interface RunEvent extends ContactEvent {\n flow: ObjectReference;\n status: string;\n}\n\nexport interface URNsChangedEvent extends ContactEvent {\n urns: string[];\n}\n\nexport interface TicketEvent extends ContactEvent {\n ticket: {\n // ticket_opened\n uuid: string;\n topic?: ObjectReference;\n };\n ticket_uuid?: string; // all other event types\n assignee?: User;\n note?: string;\n topic?: ObjectReference;\n}\n\nexport interface NameChangedEvent extends ContactEvent {\n name: string;\n}\n\nexport interface UpdateFieldEvent extends ContactEvent {\n field: { key: string; name: string };\n value: { text: string };\n}\n\nexport interface ContactGroupsEvent extends ContactEvent {\n groups_added: ObjectReference[];\n groups_removed: ObjectReference[];\n}\n\nexport interface AirtimeTransferredEvent extends ContactEvent {\n sender: string;\n recipient: string;\n currency: string;\n amount: string;\n}\n\nexport type CallStartedEvent = ContactEvent;\n\nexport interface ContactHistoryPage {\n events: ContactEvent[];\n has_older: boolean;\n recent_only: boolean;\n next_before: number;\n next_after: number;\n}\n"]}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"","sourcesContent":["import { Msg, ObjectReference, User } from './interfaces';\nimport { ContactEvent } from './display/Chat';\n\nexport interface EventGroup {\n type: string;\n events: ContactEvent[];\n open: boolean;\n}\n\nexport interface ChannelEvent extends ContactEvent {\n channel_event_type: string;\n duration: number;\n\n event: {\n type: string;\n channel: { uuid: string; name: string };\n duration?: number;\n optin?: {\n uuid: string;\n name: string;\n };\n };\n}\n\nexport interface ContactLanguageChangedEvent extends ContactEvent {\n language: string;\n}\n\nexport interface ContactStatusChangedEvent extends ContactEvent {\n status: string;\n}\n\nexport interface OptInEvent extends ContactEvent {\n optin: {\n uuid: string;\n name: string;\n };\n}\n\nexport interface CallEvent extends ContactEvent {\n call?: {\n uuid: string;\n urn: string;\n };\n}\n\nexport interface ChatStartedEvent extends ContactEvent {\n params?: object;\n}\n\nexport interface MsgEvent extends ContactEvent {\n msg: Msg;\n optin?: ObjectReference;\n _status?: {\n created_on: string;\n status: 'wired' | 'sent' | 'delivered' | 'read' | 'errored' | 'failed';\n reason: 'error_limit' | 'too_old' | 'channel_removed';\n };\n _deleted?: {\n created_on: string;\n by_contact: boolean;\n user: { name: string; uuid: string };\n };\n _logs_url?: string;\n}\n\nexport interface RunEvent extends ContactEvent {\n flow: ObjectReference;\n status: string;\n}\n\nexport interface URNsChangedEvent extends ContactEvent {\n urns: string[];\n}\n\nexport interface TicketEvent extends ContactEvent {\n ticket: {\n // ticket_opened\n uuid: string;\n topic?: ObjectReference;\n };\n ticket_uuid?: string; // all other event types\n assignee?: User;\n note?: string;\n topic?: ObjectReference;\n}\n\nexport interface NameChangedEvent extends ContactEvent {\n name: string;\n}\n\nexport interface UpdateFieldEvent extends ContactEvent {\n field: { key: string; name: string };\n value: { text: string };\n}\n\nexport interface ContactGroupsEvent extends ContactEvent {\n groups_added: ObjectReference[];\n groups_removed: ObjectReference[];\n}\n\nexport interface AirtimeTransferredEvent extends ContactEvent {\n sender: string;\n recipient: string;\n currency: string;\n amount: string;\n}\n\nexport type CallStartedEvent = ContactEvent;\n\nexport interface ContactHistoryPage {\n events: ContactEvent[];\n next: string | null;\n}\n"]}