datajunction-ui 0.0.27-alpha.0 → 0.0.29
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 +1 -1
- package/src/app/components/NamespaceHeader.jsx +96 -26
- package/src/app/components/__tests__/NamespaceHeader.test.jsx +165 -0
- package/src/app/pages/NamespacePage/Explorer.jsx +68 -10
- package/src/app/pages/NamespacePage/__tests__/index.test.jsx +21 -11
- package/src/app/pages/NamespacePage/index.jsx +316 -47
- package/src/app/pages/NotificationsPage/__tests__/index.test.jsx +28 -0
- package/src/app/pages/QueryPlannerPage/PreAggDetailsPanel.jsx +20 -20
- package/src/app/pages/QueryPlannerPage/index.jsx +1 -1
- package/src/app/pages/Root/__tests__/index.test.jsx +99 -4
- package/src/app/pages/SQLBuilderPage/__tests__/index.test.jsx +177 -0
- package/src/app/pages/SettingsPage/__tests__/CreateServiceAccountModal.test.jsx +50 -0
- package/src/app/pages/SettingsPage/__tests__/NotificationSubscriptionsSection.test.jsx +95 -0
- package/src/app/pages/SettingsPage/__tests__/index.test.jsx +315 -28
- package/src/app/services/DJService.js +33 -0
- package/src/app/utils/__tests__/date.test.js +60 -140
- package/src/styles/index.css +51 -10
|
@@ -185,7 +185,7 @@ describe('SettingsPage', () => {
|
|
|
185
185
|
});
|
|
186
186
|
});
|
|
187
187
|
|
|
188
|
-
it('handles subscription update', async () => {
|
|
188
|
+
it('handles subscription update via edit mode and checkbox toggle', async () => {
|
|
189
189
|
mockDjClient.getNotificationPreferences.mockResolvedValue([
|
|
190
190
|
{
|
|
191
191
|
entity_name: 'default.my_metric',
|
|
@@ -218,18 +218,93 @@ describe('SettingsPage', () => {
|
|
|
218
218
|
expect(screen.getByText('default.my_metric')).toBeInTheDocument();
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
// First click Edit button to enter edit mode and show checkboxes
|
|
222
|
+
const editBtn = screen.getByTitle('Edit subscription');
|
|
223
|
+
fireEvent.click(editBtn);
|
|
224
|
+
|
|
225
|
+
// Wait for checkboxes to appear
|
|
226
|
+
await waitFor(() => {
|
|
227
|
+
expect(screen.getAllByRole('checkbox').length).toBeGreaterThan(0);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Add another activity type (e.g., 'create')
|
|
231
|
+
const createCheckbox = screen.getByLabelText('Create');
|
|
232
|
+
fireEvent.click(createCheckbox);
|
|
233
|
+
|
|
234
|
+
// Save changes
|
|
235
|
+
const saveBtn = screen.getByText('Save');
|
|
236
|
+
fireEvent.click(saveBtn);
|
|
237
|
+
|
|
238
|
+
await waitFor(() => {
|
|
239
|
+
expect(mockDjClient.subscribeToNotifications).toHaveBeenCalledWith({
|
|
240
|
+
entity_type: 'node',
|
|
241
|
+
entity_name: 'default.my_metric',
|
|
242
|
+
activity_types: expect.any(Array),
|
|
243
|
+
alert_types: ['web'],
|
|
228
244
|
});
|
|
229
|
-
}
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('updates local subscription state after subscription update', async () => {
|
|
249
|
+
mockDjClient.getNotificationPreferences.mockResolvedValue([
|
|
250
|
+
{
|
|
251
|
+
entity_name: 'default.my_metric',
|
|
252
|
+
entity_type: 'node',
|
|
253
|
+
activity_types: ['update', 'status_change'],
|
|
254
|
+
alert_types: ['web'],
|
|
255
|
+
},
|
|
256
|
+
]);
|
|
257
|
+
|
|
258
|
+
mockDjClient.getNodesByNames.mockResolvedValue([
|
|
259
|
+
{
|
|
260
|
+
name: 'default.my_metric',
|
|
261
|
+
type: 'METRIC',
|
|
262
|
+
current: {
|
|
263
|
+
displayName: 'My Metric',
|
|
264
|
+
status: 'VALID',
|
|
265
|
+
mode: 'PUBLISHED',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
]);
|
|
269
|
+
|
|
270
|
+
mockDjClient.subscribeToNotifications.mockResolvedValue({
|
|
271
|
+
status: 200,
|
|
272
|
+
json: { message: 'Updated' },
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
renderWithContext();
|
|
276
|
+
|
|
277
|
+
await waitFor(() => {
|
|
278
|
+
expect(screen.getByText('default.my_metric')).toBeInTheDocument();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// First click the Edit button to enter edit mode
|
|
282
|
+
const editBtn = screen.getByTitle('Edit subscription');
|
|
283
|
+
fireEvent.click(editBtn);
|
|
284
|
+
|
|
285
|
+
// Now checkboxes should be visible
|
|
286
|
+
await waitFor(() => {
|
|
287
|
+
expect(screen.getAllByRole('checkbox').length).toBeGreaterThan(0);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Toggle a checkbox and save
|
|
291
|
+
const checkboxes = screen.getAllByRole('checkbox');
|
|
292
|
+
fireEvent.click(checkboxes[0]);
|
|
293
|
+
|
|
294
|
+
// Click Save button
|
|
295
|
+
const saveBtn = screen.getByText('Save');
|
|
296
|
+
fireEvent.click(saveBtn);
|
|
297
|
+
|
|
298
|
+
await waitFor(() => {
|
|
299
|
+
expect(mockDjClient.subscribeToNotifications).toHaveBeenCalled();
|
|
300
|
+
});
|
|
230
301
|
});
|
|
231
302
|
|
|
232
|
-
it('handles subscription unsubscribe', async () => {
|
|
303
|
+
it('handles subscription unsubscribe and removes from list', async () => {
|
|
304
|
+
// Mock window.confirm to return true
|
|
305
|
+
const originalConfirm = window.confirm;
|
|
306
|
+
window.confirm = jest.fn().mockReturnValue(true);
|
|
307
|
+
|
|
233
308
|
mockDjClient.getNotificationPreferences.mockResolvedValue([
|
|
234
309
|
{
|
|
235
310
|
entity_name: 'default.my_metric',
|
|
@@ -237,6 +312,12 @@ describe('SettingsPage', () => {
|
|
|
237
312
|
activity_types: ['update'],
|
|
238
313
|
alert_types: ['web'],
|
|
239
314
|
},
|
|
315
|
+
{
|
|
316
|
+
entity_name: 'default.another_metric',
|
|
317
|
+
entity_type: 'node',
|
|
318
|
+
activity_types: ['status_change'],
|
|
319
|
+
alert_types: ['web'],
|
|
320
|
+
},
|
|
240
321
|
]);
|
|
241
322
|
|
|
242
323
|
mockDjClient.getNodesByNames.mockResolvedValue([
|
|
@@ -249,6 +330,15 @@ describe('SettingsPage', () => {
|
|
|
249
330
|
mode: 'PUBLISHED',
|
|
250
331
|
},
|
|
251
332
|
},
|
|
333
|
+
{
|
|
334
|
+
name: 'default.another_metric',
|
|
335
|
+
type: 'METRIC',
|
|
336
|
+
current: {
|
|
337
|
+
displayName: 'Another Metric',
|
|
338
|
+
status: 'VALID',
|
|
339
|
+
mode: 'PUBLISHED',
|
|
340
|
+
},
|
|
341
|
+
},
|
|
252
342
|
]);
|
|
253
343
|
|
|
254
344
|
mockDjClient.unsubscribeFromNotifications.mockResolvedValue({
|
|
@@ -260,18 +350,20 @@ describe('SettingsPage', () => {
|
|
|
260
350
|
|
|
261
351
|
await waitFor(() => {
|
|
262
352
|
expect(screen.getByText('default.my_metric')).toBeInTheDocument();
|
|
353
|
+
expect(screen.getByText('default.another_metric')).toBeInTheDocument();
|
|
263
354
|
});
|
|
264
355
|
|
|
265
|
-
// Find unsubscribe
|
|
266
|
-
const
|
|
267
|
-
|
|
356
|
+
// Find unsubscribe buttons (there are multiple, one per subscription)
|
|
357
|
+
const unsubscribeBtns = screen.getAllByTitle('Unsubscribe');
|
|
358
|
+
fireEvent.click(unsubscribeBtns[0]);
|
|
359
|
+
|
|
360
|
+
await waitFor(() => {
|
|
361
|
+
expect(window.confirm).toHaveBeenCalled();
|
|
362
|
+
expect(mockDjClient.unsubscribeFromNotifications).toHaveBeenCalled();
|
|
268
363
|
});
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
expect(mockDjClient.unsubscribeFromNotifications).toHaveBeenCalled();
|
|
273
|
-
});
|
|
274
|
-
}
|
|
364
|
+
|
|
365
|
+
// Restore original confirm
|
|
366
|
+
window.confirm = originalConfirm;
|
|
275
367
|
});
|
|
276
368
|
|
|
277
369
|
it('opens create service account modal', async () => {
|
|
@@ -291,7 +383,69 @@ describe('SettingsPage', () => {
|
|
|
291
383
|
});
|
|
292
384
|
});
|
|
293
385
|
|
|
294
|
-
it('
|
|
386
|
+
it('creates service account and adds to list when successful', async () => {
|
|
387
|
+
const newAccount = {
|
|
388
|
+
id: 99,
|
|
389
|
+
name: 'new-account',
|
|
390
|
+
client_id: 'new-client-id-123',
|
|
391
|
+
client_secret: 'secret-xyz',
|
|
392
|
+
created_at: '2025-01-11T00:00:00Z',
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
mockDjClient.listServiceAccounts.mockResolvedValue([]);
|
|
396
|
+
mockDjClient.createServiceAccount.mockResolvedValue(newAccount);
|
|
397
|
+
|
|
398
|
+
renderWithContext();
|
|
399
|
+
|
|
400
|
+
await waitFor(() => {
|
|
401
|
+
expect(screen.getByText('Settings')).toBeInTheDocument();
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// Open create modal
|
|
405
|
+
const createBtn = screen.getByRole('button', { name: /create/i });
|
|
406
|
+
fireEvent.click(createBtn);
|
|
407
|
+
|
|
408
|
+
await waitFor(() => {
|
|
409
|
+
expect(screen.getByText('Create Service Account')).toBeInTheDocument();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Fill in the name input using ID
|
|
413
|
+
const nameInput = document.getElementById('service-account-name');
|
|
414
|
+
fireEvent.change(nameInput, { target: { value: 'new-account' } });
|
|
415
|
+
|
|
416
|
+
// Submit the form by clicking the submit button in the modal
|
|
417
|
+
const submitBtns = screen.getAllByRole('button', { name: /create/i });
|
|
418
|
+
// The second Create button is the submit button in the modal
|
|
419
|
+
fireEvent.click(submitBtns[submitBtns.length - 1]);
|
|
420
|
+
|
|
421
|
+
await waitFor(() => {
|
|
422
|
+
expect(mockDjClient.createServiceAccount).toHaveBeenCalledWith(
|
|
423
|
+
'new-account',
|
|
424
|
+
);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('does not add service account to list if creation returns no client_id', async () => {
|
|
429
|
+
mockDjClient.listServiceAccounts.mockResolvedValue([]);
|
|
430
|
+
mockDjClient.createServiceAccount.mockResolvedValue({
|
|
431
|
+
error: 'Name already exists',
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
renderWithContext();
|
|
435
|
+
|
|
436
|
+
await waitFor(() => {
|
|
437
|
+
expect(screen.getByText('Settings')).toBeInTheDocument();
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
// The service accounts section should still show empty state
|
|
441
|
+
expect(screen.getByText(/No service accounts yet/i)).toBeInTheDocument();
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('handles service account deletion by clicking delete button with confirmation', async () => {
|
|
445
|
+
// Mock window.confirm to return true
|
|
446
|
+
const originalConfirm = window.confirm;
|
|
447
|
+
window.confirm = jest.fn().mockReturnValue(true);
|
|
448
|
+
|
|
295
449
|
mockDjClient.listServiceAccounts.mockResolvedValue([
|
|
296
450
|
{
|
|
297
451
|
id: 1,
|
|
@@ -299,6 +453,12 @@ describe('SettingsPage', () => {
|
|
|
299
453
|
client_id: 'abc-123',
|
|
300
454
|
created_at: '2024-12-01T00:00:00Z',
|
|
301
455
|
},
|
|
456
|
+
{
|
|
457
|
+
id: 2,
|
|
458
|
+
name: 'other-pipeline',
|
|
459
|
+
client_id: 'def-456',
|
|
460
|
+
created_at: '2024-12-02T00:00:00Z',
|
|
461
|
+
},
|
|
302
462
|
]);
|
|
303
463
|
|
|
304
464
|
mockDjClient.deleteServiceAccount.mockResolvedValue({
|
|
@@ -309,16 +469,98 @@ describe('SettingsPage', () => {
|
|
|
309
469
|
|
|
310
470
|
await waitFor(() => {
|
|
311
471
|
expect(screen.getByText('my-pipeline')).toBeInTheDocument();
|
|
472
|
+
expect(screen.getByText('other-pipeline')).toBeInTheDocument();
|
|
312
473
|
});
|
|
313
474
|
|
|
314
|
-
// Find delete button
|
|
315
|
-
const deleteBtn = screen.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
475
|
+
// Find delete button by title attribute (exact match) - first one for my-pipeline
|
|
476
|
+
const deleteBtn = screen.getAllByTitle('Delete service account')[0];
|
|
477
|
+
fireEvent.click(deleteBtn);
|
|
478
|
+
|
|
479
|
+
await waitFor(() => {
|
|
480
|
+
expect(window.confirm).toHaveBeenCalled();
|
|
481
|
+
expect(mockDjClient.deleteServiceAccount).toHaveBeenCalledWith('abc-123');
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// Restore original confirm
|
|
485
|
+
window.confirm = originalConfirm;
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it('removes service account from list after deletion', async () => {
|
|
489
|
+
// Mock window.confirm to return true
|
|
490
|
+
const originalConfirm = window.confirm;
|
|
491
|
+
window.confirm = jest.fn().mockReturnValue(true);
|
|
492
|
+
|
|
493
|
+
mockDjClient.listServiceAccounts.mockResolvedValue([
|
|
494
|
+
{
|
|
495
|
+
id: 1,
|
|
496
|
+
name: 'my-pipeline',
|
|
497
|
+
client_id: 'abc-123',
|
|
498
|
+
created_at: '2024-12-01T00:00:00Z',
|
|
499
|
+
},
|
|
500
|
+
]);
|
|
501
|
+
|
|
502
|
+
mockDjClient.deleteServiceAccount.mockResolvedValue({
|
|
503
|
+
message: 'Deleted',
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
renderWithContext();
|
|
507
|
+
|
|
508
|
+
await waitFor(() => {
|
|
509
|
+
expect(screen.getByText('my-pipeline')).toBeInTheDocument();
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// Find and click the delete button
|
|
513
|
+
const deleteBtn = screen.getByTitle('Delete service account');
|
|
514
|
+
fireEvent.click(deleteBtn);
|
|
515
|
+
|
|
516
|
+
await waitFor(() => {
|
|
517
|
+
expect(mockDjClient.deleteServiceAccount).toHaveBeenCalledWith('abc-123');
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
// After deletion, the account should be removed
|
|
521
|
+
await waitFor(() => {
|
|
522
|
+
expect(screen.queryByText('my-pipeline')).not.toBeInTheDocument();
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// Restore original confirm
|
|
526
|
+
window.confirm = originalConfirm;
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('does not delete service account when confirmation is cancelled', async () => {
|
|
530
|
+
// Mock window.confirm to return false
|
|
531
|
+
const originalConfirm = window.confirm;
|
|
532
|
+
window.confirm = jest.fn().mockReturnValue(false);
|
|
533
|
+
|
|
534
|
+
mockDjClient.listServiceAccounts.mockResolvedValue([
|
|
535
|
+
{
|
|
536
|
+
id: 1,
|
|
537
|
+
name: 'my-pipeline',
|
|
538
|
+
client_id: 'abc-123',
|
|
539
|
+
created_at: '2024-12-01T00:00:00Z',
|
|
540
|
+
},
|
|
541
|
+
]);
|
|
542
|
+
|
|
543
|
+
renderWithContext();
|
|
544
|
+
|
|
545
|
+
await waitFor(() => {
|
|
546
|
+
expect(screen.getByText('my-pipeline')).toBeInTheDocument();
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
// Find and click the delete button
|
|
550
|
+
const deleteBtn = screen.getByTitle('Delete service account');
|
|
551
|
+
fireEvent.click(deleteBtn);
|
|
552
|
+
|
|
553
|
+
// Should show confirmation
|
|
554
|
+
expect(window.confirm).toHaveBeenCalled();
|
|
555
|
+
|
|
556
|
+
// deleteServiceAccount should NOT be called since user cancelled
|
|
557
|
+
expect(mockDjClient.deleteServiceAccount).not.toHaveBeenCalled();
|
|
558
|
+
|
|
559
|
+
// Account should still be in the list
|
|
560
|
+
expect(screen.getByText('my-pipeline')).toBeInTheDocument();
|
|
561
|
+
|
|
562
|
+
// Restore original confirm
|
|
563
|
+
window.confirm = originalConfirm;
|
|
322
564
|
});
|
|
323
565
|
|
|
324
566
|
it('handles non-node subscription types gracefully', async () => {
|
|
@@ -352,4 +594,49 @@ describe('SettingsPage', () => {
|
|
|
352
594
|
// getNotificationPreferences should not be called while user is loading
|
|
353
595
|
expect(mockDjClient.getNotificationPreferences).not.toHaveBeenCalled();
|
|
354
596
|
});
|
|
597
|
+
|
|
598
|
+
it('handles notification preferences fetch error gracefully', async () => {
|
|
599
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
600
|
+
mockDjClient.getNotificationPreferences.mockRejectedValue(
|
|
601
|
+
new Error('Failed to fetch preferences'),
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
renderWithContext();
|
|
605
|
+
|
|
606
|
+
await waitFor(() => {
|
|
607
|
+
// Page should still render after error
|
|
608
|
+
expect(screen.getByText('Settings')).toBeInTheDocument();
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// Error should be logged
|
|
612
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
613
|
+
|
|
614
|
+
consoleSpy.mockRestore();
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
it('handles null notification preferences response', async () => {
|
|
618
|
+
mockDjClient.getNotificationPreferences.mockResolvedValue(null);
|
|
619
|
+
|
|
620
|
+
renderWithContext();
|
|
621
|
+
|
|
622
|
+
await waitFor(() => {
|
|
623
|
+
expect(screen.getByText('Settings')).toBeInTheDocument();
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
// Should render subscriptions section with empty list
|
|
627
|
+
expect(screen.getByText(/not watching any nodes yet/i)).toBeInTheDocument();
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('handles null service accounts response', async () => {
|
|
631
|
+
mockDjClient.listServiceAccounts.mockResolvedValue(null);
|
|
632
|
+
|
|
633
|
+
renderWithContext();
|
|
634
|
+
|
|
635
|
+
await waitFor(() => {
|
|
636
|
+
expect(screen.getByText('Settings')).toBeInTheDocument();
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// Should render service accounts section with empty list
|
|
640
|
+
expect(screen.getByText(/No service accounts yet/i)).toBeInTheDocument();
|
|
641
|
+
});
|
|
355
642
|
});
|
|
@@ -10,6 +10,9 @@ const DJ_GQL = process.env.REACT_APP_DJ_GQL
|
|
|
10
10
|
? process.env.REACT_APP_DJ_GQL
|
|
11
11
|
: process.env.REACT_APP_DJ_URL + '/graphql';
|
|
12
12
|
|
|
13
|
+
// Export the base URL for components that need direct access
|
|
14
|
+
export const getDJUrl = () => DJ_URL;
|
|
15
|
+
|
|
13
16
|
export const DataJunctionAPI = {
|
|
14
17
|
listNodesForLanding: async function (
|
|
15
18
|
namespace,
|
|
@@ -1014,6 +1017,27 @@ export const DataJunctionAPI = {
|
|
|
1014
1017
|
).json();
|
|
1015
1018
|
},
|
|
1016
1019
|
|
|
1020
|
+
namespaceSources: async function (namespace) {
|
|
1021
|
+
return await (
|
|
1022
|
+
await fetch(`${DJ_URL}/namespaces/${namespace}/sources`, {
|
|
1023
|
+
credentials: 'include',
|
|
1024
|
+
})
|
|
1025
|
+
).json();
|
|
1026
|
+
},
|
|
1027
|
+
|
|
1028
|
+
namespaceSourcesBulk: async function (namespaces) {
|
|
1029
|
+
return await (
|
|
1030
|
+
await fetch(`${DJ_URL}/namespaces/sources/bulk`, {
|
|
1031
|
+
method: 'POST',
|
|
1032
|
+
headers: {
|
|
1033
|
+
'Content-Type': 'application/json',
|
|
1034
|
+
},
|
|
1035
|
+
body: JSON.stringify({ namespaces }),
|
|
1036
|
+
credentials: 'include',
|
|
1037
|
+
})
|
|
1038
|
+
).json();
|
|
1039
|
+
},
|
|
1040
|
+
|
|
1017
1041
|
sql: async function (metric_name, selection) {
|
|
1018
1042
|
const params = new URLSearchParams(selection);
|
|
1019
1043
|
for (const [key, value] of Object.entries(selection)) {
|
|
@@ -1107,6 +1131,7 @@ export const DataJunctionAPI = {
|
|
|
1107
1131
|
metricSelection,
|
|
1108
1132
|
dimensionSelection,
|
|
1109
1133
|
filters = '',
|
|
1134
|
+
useMaterialized = true,
|
|
1110
1135
|
) {
|
|
1111
1136
|
const params = new URLSearchParams();
|
|
1112
1137
|
metricSelection.forEach(metric => params.append('metrics', metric));
|
|
@@ -1116,9 +1141,17 @@ export const DataJunctionAPI = {
|
|
|
1116
1141
|
if (filters) {
|
|
1117
1142
|
params.append('filters', filters);
|
|
1118
1143
|
}
|
|
1144
|
+
if (useMaterialized) {
|
|
1145
|
+
params.append('use_materialized', 'true');
|
|
1146
|
+
params.append('dialect', 'druid');
|
|
1147
|
+
} else {
|
|
1148
|
+
params.append('use_materialized', 'false');
|
|
1149
|
+
params.append('dialect', 'spark');
|
|
1150
|
+
}
|
|
1119
1151
|
return await (
|
|
1120
1152
|
await fetch(`${DJ_URL}/sql/metrics/v3/?${params}`, {
|
|
1121
1153
|
credentials: 'include',
|
|
1154
|
+
params: params,
|
|
1122
1155
|
})
|
|
1123
1156
|
).json();
|
|
1124
1157
|
},
|