@nyaruka/temba-components 0.134.4 → 0.134.5

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.
@@ -868,7 +868,7 @@ export class Chat extends RapidElement {
868
868
  const logsURL = this.showMessageLogsAfter &&
869
869
  message.created_on >= this.showMessageLogsAfter &&
870
870
  message.msg.channel
871
- ? `/channels/channel/logs/${message.msg.channel}/msg/${event.uuid}/`
871
+ ? `/channels/channel/logs/${message.msg.channel.uuid}/msg/${event.uuid}/`
872
872
  : null;
873
873
  return html `
874
874
  <div class="bubble-wrap">
@@ -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 { 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 type GroupReason =\n | 'time_elapsed'\n | 'new_author'\n | 'new_type'\n | 'initial';\n\nexport interface MessageGroup {\n messages: string[];\n reason: GroupReason;\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;\nconst VERBOSE_FORMAT_WITH_YEAR = {\n weekday: undefined,\n year: 'numeric',\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 .group-reason {\n text-align: center;\n font-size: 0.75em;\n color: #999;\n margin-bottom: 1em;\n margin-top: 0.5em;\n padding: 0.5em 1em;\n font-style: italic;\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 margin-right: 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-text {\n white-space: pre-wrap;\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 }\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 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 opacity: 1;\n transition-delay: 1s;\n top: -35px;\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: MessageGroup[] = [];\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: Object })\n showMessageLogsAfter: Date = null;\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(\n msg1: ContactEvent,\n msg2: ContactEvent,\n lastTimeElapsedDate?: Date\n ): { same: boolean; reason?: GroupReason } {\n if (!msg1 || !msg2) {\n return { same: true };\n }\n\n // for type equivalence, treat all non-message types as the same\n const isMsg1 = msg1.type === 'msg_created' || msg1.type === 'msg_received';\n const isMsg2 = msg2.type === 'msg_created' || msg2.type === 'msg_received';\n const typeMatch =\n isMsg1 && isMsg2 ? msg1.type === msg2.type : isMsg1 === isMsg2;\n\n // check time first - if BATCH_TIME_WINDOW has passed since last time_elapsed reason\n const timeToCheck = lastTimeElapsedDate || msg1.created_on;\n if (\n Math.abs(msg2.created_on.getTime() - timeToCheck.getTime()) >=\n BATCH_TIME_WINDOW\n ) {\n return { same: false, reason: 'time_elapsed' };\n }\n\n if (!typeMatch) {\n return { same: false, reason: 'new_type' };\n }\n\n // only check author for message types\n if (isMsg1 && isMsg2 && msg1._user?.name !== msg2._user?.name) {\n return { same: false, reason: 'new_author' };\n }\n\n return { same: true };\n }\n\n private insertGroups(newGroups: MessageGroup[], 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.messages[group.messages.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup.messages[0]);\n // if our message belongs to the previous group, in we go\n const groupCheck = this.isSameGroup(lastMsg, newMsg);\n if (groupCheck.same) {\n group.messages.push(...newGroup.messages);\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[]): MessageGroup[] {\n // group our messages by origin and user\n const groups: MessageGroup[] = [];\n let lastGroup: MessageGroup = null;\n let lastMsg: ContactEvent = null;\n let lastTimeElapsedDate: Date = null;\n\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n const groupCheck = this.isSameGroup(msg, lastMsg, lastTimeElapsedDate);\n\n if (!groupCheck.same || !lastGroup) {\n lastGroup = {\n messages: [],\n reason: groupCheck.reason || 'initial'\n };\n groups.push(lastGroup);\n\n // track when we last broke for time_elapsed\n if (groupCheck.reason === 'time_elapsed') {\n lastTimeElapsedDate = msg.created_on;\n }\n }\n\n lastGroup.messages.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 getReasonLabel(reason: GroupReason): string {\n switch (reason) {\n case 'new_author':\n return '👤 Different author';\n case 'new_type':\n return '🔄 Message type changed';\n case 'time_elapsed':\n case 'initial':\n default:\n return '';\n }\n }\n\n private renderMessageGroup(\n group: MessageGroup,\n idx: number,\n lastShownTimestamp: Date | null\n ): { html: TemplateResult; timestamp: Date | null } {\n const today = new Date();\n const msgIds = group.messages;\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\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 const reasonLabel = this.getReasonLabel(group.reason);\n const showReason = false; // reasonLabel && idx > 0;\n\n // determine if we should show a timestamp\n // use the first message in the group (oldest) for the timestamp\n const firstMsgId = msgIds[0];\n const firstMsg = this.msgMap.get(firstMsgId);\n\n // check if we should show a timestamp based on the last shown timestamp\n let showTimeForReason = false;\n let newLastShownTimestamp = lastShownTimestamp;\n\n if (idx > 0) {\n if (lastShownTimestamp) {\n const timeSinceLastShown = Math.abs(\n firstMsg.created_on.getTime() - lastShownTimestamp.getTime()\n );\n showTimeForReason = timeSinceLastShown >= BATCH_TIME_WINDOW;\n } else {\n // no previous timestamp, check against previous group\n showTimeForReason = group.reason === 'time_elapsed';\n }\n }\n\n let timeForReason = null;\n if (showTimeForReason) {\n newLastShownTimestamp = firstMsg.created_on;\n\n const isDifferentYear =\n today.getFullYear() !== firstMsg.created_on.getFullYear();\n const format = isDifferentYear\n ? VERBOSE_FORMAT_WITH_YEAR\n : today.getDate() !== firstMsg.created_on.getDate()\n ? VERBOSE_FORMAT\n : TIME_FORMAT;\n\n timeForReason = html`<div class=\"time time-elapsed\">\n ${firstMsg.created_on.toLocaleTimeString(undefined, format)}\n </div>`;\n }\n\n const resultHtml = html`\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 ${showReason\n ? html`<div class=\"group-reason\">${reasonLabel}</div>`\n : null}\n ${timeForReason}\n `;\n\n return { html: resultHtml, timestamp: newLastShownTimestamp };\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 const logsURL =\n this.showMessageLogsAfter &&\n message.created_on >= this.showMessageLogsAfter &&\n message.msg.channel\n ? `/channels/channel/logs/${message.msg.channel}/msg/${event.uuid}/`\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 ${logsURL\n ? html`<a\n style=\"margin-left: 1em; color: var(--color-primary-dark);\"\n href=\"${logsURL}\"\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-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 ? (() => {\n let lastTimestamp: Date | null = null;\n // process from oldest to newest (high index to low index)\n // to establish logical time groupings going forward in time\n const results = [];\n for (let idx = this.messageGroups.length - 1; idx >= 0; idx--) {\n const msgGroup = this.messageGroups[idx];\n const result = this.renderMessageGroup(\n msgGroup,\n idx,\n lastTimestamp\n );\n lastTimestamp = result.timestamp;\n results.unshift(result.html); // add to front since we're going backwards\n }\n return results;\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"]}
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 type GroupReason =\n | 'time_elapsed'\n | 'new_author'\n | 'new_type'\n | 'initial';\n\nexport interface MessageGroup {\n messages: string[];\n reason: GroupReason;\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;\nconst VERBOSE_FORMAT_WITH_YEAR = {\n weekday: undefined,\n year: 'numeric',\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 .group-reason {\n text-align: center;\n font-size: 0.75em;\n color: #999;\n margin-bottom: 1em;\n margin-top: 0.5em;\n padding: 0.5em 1em;\n font-style: italic;\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 margin-right: 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-text {\n white-space: pre-wrap;\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 }\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 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 opacity: 1;\n transition-delay: 1s;\n top: -35px;\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: MessageGroup[] = [];\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: Object })\n showMessageLogsAfter: Date = null;\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(\n msg1: ContactEvent,\n msg2: ContactEvent,\n lastTimeElapsedDate?: Date\n ): { same: boolean; reason?: GroupReason } {\n if (!msg1 || !msg2) {\n return { same: true };\n }\n\n // for type equivalence, treat all non-message types as the same\n const isMsg1 = msg1.type === 'msg_created' || msg1.type === 'msg_received';\n const isMsg2 = msg2.type === 'msg_created' || msg2.type === 'msg_received';\n const typeMatch =\n isMsg1 && isMsg2 ? msg1.type === msg2.type : isMsg1 === isMsg2;\n\n // check time first - if BATCH_TIME_WINDOW has passed since last time_elapsed reason\n const timeToCheck = lastTimeElapsedDate || msg1.created_on;\n if (\n Math.abs(msg2.created_on.getTime() - timeToCheck.getTime()) >=\n BATCH_TIME_WINDOW\n ) {\n return { same: false, reason: 'time_elapsed' };\n }\n\n if (!typeMatch) {\n return { same: false, reason: 'new_type' };\n }\n\n // only check author for message types\n if (isMsg1 && isMsg2 && msg1._user?.name !== msg2._user?.name) {\n return { same: false, reason: 'new_author' };\n }\n\n return { same: true };\n }\n\n private insertGroups(newGroups: MessageGroup[], 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.messages[group.messages.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup.messages[0]);\n // if our message belongs to the previous group, in we go\n const groupCheck = this.isSameGroup(lastMsg, newMsg);\n if (groupCheck.same) {\n group.messages.push(...newGroup.messages);\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[]): MessageGroup[] {\n // group our messages by origin and user\n const groups: MessageGroup[] = [];\n let lastGroup: MessageGroup = null;\n let lastMsg: ContactEvent = null;\n let lastTimeElapsedDate: Date = null;\n\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n const groupCheck = this.isSameGroup(msg, lastMsg, lastTimeElapsedDate);\n\n if (!groupCheck.same || !lastGroup) {\n lastGroup = {\n messages: [],\n reason: groupCheck.reason || 'initial'\n };\n groups.push(lastGroup);\n\n // track when we last broke for time_elapsed\n if (groupCheck.reason === 'time_elapsed') {\n lastTimeElapsedDate = msg.created_on;\n }\n }\n\n lastGroup.messages.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 getReasonLabel(reason: GroupReason): string {\n switch (reason) {\n case 'new_author':\n return '👤 Different author';\n case 'new_type':\n return '🔄 Message type changed';\n case 'time_elapsed':\n case 'initial':\n default:\n return '';\n }\n }\n\n private renderMessageGroup(\n group: MessageGroup,\n idx: number,\n lastShownTimestamp: Date | null\n ): { html: TemplateResult; timestamp: Date | null } {\n const today = new Date();\n const msgIds = group.messages;\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\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 const reasonLabel = this.getReasonLabel(group.reason);\n const showReason = false; // reasonLabel && idx > 0;\n\n // determine if we should show a timestamp\n // use the first message in the group (oldest) for the timestamp\n const firstMsgId = msgIds[0];\n const firstMsg = this.msgMap.get(firstMsgId);\n\n // check if we should show a timestamp based on the last shown timestamp\n let showTimeForReason = false;\n let newLastShownTimestamp = lastShownTimestamp;\n\n if (idx > 0) {\n if (lastShownTimestamp) {\n const timeSinceLastShown = Math.abs(\n firstMsg.created_on.getTime() - lastShownTimestamp.getTime()\n );\n showTimeForReason = timeSinceLastShown >= BATCH_TIME_WINDOW;\n } else {\n // no previous timestamp, check against previous group\n showTimeForReason = group.reason === 'time_elapsed';\n }\n }\n\n let timeForReason = null;\n if (showTimeForReason) {\n newLastShownTimestamp = firstMsg.created_on;\n\n const isDifferentYear =\n today.getFullYear() !== firstMsg.created_on.getFullYear();\n const format = isDifferentYear\n ? VERBOSE_FORMAT_WITH_YEAR\n : today.getDate() !== firstMsg.created_on.getDate()\n ? VERBOSE_FORMAT\n : TIME_FORMAT;\n\n timeForReason = html`<div class=\"time time-elapsed\">\n ${firstMsg.created_on.toLocaleTimeString(undefined, format)}\n </div>`;\n }\n\n const resultHtml = html`\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 ${showReason\n ? html`<div class=\"group-reason\">${reasonLabel}</div>`\n : null}\n ${timeForReason}\n `;\n\n return { html: resultHtml, timestamp: newLastShownTimestamp };\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 const logsURL =\n this.showMessageLogsAfter &&\n message.created_on >= this.showMessageLogsAfter &&\n message.msg.channel\n ? `/channels/channel/logs/${message.msg.channel.uuid}/msg/${event.uuid}/`\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 ${logsURL\n ? html`<a\n style=\"margin-left: 1em; color: var(--color-primary-dark);\"\n href=\"${logsURL}\"\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-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 ? (() => {\n let lastTimestamp: Date | null = null;\n // process from oldest to newest (high index to low index)\n // to establish logical time groupings going forward in time\n const results = [];\n for (let idx = this.messageGroups.length - 1; idx >= 0; idx--) {\n const msgGroup = this.messageGroups[idx];\n const result = this.renderMessageGroup(\n msgGroup,\n idx,\n lastTimestamp\n );\n lastTimestamp = result.timestamp;\n results.unshift(result.html); // add to front since we're going backwards\n }\n return results;\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyaruka/temba-components",
3
- "version": "0.134.4",
3
+ "version": "0.134.5",
4
4
  "description": "Web components to support rapidpro and related projects",
5
5
  "author": "Nyaruka <code@nyaruka.coim>",
6
6
  "main": "dist/index.js",
@@ -1030,7 +1030,7 @@ export class Chat extends RapidElement {
1030
1030
  this.showMessageLogsAfter &&
1031
1031
  message.created_on >= this.showMessageLogsAfter &&
1032
1032
  message.msg.channel
1033
- ? `/channels/channel/logs/${message.msg.channel}/msg/${event.uuid}/`
1033
+ ? `/channels/channel/logs/${message.msg.channel.uuid}/msg/${event.uuid}/`
1034
1034
  : null;
1035
1035
 
1036
1036
  return html`