@quantumwake/terminal-ux-dashboard-components 0.1.7 → 0.1.10
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/dist/index.cjs +404 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -7
- package/dist/index.d.ts +4 -7
- package/dist/index.js +406 -51
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ require('react-pivottable/pivottable.css');
|
|
|
12
12
|
var lucideReact = require('lucide-react');
|
|
13
13
|
var CodeMirror = require('@uiw/react-codemirror');
|
|
14
14
|
var langSql = require('@codemirror/lang-sql');
|
|
15
|
+
var autocomplete = require('@codemirror/autocomplete');
|
|
15
16
|
|
|
16
17
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
18
|
|
|
@@ -43,7 +44,9 @@ function useCapabilities() {
|
|
|
43
44
|
canRefine: !!c.refineDashboard,
|
|
44
45
|
canNew: !!c.newDashboard,
|
|
45
46
|
canAddPanel: !!c.addPanel,
|
|
46
|
-
canEditPanels: !!c.removePanel
|
|
47
|
+
canEditPanels: !!c.removePanel,
|
|
48
|
+
// Studio can recompute + persist a panel's precomputed result.
|
|
49
|
+
canRefresh: !!c.persistPanelData
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -645,6 +648,280 @@ function ChartStyleControls({ style, onChange }) {
|
|
|
645
648
|
] })
|
|
646
649
|
] });
|
|
647
650
|
}
|
|
651
|
+
var AGGREGATES = [
|
|
652
|
+
"count",
|
|
653
|
+
"count_if",
|
|
654
|
+
"sum",
|
|
655
|
+
"avg",
|
|
656
|
+
"min",
|
|
657
|
+
"max",
|
|
658
|
+
"median",
|
|
659
|
+
"mode",
|
|
660
|
+
"stddev",
|
|
661
|
+
"stddev_pop",
|
|
662
|
+
"stddev_samp",
|
|
663
|
+
"var_pop",
|
|
664
|
+
"var_samp",
|
|
665
|
+
"variance",
|
|
666
|
+
"quantile",
|
|
667
|
+
"quantile_cont",
|
|
668
|
+
"quantile_disc",
|
|
669
|
+
"approx_count_distinct",
|
|
670
|
+
"approx_quantile",
|
|
671
|
+
"arg_max",
|
|
672
|
+
"arg_min",
|
|
673
|
+
"first",
|
|
674
|
+
"last",
|
|
675
|
+
"product",
|
|
676
|
+
"bool_and",
|
|
677
|
+
"bool_or",
|
|
678
|
+
"bit_and",
|
|
679
|
+
"bit_or",
|
|
680
|
+
"bit_xor",
|
|
681
|
+
"string_agg",
|
|
682
|
+
"list",
|
|
683
|
+
"array_agg",
|
|
684
|
+
"histogram",
|
|
685
|
+
"corr",
|
|
686
|
+
"covar_pop",
|
|
687
|
+
"covar_samp",
|
|
688
|
+
"kurtosis",
|
|
689
|
+
"skewness",
|
|
690
|
+
"entropy",
|
|
691
|
+
"row_number",
|
|
692
|
+
"rank",
|
|
693
|
+
"dense_rank",
|
|
694
|
+
"percent_rank",
|
|
695
|
+
"cume_dist",
|
|
696
|
+
"ntile",
|
|
697
|
+
"lag",
|
|
698
|
+
"lead",
|
|
699
|
+
"first_value",
|
|
700
|
+
"last_value",
|
|
701
|
+
"nth_value"
|
|
702
|
+
];
|
|
703
|
+
var SCALARS = [
|
|
704
|
+
// string
|
|
705
|
+
"length",
|
|
706
|
+
"len",
|
|
707
|
+
"lower",
|
|
708
|
+
"upper",
|
|
709
|
+
"trim",
|
|
710
|
+
"ltrim",
|
|
711
|
+
"rtrim",
|
|
712
|
+
"substring",
|
|
713
|
+
"substr",
|
|
714
|
+
"concat",
|
|
715
|
+
"concat_ws",
|
|
716
|
+
"replace",
|
|
717
|
+
"reverse",
|
|
718
|
+
"repeat",
|
|
719
|
+
"lpad",
|
|
720
|
+
"rpad",
|
|
721
|
+
"left",
|
|
722
|
+
"right",
|
|
723
|
+
"contains",
|
|
724
|
+
"starts_with",
|
|
725
|
+
"ends_with",
|
|
726
|
+
"position",
|
|
727
|
+
"split_part",
|
|
728
|
+
"string_split",
|
|
729
|
+
"regexp_matches",
|
|
730
|
+
"regexp_replace",
|
|
731
|
+
"regexp_extract",
|
|
732
|
+
"regexp_full_match",
|
|
733
|
+
"regexp_split_to_array",
|
|
734
|
+
"format",
|
|
735
|
+
"printf",
|
|
736
|
+
"md5",
|
|
737
|
+
"sha256",
|
|
738
|
+
"levenshtein",
|
|
739
|
+
"jaccard",
|
|
740
|
+
"ascii",
|
|
741
|
+
"chr",
|
|
742
|
+
// date / time
|
|
743
|
+
"now",
|
|
744
|
+
"current_date",
|
|
745
|
+
"current_timestamp",
|
|
746
|
+
"today",
|
|
747
|
+
"date_trunc",
|
|
748
|
+
"date_part",
|
|
749
|
+
"date_diff",
|
|
750
|
+
"date_add",
|
|
751
|
+
"date_sub",
|
|
752
|
+
"age",
|
|
753
|
+
"strftime",
|
|
754
|
+
"strptime",
|
|
755
|
+
"epoch",
|
|
756
|
+
"epoch_ms",
|
|
757
|
+
"extract",
|
|
758
|
+
"make_date",
|
|
759
|
+
"make_time",
|
|
760
|
+
"make_timestamp",
|
|
761
|
+
"last_day",
|
|
762
|
+
"dayname",
|
|
763
|
+
"monthname",
|
|
764
|
+
"year",
|
|
765
|
+
"month",
|
|
766
|
+
"day",
|
|
767
|
+
"hour",
|
|
768
|
+
"minute",
|
|
769
|
+
"second",
|
|
770
|
+
"dayofweek",
|
|
771
|
+
"dayofyear",
|
|
772
|
+
"week",
|
|
773
|
+
"quarter",
|
|
774
|
+
"time_bucket",
|
|
775
|
+
// math
|
|
776
|
+
"abs",
|
|
777
|
+
"ceil",
|
|
778
|
+
"ceiling",
|
|
779
|
+
"floor",
|
|
780
|
+
"round",
|
|
781
|
+
"trunc",
|
|
782
|
+
"sign",
|
|
783
|
+
"mod",
|
|
784
|
+
"pow",
|
|
785
|
+
"power",
|
|
786
|
+
"sqrt",
|
|
787
|
+
"cbrt",
|
|
788
|
+
"exp",
|
|
789
|
+
"ln",
|
|
790
|
+
"log",
|
|
791
|
+
"log2",
|
|
792
|
+
"log10",
|
|
793
|
+
"greatest",
|
|
794
|
+
"least",
|
|
795
|
+
"gcd",
|
|
796
|
+
"lcm",
|
|
797
|
+
"factorial",
|
|
798
|
+
"random",
|
|
799
|
+
"pi",
|
|
800
|
+
"degrees",
|
|
801
|
+
"radians",
|
|
802
|
+
"sin",
|
|
803
|
+
"cos",
|
|
804
|
+
"tan",
|
|
805
|
+
"asin",
|
|
806
|
+
"acos",
|
|
807
|
+
"atan",
|
|
808
|
+
"atan2",
|
|
809
|
+
// conditional / null / cast
|
|
810
|
+
"coalesce",
|
|
811
|
+
"ifnull",
|
|
812
|
+
"nullif",
|
|
813
|
+
"nvl",
|
|
814
|
+
"if",
|
|
815
|
+
"try_cast",
|
|
816
|
+
"cast",
|
|
817
|
+
"typeof",
|
|
818
|
+
// list / struct / map / json
|
|
819
|
+
"list_value",
|
|
820
|
+
"list_aggregate",
|
|
821
|
+
"list_distinct",
|
|
822
|
+
"list_sort",
|
|
823
|
+
"list_reverse",
|
|
824
|
+
"list_slice",
|
|
825
|
+
"list_concat",
|
|
826
|
+
"list_contains",
|
|
827
|
+
"list_position",
|
|
828
|
+
"list_extract",
|
|
829
|
+
"list_transform",
|
|
830
|
+
"list_filter",
|
|
831
|
+
"unnest",
|
|
832
|
+
"array_length",
|
|
833
|
+
"array_to_string",
|
|
834
|
+
"struct_pack",
|
|
835
|
+
"struct_extract",
|
|
836
|
+
"map",
|
|
837
|
+
"map_keys",
|
|
838
|
+
"map_values",
|
|
839
|
+
"json_extract",
|
|
840
|
+
"json_extract_string",
|
|
841
|
+
"to_json",
|
|
842
|
+
"from_json",
|
|
843
|
+
"json_array_length",
|
|
844
|
+
"json_keys",
|
|
845
|
+
"generate_series",
|
|
846
|
+
"range"
|
|
847
|
+
];
|
|
848
|
+
var TYPES = [
|
|
849
|
+
"BOOLEAN",
|
|
850
|
+
"TINYINT",
|
|
851
|
+
"SMALLINT",
|
|
852
|
+
"INTEGER",
|
|
853
|
+
"BIGINT",
|
|
854
|
+
"HUGEINT",
|
|
855
|
+
"UTINYINT",
|
|
856
|
+
"USMALLINT",
|
|
857
|
+
"UINTEGER",
|
|
858
|
+
"UBIGINT",
|
|
859
|
+
"FLOAT",
|
|
860
|
+
"REAL",
|
|
861
|
+
"DOUBLE",
|
|
862
|
+
"DECIMAL",
|
|
863
|
+
"NUMERIC",
|
|
864
|
+
"VARCHAR",
|
|
865
|
+
"CHAR",
|
|
866
|
+
"TEXT",
|
|
867
|
+
"BLOB",
|
|
868
|
+
"BIT",
|
|
869
|
+
"DATE",
|
|
870
|
+
"TIME",
|
|
871
|
+
"TIMESTAMP",
|
|
872
|
+
"TIMESTAMPTZ",
|
|
873
|
+
"INTERVAL",
|
|
874
|
+
"UUID",
|
|
875
|
+
"JSON",
|
|
876
|
+
"LIST",
|
|
877
|
+
"ARRAY",
|
|
878
|
+
"STRUCT",
|
|
879
|
+
"MAP",
|
|
880
|
+
"UNION",
|
|
881
|
+
"ENUM"
|
|
882
|
+
];
|
|
883
|
+
var EXTRA_KEYWORDS = [
|
|
884
|
+
"QUALIFY",
|
|
885
|
+
"EXCLUDE",
|
|
886
|
+
"PIVOT",
|
|
887
|
+
"UNPIVOT",
|
|
888
|
+
"ASOF",
|
|
889
|
+
"POSITIONAL",
|
|
890
|
+
"SEMI",
|
|
891
|
+
"ANTI",
|
|
892
|
+
"SUMMARIZE",
|
|
893
|
+
"DISTINCT ON",
|
|
894
|
+
"GROUP BY ALL",
|
|
895
|
+
"ORDER BY ALL",
|
|
896
|
+
"USING SAMPLE"
|
|
897
|
+
];
|
|
898
|
+
function opts(labels, type, boost = 0) {
|
|
899
|
+
return labels.map((label) => ({ label, type, boost }));
|
|
900
|
+
}
|
|
901
|
+
var SNIPPETS = [
|
|
902
|
+
autocomplete.snippetCompletion("SELECT ${col}, count(*) AS n\nFROM data\nGROUP BY ${col}\nORDER BY n DESC", {
|
|
903
|
+
label: "group by count",
|
|
904
|
+
type: "snippet",
|
|
905
|
+
detail: "aggregate by column"
|
|
906
|
+
}),
|
|
907
|
+
autocomplete.snippetCompletion("SELECT *\nFROM data\nORDER BY ${col} DESC\nLIMIT 10", {
|
|
908
|
+
label: "top N",
|
|
909
|
+
type: "snippet",
|
|
910
|
+
detail: "order + limit"
|
|
911
|
+
}),
|
|
912
|
+
autocomplete.snippetCompletion("SELECT DISTINCT ${col}\nFROM data", {
|
|
913
|
+
label: "select distinct",
|
|
914
|
+
type: "snippet"
|
|
915
|
+
})
|
|
916
|
+
];
|
|
917
|
+
var duckdbCompletionSource = autocomplete.completeFromList([
|
|
918
|
+
...opts(AGGREGATES, "function", 1),
|
|
919
|
+
// boost aggregates slightly — common in analysis
|
|
920
|
+
...opts(SCALARS, "function"),
|
|
921
|
+
...opts(TYPES, "type"),
|
|
922
|
+
...opts(EXTRA_KEYWORDS, "keyword"),
|
|
923
|
+
...SNIPPETS
|
|
924
|
+
]);
|
|
648
925
|
var DEFAULT_SQL = "SELECT *\nFROM data\nLIMIT 100";
|
|
649
926
|
var renderCell = (v) => {
|
|
650
927
|
if (v == null) return "";
|
|
@@ -684,18 +961,32 @@ function SqlConsole({ columns = [], stateId, defaultColumnsOpen = false, default
|
|
|
684
961
|
void run();
|
|
685
962
|
};
|
|
686
963
|
const schemaKey = columns.map((c) => c.name).join(",");
|
|
687
|
-
const extensions = react.useMemo(
|
|
688
|
-
|
|
689
|
-
|
|
964
|
+
const extensions = react.useMemo(() => {
|
|
965
|
+
const sqlConfig = {
|
|
966
|
+
dialect: langSql.PostgreSQL,
|
|
967
|
+
schema: { data: columns.map((c) => c.name) },
|
|
968
|
+
defaultTable: "data",
|
|
969
|
+
upperCaseKeywords: true
|
|
970
|
+
};
|
|
971
|
+
return [
|
|
972
|
+
langSql.sql(sqlConfig),
|
|
973
|
+
autocomplete.autocompletion({
|
|
974
|
+
override: [
|
|
975
|
+
langSql.schemaCompletionSource(sqlConfig),
|
|
976
|
+
langSql.keywordCompletionSource(langSql.PostgreSQL, true),
|
|
977
|
+
duckdbCompletionSource
|
|
978
|
+
]
|
|
979
|
+
}),
|
|
690
980
|
CodeMirror.EditorView.lineWrapping,
|
|
691
|
-
CodeMirror.Prec.highest(CodeMirror.keymap.of([
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
981
|
+
CodeMirror.Prec.highest(CodeMirror.keymap.of([
|
|
982
|
+
{ key: "Mod-Enter", run: () => {
|
|
983
|
+
runRef.current();
|
|
984
|
+
return true;
|
|
985
|
+
} },
|
|
986
|
+
{ key: "Tab", run: autocomplete.acceptCompletion }
|
|
987
|
+
]))
|
|
988
|
+
];
|
|
989
|
+
}, [schemaKey]);
|
|
699
990
|
const resultColumns = result?.columns || [];
|
|
700
991
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
|
|
701
992
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `border-b ${theme.border} bg-midnight-elevated p-3 shrink-0`, children: [
|
|
@@ -725,7 +1016,7 @@ function SqlConsole({ columns = [], stateId, defaultColumnsOpen = false, default
|
|
|
725
1016
|
onChange: setSql,
|
|
726
1017
|
extensions,
|
|
727
1018
|
theme: "dark",
|
|
728
|
-
basicSetup: { lineNumbers: false, foldGutter: false, highlightActiveLine: false },
|
|
1019
|
+
basicSetup: { lineNumbers: false, foldGutter: false, highlightActiveLine: false, autocompletion: false },
|
|
729
1020
|
height: "120px",
|
|
730
1021
|
placeholder: "SELECT ... FROM data",
|
|
731
1022
|
className: "border border-midnight-border text-sm overflow-hidden focus-within:border-midnight-accent"
|
|
@@ -1057,6 +1348,7 @@ var ChartPreview = ({
|
|
|
1057
1348
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-sm text-midnight-text-muted", children: "Select a chart type" });
|
|
1058
1349
|
}
|
|
1059
1350
|
};
|
|
1351
|
+
var MAX_PRECOMPUTE_ROWS = 5e3;
|
|
1060
1352
|
function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
1061
1353
|
const { theme, runQuery } = useDashboard();
|
|
1062
1354
|
const runQueryRef = react.useRef(runQuery);
|
|
@@ -1185,6 +1477,10 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1185
1477
|
config.chartType = chartType;
|
|
1186
1478
|
if (filters.length) config.filters = filters;
|
|
1187
1479
|
if (yFields.length) config.yFields = yFields.map((f) => ({ name: f.name, agg: f.agg }));
|
|
1480
|
+
if (sqlRows && sqlRows.length <= MAX_PRECOMPUTE_ROWS) {
|
|
1481
|
+
config.data = sqlRows;
|
|
1482
|
+
config.refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1483
|
+
}
|
|
1188
1484
|
}
|
|
1189
1485
|
config.style = style;
|
|
1190
1486
|
onSave({
|
|
@@ -1389,70 +1685,129 @@ function ViewLoading() {
|
|
|
1389
1685
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "Loading..." });
|
|
1390
1686
|
}
|
|
1391
1687
|
function SqlPanel({ panel }) {
|
|
1392
|
-
const { runQuery } = useDashboard();
|
|
1688
|
+
const { runQuery, persistPanelData } = useDashboard();
|
|
1689
|
+
const { canRefresh } = useCapabilities();
|
|
1393
1690
|
const runQueryRef = react.useRef(runQuery);
|
|
1394
1691
|
runQueryRef.current = runQuery;
|
|
1395
1692
|
const config = panel.config || {};
|
|
1396
1693
|
const chartType = config.chartType || panel.type;
|
|
1397
|
-
const
|
|
1694
|
+
const precomputed = config.data;
|
|
1695
|
+
const [rows, setRows] = react.useState(precomputed ?? null);
|
|
1398
1696
|
const [error, setError] = react.useState(null);
|
|
1399
|
-
const [loading, setLoading] = react.useState(
|
|
1697
|
+
const [loading, setLoading] = react.useState(!precomputed && canRefresh);
|
|
1698
|
+
const [refreshing, setRefreshing] = react.useState(false);
|
|
1400
1699
|
react.useEffect(() => {
|
|
1700
|
+
if (precomputed) {
|
|
1701
|
+
setRows(precomputed);
|
|
1702
|
+
setLoading(false);
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
if (!canRefresh) {
|
|
1706
|
+
setLoading(false);
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1401
1709
|
let cancelled = false;
|
|
1402
1710
|
setLoading(true);
|
|
1403
1711
|
setError(null);
|
|
1404
|
-
|
|
1405
|
-
runQueryRef.current(sql).then(
|
|
1712
|
+
runQueryRef.current(config.sql || "").then(
|
|
1406
1713
|
(res) => {
|
|
1407
|
-
if (cancelled)
|
|
1408
|
-
|
|
1409
|
-
|
|
1714
|
+
if (!cancelled) {
|
|
1715
|
+
setLoading(false);
|
|
1716
|
+
setRows(res?.rows || []);
|
|
1717
|
+
}
|
|
1410
1718
|
},
|
|
1411
1719
|
(err) => {
|
|
1412
|
-
if (cancelled)
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1720
|
+
if (!cancelled) {
|
|
1721
|
+
setLoading(false);
|
|
1722
|
+
setRows(null);
|
|
1723
|
+
setError(err instanceof Error ? err.message : String(err) || "Query failed");
|
|
1724
|
+
}
|
|
1416
1725
|
}
|
|
1417
1726
|
);
|
|
1418
1727
|
return () => {
|
|
1419
1728
|
cancelled = true;
|
|
1420
1729
|
};
|
|
1421
|
-
}, [config.sql]);
|
|
1730
|
+
}, [config.sql, canRefresh]);
|
|
1731
|
+
const refresh = react.useCallback(async () => {
|
|
1732
|
+
setRefreshing(true);
|
|
1733
|
+
setError(null);
|
|
1734
|
+
try {
|
|
1735
|
+
const res = await runQueryRef.current(config.sql || "");
|
|
1736
|
+
const r = res?.rows || [];
|
|
1737
|
+
setRows(r);
|
|
1738
|
+
persistPanelData?.(panel.id, r, (/* @__PURE__ */ new Date()).toISOString());
|
|
1739
|
+
} catch (err) {
|
|
1740
|
+
setError(err instanceof Error ? err.message : String(err) || "Query failed");
|
|
1741
|
+
} finally {
|
|
1742
|
+
setRefreshing(false);
|
|
1743
|
+
}
|
|
1744
|
+
}, [config.sql, panel.id, persistPanelData]);
|
|
1745
|
+
const refreshBtn = canRefresh ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1746
|
+
"button",
|
|
1747
|
+
{
|
|
1748
|
+
onClick: refresh,
|
|
1749
|
+
disabled: refreshing,
|
|
1750
|
+
title: config.refreshedAt ? `Last computed ${new Date(config.refreshedAt).toLocaleString()} \u2014 click to refresh` : "Compute & save this chart\u2019s data",
|
|
1751
|
+
className: "absolute top-1 right-1 z-10 p-1 bg-midnight-elevated/80 border border-midnight-border text-midnight-text-muted hover:text-midnight-accent transition-colors",
|
|
1752
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: `w-3 h-3 ${refreshing ? "animate-spin" : ""}` })
|
|
1753
|
+
}
|
|
1754
|
+
) : null;
|
|
1422
1755
|
if (loading && !rows) {
|
|
1423
1756
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "Running\u2026" });
|
|
1424
1757
|
}
|
|
1758
|
+
if (!rows && !error && !canRefresh) {
|
|
1759
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center h-full gap-1 px-2 text-center text-xs text-midnight-text-muted", children: [
|
|
1760
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-4 h-4" }),
|
|
1761
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Chart data not available" }),
|
|
1762
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-midnight-text-subdued", children: "Download the dataset to view this chart." })
|
|
1763
|
+
] });
|
|
1764
|
+
}
|
|
1425
1765
|
if (error) {
|
|
1426
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1766
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center h-full px-2 text-center text-xs text-red-400", children: [
|
|
1767
|
+
refreshBtn,
|
|
1768
|
+
error
|
|
1769
|
+
] });
|
|
1427
1770
|
}
|
|
1428
1771
|
if (!rows) return null;
|
|
1772
|
+
let chart;
|
|
1429
1773
|
if (chartType === "metric") {
|
|
1430
1774
|
const first = rows[0];
|
|
1431
1775
|
const v = first ? Object.values(first)[0] : 0;
|
|
1432
|
-
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1776
|
+
chart = /* @__PURE__ */ jsxRuntime.jsx(MetricView, { value: Number(v) || 0, config: { column: config.column || "", agg: config.agg, label: config.label } });
|
|
1777
|
+
} else {
|
|
1778
|
+
const shaped = shapeChartData(chartType, rows, { yFields: config.yFields || [] });
|
|
1779
|
+
switch (chartType) {
|
|
1780
|
+
case "bar":
|
|
1781
|
+
chart = /* @__PURE__ */ jsxRuntime.jsx(BarView, { data: shaped, groupColumn: config.group || "", valueColumn: config.value || "", style: config.style });
|
|
1782
|
+
break;
|
|
1783
|
+
case "grouped-bar": {
|
|
1784
|
+
const gb = shaped;
|
|
1785
|
+
chart = /* @__PURE__ */ jsxRuntime.jsx(GroupedBarChart, { data: gb.data, keys: gb.keys, yFields: config.yFields || [], style: config.style });
|
|
1786
|
+
break;
|
|
1787
|
+
}
|
|
1788
|
+
case "pie":
|
|
1789
|
+
chart = /* @__PURE__ */ jsxRuntime.jsx(PieView, { data: shaped, groupColumn: config.group || "", style: config.style });
|
|
1790
|
+
break;
|
|
1791
|
+
case "line":
|
|
1792
|
+
chart = /* @__PURE__ */ jsxRuntime.jsx(LineView, { data: shaped, xColumn: config.x || "", yColumn: config.y || "", style: config.style });
|
|
1793
|
+
break;
|
|
1794
|
+
case "scatter":
|
|
1795
|
+
chart = /* @__PURE__ */ jsxRuntime.jsx(ScatterView, { data: shaped, xColumn: config.x || "", yColumn: config.y || "", style: config.style });
|
|
1796
|
+
break;
|
|
1797
|
+
case "heatmap":
|
|
1798
|
+
chart = shaped.length ? /* @__PURE__ */ jsxRuntime.jsx(HeatmapView, { data: shaped, rowColumn: config.row || "", colColumn: config.col || "", rowOrder: config.rowOrder, colOrder: config.colOrder, marginAgg: config.marginAgg, showTotals: config.showTotals, style: config.style }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "No data" });
|
|
1799
|
+
break;
|
|
1800
|
+
default:
|
|
1801
|
+
chart = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 text-xs text-midnight-text-muted", children: [
|
|
1802
|
+
"Unsupported SQL chart: ",
|
|
1803
|
+
chartType
|
|
1804
|
+
] });
|
|
1441
1805
|
}
|
|
1442
|
-
case "pie":
|
|
1443
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PieView, { data: shaped, groupColumn: config.group || "", style: config.style });
|
|
1444
|
-
case "line":
|
|
1445
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LineView, { data: shaped, xColumn: config.x || "", yColumn: config.y || "", style: config.style });
|
|
1446
|
-
case "scatter":
|
|
1447
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ScatterView, { data: shaped, xColumn: config.x || "", yColumn: config.y || "", style: config.style });
|
|
1448
|
-
case "heatmap":
|
|
1449
|
-
return shaped.length ? /* @__PURE__ */ jsxRuntime.jsx(HeatmapView, { data: shaped, rowColumn: config.row || "", colColumn: config.col || "", rowOrder: config.rowOrder, colOrder: config.colOrder, marginAgg: config.marginAgg, showTotals: config.showTotals, style: config.style }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "No data" });
|
|
1450
|
-
default:
|
|
1451
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 text-xs text-midnight-text-muted", children: [
|
|
1452
|
-
"Unsupported SQL chart: ",
|
|
1453
|
-
chartType
|
|
1454
|
-
] });
|
|
1455
1806
|
}
|
|
1807
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-full w-full", children: [
|
|
1808
|
+
refreshBtn,
|
|
1809
|
+
chart
|
|
1810
|
+
] });
|
|
1456
1811
|
}
|
|
1457
1812
|
function PanelContent({ panel, records, columns }) {
|
|
1458
1813
|
const { type } = panel;
|