datajunction-ui 0.0.23 → 0.0.26

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 (25) hide show
  1. package/package.json +11 -4
  2. package/src/app/index.tsx +6 -0
  3. package/src/app/pages/NamespacePage/CompactSelect.jsx +100 -0
  4. package/src/app/pages/NamespacePage/NodeModeSelect.jsx +8 -5
  5. package/src/app/pages/NamespacePage/__tests__/CompactSelect.test.jsx +190 -0
  6. package/src/app/pages/NamespacePage/__tests__/index.test.jsx +297 -8
  7. package/src/app/pages/NamespacePage/index.jsx +489 -62
  8. package/src/app/pages/QueryPlannerPage/Loadable.jsx +6 -0
  9. package/src/app/pages/QueryPlannerPage/MetricFlowGraph.jsx +311 -0
  10. package/src/app/pages/QueryPlannerPage/PreAggDetailsPanel.jsx +470 -0
  11. package/src/app/pages/QueryPlannerPage/SelectionPanel.jsx +384 -0
  12. package/src/app/pages/QueryPlannerPage/__tests__/MetricFlowGraph.test.jsx +239 -0
  13. package/src/app/pages/QueryPlannerPage/__tests__/PreAggDetailsPanel.test.jsx +638 -0
  14. package/src/app/pages/QueryPlannerPage/__tests__/SelectionPanel.test.jsx +429 -0
  15. package/src/app/pages/QueryPlannerPage/__tests__/index.test.jsx +317 -0
  16. package/src/app/pages/QueryPlannerPage/index.jsx +209 -0
  17. package/src/app/pages/QueryPlannerPage/styles.css +1251 -0
  18. package/src/app/pages/Root/index.tsx +5 -0
  19. package/src/app/services/DJService.js +61 -2
  20. package/src/styles/index.css +2 -2
  21. package/src/app/icons/FilterIcon.jsx +0 -7
  22. package/src/app/pages/NamespacePage/FieldControl.jsx +0 -21
  23. package/src/app/pages/NamespacePage/NodeTypeSelect.jsx +0 -30
  24. package/src/app/pages/NamespacePage/TagSelect.jsx +0 -44
  25. package/src/app/pages/NamespacePage/UserSelect.jsx +0 -47
