datajunction-ui 0.0.26 → 0.0.27

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 (28) hide show
  1. package/package.json +2 -2
  2. package/src/app/components/Search.jsx +41 -33
  3. package/src/app/components/__tests__/Search.test.jsx +46 -11
  4. package/src/app/index.tsx +3 -3
  5. package/src/app/pages/AddEditNodePage/MetricQueryField.jsx +57 -8
  6. package/src/app/pages/AddEditNodePage/UpstreamNodeField.jsx +17 -5
  7. package/src/app/pages/AddEditNodePage/__tests__/index.test.jsx +97 -1
  8. package/src/app/pages/AddEditNodePage/index.jsx +61 -17
  9. package/src/app/pages/NodePage/WatchNodeButton.jsx +12 -5
  10. package/src/app/pages/QueryPlannerPage/MetricFlowGraph.jsx +93 -15
  11. package/src/app/pages/QueryPlannerPage/PreAggDetailsPanel.jsx +2320 -65
  12. package/src/app/pages/QueryPlannerPage/SelectionPanel.jsx +234 -25
  13. package/src/app/pages/QueryPlannerPage/__tests__/MetricFlowGraph.test.jsx +315 -122
  14. package/src/app/pages/QueryPlannerPage/__tests__/PreAggDetailsPanel.test.jsx +2672 -314
  15. package/src/app/pages/QueryPlannerPage/__tests__/SelectionPanel.test.jsx +567 -0
  16. package/src/app/pages/QueryPlannerPage/__tests__/index.test.jsx +480 -55
  17. package/src/app/pages/QueryPlannerPage/index.jsx +1021 -14
  18. package/src/app/pages/QueryPlannerPage/styles.css +1990 -62
  19. package/src/app/pages/Root/__tests__/index.test.jsx +79 -8
  20. package/src/app/pages/Root/index.tsx +1 -6
  21. package/src/app/pages/SQLBuilderPage/__tests__/index.test.jsx +82 -0
  22. package/src/app/pages/SettingsPage/__tests__/CreateServiceAccountModal.test.jsx +37 -0
  23. package/src/app/pages/SettingsPage/__tests__/ServiceAccountsSection.test.jsx +48 -0
  24. package/src/app/pages/SettingsPage/__tests__/index.test.jsx +169 -1
  25. package/src/app/services/DJService.js +492 -3
  26. package/src/app/services/__tests__/DJService.test.jsx +582 -0
  27. package/src/mocks/mockNodes.jsx +36 -0
  28. package/webpack.config.js +27 -0
@@ -14,8 +14,10 @@
14
14
 
15
15
  --accent-primary: #3b82f6;
16
16
  --accent-preagg: #d97706;
17
- --accent-metric: #7c3aed;
17
+ --accent-metric: #a2283e; /* Rose/pink - matches node_type__metric */
18
+ --accent-dimension: #a96621; /* Golden orange - matches node_type__dimension */
18
19
  --accent-derived: #db2777;
20
+ --accent-cube: #580076; /* Dark purple - matches node_type__cube */
19
21
  --accent-success: #059669;
20
22
  --accent-warning: #d97706;
21
23
  --accent-error: #dc2626;
@@ -78,6 +80,284 @@
78
80
  font-size: 13px;
79
81
  }
80
82
 
