@nyaruka/temba-components 0.160.1 → 0.161.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/package.json
CHANGED
|
@@ -200,7 +200,10 @@ export const split_by_webhook: NodeConfig = {
|
|
|
200
200
|
callWebhookAction?.headers ||
|
|
201
201
|
getDefaultHeadersRecord(callWebhookAction?.method || 'GET'),
|
|
202
202
|
body: callWebhookAction?.body || '',
|
|
203
|
-
|
|
203
|
+
// Legacy webhooks store result_name on the action; modern ones store it
|
|
204
|
+
// on the router. Prefer the action so legacy nodes round-trip correctly.
|
|
205
|
+
result_name:
|
|
206
|
+
callWebhookAction?.result_name || node.router?.result_name || ''
|
|
204
207
|
};
|
|
205
208
|
},
|
|
206
209
|
fromFormData: (formData: FormData, originalNode: Node): Node => {
|
|
@@ -213,9 +216,17 @@ export const split_by_webhook: NodeConfig = {
|
|
|
213
216
|
// Find existing call_webhook action to preserve its UUID
|
|
214
217
|
const existingCallWebhookAction = originalNode.actions?.find(
|
|
215
218
|
(action) => action.type === 'call_webhook'
|
|
216
|
-
);
|
|
219
|
+
) as CallWebhook | undefined;
|
|
217
220
|
const callWebhookUuid = existingCallWebhookAction?.uuid || generateUUID();
|
|
218
221
|
|
|
222
|
+
// Legacy webhooks keep the result_name on the action rather than the
|
|
223
|
+
// router. Detect them by the presence of result_name on the existing
|
|
224
|
+
// action so they continue to round-trip in their original format instead
|
|
225
|
+
// of being silently migrated (which would change how results are
|
|
226
|
+
// referenced downstream of the flow).
|
|
227
|
+
const isLegacyResultName = !!existingCallWebhookAction?.result_name;
|
|
228
|
+
const trimmedResultName = formData.result_name?.trim() || '';
|
|
229
|
+
|
|
219
230
|
// Create call_webhook action
|
|
220
231
|
const callWebhookAction: CallWebhook = {
|
|
221
232
|
type: 'call_webhook',
|
|
@@ -226,6 +237,11 @@ export const split_by_webhook: NodeConfig = {
|
|
|
226
237
|
body: formData.body || ''
|
|
227
238
|
};
|
|
228
239
|
|
|
240
|
+
// Preserve the legacy placement: result_name stays on the action.
|
|
241
|
+
if (isLegacyResultName && trimmedResultName !== '') {
|
|
242
|
+
callWebhookAction.result_name = trimmedResultName;
|
|
243
|
+
}
|
|
244
|
+
|
|
229
245
|
// Create categories and exits for Success and Failure
|
|
230
246
|
const existingCategories = originalNode.router?.categories || [];
|
|
231
247
|
const existingExits = originalNode.exits || [];
|
|
@@ -247,9 +263,11 @@ export const split_by_webhook: NodeConfig = {
|
|
|
247
263
|
...router
|
|
248
264
|
};
|
|
249
265
|
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
266
|
+
// Modern webhooks store result_name on the router. For legacy webhooks the
|
|
267
|
+
// result_name lives on the action (set above), so we leave it off the
|
|
268
|
+
// router to avoid storing it in both places.
|
|
269
|
+
if (!isLegacyResultName && trimmedResultName !== '') {
|
|
270
|
+
finalRouter.result_name = trimmedResultName;
|
|
253
271
|
}
|
|
254
272
|
|
|
255
273
|
// Return the complete node
|
package/src/list/FlowList.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css, html, TemplateResult } from 'lit';
|
|
2
2
|
import { ContentList, ContentListColumn } from './ContentList';
|
|
3
3
|
import { Icon } from '../Icons';
|
|
4
|
-
import { Flow, ObjectReference } from '../interfaces';
|
|
4
|
+
import { CustomEventType, Flow, ObjectReference } from '../interfaces';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Flow CRUDL list — drop-in replacement for the rapidpro
|
|
@@ -89,27 +89,28 @@ export class FlowList extends ContentList<Flow> {
|
|
|
89
89
|
key: 'name',
|
|
90
90
|
label: 'Name',
|
|
91
91
|
sortable: true,
|
|
92
|
-
|
|
92
|
+
minWidth: '160px',
|
|
93
|
+
maxWidth: '280px',
|
|
93
94
|
pinned: true
|
|
94
95
|
},
|
|
95
96
|
{
|
|
96
97
|
key: 'runs',
|
|
97
98
|
label: 'Runs',
|
|
98
99
|
sortable: true,
|
|
99
|
-
|
|
100
|
+
minWidth: '64px',
|
|
100
101
|
align: 'right'
|
|
101
102
|
},
|
|
102
103
|
{
|
|
103
104
|
key: 'ongoing',
|
|
104
105
|
label: 'Ongoing',
|
|
105
106
|
sortable: true,
|
|
106
|
-
|
|
107
|
+
minWidth: '64px',
|
|
107
108
|
align: 'right'
|
|
108
109
|
},
|
|
109
110
|
{
|
|
110
111
|
key: 'completion',
|
|
111
112
|
label: 'Completion',
|
|
112
|
-
|
|
113
|
+
minWidth: '110px',
|
|
113
114
|
align: 'right'
|
|
114
115
|
},
|
|
115
116
|
{ key: 'activity', label: 'Activity', width: '120px', align: 'right' }
|
|
@@ -146,6 +147,25 @@ export class FlowList extends ContentList<Flow> {
|
|
|
146
147
|
return item?.uuid ? `/flow/editor/${item.uuid}/` : null;
|
|
147
148
|
}
|
|
148
149
|
|
|
150
|
+
/** Clicking a label chip opens that label's filtered flow list rather
|
|
151
|
+
* than falling through to the row click (which opens the flow editor). */
|
|
152
|
+
private handleLabelClick(label: ObjectReference, event: MouseEvent): void {
|
|
153
|
+
// Stop the click from bubbling to the row's navigation handler.
|
|
154
|
+
event.stopPropagation();
|
|
155
|
+
if (!label?.uuid) return;
|
|
156
|
+
const href = `/flow/filter/${label.uuid}/`;
|
|
157
|
+
// Guard the JSON-driven href against open-redirect, same as the
|
|
158
|
+
// row-click path in ContentList.handleRowClick.
|
|
159
|
+
if (!this.isSafeHref(href)) return;
|
|
160
|
+
// Meta/ctrl-click opens a new tab, matching ordinary links and the
|
|
161
|
+
// row-click behavior.
|
|
162
|
+
if (event.metaKey || event.ctrlKey) {
|
|
163
|
+
window.open(href, '_blank');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.fireCustomEvent(CustomEventType.Redirected, { url: href });
|
|
167
|
+
}
|
|
168
|
+
|
|
149
169
|
protected renderCell(
|
|
150
170
|
item: Flow,
|
|
151
171
|
column: ContentListColumn
|
|
@@ -166,7 +186,11 @@ export class FlowList extends ContentList<Flow> {
|
|
|
166
186
|
? html`<span class="flow-labels">
|
|
167
187
|
${labels.map(
|
|
168
188
|
(l: ObjectReference) =>
|
|
169
|
-
html`<temba-label
|
|
189
|
+
html`<temba-label
|
|
190
|
+
type="label"
|
|
191
|
+
icon=${Icon.label}
|
|
192
|
+
clickable
|
|
193
|
+
@click=${(e: MouseEvent) => this.handleLabelClick(l, e)}
|
|
170
194
|
>${l.name}</temba-label
|
|
171
195
|
>`
|
|
172
196
|
)}
|