@nyaruka/temba-components 0.131.2 → 0.131.3
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 +14 -0
- package/demo/components/floating-tabs/example.html +400 -0
- package/demo/components/flow/index.html +1 -1
- package/demo/data/flows/sample-flow.json +41 -2
- package/demo/data/flows/voicemail.json +613 -0
- package/demo/index.html +6 -0
- package/dist/locales/es.js +5 -5
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +5 -5
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/locale-codes.js +11 -2
- package/dist/locales/locale-codes.js.map +1 -1
- package/dist/locales/pt.js +5 -5
- package/dist/locales/pt.js.map +1 -1
- package/dist/temba-components.js +1109 -535
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +167 -0
- package/out-tsc/src/display/FloatingTab.js.map +1 -0
- package/out-tsc/src/display/ProgressBar.js +22 -2
- package/out-tsc/src/display/ProgressBar.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +165 -31
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +857 -3
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +239 -19
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +44 -3
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
- package/out-tsc/src/flow/StickyNote.js +12 -3
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +2 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +2 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/play_audio.js +2 -1
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +2 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/request_optin.js +1 -0
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +2 -1
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +2 -1
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +2 -1
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +93 -3
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +2 -1
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +2 -1
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +2 -10
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/shared.js +54 -0
- package/out-tsc/src/flow/nodes/shared.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -3
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_groups.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_intent.js +3 -2
- package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +9 -2
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +9 -2
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_run_result.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_scheme.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +8 -3
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +15 -0
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +346 -0
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
- package/out-tsc/src/live/ContactChat.js +3 -19
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/locales/es.js +5 -5
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +5 -5
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/locale-codes.js +11 -2
- package/out-tsc/src/locales/locale-codes.js.map +1 -1
- package/out-tsc/src/locales/pt.js +5 -5
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/store/AppState.js +67 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/temba-modules.js +4 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-floating-tab.test.js +91 -0
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
- package/out-tsc/test/temba-floating-window.test.js +301 -0
- package/out-tsc/test/temba-floating-window.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +117 -0
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-localization.test.js +471 -0
- package/out-tsc/test/temba-localization.test.js.map +1 -0
- package/out-tsc/test/temba-node-type-selector.test.js +150 -0
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +18 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/floating-tab/default.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/hidden.png +0 -0
- package/screenshots/truth/floating-tab/hover.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/floating-window/chromeless.png +0 -0
- package/screenshots/truth/floating-window/custom-size.png +0 -0
- package/screenshots/truth/floating-window/default.png +0 -0
- package/screenshots/truth/floating-window/with-header.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/src/display/FloatingTab.ts +174 -0
- package/src/display/ProgressBar.ts +22 -2
- package/src/events.ts +2 -4
- package/src/flow/CanvasNode.ts +190 -32
- package/src/flow/Editor.ts +1040 -3
- package/src/flow/NodeEditor.ts +317 -19
- package/src/flow/NodeTypeSelector.ts +47 -3
- package/src/flow/StickyNote.ts +12 -3
- package/src/flow/actions/add_contact_groups.ts +2 -1
- package/src/flow/actions/add_contact_urn.ts +3 -1
- package/src/flow/actions/add_input_labels.ts +2 -1
- package/src/flow/actions/play_audio.ts +2 -1
- package/src/flow/actions/remove_contact_groups.ts +3 -1
- package/src/flow/actions/request_optin.ts +1 -0
- package/src/flow/actions/say_msg.ts +2 -1
- package/src/flow/actions/send_broadcast.ts +2 -1
- package/src/flow/actions/send_email.ts +3 -1
- package/src/flow/actions/send_msg.ts +134 -3
- package/src/flow/actions/set_contact_channel.ts +2 -1
- package/src/flow/actions/set_contact_field.ts +2 -1
- package/src/flow/actions/set_contact_language.ts +3 -1
- package/src/flow/actions/set_contact_name.ts +2 -1
- package/src/flow/actions/set_contact_status.ts +2 -1
- package/src/flow/actions/set_run_result.ts +2 -1
- package/src/flow/actions/start_session.ts +3 -1
- package/src/flow/config.ts +2 -12
- package/src/flow/nodes/shared.ts +70 -1
- package/src/flow/nodes/split_by_airtime.ts +20 -3
- package/src/flow/nodes/split_by_contact_field.ts +13 -3
- package/src/flow/nodes/split_by_expression.ts +13 -3
- package/src/flow/nodes/split_by_groups.ts +13 -3
- package/src/flow/nodes/split_by_intent.ts +3 -2
- package/src/flow/nodes/split_by_llm.ts +19 -2
- package/src/flow/nodes/split_by_llm_categorize.ts +19 -2
- package/src/flow/nodes/split_by_random.ts +12 -2
- package/src/flow/nodes/split_by_resthook.ts +13 -3
- package/src/flow/nodes/split_by_run_result.ts +13 -3
- package/src/flow/nodes/split_by_scheme.ts +13 -3
- package/src/flow/nodes/split_by_subflow.ts +12 -2
- package/src/flow/nodes/split_by_ticket.ts +12 -2
- package/src/flow/nodes/split_by_webhook.ts +12 -2
- package/src/flow/nodes/wait_for_digits.ts +3 -2
- package/src/flow/nodes/wait_for_menu.ts +3 -2
- package/src/flow/nodes/wait_for_response.ts +13 -3
- package/src/flow/types.ts +47 -0
- package/src/layout/FloatingWindow.ts +386 -0
- package/src/live/ContactChat.ts +4 -19
- package/src/locales/es.ts +18 -13
- package/src/locales/fr.ts +18 -13
- package/src/locales/locale-codes.ts +11 -2
- package/src/locales/pt.ts +18 -13
- package/src/store/AppState.ts +104 -0
- package/static/api/llms.json +18 -0
- package/temba-modules.ts +4 -0
- package/test/temba-floating-tab.test.ts +110 -0
- package/test/temba-floating-window.test.ts +477 -0
- package/test/temba-flow-editor-node.test.ts +144 -0
- package/test/temba-localization.test.ts +611 -0
- package/test/temba-node-type-selector.test.ts +203 -0
- package/test/utils.test.ts +20 -0
- package/test-assets/contacts/history.json +5 -6
- package/test-assets/select/llms.json +2 -2
- package/web-dev-server.config.mjs +47 -1
- package/web-test-runner.config.mjs +0 -1
- package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
- package/src/flow/nodes/wait_for_audio.ts +0 -7
- package/src/flow/nodes/wait_for_image.ts +0 -7
- package/src/flow/nodes/wait_for_location.ts +0 -7
- package/src/flow/nodes/wait_for_video.ts +0 -7
|
@@ -149,4 +149,207 @@ describe('temba-node-type-selector', () => {
|
|
|
149
149
|
expect(selectionDetail.position).to.deep.equal({ x: 100, y: 100 });
|
|
150
150
|
expect(selector.open).to.be.false;
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
it('filters actions by flow type - voice flow should show voice-only actions', async () => {
|
|
154
|
+
const selector = await createSelector();
|
|
155
|
+
selector.flowType = 'voice';
|
|
156
|
+
await selector.updateComplete;
|
|
157
|
+
selector.show('action', { x: 100, y: 100 });
|
|
158
|
+
await selector.updateComplete;
|
|
159
|
+
|
|
160
|
+
// get all node item titles
|
|
161
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
162
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
163
|
+
item.textContent?.trim()
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// voice flow should have Say Message and Play Audio
|
|
167
|
+
expect(titles).to.include('Say Message');
|
|
168
|
+
expect(titles).to.include('Play Audio');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('filters actions by flow type - message flow should not show voice-only actions', async () => {
|
|
172
|
+
const selector = await createSelector();
|
|
173
|
+
selector.flowType = 'message';
|
|
174
|
+
await selector.updateComplete;
|
|
175
|
+
selector.show('action', { x: 100, y: 100 });
|
|
176
|
+
await selector.updateComplete;
|
|
177
|
+
|
|
178
|
+
// get all node item titles
|
|
179
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
180
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
181
|
+
item.textContent?.trim()
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// message flow should not have Say Message or Play Audio
|
|
185
|
+
expect(titles).to.not.include('Say Message');
|
|
186
|
+
expect(titles).to.not.include('Play Audio');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('filters splits by flow type - message flow should show wait for response', async () => {
|
|
190
|
+
const selector = await createSelector();
|
|
191
|
+
selector.flowType = 'message';
|
|
192
|
+
await selector.updateComplete;
|
|
193
|
+
selector.show('split', { x: 100, y: 100 });
|
|
194
|
+
await selector.updateComplete;
|
|
195
|
+
|
|
196
|
+
// get all node item titles
|
|
197
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
198
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
199
|
+
item.textContent?.trim()
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// message flow should have Wait for Response
|
|
203
|
+
expect(titles).to.include('Wait for Response');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('filters splits by flow type - voice flow should not show wait for response', async () => {
|
|
207
|
+
const selector = await createSelector();
|
|
208
|
+
selector.flowType = 'voice';
|
|
209
|
+
await selector.updateComplete;
|
|
210
|
+
selector.show('split', { x: 100, y: 100 });
|
|
211
|
+
await selector.updateComplete;
|
|
212
|
+
|
|
213
|
+
// get all node item titles
|
|
214
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
215
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
216
|
+
item.textContent?.trim()
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// voice flow should not have Wait for Response
|
|
220
|
+
expect(titles).to.not.include('Wait for Response');
|
|
221
|
+
|
|
222
|
+
// but should have Wait for Digits and Wait for Menu Selection
|
|
223
|
+
expect(titles).to.include('Wait for Digits');
|
|
224
|
+
expect(titles).to.include('Wait for Menu Selection');
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('filters by features - AI feature enables AI splits', async () => {
|
|
228
|
+
const selector = await createSelector();
|
|
229
|
+
selector.flowType = 'message';
|
|
230
|
+
selector.features = ['ai'];
|
|
231
|
+
await selector.updateComplete;
|
|
232
|
+
selector.show('split', { x: 100, y: 100 });
|
|
233
|
+
await selector.updateComplete;
|
|
234
|
+
|
|
235
|
+
// get all node item titles
|
|
236
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
237
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
238
|
+
item.textContent?.trim()
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// with ai feature, should have Split by AI
|
|
242
|
+
expect(titles).to.include('Split by AI');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('filters by features - without AI feature, AI splits are hidden', async () => {
|
|
246
|
+
const selector = await createSelector();
|
|
247
|
+
selector.flowType = 'message';
|
|
248
|
+
selector.features = [];
|
|
249
|
+
await selector.updateComplete;
|
|
250
|
+
selector.show('split', { x: 100, y: 100 });
|
|
251
|
+
await selector.updateComplete;
|
|
252
|
+
|
|
253
|
+
// get all node item titles
|
|
254
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
255
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
256
|
+
item.textContent?.trim()
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
// without ai feature, should not have Split by AI
|
|
260
|
+
expect(titles).to.not.include('Split by AI');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('filters by features - airtime feature enables airtime actions', async () => {
|
|
264
|
+
const selector = await createSelector();
|
|
265
|
+
selector.flowType = 'message';
|
|
266
|
+
selector.features = ['airtime'];
|
|
267
|
+
await selector.updateComplete;
|
|
268
|
+
selector.show('action', { x: 100, y: 100 });
|
|
269
|
+
await selector.updateComplete;
|
|
270
|
+
|
|
271
|
+
// get all node item titles
|
|
272
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
273
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
274
|
+
item.textContent?.trim()
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
// with airtime feature, should have Send Airtime
|
|
278
|
+
expect(titles).to.include('Send Airtime');
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('filters by features - without airtime feature, airtime actions are hidden', async () => {
|
|
282
|
+
const selector = await createSelector();
|
|
283
|
+
selector.flowType = 'message';
|
|
284
|
+
selector.features = [];
|
|
285
|
+
await selector.updateComplete;
|
|
286
|
+
selector.show('action', { x: 100, y: 100 });
|
|
287
|
+
await selector.updateComplete;
|
|
288
|
+
|
|
289
|
+
// get all node item titles
|
|
290
|
+
const nodeItems = selector.shadowRoot?.querySelectorAll('.node-item-title');
|
|
291
|
+
const titles = Array.from(nodeItems || []).map((item) =>
|
|
292
|
+
item.textContent?.trim()
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
// without airtime feature, should not have Send Airtime
|
|
296
|
+
expect(titles).to.not.include('Send Airtime');
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('hides actions/nodes with empty flowTypes array from selector', async () => {
|
|
300
|
+
const selector = await createSelector();
|
|
301
|
+
|
|
302
|
+
// test that isConfigAvailable returns false for empty flowTypes array
|
|
303
|
+
const configWithEmptyFlowTypes = {
|
|
304
|
+
name: 'Test Action',
|
|
305
|
+
type: 'test_action',
|
|
306
|
+
flowTypes: [] // empty array should hide from all flow types
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
selector.flowType = 'message';
|
|
310
|
+
await selector.updateComplete;
|
|
311
|
+
|
|
312
|
+
// call private method via any to test behavior
|
|
313
|
+
const isAvailable = (selector as any).isConfigAvailable(
|
|
314
|
+
configWithEmptyFlowTypes
|
|
315
|
+
);
|
|
316
|
+
expect(isAvailable).to.be.false;
|
|
317
|
+
|
|
318
|
+
// test with different flow types - should still be false
|
|
319
|
+
selector.flowType = 'voice';
|
|
320
|
+
await selector.updateComplete;
|
|
321
|
+
|
|
322
|
+
const isAvailableVoice = (selector as any).isConfigAvailable(
|
|
323
|
+
configWithEmptyFlowTypes
|
|
324
|
+
);
|
|
325
|
+
expect(isAvailableVoice).to.be.false;
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('shows actions/nodes with undefined flowTypes for all flow types', async () => {
|
|
329
|
+
const selector = await createSelector();
|
|
330
|
+
|
|
331
|
+
// test that isConfigAvailable returns true for undefined flowTypes
|
|
332
|
+
const configWithUndefinedFlowTypes = {
|
|
333
|
+
name: 'Test Action',
|
|
334
|
+
type: 'test_action'
|
|
335
|
+
// flowTypes is undefined - should be available for all
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
selector.flowType = 'message';
|
|
339
|
+
await selector.updateComplete;
|
|
340
|
+
|
|
341
|
+
const isAvailable = (selector as any).isConfigAvailable(
|
|
342
|
+
configWithUndefinedFlowTypes
|
|
343
|
+
);
|
|
344
|
+
expect(isAvailable).to.be.true;
|
|
345
|
+
|
|
346
|
+
// test with different flow types - should still be true
|
|
347
|
+
selector.flowType = 'voice';
|
|
348
|
+
await selector.updateComplete;
|
|
349
|
+
|
|
350
|
+
const isAvailableVoice = (selector as any).isConfigAvailable(
|
|
351
|
+
configWithUndefinedFlowTypes
|
|
352
|
+
);
|
|
353
|
+
expect(isAvailableVoice).to.be.true;
|
|
354
|
+
});
|
|
152
355
|
});
|
package/test/utils.test.ts
CHANGED
|
@@ -8,6 +8,26 @@ interface Clip {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
import { expect, fixture, html, assert } from '@open-wc/testing';
|
|
11
|
+
|
|
12
|
+
// disable transitions for all tests to prevent flaky screenshot tests
|
|
13
|
+
const style = document.createElement('style');
|
|
14
|
+
style.textContent = `
|
|
15
|
+
* {
|
|
16
|
+
--transition-duration: 0ms !important;
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
document.head.appendChild(style);
|
|
20
|
+
|
|
21
|
+
// prevent resize event listeners from being added during tests
|
|
22
|
+
// this prevents flaky positioning in components that adjust on resize
|
|
23
|
+
const originalAddEventListener = window.addEventListener;
|
|
24
|
+
window.addEventListener = function (type, listener, options) {
|
|
25
|
+
if (type === 'resize') {
|
|
26
|
+
// skip adding resize listeners during tests
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
return originalAddEventListener.call(this, type, listener, options);
|
|
30
|
+
} as typeof window.addEventListener;
|
|
11
31
|
import MouseHelper from './MouseHelper';
|
|
12
32
|
import { Store } from '../src/store/Store';
|
|
13
33
|
import { stub } from 'sinon';
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
"recent_only": false,
|
|
4
4
|
"next_before": 1617135091567814,
|
|
5
5
|
"next_after": 1609359091567814,
|
|
6
|
-
"start_date": "2019-09-22",
|
|
7
6
|
"events": [
|
|
8
7
|
{
|
|
9
8
|
"uuid": "01997d74-bf67-749a-8440-688a41c3b275",
|
|
@@ -55,7 +54,7 @@
|
|
|
55
54
|
"name": "SMS Channel"
|
|
56
55
|
}
|
|
57
56
|
},
|
|
58
|
-
"_status": {"status": "failed", "reason": "error_limit"},
|
|
57
|
+
"_status": {"created_on": "2025-09-24T20:40:28.239437+00:00", "status": "failed", "reason": "error_limit"},
|
|
59
58
|
"_logs_url": null
|
|
60
59
|
},
|
|
61
60
|
{
|
|
@@ -90,7 +89,7 @@
|
|
|
90
89
|
"name": "SMS Channel"
|
|
91
90
|
}
|
|
92
91
|
},
|
|
93
|
-
"_status": "
|
|
92
|
+
"_status": {"created_on": "2025-09-23T20:40:28.239434+00:00", "status": "wired"},
|
|
94
93
|
"_logs_url": "/channels/channellog/read/1478/"
|
|
95
94
|
},
|
|
96
95
|
{
|
|
@@ -119,7 +118,7 @@
|
|
|
119
118
|
"name": "SMS Channel"
|
|
120
119
|
}
|
|
121
120
|
},
|
|
122
|
-
"_status": "
|
|
121
|
+
"_status": {"created_on": "2025-09-23T20:40:28.239434+00:00", "status": "wired"},
|
|
123
122
|
"_logs_url": "/channels/channellog/read/1476/"
|
|
124
123
|
},
|
|
125
124
|
{
|
|
@@ -148,7 +147,7 @@
|
|
|
148
147
|
"name": "SMS Channel"
|
|
149
148
|
}
|
|
150
149
|
},
|
|
151
|
-
"_status": "
|
|
150
|
+
"_status": {"created_on": "2025-09-23T20:40:28.239434+00:00", "status": "wired"},
|
|
152
151
|
"_logs_url": "/channels/channellog/read/1474/"
|
|
153
152
|
},
|
|
154
153
|
{
|
|
@@ -199,7 +198,7 @@
|
|
|
199
198
|
"name": "SMS Channel"
|
|
200
199
|
}
|
|
201
200
|
},
|
|
202
|
-
"_status": "
|
|
201
|
+
"_status": {"created_on": "2025-09-23T20:40:28.239434+00:00", "status": "wired"},
|
|
203
202
|
"_logs_url": "/channels/channellog/read/1472/"
|
|
204
203
|
},
|
|
205
204
|
{
|
|
@@ -255,7 +255,8 @@ export default {
|
|
|
255
255
|
'/api/v2/workspace.json': 'workspace.json',
|
|
256
256
|
'/api/internal/locations.json': 'locations.json',
|
|
257
257
|
'/api/internal/orgs.json': 'orgs.json',
|
|
258
|
-
'/api/v2/channels.json': 'channels.json'
|
|
258
|
+
'/api/v2/channels.json': 'channels.json',
|
|
259
|
+
'/api/internal/llms.json': 'llms.json'
|
|
259
260
|
};
|
|
260
261
|
|
|
261
262
|
// Handle base path without query parameters
|
|
@@ -328,6 +329,50 @@ export default {
|
|
|
328
329
|
if (context.request.method === 'POST' && context.path === '/api/v2/groups.json') {
|
|
329
330
|
return handleDevEntityCreation('groups', context);
|
|
330
331
|
}
|
|
332
|
+
|
|
333
|
+
// Handle mock LLM translations
|
|
334
|
+
if (
|
|
335
|
+
context.request.method === 'POST' &&
|
|
336
|
+
context.path.startsWith('/llm/translate/')
|
|
337
|
+
) {
|
|
338
|
+
return new Promise((resolve) => {
|
|
339
|
+
let body = '';
|
|
340
|
+
context.req.on('data', (chunk) => {
|
|
341
|
+
body += chunk.toString();
|
|
342
|
+
});
|
|
343
|
+
context.req.on('end', () => {
|
|
344
|
+
let payload = {};
|
|
345
|
+
try {
|
|
346
|
+
payload = body ? JSON.parse(body) : {};
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.warn('Invalid LLM translate payload', error);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const sourceText =
|
|
352
|
+
typeof payload.text === 'string' ? payload.text : '';
|
|
353
|
+
const targetLang = payload.lang?.to || 'eng';
|
|
354
|
+
const modelUuid = context.path.split('/')[3] || 'mock-model';
|
|
355
|
+
|
|
356
|
+
const translated = sourceText
|
|
357
|
+
? `${sourceText} (${targetLang.toUpperCase()})`
|
|
358
|
+
: `Translation for ${targetLang.toUpperCase()}`;
|
|
359
|
+
|
|
360
|
+
context.contentType = 'application/json';
|
|
361
|
+
context.status = 200;
|
|
362
|
+
context.body = JSON.stringify({
|
|
363
|
+
status: 'success',
|
|
364
|
+
model: modelUuid,
|
|
365
|
+
text: translated,
|
|
366
|
+
result: translated,
|
|
367
|
+
lang: {
|
|
368
|
+
from: payload.lang?.from || 'eng',
|
|
369
|
+
to: targetLang
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
resolve();
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
}
|
|
331
376
|
}
|
|
332
377
|
},
|
|
333
378
|
{
|
|
@@ -345,6 +390,7 @@ export default {
|
|
|
345
390
|
|
|
346
391
|
if (fs.existsSync(flowsDir)) {
|
|
347
392
|
const files = fs.readdirSync(flowsDir).filter(file => file.endsWith('.json'));
|
|
393
|
+
console.log(`Listing ${files.length} flow files from ${flowsDir}...`);
|
|
348
394
|
|
|
349
395
|
// Return JSON array of filenames
|
|
350
396
|
context.contentType = 'application/json';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wait_for_audio.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,UAAU,CAAC;AAEpD,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,YAAY,CAAC,IAAI;CACzB,CAAC","sourcesContent":["import { SPLIT_GROUPS, NodeConfig } from '../types';\n\nexport const wait_for_audio: NodeConfig = {\n type: 'wait_for_audio',\n name: 'Wait for Audio',\n group: SPLIT_GROUPS.wait\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wait_for_image.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,UAAU,CAAC;AAEpD,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,YAAY,CAAC,IAAI;CACzB,CAAC","sourcesContent":["import { SPLIT_GROUPS, NodeConfig } from '../types';\n\nexport const wait_for_image: NodeConfig = {\n type: 'wait_for_image',\n name: 'Wait for Image',\n group: SPLIT_GROUPS.wait\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wait_for_location.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_location.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,UAAU,CAAC;AAEpD,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,YAAY,CAAC,IAAI;CACzB,CAAC","sourcesContent":["import { SPLIT_GROUPS, NodeConfig } from '../types';\n\nexport const wait_for_location: NodeConfig = {\n type: 'wait_for_location',\n name: 'Wait for Location',\n group: SPLIT_GROUPS.wait\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wait_for_video.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,UAAU,CAAC;AAEpD,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,YAAY,CAAC,IAAI;CACzB,CAAC","sourcesContent":["import { SPLIT_GROUPS, NodeConfig } from '../types';\n\nexport const wait_for_video: NodeConfig = {\n type: 'wait_for_video',\n name: 'Wait for Video',\n group: SPLIT_GROUPS.wait\n};\n"]}
|