@nyaruka/temba-components 0.26.6 → 0.26.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/CHANGELOG.md +28 -0
- package/demo/index.html +9 -1
- package/dist/{29fc0c7c.js → d0cc86be.js} +403 -56
- package/dist/index.js +403 -56
- package/dist/static/icons/symbol-defs.svg +13 -1
- package/dist/static/img/schemes/email.svg +1 -0
- package/dist/static/img/schemes/facebook.svg +1 -0
- package/dist/static/img/schemes/instagram.svg +1 -0
- package/dist/static/img/schemes/line.svg +1 -0
- package/dist/static/img/schemes/messenger.svg +1 -0
- package/dist/static/img/schemes/tel.svg +34 -0
- package/dist/static/img/schemes/telegram.svg +1 -0
- package/dist/static/img/schemes/twitter.svg +1 -0
- package/dist/static/img/schemes/viber.svg +1 -0
- package/dist/static/img/schemes/vk.svg +1 -0
- package/dist/static/img/schemes/whatsapp.svg +1 -0
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/RapidElement.js.map +1 -1
- package/out-tsc/src/RefreshElement.js +28 -0
- package/out-tsc/src/RefreshElement.js.map +1 -0
- package/out-tsc/src/button/Button.js +4 -0
- package/out-tsc/src/button/Button.js.map +1 -1
- package/out-tsc/src/contacts/ContactChat.js +5 -13
- package/out-tsc/src/contacts/ContactChat.js.map +1 -1
- package/out-tsc/src/contacts/ContactFieldEditor.js +199 -0
- package/out-tsc/src/contacts/ContactFieldEditor.js.map +1 -0
- package/out-tsc/src/contacts/ContactFields.js +106 -0
- package/out-tsc/src/contacts/ContactFields.js.map +1 -0
- package/out-tsc/src/contacts/ContactGroups.js +39 -0
- package/out-tsc/src/contacts/ContactGroups.js.map +1 -0
- package/out-tsc/src/contacts/ContactName.js +40 -0
- package/out-tsc/src/contacts/ContactName.js.map +1 -0
- package/out-tsc/src/contacts/ContactStoreElement.js +44 -0
- package/out-tsc/src/contacts/ContactStoreElement.js.map +1 -0
- package/out-tsc/src/contacts/ContactUrn.js +38 -0
- package/out-tsc/src/contacts/ContactUrn.js.map +1 -0
- package/out-tsc/src/contacts/events.js +76 -30
- package/out-tsc/src/contacts/events.js.map +1 -1
- package/out-tsc/src/contactsearch/ContactSearch.js +1 -1
- package/out-tsc/src/contactsearch/ContactSearch.js.map +1 -1
- package/out-tsc/src/interfaces.js +1 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/label/Label.js +32 -12
- package/out-tsc/src/label/Label.js.map +1 -1
- package/out-tsc/src/select/Select.js +4 -4
- package/out-tsc/src/select/Select.js.map +1 -1
- package/out-tsc/src/store/Store.js +97 -3
- package/out-tsc/src/store/Store.js.map +1 -1
- package/out-tsc/src/store/StoreElement.js +55 -0
- package/out-tsc/src/store/StoreElement.js.map +1 -0
- package/out-tsc/src/textinput/TextInput.js +35 -17
- package/out-tsc/src/textinput/TextInput.js.map +1 -1
- package/out-tsc/src/vectoricon/VectorIcon.js +16 -14
- package/out-tsc/src/vectoricon/VectorIcon.js.map +1 -1
- package/out-tsc/temba-modules.js +12 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-contact-history.test.js +1 -1
- package/out-tsc/test/temba-contact-history.test.js.map +1 -1
- package/package.json +4 -5
- package/rollup.config.js +1 -0
- package/screenshots/truth/contacts/history.png +0 -0
- package/src/RapidElement.ts +0 -1
- package/src/RefreshElement.ts +33 -0
- package/src/button/Button.ts +4 -0
- package/src/contacts/ContactChat.ts +7 -16
- package/src/contacts/ContactFieldEditor.ts +201 -0
- package/src/contacts/ContactFields.ts +112 -0
- package/src/contacts/ContactGroups.ts +41 -0
- package/src/contacts/ContactName.ts +37 -0
- package/src/contacts/ContactStoreElement.ts +51 -0
- package/src/contacts/ContactUrn.ts +38 -0
- package/src/contacts/events.ts +83 -30
- package/src/contactsearch/ContactSearch.ts +1 -1
- package/src/interfaces.ts +2 -0
- package/src/label/Label.ts +30 -7
- package/src/select/Select.ts +4 -4
- package/src/store/Store.ts +124 -3
- package/src/store/StoreElement.ts +71 -0
- package/src/textinput/TextInput.ts +48 -27
- package/src/vectoricon/VectorIcon.ts +19 -14
- package/static/icons/Read Me.txt +1 -1
- package/static/icons/SVG/calendar1.svg +5 -0
- package/static/icons/SVG/corner-down-left.svg +5 -0
- package/static/icons/SVG/more-horizontal.svg +5 -0
- package/static/icons/SVG/refresh-cw.svg +5 -0
- package/static/icons/demo-external-svg.html +21 -1
- package/static/icons/demo.html +34 -2
- package/static/icons/selection.json +412 -316
- package/static/icons/symbol-defs.svg +13 -1
- package/static/img/schemes/email.svg +1 -0
- package/static/img/schemes/facebook.svg +1 -0
- package/static/img/schemes/instagram.svg +1 -0
- package/static/img/schemes/line.svg +1 -0
- package/static/img/schemes/messenger.svg +1 -0
- package/static/img/schemes/tel.svg +34 -0
- package/static/img/schemes/telegram.svg +1 -0
- package/static/img/schemes/twitter.svg +1 -0
- package/static/img/schemes/viber.svg +1 -0
- package/static/img/schemes/vk.svg +1 -0
- package/static/img/schemes/whatsapp.svg +1 -0
- package/temba-modules.ts +12 -0
- package/test/temba-contact-history.test.ts +1 -1
- package/test-assets/contacts/history.json +5 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactFieldEditor.js","sourceRoot":"","sources":["../../../src/contacts/ContactFieldEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators';\nimport { RapidElement } from '../RapidElement';\nimport { TextInput } from '../textinput/TextInput';\n\nexport class ContactFieldEditor extends RapidElement {\n @property({ type: String })\n key: string;\n\n @property({ type: String })\n value: string;\n\n @property({ type: String })\n name: string;\n\n @property({ type: String })\n type: string;\n\n @property({ type: String })\n icon = navigator.clipboard ? 'copy' : '';\n\n @property({ type: String })\n iconClass = '';\n\n static get styles() {\n return css`\n .prefix {\n background: rgba(0, 0, 0, 0.05);\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n color: #888;\n cursor: pointer;\n width: 100px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n padding: 0em 0.5em;\n }\n\n .prefix .name {\n padding: 0.5em 0em;\n color: #888;\n width: 80px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .postfix {\n display: flex;\n align-items: stretch;\n }\n\n .popper {\n padding: 0.5em 0.75em;\n background: rgba(240, 240, 240, 1);\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n --icon-color: #888;\n opacity: 0;\n cursor: default;\n transform: scale(0.5);\n transition: all 300ms ease-in-out;\n display: flex;\n align-items: stretch;\n z-index: 1000;\n }\n\n .postfix temba-icon[name='calendar'] {\n --icon-color: #e3e3e3;\n }\n\n .popper.check {\n background: rgba(90, 145, 86, 0.15);\n }\n\n .popper.none {\n opacity: 0;\n }\n\n .popper.copy temba-icon:hover {\n --icon-color: #555;\n }\n\n .popper.corner-down-left {\n // background: var(--color-primary-dark);\n // --icon-color: var(--color-text-light);\n opacity: 1;\n transform: scale(1);\n }\n\n temba-icon {\n cursor: pointer;\n }\n\n temba-icon[name='check'] {\n --icon-color: rgb(90, 145, 86);\n }\n\n temba-textinput:hover .popper.copy {\n opacity: 1;\n transform: scale(1);\n }\n\n temba-textinput:focus .popper.copy {\n opacity: 1;\n transform: scale(1);\n }\n\n .copy.clicked temba-icon {\n transform: scale(1.2);\n }\n\n temba-icon {\n transition: all 200ms ease-in-out;\n }\n `;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.handleInput = this.handleInput.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n public handleIconClick(evt: MouseEvent) {\n const ele = evt.target as HTMLDivElement;\n const icon = ele.getAttribute('name');\n const input = this.shadowRoot.querySelector('temba-textinput') as TextInput;\n\n if (icon === 'copy') {\n if (navigator.clipboard) {\n this.iconClass = 'clicked';\n navigator.clipboard.writeText(input.getDisplayValue()).then(() => {\n window.setTimeout(() => {\n this.iconClass = '';\n }, 300);\n });\n }\n }\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n public handleSubmit() {\n const input = this.shadowRoot.querySelector('temba-textinput') as TextInput;\n if (input.value !== this.value) {\n this.value = input.value;\n this.fireEvent('change');\n }\n this.icon = navigator.clipboard ? 'copy' : '';\n }\n\n public handleChange(evt: Event) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n public handleInput(evt: KeyboardEvent) {\n if (evt.key === 'Enter') {\n const input = evt.currentTarget as TextInput;\n input.blur();\n }\n }\n\n public render(): TemplateResult {\n return html`\n <div>\n <temba-textinput\n value=\"${this.value ? this.value : ''}\"\n ?datetimepicker=${this.type === 'datetime'}\n @blur=${this.handleSubmit}\n @keydown=${this.handleInput}\n @change=${this.handleChange}\n >\n <div class=\"prefix\" slot=\"prefix\">\n <div class=\"name\">${this.name}</div>\n </div>\n\n <div class=\"postfix\">\n ${this.type === 'datetime'\n ? html`<div\n style=\"position: absolute; padding-top: .75em; padding-left: .75em;\"\n >\n <temba-icon name=\"calendar\" />\n </div>`\n : null}\n\n <div\n class=\"popper ${this.iconClass} ${this.icon ? this.icon : 'none'}\"\n @click=${this.handleIconClick}\n >\n <temba-icon name=\"${this.icon}\" animatechange=\"spin\"></temba-icon>\n </div>\n </div>\n </temba-textinput>\n </div>\n `;\n }\n}\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { css, html } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators';
|
|
4
|
+
import { postJSON } from '../utils';
|
|
5
|
+
import { ContactStoreElement } from './ContactStoreElement';
|
|
6
|
+
export class ContactFields extends ContactStoreElement {
|
|
7
|
+
static get styles() {
|
|
8
|
+
return css `
|
|
9
|
+
:host {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-wrap: wrap;
|
|
12
|
+
flex-shrink: 1;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.field {
|
|
16
|
+
display: flex;
|
|
17
|
+
margin: 0.3em 0.3em;
|
|
18
|
+
box-shadow: 0 0 0.2em rgba(0, 0, 0, 0.15);
|
|
19
|
+
border-radius: var(--curvature);
|
|
20
|
+
align-items: center;
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.field.set {
|
|
25
|
+
background: #fff;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.field.unset {
|
|
29
|
+
opacity: 0.4;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.field.unset .label {
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.field:hover {
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.field:hover {
|
|
39
|
+
box-shadow: 1px 1px 6px 2px rgba(0, 0, 0, 0.05),
|
|
40
|
+
0px 0px 0px 2px var(--color-link-primary);
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.label {
|
|
45
|
+
padding: 0.25em 1em;
|
|
46
|
+
border-top-left-radius: var(--curvature);
|
|
47
|
+
border-bottom-left-radius: var(--curvature);
|
|
48
|
+
color: #777;
|
|
49
|
+
font-size: 0.9em;
|
|
50
|
+
font-weight: 400;
|
|
51
|
+
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.1) inset;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.value {
|
|
55
|
+
--icon-color: #ddd;
|
|
56
|
+
max-width: 150px;
|
|
57
|
+
white-space: nowrap;
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
text-overflow: ellipsis;
|
|
60
|
+
padding: 0.25em 1em;
|
|
61
|
+
border-top-right-radius: var(--curvature);
|
|
62
|
+
border-bottom-right-radius: var(--curvature);
|
|
63
|
+
font-size: 0.9em;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
temba-contact-field {
|
|
67
|
+
margin: 0.3em;
|
|
68
|
+
min-width: 320px;
|
|
69
|
+
flex-grow: 1;
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
connectedCallback() {
|
|
74
|
+
super.connectedCallback();
|
|
75
|
+
this.handleFieldChanged = this.handleFieldChanged.bind(this);
|
|
76
|
+
}
|
|
77
|
+
handleFieldChanged(evt) {
|
|
78
|
+
const field = evt.currentTarget;
|
|
79
|
+
this.data.fields[field.key] = field.value;
|
|
80
|
+
postJSON('/api/v2/contacts.json?uuid=' + this.data.uuid, {
|
|
81
|
+
fields: { [field.key]: field.value },
|
|
82
|
+
}).then(() => {
|
|
83
|
+
this.refresh();
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
render() {
|
|
87
|
+
const pinned = this.store.getPinnedFields();
|
|
88
|
+
const fields = pinned.map((field) => {
|
|
89
|
+
if (this.data) {
|
|
90
|
+
const value = this.data.fields[field.key];
|
|
91
|
+
return html `<temba-contact-field
|
|
92
|
+
key=${field.key}
|
|
93
|
+
name=${field.label}
|
|
94
|
+
value=${value}
|
|
95
|
+
type=${field.value_type}
|
|
96
|
+
@change=${this.handleFieldChanged}
|
|
97
|
+
></temba-contact-field>`;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return html `${this.data ? html ` ${fields} ` : null}`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
__decorate([
|
|
104
|
+
property({ type: Boolean })
|
|
105
|
+
], ContactFields.prototype, "dirty", void 0);
|
|
106
|
+
//# sourceMappingURL=ContactFields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactFields.js","sourceRoot":"","sources":["../../../src/contacts/ContactFields.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,aAAc,SAAQ,mBAAmB;IACpD,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+DT,CAAC;IACJ,CAAC;IAKD,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IAEM,kBAAkB,CAAC,GAAe;QACvC,MAAM,KAAK,GAAG,GAAG,CAAC,aAAmC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1C,QAAQ,CAAC,6BAA6B,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACvD,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE;SACrC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACX,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,MAAM;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QAE5C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAmB,EAAE,EAAE;YAChD,IAAI,IAAI,CAAC,IAAI,EAAE;gBACb,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC1C,OAAO,IAAI,CAAA;gBACH,KAAK,CAAC,GAAG;iBACR,KAAK,CAAC,KAAK;kBACV,KAAK;iBACN,KAAK,CAAC,UAAU;oBACb,IAAI,CAAC,kBAAkB;gCACX,CAAC;aAC1B;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,CAAC;CACF;AAnCC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;4CACb","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators';\nimport { ContactField } from '../interfaces';\nimport { postJSON } from '../utils';\nimport { ContactFieldEditor } from './ContactFieldEditor';\nimport { ContactStoreElement } from './ContactStoreElement';\n\nexport class ContactFields extends ContactStoreElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-wrap: wrap;\n flex-shrink: 1;\n }\n\n .field {\n display: flex;\n margin: 0.3em 0.3em;\n box-shadow: 0 0 0.2em rgba(0, 0, 0, 0.15);\n border-radius: var(--curvature);\n align-items: center;\n overflow: hidden;\n }\n\n .field.set {\n background: #fff;\n }\n\n .field.unset {\n opacity: 0.4;\n }\n\n .field.unset .label {\n }\n\n .field:hover {\n }\n\n .field:hover {\n box-shadow: 1px 1px 6px 2px rgba(0, 0, 0, 0.05),\n 0px 0px 0px 2px var(--color-link-primary);\n cursor: pointer;\n }\n\n .label {\n padding: 0.25em 1em;\n border-top-left-radius: var(--curvature);\n border-bottom-left-radius: var(--curvature);\n color: #777;\n font-size: 0.9em;\n font-weight: 400;\n box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.1) inset;\n }\n\n .value {\n --icon-color: #ddd;\n max-width: 150px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0.25em 1em;\n border-top-right-radius: var(--curvature);\n border-bottom-right-radius: var(--curvature);\n font-size: 0.9em;\n }\n\n temba-contact-field {\n margin: 0.3em;\n min-width: 320px;\n flex-grow: 1;\n }\n `;\n }\n\n @property({ type: Boolean })\n dirty: boolean;\n\n connectedCallback(): void {\n super.connectedCallback();\n this.handleFieldChanged = this.handleFieldChanged.bind(this);\n }\n\n public handleFieldChanged(evt: InputEvent) {\n const field = evt.currentTarget as ContactFieldEditor;\n this.data.fields[field.key] = field.value;\n postJSON('/api/v2/contacts.json?uuid=' + this.data.uuid, {\n fields: { [field.key]: field.value },\n }).then(() => {\n this.refresh();\n });\n }\n\n public render(): TemplateResult {\n const pinned = this.store.getPinnedFields();\n\n const fields = pinned.map((field: ContactField) => {\n if (this.data) {\n const value = this.data.fields[field.key];\n return html`<temba-contact-field\n key=${field.key}\n name=${field.label}\n value=${value}\n type=${field.value_type}\n @change=${this.handleFieldChanged}\n ></temba-contact-field>`;\n }\n });\n\n return html`${this.data ? html` ${fields} ` : null}`;\n }\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { css, html } from 'lit';
|
|
2
|
+
import { ContactStoreElement } from './ContactStoreElement';
|
|
3
|
+
export class ContactGroups extends ContactStoreElement {
|
|
4
|
+
static get styles() {
|
|
5
|
+
return css `
|
|
6
|
+
.groups {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-wrap: wrap;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
temba-label {
|
|
12
|
+
margin: 0.3em;
|
|
13
|
+
}
|
|
14
|
+
`;
|
|
15
|
+
}
|
|
16
|
+
render() {
|
|
17
|
+
return html `${this.data
|
|
18
|
+
? html `
|
|
19
|
+
<div class="groups">
|
|
20
|
+
${this.data.groups.map((group) => {
|
|
21
|
+
return html `
|
|
22
|
+
<temba-label
|
|
23
|
+
onclick="goto(event)"
|
|
24
|
+
href="/contact/filter/${group.uuid}/"
|
|
25
|
+
icon=${group.is_dynamic ? 'atom' : 'users'}
|
|
26
|
+
clickable
|
|
27
|
+
light
|
|
28
|
+
shadow
|
|
29
|
+
>
|
|
30
|
+
${group.name}
|
|
31
|
+
</temba-label>
|
|
32
|
+
`;
|
|
33
|
+
})}
|
|
34
|
+
</div>
|
|
35
|
+
`
|
|
36
|
+
: null}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=ContactGroups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactGroups.js","sourceRoot":"","sources":["../../../src/contacts/ContactGroups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,aAAc,SAAQ,mBAAmB;IACpD,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;KAST,CAAC;IACJ,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,IAAI;YACrB,CAAC,CAAC,IAAI,CAAA;;cAEE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAY,EAAE,EAAE;gBACtC,OAAO,IAAI,CAAA;;;0CAGiB,KAAK,CAAC,IAAI;yBAC3B,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;;;;oBAKxC,KAAK,CAAC,IAAI;;eAEf,CAAC;YACJ,CAAC,CAAC;;SAEL;YACH,CAAC,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;CACF","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { Group } from '../interfaces';\nimport { ContactStoreElement } from './ContactStoreElement';\n\nexport class ContactGroups extends ContactStoreElement {\n static get styles() {\n return css`\n .groups {\n display: flex;\n flex-wrap: wrap;\n }\n\n temba-label {\n margin: 0.3em;\n }\n `;\n }\n\n public render(): TemplateResult {\n return html`${this.data\n ? html`\n <div class=\"groups\">\n ${this.data.groups.map((group: Group) => {\n return html`\n <temba-label\n onclick=\"goto(event)\"\n href=\"/contact/filter/${group.uuid}/\"\n icon=${group.is_dynamic ? 'atom' : 'users'}\n clickable\n light\n shadow\n >\n ${group.name}\n </temba-label>\n `;\n })}\n </div>\n `\n : null}`;\n }\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { css, html } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators';
|
|
4
|
+
import { ContactStoreElement } from './ContactStoreElement';
|
|
5
|
+
export class ContactName extends ContactStoreElement {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.size = 20;
|
|
9
|
+
}
|
|
10
|
+
static get styles() {
|
|
11
|
+
return css `
|
|
12
|
+
:host {
|
|
13
|
+
display: flex;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
temba-urn {
|
|
17
|
+
margin-right: 0.2em;
|
|
18
|
+
margin-top: 2px;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
}
|
|
22
|
+
render() {
|
|
23
|
+
if (this.data) {
|
|
24
|
+
const urn = this.data.urns.length > 0
|
|
25
|
+
? html `<temba-urn
|
|
26
|
+
size=${this.size}
|
|
27
|
+
urn="${this.data.urns[0]}"
|
|
28
|
+
></temba-urn>`
|
|
29
|
+
: null;
|
|
30
|
+
return html `
|
|
31
|
+
${urn}
|
|
32
|
+
<div class="name">${this.data.name}</div>
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
__decorate([
|
|
38
|
+
property({ type: Number, attribute: 'icon-size' })
|
|
39
|
+
], ContactName.prototype, "size", void 0);
|
|
40
|
+
//# sourceMappingURL=ContactName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactName.js","sourceRoot":"","sources":["../../../src/contacts/ContactName.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,WAAY,SAAQ,mBAAmB;IAApD;;QAEE,SAAI,GAAG,EAAE,CAAC;IA8BZ,CAAC;IA5BC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;KAST,CAAC;IACJ,CAAC;IAEM,MAAM;QACX,IAAI,IAAI,CAAC,IAAI,EAAE;YACb,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;gBACvB,CAAC,CAAC,IAAI,CAAA;qBACK,IAAI,CAAC,IAAI;qBACT,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;0BACZ;gBAChB,CAAC,CAAC,IAAI,CAAC;YACX,OAAO,IAAI,CAAA;UACP,GAAG;4BACe,IAAI,CAAC,IAAI,CAAC,IAAI;OACnC,CAAC;SACH;IACH,CAAC;CACF;AA9BC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;yCACzC","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators';\nimport { ContactStoreElement } from './ContactStoreElement';\n\nexport class ContactName extends ContactStoreElement {\n @property({ type: Number, attribute: 'icon-size' })\n size = 20;\n\n static get styles() {\n return css`\n :host {\n display: flex;\n }\n\n temba-urn {\n margin-right: 0.2em;\n margin-top: 2px;\n }\n `;\n }\n\n public render(): TemplateResult {\n if (this.data) {\n const urn =\n this.data.urns.length > 0\n ? html`<temba-urn\n size=${this.size}\n urn=\"${this.data.urns[0]}\"\n ></temba-urn>`\n : null;\n return html`\n ${urn}\n <div class=\"name\">${this.data.name}</div>\n `;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { property } from 'lit/decorators';
|
|
3
|
+
import { StoreElement } from '../store/StoreElement';
|
|
4
|
+
export class ContactStoreElement extends StoreElement {
|
|
5
|
+
prepareData(data) {
|
|
6
|
+
if (data && data.length > 0) {
|
|
7
|
+
data = data[0];
|
|
8
|
+
data.groups.forEach((group) => {
|
|
9
|
+
group.is_dynamic = this.store.isDynamicGroup(group.uuid);
|
|
10
|
+
});
|
|
11
|
+
data.groups.sort((a, b) => {
|
|
12
|
+
if (!a.is_dynamic || !b.is_dynamic) {
|
|
13
|
+
if (a.is_dynamic) {
|
|
14
|
+
return -1;
|
|
15
|
+
}
|
|
16
|
+
if (b.is_dynamic) {
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return a.name.localeCompare(b.name);
|
|
21
|
+
});
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
updated(changes) {
|
|
27
|
+
super.updated(changes);
|
|
28
|
+
if (changes.has('contact')) {
|
|
29
|
+
if (this.contact) {
|
|
30
|
+
this.url = `/api/v2/contacts.json?uuid=${this.contact}`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.url = null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
__decorate([
|
|
39
|
+
property({ type: String })
|
|
40
|
+
], ContactStoreElement.prototype, "contact", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
property({ type: Object, attribute: false })
|
|
43
|
+
], ContactStoreElement.prototype, "data", void 0);
|
|
44
|
+
//# sourceMappingURL=ContactStoreElement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactStoreElement.js","sourceRoot":"","sources":["../../../src/contacts/ContactStoreElement.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IAOnD,WAAW,CAAC,IAAS;QACnB,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3B,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAY,EAAE,EAAE;gBACnC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3D,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAQ,EAAE,CAAQ,EAAE,EAAE;gBACtC,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE;oBAClC,IAAI,CAAC,CAAC,UAAU,EAAE;wBAChB,OAAO,CAAC,CAAC,CAAC;qBACX;oBAED,IAAI,CAAC,CAAC,UAAU,EAAE;wBAChB,OAAO,CAAC,CAAC;qBACV;iBACF;gBAED,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC;SACb;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAES,OAAO,CACf,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;YAC1B,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,IAAI,CAAC,GAAG,GAAG,8BAA8B,IAAI,CAAC,OAAO,EAAE,CAAC;aACzD;iBAAM;gBACL,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;aACjB;SACF;IACH,CAAC;CACF;AA3CC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oDACX;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;iDAC/B","sourcesContent":["import { PropertyValueMap } from 'lit';\nimport { property } from 'lit/decorators';\nimport { Contact, Group } from '../interfaces';\nimport { StoreElement } from '../store/StoreElement';\n\nexport class ContactStoreElement extends StoreElement {\n @property({ type: String })\n contact: string;\n\n @property({ type: Object, attribute: false })\n data: Contact;\n\n prepareData(data: any) {\n if (data && data.length > 0) {\n data = data[0];\n data.groups.forEach((group: Group) => {\n group.is_dynamic = this.store.isDynamicGroup(group.uuid);\n });\n\n data.groups.sort((a: Group, b: Group) => {\n if (!a.is_dynamic || !b.is_dynamic) {\n if (a.is_dynamic) {\n return -1;\n }\n\n if (b.is_dynamic) {\n return 1;\n }\n }\n\n return a.name.localeCompare(b.name);\n });\n\n return data;\n }\n return null;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('contact')) {\n if (this.contact) {\n this.url = `/api/v2/contacts.json?uuid=${this.contact}`;\n } else {\n this.url = null;\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { css, html } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators';
|
|
4
|
+
import { RapidElement } from '../RapidElement';
|
|
5
|
+
export class ContactUrn extends RapidElement {
|
|
6
|
+
static get styles() {
|
|
7
|
+
return css `
|
|
8
|
+
.urn {
|
|
9
|
+
box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.04) inset;
|
|
10
|
+
padding: 3px;
|
|
11
|
+
border: 1px solid #ddd;
|
|
12
|
+
border-radius: 18rem;
|
|
13
|
+
background: #eee;
|
|
14
|
+
margin-right: 0.2em;
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
render() {
|
|
19
|
+
const scheme = this.urn.split(':')[0];
|
|
20
|
+
return html `
|
|
21
|
+
<img
|
|
22
|
+
class="urn"
|
|
23
|
+
width="${this.size}em"
|
|
24
|
+
height="${this.size}em"
|
|
25
|
+
src="${this.prefix ||
|
|
26
|
+
window.static_url ||
|
|
27
|
+
'/static/'}img/schemes/${scheme}.svg"
|
|
28
|
+
/>
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
__decorate([
|
|
33
|
+
property({ type: String })
|
|
34
|
+
], ContactUrn.prototype, "urn", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
property({ type: Number })
|
|
37
|
+
], ContactUrn.prototype, "size", void 0);
|
|
38
|
+
//# sourceMappingURL=ContactUrn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactUrn.js","sourceRoot":"","sources":["../../../src/contacts/ContactUrn.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,OAAO,UAAW,SAAQ,YAAY;IAO1C,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;KAST,CAAC;IACJ,CAAC;IAEM,MAAM;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,CAAA;;;iBAGE,IAAI,CAAC,IAAI;kBACR,IAAI,CAAC,IAAI;eACZ,IAAI,CAAC,MAAM;YACjB,MAAc,CAAC,UAAU;YAC1B,UAAU,eAAe,MAAM;;KAElC,CAAC;IACJ,CAAC;CACF;AA/BC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uCACf;AAGZ;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCACd","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators';\nimport { RapidElement } from '../RapidElement';\n\nexport class ContactUrn extends RapidElement {\n @property({ type: String })\n urn: string;\n\n @property({ type: Number })\n size: number;\n\n static get styles() {\n return css`\n .urn {\n box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.04) inset;\n padding: 3px;\n border: 1px solid #ddd;\n border-radius: 18rem;\n background: #eee;\n margin-right: 0.2em;\n }\n `;\n }\n\n public render(): TemplateResult {\n const scheme = this.urn.split(':')[0];\n return html`\n <img\n class=\"urn\"\n width=\"${this.size}em\"\n height=\"${this.size}em\"\n src=\"${this.prefix ||\n (window as any).static_url ||\n '/static/'}img/schemes/${scheme}.svg\"\n />\n `;\n }\n}\n"]}
|
|
@@ -434,6 +434,10 @@ export const getEventStyles = () => {
|
|
|
434
434
|
.assigned .attn {
|
|
435
435
|
color: #777;
|
|
436
436
|
}
|
|
437
|
+
|
|
438
|
+
.attachments {
|
|
439
|
+
margin-top: 1em;
|
|
440
|
+
}
|
|
437
441
|
`;
|
|
438
442
|
};
|
|
439
443
|
const FLOW_USER_ID = 'flow';
|
|
@@ -538,14 +542,48 @@ export const renderAttachment = (attachment) => {
|
|
|
538
542
|
}
|
|
539
543
|
else if (ext === 'pdf') {
|
|
540
544
|
return html `<div
|
|
541
|
-
|
|
542
|
-
|
|
545
|
+
style="width:100%;height:300px;border-radius:var(--curvature);box-shadow:0px 0px 12px 0px rgba(0,0,0,.1), 0px 0px 2px 0px rgba(0,0,0,.15);overflow:hidden"
|
|
546
|
+
><embed src="${url}#view=Fit" type="application/pdf" frameBorder="0" scrolling="auto" height="100%" width="100%"></embed></div>`;
|
|
543
547
|
}
|
|
544
548
|
else if (mediaType === 'video') {
|
|
545
|
-
return html `<video
|
|
549
|
+
return html `<video
|
|
550
|
+
style="border-radius:var(--curvature);box-shadow:0px 0px 12px 0px rgba(0,0,0,.1), 0px 0px 2px 0px rgba(0,0,0,.15);"
|
|
551
|
+
max-width="400px"
|
|
552
|
+
height="auto"
|
|
553
|
+
controls="controls"
|
|
554
|
+
>
|
|
546
555
|
<source src="${url}" type="video/mp4" />
|
|
547
556
|
</video> `;
|
|
548
557
|
}
|
|
558
|
+
else if (mediaType === 'audio') {
|
|
559
|
+
return html `<audio
|
|
560
|
+
style="border-radius: 99px; box-shadow:0px 0px 12px 0px rgba(0,0,0,.1), 0px 0px 2px 0px rgba(0,0,0,.15);"
|
|
561
|
+
src="${url}"
|
|
562
|
+
type="${attType}"
|
|
563
|
+
controls
|
|
564
|
+
>
|
|
565
|
+
<a target="_" href="${url}">${url}</a>
|
|
566
|
+
</audio>`;
|
|
567
|
+
}
|
|
568
|
+
else if (attType === 'geo') {
|
|
569
|
+
const [lat, long] = url.split(',');
|
|
570
|
+
const latFloat = parseFloat(lat);
|
|
571
|
+
const longFloat = parseFloat(long);
|
|
572
|
+
const geo = `${lat}000000%2C${long}000000`;
|
|
573
|
+
return html ` <iframe
|
|
574
|
+
style="border-radius: var(--curvature);box-shadow:0px 0px 12px 0px rgba(0,0,0,.1), 0px 0px 2px 0px rgba(0,0,0,.15);"
|
|
575
|
+
width="300"
|
|
576
|
+
height="300"
|
|
577
|
+
frameborder="0"
|
|
578
|
+
scrolling="no"
|
|
579
|
+
marginheight="0"
|
|
580
|
+
marginwidth="0"
|
|
581
|
+
src="https://www.openstreetmap.org/export/embed.html?bbox=${longFloat -
|
|
582
|
+
0.005}000000%2C${latFloat - 0.005}%2C${longFloat +
|
|
583
|
+
0.005}000000%2C${latFloat +
|
|
584
|
+
0.005}000000&layer=mapnik&marker=${geo}"
|
|
585
|
+
></iframe>`;
|
|
586
|
+
}
|
|
549
587
|
else {
|
|
550
588
|
return html `<div style="display:flex">
|
|
551
589
|
<temba-icon name="download"></temba-icon>
|
|
@@ -553,15 +591,46 @@ export const renderAttachment = (attachment) => {
|
|
|
553
591
|
</div>`;
|
|
554
592
|
}
|
|
555
593
|
return html `<div
|
|
556
|
-
style="width:100%;max-width:300px;border-radius:var(--curvature); box-shadow:0px 0px
|
|
594
|
+
style="width:100%;max-width:300px;border-radius:var(--curvature); box-shadow:0px 0px 6px 0px rgba(0,0,0,.15);overflow:hidden"
|
|
557
595
|
>
|
|
558
596
|
${inner}
|
|
559
597
|
</div>`;
|
|
560
598
|
};
|
|
561
599
|
export const renderMsgEvent = (event, agent) => {
|
|
562
600
|
const isInbound = event.type === Events.MESSAGE_RECEIVED;
|
|
563
|
-
const isError = event.status === 'E'
|
|
564
|
-
const
|
|
601
|
+
const isError = event.status === 'E';
|
|
602
|
+
const isFailure = event.status === 'F';
|
|
603
|
+
// summary items which appear under the message bubble
|
|
604
|
+
const summary = [];
|
|
605
|
+
if (event.logs_url) {
|
|
606
|
+
summary.push(html ` <div class="icon-link">
|
|
607
|
+
<temba-icon
|
|
608
|
+
onclick="goto(event)"
|
|
609
|
+
href="${event.logs_url}"
|
|
610
|
+
name="log"
|
|
611
|
+
class="${isError || isFailure ? 'error' : ''}"
|
|
612
|
+
></temba-icon>
|
|
613
|
+
</div>`);
|
|
614
|
+
}
|
|
615
|
+
else if (isError) {
|
|
616
|
+
summary.push(html `<temba-icon
|
|
617
|
+
title="Message delivery error"
|
|
618
|
+
name="alert-triangle"
|
|
619
|
+
></temba-icon>`);
|
|
620
|
+
}
|
|
621
|
+
else if (isFailure) {
|
|
622
|
+
summary.push(html `<temba-icon
|
|
623
|
+
title="Message delivery failure: ${event.failed_reason_display}"
|
|
624
|
+
name="alert-triangle"
|
|
625
|
+
></temba-icon>`);
|
|
626
|
+
}
|
|
627
|
+
if (event.recipient_count > 1) {
|
|
628
|
+
summary.push(html `<temba-icon size="1" name="megaphone"></temba-icon>
|
|
629
|
+
<div class="recipients">${event.recipient_count} contacts</div>
|
|
630
|
+
<div class="separator">•</div>`);
|
|
631
|
+
}
|
|
632
|
+
summary.push(html `<div class="time">${timeSince(new Date(event.created_on))}</div>`);
|
|
633
|
+
return html `<div style="display:flex;align-items:flex-start">
|
|
565
634
|
<div style="display:flex;flex-direction:column">
|
|
566
635
|
${event.msg.text ? html `<div class="msg">${event.msg.text}</div>` : null}
|
|
567
636
|
${event.msg.attachments
|
|
@@ -577,29 +646,7 @@ export const renderMsgEvent = (event, agent) => {
|
|
|
577
646
|
style="flex-direction:row${isInbound ? '-reverse' : ''}"
|
|
578
647
|
>
|
|
579
648
|
<div style="flex-grow:1"></div>
|
|
580
|
-
${
|
|
581
|
-
? html `
|
|
582
|
-
<div class="icon-link">
|
|
583
|
-
<temba-icon
|
|
584
|
-
onclick="goto(event)"
|
|
585
|
-
href="${event.logs_url}"
|
|
586
|
-
name="log"
|
|
587
|
-
class="${isError ? 'error' : ''}"
|
|
588
|
-
></temba-icon>
|
|
589
|
-
</div>
|
|
590
|
-
`
|
|
591
|
-
: isError
|
|
592
|
-
? html `<temba-icon
|
|
593
|
-
title="Message delivery error"
|
|
594
|
-
name="alert-triangle"
|
|
595
|
-
></temba-icon>`
|
|
596
|
-
: null}
|
|
597
|
-
${event.recipient_count > 1
|
|
598
|
-
? html `<temba-icon size="1" name="megaphone"></temba-icon>
|
|
599
|
-
<div class="recipients">${event.recipient_count} contacts</div>
|
|
600
|
-
<div class="separator">•</div>`
|
|
601
|
-
: null}
|
|
602
|
-
<div class="time">${timeSince(new Date(event.created_on))}</div>
|
|
649
|
+
${summary}
|
|
603
650
|
</div>
|
|
604
651
|
</div>
|
|
605
652
|
|
|
@@ -613,7 +660,6 @@ export const renderMsgEvent = (event, agent) => {
|
|
|
613
660
|
</div>`
|
|
614
661
|
: null}
|
|
615
662
|
</div>`;
|
|
616
|
-
return msg;
|
|
617
663
|
};
|
|
618
664
|
export const renderFlowEvent = (event) => {
|
|
619
665
|
let verb = 'Interrupted';
|