datajunction-ui 0.0.98 → 0.0.100
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/pages/QueryPlannerPage/ResultsView.jsx +55 -5
- package/src/app/pages/QueryPlannerPage/SelectionPanel.jsx +676 -356
- package/src/app/pages/QueryPlannerPage/__tests__/ResultsView.test.jsx +151 -0
- package/src/app/pages/QueryPlannerPage/__tests__/SelectionPanel.test.jsx +9 -9
- package/src/app/pages/QueryPlannerPage/__tests__/index.test.jsx +101 -3
- package/src/app/pages/QueryPlannerPage/index.jsx +118 -11
- package/src/app/pages/QueryPlannerPage/styles.css +232 -14
- package/src/app/pages/Root/__tests__/index.test.jsx +1 -1
- package/src/app/pages/Root/index.tsx +1 -1
- package/src/app/services/DJService.js +27 -0
|
@@ -45,13 +45,14 @@
|
|
|
45
45
|
|
|
46
46
|
/* Full page layout */
|
|
47
47
|
.planner-page {
|
|
48
|
-
height: 100vh;
|
|
48
|
+
height: calc(100vh - 90px);
|
|
49
49
|
display: flex;
|
|
50
50
|
flex-direction: column;
|
|
51
51
|
background: var(--planner-bg);
|
|
52
52
|
color: var(--planner-text);
|
|
53
53
|
font-family: var(--font-body);
|
|
54
54
|
overflow: hidden;
|
|
55
|
+
border-top: 1px solid #eee;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
/* Header */
|
|
@@ -89,6 +90,14 @@
|
|
|
89
90
|
font-size: 13px;
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
.planner-error-banner {
|
|
94
|
+
flex-shrink: 0;
|
|
95
|
+
border-radius: 0;
|
|
96
|
+
border-left: none;
|
|
97
|
+
border-right: none;
|
|
98
|
+
border-top: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
/* Materialization Error Banner */
|
|
93
102
|
.materialization-error {
|
|
94
103
|
display: flex;
|
|
@@ -374,16 +383,17 @@
|
|
|
374
383
|
.planner-layout {
|
|
375
384
|
display: flex;
|
|
376
385
|
flex: 1;
|
|
386
|
+
min-height: 0;
|
|
377
387
|
overflow: hidden;
|
|
378
388
|
}
|
|
379
389
|
|
|
380
390
|
/* Left: Selection Panel */
|
|
381
391
|
.planner-selection {
|
|
382
392
|
width: 20%;
|
|
383
|
-
|
|
393
|
+
min-width: 200px;
|
|
394
|
+
min-height: 0;
|
|
384
395
|
background: var(--planner-surface);
|
|
385
|
-
|
|
386
|
-
overflow: visible; /* Allow cube dropdown to overflow */
|
|
396
|
+
overflow: hidden;
|
|
387
397
|
display: flex;
|
|
388
398
|
flex-direction: column;
|
|
389
399
|
}
|
|
@@ -464,12 +474,37 @@
|
|
|
464
474
|
max-width: 300px;
|
|
465
475
|
}
|
|
466
476
|
|
|
477
|
+
/* Vertical resizer between graph and details panels */
|
|
478
|
+
.vertical-resizer {
|
|
479
|
+
width: 1px;
|
|
480
|
+
background: var(--planner-border);
|
|
481
|
+
cursor: col-resize;
|
|
482
|
+
flex-shrink: 0;
|
|
483
|
+
position: relative;
|
|
484
|
+
z-index: 1;
|
|
485
|
+
transition: background 0.15s;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/* Wider invisible hit area */
|
|
489
|
+
.vertical-resizer::after {
|
|
490
|
+
content: '';
|
|
491
|
+
position: absolute;
|
|
492
|
+
top: 0;
|
|
493
|
+
bottom: 0;
|
|
494
|
+
left: -4px;
|
|
495
|
+
right: -4px;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.vertical-resizer:hover,
|
|
499
|
+
.vertical-resizer:active {
|
|
500
|
+
background: var(--accent-primary);
|
|
501
|
+
}
|
|
502
|
+
|
|
467
503
|
/* Right: Details Panel */
|
|
468
504
|
.planner-details {
|
|
469
505
|
width: 40%;
|
|
470
|
-
min-width:
|
|
506
|
+
min-width: 280px;
|
|
471
507
|
background: var(--planner-surface);
|
|
472
|
-
border-left: 1px solid var(--planner-border);
|
|
473
508
|
overflow-y: auto;
|
|
474
509
|
}
|
|
475
510
|
|
|
@@ -480,8 +515,17 @@
|
|
|
480
515
|
.selection-panel {
|
|
481
516
|
display: flex;
|
|
482
517
|
flex-direction: column;
|
|
483
|
-
|
|
484
|
-
|
|
518
|
+
flex: 1;
|
|
519
|
+
min-height: 0;
|
|
520
|
+
overflow: hidden;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.resizable-sections {
|
|
524
|
+
display: flex;
|
|
525
|
+
flex-direction: column;
|
|
526
|
+
flex: 1;
|
|
527
|
+
min-height: 0;
|
|
528
|
+
overflow: hidden;
|
|
485
529
|
}
|
|
486
530
|
|
|
487
531
|
/* Cube Preset Section */
|
|
@@ -850,6 +894,20 @@
|
|
|
850
894
|
accent-color: var(--accent-primary);
|
|
851
895
|
}
|
|
852
896
|
|
|
897
|
+
/* Incompatible metric (dims selected, this metric doesn't support them) */
|
|
898
|
+
.selection-item.metric-incompatible {
|
|
899
|
+
opacity: 0.35;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/* Compatible badge shown next to metrics that match selected dims */
|
|
903
|
+
.metric-compatible-badge {
|
|
904
|
+
margin-left: auto;
|
|
905
|
+
font-size: 11px;
|
|
906
|
+
color: var(--accent-success);
|
|
907
|
+
font-weight: 600;
|
|
908
|
+
flex-shrink: 0;
|
|
909
|
+
}
|
|
910
|
+
|
|
853
911
|
.item-name {
|
|
854
912
|
font-size: 13px;
|
|
855
913
|
color: var(--planner-text);
|
|
@@ -879,6 +937,115 @@
|
|
|
879
937
|
font-family: var(--font-display);
|
|
880
938
|
}
|
|
881
939
|
|
|
940
|
+
/* Dimension group (node-level header + items) */
|
|
941
|
+
.dim-group {
|
|
942
|
+
margin-bottom: 4px;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
.dim-group-header {
|
|
946
|
+
display: flex;
|
|
947
|
+
align-items: center;
|
|
948
|
+
gap: 8px;
|
|
949
|
+
padding: 8px 12px;
|
|
950
|
+
cursor: pointer;
|
|
951
|
+
user-select: none;
|
|
952
|
+
transition: background 0.15s;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
.dim-group-header:hover {
|
|
956
|
+
background: var(--planner-surface-hover);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.dim-group-name {
|
|
960
|
+
flex: 1;
|
|
961
|
+
font-size: 12px;
|
|
962
|
+
font-weight: 600;
|
|
963
|
+
color: var(--planner-text);
|
|
964
|
+
font-family: var(--font-display);
|
|
965
|
+
overflow: hidden;
|
|
966
|
+
text-overflow: ellipsis;
|
|
967
|
+
white-space: nowrap;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
.dim-group-meta {
|
|
971
|
+
font-size: 10px;
|
|
972
|
+
font-weight: 400;
|
|
973
|
+
color: var(--planner-text-muted);
|
|
974
|
+
background: var(--planner-bg-subtle, rgba(0, 0, 0, 0.06));
|
|
975
|
+
padding: 1px 5px;
|
|
976
|
+
border-radius: 8px;
|
|
977
|
+
white-space: nowrap;
|
|
978
|
+
flex-shrink: 0;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.dim-group-count {
|
|
982
|
+
font-size: 11px;
|
|
983
|
+
color: var(--planner-text-dim);
|
|
984
|
+
flex-shrink: 0;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
.dim-group-item {
|
|
988
|
+
padding-left: 28px;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/* Role path sub-group (second level) */
|
|
992
|
+
.dim-role-group {
|
|
993
|
+
padding-left: 20px;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.dim-role-header {
|
|
997
|
+
display: flex;
|
|
998
|
+
align-items: center;
|
|
999
|
+
gap: 8px;
|
|
1000
|
+
padding: 5px 12px;
|
|
1001
|
+
cursor: pointer;
|
|
1002
|
+
user-select: none;
|
|
1003
|
+
transition: background 0.15s;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.dim-role-header:hover {
|
|
1007
|
+
background: var(--planner-surface-hover);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.dim-role-label {
|
|
1011
|
+
flex: 1;
|
|
1012
|
+
font-size: 11px;
|
|
1013
|
+
color: var(--planner-text-muted);
|
|
1014
|
+
font-family: var(--font-display);
|
|
1015
|
+
white-space: nowrap;
|
|
1016
|
+
overflow: hidden;
|
|
1017
|
+
text-overflow: ellipsis;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.dim-role-item {
|
|
1021
|
+
padding-left: 22px;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
.dim-filter-btn {
|
|
1025
|
+
opacity: 0;
|
|
1026
|
+
pointer-events: none;
|
|
1027
|
+
margin-left: auto;
|
|
1028
|
+
align-self: center;
|
|
1029
|
+
flex-shrink: 0;
|
|
1030
|
+
background: none;
|
|
1031
|
+
border: none;
|
|
1032
|
+
color: var(--planner-text-dim);
|
|
1033
|
+
font-size: 10px;
|
|
1034
|
+
font-family: var(--font-display);
|
|
1035
|
+
padding: 0 2px;
|
|
1036
|
+
cursor: pointer;
|
|
1037
|
+
transition: opacity 0.1s, color 0.1s;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
.dim-role-item:hover .dim-filter-btn {
|
|
1041
|
+
opacity: 1;
|
|
1042
|
+
pointer-events: auto;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.dim-filter-btn:hover {
|
|
1046
|
+
color: var(--accent-dimension);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
882
1049
|
/* Search result items (flat list) */
|
|
883
1050
|
.search-result-item {
|
|
884
1051
|
padding: 8px 12px;
|
|
@@ -903,6 +1070,19 @@
|
|
|
903
1070
|
flex-shrink: 0;
|
|
904
1071
|
}
|
|
905
1072
|
|
|
1073
|
+
.section-divider.draggable-divider {
|
|
1074
|
+
height: 5px;
|
|
1075
|
+
cursor: row-resize;
|
|
1076
|
+
background: var(--planner-border);
|
|
1077
|
+
transition: background 0.15s;
|
|
1078
|
+
position: relative;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.section-divider.draggable-divider:hover,
|
|
1082
|
+
.section-divider.draggable-divider:active {
|
|
1083
|
+
background: var(--accent-primary);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
906
1086
|
.empty-list {
|
|
907
1087
|
padding: 24px 16px;
|
|
908
1088
|
text-align: center;
|
|
@@ -3406,6 +3586,13 @@ a.action-btn {
|
|
|
3406
3586
|
font-family: var(--font-display);
|
|
3407
3587
|
transition: all 0.12s ease;
|
|
3408
3588
|
white-space: nowrap;
|
|
3589
|
+
max-width: 260px;
|
|
3590
|
+
}
|
|
3591
|
+
|
|
3592
|
+
.selected-chip .chip-label {
|
|
3593
|
+
overflow: hidden;
|
|
3594
|
+
text-overflow: ellipsis;
|
|
3595
|
+
white-space: nowrap;
|
|
3409
3596
|
}
|
|
3410
3597
|
|
|
3411
3598
|
/* Metrics: Pink (matches node_type__metric background #fad7dd) */
|
|
@@ -3469,9 +3656,8 @@ a.action-btn {
|
|
|
3469
3656
|
================================= */
|
|
3470
3657
|
|
|
3471
3658
|
.filters-section {
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
overflow: visible !important;
|
|
3659
|
+
min-height: 0;
|
|
3660
|
+
overflow-y: auto;
|
|
3475
3661
|
}
|
|
3476
3662
|
|
|
3477
3663
|
.filter-chips-container {
|
|
@@ -3577,6 +3763,14 @@ a.action-btn {
|
|
|
3577
3763
|
Engine Selection
|
|
3578
3764
|
================================= */
|
|
3579
3765
|
|
|
3766
|
+
.engine-run-section {
|
|
3767
|
+
display: flex;
|
|
3768
|
+
flex-direction: column;
|
|
3769
|
+
overflow: hidden;
|
|
3770
|
+
min-height: 0;
|
|
3771
|
+
flex-shrink: 0;
|
|
3772
|
+
}
|
|
3773
|
+
|
|
3580
3774
|
.engine-section {
|
|
3581
3775
|
display: flex;
|
|
3582
3776
|
align-items: center;
|
|
@@ -3628,7 +3822,6 @@ a.action-btn {
|
|
|
3628
3822
|
|
|
3629
3823
|
.run-query-section {
|
|
3630
3824
|
padding: 16px 12px;
|
|
3631
|
-
border-top: 1px solid var(--planner-border);
|
|
3632
3825
|
background: var(--planner-bg);
|
|
3633
3826
|
flex-shrink: 0;
|
|
3634
3827
|
}
|
|
@@ -3772,12 +3965,37 @@ a.action-btn {
|
|
|
3772
3965
|
flex: 0 0 33.333%;
|
|
3773
3966
|
display: flex;
|
|
3774
3967
|
flex-direction: column;
|
|
3775
|
-
border-bottom: 2px solid var(--planner-border);
|
|
3776
3968
|
background: var(--planner-surface);
|
|
3777
|
-
min-height:
|
|
3969
|
+
min-height: 80px;
|
|
3778
3970
|
max-height: 33.333%;
|
|
3779
3971
|
}
|
|
3780
3972
|
|
|
3973
|
+
/* Horizontal resizer between SQL pane and results pane */
|
|
3974
|
+
.horizontal-resizer {
|
|
3975
|
+
height: 1px;
|
|
3976
|
+
background: var(--planner-border);
|
|
3977
|
+
cursor: row-resize;
|
|
3978
|
+
flex-shrink: 0;
|
|
3979
|
+
position: relative;
|
|
3980
|
+
z-index: 1;
|
|
3981
|
+
transition: background 0.15s;
|
|
3982
|
+
}
|
|
3983
|
+
|
|
3984
|
+
/* Wider invisible hit area */
|
|
3985
|
+
.horizontal-resizer::after {
|
|
3986
|
+
content: '';
|
|
3987
|
+
position: absolute;
|
|
3988
|
+
left: 0;
|
|
3989
|
+
right: 0;
|
|
3990
|
+
top: -4px;
|
|
3991
|
+
bottom: -4px;
|
|
3992
|
+
}
|
|
3993
|
+
|
|
3994
|
+
.horizontal-resizer:hover,
|
|
3995
|
+
.horizontal-resizer:active {
|
|
3996
|
+
background: var(--accent-primary);
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3781
3999
|
.sql-pane-header {
|
|
3782
4000
|
display: flex;
|
|
3783
4001
|
align-items: center;
|
|
@@ -43,7 +43,7 @@ describe('<Root />', () => {
|
|
|
43
43
|
|
|
44
44
|
// Check navigation links exist
|
|
45
45
|
expect(screen.getAllByText('Catalog')).toHaveLength(1);
|
|
46
|
-
expect(screen.getAllByText('
|
|
46
|
+
expect(screen.getAllByText('Explorer')).toHaveLength(1);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it('renders Docs dropdown', async () => {
|
|
@@ -1053,6 +1053,33 @@ export const DataJunctionAPI = {
|
|
|
1053
1053
|
).json();
|
|
1054
1054
|
},
|
|
1055
1055
|
|
|
1056
|
+
commonMetrics: async function (dimensions) {
|
|
1057
|
+
// Dimension names are "node.attribute[role]" — strip role path and attribute to get node name
|
|
1058
|
+
const stripped = [
|
|
1059
|
+
...new Set(
|
|
1060
|
+
dimensions
|
|
1061
|
+
.map(d =>
|
|
1062
|
+
d
|
|
1063
|
+
.replace(/\[[^\]]*\]$/, '')
|
|
1064
|
+
.split('.')
|
|
1065
|
+
.slice(0, -1)
|
|
1066
|
+
.join('.'),
|
|
1067
|
+
)
|
|
1068
|
+
.filter(Boolean),
|
|
1069
|
+
),
|
|
1070
|
+
];
|
|
1071
|
+
if (stripped.length === 0) return [];
|
|
1072
|
+
const dimsQuery =
|
|
1073
|
+
'?' +
|
|
1074
|
+
stripped.map(d => `dimension=${encodeURIComponent(d)}`).join('&') +
|
|
1075
|
+
'&node_type=metric';
|
|
1076
|
+
return await (
|
|
1077
|
+
await fetch(`${DJ_URL}/dimensions/common/${dimsQuery}`, {
|
|
1078
|
+
credentials: 'include',
|
|
1079
|
+
})
|
|
1080
|
+
).json();
|
|
1081
|
+
},
|
|
1082
|
+
|
|
1056
1083
|
history: async function (type, name, offset, limit) {
|
|
1057
1084
|
return await (
|
|
1058
1085
|
await fetch(
|