@@ -0,0 +1,1251 @@
1
+ /* =================================
2
+ Materialization Planner - Three Column Layout
3
+ ================================= */
4
+
5
+ /* CSS Variables for theming */
6
+ :root {
7
+ --planner-bg: #f8fafc;
8
+ --planner-surface: #ffffff;
9
+ --planner-surface-hover: #f1f5f9;
10
+ --planner-border: #e2e8f0;
11
+ --planner-text: #1e293b;
12
+ --planner-text-muted: #64748b;
13
+ --planner-text-dim: #94a3b8;
14
+
15
+ --accent-primary: #3b82f6;
16
+ --accent-preagg: #d97706;
17
+ --accent-metric: #7c3aed;
18
+ --accent-derived: #db2777;
19
+ --accent-success: #059669;
20
+ --accent-warning: #d97706;
21
+ --accent-error: #dc2626;
22
+
23
+ --font-display: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;
24
+ --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
25
+
26
+ --radius-sm: 4px;
27
+ --radius-md: 8px;
28
+ --radius-lg: 12px;
29
+
30
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
31
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
32
+ --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.15);
33
+ }
34
+
35
+ /* Full page layout */
36
+ .planner-page {
37
+ height: 100vh;
38
+ display: flex;
39
+ flex-direction: column;
40
+ background: var(--planner-bg);
41
+ color: var(--planner-text);
42
+ font-family: var(--font-body);
43
+ overflow: hidden;
44
+ }
45
+
46
+ /* Header */
47
+ .planner-header {
48
+ display: flex;
49
+ justify-content: space-between;
50
+ align-items: center;
51
+ padding: 16px 24px;
52
+ background: var(--planner-surface);
53
+ border-bottom: 1px solid var(--planner-border);
54
+ flex-shrink: 0;
55
+ }
56
+
57
+ .planner-header-content h1 {
58
+ margin: 0;
59
+ font-family: var(--font-display);
60
+ font-size: 18px;
61
+ font-weight: 700;
62
+ letter-spacing: -0.3px;
63
+ color: var(--planner-text);
64
+ }
65
+
66
+ .planner-header-content p {
67
+ margin: 4px 0 0;
68
+ font-size: 13px;
69
+ color: var(--planner-text-muted);
70
+ }
71
+
72
+ .header-error {
73
+ padding: 8px 16px;
74
+ background: rgba(220, 38, 38, 0.1);
75
+ border: 1px solid rgba(220, 38, 38, 0.3);
76
+ border-radius: var(--radius-md);
77
+ color: var(--accent-error);
78
+ font-size: 13px;
79
+ }
80
+
81
+ /* =================================
82
+ Three Column Layout
83
+ ================================= */
84
+
85
+ .planner-layout {
86
+ display: flex;
87
+ flex: 1;
88
+ overflow: hidden;
89
+ }
90
+
91
+ /* Left: Selection Panel */
92
+ .planner-selection {
93
+ width: 20%;
94
+ /* min-width: 280px; */
95
+ background: var(--planner-surface);
96
+ border-right: 1px solid var(--planner-border);
97
+ overflow: hidden;
98
+ display: flex;
99
+ flex-direction: column;
100
+ }
101
+
102
+ /* Center: Graph */
103
+ .planner-graph {
104
+ flex: 1;
105
+ display: flex;
106
+ flex-direction: column;
107
+ background: var(--planner-bg);
108
+ overflow: hidden;
109
+ }
110
+
111
+ .graph-header {
112
+ padding: 12px 16px;
113
+ background: var(--planner-surface);
114
+ border-bottom: 1px solid var(--planner-border);
115
+ flex-shrink: 0;
116
+ }
117
+
118
+ .graph-stats {
119
+ font-size: 12px;
120
+ color: var(--planner-text-muted);
121
+ font-family: var(--font-display);
122
+ }
123
+
124
+ .graph-loading {
125
+ flex: 1;
126
+ display: flex;
127
+ flex-direction: column;
128
+ align-items: center;
129
+ justify-content: center;
130
+ gap: 16px;
131
+ color: var(--planner-text-muted);
132
+ }
133
+
134
+ .loading-spinner {
135
+ width: 32px;
136
+ height: 32px;
137
+ border: 3px solid var(--planner-border);
138
+ border-top-color: var(--accent-primary);
139
+ border-radius: 50%;
140
+ animation: spin 0.8s linear infinite;
141
+ }
142
+
143
+ @keyframes spin {
144
+ to {
145
+ transform: rotate(360deg);
146
+ }
147
+ }
148
+
149
+ .graph-empty {
150
+ flex: 1;
151
+ display: flex;
152
+ flex-direction: column;
153
+ align-items: center;
154
+ justify-content: center;
155
+ padding: 48px;
156
+ text-align: center;
157
+ }
158
+
159
+ .graph-empty .empty-icon {
160
+ font-size: 48px;
161
+ opacity: 0.3;
162
+ margin-bottom: 16px;
163
+ }
164
+
165
+ .graph-empty h3 {
166
+ margin: 0 0 8px;
167
+ font-size: 18px;
168
+ color: var(--planner-text);
169
+ }
170
+
171
+ .graph-empty p {
172
+ margin: 0;
173
+ font-size: 14px;
174
+ color: var(--planner-text-muted);
175
+ max-width: 300px;
176
+ }
177
+
178
+ /* Right: Details Panel */
179
+ .planner-details {
180
+ width: 40%;
181
+ min-width: 380px;
182
+ background: var(--planner-surface);
183
+ border-left: 1px solid var(--planner-border);
184
+ overflow-y: auto;
185
+ }
186
+
187
+ /* =================================
188
+ Selection Panel Styles
189
+ ================================= */
190
+
191
+ .selection-panel {
192
+ display: flex;
193
+ flex-direction: column;
194
+ height: 100%;
195
+ overflow: hidden;
196
+ }
197
+
198
+ .selection-section {
199
+ display: flex;
200
+ flex-direction: column;
201
+ flex: 1;
202
+ min-height: 0;
203
+ overflow: hidden;
204
+ }
205
+
206
+ .section-header {
207
+ display: flex;
208
+ justify-content: space-between;
209
+ align-items: center;
210
+ padding: 12px 16px;
211
+ border-bottom: 1px solid var(--planner-border);
212
+ flex-shrink: 0;
213
+ }
214
+
215
+ .section-header h3 {
216
+ margin: 0;
217
+ font-size: 11px;
218
+ font-weight: 700;
219
+ text-transform: uppercase;
220
+ letter-spacing: 0.5px;
221
+ color: var(--planner-text);
222
+ }
223
+
224
+ .selection-count {
225
+ font-size: 11px;
226
+ color: var(--planner-text-dim);
227
+ }
228
+
229
+ .search-box {
230
+ position: relative;
231
+ padding: 8px 12px;
232
+ flex-shrink: 0;
233
+ max-height: 70px;
234
+ }
235
+
236
+ .search-box input {
237
+ width: 100%;
238
+ padding: 8px 12px;
239
+ padding-right: 32px;
240
+ background: var(--planner-bg);
241
+ border: 1px solid var(--planner-border);
242
+ border-radius: var(--radius-md);
243
+ font-size: 13px;
244
+ color: var(--planner-text);
245
+ outline: none;
246
+ transition: border-color 0.15s;
247
+ }
248
+
249
+ .search-box input:focus {
250
+ border-color: var(--accent-primary);
251
+ }
252
+
253
+ .search-box input::placeholder {
254
+ color: var(--planner-text-dim);
255
+ }
256
+
257
+ .clear-search {
258
+ position: absolute;
259
+ right: 20px;
260
+ top: 50%;
261
+ transform: translateY(-50%);
262
+ background: none;
263
+ border: none;
264
+ color: var(--planner-text-dim);
265
+ font-size: 16px;
266
+ cursor: pointer;
267
+ padding: 4px;
268
+ line-height: 1;
269
+ }
270
+
271
+ .clear-search:hover {
272
+ color: var(--planner-text);
273
+ }
274
+
275
+ .selection-list {
276
+ flex: 1;
277
+ overflow-y: auto;
278
+ padding: 8px 0;
279
+ }
280
+
281
+ .namespace-group {
282
+ margin-bottom: 4px;
283
+ }
284
+
285
+ .namespace-header {
286
+ display: flex;
287
+ align-items: center;
288
+ gap: 8px;
289
+ padding: 8px 12px;
290
+ cursor: pointer;
291
+ user-select: none;
292
+ transition: background 0.15s;
293
+ }
294
+
295
+ .namespace-header:hover {
296
+ background: var(--planner-surface-hover);
297
+ }
298
+
299
+ .expand-icon {
300
+ font-size: 10px;
301
+ color: var(--planner-text-dim);
302
+ width: 12px;
303
+ }
304
+
305
+ .namespace-name {
306
+ flex: 1;
307
+ font-size: 12px;
308
+ font-weight: 600;
309
+ color: var(--planner-text);
310
+ font-family: var(--font-display);
311
+ overflow: hidden;
312
+ text-overflow: ellipsis;
313
+ white-space: nowrap;
314
+ }
315
+
316
+ .namespace-count {
317
+ display: flex;
318
+ align-items: center;
319
+ gap: 4px;
320
+ font-size: 11px;
321
+ color: var(--planner-text-dim);
322
+ }
323
+
324
+ .selected-badge {
325
+ background: var(--accent-primary);
326
+ color: white;
327
+ padding: 2px 6px;
328
+ border-radius: 10px;
329
+ font-size: 10px;
330
+ font-weight: 600;
331
+ }
332
+
333
+ .namespace-items {
334
+ padding-left: 20px;
335
+ }
336
+
337
+ .namespace-actions {
338
+ display: flex;
339
+ gap: 8px;
340
+ padding: 4px 12px 8px;
341
+ }
342
+
343
+ .select-all-btn {
344
+ background: none;
345
+ border: none;
346
+ color: var(--accent-primary);
347
+ font-size: 11px;
348
+ cursor: pointer;
349
+ padding: 4px 8px;
350
+ border-radius: var(--radius-sm);
351
+ transition: background 0.15s;
352
+ }
353
+
354
+ .select-all-btn:hover {
355
+ background: rgba(59, 130, 246, 0.1);
356
+ text-decoration: underline;
357
+ }
358
+
359
+ .selection-item {
360
+ display: flex;
361
+ align-items: flex-start;
362
+ gap: 8px;
363
+ padding: 6px 12px;
364
+ cursor: pointer;
365
+ transition: background 0.15s;
366
+ }
367
+
368
+ .selection-item:hover {
369
+ background: var(--planner-surface-hover);
370
+ }
371
+
372
+ .selection-item input[type='checkbox'] {
373
+ margin-top: 2px;
374
+ accent-color: var(--accent-primary);
375
+ }
376
+
377
+ .item-name {
378
+ font-size: 13px;
379
+ color: var(--planner-text);
380
+ word-break: break-word;
381
+ }
382
+
383
+ .dimension-item {
384
+ align-items: flex-start;
385
+ }
386
+
387
+ .dimension-info {
388
+ display: flex;
389
+ flex-direction: column;
390
+ gap: 2px;
391
+ }
392
+
393
+ .dimension-path {
394
+ font-size: 10px;
395
+ color: var(--planner-text-dim);
396
+ font-family: var(--font-display);
397
+ }
398
+
399
+ /* Search result items (flat list) */
400
+ .search-result-item {
401
+ padding: 8px 12px;
402
+ }
403
+
404
+ .search-result-info {
405
+ display: flex;
406
+ flex-direction: column;
407
+ gap: 2px;
408
+ }
409
+
410
+ .item-namespace {
411
+ font-size: 10px;
412
+ color: var(--planner-text-dim);
413
+ font-family: var(--font-display);
414
+ }
415
+
416
+ .section-divider {
417
+ height: 1px;
418
+ background: var(--planner-border);
419
+ margin: 0;
420
+ flex-shrink: 0;
421
+ }
422
+
423
+ .empty-list {
424
+ padding: 24px 16px;
425
+ text-align: center;
426
+ font-size: 13px;
427
+ color: var(--planner-text-dim);
428
+ }
429
+
430
+ .empty-list.hint {
431
+ font-style: italic;
432
+ }
433
+
434
+ /* =================================
435
+ Flow Graph Styles
436
+ ================================= */
437
+
438
+ .compact-flow-container {
439
+ flex: 1;
440
+ position: relative;
441
+ background: var(--planner-bg);
442
+ }
443
+
444
+ .compact-flow-container .react-flow__background {
445
+ background: var(--planner-bg) !important;
446
+ }
447
+
448
+ .graph-empty-state {
449
+ display: flex;
450
+ flex-direction: column;
451
+ align-items: center;
452
+ justify-content: center;
453
+ height: 100%;
454
+ color: var(--planner-text-dim);
455
+ }
456
+
457
+ .graph-empty-state .empty-icon {
458
+ font-size: 48px;
459
+ opacity: 0.3;
460
+ margin-bottom: 16px;
461
+ }
462
+
463
+ /* Compact Nodes */
464
+ .compact-node {
465
+ display: flex;
466
+ align-items: center;
467
+ gap: 10px;
468
+ padding: 10px 14px;
469
+ background: var(--planner-surface);
470
+ border: 2px solid var(--planner-border);
471
+ border-radius: var(--radius-md);
472
+ cursor: pointer;
473
+ transition: all 0.15s ease;
474
+ min-width: 160px;
475
+ box-shadow: var(--shadow-sm);
476
+ }
477
+
478
+ .compact-node:hover {
479
+ transform: translateY(-1px);
480
+ box-shadow: var(--shadow-md);
481
+ }
482
+
483
+ .compact-node.selected {
484
+ border-color: var(--accent-primary);
485
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
486
+ }
487
+
488
+ .compact-node-icon {
489
+ font-size: 16px;
490
+ opacity: 0.7;
491
+ }
492
+
493
+ .compact-node-content {
494
+ flex: 1;
495
+ min-width: 0;
496
+ }
497
+
498
+ .compact-node-name {
499
+ font-size: 12px;
500
+ font-weight: 600;
501
+ color: var(--planner-text);
502
+ margin-bottom: 2px;
503
+ white-space: nowrap;
504
+ overflow: hidden;
505
+ text-overflow: ellipsis;
506
+ }
507
+
508
+ .compact-node-meta {
509
+ display: flex;
510
+ gap: 8px;
511
+ font-size: 10px;
512
+ color: var(--planner-text-dim);
513
+ }
514
+
515
+ .compact-node-badge {
516
+ font-size: 9px;
517
+ text-transform: uppercase;
518
+ letter-spacing: 0.5px;
519
+ padding: 2px 6px;
520
+ border-radius: 3px;
521
+ background: rgba(219, 39, 119, 0.15);
522
+ color: var(--accent-derived);
523
+ font-weight: 600;
524
+ }
525
+
526
+ /* Pre-agg Node */
527
+ .compact-node-preagg {
528
+ border-color: rgba(217, 119, 6, 0.4);
529
+ }
530
+
531
+ .compact-node-preagg:hover {
532
+ border-color: var(--accent-preagg);
533
+ }
534
+
535
+ .compact-node-preagg .compact-node-icon {
536
+ color: var(--accent-preagg);
537
+ }
538
+
539
+ .compact-node-preagg.selected {
540
+ border-color: var(--accent-preagg);
541
+ box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.2);
542
+ }
543
+
544
+ /* Metric Node */
545
+ .compact-node-metric {
546
+ border-color: rgba(124, 58, 237, 0.4);
547
+ }
548
+
549
+ .compact-node-metric:hover {
550
+ border-color: var(--accent-metric);
551
+ }
552
+
553
+ .compact-node-metric .compact-node-icon {
554
+ color: var(--accent-metric);
555
+ }
556
+
557
+ .compact-node-metric.selected {
558
+ border-color: var(--accent-metric);
559
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.2);
560
+ }
561
+
562
+ /* Derived Metric */
563
+ .compact-node-derived {
564
+ border-color: rgba(219, 39, 119, 0.4);
565
+ }
566
+
567
+ .compact-node-derived:hover {
568
+ border-color: var(--accent-derived);
569
+ }
570
+
571
+ .compact-node-derived .compact-node-icon {
572
+ color: var(--accent-derived);
573
+ }
574
+
575
+ /* Node Handles */
576
+ .compact-node .react-flow__handle {
577
+ width: 8px;
578
+ height: 8px;
579
+ border: 2px solid var(--planner-surface);
580
+ background: var(--planner-text-dim);
581
+ }
582
+
583
+ .compact-node-preagg .react-flow__handle {
584
+ background: var(--accent-preagg);
585
+ }
586
+
587
+ .compact-node-metric .react-flow__handle {
588
+ background: var(--accent-metric);
589
+ }
590
+
591
+ /* Graph Legend */
592
+ .graph-legend {
593
+ position: absolute;
594
+ bottom: 16px;
595
+ right: 16px;
596
+ display: flex;
597
+ gap: 16px;
598
+ padding: 10px 16px;
599
+ background: rgba(255, 255, 255, 0.95);
600
+ border: 1px solid var(--planner-border);
601
+ border-radius: var(--radius-md);
602
+ font-size: 11px;
603
+ color: var(--planner-text-muted);
604
+ backdrop-filter: blur(8px);
605
+ z-index: 10;
606
+ }
607
+
608
+ .legend-item {
609
+ display: flex;
610
+ align-items: center;
611
+ gap: 6px;
612
+ }
613
+
614
+ .legend-dot {
615
+ width: 10px;
616
+ height: 10px;
617
+ border-radius: 50%;
618
+ }
619
+
620
+ .legend-dot.preagg {
621
+ background: var(--accent-preagg);
622
+ }
623
+
624
+ .legend-dot.metric {
625
+ background: var(--accent-metric);
626
+ }
627
+
628
+ .legend-dot.derived {
629
+ background: var(--accent-derived);
630
+ }
631
+
632
+ /* =================================
633
+ Details Panel Styles
634
+ ================================= */
635
+
636
+ .details-panel {
637
+ height: 100%;
638
+ overflow-y: auto;
639
+ }
640
+
641
+ .details-panel-empty {
642
+ display: flex;
643
+ align-items: center;
644
+ justify-content: center;
645
+ height: 100%;
646
+ }
647
+
648
+ .empty-hint {
649
+ text-align: center;
650
+ padding: 48px 24px;
651
+ }
652
+
653
+ .empty-hint .empty-icon {
654
+ font-size: 40px;
655
+ opacity: 0.2;
656
+ margin-bottom: 16px;
657
+ }
658
+
659
+ .empty-hint h4 {
660
+ margin: 0 0 8px;
661
+ font-size: 14px;
662
+ color: var(--planner-text);
663
+ }
664
+
665
+ .empty-hint p {
666
+ margin: 0;
667
+ font-size: 12px;
668
+ color: var(--planner-text-dim);
669
+ }
670
+
671
+ /* Details Header */
672
+ .details-header {
673
+ padding: 16px;
674
+ background: var(--planner-bg);
675
+ border-bottom: 1px solid var(--planner-border);
676
+ }
677
+
678
+ .details-title-row {
679
+ display: flex;
680
+ justify-content: space-between;
681
+ align-items: center;
682
+ margin-bottom: 10px;
683
+ }
684
+
685
+ .details-type-badge {
686
+ font-size: 9px;
687
+ font-weight: 700;
688
+ text-transform: uppercase;
689
+ letter-spacing: 0.5px;
690
+ padding: 4px 8px;
691
+ border-radius: var(--radius-sm);
692
+ }
693
+
694
+ .details-type-badge.preagg {
695
+ background: rgba(217, 119, 6, 0.15);
696
+ color: var(--accent-preagg);
697
+ }
698
+
699
+ .details-type-badge.metric {
700
+ background: rgba(124, 58, 237, 0.15);
701
+ color: var(--accent-metric);
702
+ }
703
+
704
+ .details-type-badge.derived {
705
+ background: rgba(219, 39, 119, 0.15);
706
+ color: var(--accent-derived);
707
+ }
708
+
709
+ .details-type-badge.overview {
710
+ background: rgba(59, 130, 246, 0.15);
711
+ color: var(--accent-primary);
712
+ }
713
+
714
+ .details-close {
715
+ width: 24px;
716
+ height: 24px;
717
+ display: flex;
718
+ align-items: center;
719
+ justify-content: center;
720
+ background: transparent;
721
+ border: 1px solid var(--planner-border);
722
+ border-radius: var(--radius-sm);
723
+ color: var(--planner-text-muted);
724
+ font-size: 16px;
725
+ cursor: pointer;
726
+ transition: all 0.15s;
727
+ }
728
+
729
+ .details-close:hover {
730
+ background: var(--planner-surface-hover);
731
+ color: var(--planner-text);
732
+ }
733
+
734
+ .details-title {
735
+ margin: 0 0 4px;
736
+ font-size: 16px;
737
+ font-weight: 700;
738
+ color: var(--planner-text);
739
+ font-family: var(--font-display);
740
+ }
741
+
742
+ .details-full-name {
743
+ margin: 0;
744
+ font-size: 11px;
745
+ color: var(--planner-text-dim);
746
+ font-family: var(--font-display);
747
+ word-break: break-all;
748
+ }
749
+
750
+ /* Details Sections */
751
+ .details-section {
752
+ padding: 14px 16px;
753
+ border-bottom: 1px solid var(--planner-border);
754
+ }
755
+
756
+ .details-section-full {
757
+ padding: 14px 0;
758
+ }
759
+
760
+ .details-section-full > .section-title,
761
+ .details-section-full > .section-header-row {
762
+ padding: 0 16px;
763
+ }
764
+
765
+ .details-section .section-title {
766
+ display: flex;
767
+ align-items: center;
768
+ gap: 6px;
769
+ margin: 0 0 10px;
770
+ font-size: 10px;
771
+ font-weight: 600;
772
+ text-transform: uppercase;
773
+ letter-spacing: 0.5px;
774
+ color: var(--planner-text-muted);
775
+ }
776
+
777
+ .section-icon {
778
+ font-size: 12px;
779
+ opacity: 0.6;
780
+ }
781
+
782
+ .section-header-row {
783
+ display: flex;
784
+ justify-content: space-between;
785
+ align-items: center;
786
+ margin-bottom: 10px;
787
+ }
788
+
789
+ /* Aggregability Badge */
790
+ .details-aggregability-section {
791
+ text-align: center;
792
+ }
793
+
794
+ .aggregability-badge {
795
+ display: inline-block;
796
+ padding: 6px 12px;
797
+ border-radius: var(--radius-md);
798
+ font-size: 11px;
799
+ font-weight: 600;
800
+ text-transform: uppercase;
801
+ letter-spacing: 0.5px;
802
+ }
803
+
804
+ .aggregability-full {
805
+ background: rgba(5, 150, 105, 0.1);
806
+ color: var(--accent-success);
807
+ border: 1px solid rgba(5, 150, 105, 0.2);
808
+ }
809
+
810
+ .aggregability-limited {
811
+ background: rgba(217, 119, 6, 0.1);
812
+ color: var(--accent-warning);
813
+ border: 1px solid rgba(217, 119, 6, 0.2);
814
+ }
815
+
816
+ .aggregability-none {
817
+ background: rgba(220, 38, 38, 0.1);
818
+ color: var(--accent-error);
819
+ border: 1px solid rgba(220, 38, 38, 0.2);
820
+ }
821
+
822
+ /* Grain Pills */
823
+ .grain-pills {
824
+ display: flex;
825
+ flex-wrap: wrap;
826
+ gap: 6px;
827
+ }
828
+
829
+ .grain-pill {
830
+ display: inline-block;
831
+ padding: 5px 8px;
832
+ background: var(--planner-bg);
833
+ border: 1px solid var(--planner-border);
834
+ border-radius: var(--radius-sm);
835
+ font-size: 11px;
836
+ font-family: var(--font-display);
837
+ color: var(--planner-text);
838
+ }
839
+
840
+ .details-section .empty-text {
841
+ font-size: 12px;
842
+ color: var(--planner-text-dim);
843
+ font-style: italic;
844
+ }
845
+
846
+ /* Metrics List */
847
+ .metrics-list {
848
+ display: flex;
849
+ flex-direction: column;
850
+ gap: 6px;
851
+ }
852
+
853
+ .related-metric {
854
+ display: flex;
855
+ align-items: center;
856
+ gap: 8px;
857
+ padding: 8px 10px;
858
+ background: var(--planner-bg);
859
+ border-radius: var(--radius-sm);
860
+ border: 1px solid var(--planner-border);
861
+ }
862
+
863
+ .related-metric .metric-name {
864
+ font-size: 12px;
865
+ font-weight: 500;
866
+ color: var(--accent-metric);
867
+ }
868
+
869
+ .related-metric .derived-badge {
870
+ font-size: 9px;
871
+ text-transform: uppercase;
872
+ padding: 2px 6px;
873
+ border-radius: 3px;
874
+ background: rgba(219, 39, 119, 0.15);
875
+ color: var(--accent-derived);
876
+ font-weight: 600;
877
+ }
878
+
879
+ /* Components Table */
880
+ .components-table-wrapper {
881
+ overflow-x: auto;
882
+ }
883
+
884
+ .details-table {
885
+ width: 100%;
886
+ border-collapse: collapse;
887
+ font-size: 11px;
888
+ }
889
+
890
+ .details-table th {
891
+ padding: 8px 12px;
892
+ background: var(--planner-bg);
893
+ color: var(--planner-text-muted);
894
+ font-weight: 600;
895
+ font-size: 9px;
896
+ text-transform: uppercase;
897
+ letter-spacing: 0.5px;
898
+ text-align: left;
899
+ border-bottom: 1px solid var(--planner-border);
900
+ }
901
+
902
+ .details-table td {
903
+ padding: 10px 12px;
904
+ border-bottom: 1px solid var(--planner-border);
905
+ vertical-align: top;
906
+ }
907
+
908
+ .details-table tr:hover td {
909
+ background: rgba(59, 130, 246, 0.03);
910
+ }
911
+
912
+ .comp-name-cell code {
913
+ font-family: var(--font-display);
914
+ font-size: 10px;
915
+ color: var(--accent-preagg);
916
+ background: rgba(217, 119, 6, 0.1);
917
+ padding: 2px 5px;
918
+ border-radius: 3px;
919
+ }
920
+
921
+ .comp-expr-cell code {
922
+ font-family: var(--font-display);
923
+ font-size: 10px;
924
+ color: var(--planner-text-muted);
925
+ word-break: break-all;
926
+ }
927
+
928
+ .agg-func,
929
+ .merge-func {
930
+ font-family: var(--font-display);
931
+ font-size: 10px;
932
+ color: var(--planner-text-dim);
933
+ }
934
+
935
+ /* SQL Section */
936
+ .details-sql-section {
937
+ border-bottom: none;
938
+ }
939
+
940
+ .copy-sql-btn {
941
+ padding: 5px 10px;
942
+ background: var(--accent-primary);
943
+ color: white;
944
+ border: none;
945
+ border-radius: var(--radius-sm);
946
+ font-size: 10px;
947
+ font-weight: 600;
948
+ cursor: pointer;
949
+ transition: all 0.15s;
950
+ }
951
+
952
+ .copy-sql-btn:hover {
953
+ background: #2563eb;
954
+ }
955
+
956
+ .sql-code-wrapper {
957
+ padding: 0 16px 16px;
958
+ }
959
+
960
+ .sql-code-wrapper pre {
961
+ margin: 0 !important;
962
+ }
963
+
964
+ /* Formula Display (for metric details) */
965
+ .formula-display {
966
+ padding: 10px;
967
+ background: var(--planner-bg);
968
+ border: 1px solid var(--planner-border);
969
+ border-radius: var(--radius-sm);
970
+ }
971
+
972
+ .formula-display code {
973
+ font-family: var(--font-display);
974
+ font-size: 11px;
975
+ color: var(--accent-primary);
976
+ word-break: break-all;
977
+ }
978
+
979
+ /* Component Tags */
980
+ .component-tags {
981
+ display: flex;
982
+ flex-wrap: wrap;
983
+ gap: 6px;
984
+ }
985
+
986
+ .component-tag {
987
+ padding: 5px 8px;
988
+ background: rgba(217, 119, 6, 0.1);
989
+ color: var(--accent-preagg);
990
+ border-radius: var(--radius-sm);
991
+ font-size: 10px;
992
+ font-family: var(--font-display);
993
+ }
994
+
995
+ /* Pre-agg Sources */
996
+ .preagg-sources {
997
+ display: flex;
998
+ flex-direction: column;
999
+ gap: 6px;
1000
+ }
1001
+
1002
+ .preagg-source-item {
1003
+ padding: 8px 10px;
1004
+ background: var(--planner-bg);
1005
+ border: 1px solid var(--planner-border);
1006
+ border-radius: var(--radius-sm);
1007
+ }
1008
+
1009
+ .preagg-source-name {
1010
+ display: block;
1011
+ font-size: 12px;
1012
+ font-weight: 500;
1013
+ color: var(--accent-preagg);
1014
+ margin-bottom: 2px;
1015
+ }
1016
+
1017
+ .preagg-source-full {
1018
+ font-size: 10px;
1019
+ color: var(--planner-text-dim);
1020
+ font-family: var(--font-display);
1021
+ }
1022
+
1023
+ /* =================================
1024
+ Query Overview Panel Styles
1025
+ ================================= */
1026
+
1027
+ .preagg-summary-list {
1028
+ display: flex;
1029
+ flex-direction: column;
1030
+ gap: 10px;
1031
+ }
1032
+
1033
+ .preagg-summary-card {
1034
+ padding: 12px;
1035
+ background: var(--planner-bg);
1036
+ border: 1px solid var(--planner-border);
1037
+ border-radius: var(--radius-md);
1038
+ }
1039
+
1040
+ .preagg-summary-header {
1041
+ display: flex;
1042
+ justify-content: space-between;
1043
+ align-items: center;
1044
+ margin-bottom: 10px;
1045
+ }
1046
+
1047
+ .preagg-summary-name {
1048
+ font-size: 13px;
1049
+ font-weight: 600;
1050
+ color: var(--accent-preagg);
1051
+ font-family: var(--font-display);
1052
+ }
1053
+
1054
+ .aggregability-pill {
1055
+ font-size: 9px;
1056
+ font-weight: 600;
1057
+ text-transform: uppercase;
1058
+ letter-spacing: 0.3px;
1059
+ padding: 3px 6px;
1060
+ border-radius: var(--radius-sm);
1061
+ }
1062
+
1063
+ .aggregability-pill.aggregability-full {
1064
+ background: rgba(5, 150, 105, 0.1);
1065
+ color: var(--accent-success);
1066
+ }
1067
+
1068
+ .aggregability-pill.aggregability-limited {
1069
+ background: rgba(217, 119, 6, 0.1);
1070
+ color: var(--accent-warning);
1071
+ }
1072
+
1073
+ .aggregability-pill.aggregability-none {
1074
+ background: rgba(220, 38, 38, 0.1);
1075
+ color: var(--accent-error);
1076
+ }
1077
+
1078
+ .preagg-summary-details {
1079
+ display: flex;
1080
+ flex-direction: column;
1081
+ gap: 4px;
1082
+ margin-bottom: 8px;
1083
+ }
1084
+
1085
+ .preagg-summary-row {
1086
+ display: flex;
1087
+ gap: 8px;
1088
+ font-size: 11px;
1089
+ }
1090
+
1091
+ .preagg-summary-row .label {
1092
+ color: var(--planner-text-dim);
1093
+ min-width: 60px;
1094
+ }
1095
+
1096
+ .preagg-summary-row .value {
1097
+ color: var(--planner-text);
1098
+ font-family: var(--font-display);
1099
+ flex: 1;
1100
+ overflow: hidden;
1101
+ text-overflow: ellipsis;
1102
+ white-space: nowrap;
1103
+ }
1104
+
1105
+ .preagg-summary-status {
1106
+ display: flex;
1107
+ align-items: center;
1108
+ gap: 6px;
1109
+ padding-top: 8px;
1110
+ border-top: 1px solid var(--planner-border);
1111
+ font-size: 11px;
1112
+ color: var(--planner-text-muted);
1113
+ }
1114
+
1115
+ .status-indicator {
1116
+ font-size: 12px;
1117
+ }
1118
+
1119
+ .status-indicator.status-materialized {
1120
+ color: var(--accent-success);
1121
+ }
1122
+
1123
+ .status-indicator.status-not-materialized {
1124
+ color: var(--planner-text-dim);
1125
+ }
1126
+
1127
+ .status-indicator.status-stale {
1128
+ color: var(--accent-warning);
1129
+ }
1130
+
1131
+ /* Metrics & Dimensions Summary Grid */
1132
+ .selection-summary-grid {
1133
+ display: grid;
1134
+ grid-template-columns: 1fr 1fr;
1135
+ gap: 16px;
1136
+ }
1137
+
1138
+ .selection-summary-column .section-title {
1139
+ margin-bottom: 8px;
1140
+ }
1141
+
1142
+ .selection-summary-list {
1143
+ display: flex;
1144
+ flex-direction: column;
1145
+ gap: 4px;
1146
+ max-height: 150px;
1147
+ overflow-y: auto;
1148
+ }
1149
+
1150
+ .selection-summary-item {
1151
+ display: flex;
1152
+ align-items: center;
1153
+ gap: 6px;
1154
+ padding: 6px 8px;
1155
+ background: var(--planner-bg);
1156
+ border: 1px solid var(--planner-border);
1157
+ border-radius: var(--radius-sm);
1158
+ text-decoration: none;
1159
+ transition: all 0.15s ease;
1160
+ }
1161
+
1162
+ .selection-summary-item.clickable:hover {
1163
+ background: var(--planner-surface-hover);
1164
+ border-color: var(--accent-primary);
1165
+ text-decoration: none;
1166
+ }
1167
+
1168
+ .selection-summary-item.clickable.metric:hover {
1169
+ border-color: var(--accent-metric);
1170
+ }
1171
+
1172
+ .selection-summary-item.clickable.dimension:hover {
1173
+ border-color: var(--accent-primary);
1174
+ }
1175
+
1176
+ .selection-summary-item.metric {
1177
+ border-left: 3px solid var(--accent-metric);
1178
+ }
1179
+
1180
+ .selection-summary-item.dimension {
1181
+ border-left: 3px solid var(--accent-primary);
1182
+ }
1183
+
1184
+ .selection-summary-name {
1185
+ font-size: 11px;
1186
+ font-weight: 500;
1187
+ color: var(--planner-text);
1188
+ font-family: var(--font-display);
1189
+ }
1190
+
1191
+ .selection-summary-item.metric .selection-summary-name {
1192
+ color: var(--accent-metric);
1193
+ }
1194
+
1195
+ .selection-summary-item.dimension .selection-summary-name {
1196
+ color: var(--accent-primary);
1197
+ }
1198
+
1199
+ /* =================================
1200
+ React Flow Overrides
1201
+ ================================= */
1202
+
1203
+ .react-flow__controls {
1204
+ background: var(--planner-surface) !important;
1205
+ border: 1px solid var(--planner-border) !important;
1206
+ border-radius: var(--radius-md) !important;
1207
+ box-shadow: var(--shadow-md) !important;
1208
+ }
1209
+
1210
+ .react-flow__controls-button {
1211
+ background: transparent !important;
1212
+ border-bottom-color: var(--planner-border) !important;
1213
+ color: var(--planner-text-muted) !important;
1214
+ }
1215
+
1216
+ .react-flow__controls-button:hover {
1217
+ background: var(--planner-surface-hover) !important;
1218
+ color: var(--planner-text) !important;
1219
+ }
1220
+
1221
+ .react-flow__minimap {
1222
+ background: var(--planner-surface) !important;
1223
+ border: 1px solid var(--planner-border) !important;
1224
+ border-radius: var(--radius-md) !important;
1225
+ }
1226
+
1227
+ /* Scrollbar styling */
1228
+ .selection-list::-webkit-scrollbar,
1229
+ .details-panel::-webkit-scrollbar,
1230
+ .planner-details::-webkit-scrollbar {
1231
+ width: 6px;
1232
+ }
1233
+
1234
+ .selection-list::-webkit-scrollbar-track,
1235
+ .details-panel::-webkit-scrollbar-track,
1236
+ .planner-details::-webkit-scrollbar-track {
1237
+ background: transparent;
1238
+ }
1239
+
1240
+ .selection-list::-webkit-scrollbar-thumb,
1241
+ .details-panel::-webkit-scrollbar-thumb,
1242
+ .planner-details::-webkit-scrollbar-thumb {
1243
+ background: var(--planner-border);
1244
+ border-radius: 3px;
1245
+ }
1246
+
1247
+ .selection-list::-webkit-scrollbar-thumb:hover,
1248
+ .details-panel::-webkit-scrollbar-thumb:hover,
1249
+ .planner-details::-webkit-scrollbar-thumb:hover {
1250
+ background: var(--planner-text-dim);
1251
+ }