@nyaruka/temba-components 0.113.0 → 0.114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -2
- package/demo/index.html +1 -1
- package/dist/temba-components.js +793 -966
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/aliaseditor/AliasEditor.js.map +1 -1
- package/out-tsc/src/button/Button.js +6 -2
- package/out-tsc/src/button/Button.js.map +1 -1
- package/out-tsc/src/chat/Chat.js +29 -7
- package/out-tsc/src/chat/Chat.js.map +1 -1
- package/out-tsc/src/compose/Compose.js +10 -5
- package/out-tsc/src/compose/Compose.js.map +1 -1
- package/out-tsc/src/contacts/ContactChat.js +240 -114
- package/out-tsc/src/contacts/ContactChat.js.map +1 -1
- package/out-tsc/src/contacts/ContactFieldEditor.js.map +1 -1
- package/out-tsc/src/contacts/events.js.map +1 -1
- package/out-tsc/src/contacts/helpers.js +5 -1
- package/out-tsc/src/contacts/helpers.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/dropdown/Dropdown.js +121 -108
- package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
- package/out-tsc/src/interfaces.js +2 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/list/ContentMenu.js +11 -8
- package/out-tsc/src/list/ContentMenu.js.map +1 -1
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/list/TembaList.js +21 -14
- package/out-tsc/src/list/TembaList.js.map +1 -1
- package/out-tsc/src/list/TembaMenu.js +11 -12
- package/out-tsc/src/list/TembaMenu.js.map +1 -1
- package/out-tsc/src/list/TicketList.js +10 -0
- package/out-tsc/src/list/TicketList.js.map +1 -1
- package/out-tsc/src/omnibox/Omnibox.js +33 -90
- package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
- package/out-tsc/src/options/Options.js +49 -47
- package/out-tsc/src/options/Options.js.map +1 -1
- package/out-tsc/src/select/PopupSelect.js +57 -0
- package/out-tsc/src/select/PopupSelect.js.map +1 -0
- package/out-tsc/src/select/Select.js +194 -144
- package/out-tsc/src/select/Select.js.map +1 -1
- package/out-tsc/src/select/UserSelect.js +67 -0
- package/out-tsc/src/select/UserSelect.js.map +1 -0
- package/out-tsc/src/store/Store.js +65 -14
- package/out-tsc/src/store/Store.js.map +1 -1
- package/out-tsc/src/tabpane/TabPane.js +72 -115
- package/out-tsc/src/tabpane/TabPane.js.map +1 -1
- package/out-tsc/src/textinput/TextInput.js +1 -0
- package/out-tsc/src/textinput/TextInput.js.map +1 -1
- package/out-tsc/src/user/TembaUser.js +24 -37
- package/out-tsc/src/user/TembaUser.js.map +1 -1
- package/out-tsc/src/utils/index.js +13 -6
- package/out-tsc/src/utils/index.js.map +1 -1
- package/out-tsc/temba-modules.js +4 -2
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-omnibox.test.js +43 -4
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +121 -65
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +4 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/compose/attachments-tab.png +0 -0
- package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
- package/screenshots/truth/compose/attachments-with-files.png +0 -0
- package/screenshots/truth/compose/intial-text.png +0 -0
- package/screenshots/truth/compose/no-counter.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
- package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
- package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
- package/screenshots/truth/content-menu/item-no-buttons.png +0 -0
- package/screenshots/truth/content-menu/items-and-buttons.png +0 -0
- package/screenshots/truth/omnibox/selected.png +0 -0
- package/screenshots/truth/select/enabled-multi-selection.png +0 -0
- package/screenshots/truth/select/endpoint-initial-value-updated.png +0 -0
- package/screenshots/truth/select/endpoint-initial-value.png +0 -0
- package/screenshots/truth/select/expressions.png +0 -0
- package/screenshots/truth/select/functions.png +0 -0
- package/screenshots/truth/select/initial-value.png +0 -0
- package/screenshots/truth/select/multi-with-endpoint.png +0 -0
- package/screenshots/truth/select/multiple-initial-values.png +0 -0
- package/screenshots/truth/select/selected-multi-test.png +0 -0
- package/screenshots/truth/select/static-initial-value.png +0 -0
- package/screenshots/truth/select/static-initial-via-selected.png +0 -0
- package/screenshots/truth/select/value-initial.png +0 -0
- package/src/aliaseditor/AliasEditor.ts +1 -1
- package/src/button/Button.ts +6 -2
- package/src/chat/Chat.ts +28 -6
- package/src/compose/Compose.ts +11 -6
- package/src/contacts/ContactChat.ts +260 -118
- package/src/contacts/ContactFieldEditor.ts +1 -1
- package/src/contacts/events.ts +1 -0
- package/src/contacts/helpers.ts +8 -1
- package/src/contactsearch/ContactSearch.ts +3 -3
- package/src/dropdown/Dropdown.ts +142 -103
- package/src/interfaces.ts +4 -1
- package/src/list/ContentMenu.ts +11 -9
- package/src/list/RunList.ts +3 -1
- package/src/list/TembaList.ts +24 -14
- package/src/list/TembaMenu.ts +14 -15
- package/src/list/TicketList.ts +11 -0
- package/src/omnibox/Omnibox.ts +34 -95
- package/src/options/Options.ts +57 -60
- package/src/select/PopupSelect.ts +53 -0
- package/src/select/Select.ts +182 -112
- package/src/select/UserSelect.ts +71 -0
- package/src/store/Store.ts +70 -21
- package/src/tabpane/TabPane.ts +79 -113
- package/src/textinput/TextInput.ts +1 -0
- package/src/user/TembaUser.ts +30 -41
- package/src/utils/index.ts +12 -8
- package/temba-modules.ts +4 -2
- package/test/temba-omnibox.test.ts +56 -4
- package/test/temba-select.test.ts +170 -56
- package/test/utils.test.ts +5 -0
- package/test-assets/select/omnibox.json +55 -0
- package/web-test-runner.config.mjs +16 -4
- package/out-tsc/src/contacts/ContactTickets.js +0 -462
- package/out-tsc/src/contacts/ContactTickets.js.map +0 -1
- package/out-tsc/test/temba-contact-tickets.test.js +0 -36
- package/out-tsc/test/temba-contact-tickets.test.js.map +0 -1
- package/src/contacts/ContactTickets.ts +0 -490
- package/test/temba-contact-tickets.test.ts +0 -52
package/src/dropdown/Dropdown.ts
CHANGED
|
@@ -2,10 +2,16 @@ import { css, html, TemplateResult } from 'lit';
|
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
3
|
import { RapidElement } from '../RapidElement';
|
|
4
4
|
import { getClasses } from '../utils';
|
|
5
|
+
import { CustomEventType } from '../interfaces';
|
|
6
|
+
|
|
7
|
+
import { styleMap } from 'lit-html/directives/style-map.js';
|
|
5
8
|
|
|
6
9
|
export class Dropdown extends RapidElement {
|
|
7
10
|
static get styles() {
|
|
8
11
|
return css`
|
|
12
|
+
:host {
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
.wrapper {
|
|
10
16
|
position: relative;
|
|
11
17
|
}
|
|
@@ -19,15 +25,20 @@ export class Dropdown extends RapidElement {
|
|
|
19
25
|
overflow: auto;
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
.dropdown:focus {
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.dropdown.dormant {
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
.dropdown {
|
|
23
|
-
position:
|
|
24
|
-
opacity: 0;
|
|
36
|
+
position: fixed;
|
|
25
37
|
z-index: 2;
|
|
26
|
-
pointer-events: none;
|
|
27
38
|
padding: 0;
|
|
39
|
+
opacity: 0;
|
|
28
40
|
border-radius: var(--curvature);
|
|
29
41
|
background: #fff;
|
|
30
|
-
transform: translateY(1em) scale(0.9);
|
|
31
42
|
transition: all calc(0.8 * var(--transition-speed)) var(--bounce);
|
|
32
43
|
user-select: none;
|
|
33
44
|
margin-top: 0px;
|
|
@@ -64,7 +75,7 @@ export class Dropdown extends RapidElement {
|
|
|
64
75
|
right: 0;
|
|
65
76
|
bottom: 0;
|
|
66
77
|
background: rgba(0, 0, 0, 0.7);
|
|
67
|
-
opacity: 0;
|
|
78
|
+
opacity: 0.5;
|
|
68
79
|
transition: opacity var(--transition-speed) ease-in-out;
|
|
69
80
|
pointer-events: none;
|
|
70
81
|
z-index: 1;
|
|
@@ -85,149 +96,176 @@ export class Dropdown extends RapidElement {
|
|
|
85
96
|
open = false;
|
|
86
97
|
|
|
87
98
|
@property({ type: Boolean })
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
@property({ type: Boolean })
|
|
91
|
-
bottom = false;
|
|
92
|
-
|
|
93
|
-
@property({ type: Boolean })
|
|
94
|
-
left = false;
|
|
95
|
-
|
|
96
|
-
@property({ type: Boolean })
|
|
97
|
-
right = false;
|
|
98
|
-
|
|
99
|
-
@property({ type: Number })
|
|
100
|
-
arrowSize = 6;
|
|
99
|
+
dormant = true;
|
|
101
100
|
|
|
102
101
|
@property({ type: Number })
|
|
103
|
-
|
|
102
|
+
arrowSize = 8;
|
|
104
103
|
|
|
105
104
|
@property({ type: Number })
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@property({ type: Number })
|
|
109
|
-
offsetY = 0;
|
|
105
|
+
margin = 10;
|
|
110
106
|
|
|
111
107
|
@property({ type: Boolean })
|
|
112
108
|
mask = false;
|
|
113
109
|
|
|
110
|
+
@property({ type: Object, attribute: false })
|
|
111
|
+
dropdownStyle = {};
|
|
112
|
+
|
|
113
|
+
@property({ type: Object, attribute: false })
|
|
114
|
+
arrowStyle = {};
|
|
115
|
+
|
|
114
116
|
constructor() {
|
|
115
117
|
super();
|
|
116
|
-
this.
|
|
118
|
+
this.calculatePosition = this.calculatePosition.bind(this);
|
|
117
119
|
}
|
|
118
120
|
|
|
121
|
+
private activeFocus: any;
|
|
122
|
+
private blurHandler: any;
|
|
123
|
+
|
|
119
124
|
public firstUpdated(props: any) {
|
|
120
125
|
super.firstUpdated(props);
|
|
126
|
+
this.resetBlurHandler();
|
|
127
|
+
}
|
|
121
128
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
private resetBlurHandler() {
|
|
130
|
+
const dropdown = this.shadowRoot.querySelector(
|
|
131
|
+
'.dropdown'
|
|
132
|
+
) as HTMLDivElement;
|
|
133
|
+
|
|
134
|
+
if (this.activeFocus) {
|
|
135
|
+
this.activeFocus.removeEventListener('blur', this.blurHandler);
|
|
136
|
+
}
|
|
125
137
|
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
this.activeFocus = dropdown;
|
|
139
|
+
this.blurHandler = this.handleBlur.bind(this);
|
|
140
|
+
|
|
141
|
+
this.activeFocus.addEventListener('blur', this.blurHandler);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private handleBlur(event: FocusEvent) {
|
|
145
|
+
const newTarget = event.relatedTarget as any;
|
|
146
|
+
|
|
147
|
+
if (this.contains(newTarget)) {
|
|
148
|
+
newTarget.addEventListener('blur', this.blurHandler);
|
|
149
|
+
this.activeFocus = newTarget;
|
|
128
150
|
} else {
|
|
129
|
-
|
|
151
|
+
this.closeDropdown();
|
|
130
152
|
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private openDropdown() {
|
|
156
|
+
this.open = true;
|
|
157
|
+
this.dormant = false;
|
|
158
|
+
this.resetBlurHandler();
|
|
131
159
|
|
|
132
160
|
const dropdown = this.shadowRoot.querySelector(
|
|
133
161
|
'.dropdown'
|
|
134
162
|
) as HTMLDivElement;
|
|
163
|
+
dropdown.focus();
|
|
164
|
+
dropdown.click();
|
|
135
165
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
166
|
+
this.fireCustomEvent(CustomEventType.Opened);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private closeDropdown() {
|
|
170
|
+
this.activeFocus.removeEventListener('blur', this.blurHandler);
|
|
171
|
+
|
|
172
|
+
this.open = false;
|
|
173
|
+
this.resetBlurHandler();
|
|
174
|
+
|
|
175
|
+
window.setTimeout(() => {
|
|
176
|
+
this.dormant = true;
|
|
177
|
+
}, 250);
|
|
178
|
+
|
|
179
|
+
this.blur();
|
|
146
180
|
}
|
|
147
181
|
|
|
148
182
|
public updated(changedProperties: Map<string, any>) {
|
|
149
183
|
super.updated(changedProperties);
|
|
150
|
-
const dropdown = this.shadowRoot.querySelector(
|
|
151
|
-
'.dropdown'
|
|
152
|
-
) as HTMLDivElement;
|
|
153
184
|
|
|
154
|
-
if (changedProperties.has('
|
|
155
|
-
|
|
156
|
-
if (dropdown.offsetLeft + dropdown.clientWidth > window.outerWidth) {
|
|
157
|
-
dropdown.style.marginLeft =
|
|
158
|
-
'-' + (dropdown.clientWidth - this.clientWidth - this.offsetX) + 'px';
|
|
159
|
-
} else {
|
|
160
|
-
if (this.right) {
|
|
161
|
-
dropdown.style.marginRight = this.offsetX + 'px';
|
|
162
|
-
} else {
|
|
163
|
-
dropdown.style.marginLeft = this.offsetX + 'px';
|
|
164
|
-
}
|
|
165
|
-
}
|
|
185
|
+
if (changedProperties.has('open')) {
|
|
186
|
+
this.dropdownStyle = {};
|
|
166
187
|
}
|
|
167
188
|
|
|
168
|
-
if (changedProperties.has('
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
189
|
+
if (changedProperties.has('dropdownStyle')) {
|
|
190
|
+
if (Object.keys(this.dropdownStyle).length === 0) {
|
|
191
|
+
this.calculatePosition();
|
|
192
|
+
}
|
|
172
193
|
}
|
|
173
194
|
}
|
|
174
195
|
|
|
175
|
-
public
|
|
196
|
+
public calculatePosition() {
|
|
176
197
|
const dropdown = this.shadowRoot.querySelector(
|
|
177
198
|
'.dropdown'
|
|
178
199
|
) as HTMLDivElement;
|
|
200
|
+
const toggle = this.querySelector('div[slot="toggle"]');
|
|
201
|
+
|
|
202
|
+
const arrow = this.shadowRoot.querySelector('.arrow') as HTMLDivElement;
|
|
203
|
+
|
|
204
|
+
let bumpedUp = false;
|
|
205
|
+
let bumpedLeft = false;
|
|
179
206
|
|
|
180
|
-
if (dropdown) {
|
|
181
|
-
|
|
182
|
-
const
|
|
207
|
+
if (dropdown && toggle) {
|
|
208
|
+
const dropdownBounds = dropdown.getBoundingClientRect();
|
|
209
|
+
const toggleBounds = toggle.getBoundingClientRect();
|
|
210
|
+
const arrowBounds = arrow.getBoundingClientRect();
|
|
183
211
|
|
|
184
212
|
if (!toggle) {
|
|
185
213
|
return;
|
|
186
214
|
}
|
|
187
215
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
dropdown.style.top = toggle.clientHeight + 'px';
|
|
200
|
-
dropdown.style.bottom = '';
|
|
201
|
-
}
|
|
216
|
+
const dropdownStyle = {
|
|
217
|
+
border: '1px solid rgba(0,0,0,0.1)',
|
|
218
|
+
marginTop: '0.5em'
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// if off the the right, bump it left
|
|
222
|
+
if (dropdownBounds.right > window.innerWidth) {
|
|
223
|
+
dropdownStyle['left'] =
|
|
224
|
+
toggleBounds.right - dropdownBounds.width + 'px';
|
|
225
|
+
delete dropdownStyle['right'];
|
|
226
|
+
bumpedLeft = true;
|
|
202
227
|
}
|
|
203
228
|
|
|
204
|
-
if
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
dropdown.style.right = '';
|
|
229
|
+
// if off to the bottom, bump it up
|
|
230
|
+
if (dropdownBounds.bottom > window.innerHeight) {
|
|
231
|
+
dropdownStyle['top'] = toggleBounds.top - dropdownBounds.height + 'px';
|
|
232
|
+
dropdownStyle['margin-top'] = '-0.5em';
|
|
233
|
+
bumpedUp = true;
|
|
210
234
|
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
235
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
236
|
+
const arrowStyle = {
|
|
237
|
+
left: toggleBounds.width / 2 - arrowBounds.width / 2 + 'px',
|
|
238
|
+
borderWidth: this.arrowSize + 'px',
|
|
239
|
+
top: '-' + this.arrowSize + 'px'
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
if (bumpedUp) {
|
|
243
|
+
// rotate our arrow 180 degrees
|
|
244
|
+
arrowStyle['transform'] = 'rotate(180deg)';
|
|
245
|
+
|
|
246
|
+
// and place it at the bottom of the dropdown
|
|
247
|
+
arrowStyle['top'] = 'auto';
|
|
248
|
+
arrowStyle['bottom'] = '-' + this.arrowSize + 'px';
|
|
249
|
+
}
|
|
219
250
|
|
|
220
|
-
|
|
221
|
-
'
|
|
222
|
-
|
|
223
|
-
|
|
251
|
+
if (bumpedLeft) {
|
|
252
|
+
arrowStyle['right'] =
|
|
253
|
+
toggleBounds.width / 2 - arrowBounds.width / 2 + 'px';
|
|
254
|
+
delete arrowStyle['left'];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
this.arrowStyle = arrowStyle;
|
|
258
|
+
this.dropdownStyle = dropdownStyle;
|
|
224
259
|
}
|
|
260
|
+
this.requestUpdate();
|
|
225
261
|
}
|
|
226
262
|
|
|
227
|
-
|
|
228
|
-
// block mouse down when clicking inside dropdown so we don't lose focus yet
|
|
263
|
+
public handleToggleClicked(event: MouseEvent): void {
|
|
229
264
|
event.preventDefault();
|
|
230
265
|
event.stopPropagation();
|
|
266
|
+
if (!this.open && this.dormant) {
|
|
267
|
+
this.openDropdown();
|
|
268
|
+
}
|
|
231
269
|
}
|
|
232
270
|
|
|
233
271
|
public render(): TemplateResult {
|
|
@@ -236,7 +274,11 @@ export class Dropdown extends RapidElement {
|
|
|
236
274
|
? html`<div class="mask ${this.open ? 'open' : ''}" />`
|
|
237
275
|
: null}
|
|
238
276
|
|
|
239
|
-
<div
|
|
277
|
+
<div
|
|
278
|
+
class="wrapper ${getClasses({
|
|
279
|
+
open: this.open
|
|
280
|
+
})}"
|
|
281
|
+
>
|
|
240
282
|
<slot
|
|
241
283
|
name="toggle"
|
|
242
284
|
class="toggle"
|
|
@@ -245,15 +287,12 @@ export class Dropdown extends RapidElement {
|
|
|
245
287
|
<div
|
|
246
288
|
class="${getClasses({
|
|
247
289
|
dropdown: true,
|
|
248
|
-
|
|
249
|
-
left: this.left,
|
|
250
|
-
top: this.top,
|
|
251
|
-
bottom: this.bottom
|
|
290
|
+
dormant: this.dormant
|
|
252
291
|
})}"
|
|
292
|
+
style=${styleMap(this.dropdownStyle)}
|
|
253
293
|
tabindex="0"
|
|
254
|
-
@mousedown=${this.handleDropdownMouseDown}
|
|
255
294
|
>
|
|
256
|
-
<div class="arrow"></div>
|
|
295
|
+
<div class="arrow" style=${styleMap(this.arrowStyle)}></div>
|
|
257
296
|
<div class="dropdown-wrapper">
|
|
258
297
|
<slot name="dropdown" tabindex="1"></slot>
|
|
259
298
|
</div>
|
package/src/interfaces.ts
CHANGED
|
@@ -56,6 +56,7 @@ export interface User {
|
|
|
56
56
|
id?: number;
|
|
57
57
|
first_name?: string;
|
|
58
58
|
last_name?: string;
|
|
59
|
+
name?: string;
|
|
59
60
|
email?: string;
|
|
60
61
|
role?: string;
|
|
61
62
|
created_on?: string;
|
|
@@ -281,5 +282,7 @@ export enum CustomEventType {
|
|
|
281
282
|
Resized = 'temba-resized',
|
|
282
283
|
DetailsChanged = 'temba-details-changed',
|
|
283
284
|
Error = 'temba-error',
|
|
284
|
-
Interrupt = 'temba-interrupt'
|
|
285
|
+
Interrupt = 'temba-interrupt',
|
|
286
|
+
Opened = 'temba-opened',
|
|
287
|
+
TicketUpdated = 'temba-ticket-updated'
|
|
285
288
|
}
|
package/src/list/ContentMenu.ts
CHANGED
|
@@ -34,10 +34,14 @@ export enum ContentMenuItemType {
|
|
|
34
34
|
export class ContentMenu extends RapidElement {
|
|
35
35
|
static get styles() {
|
|
36
36
|
return css`
|
|
37
|
+
:host {
|
|
38
|
+
tabindex: 0;
|
|
39
|
+
}
|
|
37
40
|
.container {
|
|
38
41
|
--button-y: 0.4em;
|
|
39
42
|
--button-x: 1em;
|
|
40
43
|
display: flex;
|
|
44
|
+
align-items: center;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
.button_item,
|
|
@@ -45,10 +49,12 @@ export class ContentMenu extends RapidElement {
|
|
|
45
49
|
margin-left: 1rem;
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
temba-button {
|
|
53
|
+
margin-right: 0.5rem;
|
|
54
|
+
}
|
|
48
55
|
.toggle {
|
|
49
56
|
--icon-color: rgb(102, 102, 102);
|
|
50
|
-
padding: 0.
|
|
51
|
-
margin-left: 0.5rem;
|
|
57
|
+
padding: 0.4em;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
.toggle:hover {
|
|
@@ -62,6 +68,7 @@ export class ContentMenu extends RapidElement {
|
|
|
62
68
|
color: rgb(45, 45, 45);
|
|
63
69
|
z-index: 50;
|
|
64
70
|
min-width: 200px;
|
|
71
|
+
tabindex: 0;
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
.divider {
|
|
@@ -75,6 +82,7 @@ export class ContentMenu extends RapidElement {
|
|
|
75
82
|
font-size: 1.1rem;
|
|
76
83
|
cursor: pointer;
|
|
77
84
|
font-weight: 400;
|
|
85
|
+
tabindex: 0;
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
.item:hover {
|
|
@@ -145,7 +153,6 @@ export class ContentMenu extends RapidElement {
|
|
|
145
153
|
|
|
146
154
|
protected updated(changes: Map<string, any>) {
|
|
147
155
|
super.updated(changes);
|
|
148
|
-
|
|
149
156
|
if (changes.has('endpoint') || changes.has('legacy')) {
|
|
150
157
|
this.fetchContentMenu();
|
|
151
158
|
}
|
|
@@ -168,12 +175,7 @@ export class ContentMenu extends RapidElement {
|
|
|
168
175
|
</temba-button>`;
|
|
169
176
|
})}
|
|
170
177
|
${this.items && this.items.length > 0
|
|
171
|
-
? html`<temba-dropdown
|
|
172
|
-
arrowsize="8"
|
|
173
|
-
arrowoffset="${this.arrowTopLeft ? '12' : '-12'}"
|
|
174
|
-
offsety="6"
|
|
175
|
-
bottom
|
|
176
|
-
>
|
|
178
|
+
? html`<temba-dropdown>
|
|
177
179
|
<div slot="toggle" class="toggle">
|
|
178
180
|
<temba-icon name="menu" size="1.5"></temba-icon>
|
|
179
181
|
</div>
|
package/src/list/RunList.ts
CHANGED
|
@@ -70,7 +70,9 @@ export class RunList extends TembaList {
|
|
|
70
70
|
|
|
71
71
|
if (changedProperties.has('results')) {
|
|
72
72
|
if (this.results) {
|
|
73
|
-
const select = this.shadowRoot.querySelector(
|
|
73
|
+
const select = this.shadowRoot.querySelector(
|
|
74
|
+
'temba-select'
|
|
75
|
+
) as Select<any>;
|
|
74
76
|
select.setOptions(this.results);
|
|
75
77
|
this.resultKeys = this.results.reduce(
|
|
76
78
|
(current, result) => ({ ...current, [result.key]: result }),
|
package/src/list/TembaList.ts
CHANGED
|
@@ -224,6 +224,10 @@ export class TembaList extends RapidElement {
|
|
|
224
224
|
return this.endpoint;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
protected sanitizeResults(results: any[]): Promise<any[]> {
|
|
228
|
+
return Promise.resolve(results);
|
|
229
|
+
}
|
|
230
|
+
|
|
227
231
|
/**
|
|
228
232
|
* Refreshes the first page, updating any found items in our list
|
|
229
233
|
*/
|
|
@@ -250,10 +254,12 @@ export class TembaList extends RapidElement {
|
|
|
250
254
|
controller
|
|
251
255
|
);
|
|
252
256
|
|
|
257
|
+
const sanitizedResults = await this.sanitizeResults(page.results);
|
|
253
258
|
const items = [...this.items];
|
|
259
|
+
|
|
254
260
|
// remove any dupes already in our list
|
|
255
|
-
if (
|
|
256
|
-
|
|
261
|
+
if (sanitizedResults) {
|
|
262
|
+
sanitizedResults.forEach((newOption: any) => {
|
|
257
263
|
if (this.sanitizeOption) {
|
|
258
264
|
this.sanitizeOption(newOption);
|
|
259
265
|
}
|
|
@@ -268,9 +274,9 @@ export class TembaList extends RapidElement {
|
|
|
268
274
|
});
|
|
269
275
|
|
|
270
276
|
// insert our new items at the front
|
|
271
|
-
let results =
|
|
277
|
+
let results = sanitizedResults;
|
|
272
278
|
if (this.reverseRefresh) {
|
|
273
|
-
results =
|
|
279
|
+
results = sanitizedResults.reverse();
|
|
274
280
|
}
|
|
275
281
|
const newItems = [...results, ...items];
|
|
276
282
|
|
|
@@ -332,13 +338,15 @@ export class TembaList extends RapidElement {
|
|
|
332
338
|
|
|
333
339
|
try {
|
|
334
340
|
const page = await fetchResultsPage(endpoint, controller);
|
|
341
|
+
const sanitizedResults = await this.sanitizeResults(page.results);
|
|
342
|
+
|
|
335
343
|
// sanitize our options if necessary
|
|
336
344
|
if (this.sanitizeOption) {
|
|
337
|
-
|
|
345
|
+
sanitizedResults.forEach(this.sanitizeOption);
|
|
338
346
|
}
|
|
339
347
|
|
|
340
|
-
if (
|
|
341
|
-
fetchedItems = fetchedItems.concat(
|
|
348
|
+
if (sanitizedResults) {
|
|
349
|
+
fetchedItems = fetchedItems.concat(sanitizedResults);
|
|
342
350
|
}
|
|
343
351
|
|
|
344
352
|
// save our next pages
|
|
@@ -427,14 +435,16 @@ export class TembaList extends RapidElement {
|
|
|
427
435
|
if (this.nextPage && !this.loading) {
|
|
428
436
|
this.loading = true;
|
|
429
437
|
fetchResultsPage(this.nextPage).then((page: ResultsPage) => {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
438
|
+
this.sanitizeResults(page.results).then((sanitizedResults) => {
|
|
439
|
+
if (this.sanitizeOption) {
|
|
440
|
+
sanitizedResults.forEach(this.sanitizeOption);
|
|
441
|
+
}
|
|
433
442
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
443
|
+
this.items = [...this.items, ...sanitizedResults];
|
|
444
|
+
this.nextPage = page.next;
|
|
445
|
+
this.pages++;
|
|
446
|
+
this.loading = false;
|
|
447
|
+
});
|
|
438
448
|
});
|
|
439
449
|
}
|
|
440
450
|
}
|
package/src/list/TembaMenu.ts
CHANGED
|
@@ -154,7 +154,7 @@ export class TembaMenu extends ResizeElement {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
.level-0 > temba-dropdown .icon-wrapper {
|
|
157
|
-
padding: 0.2em 0.4em 0.2em
|
|
157
|
+
padding: 0.2em 0.4em 0.2em 0em;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
.level-0 > .item.selected::before,
|
|
@@ -202,6 +202,12 @@ export class TembaMenu extends ResizeElement {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
temba-dropdown {
|
|
205
|
+
margin: 0 0.25em;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
temba-dropdown > div[slot='dropdown'] {
|
|
209
|
+
width: 300px;
|
|
210
|
+
overflow: hidden;
|
|
205
211
|
}
|
|
206
212
|
|
|
207
213
|
temba-dropdown > div[slot='dropdown'] .avatar > .details {
|
|
@@ -1200,21 +1206,14 @@ export class TembaMenu extends ResizeElement {
|
|
|
1200
1206
|
|
|
1201
1207
|
if (menuItem.popup) {
|
|
1202
1208
|
return html`
|
|
1203
|
-
<temba-dropdown
|
|
1204
|
-
offsetx="10"
|
|
1205
|
-
arrowoffset="8"
|
|
1206
|
-
arrowSize="0"
|
|
1207
|
-
drop_align="left"
|
|
1208
|
-
id="dd-${menuItem.id}"
|
|
1209
|
-
>
|
|
1209
|
+
<temba-dropdown id="dd-${menuItem.id}">
|
|
1210
1210
|
<div slot="toggle">${item}</div>
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
</div>
|
|
1211
|
+
|
|
1212
|
+
<div slot="dropdown">
|
|
1213
|
+
${(menuItem.items || []).map((child: MenuItem) => {
|
|
1214
|
+
child.level = menuItem.level + 1;
|
|
1215
|
+
return html`${this.renderMenuItem(child, menuItem)}`;
|
|
1216
|
+
})}
|
|
1218
1217
|
</div>
|
|
1219
1218
|
</temba-dropdown>
|
|
1220
1219
|
`;
|
package/src/list/TicketList.ts
CHANGED
|
@@ -18,6 +18,15 @@ export class TicketList extends TembaList {
|
|
|
18
18
|
return this.endpoint;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
protected sanitizeResults(results: any[]): Promise<any[]> {
|
|
22
|
+
return new Promise<any[]>((resolve) => {
|
|
23
|
+
const contacts: Contact[] = results as Contact[];
|
|
24
|
+
this.store.resolveUsers(contacts, ['ticket.assignee']).then(() => {
|
|
25
|
+
resolve(contacts);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
21
30
|
constructor() {
|
|
22
31
|
super();
|
|
23
32
|
|
|
@@ -76,7 +85,9 @@ export class TicketList extends TembaList {
|
|
|
76
85
|
<div>
|
|
77
86
|
${!contact.ticket.closed_on && contact.ticket.assignee
|
|
78
87
|
? html`<temba-user
|
|
88
|
+
name=${contact.ticket.assignee.name}
|
|
79
89
|
email=${contact.ticket.assignee.email}
|
|
90
|
+
avatar=${contact.ticket.assignee.avatar}
|
|
80
91
|
scale="0.8"
|
|
81
92
|
></temba-user>`
|
|
82
93
|
: null}
|