@inkindcards/semantic-layer 2.2.5 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components.cjs +270 -134
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +35 -4
- package/dist/components.d.ts +35 -4
- package/dist/components.js +269 -135
- package/dist/components.js.map +1 -1
- package/package.json +1 -1
package/dist/components.cjs
CHANGED
|
@@ -998,48 +998,83 @@ function matchDisplayName(column, catalog) {
|
|
|
998
998
|
if (lower.length < 3) return null;
|
|
999
999
|
return catalog.find((f) => f.displayName.toLowerCase().includes(lower)) ?? catalog.find((f) => f.description.toLowerCase().includes(lower)) ?? null;
|
|
1000
1000
|
}
|
|
1001
|
+
function matchField(column, catalog) {
|
|
1002
|
+
const exact = matchExact(column, catalog);
|
|
1003
|
+
if (exact) return { field: exact, confidence: "exact" };
|
|
1004
|
+
const normalized = matchNormalized(column, catalog);
|
|
1005
|
+
if (normalized) return { field: normalized, confidence: "fuzzy" };
|
|
1006
|
+
const display = matchDisplayName(column, catalog);
|
|
1007
|
+
if (display) return { field: display, confidence: "fuzzy" };
|
|
1008
|
+
return { field: null, confidence: "manual" };
|
|
1009
|
+
}
|
|
1001
1010
|
function matchFields(columns, catalog) {
|
|
1002
1011
|
return columns.map((column) => {
|
|
1003
|
-
const
|
|
1004
|
-
|
|
1005
|
-
const normalized = matchNormalized(column, catalog);
|
|
1006
|
-
if (normalized) return { column, suggestedField: normalized, confidence: "fuzzy" };
|
|
1007
|
-
const display = matchDisplayName(column, catalog);
|
|
1008
|
-
if (display) return { column, suggestedField: display, confidence: "fuzzy" };
|
|
1009
|
-
return { column, suggestedField: null, confidence: "manual" };
|
|
1012
|
+
const { field, confidence } = matchField(column, catalog);
|
|
1013
|
+
return { column, suggestedField: field, confidence };
|
|
1010
1014
|
});
|
|
1011
1015
|
}
|
|
1016
|
+
function analyzeChartData(columns, sampleValues) {
|
|
1017
|
+
const dimensionColumns = [];
|
|
1018
|
+
const metricColumns = [];
|
|
1019
|
+
for (const col of columns) {
|
|
1020
|
+
const values = sampleValues.map((row) => row[col]).filter((v) => v !== null && v !== void 0);
|
|
1021
|
+
if (values.length === 0) {
|
|
1022
|
+
dimensionColumns.push(col);
|
|
1023
|
+
continue;
|
|
1024
|
+
}
|
|
1025
|
+
const numericCount = values.filter((v) => typeof v === "number" || typeof v === "string" && !isNaN(Number(v)) && v.trim() !== "").length;
|
|
1026
|
+
const isNumeric = numericCount / values.length > 0.5;
|
|
1027
|
+
if (isNumeric) {
|
|
1028
|
+
metricColumns.push(col);
|
|
1029
|
+
} else {
|
|
1030
|
+
dimensionColumns.push(col);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
return { dimensionColumns, metricColumns };
|
|
1034
|
+
}
|
|
1012
1035
|
|
|
1013
1036
|
// src/components/prompt-generator.ts
|
|
1014
|
-
function generateMigrationPrompt(
|
|
1015
|
-
const
|
|
1016
|
-
if (
|
|
1037
|
+
function generateMigrationPrompt(config) {
|
|
1038
|
+
const { componentLabel, dimensions, metrics, grain, originalMetricColumns } = config;
|
|
1039
|
+
if (dimensions.length === 0 && metrics.length === 0) {
|
|
1017
1040
|
return `Replace the sample/hardcoded data in the "${componentLabel}" component with live data from the semantic layer using useSemanticQuery. Use the DataCatalog to find the right field names.`;
|
|
1018
1041
|
}
|
|
1019
|
-
const metrics = resolved.filter((m) => m.field.type === "metric").map((m) => m.field.name);
|
|
1020
|
-
const timeDims = resolved.filter((m) => m.field.type === "time_dimension").map((m) => m.field.name);
|
|
1021
|
-
const dims = resolved.filter((m) => m.field.type === "dimension").map((m) => m.field.name);
|
|
1022
|
-
const groupBy = [...timeDims, ...dims];
|
|
1023
1042
|
const parts = [
|
|
1024
|
-
`Replace the sample/hardcoded data in the "${componentLabel}" component with a useSemanticQuery call using
|
|
1043
|
+
`Replace the sample/hardcoded data in the "${componentLabel}" component with a useSemanticQuery call using:`,
|
|
1044
|
+
""
|
|
1025
1045
|
];
|
|
1026
1046
|
if (metrics.length > 0) {
|
|
1027
|
-
parts.push(` metrics: [${metrics.map((
|
|
1047
|
+
parts.push(` metrics: [${metrics.map((m) => `'${m.name}'`).join(", ")}]`);
|
|
1028
1048
|
}
|
|
1029
|
-
if (
|
|
1049
|
+
if (dimensions.length > 0) {
|
|
1050
|
+
const groupBy = dimensions.map((d) => d.field.name);
|
|
1030
1051
|
parts.push(` groupBy: [${groupBy.map((n) => `'${n}'`).join(", ")}]`);
|
|
1031
1052
|
}
|
|
1032
|
-
if (
|
|
1033
|
-
parts.push(` grain: '
|
|
1053
|
+
if (grain) {
|
|
1054
|
+
parts.push(` grain: '${grain}'`);
|
|
1034
1055
|
}
|
|
1035
1056
|
parts.push("");
|
|
1036
|
-
|
|
1037
|
-
for (const
|
|
1038
|
-
|
|
1057
|
+
const sampleRow = [];
|
|
1058
|
+
for (const d of dimensions) {
|
|
1059
|
+
sampleRow.push(`${d.field.name}: "..."`);
|
|
1060
|
+
}
|
|
1061
|
+
for (const m of metrics) {
|
|
1062
|
+
sampleRow.push(`${m.name}: 1234`);
|
|
1063
|
+
}
|
|
1064
|
+
parts.push("The query returns rows like:");
|
|
1065
|
+
parts.push(` { ${sampleRow.join(", ")} }`);
|
|
1066
|
+
parts.push("");
|
|
1067
|
+
parts.push("Map to the chart's expected format:");
|
|
1068
|
+
for (const d of dimensions) {
|
|
1069
|
+
parts.push(` X-axis / category: "${d.field.name}" (was "${d.column}" in the hardcoded data)`);
|
|
1070
|
+
}
|
|
1071
|
+
if (metrics.length > 0 && originalMetricColumns.length > 0) {
|
|
1072
|
+
parts.push(` Series / values: each metric (${metrics.map((m) => `"${m.name}"`).join(", ")}) becomes a line/area/bar in the chart`);
|
|
1073
|
+
parts.push(` (replaces the old columns: ${originalMetricColumns.map((c) => `"${c}"`).join(", ")})`);
|
|
1039
1074
|
}
|
|
1040
1075
|
parts.push("");
|
|
1041
1076
|
parts.push(
|
|
1042
|
-
"Remove the old hardcoded/sample data and any fetch logic it used. Use the data, isLoading, and error values from useSemanticQuery to render the component."
|
|
1077
|
+
"Remove the old hardcoded/sample data and any fetch logic it used. Use the data, isLoading, and error values from useSemanticQuery to render the component. Show a loading spinner while isLoading is true. Show an error message if error is not null."
|
|
1043
1078
|
);
|
|
1044
1079
|
return parts.join("\n");
|
|
1045
1080
|
}
|
|
@@ -1148,31 +1183,54 @@ function InspectorModal({
|
|
|
1148
1183
|
entry,
|
|
1149
1184
|
onClose
|
|
1150
1185
|
}) {
|
|
1151
|
-
const { fields: catalog } = chunkT2C43AAL_cjs.useMetrics();
|
|
1152
|
-
const
|
|
1153
|
-
() =>
|
|
1154
|
-
[entry.columns,
|
|
1155
|
-
);
|
|
1156
|
-
const [mappings, setMappings] = react.useState(
|
|
1157
|
-
() => new Map(initialMatches.map((m) => [m.column, m.suggestedField]))
|
|
1186
|
+
const { fields: catalog, error: catalogError, isLoading: catalogLoading } = chunkT2C43AAL_cjs.useMetrics();
|
|
1187
|
+
const analysis = react.useMemo(
|
|
1188
|
+
() => analyzeChartData(entry.columns, entry.sampleValues),
|
|
1189
|
+
[entry.columns, entry.sampleValues]
|
|
1158
1190
|
);
|
|
1191
|
+
const dimensions = catalog.filter((f) => f.type === "dimension" || f.type === "time_dimension");
|
|
1192
|
+
const metrics = catalog.filter((f) => f.type === "metric");
|
|
1193
|
+
const initialDimMappings = react.useMemo(() => {
|
|
1194
|
+
const map = /* @__PURE__ */ new Map();
|
|
1195
|
+
for (const col of analysis.dimensionColumns) {
|
|
1196
|
+
const { field } = matchField(col, dimensions);
|
|
1197
|
+
map.set(col, field);
|
|
1198
|
+
}
|
|
1199
|
+
return map;
|
|
1200
|
+
}, [analysis.dimensionColumns, dimensions]);
|
|
1201
|
+
const [dimMappings, setDimMappings] = react.useState(initialDimMappings);
|
|
1159
1202
|
react.useEffect(() => {
|
|
1160
|
-
|
|
1161
|
-
}, [
|
|
1203
|
+
setDimMappings(initialDimMappings);
|
|
1204
|
+
}, [initialDimMappings]);
|
|
1205
|
+
const [selectedMetrics, setSelectedMetrics] = react.useState([]);
|
|
1206
|
+
const hasTimeDim = Array.from(dimMappings.values()).some((f) => f?.type === "time_dimension");
|
|
1207
|
+
const [grain, setGrain] = react.useState("month");
|
|
1162
1208
|
const [copied, setCopied] = react.useState(false);
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1209
|
+
const handleDimChange = react.useCallback((col, field) => {
|
|
1210
|
+
setDimMappings((prev) => {
|
|
1165
1211
|
const next = new Map(prev);
|
|
1166
|
-
next.set(
|
|
1212
|
+
next.set(col, field);
|
|
1167
1213
|
return next;
|
|
1168
1214
|
});
|
|
1169
1215
|
}, []);
|
|
1216
|
+
const handleToggleMetric = react.useCallback((field) => {
|
|
1217
|
+
setSelectedMetrics(
|
|
1218
|
+
(prev) => prev.some((m) => m.name === field.name) ? prev.filter((m) => m.name !== field.name) : [...prev, field]
|
|
1219
|
+
);
|
|
1220
|
+
}, []);
|
|
1170
1221
|
const handleGenerate = react.useCallback(async () => {
|
|
1171
|
-
const
|
|
1172
|
-
|
|
1173
|
-
field
|
|
1174
|
-
}
|
|
1175
|
-
const
|
|
1222
|
+
const resolvedDims = [];
|
|
1223
|
+
for (const [col, field] of dimMappings) {
|
|
1224
|
+
if (field) resolvedDims.push({ column: col, field });
|
|
1225
|
+
}
|
|
1226
|
+
const migrationConfig = {
|
|
1227
|
+
componentLabel: entry.label,
|
|
1228
|
+
dimensions: resolvedDims,
|
|
1229
|
+
metrics: selectedMetrics,
|
|
1230
|
+
grain: hasTimeDim && grain ? grain : null,
|
|
1231
|
+
originalMetricColumns: analysis.metricColumns
|
|
1232
|
+
};
|
|
1233
|
+
const prompt = generateMigrationPrompt(migrationConfig);
|
|
1176
1234
|
try {
|
|
1177
1235
|
await navigator.clipboard.writeText(prompt);
|
|
1178
1236
|
setCopied(true);
|
|
@@ -1187,12 +1245,8 @@ function InspectorModal({
|
|
|
1187
1245
|
setCopied(true);
|
|
1188
1246
|
setTimeout(() => setCopied(false), 2e3);
|
|
1189
1247
|
}
|
|
1190
|
-
}, [entry,
|
|
1191
|
-
const
|
|
1192
|
-
const map = /* @__PURE__ */ new Map();
|
|
1193
|
-
for (const m of initialMatches) map.set(m.column, m.confidence);
|
|
1194
|
-
return map;
|
|
1195
|
-
}, [initialMatches]);
|
|
1248
|
+
}, [entry, dimMappings, selectedMetrics, grain, hasTimeDim, analysis.metricColumns]);
|
|
1249
|
+
const canGenerate = selectedMetrics.length > 0 || Array.from(dimMappings.values()).some(Boolean);
|
|
1196
1250
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1197
1251
|
/* @__PURE__ */ jsxRuntime.jsx("div", { onClick: onClose, style: backdropStyle }),
|
|
1198
1252
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalStyle, children: [
|
|
@@ -1206,92 +1260,175 @@ function InspectorModal({
|
|
|
1206
1260
|
] }),
|
|
1207
1261
|
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, style: closeBtnStyle, children: "\xD7" })
|
|
1208
1262
|
] }),
|
|
1209
|
-
|
|
1210
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1211
|
-
|
|
1212
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
] }),
|
|
1216
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
|
|
1217
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Field Mapping" }),
|
|
1218
|
-
/* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 13 }, children: [
|
|
1219
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1220
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Current Column" }),
|
|
1221
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Confidence" }),
|
|
1222
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Semantic Layer Field" })
|
|
1263
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { overflow: "auto", flex: 1 }, children: [
|
|
1264
|
+
entry.sampleValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
|
|
1265
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Current Data Preview" }),
|
|
1266
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflow: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: previewTableStyle, children: [
|
|
1267
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: entry.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { style: previewThStyle, children: col }, col)) }) }),
|
|
1268
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: entry.sampleValues.map((row, i) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: entry.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { style: previewTdStyle, children: row[col] === null || row[col] === void 0 ? "\u2014" : String(row[col]) }, col)) }, i)) })
|
|
1223
1269
|
] }) }),
|
|
1224
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1270
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8, fontSize: 11, color: "#9ca3af" }, children: [
|
|
1271
|
+
"Detected: ",
|
|
1272
|
+
analysis.dimensionColumns.length,
|
|
1273
|
+
" dimension column",
|
|
1274
|
+
analysis.dimensionColumns.length !== 1 ? "s" : "",
|
|
1275
|
+
" (",
|
|
1276
|
+
analysis.dimensionColumns.join(", ") || "none",
|
|
1277
|
+
")",
|
|
1278
|
+
" \xB7 ",
|
|
1279
|
+
analysis.metricColumns.length,
|
|
1280
|
+
" value column",
|
|
1281
|
+
analysis.metricColumns.length !== 1 ? "s" : "",
|
|
1282
|
+
" (",
|
|
1283
|
+
analysis.metricColumns.join(", ") || "none",
|
|
1284
|
+
")"
|
|
1285
|
+
] })
|
|
1286
|
+
] }),
|
|
1287
|
+
catalog.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...sectionStyle, textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: "#9ca3af" }, children: catalogLoading ? "Loading catalog..." : catalogError ? `Error loading catalog: ${catalogError}` : "No semantic layer catalog available. Connect to the gateway to enable smart matching." }) }),
|
|
1288
|
+
catalog.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
|
|
1289
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Dimensions (Group By)" }),
|
|
1290
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#9ca3af", marginBottom: 8 }, children: "What categories define the rows? (X-axis, grouping)" }),
|
|
1291
|
+
analysis.dimensionColumns.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: "#9ca3af", fontStyle: "italic" }, children: "No dimension columns detected in the data." }) : /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 13 }, children: [
|
|
1292
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1293
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Current Column" }),
|
|
1294
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Sample Values" }),
|
|
1295
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Semantic Layer Dimension" })
|
|
1296
|
+
] }) }),
|
|
1297
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: analysis.dimensionColumns.map((col) => {
|
|
1298
|
+
const sampleVals = entry.sampleValues.map((row) => row[col]).filter((v) => v !== null && v !== void 0).slice(0, 4).map(String);
|
|
1299
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1300
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: mappingTdStyle, children: /* @__PURE__ */ jsxRuntime.jsx("code", { style: { fontSize: 12, color: "#6366f1", fontFamily: "monospace" }, children: col }) }),
|
|
1301
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { style: { ...mappingTdStyle, fontSize: 11, color: "#9ca3af" }, children: [
|
|
1302
|
+
sampleVals.join(", "),
|
|
1303
|
+
sampleVals.length >= 4 ? ", ..." : ""
|
|
1304
|
+
] }),
|
|
1305
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: mappingTdStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1306
|
+
"select",
|
|
1307
|
+
{
|
|
1308
|
+
value: dimMappings.get(col)?.name ?? "",
|
|
1309
|
+
onChange: (e) => {
|
|
1310
|
+
const field = dimensions.find((f) => f.name === e.target.value) ?? null;
|
|
1311
|
+
handleDimChange(col, field);
|
|
1312
|
+
},
|
|
1313
|
+
style: selectStyle2,
|
|
1314
|
+
children: [
|
|
1315
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "-- select dimension --" }),
|
|
1316
|
+
dimensions.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: f.name, children: [
|
|
1317
|
+
f.displayName,
|
|
1318
|
+
" (",
|
|
1319
|
+
f.type,
|
|
1320
|
+
") \u2014 ",
|
|
1321
|
+
f.name
|
|
1322
|
+
] }, f.name))
|
|
1323
|
+
]
|
|
1324
|
+
}
|
|
1325
|
+
) })
|
|
1326
|
+
] }, col);
|
|
1327
|
+
}) })
|
|
1328
|
+
] }),
|
|
1329
|
+
hasTimeDim && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 10, display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
1330
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: 12, fontWeight: 600, color: "#374151" }, children: "Time Grain:" }),
|
|
1331
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1332
|
+
"select",
|
|
1333
|
+
{
|
|
1334
|
+
value: grain,
|
|
1335
|
+
onChange: (e) => setGrain(e.target.value),
|
|
1336
|
+
style: { ...selectStyle2, width: "auto" },
|
|
1337
|
+
children: [
|
|
1338
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "day", children: "Day" }),
|
|
1339
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "week", children: "Week" }),
|
|
1340
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "month", children: "Month" }),
|
|
1341
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "quarter", children: "Quarter" }),
|
|
1342
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "year", children: "Year" })
|
|
1343
|
+
]
|
|
1344
|
+
}
|
|
1345
|
+
)
|
|
1346
|
+
] })
|
|
1235
1347
|
] }),
|
|
1236
|
-
catalog.length
|
|
1348
|
+
catalog.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
|
|
1349
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Metrics (Values)" }),
|
|
1350
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 11, color: "#9ca3af", marginBottom: 8 }, children: [
|
|
1351
|
+
"Which metrics should be queried? These become the series/values in the chart.",
|
|
1352
|
+
analysis.metricColumns.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1353
|
+
" (replaces: ",
|
|
1354
|
+
analysis.metricColumns.join(", "),
|
|
1355
|
+
")"
|
|
1356
|
+
] })
|
|
1357
|
+
] }),
|
|
1358
|
+
metrics.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: "#9ca3af", fontStyle: "italic" }, children: "No metrics available in the catalog." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 4, maxHeight: 200, overflow: "auto" }, children: metrics.map((m) => {
|
|
1359
|
+
const isSelected = selectedMetrics.some((s) => s.name === m.name);
|
|
1360
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1361
|
+
"label",
|
|
1362
|
+
{
|
|
1363
|
+
style: {
|
|
1364
|
+
display: "flex",
|
|
1365
|
+
alignItems: "center",
|
|
1366
|
+
gap: 8,
|
|
1367
|
+
padding: "4px 8px",
|
|
1368
|
+
borderRadius: 4,
|
|
1369
|
+
cursor: "pointer",
|
|
1370
|
+
backgroundColor: isSelected ? "#eff6ff" : "transparent",
|
|
1371
|
+
border: isSelected ? "1px solid #bfdbfe" : "1px solid transparent",
|
|
1372
|
+
fontSize: 12
|
|
1373
|
+
},
|
|
1374
|
+
children: [
|
|
1375
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1376
|
+
"input",
|
|
1377
|
+
{
|
|
1378
|
+
type: "checkbox",
|
|
1379
|
+
checked: isSelected,
|
|
1380
|
+
onChange: () => handleToggleMetric(m),
|
|
1381
|
+
style: { margin: 0 }
|
|
1382
|
+
}
|
|
1383
|
+
),
|
|
1384
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, color: "#111827" }, children: m.displayName }),
|
|
1385
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { style: { fontSize: 10, color: "#6366f1", fontFamily: "monospace" }, children: m.name }),
|
|
1386
|
+
m.category && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto", fontSize: 10, color: "#9ca3af" }, children: m.category })
|
|
1387
|
+
]
|
|
1388
|
+
},
|
|
1389
|
+
m.name
|
|
1390
|
+
);
|
|
1391
|
+
}) }),
|
|
1392
|
+
selectedMetrics.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8, fontSize: 11, color: "#6b7280" }, children: [
|
|
1393
|
+
"Selected: ",
|
|
1394
|
+
selectedMetrics.map((m) => m.displayName).join(", ")
|
|
1395
|
+
] })
|
|
1396
|
+
] }),
|
|
1397
|
+
canGenerate && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
|
|
1398
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Query Preview" }),
|
|
1399
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { style: {
|
|
1400
|
+
fontSize: 11,
|
|
1401
|
+
fontFamily: "monospace",
|
|
1402
|
+
backgroundColor: "#f9fafb",
|
|
1403
|
+
border: "1px solid #e5e7eb",
|
|
1404
|
+
borderRadius: 6,
|
|
1405
|
+
padding: "8px 12px",
|
|
1406
|
+
whiteSpace: "pre-wrap",
|
|
1407
|
+
color: "#374151",
|
|
1408
|
+
margin: 0
|
|
1409
|
+
}, children: `useSemanticQuery({${selectedMetrics.length > 0 ? `
|
|
1410
|
+
metrics: [${selectedMetrics.map((m) => `'${m.name}'`).join(", ")}],` : ""}${Array.from(dimMappings.values()).some(Boolean) ? `
|
|
1411
|
+
groupBy: [${Array.from(dimMappings.values()).filter(Boolean).map((f) => `'${f.name}'`).join(", ")}],` : ""}${hasTimeDim && grain ? `
|
|
1412
|
+
grain: '${grain}',` : ""}
|
|
1413
|
+
})` })
|
|
1414
|
+
] })
|
|
1237
1415
|
] }),
|
|
1238
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "12px 20px", borderTop: "1px solid #e5e7eb" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1416
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "12px 20px", borderTop: "1px solid #e5e7eb" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1417
|
+
"button",
|
|
1418
|
+
{
|
|
1419
|
+
onClick: handleGenerate,
|
|
1420
|
+
disabled: !canGenerate,
|
|
1421
|
+
style: {
|
|
1422
|
+
...generateBtnStyle,
|
|
1423
|
+
opacity: canGenerate ? 1 : 0.5,
|
|
1424
|
+
cursor: canGenerate ? "pointer" : "not-allowed"
|
|
1425
|
+
},
|
|
1426
|
+
children: copied ? "Copied to clipboard!" : "Generate Migration Prompt"
|
|
1427
|
+
}
|
|
1428
|
+
) })
|
|
1239
1429
|
] })
|
|
1240
1430
|
] });
|
|
1241
1431
|
}
|
|
1242
|
-
function MappingRow({
|
|
1243
|
-
column,
|
|
1244
|
-
confidence,
|
|
1245
|
-
selectedField,
|
|
1246
|
-
catalog,
|
|
1247
|
-
onChange
|
|
1248
|
-
}) {
|
|
1249
|
-
const badgeColors = {
|
|
1250
|
-
exact: { bg: "#dcfce7", color: "#15803d" },
|
|
1251
|
-
fuzzy: { bg: "#fef9c3", color: "#a16207" },
|
|
1252
|
-
manual: { bg: "#fee2e2", color: "#dc2626" }
|
|
1253
|
-
};
|
|
1254
|
-
const badge = badgeColors[confidence] ?? badgeColors.manual;
|
|
1255
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1256
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { style: mappingTdStyle, children: /* @__PURE__ */ jsxRuntime.jsx("code", { style: { fontSize: 12, color: "#6366f1", fontFamily: "monospace" }, children: column }) }),
|
|
1257
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { style: { ...mappingTdStyle, textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1258
|
-
"span",
|
|
1259
|
-
{
|
|
1260
|
-
style: {
|
|
1261
|
-
display: "inline-block",
|
|
1262
|
-
padding: "1px 6px",
|
|
1263
|
-
fontSize: 10,
|
|
1264
|
-
fontWeight: 600,
|
|
1265
|
-
borderRadius: 4,
|
|
1266
|
-
backgroundColor: badge.bg,
|
|
1267
|
-
color: badge.color
|
|
1268
|
-
},
|
|
1269
|
-
children: confidence
|
|
1270
|
-
}
|
|
1271
|
-
) }),
|
|
1272
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { style: mappingTdStyle, children: catalog.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1273
|
-
"select",
|
|
1274
|
-
{
|
|
1275
|
-
value: selectedField?.name ?? "",
|
|
1276
|
-
onChange: (e) => {
|
|
1277
|
-
const field = catalog.find((f) => f.name === e.target.value) ?? null;
|
|
1278
|
-
onChange(field);
|
|
1279
|
-
},
|
|
1280
|
-
style: selectStyle2,
|
|
1281
|
-
children: [
|
|
1282
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "-- none --" }),
|
|
1283
|
-
catalog.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: f.name, children: [
|
|
1284
|
-
f.displayName,
|
|
1285
|
-
" (",
|
|
1286
|
-
f.type,
|
|
1287
|
-
") \u2014 ",
|
|
1288
|
-
f.name
|
|
1289
|
-
] }, f.name))
|
|
1290
|
-
]
|
|
1291
|
-
}
|
|
1292
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#9ca3af" }, children: selectedField ? selectedField.name : "No catalog" }) })
|
|
1293
|
-
] });
|
|
1294
|
-
}
|
|
1295
1432
|
var backdropStyle = {
|
|
1296
1433
|
position: "fixed",
|
|
1297
1434
|
inset: 0,
|
|
@@ -1304,8 +1441,8 @@ var modalStyle = {
|
|
|
1304
1441
|
left: "50%",
|
|
1305
1442
|
transform: "translate(-50%, -50%)",
|
|
1306
1443
|
zIndex: 100001,
|
|
1307
|
-
width: "min(
|
|
1308
|
-
maxHeight: "
|
|
1444
|
+
width: "min(700px, 90vw)",
|
|
1445
|
+
maxHeight: "85vh",
|
|
1309
1446
|
backgroundColor: "#fff",
|
|
1310
1447
|
borderRadius: 12,
|
|
1311
1448
|
boxShadow: "0 8px 30px rgba(0,0,0,0.2)",
|
|
@@ -1331,9 +1468,7 @@ var closeBtnStyle = {
|
|
|
1331
1468
|
lineHeight: 1
|
|
1332
1469
|
};
|
|
1333
1470
|
var sectionStyle = {
|
|
1334
|
-
padding: "12px 20px"
|
|
1335
|
-
overflow: "auto",
|
|
1336
|
-
flex: 1
|
|
1471
|
+
padding: "12px 20px"
|
|
1337
1472
|
};
|
|
1338
1473
|
var sectionTitleStyle = {
|
|
1339
1474
|
fontSize: 11,
|
|
@@ -1341,7 +1476,7 @@ var sectionTitleStyle = {
|
|
|
1341
1476
|
textTransform: "uppercase",
|
|
1342
1477
|
letterSpacing: "0.05em",
|
|
1343
1478
|
color: "#6b7280",
|
|
1344
|
-
marginBottom:
|
|
1479
|
+
marginBottom: 4
|
|
1345
1480
|
};
|
|
1346
1481
|
var previewTableStyle = {
|
|
1347
1482
|
width: "100%",
|
|
@@ -1396,8 +1531,7 @@ var generateBtnStyle = {
|
|
|
1396
1531
|
color: "#fff",
|
|
1397
1532
|
backgroundColor: "#3b82f6",
|
|
1398
1533
|
border: "none",
|
|
1399
|
-
borderRadius: 8
|
|
1400
|
-
cursor: "pointer"
|
|
1534
|
+
borderRadius: 8
|
|
1401
1535
|
};
|
|
1402
1536
|
|
|
1403
1537
|
exports.AdminDashboard = AdminDashboard;
|
|
@@ -1406,7 +1540,9 @@ exports.DataInspector = DataInspector;
|
|
|
1406
1540
|
exports.Inspectable = Inspectable;
|
|
1407
1541
|
exports.MetricPicker = MetricPicker;
|
|
1408
1542
|
exports.ResultsTable = ResultsTable;
|
|
1543
|
+
exports.analyzeChartData = analyzeChartData;
|
|
1409
1544
|
exports.generateMigrationPrompt = generateMigrationPrompt;
|
|
1545
|
+
exports.matchField = matchField;
|
|
1410
1546
|
exports.matchFields = matchFields;
|
|
1411
1547
|
//# sourceMappingURL=components.cjs.map
|
|
1412
1548
|
//# sourceMappingURL=components.cjs.map
|