@nyaruka/temba-components 0.166.0 → 0.168.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 +27 -0
- package/dist/locales/es.js +3 -1
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +3 -1
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/pt.js +3 -1
- package/dist/locales/pt.js.map +1 -1
- package/dist/temba-components.js +2791 -1666
- package/dist/temba-components.js.map +1 -1
- package/package.json +1 -1
- package/src/Icons.ts +2 -0
- package/src/display/Button.ts +8 -6
- package/src/display/Chat.ts +541 -191
- package/src/display/Dropdown.ts +40 -17
- package/src/display/Label.ts +25 -4
- package/src/display/TembaDate.ts +11 -2
- package/src/display/Tip.ts +157 -18
- package/src/events/eventRenderers.ts +678 -268
- package/src/events.ts +16 -1
- package/src/flow/NodeEditor.ts +82 -9
- package/src/flow/actions/add_contact_urn.ts +1 -0
- package/src/flow/actions/play_audio.ts +1 -0
- package/src/flow/actions/send_broadcast.ts +17 -1
- package/src/flow/actions/send_msg.ts +12 -1
- package/src/flow/actions/set_run_result.ts +1 -0
- package/src/flow/actions/start_session.ts +10 -1
- package/src/flow/nodes/shared-rules.ts +2 -0
- package/src/flow/nodes/split_by_airtime.ts +6 -0
- package/src/flow/nodes/split_by_expression.ts +1 -0
- package/src/flow/nodes/split_by_llm.ts +2 -0
- package/src/flow/nodes/split_by_llm_categorize.ts +3 -1
- package/src/flow/nodes/split_by_random.ts +2 -1
- package/src/flow/nodes/split_by_resthook.ts +4 -1
- package/src/flow/nodes/split_by_webhook.ts +9 -1
- package/src/flow/types.ts +3 -0
- package/src/flow/utils.ts +49 -0
- package/src/form/DatePicker.ts +2 -1
- package/src/layout/Card.ts +9 -0
- package/src/layout/CardLayout.ts +426 -21
- package/src/layout/CardStack.ts +4 -1
- package/src/list/ContactList.ts +58 -22
- package/src/list/ContentList.ts +632 -29
- package/src/list/MsgList.ts +4 -2
- package/src/list/SortableList.ts +5 -1
- package/src/list/TembaMenu.ts +67 -6
- package/src/live/ContactChat.ts +655 -336
- package/src/live/ContactDetails.ts +961 -88
- package/src/live/ContactFieldEditor.ts +46 -11
- package/src/live/ContactFields.ts +57 -16
- package/src/live/ContactStoreElement.ts +15 -8
- package/src/locales/es.ts +3 -2
- package/src/locales/fr.ts +3 -2
- package/src/locales/pt.ts +3 -2
- package/src/simulator/Simulator.ts +28 -0
- package/src/styles/pillVariants.ts +13 -1
- package/web-test-runner.config.mjs +2 -0
- package/xliff/es.xlf +6 -3
- package/xliff/fr.xlf +6 -3
- package/xliff/pt.xlf +6 -3
package/src/list/ContactList.ts
CHANGED
|
@@ -49,6 +49,12 @@ export class ContactList extends ContentList<Contact> {
|
|
|
49
49
|
@property({ type: String, attribute: 'fields-endpoint' })
|
|
50
50
|
fieldsEndpoint = '/api/v2/fields.json';
|
|
51
51
|
|
|
52
|
+
/** Anonymous workspaces mask URN values, so instead of the URN
|
|
53
|
+
* column the list shows each contact's ref (served as its own
|
|
54
|
+
* anon-only key by the endpoint). */
|
|
55
|
+
@property({ type: Boolean })
|
|
56
|
+
anon = false;
|
|
57
|
+
|
|
52
58
|
@state()
|
|
53
59
|
private featuredFields: any[] = [];
|
|
54
60
|
|
|
@@ -91,6 +97,16 @@ export class ContactList extends ContentList<Contact> {
|
|
|
91
97
|
super.disconnectedCallback();
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
protected willUpdate(changes: PropertyValues): void {
|
|
101
|
+
super.willUpdate(changes);
|
|
102
|
+
// Rebuilding here (rather than in updated()) means a mounted
|
|
103
|
+
// anon attribute is reflected in the first paint instead of
|
|
104
|
+
// flashing the URN header for a frame.
|
|
105
|
+
if (changes.has('anon')) {
|
|
106
|
+
this.columns = this.buildColumns();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
94
110
|
protected updated(changes: PropertyValues): void {
|
|
95
111
|
super.updated(changes);
|
|
96
112
|
if (changes.has('fieldsEndpoint') && this.fieldsEndpoint) {
|
|
@@ -134,27 +150,28 @@ export class ContactList extends ContentList<Contact> {
|
|
|
134
150
|
* created on.
|
|
135
151
|
*
|
|
136
152
|
* Name leads, with URN, the workspace's custom fields, and the
|
|
137
|
-
* last-seen / created-on dates trailing it.
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* scrolls.
|
|
153
|
+
* last-seen / created-on dates trailing it. Columns through Last Seen
|
|
154
|
+
* size to their content between min/max bounds and can be resized;
|
|
155
|
+
* Created On grows to absorb any remaining browser width. Only Name is
|
|
156
|
+
* pinned to the left edge, so identity stays anchored while everything
|
|
157
|
+
* else scrolls.
|
|
143
158
|
*
|
|
144
159
|
* There is deliberately no group-membership column — contacts
|
|
145
160
|
* routinely belong to dozens of groups, so a groups cell is
|
|
146
161
|
* noise rather than signal in a list view. */
|
|
147
162
|
private buildColumns(): ContentListColumn[] {
|
|
148
|
-
// Custom-field columns are all left-aligned for simplicity
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
163
|
+
// Custom-field columns are all left-aligned for simplicity. Their
|
|
164
|
+
// resize floor is deliberately half the generic 80px floor so users
|
|
165
|
+
// can pack more workspace-specific fields into view; maxWidth caps a
|
|
166
|
+
// runaway value.
|
|
152
167
|
const fieldColumns: ContentListColumn[] = (this.featuredFields || []).map(
|
|
153
168
|
(f: any) => ({
|
|
154
169
|
key: FIELD_PREFIX + f.key,
|
|
155
170
|
label: f.name || f.label || f.key,
|
|
156
171
|
sortable: true,
|
|
157
|
-
|
|
172
|
+
resizeMinWidth: '40px',
|
|
173
|
+
maxWidth: '200px',
|
|
174
|
+
resizable: true
|
|
158
175
|
})
|
|
159
176
|
);
|
|
160
177
|
// Name + URN are the pinned identity columns and are not
|
|
@@ -166,14 +183,24 @@ export class ContactList extends ContentList<Contact> {
|
|
|
166
183
|
label: 'Name',
|
|
167
184
|
minWidth: '150px',
|
|
168
185
|
maxWidth: '260px',
|
|
169
|
-
pinned: true
|
|
170
|
-
|
|
171
|
-
{
|
|
172
|
-
key: 'urn',
|
|
173
|
-
label: 'URN',
|
|
174
|
-
minWidth: '120px',
|
|
175
|
-
maxWidth: '190px'
|
|
186
|
+
pinned: true,
|
|
187
|
+
resizable: true
|
|
176
188
|
},
|
|
189
|
+
this.anon
|
|
190
|
+
? {
|
|
191
|
+
key: 'ref',
|
|
192
|
+
label: 'Ref',
|
|
193
|
+
minWidth: '120px',
|
|
194
|
+
maxWidth: '190px',
|
|
195
|
+
resizable: true
|
|
196
|
+
}
|
|
197
|
+
: {
|
|
198
|
+
key: 'urn',
|
|
199
|
+
label: 'URN',
|
|
200
|
+
minWidth: '120px',
|
|
201
|
+
maxWidth: '190px',
|
|
202
|
+
resizable: true
|
|
203
|
+
},
|
|
177
204
|
...fieldColumns,
|
|
178
205
|
{
|
|
179
206
|
key: 'last_seen_on',
|
|
@@ -181,15 +208,16 @@ export class ContactList extends ContentList<Contact> {
|
|
|
181
208
|
sortable: true,
|
|
182
209
|
minWidth: '96px',
|
|
183
210
|
maxWidth: '150px',
|
|
184
|
-
align: 'right'
|
|
211
|
+
align: 'right',
|
|
212
|
+
resizable: true
|
|
185
213
|
},
|
|
186
214
|
{
|
|
187
215
|
key: 'created_on',
|
|
188
216
|
label: 'Created on',
|
|
189
217
|
sortable: true,
|
|
190
218
|
minWidth: '96px',
|
|
191
|
-
|
|
192
|
-
|
|
219
|
+
align: 'right',
|
|
220
|
+
grow: true
|
|
193
221
|
}
|
|
194
222
|
];
|
|
195
223
|
}
|
|
@@ -232,6 +260,10 @@ export class ContactList extends ContentList<Contact> {
|
|
|
232
260
|
return html`<span class="contact-urn"
|
|
233
261
|
>${this.primaryUrn(item) || EMPTY}</span
|
|
234
262
|
>`;
|
|
263
|
+
case 'ref':
|
|
264
|
+
return html`<span class="contact-urn"
|
|
265
|
+
>${(item as any).ref || EMPTY}</span
|
|
266
|
+
>`;
|
|
235
267
|
case 'last_seen_on':
|
|
236
268
|
return item.last_seen_on
|
|
237
269
|
? html`<temba-date
|
|
@@ -281,7 +313,11 @@ export class ContactList extends ContentList<Contact> {
|
|
|
281
313
|
|
|
282
314
|
private primaryUrn(item: Contact): string {
|
|
283
315
|
const i = item as any;
|
|
284
|
-
if (i.urn)
|
|
316
|
+
if (i.urn) {
|
|
317
|
+
// served as {scheme, display} by the list endpoint, but tolerate
|
|
318
|
+
// a plain string (e.g. the public API's urn field)
|
|
319
|
+
return typeof i.urn === 'string' ? i.urn : i.urn.display || '';
|
|
320
|
+
}
|
|
285
321
|
if (Array.isArray(i.urns) && i.urns.length > 0) {
|
|
286
322
|
const u = i.urns[0];
|
|
287
323
|
return typeof u === 'string'
|