@truedat/qx 7.13.9 → 7.14.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.
Files changed (46) hide show
  1. package/package.json +3 -3
  2. package/src/components/common/ClauseViewer.js +183 -21
  3. package/src/components/common/expressions/Condition.js +13 -6
  4. package/src/components/dataViews/DataViewEditor.js +0 -2
  5. package/src/components/dataViews/DataViewSummary.js +73 -0
  6. package/src/components/dataViews/__tests__/AdvancedDataViewEditor.spec.js +4 -1
  7. package/src/components/dataViews/__tests__/DataViewEditor.spec.js +167 -132
  8. package/src/components/dataViews/__tests__/DataViewSummary.spec.js +820 -0
  9. package/src/components/dataViews/__tests__/DataViews.spec.js +57 -17
  10. package/src/components/dataViews/__tests__/SimpleDataViewEditor.spec.js +140 -141
  11. package/src/components/dataViews/__tests__/__snapshots__/AdvancedDataViewEditor.spec.js.snap +963 -759
  12. package/src/components/dataViews/__tests__/__snapshots__/DataViewSelect.spec.js.snap +17 -13
  13. package/src/components/dataViews/__tests__/__snapshots__/DataViewSummary.spec.js.snap +1786 -0
  14. package/src/components/dataViews/__tests__/__snapshots__/Queryable.spec.js.snap +18 -14
  15. package/src/components/dataViews/__tests__/__snapshots__/Queryables.spec.js.snap +18 -14
  16. package/src/components/dataViews/advancedForm/AdvancedDataViewEditor.js +59 -48
  17. package/src/components/dataViews/queryableProperties/Join.js +2 -1
  18. package/src/components/dataViews/queryableProperties/Select.js +22 -30
  19. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Join.spec.js.snap +1 -1
  20. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Select.spec.js.snap +37 -25
  21. package/src/components/dataViews/queryableSummaryHelpers.js +101 -0
  22. package/src/components/dataViews/simpleForm/SimpleDataViewEditor.js +9 -4
  23. package/src/components/dataViews/summary/From.js +45 -0
  24. package/src/components/dataViews/summary/GroupBy.js +82 -0
  25. package/src/components/dataViews/summary/Join.js +60 -0
  26. package/src/components/dataViews/summary/Select.js +31 -0
  27. package/src/components/dataViews/summary/Where.js +37 -0
  28. package/src/components/qualityControls/ControlPropertiesView.js +115 -63
  29. package/src/components/qualityControls/EditQualityControl.js +5 -3
  30. package/src/components/qualityControls/NewDraftQualityControl.js +8 -3
  31. package/src/components/qualityControls/NewQualityControl.js +5 -3
  32. package/src/components/qualityControls/QualityControlCrumbs.js +46 -5
  33. package/src/components/qualityControls/QualityControlRoutes.js +3 -1
  34. package/src/components/qualityControls/QualityControls.js +9 -18
  35. package/src/components/qualityControls/QualityControlsLabelResults.js +2 -2
  36. package/src/components/qualityControls/__tests__/__snapshots__/ControlPropertiesView.spec.js.snap +12 -9
  37. package/src/components/qualityControls/__tests__/__snapshots__/EditQualityControl.spec.js.snap +536 -493
  38. package/src/components/qualityControls/__tests__/__snapshots__/NewDraftQualityControl.spec.js.snap +510 -483
  39. package/src/components/qualityControls/__tests__/__snapshots__/NewQualityControl.spec.js.snap +261 -245
  40. package/src/components/qualityControls/__tests__/__snapshots__/QualityControl.spec.js.snap +11 -8
  41. package/src/components/qualityControls/__tests__/__snapshots__/QualityControlCrumbs.spec.js.snap +1 -1
  42. package/src/components/qualityControls/__tests__/__snapshots__/QualityControlHeader.spec.js.snap +1 -1
  43. package/src/components/qualityControls/__tests__/__snapshots__/QualityControls.spec.js.snap +87 -87
  44. package/src/components/qualityControls/__tests__/__snapshots__/QualityControlsLabelResults.spec.js.snap +6 -2
  45. package/src/hooks/useDataViews.js +1 -1
  46. package/src/styles/Expression.less +25 -1
