@nyaruka/temba-components 0.134.6 → 0.135.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +16 -8
- package/CHANGELOG.md +68 -0
- package/dist/temba-components.js +66 -60
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +7 -2
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/display/Thumbnail.js +65 -8
- package/out-tsc/src/display/Thumbnail.js.map +1 -1
- package/out-tsc/src/utils.js +7 -6
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/test/temba-thumbnail.test.js +120 -0
- package/out-tsc/test/temba-thumbnail.test.js.map +1 -0
- package/out-tsc/test/temba-utils-index.test.js +12 -6
- package/out-tsc/test/temba-utils-index.test.js.map +1 -1
- package/package.json +1 -1
- package/src/display/Chat.ts +10 -1
- package/src/display/Thumbnail.ts +67 -8
- package/src/utils.ts +6 -6
- package/test/temba-thumbnail.test.ts +150 -0
- package/test/temba-utils-index.test.ts +14 -6
|
@@ -870,7 +870,7 @@ export class Chat extends RapidElement {
|
|
|
870
870
|
return { html: resultHtml, timestamp: newLastShownTimestamp };
|
|
871
871
|
}
|
|
872
872
|
renderMessage(event, name = null) {
|
|
873
|
-
var _a, _b, _c;
|
|
873
|
+
var _a, _b, _c, _d;
|
|
874
874
|
if (event._rendered) {
|
|
875
875
|
return html `<div class="event">${event._rendered.html}</div>`;
|
|
876
876
|
}
|
|
@@ -894,6 +894,11 @@ export class Chat extends RapidElement {
|
|
|
894
894
|
? 'contact'
|
|
895
895
|
: ((_c = message._deleted.user) === null || _c === void 0 ? void 0 : _c.name) || 'user'
|
|
896
896
|
: null;
|
|
897
|
+
// check if message has location attachment and text is just coordinates
|
|
898
|
+
const hasLocationAttachment = (_d = message.msg.attachments) === null || _d === void 0 ? void 0 : _d.some((att) => att.startsWith('geo:'));
|
|
899
|
+
const textIsCoordinates = hasLocationAttachment &&
|
|
900
|
+
message.msg.text &&
|
|
901
|
+
/^-?\d+\.?\d*\s*,\s*-?\d+\.?\d*$/.test(message.msg.text.trim());
|
|
897
902
|
return html `
|
|
898
903
|
<div class="bubble-wrap">
|
|
899
904
|
<div class="popup" style="white-space: nowrap;">
|
|
@@ -925,7 +930,7 @@ export class Chat extends RapidElement {
|
|
|
925
930
|
Message deleted by ${deletedByText}
|
|
926
931
|
</div>
|
|
927
932
|
</div>`
|
|
928
|
-
: message.msg.text
|
|
933
|
+
: message.msg.text && !textIsCoordinates
|
|
929
934
|
? html `<div class="bubble">
|
|
930
935
|
${name ? html `<div class="name">${name}</div>` : null}
|
|
931
936
|
<div class="message-text">${message.msg.text}</div>
|
|
@@ -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 .deleted .bubble {\n background: #fff;\n color: #999;\n border: 1px solid #e0e0e0;\n }\n\n .deleted .bubble .name {\n color: #aaa;\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 .message-deleted {\n font-style: italic;\n margin-bottom: 0.5em;\n line-height: 1.2em;\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 const deletedClass = msgEvent._deleted ? 'deleted' : '';\n return html`<div\n class=\"row message ${statusClass} ${unsendableClass} ${deletedClass}\"\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 // handle deleted messages\n const isDeleted = message._deleted;\n const deletedByText = isDeleted\n ? message._deleted.by_contact\n ? 'contact'\n : message._deleted.user?.name || 'user'\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 ${isDeleted\n ? html`<div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message-deleted\">\n Message deleted by ${deletedByText}\n </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 .deleted .bubble {\n background: #fff;\n color: #999;\n border: 1px solid #e0e0e0;\n }\n\n .deleted .bubble .name {\n color: #aaa;\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 .message-deleted {\n font-style: italic;\n margin-bottom: 0.5em;\n line-height: 1.2em;\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 const deletedClass = msgEvent._deleted ? 'deleted' : '';\n return html`<div\n class=\"row message ${statusClass} ${unsendableClass} ${deletedClass}\"\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 // handle deleted messages\n const isDeleted = message._deleted;\n const deletedByText = isDeleted\n ? message._deleted.by_contact\n ? 'contact'\n : message._deleted.user?.name || 'user'\n : null;\n\n // check if message has location attachment and text is just coordinates\n const hasLocationAttachment = message.msg.attachments?.some((att) =>\n att.startsWith('geo:')\n );\n const textIsCoordinates =\n hasLocationAttachment &&\n message.msg.text &&\n /^-?\\d+\\.?\\d*\\s*,\\s*-?\\d+\\.?\\d*$/.test(message.msg.text.trim());\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 ${isDeleted\n ? html`<div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message-deleted\">\n Message deleted by ${deletedByText}\n </div>\n </div>`\n : message.msg.text && !textIsCoordinates\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"]}
|
|
@@ -10,6 +10,7 @@ var ThumbnailContentType;
|
|
|
10
10
|
ThumbnailContentType["AUDIO"] = "audio";
|
|
11
11
|
ThumbnailContentType["VIDEO"] = "video";
|
|
12
12
|
ThumbnailContentType["DOCUMENT"] = "document";
|
|
13
|
+
ThumbnailContentType["LOCATION"] = "location";
|
|
13
14
|
ThumbnailContentType["OTHER"] = "other";
|
|
14
15
|
})(ThumbnailContentType || (ThumbnailContentType = {}));
|
|
15
16
|
const ThumbnailIcons = {
|
|
@@ -24,6 +25,8 @@ export class Thumbnail extends RapidElement {
|
|
|
24
25
|
super(...arguments);
|
|
25
26
|
this.ratio = 0;
|
|
26
27
|
this.preview = true;
|
|
28
|
+
// cached tile URL for location thumbnails
|
|
29
|
+
this.tileUrl = '';
|
|
27
30
|
}
|
|
28
31
|
static get styles() {
|
|
29
32
|
return css `
|
|
@@ -106,6 +109,15 @@ export class Thumbnail extends RapidElement {
|
|
|
106
109
|
}
|
|
107
110
|
`;
|
|
108
111
|
}
|
|
112
|
+
// convert lat/lng to tile coordinates for OSM
|
|
113
|
+
latLngToTile(lat, lng, zoom) {
|
|
114
|
+
const n = Math.pow(2, zoom);
|
|
115
|
+
const x = Math.floor(((lng + 180) / 360) * n);
|
|
116
|
+
const latRad = (lat * Math.PI) / 180;
|
|
117
|
+
const y = Math.floor(((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2) *
|
|
118
|
+
n);
|
|
119
|
+
return { x, y, z: zoom };
|
|
120
|
+
}
|
|
109
121
|
updated(changes) {
|
|
110
122
|
super.updated(changes);
|
|
111
123
|
if (changes.has('contentType') &&
|
|
@@ -144,12 +156,35 @@ export class Thumbnail extends RapidElement {
|
|
|
144
156
|
else if (contentType.startsWith('application')) {
|
|
145
157
|
this.contentType = ThumbnailContentType.DOCUMENT;
|
|
146
158
|
}
|
|
159
|
+
else if (contentType.startsWith('geo')) {
|
|
160
|
+
this.contentType = ThumbnailContentType.LOCATION;
|
|
161
|
+
// Parse coordinates from URL which is already stripped of "geo:" prefix
|
|
162
|
+
// Format is now just: lat,lng
|
|
163
|
+
const coords = this.url.match(/^([^,]+),([^,]+)/);
|
|
164
|
+
if (coords) {
|
|
165
|
+
this.latitude = parseFloat(coords[1]);
|
|
166
|
+
this.longitude = parseFloat(coords[2]);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
147
169
|
else {
|
|
148
170
|
this.contentType = ThumbnailContentType.OTHER;
|
|
149
171
|
}
|
|
150
172
|
}
|
|
151
173
|
}
|
|
152
174
|
}
|
|
175
|
+
// calculate tile URL when latitude/longitude changes
|
|
176
|
+
if (changes.has('latitude') || changes.has('longitude')) {
|
|
177
|
+
if (this.latitude !== undefined &&
|
|
178
|
+
this.longitude !== undefined &&
|
|
179
|
+
!isNaN(this.latitude) &&
|
|
180
|
+
!isNaN(this.longitude)) {
|
|
181
|
+
const tile = this.latLngToTile(this.latitude, this.longitude, 13);
|
|
182
|
+
this.tileUrl = `https://tile.openstreetmap.org/${tile.z}/${tile.x}/${tile.y}.png`;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
this.tileUrl = '';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
153
188
|
}
|
|
154
189
|
handleThumbnailClicked() {
|
|
155
190
|
if (this.contentType === ThumbnailContentType.IMAGE && this.preview) {
|
|
@@ -158,6 +193,11 @@ export class Thumbnail extends RapidElement {
|
|
|
158
193
|
lightbox.showElement(this);
|
|
159
194
|
}, 100);
|
|
160
195
|
}
|
|
196
|
+
else if (this.contentType === ThumbnailContentType.LOCATION) {
|
|
197
|
+
// open location in openstreetmap
|
|
198
|
+
const osmUrl = `https://www.openstreetmap.org/?mlat=${this.latitude}&mlon=${this.longitude}#map=15/${this.latitude}/${this.longitude}`;
|
|
199
|
+
window.open(osmUrl, '_blank');
|
|
200
|
+
}
|
|
161
201
|
else {
|
|
162
202
|
window.open(this.url, '_blank');
|
|
163
203
|
}
|
|
@@ -180,14 +220,22 @@ export class Thumbnail extends RapidElement {
|
|
|
180
220
|
class="observe thumb ${this.contentType}"
|
|
181
221
|
src="${this.url}"
|
|
182
222
|
></img></div>`
|
|
183
|
-
: html
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
223
|
+
: html `
|
|
224
|
+
${this.contentType === ThumbnailContentType.LOCATION
|
|
225
|
+
? html `<img
|
|
226
|
+
style="height:125px;margin-bottom:-3px;border-radius:var(--curvature);"
|
|
227
|
+
src="${this.tileUrl}"
|
|
228
|
+
alt="Location preview"
|
|
229
|
+
/>`
|
|
230
|
+
: html `<div
|
|
231
|
+
style="padding:1em; background:rgba(0,0,0,.05);border-radius:var(--curvature);"
|
|
232
|
+
>
|
|
233
|
+
<temba-icon
|
|
234
|
+
size="1.5"
|
|
235
|
+
name="${ThumbnailIcons[this.contentType]}"
|
|
236
|
+
></temba-icon>
|
|
237
|
+
</div>`}
|
|
238
|
+
`}
|
|
191
239
|
</div>
|
|
192
240
|
`;
|
|
193
241
|
}
|
|
@@ -210,4 +258,13 @@ __decorate([
|
|
|
210
258
|
__decorate([
|
|
211
259
|
property({ type: String, attribute: true })
|
|
212
260
|
], Thumbnail.prototype, "contentType", void 0);
|
|
261
|
+
__decorate([
|
|
262
|
+
property({ type: Number, attribute: false })
|
|
263
|
+
], Thumbnail.prototype, "latitude", void 0);
|
|
264
|
+
__decorate([
|
|
265
|
+
property({ type: Number, attribute: false })
|
|
266
|
+
], Thumbnail.prototype, "longitude", void 0);
|
|
267
|
+
__decorate([
|
|
268
|
+
property({ type: String, attribute: false })
|
|
269
|
+
], Thumbnail.prototype, "tileUrl", void 0);
|
|
213
270
|
//# sourceMappingURL=Thumbnail.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thumbnail.js","sourceRoot":"","sources":["../../../src/display/Thumbnail.ts"],"names":[],"mappings":"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","sourcesContent":["import { PropertyValueMap, css, html } from 'lit';\nimport { RapidElement } from '../RapidElement';\nimport { property } from 'lit/decorators.js';\nimport { getClasses } from '../utils';\nimport { Lightbox } from './Lightbox';\nimport { WebChatIcon } from '../webchat';\n\nenum ThumbnailContentType {\n IMAGE = 'image',\n AUDIO = 'audio',\n VIDEO = 'video',\n DOCUMENT = 'document',\n OTHER = 'other'\n}\n\nconst ThumbnailIcons = {\n [ThumbnailContentType.IMAGE]: WebChatIcon.attachment_image,\n [ThumbnailContentType.AUDIO]: WebChatIcon.attachment_audio,\n [ThumbnailContentType.VIDEO]: WebChatIcon.attachment_video,\n [ThumbnailContentType.DOCUMENT]: WebChatIcon.attachment_document,\n [ThumbnailContentType.OTHER]: WebChatIcon.attachment\n};\n\nexport class Thumbnail extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: inline;\n }\n\n .wrapper {\n padding: var(--thumb-padding, 0.4em);\n background: var(--thumb-background, #fff);\n box-shadow: var(--widget-box-shadow);\n cursor: pointer;\n border-radius: calc(var(--curvature) * 1.5);\n border: 0px solid #f3f3f3;\n }\n\n .wrapper.zoom {\n border: none;\n padding: 0 !important;\n border-radius: 0 !important;\n overflow: hidden !important;\n }\n\n .zoom .thumb {\n border-radius: 0px !important;\n width: calc(var(--thumb-size, 4em) + 0.8em);\n max-height: calc(90vh - 10em);\n }\n\n .thumb {\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n border-radius: var(--curvature);\n max-height: calc(var(--thumb-size, 4em) * 2);\n max-width: calc(var(--thumb-size, 4em) * 2);\n height: var(--thumb-size, 4em);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 400;\n color: var(--thumb-icon, #bbb);\n }\n\n .thumb.document,\n .thumb.audio,\n .thumb.video {\n border: 1px solid #eee;\n }\n\n .wrapper:hover .thumb.icon {\n }\n\n .viewer {\n display: block;\n }\n\n .zoom .viewer {\n display: block;\n }\n\n .download {\n display: none;\n position: absolute;\n right: 0em;\n bottom: 0em;\n border-radius: var(--curvature);\n transform: scale(0.2) translate(3em, 3em);\n padding: 0.4em;\n }\n\n .zoom .download {\n display: block;\n background: rgba(0, 0, 0, 0.5);\n }\n\n .zoom .download:hover {\n background: rgba(0, 0, 0, 0.6);\n cursor: pointer;\n }\n `;\n }\n\n @property({ type: String })\n url: string;\n\n @property({ type: String })\n attachment: string;\n\n @property({ type: Number })\n ratio: number = 0;\n\n @property({ type: Boolean })\n preview: boolean = true;\n\n @property({ type: Boolean, attribute: false })\n zoom: boolean;\n\n @property({ type: String, attribute: true })\n contentType: string;\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n\n if (\n changes.has('contentType') &&\n this.contentType === ThumbnailContentType.IMAGE\n ) {\n const toObserve = this.shadowRoot.querySelector('.observe');\n if (toObserve) {\n new ResizeObserver((e, observer) => {\n if (toObserve.clientHeight > 0 && toObserve.clientWidth > 0) {\n this.ratio = toObserve.clientHeight / toObserve.clientWidth;\n this.preview =\n this.ratio === 0 || (this.ratio > 0.25 && this.ratio <= 1.5);\n observer.disconnect();\n }\n }).observe(toObserve);\n }\n }\n\n // convert our attachment to a url and label\n if (changes.has('attachment')) {\n if (this.attachment) {\n const splitIndex = this.attachment.indexOf(':');\n if (splitIndex === -1) {\n this.url = this.attachment;\n } else {\n const contentType = this.attachment.substring(0, splitIndex);\n this.url = this.attachment.substring(splitIndex + 1);\n\n if (contentType.startsWith('image')) {\n this.contentType = ThumbnailContentType.IMAGE;\n } else if (contentType.startsWith('audio')) {\n this.contentType = ThumbnailContentType.AUDIO;\n } else if (contentType.startsWith('video')) {\n this.contentType = ThumbnailContentType.VIDEO;\n } else if (contentType.startsWith('application')) {\n this.contentType = ThumbnailContentType.DOCUMENT;\n } else {\n this.contentType = ThumbnailContentType.OTHER;\n }\n }\n }\n }\n }\n\n public handleThumbnailClicked() {\n if (this.contentType === ThumbnailContentType.IMAGE && this.preview) {\n window.setTimeout(() => {\n const lightbox = document.querySelector('temba-lightbox') as Lightbox;\n lightbox.showElement(this);\n }, 100);\n } else {\n window.open(this.url, '_blank');\n }\n }\n\n public handleDownload(e: Event) {\n e.stopPropagation();\n e.preventDefault();\n\n // open this.url in another tab\n window.open(this.url, '_blank');\n }\n\n public render() {\n return html`\n <div\n @click=${this.handleThumbnailClicked.bind(this)}\n class=\"${getClasses({ wrapper: true, zoom: this.zoom })}\"\n url=${this.url}\n >\n ${this.contentType === ThumbnailContentType.IMAGE && this.preview\n ? html`<div class=\"\"><div class=\"download\" @click=${this.handleDownload.bind(\n this\n )}><temba-icon size=\"1\" style=\"color:#fff;\" name=\"download\"></temba-icon></div><img\n class=\"observe thumb ${this.contentType}\"\n src=\"${this.url}\"\n ></img></div>`\n : html`<div\n style=\"padding:1em; background:rgba(0,0,0,.05);border-radius:var(--curvature);\"\n >\n <temba-icon\n size=\"1.5\"\n name=\"${ThumbnailIcons[this.contentType]}\"\n ></temba-icon>\n </div>`}\n </div>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Thumbnail.js","sourceRoot":"","sources":["../../../src/display/Thumbnail.ts"],"names":[],"mappings":"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","sourcesContent":["import { PropertyValueMap, css, html } from 'lit';\nimport { RapidElement } from '../RapidElement';\nimport { property } from 'lit/decorators.js';\nimport { getClasses } from '../utils';\nimport { Lightbox } from './Lightbox';\nimport { WebChatIcon } from '../webchat';\n\nenum ThumbnailContentType {\n IMAGE = 'image',\n AUDIO = 'audio',\n VIDEO = 'video',\n DOCUMENT = 'document',\n LOCATION = 'location',\n OTHER = 'other'\n}\n\nconst ThumbnailIcons = {\n [ThumbnailContentType.IMAGE]: WebChatIcon.attachment_image,\n [ThumbnailContentType.AUDIO]: WebChatIcon.attachment_audio,\n [ThumbnailContentType.VIDEO]: WebChatIcon.attachment_video,\n [ThumbnailContentType.DOCUMENT]: WebChatIcon.attachment_document,\n [ThumbnailContentType.OTHER]: WebChatIcon.attachment\n};\n\nexport class Thumbnail extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: inline;\n }\n\n .wrapper {\n padding: var(--thumb-padding, 0.4em);\n background: var(--thumb-background, #fff);\n box-shadow: var(--widget-box-shadow);\n cursor: pointer;\n border-radius: calc(var(--curvature) * 1.5);\n border: 0px solid #f3f3f3;\n }\n\n .wrapper.zoom {\n border: none;\n padding: 0 !important;\n border-radius: 0 !important;\n overflow: hidden !important;\n }\n\n .zoom .thumb {\n border-radius: 0px !important;\n width: calc(var(--thumb-size, 4em) + 0.8em);\n max-height: calc(90vh - 10em);\n }\n\n .thumb {\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n border-radius: var(--curvature);\n max-height: calc(var(--thumb-size, 4em) * 2);\n max-width: calc(var(--thumb-size, 4em) * 2);\n height: var(--thumb-size, 4em);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 400;\n color: var(--thumb-icon, #bbb);\n }\n\n .thumb.document,\n .thumb.audio,\n .thumb.video {\n border: 1px solid #eee;\n }\n\n .wrapper:hover .thumb.icon {\n }\n\n .viewer {\n display: block;\n }\n\n .zoom .viewer {\n display: block;\n }\n\n .download {\n display: none;\n position: absolute;\n right: 0em;\n bottom: 0em;\n border-radius: var(--curvature);\n transform: scale(0.2) translate(3em, 3em);\n padding: 0.4em;\n }\n\n .zoom .download {\n display: block;\n background: rgba(0, 0, 0, 0.5);\n }\n\n .zoom .download:hover {\n background: rgba(0, 0, 0, 0.6);\n cursor: pointer;\n }\n `;\n }\n\n @property({ type: String })\n url: string;\n\n @property({ type: String })\n attachment: string;\n\n @property({ type: Number })\n ratio: number = 0;\n\n @property({ type: Boolean })\n preview: boolean = true;\n\n @property({ type: Boolean, attribute: false })\n zoom: boolean;\n\n @property({ type: String, attribute: true })\n contentType: string;\n\n @property({ type: Number, attribute: false })\n latitude: number;\n\n @property({ type: Number, attribute: false })\n longitude: number;\n\n // cached tile URL for location thumbnails\n @property({ type: String, attribute: false })\n private tileUrl: string = '';\n\n // convert lat/lng to tile coordinates for OSM\n private latLngToTile(lat: number, lng: number, zoom: number) {\n const n = Math.pow(2, zoom);\n const x = Math.floor(((lng + 180) / 360) * n);\n const latRad = (lat * Math.PI) / 180;\n const y = Math.floor(\n ((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2) *\n n\n );\n return { x, y, z: zoom };\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n\n if (\n changes.has('contentType') &&\n this.contentType === ThumbnailContentType.IMAGE\n ) {\n const toObserve = this.shadowRoot.querySelector('.observe');\n if (toObserve) {\n new ResizeObserver((e, observer) => {\n if (toObserve.clientHeight > 0 && toObserve.clientWidth > 0) {\n this.ratio = toObserve.clientHeight / toObserve.clientWidth;\n this.preview =\n this.ratio === 0 || (this.ratio > 0.25 && this.ratio <= 1.5);\n observer.disconnect();\n }\n }).observe(toObserve);\n }\n }\n\n // convert our attachment to a url and label\n if (changes.has('attachment')) {\n if (this.attachment) {\n const splitIndex = this.attachment.indexOf(':');\n if (splitIndex === -1) {\n this.url = this.attachment;\n } else {\n const contentType = this.attachment.substring(0, splitIndex);\n this.url = this.attachment.substring(splitIndex + 1);\n\n if (contentType.startsWith('image')) {\n this.contentType = ThumbnailContentType.IMAGE;\n } else if (contentType.startsWith('audio')) {\n this.contentType = ThumbnailContentType.AUDIO;\n } else if (contentType.startsWith('video')) {\n this.contentType = ThumbnailContentType.VIDEO;\n } else if (contentType.startsWith('application')) {\n this.contentType = ThumbnailContentType.DOCUMENT;\n } else if (contentType.startsWith('geo')) {\n this.contentType = ThumbnailContentType.LOCATION;\n // Parse coordinates from URL which is already stripped of \"geo:\" prefix\n // Format is now just: lat,lng\n const coords = this.url.match(/^([^,]+),([^,]+)/);\n if (coords) {\n this.latitude = parseFloat(coords[1]);\n this.longitude = parseFloat(coords[2]);\n }\n } else {\n this.contentType = ThumbnailContentType.OTHER;\n }\n }\n }\n }\n\n // calculate tile URL when latitude/longitude changes\n if (changes.has('latitude') || changes.has('longitude')) {\n if (\n this.latitude !== undefined &&\n this.longitude !== undefined &&\n !isNaN(this.latitude) &&\n !isNaN(this.longitude)\n ) {\n const tile = this.latLngToTile(this.latitude, this.longitude, 13);\n this.tileUrl = `https://tile.openstreetmap.org/${tile.z}/${tile.x}/${tile.y}.png`;\n } else {\n this.tileUrl = '';\n }\n }\n }\n\n public handleThumbnailClicked() {\n if (this.contentType === ThumbnailContentType.IMAGE && this.preview) {\n window.setTimeout(() => {\n const lightbox = document.querySelector('temba-lightbox') as Lightbox;\n lightbox.showElement(this);\n }, 100);\n } else if (this.contentType === ThumbnailContentType.LOCATION) {\n // open location in openstreetmap\n const osmUrl = `https://www.openstreetmap.org/?mlat=${this.latitude}&mlon=${this.longitude}#map=15/${this.latitude}/${this.longitude}`;\n window.open(osmUrl, '_blank');\n } else {\n window.open(this.url, '_blank');\n }\n }\n\n public handleDownload(e: Event) {\n e.stopPropagation();\n e.preventDefault();\n\n // open this.url in another tab\n window.open(this.url, '_blank');\n }\n\n public render() {\n return html`\n <div\n @click=${this.handleThumbnailClicked.bind(this)}\n class=\"${getClasses({ wrapper: true, zoom: this.zoom })}\"\n url=${this.url}\n >\n ${this.contentType === ThumbnailContentType.IMAGE && this.preview\n ? html`<div class=\"\"><div class=\"download\" @click=${this.handleDownload.bind(\n this\n )}><temba-icon size=\"1\" style=\"color:#fff;\" name=\"download\"></temba-icon></div><img\n class=\"observe thumb ${this.contentType}\"\n src=\"${this.url}\"\n ></img></div>`\n : html`\n ${this.contentType === ThumbnailContentType.LOCATION\n ? html`<img\n style=\"height:125px;margin-bottom:-3px;border-radius:var(--curvature);\"\n src=\"${this.tileUrl}\"\n alt=\"Location preview\"\n />`\n : html`<div\n style=\"padding:1em; background:rgba(0,0,0,.05);border-radius:var(--curvature);\"\n >\n <temba-icon\n size=\"1.5\"\n name=\"${ThumbnailIcons[this.contentType]}\"\n ></temba-icon>\n </div>`}\n `}\n </div>\n `;\n }\n}\n"]}
|
package/out-tsc/src/utils.js
CHANGED
|
@@ -42,6 +42,7 @@ export const getHTTPCookie = (name) => {
|
|
|
42
42
|
return null;
|
|
43
43
|
};
|
|
44
44
|
export const getHeaders = (headers = {}) => {
|
|
45
|
+
var _a;
|
|
45
46
|
let csrf = getHTTPCookie('csrftoken');
|
|
46
47
|
if (!csrf) {
|
|
47
48
|
const tokenEle = document.querySelector('[name=csrfmiddlewaretoken]');
|
|
@@ -50,17 +51,17 @@ export const getHeaders = (headers = {}) => {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
const fetchHeaders = csrf ? { 'X-CSRFToken': csrf } : {};
|
|
53
|
-
// include the current
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
56
|
-
fetchHeaders['X-Temba-
|
|
54
|
+
// include the current workspace identifier
|
|
55
|
+
const workspaceUUID = (_a = window.workspace) === null || _a === void 0 ? void 0 : _a.uuid;
|
|
56
|
+
if (workspaceUUID) {
|
|
57
|
+
fetchHeaders['X-Temba-Workspace'] = workspaceUUID;
|
|
57
58
|
}
|
|
58
59
|
// mark us as ajax
|
|
59
60
|
fetchHeaders['X-Requested-With'] = 'XMLHttpRequest';
|
|
60
61
|
Object.keys(headers).forEach((key) => {
|
|
61
|
-
// if we are
|
|
62
|
+
// if we are requesting to service, we omit current workspace identifier
|
|
62
63
|
if (key === 'X-Temba-Service-Org') {
|
|
63
|
-
delete fetchHeaders['X-Temba-
|
|
64
|
+
delete fetchHeaders['X-Temba-Workspace'];
|
|
64
65
|
}
|
|
65
66
|
fetchHeaders[key] = headers[key];
|
|
66
67
|
});
|