83
+ /* Materialization Error Banner */
84
+ .materialization-error {
85
+ display: flex;
86
+ align-items: flex-start;
87
+ justify-content: space-between;
88
+ gap: 12px;
89
+ padding: 12px 14px;
90
+ margin-bottom: 12px;
91
+ background: rgba(220, 38, 38, 0.08);
92
+ border: 1px solid rgba(220, 38, 38, 0.25);
93
+ border-radius: var(--radius-md);
94
+ color: var(--accent-error);
95
+ font-size: 12px;
96
+ line-height: 1.5;
97
+ }
98
+
99
+ .materialization-error .error-content {
100
+ display: flex;
101
+ align-items: flex-start;
102
+ gap: 8px;
103
+ flex: 1;
104
+ }
105
+
106
+ .materialization-error .error-icon {
107
+ font-size: 14px;
108
+ flex-shrink: 0;
109
+ margin-top: 1px;
110
+ }
111
+
112
+ .materialization-error .error-message {
113
+ word-break: break-word;
114
+ }
115
+
116
+ .materialization-error .error-dismiss {
117
+ background: none;
118
+ border: none;
119
+ color: var(--accent-error);
120
+ font-size: 18px;
121
+ line-height: 1;
122
+ cursor: pointer;
123
+ padding: 0;
124
+ opacity: 0.7;
125
+ transition: opacity 0.15s ease;
126
+ flex-shrink: 0;
127
+ }
128
+
129
+ .materialization-error .error-dismiss:hover {
130
+ opacity: 1;
131
+ }
132
+
133
+ /* Global error banner (outside form) */
134
+ .materialization-error.global-error {
135
+ margin: 0 0 16px 0;
136
+ }
137
+
138
+ /* Workflow Success Banner */
139
+ .workflow-success {
140
+ display: flex;
141
+ align-items: flex-start;
142
+ justify-content: space-between;
143
+ gap: 12px;
144
+ padding: 12px 14px;
145
+ margin-bottom: 12px;
146
+ background: rgba(34, 197, 94, 0.08);
147
+ border: 1px solid rgba(34, 197, 94, 0.25);
148
+ border-radius: var(--radius-md);
149
+ color: var(--accent-green, #22c55e);
150
+ font-size: 12px;
151
+ line-height: 1.5;
152
+ }
153
+
154
+ .workflow-success .success-content {
155
+ display: flex;
156
+ align-items: flex-start;
157
+ gap: 8px;
158
+ flex: 1;
159
+ }
160
+
161
+ .workflow-success .success-icon {
162
+ font-size: 14px;
163
+ flex-shrink: 0;
164
+ margin-top: 1px;
165
+ background: var(--accent-green, #22c55e);
166
+ color: white;
167
+ width: 18px;
168
+ height: 18px;
169
+ border-radius: 50%;
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ font-weight: bold;
174
+ }
175
+
176
+ .workflow-success .success-message {
177
+ word-break: break-word;
178
+ }
179
+
180
+ .workflow-success .success-message strong {
181
+ display: block;
182
+ margin-bottom: 6px;
183
+ color: var(--planner-text);
184
+ }
185
+
186
+ .workflow-success .workflow-url-list {
187
+ list-style: none;
188
+ padding: 0;
189
+ margin: 0;
190
+ display: flex;
191
+ flex-direction: column;
192
+ gap: 4px;
193
+ }
194
+
195
+ .workflow-success .workflow-url-list a {
196
+ color: var(--accent-green, #22c55e);
197
+ text-decoration: none;
198
+ display: inline-flex;
199
+ align-items: center;
200
+ gap: 4px;
201
+ }
202
+
203
+ .workflow-success .workflow-url-list a:hover {
204
+ text-decoration: underline;
205
+ }
206
+
207
+ .workflow-success .success-dismiss {
208
+ background: none;
209
+ border: none;
210
+ color: var(--accent-green, #22c55e);
211
+ font-size: 18px;
212
+ line-height: 1;
213
+ cursor: pointer;
214
+ padding: 0;
215
+ opacity: 0.7;
216
+ transition: opacity 0.15s ease;
217
+ flex-shrink: 0;
218
+ }
219
+
220
+ .workflow-success .success-dismiss:hover {
221
+ opacity: 1;
222
+ }
223
+
224
+ /* Cube Card (matches pre-agg card styling) */
225
+ .preagg-summary-card.cube-card {
226
+ /* border-color: rgba(88, 0, 118, 0.3); */
227
+ background: linear-gradient(
228
+ 135deg,
229
+ rgba(88, 0, 118, 0.04),
230
+ var(--planner-bg)
231
+ );
232
+ }
233
+
234
+ .preagg-summary-card.cube-card .preagg-summary-name.cube-name {
235
+ color: var(--accent-cube, #580076);
236
+ }
237
+
238
+ .cube-workflow-links {
239
+ display: flex;
240
+ flex-wrap: wrap;
241
+ gap: 8px;
242
+ margin-top: 10px;
243
+ padding-top: 10px;
244
+ border-top: 1px solid var(--planner-border);
245
+ }
246
+
247
+ /* Materialization Status Bar (compact) */
248
+ .materialization-status-bar {
249
+ display: flex;
250
+ align-items: center;
251
+ justify-content: space-between;
252
+ padding: 8px 12px;
253
+ background: linear-gradient(
254
+ 135deg,
255
+ rgba(5, 150, 105, 0.06),
256
+ var(--planner-bg)
257
+ );
258
+ border: 1px solid rgba(5, 150, 105, 0.25);
259
+ border-radius: var(--radius-md);
260
+ margin-bottom: 16px;
261
+ }
262
+
263
+ .status-bar-left {
264
+ display: flex;
265
+ align-items: center;
266
+ gap: 8px;
267
+ }
268
+
269
+ .status-bar-indicator {
270
+ color: var(--accent-success, #059669);
271
+ font-size: 12px;
272
+ font-weight: bold;
273
+ }
274
+
275
+ .status-bar-label {
276
+ font-size: 12px;
277
+ font-weight: 600;
278
+ color: var(--accent-success, #059669);
279
+ }
280
+
281
+ .status-bar-badge {
282
+ font-size: 10px;
283
+ font-weight: 600;
284
+ padding: 3px 8px;
285
+ border-radius: 10px;
286
+ }
287
+
288
+ .status-bar-badge.badge-cube {
289
+ background: rgba(88, 0, 118, 0.12);
290
+ color: var(--accent-cube, #580076);
291
+ }
292
+
293
+ .status-bar-badge.badge-preagg {
294
+ background: rgba(107, 114, 128, 0.12);
295
+ color: var(--planner-text);
296
+ }
297
+
298
+ .status-bar-edit {
299
+ padding: 4px 10px;
300
+ font-size: 11px;
301
+ font-weight: 500;
302
+ border-radius: var(--radius-sm);
303
+ cursor: pointer;
304
+ transition: all 0.15s ease;
305
+ border: 1px solid var(--planner-border);
306
+ background: var(--planner-surface);
307
+ color: var(--planner-text);
308
+ }
309
+
310
+ .status-bar-edit:hover {
311
+ background: var(--planner-surface-hover);
312
+ border-color: var(--accent-primary);
313
+ }
314
+
315
+ /* Selection Summary Label */
316
+ .selection-summary-label {
317
+ font-size: 11px;
318
+ font-weight: 600;
319
+ color: var(--planner-text-muted);
320
+ margin-bottom: 6px;
321
+ text-transform: uppercase;
322
+ letter-spacing: 0.3px;
323
+ }
324
+
325
+ /* Status Pill Badges */
326
+ .status-pill {
327
+ font-size: 10px;
328
+ font-weight: 600;
329
+ padding: 3px 8px;
330
+ border-radius: var(--radius-sm);
331
+ white-space: nowrap;
332
+ }
333
+
334
+ .status-pill.status-active {
335
+ background: rgba(5, 150, 105, 0.1);
336
+ color: var(--accent-success, #059669);
337
+ }
338
+
339
+ .status-pill.status-not-set {
340
+ background: rgba(107, 114, 128, 0.1);
341
+ color: var(--planner-text-muted);
342
+ }
343
+
344
+ .status-pill.status-pending {
345
+ background: rgba(245, 158, 11, 0.1);
346
+ color: var(--accent-warning, #f59e0b);
347
+ }
348
+
349
+ /* Pre-Aggregation Section Header */
350
+ .preagg-section-header {
351
+ font-size: 11px;
352
+ font-weight: 600;
353
+ text-transform: uppercase;
354
+ letter-spacing: 0.5px;
355
+ color: var(--planner-text-muted);
356
+ padding: 8px 0;
357
+ margin-bottom: 4px;
358
+ border-bottom: 1px solid var(--planner-border);
359
+ }
360
+
81
361
  /* =================================
82
362
  Three Column Layout
83
363
  ================================= */
@@ -94,7 +374,7 @@
94
374
  /* min-width: 280px; */
95
375
  background: var(--planner-surface);
96
376
  border-right: 1px solid var(--planner-border);
97
- overflow: hidden;
377
+ overflow: visible; /* Allow cube dropdown to overflow */
98
378
  display: flex;
99
379
  flex-direction: column;
100
380
  }
@@ -192,83 +472,242 @@
192
472
  display: flex;
193
473
  flex-direction: column;
194
474
  height: 100%;
195
- overflow: hidden;
475
+ overflow: visible; /* Allow cube dropdown to overflow */
196
476
  }
197
477
 
198
- .selection-section {
199
- display: flex;
200
- flex-direction: column;
201
- flex: 1;
202
- min-height: 0;
203
- overflow: hidden;
478
+ /* Cube Preset Section */
479
+ .cube-preset-section {
480
+ padding: 10px 12px;
481
+ border-bottom: 1px solid var(--planner-border);
482
+ background: var(--planner-bg);
483
+ position: relative;
484
+ flex-shrink: 0;
485
+ z-index: 10; /* Create stacking context for dropdown */
204
486
  }
205
487
 
206
- .section-header {
488
+ .preset-row {
207
489
  display: flex;
208
- justify-content: space-between;
209
490
  align-items: center;
210
- padding: 12px 16px;
211
- border-bottom: 1px solid var(--planner-border);
212
- flex-shrink: 0;
491
+ gap: 8px;
213
492
  }
214
493
 
215
- .section-header h3 {
216
- margin: 0;
217
- font-size: 11px;
218
- font-weight: 700;
219
- text-transform: uppercase;
220
- letter-spacing: 0.5px;
494
+ .preset-button {
495
+ display: flex;
496
+ align-items: center;
497
+ gap: 6px;
498
+ padding: 6px 10px;
499
+ background: var(--planner-elevated);
500
+ border: 1px solid var(--planner-border);
501
+ border-radius: var(--radius-md);
221
502
  color: var(--planner-text);
503
+ font-size: 11px;
504
+ font-weight: 500;
505
+ font-family: var(--font-display);
506
+ cursor: pointer;
507
+ transition: all 0.15s ease;
508
+ flex: 1;
222
509
  }
223
510
 
224
- .selection-count {
225
- font-size: 11px;
226
- color: var(--planner-text-dim);
511
+ .preset-button:hover {
512
+ background: var(--planner-surface);
513
+ border-color: var(--accent-primary);
227
514
  }
228
515
 
229
- .search-box {
230
- position: relative;
231
- padding: 8px 12px;
232
- flex-shrink: 0;
233
- max-height: 70px;
516
+ /* Loaded cube preset state */
517
+ .preset-button.has-preset {
518
+ background: rgba(88, 0, 118, 0.1); /* Light purple - matches cube color */
519
+ border-color: var(--accent-cube);
520
+ color: var(--accent-cube);
234
521
  }
235
522
 
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;
523
+ .preset-button.has-preset:hover {
524
+ background: rgba(88, 0, 118, 0.15);
525
+ border-color: var(--accent-cube);
247
526
  }
248
527
 
249
- .search-box input:focus {
250
- border-color: var(--accent-primary);
528
+ .preset-label {
529
+ flex: 1;
530
+ text-align: left;
531
+ overflow: hidden;
532
+ text-overflow: ellipsis;
533
+ white-space: nowrap;
251
534
  }
252
535
 
253
- .search-box input::placeholder {
254
- color: var(--planner-text-dim);
536
+ .preset-icon {
537
+ font-size: 12px;
538
+ flex-shrink: 0;
255
539
  }
256
540
 
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;
541
+ .dropdown-arrow {
542
+ margin-left: auto;
543
+ font-size: 8px;
544
+ opacity: 0.6;
269
545
  }
270
546
 
271
- .clear-search:hover {
547
+ .clear-all-btn {
548
+ padding: 6px 10px;
549
+ background: transparent;
550
+ border: 1px solid var(--planner-border);
551
+ border-radius: var(--radius-md);
552
+ color: var(--planner-text-muted);
553
+ font-size: 10px;
554
+ font-weight: 500;
555
+ cursor: pointer;
556
+ transition: all 0.15s ease;
557
+ white-space: nowrap;
558
+ }
559
+
560
+ .clear-all-btn:hover {
561
+ background: rgba(239, 68, 68, 0.1);
562
+ border-color: rgba(239, 68, 68, 0.3);
563
+ color: #dc2626;
564
+ }
565
+
566
+ .cube-dropdown {
567
+ position: absolute;
568
+ top: calc(100% - 1px);
569
+ left: 0;
570
+ right: 0;
571
+ background: #ffffff;
572
+ border: 1px solid var(--planner-border);
573
+ border-top: none;
574
+ border-radius: 0 0 var(--radius-md) var(--radius-md);
575
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
576
+ z-index: 1000; /* High z-index to appear above everything */
577
+ max-height: 300px;
578
+ display: flex;
579
+ flex-direction: column;
580
+ }
581
+
582
+ .cube-search {
583
+ padding: 8px 12px;
584
+ border: none;
585
+ border-bottom: 1px solid var(--planner-border);
586
+ background: transparent;
587
+ color: var(--planner-text);
588
+ font-size: 12px;
589
+ outline: none;
590
+ }
591
+
592
+ .cube-search::placeholder {
593
+ color: var(--planner-text-muted);
594
+ }
595
+
596
+ .cube-list {
597
+ overflow-y: auto;
598
+ max-height: 250px;
599
+ }
600
+
601
+ .cube-option {
602
+ display: flex;
603
+ flex-direction: column;
604
+ gap: 2px;
605
+ width: 100%;
606
+ padding: 8px 12px;
607
+ background: transparent;
608
+ border: none;
609
+ text-align: left;
610
+ cursor: pointer;
611
+ transition: background 0.1s ease;
612
+ }
613
+
614
+ .cube-option:hover {
615
+ background: var(--planner-surface);
616
+ }
617
+
618
+ .cube-name {
619
+ font-size: 12px;
620
+ font-weight: 500;
621
+ color: var(--planner-text);
622
+ font-family: var(--font-display);
623
+ }
624
+
625
+ .cube-info {
626
+ font-size: 10px;
627
+ color: var(--planner-text-muted);
628
+ }
629
+
630
+ .cube-empty {
631
+ padding: 16px 12px;
632
+ text-align: center;
633
+ font-size: 11px;
634
+ color: var(--planner-text-muted);
635
+ }
636
+
637
+ .selection-section {
638
+ display: flex;
639
+ flex-direction: column;
640
+ flex: 1;
641
+ min-height: 0;
642
+ overflow: hidden;
643
+ }
644
+
645
+ .section-header {
646
+ display: flex;
647
+ justify-content: space-between;
648
+ align-items: center;
649
+ padding: 12px 16px;
650
+ border-bottom: 1px solid var(--planner-border);
651
+ flex-shrink: 0;
652
+ }
653
+
654
+ .section-header h3 {
655
+ margin: 0;
656
+ font-size: 11px;
657
+ font-weight: 700;
658
+ text-transform: uppercase;
659
+ letter-spacing: 0.5px;
660
+ color: var(--planner-text);
661
+ }
662
+
663
+ .selection-count {
664
+ font-size: 11px;
665
+ color: var(--planner-text-dim);
666
+ }
667
+
668
+ .search-box {
669
+ position: relative;
670
+ padding: 8px 12px;
671
+ flex-shrink: 0;
672
+ max-height: 70px;
673
+ }
674
+
675
+ .search-box input {
676
+ width: 100%;
677
+ padding: 8px 12px;
678
+ padding-right: 32px;
679
+ background: var(--planner-bg);
680
+ border: 1px solid var(--planner-border);
681
+ border-radius: var(--radius-md);
682
+ font-size: 13px;
683
+ color: var(--planner-text);
684
+ outline: none;
685
+ transition: border-color 0.15s;
686
+ }
687
+
688
+ .search-box input:focus {
689
+ border-color: var(--accent-primary);
690
+ }
691
+
692
+ .search-box input::placeholder {
693
+ color: var(--planner-text-dim);
694
+ }
695
+
696
+ .clear-search {
697
+ position: absolute;
698
+ right: 20px;
699
+ top: 50%;
700
+ transform: translateY(-50%);
701
+ background: none;
702
+ border: none;
703
+ color: var(--planner-text-dim);
704
+ font-size: 16px;
705
+ cursor: pointer;
706
+ padding: 4px;
707
+ line-height: 1;
708
+ }
709
+
710
+ .clear-search:hover {
272
711
  color: var(--planner-text);
273
712
  }
274
713
 
@@ -543,7 +982,7 @@
543
982
 
544
983
  /* Metric Node */
545
984
  .compact-node-metric {
546
- border-color: rgba(124, 58, 237, 0.4);
985
+ border-color: rgba(162, 40, 62, 0.4); /* Matches --accent-metric */
547
986
  }
548
987
 
549
988
  .compact-node-metric:hover {
@@ -556,7 +995,7 @@
556
995
 
557
996
  .compact-node-metric.selected {
558
997
  border-color: var(--accent-metric);
559
- box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.2);
998
+ box-shadow: 0 0 0 3px rgba(162, 40, 62, 0.2); /* Matches --accent-metric */
560
999
  }
561
1000
 
562
1001
  /* Derived Metric */
@@ -572,6 +1011,24 @@
572
1011
  color: var(--accent-derived);
573
1012
  }
574
1013
 
1014
+ /* Component Node */
1015
+ .compact-node-component {
1016
+ border-color: rgba(34, 197, 94, 0.4);
1017
+ }
1018
+
1019
+ .compact-node-component:hover {
1020
+ border-color: #22c55e;
1021
+ }
1022
+
1023
+ .compact-node-component .compact-node-icon {
1024
+ color: #22c55e;
1025
+ }
1026
+
1027
+ .compact-node-component.selected {
1028
+ border-color: #22c55e;
1029
+ box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.2);
1030
+ }
1031
+
575
1032
  /* Node Handles */
576
1033
  .compact-node .react-flow__handle {
577
1034
  width: 8px;
@@ -584,6 +1041,10 @@
584
1041
  background: var(--accent-preagg);
585
1042
  }
586
1043
 
1044
+ .compact-node-component .react-flow__handle {
1045
+ background: #22c55e;
1046
+ }
1047
+
587
1048
  .compact-node-metric .react-flow__handle {
588
1049
  background: var(--accent-metric);
589
1050
  }
@@ -621,6 +1082,10 @@
621
1082
  background: var(--accent-preagg);
622
1083
  }
623
1084
 
1085
+ .legend-dot.component {
1086
+ background: #22c55e;
1087
+ }
1088
+
624
1089
  .legend-dot.metric {
625
1090
  background: var(--accent-metric);
626
1091
  }
@@ -697,7 +1162,7 @@
697
1162
  }
698
1163
 
699
1164
  .details-type-badge.metric {
700
- background: rgba(124, 58, 237, 0.15);
1165
+ background: rgba(162, 40, 62, 0.15); /* Matches --accent-metric */
701
1166
  color: var(--accent-metric);
702
1167
  }
703
1168
 
@@ -779,6 +1244,11 @@
779
1244
  opacity: 0.6;
780
1245
  }
781
1246
 
1247
+ .section-icon.cube-icon {
1248
+ color: var(--accent-cube, #580076);
1249
+ opacity: 1;
1250
+ }
1251
+
782
1252
  .section-header-row {
783
1253
  display: flex;
784
1254
  justify-content: space-between;
@@ -909,6 +1379,26 @@
909
1379
  background: rgba(59, 130, 246, 0.03);
910
1380
  }
911
1381
 
1382
+ /* Highlighted component row - when clicking a component in the graph */
1383
+ .details-table tr.component-row-highlighted {
1384
+ animation: highlightFade 2s ease-out;
1385
+ }
1386
+
1387
+ .details-table tr.component-row-highlighted td {
1388
+ background: rgb(240 246 59 / 15%);
1389
+ border-top: 1px solid rgba(59, 130, 246, 0.3);
1390
+ border-bottom: 1px solid rgba(59, 130, 246, 0.3);
1391
+ }
1392
+
1393
+ @keyframes highlightFade {
1394
+ 0% {
1395
+ background: rgba(59, 130, 246, 0.3);
1396
+ }
1397
+ 100% {
1398
+ background: rgba(59, 130, 246, 0.15);
1399
+ }
1400
+ }
1401
+
912
1402
  .comp-name-cell code {
913
1403
  font-family: var(--font-display);
914
1404
  font-size: 10px;
@@ -937,6 +1427,44 @@
937
1427
  border-bottom: none;
938
1428
  }
939
1429
 
1430
+ /* SQL View Toggle */
1431
+ .sql-view-toggle {
1432
+ display: flex;
1433
+ gap: 2px;
1434
+ background: #e2e8f0;
1435
+ border-radius: var(--radius-sm);
1436
+ padding: 2px;
1437
+ }
1438
+
1439
+ .sql-toggle-btn {
1440
+ padding: 4px 10px;
1441
+ background: transparent;
1442
+ color: #64748b;
1443
+ border: none;
1444
+ border-radius: calc(var(--radius-sm) - 2px);
1445
+ font-size: 10px;
1446
+ font-weight: 600;
1447
+ cursor: pointer;
1448
+ transition: all 0.15s;
1449
+ }
1450
+
1451
+ .sql-toggle-btn:hover:not(.active):not(:disabled) {
1452
+ color: #334155;
1453
+ background: rgba(255, 255, 255, 0.5);
1454
+ }
1455
+
1456
+ .sql-toggle-btn.active {
1457
+ background: white;
1458
+ color: var(--accent-primary);
1459
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
1460
+ }
1461
+
1462
+ .sql-toggle-btn:disabled {
1463
+ cursor: wait;
1464
+ opacity: 0.7;
1465
+ }
1466
+
1467
+ /* Copy SQL button (for PreAggDetailsPanel) */
940
1468
  .copy-sql-btn {
941
1469
  padding: 5px 10px;
942
1470
  background: var(--accent-primary);
@@ -1116,6 +1644,16 @@
1116
1644
  font-size: 12px;
1117
1645
  }
1118
1646
 
1647
+ /* Pre-agg/Cube action buttons row */
1648
+ .preagg-actions {
1649
+ display: flex;
1650
+ flex-wrap: wrap;
1651
+ gap: 8px;
1652
+ margin-top: 10px;
1653
+ padding-top: 10px;
1654
+ border-top: 1px solid var(--planner-border);
1655
+ }
1656
+
1119
1657
  .status-indicator.status-materialized {
1120
1658
  color: var(--accent-success);
1121
1659
  }
@@ -1170,7 +1708,7 @@
1170
1708
  }
1171
1709
 
1172
1710
  .selection-summary-item.clickable.dimension:hover {
1173
- border-color: var(--accent-primary);
1711
+ border-color: var(--accent-dimension);
1174
1712
  }
1175
1713
 
1176
1714
  .selection-summary-item.metric {
@@ -1178,7 +1716,7 @@
1178
1716
  }
1179
1717
 
1180
1718
  .selection-summary-item.dimension {
1181
- border-left: 3px solid var(--accent-primary);
1719
+ border-left: 3px solid var(--accent-dimension);
1182
1720
  }
1183
1721
 
1184
1722
  .selection-summary-name {
@@ -1193,7 +1731,7 @@
1193
1731
  }
1194
1732
 
1195
1733
  .selection-summary-item.dimension .selection-summary-name {
1196
- color: var(--accent-primary);
1734
+ color: var(--accent-dimension);
1197
1735
  }
1198
1736
 
1199
1737
  /* =================================
@@ -1249,3 +1787,1393 @@
1249
1787
  .planner-details::-webkit-scrollbar-thumb:hover {
1250
1788
  background: var(--planner-text-dim);
1251
1789
  }
1790
+
1791
+ /* =================================
1792
+ Materialization Status Section
1793
+ ================================= */
1794
+
1795
+ /* Status Header - Compact row with status + expand toggle */
1796
+ .materialization-header {
1797
+ display: flex;
1798
+ align-items: center;
1799
+ justify-content: space-between;
1800
+ padding: 8px 10px;
1801
+ margin-top: 8px;
1802
+ background: var(--planner-bg);
1803
+ border: 1px solid var(--planner-border);
1804
+ border-radius: var(--radius-sm);
1805
+ transition: all 0.15s ease;
1806
+ }
1807
+
1808
+ .materialization-header.clickable {
1809
+ cursor: pointer;
1810
+ }
1811
+
1812
+ .materialization-header.clickable:hover {
1813
+ background: var(--planner-surface-hover);
1814
+ border-color: var(--accent-primary);
1815
+ }
1816
+
1817
+ .materialization-status {
1818
+ display: flex;
1819
+ align-items: center;
1820
+ gap: 6px;
1821
+ font-size: 11px;
1822
+ }
1823
+
1824
+ .status-indicator {
1825
+ font-size: 10px;
1826
+ line-height: 1;
1827
+ }
1828
+
1829
+ .status-text {
1830
+ font-weight: 500;
1831
+ color: var(--planner-text);
1832
+ }
1833
+
1834
+ .status-separator {
1835
+ color: var(--planner-text-dim);
1836
+ margin: 0 2px;
1837
+ }
1838
+
1839
+ .schedule-summary {
1840
+ color: var(--planner-text-muted);
1841
+ font-size: 10px;
1842
+ }
1843
+
1844
+ /* Status Colors */
1845
+ .status-not-planned {
1846
+ color: var(--planner-text-dim);
1847
+ }
1848
+
1849
+ .status-materialized {
1850
+ color: var(--accent-success);
1851
+ }
1852
+
1853
+ .status-compatible {
1854
+ color: var(--accent-warning);
1855
+ }
1856
+
1857
+ .status-compatible-materialized {
1858
+ color: var(--accent-success);
1859
+ }
1860
+
1861
+ /* Compatible pre-agg note */
1862
+ .compatible-preagg-note {
1863
+ display: flex;
1864
+ align-items: flex-start;
1865
+ gap: 8px;
1866
+ padding: 10px 12px;
1867
+ margin-bottom: 12px;
1868
+ background: rgba(59, 130, 246, 0.08);
1869
+ border: 1px solid rgba(59, 130, 246, 0.2);
1870
+ border-radius: var(--radius-sm);
1871
+ font-size: 11px;
1872
+ line-height: 1.5;
1873
+ color: var(--planner-text-muted);
1874
+ }
1875
+
1876
+ .compatible-preagg-note .note-icon {
1877
+ flex-shrink: 0;
1878
+ }
1879
+
1880
+ .compatible-preagg-note strong {
1881
+ color: var(--planner-text);
1882
+ font-weight: 600;
1883
+ }
1884
+
1885
+ .status-pending {
1886
+ color: var(--accent-warning);
1887
+ }
1888
+
1889
+ .status-running {
1890
+ color: var(--accent-primary);
1891
+ }
1892
+
1893
+ .status-failed {
1894
+ color: var(--accent-error);
1895
+ }
1896
+
1897
+ /* Expand Toggle Button */
1898
+ .expand-toggle {
1899
+ background: transparent;
1900
+ border: none;
1901
+ padding: 2px 6px;
1902
+ font-size: 10px;
1903
+ color: var(--planner-text-muted);
1904
+ cursor: pointer;
1905
+ border-radius: var(--radius-sm);
1906
+ transition: all 0.15s ease;
1907
+ }
1908
+
1909
+ .expand-toggle:hover {
1910
+ background: var(--planner-border);
1911
+ color: var(--planner-text);
1912
+ }
1913
+
1914
+ /* Expandable Materialization Details */
1915
+ .materialization-details {
1916
+ margin-top: 8px;
1917
+ padding: 10px 12px;
1918
+ background: var(--planner-surface);
1919
+ border: 1px solid var(--planner-border);
1920
+ border-radius: var(--radius-sm);
1921
+ animation: slideDown 0.15s ease-out;
1922
+ }
1923
+
1924
+ @keyframes slideDown {
1925
+ from {
1926
+ opacity: 0;
1927
+ transform: translateY(-8px);
1928
+ }
1929
+ to {
1930
+ opacity: 1;
1931
+ transform: translateY(0);
1932
+ }
1933
+ }
1934
+
1935
+ /* Config Rows */
1936
+ .materialization-config {
1937
+ display: flex;
1938
+ flex-direction: column;
1939
+ gap: 6px;
1940
+ margin-bottom: 12px;
1941
+ }
1942
+
1943
+ .config-row {
1944
+ display: flex;
1945
+ align-items: center;
1946
+ gap: 8px;
1947
+ font-size: 11px;
1948
+ }
1949
+
1950
+ .config-label {
1951
+ color: var(--planner-text-muted);
1952
+ min-width: 70px;
1953
+ }
1954
+
1955
+ .config-value {
1956
+ color: var(--planner-text);
1957
+ font-weight: 500;
1958
+ }
1959
+
1960
+ .config-value.config-mono {
1961
+ font-family: var(--font-display);
1962
+ font-size: 10px;
1963
+ background: var(--planner-bg);
1964
+ padding: 2px 6px;
1965
+ border-radius: var(--radius-sm);
1966
+ }
1967
+
1968
+ .run-status {
1969
+ font-size: 10px;
1970
+ }
1971
+
1972
+ .run-status.success {
1973
+ color: var(--accent-success);
1974
+ }
1975
+
1976
+ .run-status.failed {
1977
+ color: var(--accent-error);
1978
+ }
1979
+
1980
+ /* Workflow Links */
1981
+ .workflow-links {
1982
+ display: flex;
1983
+ flex-direction: row;
1984
+ gap: 4px;
1985
+ }
1986
+
1987
+ .workflow-link {
1988
+ display: inline-flex;
1989
+ align-items: center;
1990
+ gap: 4px;
1991
+ color: var(--accent-primary);
1992
+ font-size: 11px;
1993
+ font-weight: 500;
1994
+ text-decoration: none;
1995
+ transition: color 0.15s ease;
1996
+ }
1997
+
1998
+ .workflow-link:hover {
1999
+ color: var(--accent-primary);
2000
+ text-decoration: underline;
2001
+ }
2002
+
2003
+ .workflow-link .link-icon {
2004
+ font-size: 10px;
2005
+ opacity: 0.7;
2006
+ }
2007
+
2008
+ /* Action Buttons */
2009
+ .materialization-actions {
2010
+ display: flex;
2011
+ gap: 8px;
2012
+ padding-top: 10px;
2013
+ border-top: 1px solid var(--planner-border);
2014
+ }
2015
+
2016
+ .action-btn {
2017
+ padding: 6px 12px;
2018
+ font-size: 11px;
2019
+ font-weight: 500;
2020
+ border-radius: var(--radius-sm);
2021
+ cursor: pointer;
2022
+ transition: all 0.15s ease;
2023
+ border: 1px solid var(--planner-border);
2024
+ background: var(--planner-surface);
2025
+ color: var(--planner-text);
2026
+ }
2027
+
2028
+ .action-btn:hover {
2029
+ background: var(--planner-surface-hover);
2030
+ }
2031
+
2032
+ .action-btn-primary {
2033
+ background: var(--accent-primary);
2034
+ border-color: var(--accent-primary);
2035
+ color: white;
2036
+ }
2037
+
2038
+ .action-btn-primary:hover {
2039
+ background: #2563eb;
2040
+ border-color: #2563eb;
2041
+ }
2042
+
2043
+ .action-btn-primary:disabled {
2044
+ background: #93c5fd;
2045
+ border-color: #93c5fd;
2046
+ cursor: not-allowed;
2047
+ opacity: 0.8;
2048
+ }
2049
+
2050
+ .action-btn-secondary {
2051
+ background: transparent;
2052
+ border-color: var(--planner-border);
2053
+ color: var(--planner-text-muted);
2054
+ }
2055
+
2056
+ .action-btn-danger {
2057
+ background: transparent;
2058
+ border-color: #ef4444;
2059
+ color: #ef4444;
2060
+ }
2061
+
2062
+ .action-btn-danger:hover {
2063
+ background: rgba(239, 68, 68, 0.1);
2064
+ border-color: #dc2626;
2065
+ color: #dc2626;
2066
+ }
2067
+
2068
+ .action-btn-danger:disabled {
2069
+ opacity: 0.5;
2070
+ cursor: not-allowed;
2071
+ }
2072
+
2073
+ .action-btn-secondary:hover {
2074
+ background: var(--planner-surface-hover);
2075
+ color: var(--planner-text);
2076
+ }
2077
+
2078
+ .action-btn-small {
2079
+ padding: 4px 10px;
2080
+ font-size: 10px;
2081
+ }
2082
+
2083
+ /* =================================
2084
+ Plan Materialization CTA
2085
+ ================================= */
2086
+
2087
+ .plan-materialization-cta {
2088
+ display: flex;
2089
+ align-items: center;
2090
+ justify-content: space-between;
2091
+ gap: 16px;
2092
+ padding: 16px 20px;
2093
+ margin: 12px 0;
2094
+ background: linear-gradient(
2095
+ 135deg,
2096
+ rgba(59, 130, 246, 0.08) 0%,
2097
+ rgba(139, 92, 246, 0.08) 100%
2098
+ );
2099
+ border: 1px solid rgba(59, 130, 246, 0.2);
2100
+ border-radius: var(--radius-md);
2101
+ transition: all 0.2s ease;
2102
+ }
2103
+
2104
+ .plan-materialization-cta:hover {
2105
+ border-color: rgba(59, 130, 246, 0.4);
2106
+ background: linear-gradient(
2107
+ 135deg,
2108
+ rgba(59, 130, 246, 0.12) 0%,
2109
+ rgba(139, 92, 246, 0.12) 100%
2110
+ );
2111
+ }
2112
+
2113
+ .cta-content {
2114
+ display: flex;
2115
+ align-items: center;
2116
+ gap: 12px;
2117
+ }
2118
+
2119
+ .cta-icon {
2120
+ font-size: 24px;
2121
+ filter: grayscale(0%);
2122
+ }
2123
+
2124
+ .cta-text {
2125
+ display: flex;
2126
+ flex-direction: column;
2127
+ gap: 2px;
2128
+ }
2129
+
2130
+ .cta-text strong {
2131
+ font-size: 13px;
2132
+ font-weight: 600;
2133
+ color: var(--planner-text);
2134
+ }
2135
+
2136
+ .cta-text span {
2137
+ font-size: 12px;
2138
+ color: var(--planner-text-muted);
2139
+ }
2140
+
2141
+ .plan-materialization-cta .action-btn-primary {
2142
+ flex-shrink: 0;
2143
+ padding: 8px 16px;
2144
+ font-size: 12px;
2145
+ font-weight: 600;
2146
+ }
2147
+
2148
+ /* =================================
2149
+ Materialization Config Form
2150
+ ================================= */
2151
+
2152
+ .materialization-config-form {
2153
+ margin-top: 8px;
2154
+ background: var(--planner-surface);
2155
+ border: 1px solid var(--accent-primary);
2156
+ border-radius: var(--radius-sm);
2157
+ overflow: hidden;
2158
+ animation: slideDown 0.15s ease-out;
2159
+ }
2160
+
2161
+ .config-form-header {
2162
+ display: flex;
2163
+ justify-content: space-between;
2164
+ align-items: center;
2165
+ padding: 8px 12px;
2166
+ background: rgba(59, 130, 246, 0.1);
2167
+ border-bottom: 1px solid var(--planner-border);
2168
+ font-size: 11px;
2169
+ font-weight: 600;
2170
+ color: var(--accent-primary);
2171
+ }
2172
+
2173
+ .config-close-btn {
2174
+ background: transparent;
2175
+ border: none;
2176
+ font-size: 16px;
2177
+ color: var(--planner-text-muted);
2178
+ cursor: pointer;
2179
+ padding: 0;
2180
+ line-height: 1;
2181
+ }
2182
+
2183
+ .config-form-note {
2184
+ padding: 8px 12px;
2185
+ background: rgba(217, 119, 6, 0.1);
2186
+ border-bottom: 1px solid rgba(217, 119, 6, 0.2);
2187
+ font-size: 10px;
2188
+ color: var(--accent-warning);
2189
+ line-height: 1.4;
2190
+ }
2191
+
2192
+ .config-close-btn:hover {
2193
+ color: var(--planner-text);
2194
+ }
2195
+
2196
+ .config-form-body {
2197
+ padding: 12px;
2198
+ display: flex;
2199
+ flex-direction: column;
2200
+ gap: 12px;
2201
+ }
2202
+
2203
+ .config-form-row {
2204
+ display: flex;
2205
+ flex-direction: column;
2206
+ gap: 6px;
2207
+ }
2208
+
2209
+ .config-form-label {
2210
+ font-size: 10px;
2211
+ font-weight: 600;
2212
+ text-transform: uppercase;
2213
+ letter-spacing: 0.5px;
2214
+ color: var(--planner-text-muted);
2215
+ }
2216
+
2217
+ .config-form-options {
2218
+ display: flex;
2219
+ gap: 12px;
2220
+ }
2221
+
2222
+ .radio-option {
2223
+ display: flex;
2224
+ align-items: center;
2225
+ gap: 6px;
2226
+ font-size: 11px;
2227
+ color: var(--planner-text);
2228
+ cursor: pointer;
2229
+ }
2230
+
2231
+ .radio-option input[type='radio'] {
2232
+ margin: 0;
2233
+ accent-color: var(--accent-primary);
2234
+ }
2235
+
2236
+ .radio-option.disabled {
2237
+ opacity: 0.5;
2238
+ cursor: not-allowed;
2239
+ }
2240
+
2241
+ .radio-option.disabled input[type='radio'] {
2242
+ cursor: not-allowed;
2243
+ }
2244
+
2245
+ .option-hint {
2246
+ font-size: 10px;
2247
+ color: var(--planner-text-dim);
2248
+ font-style: italic;
2249
+ margin-left: 4px;
2250
+ }
2251
+
2252
+ .partition-badge {
2253
+ display: inline-block;
2254
+ font-size: 10px;
2255
+ font-weight: 500;
2256
+ color: #065f46;
2257
+ background: #f5fffa;
2258
+ border: 1px solid #a7f3d0;
2259
+ padding: 2px 6px;
2260
+ border-radius: 4px;
2261
+ margin-left: 6px;
2262
+ }
2263
+
2264
+ .config-form-input {
2265
+ padding: 6px 10px;
2266
+ font-size: 11px;
2267
+ border: 1px solid var(--planner-border);
2268
+ border-radius: var(--radius-sm);
2269
+ background: var(--planner-bg);
2270
+ color: var(--planner-text);
2271
+ font-family: var(--font-display);
2272
+ }
2273
+
2274
+ .config-form-input:focus {
2275
+ outline: none;
2276
+ border-color: var(--accent-primary);
2277
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
2278
+ }
2279
+
2280
+ .config-form-input::placeholder {
2281
+ color: var(--planner-text-dim);
2282
+ }
2283
+
2284
+ .config-form-actions {
2285
+ display: flex;
2286
+ justify-content: flex-end;
2287
+ gap: 8px;
2288
+ padding: 10px 12px;
2289
+ border-top: 1px solid var(--planner-border);
2290
+ background: var(--planner-bg);
2291
+ }
2292
+
2293
+ .action-btn:disabled {
2294
+ opacity: 0.6;
2295
+ cursor: not-allowed;
2296
+ }
2297
+
2298
+ /* Loading Spinner */
2299
+ .spinner {
2300
+ display: inline-block;
2301
+ width: 12px;
2302
+ height: 12px;
2303
+ border: 2px solid currentColor;
2304
+ border-right-color: transparent;
2305
+ border-radius: 50%;
2306
+ animation: spinner-rotate 0.75s linear infinite;
2307
+ margin-right: 6px;
2308
+ vertical-align: middle;
2309
+ }
2310
+
2311
+ @keyframes spinner-rotate {
2312
+ from {
2313
+ transform: rotate(0deg);
2314
+ }
2315
+ to {
2316
+ transform: rotate(360deg);
2317
+ }
2318
+ }
2319
+
2320
+ /* Partition Setup Inline Form */
2321
+ .partition-setup-link {
2322
+ background: none;
2323
+ border: none;
2324
+ color: var(--accent-primary);
2325
+ font-size: 11px;
2326
+ cursor: pointer;
2327
+ padding: 2px 6px;
2328
+ margin-left: 8px;
2329
+ border-radius: var(--radius-sm);
2330
+ transition: background 0.15s ease;
2331
+ }
2332
+
2333
+ .partition-setup-link:hover {
2334
+ background: rgba(59, 130, 246, 0.1);
2335
+ text-decoration: underline;
2336
+ }
2337
+
2338
+ .partition-setup-form {
2339
+ margin: 8px 0;
2340
+ padding: 10px;
2341
+ background: #fefce8;
2342
+ border: 1px solid #fde68a;
2343
+ border-radius: var(--radius-md);
2344
+ }
2345
+
2346
+ .partition-setup-header {
2347
+ display: flex;
2348
+ align-items: center;
2349
+ gap: 6px;
2350
+ font-size: 11px;
2351
+ font-weight: 500;
2352
+ color: #a16207;
2353
+ margin-bottom: 8px;
2354
+ }
2355
+
2356
+ .partition-setup-icon {
2357
+ font-size: 12px;
2358
+ }
2359
+
2360
+ .partition-setup-error {
2361
+ padding: 6px 10px;
2362
+ background: #fef2f2;
2363
+ border: 1px solid #fecaca;
2364
+ border-radius: var(--radius-sm);
2365
+ color: #dc2626;
2366
+ font-size: 11px;
2367
+ margin-bottom: 8px;
2368
+ }
2369
+
2370
+ .partition-setup-body {
2371
+ display: flex;
2372
+ flex-direction: column;
2373
+ gap: 8px;
2374
+ }
2375
+
2376
+ .partition-setup-row {
2377
+ display: flex;
2378
+ flex-direction: column;
2379
+ gap: 3px;
2380
+ }
2381
+
2382
+ .partition-setup-row label {
2383
+ font-size: 10px;
2384
+ font-weight: 600;
2385
+ text-transform: uppercase;
2386
+ letter-spacing: 0.4px;
2387
+ color: #a16207;
2388
+ }
2389
+
2390
+ .partition-setup-row select,
2391
+ .partition-setup-row input[type='text'] {
2392
+ padding: 6px 8px;
2393
+ font-size: 12px;
2394
+ border: 1px solid #fde68a;
2395
+ border-radius: var(--radius-sm);
2396
+ background: white;
2397
+ color: var(--planner-text);
2398
+ }
2399
+
2400
+ .partition-setup-row select:focus,
2401
+ .partition-setup-row input[type='text']:focus {
2402
+ outline: none;
2403
+ border-color: #fbbf24;
2404
+ box-shadow: 0 0 0 2px rgba(251, 191, 36, 0.15);
2405
+ }
2406
+
2407
+ .partition-setup-row .readonly-value {
2408
+ font-size: 12px;
2409
+ font-family: var(--font-display);
2410
+ color: var(--planner-text);
2411
+ padding: 2px 0;
2412
+ }
2413
+
2414
+ .partition-setup-row-inline {
2415
+ flex-direction: row;
2416
+ gap: 10px;
2417
+ }
2418
+
2419
+ .partition-setup-row-inline .partition-field {
2420
+ flex: 1;
2421
+ display: flex;
2422
+ flex-direction: column;
2423
+ gap: 3px;
2424
+ }
2425
+
2426
+ .partition-setup-row-inline .partition-field:first-child {
2427
+ flex: 0 0 auto;
2428
+ }
2429
+
2430
+ .partition-setup-row-inline .partition-field select,
2431
+ .partition-setup-row-inline .partition-field input[type='text'] {
2432
+ width: 100%;
2433
+ }
2434
+
2435
+ .partition-setup-hint {
2436
+ font-size: 10px;
2437
+ color: #ca8a04;
2438
+ font-style: italic;
2439
+ }
2440
+
2441
+ /* Multi-node partition setup */
2442
+ .partition-node-section {
2443
+ padding: 8px;
2444
+ background: white;
2445
+ border: 1px solid #fde68a;
2446
+ border-radius: var(--radius-sm);
2447
+ margin-bottom: 8px;
2448
+ }
2449
+
2450
+ .partition-node-section:last-child {
2451
+ margin-bottom: 0;
2452
+ }
2453
+
2454
+ .partition-node-header {
2455
+ margin-bottom: 6px;
2456
+ }
2457
+
2458
+ .partition-node-name {
2459
+ display: flex;
2460
+ align-items: center;
2461
+ gap: 6px;
2462
+ font-size: 12px;
2463
+ font-weight: 600;
2464
+ color: #a16207;
2465
+ }
2466
+
2467
+ .partition-node-icon {
2468
+ font-size: 11px;
2469
+ }
2470
+
2471
+ .partition-node-done .partition-node-name {
2472
+ color: #166534;
2473
+ }
2474
+
2475
+ .partition-node-done .partition-node-icon {
2476
+ color: #22c55e;
2477
+ }
2478
+
2479
+ .partition-node-status {
2480
+ display: flex;
2481
+ align-items: center;
2482
+ gap: 8px;
2483
+ }
2484
+
2485
+ .partition-node-form {
2486
+ display: flex;
2487
+ align-items: flex-end;
2488
+ gap: 8px;
2489
+ }
2490
+
2491
+ .partition-node-form .partition-field {
2492
+ display: flex;
2493
+ flex-direction: column;
2494
+ gap: 2px;
2495
+ }
2496
+
2497
+ .partition-node-form .partition-field:first-child {
2498
+ flex: 1;
2499
+ }
2500
+
2501
+ .partition-node-form .partition-field-small {
2502
+ flex: 0 0 auto;
2503
+ }
2504
+
2505
+ .partition-node-form .partition-field label {
2506
+ font-size: 9px;
2507
+ font-weight: 600;
2508
+ text-transform: uppercase;
2509
+ letter-spacing: 0.3px;
2510
+ color: #a16207;
2511
+ }
2512
+
2513
+ .partition-node-form .partition-field select,
2514
+ .partition-node-form .partition-field input[type='text'] {
2515
+ padding: 4px 6px;
2516
+ font-size: 11px;
2517
+ border: 1px solid #fde68a;
2518
+ border-radius: var(--radius-sm);
2519
+ background: white;
2520
+ color: var(--planner-text);
2521
+ }
2522
+
2523
+ .partition-node-form .partition-field select:focus,
2524
+ .partition-node-form .partition-field input[type='text']:focus {
2525
+ outline: none;
2526
+ border-color: #fbbf24;
2527
+ box-shadow: 0 0 0 2px rgba(251, 191, 36, 0.15);
2528
+ }
2529
+
2530
+ .partition-node-form .partition-field input[type='text'] {
2531
+ width: 80px;
2532
+ }
2533
+
2534
+ .partition-set-btn {
2535
+ padding: 4px 10px;
2536
+ font-size: 11px;
2537
+ font-weight: 500;
2538
+ background: #eab308;
2539
+ border: 1px solid #ca8a04;
2540
+ border-radius: var(--radius-sm);
2541
+ color: white;
2542
+ cursor: pointer;
2543
+ transition: background 0.15s ease;
2544
+ white-space: nowrap;
2545
+ }
2546
+
2547
+ .partition-set-btn:hover:not(:disabled) {
2548
+ background: #ca8a04;
2549
+ }
2550
+
2551
+ .partition-set-btn:disabled {
2552
+ opacity: 0.6;
2553
+ cursor: not-allowed;
2554
+ }
2555
+
2556
+ .partition-setup-actions {
2557
+ display: flex;
2558
+ justify-content: flex-end;
2559
+ gap: 6px;
2560
+ margin-top: 6px;
2561
+ padding-top: 8px;
2562
+ border-top: 1px solid #fde68a;
2563
+ }
2564
+
2565
+ .partition-setup-actions .button-secondary {
2566
+ padding: 5px 10px;
2567
+ font-size: 11px;
2568
+ background: white;
2569
+ border: 1px solid #d1d5db;
2570
+ border-radius: var(--radius-sm);
2571
+ color: var(--planner-text);
2572
+ cursor: pointer;
2573
+ transition: background 0.15s ease;
2574
+ }
2575
+
2576
+ .partition-setup-actions .button-secondary:hover {
2577
+ background: #f3f4f6;
2578
+ }
2579
+
2580
+ .partition-setup-actions .button-primary {
2581
+ padding: 5px 10px;
2582
+ font-size: 11px;
2583
+ background: #ffefd0;
2584
+ border: 1px solid #cccccc;
2585
+ border-radius: var(--radius-sm);
2586
+ color: #a96621;
2587
+ font-weight: 500;
2588
+ cursor: pointer;
2589
+ transition: background 0.15s ease;
2590
+ }
2591
+
2592
+ .partition-setup-actions .button-primary:hover:not(:disabled) {
2593
+ background: #ffe4b3;
2594
+ }
2595
+
2596
+ .partition-setup-actions .button-primary:disabled {
2597
+ opacity: 0.6;
2598
+ cursor: not-allowed;
2599
+ }
2600
+
2601
+ /* Backfill Modal */
2602
+ .backfill-modal-overlay {
2603
+ position: fixed;
2604
+ top: 0;
2605
+ left: 0;
2606
+ right: 0;
2607
+ bottom: 0;
2608
+ background: rgba(0, 0, 0, 0.5);
2609
+ display: flex;
2610
+ align-items: center;
2611
+ justify-content: center;
2612
+ z-index: 1000;
2613
+ }
2614
+
2615
+ .backfill-modal {
2616
+ background: var(--planner-surface);
2617
+ border-radius: var(--radius-lg);
2618
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
2619
+ width: 400px;
2620
+ max-width: 90vw;
2621
+ }
2622
+
2623
+ .backfill-modal-header {
2624
+ display: flex;
2625
+ justify-content: space-between;
2626
+ align-items: center;
2627
+ padding: 16px 20px;
2628
+ border-bottom: 1px solid var(--planner-border);
2629
+ }
2630
+
2631
+ .backfill-modal-header h3 {
2632
+ font-size: 14px;
2633
+ font-weight: 600;
2634
+ color: var(--planner-text);
2635
+ margin: 0;
2636
+ }
2637
+
2638
+ .modal-close {
2639
+ background: none;
2640
+ border: none;
2641
+ font-size: 20px;
2642
+ color: var(--planner-text-muted);
2643
+ cursor: pointer;
2644
+ padding: 0;
2645
+ line-height: 1;
2646
+ }
2647
+
2648
+ .modal-close:hover {
2649
+ color: var(--planner-text);
2650
+ }
2651
+
2652
+ .backfill-modal-body {
2653
+ padding: 20px;
2654
+ display: flex;
2655
+ flex-direction: column;
2656
+ gap: 16px;
2657
+ }
2658
+
2659
+ .backfill-description {
2660
+ font-size: 13px;
2661
+ color: var(--planner-text);
2662
+ margin: 0;
2663
+ }
2664
+
2665
+ .backfill-steps {
2666
+ margin: 0;
2667
+ padding-left: 20px;
2668
+ font-size: 12px;
2669
+ color: var(--planner-text-muted);
2670
+ }
2671
+
2672
+ .backfill-steps li {
2673
+ margin-bottom: 6px;
2674
+ }
2675
+
2676
+ .backfill-form-row {
2677
+ display: flex;
2678
+ flex-direction: column;
2679
+ gap: 6px;
2680
+ }
2681
+
2682
+ .backfill-form-row label {
2683
+ font-size: 11px;
2684
+ font-weight: 600;
2685
+ text-transform: uppercase;
2686
+ letter-spacing: 0.5px;
2687
+ color: var(--planner-text-muted);
2688
+ }
2689
+
2690
+ .backfill-form-row input[type='date'] {
2691
+ padding: 8px 12px;
2692
+ font-size: 12px;
2693
+ border: 1px solid var(--planner-border);
2694
+ border-radius: var(--radius-sm);
2695
+ background: var(--planner-bg);
2696
+ color: var(--planner-text);
2697
+ font-family: var(--font-base);
2698
+ }
2699
+
2700
+ .backfill-form-row input[type='date']:focus {
2701
+ outline: none;
2702
+ border-color: var(--accent-primary);
2703
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
2704
+ }
2705
+
2706
+ /* Simple date inputs for cube backfill */
2707
+ .backfill-date-inputs {
2708
+ display: flex;
2709
+ gap: 16px;
2710
+ margin-top: 16px;
2711
+ }
2712
+
2713
+ .date-input-group {
2714
+ display: flex;
2715
+ flex-direction: column;
2716
+ gap: 6px;
2717
+ flex: 1;
2718
+ }
2719
+
2720
+ .date-input-group label {
2721
+ font-size: 12px;
2722
+ font-weight: 500;
2723
+ color: var(--planner-text-muted);
2724
+ }
2725
+
2726
+ .date-input-group input[type='date'] {
2727
+ padding: 8px 12px;
2728
+ font-size: 13px;
2729
+ border: 1px solid var(--planner-border);
2730
+ border-radius: var(--radius-sm);
2731
+ background: var(--planner-surface);
2732
+ color: var(--planner-text);
2733
+ }
2734
+
2735
+ .date-input-group input[type='date']:focus {
2736
+ outline: none;
2737
+ border-color: var(--accent-primary);
2738
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
2739
+ }
2740
+
2741
+ .backfill-modal-actions {
2742
+ display: flex;
2743
+ justify-content: flex-end;
2744
+ gap: 10px;
2745
+ padding: 16px 20px;
2746
+ border-top: 1px solid var(--planner-border);
2747
+ background: var(--planner-bg);
2748
+ border-radius: 0 0 var(--radius-lg) var(--radius-lg);
2749
+ }
2750
+
2751
+ /* Toast Message */
2752
+ .toast-message {
2753
+ position: fixed;
2754
+ bottom: 24px;
2755
+ right: 24px;
2756
+ background: var(--planner-surface);
2757
+ border: 1px solid var(--planner-border);
2758
+ border-radius: var(--radius-md);
2759
+ padding: 12px 16px;
2760
+ font-size: 12px;
2761
+ color: var(--planner-text);
2762
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
2763
+ display: flex;
2764
+ align-items: center;
2765
+ gap: 12px;
2766
+ z-index: 1001;
2767
+ animation: slideInUp 0.3s ease;
2768
+ }
2769
+
2770
+ .toast-message a {
2771
+ color: var(--accent-primary);
2772
+ text-decoration: none;
2773
+ font-weight: 500;
2774
+ }
2775
+
2776
+ .toast-message a:hover {
2777
+ text-decoration: underline;
2778
+ }
2779
+
2780
+ .toast-close {
2781
+ background: none;
2782
+ border: none;
2783
+ font-size: 16px;
2784
+ color: var(--planner-text-muted);
2785
+ cursor: pointer;
2786
+ padding: 0;
2787
+ line-height: 1;
2788
+ }
2789
+
2790
+ .toast-close:hover {
2791
+ color: var(--planner-text);
2792
+ }
2793
+
2794
+ @keyframes slideInUp {
2795
+ from {
2796
+ opacity: 0;
2797
+ transform: translateY(20px);
2798
+ }
2799
+ to {
2800
+ opacity: 1;
2801
+ transform: translateY(0);
2802
+ }
2803
+ }
2804
+
2805
+ /* Workflow link button style */
2806
+ a.action-btn {
2807
+ display: inline-flex;
2808
+ align-items: center;
2809
+ text-decoration: none;
2810
+ }
2811
+
2812
+ /* Section-level config form */
2813
+ .section-level-config {
2814
+ margin: 12px 0;
2815
+ border: 1px solid var(--accent-primary);
2816
+ border-radius: var(--radius-md);
2817
+ background: rgba(59, 130, 246, 0.03);
2818
+ }
2819
+
2820
+ .section-level-config .config-form-header {
2821
+ background: rgba(59, 130, 246, 0.08);
2822
+ border-bottom: 1px solid rgba(59, 130, 246, 0.15);
2823
+ }
2824
+
2825
+ /* Config form section (for grouped fields like Backfill) */
2826
+ .config-form-section {
2827
+ background: var(--planner-bg);
2828
+ border: 1px solid var(--planner-border);
2829
+ border-radius: var(--radius-sm);
2830
+ padding: 12px;
2831
+ margin: 4px 0;
2832
+ }
2833
+
2834
+ .config-form-section-label {
2835
+ display: block;
2836
+ font-size: 10px;
2837
+ font-weight: 600;
2838
+ text-transform: uppercase;
2839
+ letter-spacing: 0.5px;
2840
+ color: var(--planner-text-muted);
2841
+ margin-bottom: 10px;
2842
+ }
2843
+
2844
+ /* Backfill date range */
2845
+ .backfill-range {
2846
+ display: flex;
2847
+ gap: 16px;
2848
+ }
2849
+
2850
+ .backfill-field {
2851
+ flex: 1;
2852
+ display: flex;
2853
+ flex-direction: column;
2854
+ gap: 4px;
2855
+ }
2856
+
2857
+ .backfill-field label {
2858
+ font-size: 10px;
2859
+ color: var(--planner-text-muted);
2860
+ }
2861
+
2862
+ .backfill-field input[type='date'],
2863
+ .backfill-field select {
2864
+ padding: 6px 10px;
2865
+ font-size: 11px;
2866
+ border: 1px solid var(--planner-border);
2867
+ border-radius: var(--radius-sm);
2868
+ background: var(--planner-surface);
2869
+ color: var(--planner-text);
2870
+ }
2871
+
2872
+ .backfill-field input[type='date']:focus,
2873
+ .backfill-field select:focus {
2874
+ outline: none;
2875
+ border-color: var(--accent-primary);
2876
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
2877
+ }
2878
+
2879
+ /* Checkbox option */
2880
+ .checkbox-option {
2881
+ display: flex;
2882
+ align-items: center;
2883
+ gap: 8px;
2884
+ font-size: 11px;
2885
+ color: var(--planner-text);
2886
+ cursor: pointer;
2887
+ }
2888
+
2889
+ .checkbox-option input[type='checkbox'] {
2890
+ margin: 0;
2891
+ accent-color: var(--accent-primary);
2892
+ }
2893
+
2894
+ /* Config form select */
2895
+ .config-form-select {
2896
+ padding: 6px 10px;
2897
+ font-size: 11px;
2898
+ border: 1px solid var(--planner-border);
2899
+ border-radius: var(--radius-sm);
2900
+ background: var(--planner-surface);
2901
+ color: var(--planner-text);
2902
+ cursor: pointer;
2903
+ }
2904
+
2905
+ .config-form-select:focus {
2906
+ outline: none;
2907
+ border-color: var(--accent-primary);
2908
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
2909
+ }
2910
+
2911
+ /* Config form hint */
2912
+ .config-form-hint {
2913
+ display: block;
2914
+ font-size: 10px;
2915
+ color: var(--planner-text-dim);
2916
+ margin-top: 4px;
2917
+ font-style: italic;
2918
+ }
2919
+
2920
+ /* Config form section divider */
2921
+ .config-form-divider {
2922
+ display: flex;
2923
+ align-items: center;
2924
+ gap: 12px;
2925
+ margin: 16px 0 12px 0;
2926
+ font-size: 10px;
2927
+ font-weight: 600;
2928
+ text-transform: uppercase;
2929
+ letter-spacing: 0.5px;
2930
+ color: var(--planner-text-muted);
2931
+ }
2932
+
2933
+ .config-form-divider::before,
2934
+ .config-form-divider::after {
2935
+ content: '';
2936
+ flex: 1;
2937
+ height: 1px;
2938
+ background: var(--planner-border);
2939
+ }
2940
+
2941
+ /* Druid cube config section */
2942
+ .druid-cube-config {
2943
+ background: linear-gradient(
2944
+ 135deg,
2945
+ rgba(236, 72, 153, 0.03) 0%,
2946
+ rgba(168, 85, 247, 0.03) 100%
2947
+ );
2948
+ border-color: rgba(168, 85, 247, 0.2);
2949
+ margin-top: 8px;
2950
+ }
2951
+
2952
+ /* Druid cube preview */
2953
+ .druid-cube-preview {
2954
+ background: var(--planner-surface);
2955
+ border: 1px solid var(--planner-border);
2956
+ border-radius: var(--radius-sm);
2957
+ padding: 10px 12px;
2958
+ margin-top: 12px;
2959
+ }
2960
+
2961
+ .druid-cube-preview .preview-label {
2962
+ font-size: 10px;
2963
+ font-weight: 600;
2964
+ text-transform: uppercase;
2965
+ letter-spacing: 0.5px;
2966
+ color: var(--planner-text-muted);
2967
+ margin-bottom: 8px;
2968
+ }
2969
+
2970
+ .druid-cube-preview .preview-list {
2971
+ display: flex;
2972
+ flex-direction: column;
2973
+ gap: 4px;
2974
+ }
2975
+
2976
+ .druid-cube-preview .preview-item {
2977
+ display: flex;
2978
+ align-items: center;
2979
+ gap: 6px;
2980
+ font-size: 11px;
2981
+ }
2982
+
2983
+ .druid-cube-preview .preview-source {
2984
+ color: var(--planner-text);
2985
+ font-weight: 500;
2986
+ }
2987
+
2988
+ .druid-cube-preview .preview-grain {
2989
+ color: var(--planner-text-muted);
2990
+ font-size: 10px;
2991
+ }
2992
+
2993
+ .druid-cube-preview .preview-info {
2994
+ display: flex;
2995
+ align-items: flex-start;
2996
+ gap: 6px;
2997
+ margin-top: 10px;
2998
+ padding-top: 10px;
2999
+ border-top: 1px solid var(--planner-border);
3000
+ font-size: 10px;
3001
+ color: var(--planner-text-dim);
3002
+ font-style: italic;
3003
+ }
3004
+
3005
+ .druid-cube-preview .info-icon {
3006
+ flex-shrink: 0;
3007
+ }
3008
+
3009
+ /* Existing cube name display */
3010
+ .existing-cube-name {
3011
+ display: flex;
3012
+ align-items: center;
3013
+ gap: 8px;
3014
+ padding: 8px 12px;
3015
+ background: var(--planner-surface);
3016
+ border: 1px solid var(--planner-border);
3017
+ border-radius: var(--radius-sm);
3018
+ }
3019
+
3020
+ .existing-cube-name .cube-badge {
3021
+ font-size: 14px;
3022
+ }
3023
+
3024
+ .existing-cube-name code {
3025
+ font-size: 12px;
3026
+ font-weight: 500;
3027
+ color: var(--planner-text);
3028
+ }
3029
+
3030
+ /* Cube name input group (namespace.name) */
3031
+ .cube-name-input-group {
3032
+ display: flex;
3033
+ align-items: center;
3034
+ gap: 2px;
3035
+ }
3036
+
3037
+ .cube-name-input-group .namespace-input {
3038
+ flex: 1;
3039
+ min-width: 100px;
3040
+ }
3041
+
3042
+ .cube-name-input-group .namespace-separator {
3043
+ color: var(--planner-text-muted);
3044
+ font-weight: 600;
3045
+ font-size: 14px;
3046
+ padding: 0 2px;
3047
+ }
3048
+
3049
+ .cube-name-input-group .name-input {
3050
+ flex: 1.5;
3051
+ min-width: 120px;
3052
+ }
3053
+
3054
+ /* =================================
3055
+ Selected Chips (Metrics & Dimensions)
3056
+ ================================= */
3057
+
3058
+ .selected-chips-container {
3059
+ padding: 6px 10px;
3060
+ border-bottom: 1px solid var(--planner-border);
3061
+ background: var(--planner-bg);
3062
+ }
3063
+
3064
+ .selected-chips-wrapper {
3065
+ max-height: 54px; /* ~2 rows of chips */
3066
+ overflow: hidden;
3067
+ transition: max-height 0.2s ease;
3068
+ }
3069
+
3070
+ .selected-chips-wrapper.expanded {
3071
+ max-height: 200px;
3072
+ overflow-y: auto;
3073
+ }
3074
+
3075
+ .selected-chips {
3076
+ display: flex;
3077
+ flex-wrap: wrap;
3078
+ gap: 4px;
3079
+ }
3080
+
3081
+ .chips-toggle {
3082
+ display: flex;
3083
+ align-items: center;
3084
+ justify-content: center;
3085
+ gap: 4px;
3086
+ margin-top: 4px;
3087
+ padding: 2px 6px;
3088
+ background: transparent;
3089
+ border: none;
3090
+ color: var(--planner-text-muted);
3091
+ font-size: 9px;
3092
+ font-weight: 500;
3093
+ cursor: pointer;
3094
+ width: 100%;
3095
+ transition: color 0.15s ease;
3096
+ }
3097
+
3098
+ .chips-toggle:hover {
3099
+ color: var(--accent-primary);
3100
+ }
3101
+
3102
+ .chips-toggle-icon {
3103
+ font-size: 8px;
3104
+ }
3105
+
3106
+ .selected-chip {
3107
+ display: inline-flex;
3108
+ align-items: center;
3109
+ gap: 2px;
3110
+ padding: 2px 4px 2px 6px;
3111
+ border-radius: 3px;
3112
+ font-size: 10px;
3113
+ font-weight: 500;
3114
+ font-family: var(--font-display);
3115
+ transition: all 0.12s ease;
3116
+ max-width: 140px;
3117
+ }
3118
+
3119
+ .selected-chip .chip-label {
3120
+ overflow: hidden;
3121
+ text-overflow: ellipsis;
3122
+ white-space: nowrap;
3123
+ }
3124
+
3125
+ /* Metrics: Pink (matches node_type__metric background #fad7dd) */
3126
+ .selected-chip.metric-chip {
3127
+ background: #fad7dd;
3128
+ color: #a2283e;
3129
+ border: 1px solid rgba(162, 40, 62, 0.3);
3130
+ }
3131
+
3132
+ .selected-chip.metric-chip:hover {
3133
+ background: #f5c4cd;
3134
+ border-color: rgba(162, 40, 62, 0.5);
3135
+ }
3136
+
3137
+ /* Dimensions: Golden orange (matches node_type__dimension background #ffefd0) */
3138
+ .selected-chip.dimension-chip {
3139
+ background: #ffefd0;
3140
+ color: #a96621;
3141
+ border: 1px solid rgba(169, 102, 33, 0.3);
3142
+ }
3143
+
3144
+ .selected-chip.dimension-chip:hover {
3145
+ background: #ffe4b3;
3146
+ border-color: rgba(169, 102, 33, 0.5);
3147
+ }
3148
+
3149
+ .chip-remove {
3150
+ display: flex;
3151
+ align-items: center;
3152
+ justify-content: center;
3153
+ width: 12px;
3154
+ height: 12px;
3155
+ padding: 0;
3156
+ background: transparent;
3157
+ border: none;
3158
+ border-radius: 2px;
3159
+ color: inherit;
3160
+ font-size: 12px;
3161
+ font-weight: 400;
3162
+ line-height: 1;
3163
+ cursor: pointer;
3164
+ opacity: 0.5;
3165
+ transition: all 0.12s ease;
3166
+ }
3167
+
3168
+ .chip-remove:hover {
3169
+ opacity: 1;
3170
+ background: rgba(0, 0, 0, 0.08);
3171
+ }
3172
+
3173
+ .metric-chip .chip-remove:hover {
3174
+ background: rgba(239, 68, 68, 0.15);
3175
+ }
3176
+
3177
+ .dimension-chip .chip-remove:hover {
3178
+ background: rgba(217, 119, 6, 0.15);
3179
+ }