@datatechsolutions/ui 2.11.42 → 2.11.44

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.
@@ -1155,6 +1155,481 @@ function getEntityHandleColor(entityKey) {
1155
1155
  function getEntityMinimapColor(entityKey) {
1156
1156
  return presetFromKey(entityKey).minimapColor;
1157
1157
  }
1158
+ var DATASOURCE_LOGOS = {
1159
+ bigquery: "/logos/datasources/bigquery.svg",
1160
+ postgres: "/logos/datasources/postgres.svg",
1161
+ snowflake: "/logos/datasources/snowflake.svg",
1162
+ mongodb: "/logos/datasources/mongodb.svg",
1163
+ redis: "/logos/datasources/redis.svg",
1164
+ mysql: "/logos/datasources/mysql.svg",
1165
+ clickhouse: "/logos/datasources/clickhouse.svg",
1166
+ elasticsearch: "/logos/datasources/elasticsearch.svg",
1167
+ duckdb: "/logos/datasources/duckdb.svg",
1168
+ sqlite: "/logos/datasources/sqlite.svg",
1169
+ mariadb: "/logos/datasources/mariadb.svg",
1170
+ oracle: "/logos/datasources/oracle.svg",
1171
+ mssql: "/logos/datasources/mssql.svg",
1172
+ sqlserver: "/logos/datasources/mssql.svg",
1173
+ cassandra: "/logos/datasources/cassandra.svg",
1174
+ dynamodb: "/logos/datasources/dynamodb.svg",
1175
+ cockroach: "/logos/datasources/cockroachdb.svg",
1176
+ supabase: "/logos/datasources/supabase.svg",
1177
+ firebase: "/logos/datasources/firebase.svg",
1178
+ neo4j: "/logos/datasources/neo4j.svg"
1179
+ };
1180
+ function getDatasourceLogo(datasourceId, dialect) {
1181
+ const search = (dialect ?? datasourceId).toLowerCase();
1182
+ for (const [key, url] of Object.entries(DATASOURCE_LOGOS)) {
1183
+ if (search.includes(key)) return url;
1184
+ }
1185
+ return null;
1186
+ }
1187
+ var TYPE_COLORS = {
1188
+ string: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
1189
+ varchar: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
1190
+ text: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
1191
+ integer: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1192
+ int: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1193
+ bigint: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1194
+ number: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1195
+ decimal: "bg-indigo-500/10 text-indigo-600 dark:text-indigo-400",
1196
+ float: "bg-indigo-500/10 text-indigo-600 dark:text-indigo-400",
1197
+ boolean: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
1198
+ date: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
1199
+ timestamp: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
1200
+ datetime: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
1201
+ json: "bg-violet-500/10 text-violet-600 dark:text-violet-400",
1202
+ jsonb: "bg-violet-500/10 text-violet-600 dark:text-violet-400",
1203
+ uuid: "bg-teal-500/10 text-teal-600 dark:text-teal-400",
1204
+ array: "bg-pink-500/10 text-pink-600 dark:text-pink-400"
1205
+ };
1206
+ var SIDEBAR_SECTIONS = [
1207
+ { id: "connection", label: "Connection", icon: outline.CircleStackIcon },
1208
+ { id: "table", label: "Table", icon: outline.TableCellsIcon },
1209
+ { id: "columns", label: "Columns", icon: outline.TableCellsIcon },
1210
+ { id: "filters", label: "Filters", icon: outline.FunnelIcon },
1211
+ { id: "output", label: "Output", icon: outline.Cog6ToothIcon }
1212
+ ];
1213
+ function DatasourceNodeConfigForm({
1214
+ open,
1215
+ nodeId,
1216
+ config,
1217
+ onSave,
1218
+ onCancel,
1219
+ datasources,
1220
+ onLoadTables,
1221
+ onLoadSchema
1222
+ }) {
1223
+ const t = chunkYXN2K77G_js.useTranslations("agents.workflow.datasourceNodeConfig");
1224
+ const [activeSectionId, setActiveSectionId] = react.useState("connection");
1225
+ const [selectedDatasourceId, setSelectedDatasourceId] = react.useState(config.datasourceId ?? "");
1226
+ const [selectedTable, setSelectedTable] = react.useState(config.table ?? "");
1227
+ const [availableTables, setAvailableTables] = react.useState([]);
1228
+ const [availableColumns, setAvailableColumns] = react.useState([]);
1229
+ const [selectedColumns, setSelectedColumns] = react.useState([...config.selectedColumns ?? []]);
1230
+ const [outputVariable, setOutputVariable] = react.useState(config.outputVariable);
1231
+ const [limit, setLimit] = react.useState(config.limit);
1232
+ const [filterVariables, setFilterVariables] = react.useState({ ...config.filterVariables });
1233
+ const [tableSearch, setTableSearch] = react.useState("");
1234
+ const [columnSearch, setColumnSearch] = react.useState("");
1235
+ const allColumnNames = availableColumns.map((column) => column.name);
1236
+ const allSelected = selectedColumns.length > 0 && selectedColumns.length === allColumnNames.length;
1237
+ const selectedDatasource = datasources.find((datasource) => datasource.id === selectedDatasourceId);
1238
+ const filteredTables = react.useMemo(
1239
+ () => tableSearch ? availableTables.filter((table) => table.toLowerCase().includes(tableSearch.toLowerCase())) : availableTables,
1240
+ [availableTables, tableSearch]
1241
+ );
1242
+ const filteredColumns = react.useMemo(
1243
+ () => columnSearch ? availableColumns.filter((column) => column.name.toLowerCase().includes(columnSearch.toLowerCase())) : availableColumns,
1244
+ [availableColumns, columnSearch]
1245
+ );
1246
+ const loadTables = react.useCallback(async (datasourceId) => {
1247
+ if (!datasourceId) {
1248
+ setAvailableTables([]);
1249
+ return;
1250
+ }
1251
+ const tables = await onLoadTables(datasourceId);
1252
+ setAvailableTables(tables);
1253
+ }, [onLoadTables]);
1254
+ const loadSchema = react.useCallback(async (datasourceId, table) => {
1255
+ if (!datasourceId || !table) {
1256
+ setAvailableColumns([]);
1257
+ return;
1258
+ }
1259
+ const columns = await onLoadSchema(datasourceId, table);
1260
+ setAvailableColumns(columns);
1261
+ }, [onLoadSchema]);
1262
+ react.useEffect(() => {
1263
+ if (selectedDatasourceId) loadTables(selectedDatasourceId);
1264
+ }, [selectedDatasourceId, loadTables]);
1265
+ react.useEffect(() => {
1266
+ if (selectedDatasourceId && selectedTable) loadSchema(selectedDatasourceId, selectedTable);
1267
+ }, [selectedDatasourceId, selectedTable, loadSchema]);
1268
+ const handleDatasourceChange = (datasourceId) => {
1269
+ setSelectedDatasourceId(datasourceId);
1270
+ setSelectedTable("");
1271
+ setAvailableTables([]);
1272
+ setAvailableColumns([]);
1273
+ setSelectedColumns([]);
1274
+ setFilterVariables({});
1275
+ setTableSearch("");
1276
+ setColumnSearch("");
1277
+ };
1278
+ const handleTableChange = (table) => {
1279
+ setSelectedTable(table);
1280
+ setAvailableColumns([]);
1281
+ setSelectedColumns([]);
1282
+ setFilterVariables({});
1283
+ setColumnSearch("");
1284
+ };
1285
+ const handleToggleColumn = (columnName) => {
1286
+ setSelectedColumns(
1287
+ (previous) => previous.includes(columnName) ? previous.filter((name) => name !== columnName) : [...previous, columnName]
1288
+ );
1289
+ };
1290
+ const handleAddFilter = () => {
1291
+ setFilterVariables((previous) => ({ ...previous, [`field_${Object.keys(previous).length}`]: "" }));
1292
+ };
1293
+ const handleUpdateFilterVariable = (oldKey, newKey) => {
1294
+ setFilterVariables((previous) => {
1295
+ const updated = { ...previous };
1296
+ const value = updated[oldKey] ?? "";
1297
+ delete updated[oldKey];
1298
+ updated[newKey] = value;
1299
+ return updated;
1300
+ });
1301
+ };
1302
+ const handleUpdateFilterField = (key, newValue) => {
1303
+ setFilterVariables((previous) => ({ ...previous, [key]: newValue }));
1304
+ };
1305
+ const handleRemoveFilter = (key) => {
1306
+ setFilterVariables((previous) => {
1307
+ const updated = { ...previous };
1308
+ delete updated[key];
1309
+ return updated;
1310
+ });
1311
+ };
1312
+ const handleSave = () => {
1313
+ const cleanedFilters = {};
1314
+ for (const [key, value] of Object.entries(filterVariables)) {
1315
+ if (key.trim() && value.trim()) cleanedFilters[key.trim()] = value.trim();
1316
+ }
1317
+ onSave({
1318
+ ...config,
1319
+ datasourceId: selectedDatasourceId,
1320
+ dialect: selectedDatasource?.dialect ?? "",
1321
+ table: selectedTable,
1322
+ selectedColumns,
1323
+ outputVariable: outputVariable.trim(),
1324
+ limit,
1325
+ filterVariables: cleanedFilters
1326
+ });
1327
+ };
1328
+ const filterEntries = Object.entries(filterVariables);
1329
+ const canSave = selectedDatasourceId && selectedTable && selectedColumns.length > 0;
1330
+ function renderSection() {
1331
+ switch (activeSectionId) {
1332
+ case "connection":
1333
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1334
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("datasourceHelp") }),
1335
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: datasources.map((datasource) => {
1336
+ const isSelected = datasource.id === selectedDatasourceId;
1337
+ const logo2 = getDatasourceLogo(datasource.id, datasource.dialect);
1338
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1339
+ "button",
1340
+ {
1341
+ type: "button",
1342
+ onClick: () => {
1343
+ handleDatasourceChange(datasource.id);
1344
+ setActiveSectionId("table");
1345
+ },
1346
+ className: `flex items-center gap-3 rounded-xl border px-3 py-2.5 text-left transition-all ${isSelected ? "border-cyan-500/50 bg-cyan-500/5 ring-1 ring-cyan-500/20 dark:border-cyan-400/40 dark:bg-cyan-400/5" : "border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm dark:border-white/10 dark:bg-white/[0.03] dark:hover:border-white/20"}`,
1347
+ children: [
1348
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center", children: logo2 ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logo2, alt: datasource.dialect, className: "h-7 w-7" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.ServerStackIcon, { className: "h-6 w-6 text-gray-400" }) }),
1349
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
1350
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs font-semibold text-gray-900 dark:text-white", children: datasource.name }),
1351
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: datasource.dialect })
1352
+ ] }),
1353
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(outline.CheckIcon, { className: "h-4 w-4 shrink-0 text-cyan-500 dark:text-cyan-400" })
1354
+ ]
1355
+ },
1356
+ datasource.id
1357
+ );
1358
+ }) })
1359
+ ] });
1360
+ case "table":
1361
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1362
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("tableHelp") }),
1363
+ !selectedDatasourceId ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-8 text-center text-xs text-gray-400", children: t("selectDatasource") }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "liquid-surface rounded-xl border border-white/30 dark:border-white/10", children: [
1364
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-b border-gray-200/50 px-3 py-2 dark:border-white/5", children: [
1365
+ /* @__PURE__ */ jsxRuntime.jsx(outline.MagnifyingGlassIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
1366
+ /* @__PURE__ */ jsxRuntime.jsx(
1367
+ "input",
1368
+ {
1369
+ type: "text",
1370
+ value: tableSearch,
1371
+ onChange: (event) => setTableSearch(event.target.value),
1372
+ placeholder: t("selectTable"),
1373
+ className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1374
+ }
1375
+ ),
1376
+ availableTables.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400", children: availableTables.length })
1377
+ ] }),
1378
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-64 overflow-y-auto p-1", children: [
1379
+ filteredTables.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-6 text-center text-[10px] text-gray-400", children: t("noColumnsAvailable") }),
1380
+ filteredTables.map((table) => {
1381
+ const isSelected = table === selectedTable;
1382
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1383
+ "button",
1384
+ {
1385
+ type: "button",
1386
+ onClick: () => {
1387
+ handleTableChange(table);
1388
+ setActiveSectionId("columns");
1389
+ },
1390
+ className: `flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs transition-colors ${isSelected ? "bg-cyan-500/10 font-semibold text-cyan-700 dark:text-cyan-300" : "text-gray-700 hover:bg-gray-100/60 dark:text-gray-300 dark:hover:bg-white/5"}`,
1391
+ children: [
1392
+ /* @__PURE__ */ jsxRuntime.jsx(outline.TableCellsIcon, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" }),
1393
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: table }),
1394
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(outline.CheckIcon, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-cyan-500" })
1395
+ ]
1396
+ },
1397
+ table
1398
+ );
1399
+ })
1400
+ ] })
1401
+ ] })
1402
+ ] });
1403
+ case "columns":
1404
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1405
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1406
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
1407
+ selectedColumns.length,
1408
+ "/",
1409
+ availableColumns.length,
1410
+ " selected"
1411
+ ] }),
1412
+ /* @__PURE__ */ jsxRuntime.jsx(
1413
+ "button",
1414
+ {
1415
+ type: "button",
1416
+ onClick: () => setSelectedColumns(allSelected ? [] : [...allColumnNames]),
1417
+ disabled: availableColumns.length === 0,
1418
+ className: "text-[10px] font-semibold text-cyan-600 hover:text-cyan-700 disabled:opacity-40 dark:text-cyan-400",
1419
+ children: allSelected ? t("deselectAll") : t("selectAll")
1420
+ }
1421
+ )
1422
+ ] }),
1423
+ !selectedTable ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-8 text-center text-xs text-gray-400", children: t("selectTable") }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "liquid-surface rounded-xl border border-white/30 dark:border-white/10", children: [
1424
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-b border-gray-200/50 px-3 py-2 dark:border-white/5", children: [
1425
+ /* @__PURE__ */ jsxRuntime.jsx(outline.MagnifyingGlassIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
1426
+ /* @__PURE__ */ jsxRuntime.jsx(
1427
+ "input",
1428
+ {
1429
+ type: "text",
1430
+ value: columnSearch,
1431
+ onChange: (event) => setColumnSearch(event.target.value),
1432
+ placeholder: "Search columns...",
1433
+ className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1434
+ }
1435
+ )
1436
+ ] }),
1437
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-64 overflow-y-auto p-1", children: [
1438
+ filteredColumns.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-6 text-center text-[10px] text-gray-400", children: t("noColumnsAvailable") }),
1439
+ filteredColumns.map((column) => {
1440
+ const isSelected = selectedColumns.includes(column.name);
1441
+ const typeColor = TYPE_COLORS[column.type.toLowerCase()] ?? TYPE_COLORS.string;
1442
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1443
+ "button",
1444
+ {
1445
+ type: "button",
1446
+ onClick: () => handleToggleColumn(column.name),
1447
+ className: `flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left transition-colors ${isSelected ? "bg-cyan-500/8 dark:bg-cyan-400/5" : "hover:bg-gray-100/60 dark:hover:bg-white/5"}`,
1448
+ children: [
1449
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors ${isSelected ? "border-cyan-500 bg-cyan-500 dark:border-cyan-400 dark:bg-cyan-400" : "border-gray-300 dark:border-gray-600"}`, children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(outline.CheckIcon, { className: "h-2.5 w-2.5 text-white" }) }),
1450
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1 truncate text-xs text-gray-900 dark:text-white", children: [
1451
+ column.name,
1452
+ column.nullable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-[9px] text-gray-400", children: "?" })
1453
+ ] }),
1454
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `shrink-0 rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeColor}`, children: column.type })
1455
+ ]
1456
+ },
1457
+ column.name
1458
+ );
1459
+ })
1460
+ ] })
1461
+ ] })
1462
+ ] });
1463
+ case "filters":
1464
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1465
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1466
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("filtersHelp") }),
1467
+ /* @__PURE__ */ jsxRuntime.jsxs(
1468
+ "button",
1469
+ {
1470
+ type: "button",
1471
+ onClick: handleAddFilter,
1472
+ className: "flex items-center gap-1 text-[10px] font-semibold text-cyan-600 hover:text-cyan-700 dark:text-cyan-400",
1473
+ children: [
1474
+ /* @__PURE__ */ jsxRuntime.jsx(outline.PlusIcon, { className: "h-3 w-3" }),
1475
+ t("addFilter")
1476
+ ]
1477
+ }
1478
+ )
1479
+ ] }),
1480
+ filterEntries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 py-8", children: [
1481
+ /* @__PURE__ */ jsxRuntime.jsx(outline.FunnelIcon, { className: "h-8 w-8 text-gray-300 dark:text-gray-600" }),
1482
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: "No filters configured" }),
1483
+ /* @__PURE__ */ jsxRuntime.jsxs(
1484
+ "button",
1485
+ {
1486
+ type: "button",
1487
+ onClick: handleAddFilter,
1488
+ className: "flex items-center gap-1 rounded-lg bg-cyan-500/10 px-3 py-1.5 text-[10px] font-semibold text-cyan-600 hover:bg-cyan-500/15 dark:text-cyan-400",
1489
+ children: [
1490
+ /* @__PURE__ */ jsxRuntime.jsx(outline.PlusIcon, { className: "h-3 w-3" }),
1491
+ t("addFilter")
1492
+ ]
1493
+ }
1494
+ )
1495
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: filterEntries.map(([variableName, columnName], index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-3 py-2 dark:border-white/10 dark:bg-white/[0.03]", children: [
1496
+ /* @__PURE__ */ jsxRuntime.jsxs(
1497
+ "select",
1498
+ {
1499
+ value: columnName,
1500
+ onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
1501
+ className: "flex-1 rounded bg-transparent text-xs text-gray-900 outline-none dark:text-white",
1502
+ children: [
1503
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("columnName") }),
1504
+ availableColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: column.name, children: column.name }, column.name))
1505
+ ]
1506
+ }
1507
+ ),
1508
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-gray-400", children: "=" }),
1509
+ /* @__PURE__ */ jsxRuntime.jsx(
1510
+ "input",
1511
+ {
1512
+ type: "text",
1513
+ value: variableName,
1514
+ onChange: (event) => handleUpdateFilterVariable(variableName, event.target.value),
1515
+ placeholder: t("variableReference"),
1516
+ className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1517
+ }
1518
+ ),
1519
+ /* @__PURE__ */ jsxRuntime.jsx(
1520
+ "button",
1521
+ {
1522
+ type: "button",
1523
+ onClick: () => handleRemoveFilter(variableName),
1524
+ className: "shrink-0 rounded-md p-1 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-500 dark:hover:bg-red-900/20",
1525
+ children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "h-3 w-3" })
1526
+ }
1527
+ )
1528
+ ] }, index)) })
1529
+ ] });
1530
+ case "output":
1531
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
1532
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1533
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1.5 block text-xs font-medium text-gray-700 dark:text-gray-300", children: t("outputVariableLabel") }),
1534
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[10px] text-gray-500 dark:text-gray-400", children: t("outputVariableHelp") }),
1535
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-3 py-2.5 dark:border-white/10 dark:bg-white/[0.03]", children: [
1536
+ /* @__PURE__ */ jsxRuntime.jsx(outline.VariableIcon, { className: "h-4 w-4 text-gray-400" }),
1537
+ /* @__PURE__ */ jsxRuntime.jsx(
1538
+ "input",
1539
+ {
1540
+ type: "text",
1541
+ value: outputVariable,
1542
+ onChange: (event) => setOutputVariable(event.target.value),
1543
+ placeholder: "datasourceResult",
1544
+ className: "flex-1 bg-transparent text-sm text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1545
+ }
1546
+ )
1547
+ ] })
1548
+ ] }),
1549
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1550
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1.5 block text-xs font-medium text-gray-700 dark:text-gray-300", children: t("limitLabel") }),
1551
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[10px] text-gray-500 dark:text-gray-400", children: t("limitHelp") }),
1552
+ /* @__PURE__ */ jsxRuntime.jsx(
1553
+ "input",
1554
+ {
1555
+ type: "number",
1556
+ value: limit,
1557
+ onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
1558
+ min: 1,
1559
+ max: 1e4,
1560
+ className: "w-32 rounded-xl border border-gray-200 bg-white px-3 py-2.5 text-sm text-gray-900 outline-none focus:border-cyan-400 dark:border-white/10 dark:bg-white/[0.03] dark:text-white"
1561
+ }
1562
+ )
1563
+ ] }),
1564
+ selectedDatasource && selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-cyan-500/20 bg-cyan-500/5 p-3 dark:border-cyan-400/15 dark:bg-cyan-400/5", children: [
1565
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-cyan-600 dark:text-cyan-400 mb-2", children: "Summary" }),
1566
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 text-xs text-gray-600 dark:text-gray-300", children: [
1567
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1568
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "Source:" }),
1569
+ " ",
1570
+ selectedDatasource.name,
1571
+ " (",
1572
+ selectedDatasource.dialect,
1573
+ ")"
1574
+ ] }),
1575
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1576
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "Table:" }),
1577
+ " ",
1578
+ selectedTable
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1581
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "Columns:" }),
1582
+ " ",
1583
+ selectedColumns.length,
1584
+ " of ",
1585
+ availableColumns.length
1586
+ ] }),
1587
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1588
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "Filters:" }),
1589
+ " ",
1590
+ filterEntries.length
1591
+ ] }),
1592
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1593
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "Limit:" }),
1594
+ " ",
1595
+ limit
1596
+ ] }),
1597
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1598
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "Output:" }),
1599
+ " ",
1600
+ outputVariable || "\u2014"
1601
+ ] })
1602
+ ] })
1603
+ ] })
1604
+ ] });
1605
+ default:
1606
+ return null;
1607
+ }
1608
+ }
1609
+ const logo = getDatasourceLogo(selectedDatasourceId, selectedDatasource?.dialect);
1610
+ return /* @__PURE__ */ jsxRuntime.jsx(
1611
+ chunkKEUOCEOO_js.GlassModal,
1612
+ {
1613
+ open,
1614
+ onClose: onCancel,
1615
+ title: selectedDatasource?.name ?? t("datasourceLabel"),
1616
+ subtitle: selectedTable ? `${selectedDatasource?.dialect} \xB7 ${selectedTable}` : void 0,
1617
+ icon: logo ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logo, alt: "", className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.ServerStackIcon, { className: "h-5 w-5 text-white" }),
1618
+ gradient: "from-cyan-500 to-blue-600",
1619
+ maxWidth: "3xl",
1620
+ sidebar: {
1621
+ sections: SIDEBAR_SECTIONS,
1622
+ activeSectionId,
1623
+ onSectionChange: setActiveSectionId
1624
+ },
1625
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 px-6 py-3", children: [
1626
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKEUOCEOO_js.Button, { outline: true, onClick: onCancel, children: t("cancel") }),
1627
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKEUOCEOO_js.Button, { color: "cyan", onClick: handleSave, disabled: !canSave, children: t("save") })
1628
+ ] }),
1629
+ children: renderSection()
1630
+ }
1631
+ );
1632
+ }
1158
1633
  function LangChainIcon({ className }) {
1159
1634
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { role: "img", viewBox: "0 0 24 24", fill: "currentColor", className, "aria-label": "LangChain", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.0988 5.9175C2.7359 5.9175 0 8.6462 0 12s2.736 6.0825 6.0988 6.0825h11.8024C21.2641 18.0825 24 15.3538 24 12s-2.736-6.0825-6.0988-6.0825ZM5.9774 7.851c.493.0124 1.02.2496 1.273.6228.3673.4592.4778 1.0668.8944 1.4932.5604.6118 1.199 1.1505 1.7161 1.802.4892.5954.8386 1.2937 1.1436 1.9975.1244.2335.1257.5202.31.7197.0908.1204.5346.4483.4383.5645.0555.1204.4702.286.3263.4027-.1944.04-.4129.0476-.5616-.1074-.0549.126-.183.0596-.2819.0432a4 4 0 0 0-.025.0736c-.3288.0219-.5754-.3126-.732-.565-.3111-.168-.6642-.2702-.982-.446-.0182.2895.0452.6485-.231.8353-.014.5565.8436.0656.9222.4804-.061.0067-.1286-.0095-.1774.0373-.2239.2172-.4805-.1645-.7385-.007-.3464.174-.3808.3161-.8096.352-.0237-.0359-.0143-.0592.0059-.0811.1207-.1399.1295-.3046.3356-.3643-.2122-.0334-.3899.0833-.5686.1757-.2323.095-.2304-.2141-.5878.0164-.0396-.0322-.0208-.0615.0018-.0864.0908-.1107.2102-.127.345-.1208-.663-.3686-.9751.4507-1.2813.0432-.092.0243-.1265.1068-.1845.1652-.05-.0548-.0123-.1212-.0099-.1857-.0598-.028-.1356-.041-.1179-.1366-.1171-.0395-.1988.0295-.286.0952-.0787-.0608.0532-.1492.0776-.2125.0702-.1216.23-.025.3111-.1126.2306-.1308.552.0814.8155.0455.203.0255.4544-.1825.3526-.39-.2171-.2767-.179-.6386-.1839-.9695-.0268-.1929-.491-.4382-.6252-.6462-.1659-.1873-.295-.4047-.4243-.6182-.4666-.9008-.3198-2.0584-.9077-2.8947-.266.1466-.6125.0774-.8418-.119-.1238.1125-.1292.2598-.139.4161-.297-.2962-.2593-.8559-.022-1.1855.0969-.1302.2127-.2373.342-.3316.0292-.0213.0391-.0419.0385-.0747.1174-.5267.5764-.7391 1.0694-.7267m12.4071.46c.5575 0 1.0806.2159 1.474.6082s.61.9145.61 1.4704c0 .556-.2167 1.078-.61 1.4698v.0006l-.902.8995a2.08 2.08 0 0 1-.8597.5166l-.0164.0047-.0058.0164a2.05 2.05 0 0 1-.474.7308l-.9018.8995c-.3934.3924-.917.6083-1.4745.6083s-1.0806-.216-1.474-.6083c-.813-.8107-.813-2.1294 0-2.9402l.9019-.8995a2.056 2.056 0 0 1 .858-.5143l.017-.0053.0058-.0158a2.07 2.07 0 0 1 .4752-.7337l.9018-.8995c.3934-.3924.9171-.6083 1.4745-.6083zm0 .8965a1.18 1.18 0 0 0-.8388.3462l-.9018.8995a1.181 1.181 0 0 0-.3427.9252l.0053.0572c.0323.2652.149.5044.3374.6917.13.1296.2733.2114.4471.2686a.9.9 0 0 1 .014.1582.884.884 0 0 1-.2609.6304l-.0554.0554c-.3013-.1028-.5525-.253-.7794-.4792a2.06 2.06 0 0 1-.5761-1.0968l-.0099-.0578-.0461.0368a1.1 1.1 0 0 0-.0876.0794l-.9024.8995c-.4623.461-.4623 1.212 0 1.673.2311.2305.535.346.8394.3461.3043 0 .6077-.1156.8388-.3462l.9019-.8995c.4623-.461.4623-1.2113 0-1.673a1.17 1.17 0 0 0-.4367-.2749 1 1 0 0 1-.014-.1611c0-.2591.1023-.505.2901-.6923.3019.1028.57.2694.7962.495.3007.2999.4994.679.5756 1.0968l.0105.0578.0455-.0373a1.1 1.1 0 0 0 .0887-.0794l.902-.8996c.4622-.461.4628-1.2124 0-1.6735a1.18 1.18 0 0 0-.8395-.3462Zm-9.973 5.1567-.0006.0006c-.0793.3078-.1048.8318-.506.847-.033.1776.1228.2445.2655.1874.141-.0645.2081.0508.2557.1657.2177.0317.5394-.0725.5516-.3298-.325-.1867-.4253-.5418-.5662-.8709" }) });
1160
1635
  }
@@ -2840,7 +3315,7 @@ var NoteFlowNode = react.memo(function NoteFlowNode2({ data, selected }) {
2840
3315
  }
2841
3316
  );
2842
3317
  });
2843
- var DATASOURCE_LOGOS = {
3318
+ var DATASOURCE_LOGOS2 = {
2844
3319
  bigquery: "/logos/datasources/bigquery.svg",
2845
3320
  postgres: "/logos/datasources/postgres.svg",
2846
3321
  snowflake: "/logos/datasources/snowflake.svg",
@@ -2862,9 +3337,9 @@ var DATASOURCE_LOGOS = {
2862
3337
  firebase: "/logos/datasources/firebase.svg",
2863
3338
  neo4j: "/logos/datasources/neo4j.svg"
2864
3339
  };
2865
- function getDatasourceLogo(datasourceId, dialect) {
3340
+ function getDatasourceLogo2(datasourceId, dialect) {
2866
3341
  const search = (dialect ?? datasourceId).toLowerCase();
2867
- for (const [key, url] of Object.entries(DATASOURCE_LOGOS)) {
3342
+ for (const [key, url] of Object.entries(DATASOURCE_LOGOS2)) {
2868
3343
  if (search.includes(key)) return url;
2869
3344
  }
2870
3345
  return null;
@@ -2891,7 +3366,7 @@ var DatasourceFlowNode = react.memo(function DatasourceFlowNode2({ id, data, sel
2891
3366
  }
2892
3367
  const columnCount = config.selectedColumns?.length ?? 0;
2893
3368
  const filterCount = config.filterVariables ? Object.keys(config.filterVariables).length : 0;
2894
- const logo = getDatasourceLogo(config.datasourceId, config.dialect);
3369
+ const logo = getDatasourceLogo2(config.datasourceId, config.dialect);
2895
3370
  const content = /* @__PURE__ */ jsxRuntime.jsxs(NodeCard, { compact: isCompact, selected, nodeType: "datasource", children: [
2896
3371
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
2897
3372
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
@@ -4859,328 +5334,6 @@ function EntityNodeConfigForm({ config, entities = [], onSave, onCancel }) {
4859
5334
  ] })
4860
5335
  ] });
4861
5336
  }
4862
- var COLUMN_TYPE_BADGE_COLORS = {
4863
- string: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4864
- varchar: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4865
- text: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4866
- integer: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4867
- int: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4868
- bigint: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4869
- number: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4870
- decimal: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4871
- float: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4872
- boolean: "bg-green-100 text-green-600 dark:bg-green-500/20 dark:text-green-300",
4873
- date: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4874
- timestamp: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4875
- datetime: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4876
- json: "bg-purple-100 text-purple-600 dark:bg-purple-500/20 dark:text-purple-300",
4877
- jsonb: "bg-purple-100 text-purple-600 dark:bg-purple-500/20 dark:text-purple-300",
4878
- uuid: "bg-teal-100 text-teal-600 dark:bg-teal-500/20 dark:text-teal-300"
4879
- };
4880
- function DatasourceNodeConfigForm({
4881
- nodeId,
4882
- config,
4883
- onSave,
4884
- onCancel,
4885
- datasources,
4886
- onLoadTables,
4887
- onLoadSchema
4888
- }) {
4889
- const t = chunkYXN2K77G_js.useTranslations("agents.workflow.datasourceNodeConfig");
4890
- const [selectedDatasourceId, setSelectedDatasourceId] = react.useState(config.datasourceId ?? "");
4891
- const [selectedTable, setSelectedTable] = react.useState(config.table ?? "");
4892
- const [availableTables, setAvailableTables] = react.useState([]);
4893
- const [availableColumns, setAvailableColumns] = react.useState([]);
4894
- const [selectedColumns, setSelectedColumns] = react.useState([...config.selectedColumns ?? []]);
4895
- const [outputVariable, setOutputVariable] = react.useState(config.outputVariable);
4896
- const [limit, setLimit] = react.useState(config.limit);
4897
- const [filterVariables, setFilterVariables] = react.useState({ ...config.filterVariables });
4898
- const allColumnNames = availableColumns.map((column) => column.name);
4899
- const allSelected = selectedColumns.length > 0 && selectedColumns.length === allColumnNames.length;
4900
- const selectedDatasource = datasources.find((datasource) => datasource.id === selectedDatasourceId);
4901
- const loadTables = react.useCallback(async (datasourceId) => {
4902
- if (!datasourceId) {
4903
- setAvailableTables([]);
4904
- return;
4905
- }
4906
- const tables = await onLoadTables(datasourceId);
4907
- setAvailableTables(tables);
4908
- }, [onLoadTables]);
4909
- const loadSchema = react.useCallback(async (datasourceId, table) => {
4910
- if (!datasourceId || !table) {
4911
- setAvailableColumns([]);
4912
- return;
4913
- }
4914
- const columns = await onLoadSchema(datasourceId, table);
4915
- setAvailableColumns(columns);
4916
- }, [onLoadSchema]);
4917
- react.useEffect(() => {
4918
- if (selectedDatasourceId) {
4919
- loadTables(selectedDatasourceId);
4920
- }
4921
- }, [selectedDatasourceId, loadTables]);
4922
- react.useEffect(() => {
4923
- if (selectedDatasourceId && selectedTable) {
4924
- loadSchema(selectedDatasourceId, selectedTable);
4925
- }
4926
- }, [selectedDatasourceId, selectedTable, loadSchema]);
4927
- const handleDatasourceChange = (datasourceId) => {
4928
- setSelectedDatasourceId(datasourceId);
4929
- setSelectedTable("");
4930
- setAvailableTables([]);
4931
- setAvailableColumns([]);
4932
- setSelectedColumns([]);
4933
- setFilterVariables({});
4934
- };
4935
- const handleTableChange = (table) => {
4936
- setSelectedTable(table);
4937
- setAvailableColumns([]);
4938
- setSelectedColumns([]);
4939
- setFilterVariables({});
4940
- };
4941
- const handleToggleSelectAll = () => {
4942
- if (allSelected) {
4943
- setSelectedColumns([]);
4944
- } else {
4945
- setSelectedColumns([...allColumnNames]);
4946
- }
4947
- };
4948
- const handleToggleColumn = (columnName) => {
4949
- setSelectedColumns(
4950
- (previous) => previous.includes(columnName) ? previous.filter((name) => name !== columnName) : [...previous, columnName]
4951
- );
4952
- };
4953
- const handleAddFilter = () => {
4954
- setFilterVariables((previous) => ({ ...previous, "": "" }));
4955
- };
4956
- const handleUpdateFilterVariable = (oldKey, newKey) => {
4957
- setFilterVariables((previous) => {
4958
- const updated = { ...previous };
4959
- const value = updated[oldKey] ?? "";
4960
- delete updated[oldKey];
4961
- updated[newKey] = value;
4962
- return updated;
4963
- });
4964
- };
4965
- const handleUpdateFilterField = (key, newValue) => {
4966
- setFilterVariables((previous) => ({ ...previous, [key]: newValue }));
4967
- };
4968
- const handleRemoveFilter = (key) => {
4969
- setFilterVariables((previous) => {
4970
- const updated = { ...previous };
4971
- delete updated[key];
4972
- return updated;
4973
- });
4974
- };
4975
- const handleSave = () => {
4976
- const cleanedFilters = {};
4977
- for (const [key, value] of Object.entries(filterVariables)) {
4978
- if (key.trim() && value.trim()) {
4979
- cleanedFilters[key.trim()] = value.trim();
4980
- }
4981
- }
4982
- onSave({
4983
- ...config,
4984
- datasourceId: selectedDatasourceId,
4985
- dialect: selectedDatasource?.dialect ?? "",
4986
- table: selectedTable,
4987
- selectedColumns,
4988
- outputVariable: outputVariable.trim(),
4989
- limit,
4990
- filterVariables: cleanedFilters
4991
- });
4992
- };
4993
- const filterEntries = Object.entries(filterVariables);
4994
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
4995
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4996
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("datasourceLabel") }),
4997
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("datasourceHelp") }),
4998
- /* @__PURE__ */ jsxRuntime.jsxs(
4999
- "select",
5000
- {
5001
- value: selectedDatasourceId,
5002
- onChange: (event) => handleDatasourceChange(event.target.value),
5003
- className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white",
5004
- children: [
5005
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("selectDatasource") }),
5006
- datasources.map((datasource) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: datasource.id, children: [
5007
- datasource.name,
5008
- " (",
5009
- datasource.dialect,
5010
- ")"
5011
- ] }, datasource.id))
5012
- ]
5013
- }
5014
- ),
5015
- selectedDatasource && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-300", children: selectedDatasource.dialect }) })
5016
- ] }),
5017
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5018
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("tableLabel") }),
5019
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("tableHelp") }),
5020
- /* @__PURE__ */ jsxRuntime.jsxs(
5021
- "select",
5022
- {
5023
- value: selectedTable,
5024
- onChange: (event) => handleTableChange(event.target.value),
5025
- disabled: !selectedDatasourceId,
5026
- className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-white",
5027
- children: [
5028
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("selectTable") }),
5029
- availableTables.map((table) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: table, children: table }, table))
5030
- ]
5031
- }
5032
- )
5033
- ] }),
5034
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5035
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("outputVariableLabel") }),
5036
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("outputVariableHelp") }),
5037
- /* @__PURE__ */ jsxRuntime.jsx(
5038
- "input",
5039
- {
5040
- type: "text",
5041
- value: outputVariable,
5042
- onChange: (event) => setOutputVariable(event.target.value),
5043
- placeholder: "datasourceResult",
5044
- className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 placeholder-gray-400 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
5045
- }
5046
- )
5047
- ] }),
5048
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5049
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("limitLabel") }),
5050
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("limitHelp") }),
5051
- /* @__PURE__ */ jsxRuntime.jsx(
5052
- "input",
5053
- {
5054
- type: "number",
5055
- value: limit,
5056
- onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
5057
- min: 1,
5058
- max: 1e4,
5059
- className: "w-32 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white"
5060
- }
5061
- )
5062
- ] }),
5063
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5064
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
5065
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("columnsLabel") }),
5066
- /* @__PURE__ */ jsxRuntime.jsx(
5067
- "button",
5068
- {
5069
- type: "button",
5070
- onClick: handleToggleSelectAll,
5071
- disabled: availableColumns.length === 0,
5072
- className: "text-xs font-medium text-indigo-600 hover:text-indigo-700 disabled:cursor-not-allowed disabled:opacity-50 dark:text-indigo-400 dark:hover:text-indigo-300",
5073
- children: allSelected ? t("deselectAll") : t("selectAll")
5074
- }
5075
- )
5076
- ] }),
5077
- selectedColumns.length === 0 && availableColumns.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-amber-600 dark:text-amber-400", children: t("noColumnsSelected") }),
5078
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-48 space-y-1 overflow-y-auto rounded-lg border border-gray-200 p-2 dark:border-gray-700", children: [
5079
- availableColumns.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 py-2 text-xs text-gray-500 dark:text-gray-400", children: t("noColumnsAvailable") }),
5080
- availableColumns.map((column) => {
5081
- const isSelected = selectedColumns.includes(column.name);
5082
- const typeBadgeColor = COLUMN_TYPE_BADGE_COLORS[column.type.toLowerCase()] ?? COLUMN_TYPE_BADGE_COLORS.string;
5083
- return /* @__PURE__ */ jsxRuntime.jsxs(
5084
- "label",
5085
- {
5086
- className: `flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 transition-colors ${isSelected ? "bg-indigo-50 dark:bg-indigo-500/10" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
5087
- children: [
5088
- /* @__PURE__ */ jsxRuntime.jsx(
5089
- "input",
5090
- {
5091
- type: "checkbox",
5092
- checked: isSelected,
5093
- onChange: () => handleToggleColumn(column.name),
5094
- className: "h-3.5 w-3.5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600"
5095
- }
5096
- ),
5097
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1 text-xs font-medium text-gray-900 dark:text-white", children: [
5098
- column.name,
5099
- column.nullable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-[9px] text-gray-400 dark:text-gray-500", children: "?" })
5100
- ] }),
5101
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeBadgeColor}`, children: column.type })
5102
- ]
5103
- },
5104
- column.name
5105
- );
5106
- })
5107
- ] })
5108
- ] }),
5109
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5110
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
5111
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("filtersLabel") }),
5112
- /* @__PURE__ */ jsxRuntime.jsxs(
5113
- "button",
5114
- {
5115
- type: "button",
5116
- onClick: handleAddFilter,
5117
- className: "flex items-center gap-1 text-xs font-medium text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 dark:hover:text-indigo-300",
5118
- children: [
5119
- /* @__PURE__ */ jsxRuntime.jsx(outline.PlusIcon, { className: "h-3 w-3" }),
5120
- t("addFilter")
5121
- ]
5122
- }
5123
- )
5124
- ] }),
5125
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("filtersHelp") }),
5126
- filterEntries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: filterEntries.map(([variableName, columnName], index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
5127
- /* @__PURE__ */ jsxRuntime.jsxs(
5128
- "select",
5129
- {
5130
- value: columnName,
5131
- onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
5132
- className: "flex-1 rounded-lg border border-gray-300 bg-white px-2 py-1.5 text-xs text-gray-900 outline-none focus:border-indigo-400 focus:ring-1 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white",
5133
- children: [
5134
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("columnName") }),
5135
- availableColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: column.name, children: column.name }, column.name))
5136
- ]
5137
- }
5138
- ),
5139
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-400", children: "=" }),
5140
- /* @__PURE__ */ jsxRuntime.jsx(
5141
- "input",
5142
- {
5143
- type: "text",
5144
- value: variableName,
5145
- onChange: (event) => handleUpdateFilterVariable(variableName, event.target.value),
5146
- placeholder: t("variableReference"),
5147
- className: "flex-1 rounded-lg border border-gray-300 bg-white px-2 py-1.5 text-xs text-gray-900 placeholder-gray-400 outline-none focus:border-indigo-400 focus:ring-1 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
5148
- }
5149
- ),
5150
- /* @__PURE__ */ jsxRuntime.jsx(
5151
- "button",
5152
- {
5153
- type: "button",
5154
- onClick: () => handleRemoveFilter(variableName),
5155
- className: "rounded-md p-1 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20",
5156
- children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "h-3.5 w-3.5" })
5157
- }
5158
- )
5159
- ] }, index)) })
5160
- ] }),
5161
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 border-t border-gray-200 pt-4 dark:border-gray-700", children: [
5162
- /* @__PURE__ */ jsxRuntime.jsx(
5163
- "button",
5164
- {
5165
- type: "button",
5166
- onClick: onCancel,
5167
- className: "rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800",
5168
- children: t("cancel")
5169
- }
5170
- ),
5171
- /* @__PURE__ */ jsxRuntime.jsx(
5172
- "button",
5173
- {
5174
- type: "button",
5175
- onClick: handleSave,
5176
- disabled: !selectedDatasourceId || !selectedTable || selectedColumns.length === 0,
5177
- className: "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-indigo-500 dark:hover:bg-indigo-600",
5178
- children: t("save")
5179
- }
5180
- )
5181
- ] })
5182
- ] });
5183
- }
5184
5337
  var GROUP_COLOR_OPTIONS = [
5185
5338
  { value: "indigo", ring: "ring-indigo-500", fill: "bg-indigo-500" },
5186
5339
  { value: "teal", ring: "ring-teal-500", fill: "bg-teal-500" },
@@ -5542,18 +5695,8 @@ function LogicNodeModal({ onSave, entities = [], datasources = [], onLoadTables,
5542
5695
  case "iteration_start":
5543
5696
  return /* @__PURE__ */ jsxRuntime.jsx(IterationStartNodeConfigForm, { config, onSave: handleSave, onCancel: closeModal });
5544
5697
  case "datasource":
5545
- return /* @__PURE__ */ jsxRuntime.jsx(
5546
- DatasourceNodeConfigForm,
5547
- {
5548
- nodeId,
5549
- config,
5550
- onSave: handleSave,
5551
- onCancel: closeModal,
5552
- datasources,
5553
- onLoadTables: onLoadTables ?? (async () => []),
5554
- onLoadSchema: onLoadSchema ?? (async () => [])
5555
- }
5556
- );
5698
+ return null;
5699
+ // Datasource uses its own GlassModal with sidebar — rendered separately
5557
5700
  case "entity":
5558
5701
  return /* @__PURE__ */ jsxRuntime.jsx(EntityNodeConfigForm, { config, entities, onSave: handleSave, onCancel: closeModal });
5559
5702
  case "group":
@@ -5985,6 +6128,9 @@ function WorkflowCanvasInner({
5985
6128
  agentTools = [],
5986
6129
  rules,
5987
6130
  entities = [],
6131
+ datasources = [],
6132
+ onLoadTables,
6133
+ onLoadSchema,
5988
6134
  initialGraph,
5989
6135
  onGraphChange,
5990
6136
  onEditTool,
@@ -7341,7 +7487,7 @@ function WorkflowCanvasInner({
7341
7487
  const handleEdgeClick = react.useCallback(() => {
7342
7488
  closeContextMenu();
7343
7489
  }, [closeContextMenu]);
7344
- react.useMemo(() => {
7490
+ const editingLogicNode = react.useMemo(() => {
7345
7491
  if (!editingLogicNodeId) return null;
7346
7492
  const node = nodes.find((matchingNode) => matchingNode.id === editingLogicNodeId);
7347
7493
  if (!node) return null;
@@ -7517,6 +7663,22 @@ function WorkflowCanvasInner({
7517
7663
  },
7518
7664
  entities: allEntities
7519
7665
  }
7666
+ ),
7667
+ editingLogicNode?.config?.type === "datasource" && /* @__PURE__ */ jsxRuntime.jsx(
7668
+ DatasourceNodeConfigForm,
7669
+ {
7670
+ open: true,
7671
+ nodeId: editingLogicNode.nodeId,
7672
+ config: editingLogicNode.config,
7673
+ onSave: (updatedConfig) => {
7674
+ handleSaveLogicNodeConfig(editingLogicNode.nodeId, updatedConfig);
7675
+ setEditingLogicNodeId(null);
7676
+ },
7677
+ onCancel: () => setEditingLogicNodeId(null),
7678
+ datasources,
7679
+ onLoadTables: onLoadTables ?? (async () => []),
7680
+ onLoadSchema: onLoadSchema ?? (async () => [])
7681
+ }
7520
7682
  )
7521
7683
  ] });
7522
7684
  }
@@ -7718,5 +7880,5 @@ exports.useModalStore = useModalStore;
7718
7880
  exports.useWorkflowBuilderClient = useWorkflowBuilderClient;
7719
7881
  exports.useWorkflowBuilderClientOptional = useWorkflowBuilderClientOptional;
7720
7882
  exports.useWorkflowStore = useWorkflowStore;
7721
- //# sourceMappingURL=chunk-YI6QMBKC.js.map
7722
- //# sourceMappingURL=chunk-YI6QMBKC.js.map
7883
+ //# sourceMappingURL=chunk-36EAW7JS.js.map
7884
+ //# sourceMappingURL=chunk-36EAW7JS.js.map