@@ -0,0 +1,820 @@
1
+ import { render, waitForLoad } from "@truedat/test/render";
2
+ import DataViewSummary from "../DataViewSummary";
3
+
4
+ const messages = {
5
+ "dataViews.form.queryable.from": "FROM",
6
+ "dataViews.form.queryable.join": "JOIN",
7
+ "dataViews.form.queryable.where": "WHERE",
8
+ "dataViews.form.queryable.having": "HAVING",
9
+ "dataViews.form.queryable.group_by": "GROUP BY",
10
+ "dataViews.form.queryable.select": "SELECT",
11
+ "queryables.resource.selector.data_structure": "Data Structure",
12
+ "queryables.resource.selector.data_view": "Data View",
13
+ "queryables.resource.selector.reference_dataset": "Reference Dataset",
14
+ "queryables.group_by.form.group_fields": "Group Fields",
15
+ "queryables.group_by.form.aggregate_fields": "Aggregate Fields",
16
+ "dataViews.summary.field.unnamed": "(unnamed)",
17
+ "dataViews.summary.group_by.empty": "No group by fields",
18
+ "dataViews.summary.where.empty": "No conditions",
19
+ "joinType.inner": "Inner Join",
20
+ "joinType.left": "Left Join",
21
+ "joinType.right": "Right Join",
22
+ "joinType.full_outer": "Full Outer Join",
23
+ };
24
+
25
+ const renderOpts = { messages };
26
+
27
+ const createDataView = (queryables = [], select = null) => ({
28
+ name: "Test Data View",
29
+ queryables,
30
+ select,
31
+ });
32
+
33
+ describe("<DataViewSummary />", () => {
34
+ it("returns null when data view has no valid structure", async () => {
35
+ const dataView = createDataView([]);
36
+ const rendered = render(
37
+ <DataViewSummary dataView={dataView} />,
38
+ renderOpts
39
+ );
40
+ await waitForLoad(rendered);
41
+ expect(rendered.container).toBeEmptyDOMElement();
42
+ });
43
+
44
+ it("returns null when data view is null", async () => {
45
+ const rendered = render(<DataViewSummary dataView={null} />, renderOpts);
46
+ await waitForLoad(rendered);
47
+ expect(rendered.container).toBeEmptyDOMElement();
48
+ });
49
+
50
+ it("matches snapshot for simple FROM only", async () => {
51
+ const dataView = createDataView([
52
+ {
53
+ id: 0,
54
+ type: "from",
55
+ alias: "users",
56
+ properties: {
57
+ resource: {
58
+ id: 100,
59
+ type: "data_structure",
60
+ embedded: {
61
+ name: "USERS_TABLE",
62
+ },
63
+ },
64
+ },
65
+ },
66
+ ]);
67
+
68
+ const rendered = render(
69
+ <DataViewSummary dataView={dataView} />,
70
+ renderOpts
71
+ );
72
+ await waitForLoad(rendered);
73
+ expect(rendered.container).toMatchSnapshot();
74
+ });
75
+
76
+ it("matches snapshot for FROM with JOIN", async () => {
77
+ const dataView = createDataView([
78
+ {
79
+ id: 0,
80
+ type: "from",
81
+ alias: "users",
82
+ properties: {
83
+ resource: {
84
+ id: 100,
85
+ type: "data_structure",
86
+ embedded: {
87
+ name: "USERS_TABLE",
88
+ },
89
+ },
90
+ },
91
+ },
92
+ {
93
+ id: 1,
94
+ type: "join",
95
+ alias: "orders",
96
+ properties: {
97
+ type: "left",
98
+ resource: {
99
+ id: 101,
100
+ type: "data_structure",
101
+ embedded: {
102
+ name: "ORDERS_TABLE",
103
+ },
104
+ },
105
+ clauses: [
106
+ {
107
+ expressions: [
108
+ {
109
+ shape: "function",
110
+ value: {
111
+ name: "eq",
112
+ type: "boolean",
113
+ args: {
114
+ arg1: {
115
+ shape: "field",
116
+ value: {
117
+ id: 1,
118
+ name: "user_id",
119
+ type: "number",
120
+ parent_id: 0,
121
+ },
122
+ },
123
+ arg2: {
124
+ shape: "field",
125
+ value: {
126
+ id: 2,
127
+ name: "user_id",
128
+ type: "number",
129
+ parent_id: 1,
130
+ },
131
+ },
132
+ },
133
+ },
134
+ },
135
+ ],
136
+ },
137
+ ],
138
+ },
139
+ },
140
+ ]);
141
+
142
+ const rendered = render(
143
+ <DataViewSummary dataView={dataView} />,
144
+ renderOpts
145
+ );
146
+ await waitForLoad(rendered);
147
+ expect(rendered.container).toMatchSnapshot();
148
+ });
149
+
150
+ it("matches snapshot for FROM with WHERE clause", async () => {
151
+ const dataView = createDataView([
152
+ {
153
+ id: 0,
154
+ type: "from",
155
+ alias: "users",
156
+ properties: {
157
+ resource: {
158
+ id: 100,
159
+ type: "data_structure",
160
+ embedded: {
161
+ name: "USERS_TABLE",
162
+ },
163
+ },
164
+ },
165
+ },
166
+ {
167
+ id: 1,
168
+ type: "where",
169
+ properties: {
170
+ clauses: [
171
+ {
172
+ expressions: [
173
+ {
174
+ shape: "function",
175
+ value: {
176
+ name: "gt",
177
+ type: "boolean",
178
+ args: {
179
+ arg1: {
180
+ shape: "field",
181
+ value: {
182
+ id: 1,
183
+ name: "age",
184
+ type: "number",
185
+ parent_id: 0,
186
+ },
187
+ },
188
+ arg2: {
189
+ shape: "constant",
190
+ value: {
191
+ value: 18,
192
+ type: "number",
193
+ },
194
+ },
195
+ },
196
+ },
197
+ },
198
+ ],
199
+ },
200
+ ],
201
+ },
202
+ },
203
+ ]);
204
+
205
+ const rendered = render(
206
+ <DataViewSummary dataView={dataView} />,
207
+ renderOpts
208
+ );
209
+ await waitForLoad(rendered);
210
+ expect(rendered.container).toMatchSnapshot();
211
+ });
212
+
213
+ it("matches snapshot for FROM with GROUP BY", async () => {
214
+ const dataView = createDataView([
215
+ {
216
+ id: 0,
217
+ type: "from",
218
+ alias: "sales",
219
+ properties: {
220
+ resource: {
221
+ id: 100,
222
+ type: "data_structure",
223
+ embedded: {
224
+ name: "SALES_TABLE",
225
+ },
226
+ },
227
+ },
228
+ },
229
+ {
230
+ id: 1,
231
+ type: "group_by",
232
+ alias: "",
233
+ properties: {
234
+ group_fields: [
235
+ {
236
+ id: 0,
237
+ alias: "category",
238
+ expression: {
239
+ shape: "field",
240
+ value: {
241
+ id: 1,
242
+ name: "category",
243
+ type: "string",
244
+ parent_id: 0,
245
+ },
246
+ },
247
+ },
248
+ ],
249
+ aggregate_fields: [
250
+ {
251
+ id: 1,
252
+ alias: "total_sales",
253
+ expression: {
254
+ shape: "function",
255
+ value: {
256
+ name: "sum",
257
+ type: "number",
258
+ args: {
259
+ arg1: {
260
+ shape: "field",
261
+ value: {
262
+ id: 2,
263
+ name: "amount",
264
+ type: "number",
265
+ parent_id: 0,
266
+ },
267
+ },
268
+ },
269
+ },
270
+ },
271
+ },
272
+ ],
273
+ },
274
+ },
275
+ ]);
276
+
277
+ const rendered = render(
278
+ <DataViewSummary dataView={dataView} />,
279
+ renderOpts
280
+ );
281
+ await waitForLoad(rendered);
282
+ expect(rendered.container).toMatchSnapshot();
283
+ });
284
+
285
+ it("matches snapshot for complete data view with all queryable types", async () => {
286
+ const dataView = createDataView(
287
+ [
288
+ {
289
+ id: 0,
290
+ type: "from",
291
+ alias: "users",
292
+ properties: {
293
+ resource: {
294
+ id: 100,
295
+ type: "data_structure",
296
+ embedded: {
297
+ name: "USERS_TABLE",
298
+ },
299
+ },
300
+ },
301
+ },
302
+ {
303
+ id: 1,
304
+ type: "join",
305
+ alias: "orders",
306
+ properties: {
307
+ type: "inner",
308
+ resource: {
309
+ id: 101,
310
+ type: "data_structure",
311
+ embedded: {
312
+ name: "ORDERS_TABLE",
313
+ },
314
+ },
315
+ clauses: [
316
+ {
317
+ expressions: [
318
+ {
319
+ shape: "function",
320
+ value: {
321
+ name: "eq",
322
+ type: "boolean",
323
+ args: {
324
+ arg1: {
325
+ shape: "field",
326
+ value: {
327
+ id: 1,
328
+ name: "user_id",
329
+ type: "number",
330
+ parent_id: 0,
331
+ },
332
+ },
333
+ arg2: {
334
+ shape: "field",
335
+ value: {
336
+ id: 2,
337
+ name: "user_id",
338
+ type: "number",
339
+ parent_id: 1,
340
+ },
341
+ },
342
+ },
343
+ },
344
+ },
345
+ ],
346
+ },
347
+ ],
348
+ },
349
+ },
350
+ {
351
+ id: 2,
352
+ type: "where",
353
+ properties: {
354
+ clauses: [
355
+ {
356
+ expressions: [
357
+ {
358
+ shape: "function",
359
+ value: {
360
+ name: "gt",
361
+ type: "boolean",
362
+ args: {
363
+ arg1: {
364
+ shape: "field",
365
+ value: {
366
+ id: 3,
367
+ name: "total",
368
+ type: "number",
369
+ parent_id: 1,
370
+ },
371
+ },
372
+ arg2: {
373
+ shape: "constant",
374
+ value: {
375
+ value: 100,
376
+ type: "number",
377
+ },
378
+ },
379
+ },
380
+ },
381
+ },
382
+ ],
383
+ },
384
+ ],
385
+ },
386
+ },
387
+ {
388
+ id: 3,
389
+ type: "group_by",
390
+ alias: "",
391
+ properties: {
392
+ group_fields: [
393
+ {
394
+ id: 0,
395
+ alias: "user_name",
396
+ expression: {
397
+ shape: "field",
398
+ value: {
399
+ id: 4,
400
+ name: "name",
401
+ type: "string",
402
+ parent_id: 0,
403
+ },
404
+ },
405
+ },
406
+ ],
407
+ aggregate_fields: [
408
+ {
409
+ id: 1,
410
+ alias: "order_count",
411
+ expression: {
412
+ shape: "function",
413
+ value: {
414
+ name: "count",
415
+ type: "number",
416
+ },
417
+ },
418
+ },
419
+ ],
420
+ },
421
+ },
422
+ ],
423
+ {
424
+ type: "select",
425
+ properties: {
426
+ fields: [
427
+ {
428
+ id: 0,
429
+ alias: "user_name",
430
+ expression: {
431
+ shape: "field",
432
+ value: {
433
+ id: 4,
434
+ name: "name",
435
+ type: "string",
436
+ parent_id: 0,
437
+ },
438
+ },
439
+ },
440
+ {
441
+ id: 1,
442
+ alias: "total_orders",
443
+ expression: {
444
+ shape: "field",
445
+ value: {
446
+ id: 1,
447
+ name: "order_count",
448
+ type: "number",
449
+ parent_id: 3,
450
+ },
451
+ },
452
+ },
453
+ ],
454
+ },
455
+ }
456
+ );
457
+
458
+ const rendered = render(
459
+ <DataViewSummary dataView={dataView} />,
460
+ renderOpts
461
+ );
462
+ await waitForLoad(rendered);
463
+ expect(rendered.container).toMatchSnapshot();
464
+ });
465
+
466
+ it("matches snapshot with HAVING clause (where after group_by)", async () => {
467
+ const dataView = createDataView([
468
+ {
469
+ id: 0,
470
+ type: "from",
471
+ alias: "sales",
472
+ properties: {
473
+ resource: {
474
+ id: 100,
475
+ type: "data_structure",
476
+ embedded: {
477
+ name: "SALES_TABLE",
478
+ },
479
+ },
480
+ },
481
+ },
482
+ {
483
+ id: 1,
484
+ type: "group_by",
485
+ alias: "",
486
+ properties: {
487
+ group_fields: [
488
+ {
489
+ id: 0,
490
+ alias: "category",
491
+ expression: {
492
+ shape: "field",
493
+ value: {
494
+ id: 1,
495
+ name: "category",
496
+ type: "string",
497
+ parent_id: 0,
498
+ },
499
+ },
500
+ },
501
+ ],
502
+ aggregate_fields: [
503
+ {
504
+ id: 1,
505
+ alias: "total",
506
+ expression: {
507
+ shape: "function",
508
+ value: {
509
+ name: "sum",
510
+ type: "number",
511
+ args: {
512
+ arg1: {
513
+ shape: "field",
514
+ value: {
515
+ id: 2,
516
+ name: "amount",
517
+ type: "number",
518
+ parent_id: 0,
519
+ },
520
+ },
521
+ },
522
+ },
523
+ },
524
+ },
525
+ ],
526
+ },
527
+ },
528
+ {
529
+ id: 2,
530
+ type: "where",
531
+ properties: {
532
+ clauses: [
533
+ {
534
+ expressions: [
535
+ {
536
+ shape: "function",
537
+ value: {
538
+ name: "gt",
539
+ type: "boolean",
540
+ args: {
541
+ arg1: {
542
+ shape: "field",
543
+ value: {
544
+ id: 3,
545
+ name: "total",
546
+ type: "number",
547
+ parent_id: 1,
548
+ },
549
+ },
550
+ arg2: {
551
+ shape: "constant",
552
+ value: {
553
+ value: 1000,
554
+ type: "number",
555
+ },
556
+ },
557
+ },
558
+ },
559
+ },
560
+ ],
561
+ },
562
+ ],
563
+ },
564
+ },
565
+ ]);
566
+
567
+ const rendered = render(
568
+ <DataViewSummary dataView={dataView} />,
569
+ renderOpts
570
+ );
571
+ await waitForLoad(rendered);
572
+ expect(rendered.container).toMatchSnapshot();
573
+ });
574
+
575
+ it("matches snapshot for data view without alias", async () => {
576
+ const dataView = createDataView([
577
+ {
578
+ id: 0,
579
+ type: "from",
580
+ alias: "",
581
+ properties: {
582
+ resource: {
583
+ id: 100,
584
+ type: "data_structure",
585
+ embedded: {
586
+ name: "USERS_TABLE",
587
+ },
588
+ },
589
+ },
590
+ },
591
+ ]);
592
+
593
+ const rendered = render(
594
+ <DataViewSummary dataView={dataView} />,
595
+ renderOpts
596
+ );
597
+ await waitForLoad(rendered);
598
+ expect(rendered.container).toMatchSnapshot();
599
+ });
600
+
601
+ it("matches snapshot with reference dataset resource", async () => {
602
+ const dataView = createDataView([
603
+ {
604
+ id: 0,
605
+ type: "from",
606
+ alias: "countries",
607
+ properties: {
608
+ resource: {
609
+ id: 200,
610
+ type: "reference_dataset",
611
+ embedded: {
612
+ name: "COUNTRIES",
613
+ },
614
+ },
615
+ },
616
+ },
617
+ ]);
618
+
619
+ const rendered = render(
620
+ <DataViewSummary dataView={dataView} />,
621
+ renderOpts
622
+ );
623
+ await waitForLoad(rendered);
624
+ expect(rendered.container).toMatchSnapshot();
625
+ });
626
+
627
+ it("matches snapshot with data_view resource", async () => {
628
+ const dataView = createDataView([
629
+ {
630
+ id: 0,
631
+ type: "from",
632
+ alias: "base_view",
633
+ properties: {
634
+ resource: {
635
+ id: 300,
636
+ type: "data_view",
637
+ embedded: {
638
+ name: "BASE_DATA_VIEW",
639
+ },
640
+ },
641
+ },
642
+ },
643
+ ]);
644
+
645
+ const rendered = render(
646
+ <DataViewSummary dataView={dataView} />,
647
+ renderOpts
648
+ );
649
+ await waitForLoad(rendered);
650
+ expect(rendered.container).toMatchSnapshot();
651
+ });
652
+
653
+ it("matches snapshot with select in dataView.select", async () => {
654
+ const dataView = createDataView(
655
+ [
656
+ {
657
+ id: 0,
658
+ type: "from",
659
+ alias: "users",
660
+ properties: {
661
+ resource: {
662
+ id: 100,
663
+ type: "data_structure",
664
+ embedded: {
665
+ name: "USERS_TABLE",
666
+ },
667
+ },
668
+ },
669
+ },
670
+ ],
671
+ {
672
+ type: "select",
673
+ properties: {
674
+ fields: [
675
+ {
676
+ id: 0,
677
+ alias: "user_name",
678
+ expression: {
679
+ shape: "field",
680
+ value: {
681
+ id: 1,
682
+ name: "name",
683
+ type: "string",
684
+ parent_id: 0,
685
+ },
686
+ },
687
+ },
688
+ {
689
+ id: 1,
690
+ alias: "user_email",
691
+ expression: {
692
+ shape: "field",
693
+ value: {
694
+ id: 2,
695
+ name: "email",
696
+ type: "string",
697
+ parent_id: 0,
698
+ },
699
+ },
700
+ },
701
+ ],
702
+ },
703
+ }
704
+ );
705
+
706
+ const rendered = render(
707
+ <DataViewSummary dataView={dataView} />,
708
+ renderOpts
709
+ );
710
+ await waitForLoad(rendered);
711
+ expect(rendered.container).toMatchSnapshot();
712
+ });
713
+
714
+ it("matches snapshot with multiple joins", async () => {
715
+ const dataView = createDataView([
716
+ {
717
+ id: 0,
718
+ type: "from",
719
+ alias: "users",
720
+ properties: {
721
+ resource: {
722
+ id: 100,
723
+ type: "data_structure",
724
+ embedded: {
725
+ name: "USERS_TABLE",
726
+ },
727
+ },
728
+ },
729
+ },
730
+ {
731
+ id: 1,
732
+ type: "join",
733
+ alias: "orders",
734
+ properties: {
735
+ type: "inner",
736
+ resource: {
737
+ id: 101,
738
+ type: "data_structure",
739
+ embedded: {
740
+ name: "ORDERS_TABLE",
741
+ },
742
+ },
743
+ clauses: [],
744
+ },
745
+ },
746
+ {
747
+ id: 2,
748
+ type: "join",
749
+ alias: "products",
750
+ properties: {
751
+ type: "left",
752
+ resource: {
753
+ id: 102,
754
+ type: "data_structure",
755
+ embedded: {
756
+ name: "PRODUCTS_TABLE",
757
+ },
758
+ },
759
+ clauses: [],
760
+ },
761
+ },
762
+ ]);
763
+
764
+ const rendered = render(
765
+ <DataViewSummary dataView={dataView} />,
766
+ renderOpts
767
+ );
768
+ await waitForLoad(rendered);
769
+ expect(rendered.container).toMatchSnapshot();
770
+ });
771
+
772
+ it("matches snapshot for fields without alias", async () => {
773
+ const dataView = createDataView([
774
+ {
775
+ id: 0,
776
+ type: "from",
777
+ alias: "users",
778
+ properties: {
779
+ resource: {
780
+ id: 100,
781
+ type: "data_structure",
782
+ embedded: {
783
+ name: "USERS_TABLE",
784
+ },
785
+ },
786
+ },
787
+ },
788
+ {
789
+ id: 1,
790
+ type: "group_by",
791
+ alias: "",
792
+ properties: {
793
+ group_fields: [
794
+ {
795
+ id: 0,
796
+ alias: "", // Empty alias
797
+ expression: {
798
+ shape: "field",
799
+ value: {
800
+ id: 1,
801
+ name: "category",
802
+ type: "string",
803
+ parent_id: 0,
804
+ },
805
+ },
806
+ },
807
+ ],
808
+ aggregate_fields: [],
809
+ },
810
+ },
811
+ ]);
812
+
813
+ const rendered = render(
814
+ <DataViewSummary dataView={dataView} />,
815
+ renderOpts
816
+ );
817
+ await waitForLoad(rendered);
818
+ expect(rendered.container).toMatchSnapshot();
819
+ });
820
+ });