@datatechsolutions/ui 2.11.43 → 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: [
@@ -4512,331 +4987,54 @@ function ListOperatorNodeConfigForm({ config, onSave, onCancel }) {
4512
4987
  "input",
4513
4988
  {
4514
4989
  type: "text",
4515
- value: condition,
4516
- onChange: (event) => setCondition(event.target.value),
4517
- placeholder: t("conditionPlaceholder"),
4518
- 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"
4519
- }
4520
- )
4521
- ] }),
4522
- showSortFields && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4523
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4524
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("sortKeyLabel") }),
4525
- /* @__PURE__ */ jsxRuntime.jsx(
4526
- "input",
4527
- {
4528
- type: "text",
4529
- value: sortKey,
4530
- onChange: (event) => setSortKey(event.target.value),
4531
- placeholder: t("sortKeyPlaceholder"),
4532
- 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"
4533
- }
4534
- )
4535
- ] }),
4536
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4537
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("sortOrderLabel") }),
4538
- /* @__PURE__ */ jsxRuntime.jsx(
4539
- "select",
4540
- {
4541
- value: sortOrder,
4542
- onChange: (event) => setSortOrder(event.target.value),
4543
- 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",
4544
- children: SORT_ORDER_OPTIONS.map((order) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: order, children: t(`sortOrder_${order}`) }, order))
4545
- }
4546
- )
4547
- ] })
4548
- ] }),
4549
- showLimitField && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4550
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("limitCountLabel") }),
4551
- /* @__PURE__ */ jsxRuntime.jsx(
4552
- "input",
4553
- {
4554
- type: "number",
4555
- value: limitCount,
4556
- onChange: (event) => setLimitCount(Number(event.target.value)),
4557
- min: 1,
4558
- 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"
4559
- }
4560
- )
4561
- ] }),
4562
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
4563
- /* @__PURE__ */ jsxRuntime.jsx(
4564
- "button",
4565
- {
4566
- type: "button",
4567
- onClick: onCancel,
4568
- 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",
4569
- children: t("cancel")
4570
- }
4571
- ),
4572
- /* @__PURE__ */ jsxRuntime.jsx(
4573
- "button",
4574
- {
4575
- type: "button",
4576
- onClick: handleSave,
4577
- className: "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600",
4578
- children: t("save")
4579
- }
4580
- )
4581
- ] })
4582
- ] });
4583
- }
4584
- function IterationStartNodeConfigForm({ config, onSave, onCancel }) {
4585
- const t = chunkYXN2K77G_js.useTranslations("agents.workflow.iterationStartNodeConfig");
4586
- const [iteratorVariable, setIteratorVariable] = react.useState(config.iteratorVariable);
4587
- const [itemVariable, setItemVariable] = react.useState(config.itemVariable);
4588
- const [indexVariable, setIndexVariable] = react.useState(config.indexVariable);
4589
- const handleSave = () => {
4590
- onSave({ ...config, iteratorVariable, itemVariable, indexVariable });
4591
- };
4592
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
4593
- /* @__PURE__ */ jsxRuntime.jsx(
4594
- chunkKEUOCEOO_js.FormInput,
4595
- {
4596
- type: "text",
4597
- label: t("iteratorVariableLabel"),
4598
- value: iteratorVariable,
4599
- onValueChange: setIteratorVariable,
4600
- placeholder: t("iteratorVariablePlaceholder")
4601
- }
4602
- ),
4603
- /* @__PURE__ */ jsxRuntime.jsx(
4604
- chunkKEUOCEOO_js.FormInput,
4605
- {
4606
- type: "text",
4607
- label: t("itemVariableLabel"),
4608
- value: itemVariable,
4609
- onValueChange: setItemVariable,
4610
- placeholder: t("itemVariablePlaceholder")
4611
- }
4612
- ),
4613
- /* @__PURE__ */ jsxRuntime.jsx(
4614
- chunkKEUOCEOO_js.FormInput,
4615
- {
4616
- type: "text",
4617
- label: t("indexVariableLabel"),
4618
- value: indexVariable,
4619
- onValueChange: setIndexVariable,
4620
- placeholder: t("indexVariablePlaceholder")
4621
- }
4622
- ),
4623
- /* @__PURE__ */ jsxRuntime.jsx(
4624
- ConfigFormActions,
4625
- {
4626
- cancelLabel: t("cancel"),
4627
- saveLabel: t("save"),
4628
- onCancel,
4629
- onSave: handleSave
4630
- }
4631
- )
4632
- ] });
4633
- }
4634
- var FIELD_TYPE_BADGE_COLORS = {
4635
- string: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4636
- number: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4637
- boolean: "bg-green-100 text-green-600 dark:bg-green-500/20 dark:text-green-300",
4638
- date: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4639
- object: "bg-purple-100 text-purple-600 dark:bg-purple-500/20 dark:text-purple-300",
4640
- array: "bg-teal-100 text-teal-600 dark:bg-teal-500/20 dark:text-teal-300"
4641
- };
4642
- function EntityNodeConfigForm({ config, entities = [], onSave, onCancel }) {
4643
- const t = chunkYXN2K77G_js.useTranslations("agents.workflow.entityNodeConfig");
4644
- const [selectedFields, setSelectedFields] = react.useState([...config.selectedFields]);
4645
- const [outputVariable, setOutputVariable] = react.useState(config.outputVariable);
4646
- const [limit, setLimit] = react.useState(config.limit);
4647
- const [filterVariables, setFilterVariables] = react.useState({ ...config.filterVariables });
4648
- const entityDefinition = react.useMemo(
4649
- () => entities.find((entity) => entity.id === config.entityMasterId),
4650
- [entities, config.entityMasterId]
4651
- );
4652
- const availableFields = react.useMemo(() => entityDefinition?.fields ?? [], [entityDefinition]);
4653
- const allFieldNames = react.useMemo(() => availableFields.map((field) => field.name), [availableFields]);
4654
- const allSelected = selectedFields.length === allFieldNames.length;
4655
- const gradient = getEntityGradient(config.entityMasterId);
4656
- const badgeColor = getEntityBadgeColor(config.entityMasterId);
4657
- const handleToggleSelectAll = () => {
4658
- if (allSelected) {
4659
- setSelectedFields([]);
4660
- } else {
4661
- setSelectedFields([...allFieldNames]);
4662
- }
4663
- };
4664
- const handleToggleField = (fieldName) => {
4665
- setSelectedFields(
4666
- (previous) => previous.includes(fieldName) ? previous.filter((name) => name !== fieldName) : [...previous, fieldName]
4667
- );
4668
- };
4669
- const handleAddFilter = () => {
4670
- setFilterVariables((previous) => ({ ...previous, "": "" }));
4671
- };
4672
- const handleUpdateFilterVariable = (oldKey, newKey) => {
4673
- setFilterVariables((previous) => {
4674
- const updated = { ...previous };
4675
- const value = updated[oldKey] ?? "";
4676
- delete updated[oldKey];
4677
- updated[newKey] = value;
4678
- return updated;
4679
- });
4680
- };
4681
- const handleUpdateFilterField = (key, newValue) => {
4682
- setFilterVariables((previous) => ({ ...previous, [key]: newValue }));
4683
- };
4684
- const handleRemoveFilter = (key) => {
4685
- setFilterVariables((previous) => {
4686
- const updated = { ...previous };
4687
- delete updated[key];
4688
- return updated;
4689
- });
4690
- };
4691
- const handleSave = () => {
4692
- const cleanedFilters = {};
4693
- for (const [key, value] of Object.entries(filterVariables)) {
4694
- if (key.trim() && value.trim()) {
4695
- cleanedFilters[key.trim()] = value.trim();
4696
- }
4697
- }
4698
- onSave({
4699
- ...config,
4700
- selectedFields,
4701
- outputVariable: outputVariable.trim(),
4702
- limit,
4703
- filterVariables: cleanedFilters
4704
- });
4705
- };
4706
- const filterEntries = Object.entries(filterVariables);
4707
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
4708
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4709
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("entityTypeLabel") }),
4710
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4711
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br ${gradient}`, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-white font-bold", children: (entityDefinition?.label ?? config.entityMasterId ?? "?").charAt(0).toUpperCase() }) }),
4712
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${badgeColor}`, children: entityDefinition?.label ?? config.entityMasterId ?? t("entityTypeLabel") })
4713
- ] }),
4714
- !entityDefinition && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-xs text-amber-600 dark:text-amber-400", children: t("entityNotConfigured") })
4715
- ] }),
4716
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4717
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("outputVariableLabel") }),
4718
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("outputVariableHelp") }),
4719
- /* @__PURE__ */ jsxRuntime.jsx(
4720
- "input",
4721
- {
4722
- type: "text",
4723
- value: outputVariable,
4724
- onChange: (event) => setOutputVariable(event.target.value),
4725
- placeholder: `${(entityDefinition?.label ?? "entity").replace(/\s+/g, "")}Data`,
4726
- 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"
4727
- }
4728
- )
4729
- ] }),
4730
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4731
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("limitLabel") }),
4732
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("limitHelp") }),
4733
- /* @__PURE__ */ jsxRuntime.jsx(
4734
- "input",
4735
- {
4736
- type: "number",
4737
- value: limit,
4738
- onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
4739
- min: 1,
4740
- max: 1e3,
4741
- 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"
4990
+ value: condition,
4991
+ onChange: (event) => setCondition(event.target.value),
4992
+ placeholder: t("conditionPlaceholder"),
4993
+ 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"
4742
4994
  }
4743
4995
  )
4744
4996
  ] }),
4745
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4746
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
4747
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("fieldsLabel") }),
4997
+ showSortFields && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4998
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4999
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("sortKeyLabel") }),
4748
5000
  /* @__PURE__ */ jsxRuntime.jsx(
4749
- "button",
4750
- {
4751
- type: "button",
4752
- onClick: handleToggleSelectAll,
4753
- className: "text-xs font-medium text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 dark:hover:text-indigo-300",
4754
- children: allSelected ? t("deselectAll") : t("selectAll")
4755
- }
4756
- )
4757
- ] }),
4758
- selectedFields.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-amber-600 dark:text-amber-400", children: t("noFieldsSelected") }),
4759
- /* @__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: [
4760
- availableFields.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 py-2 text-xs text-gray-500 dark:text-gray-400", children: t("noFieldsSelected") }),
4761
- availableFields.map((field) => {
4762
- const isSelected = selectedFields.includes(field.name);
4763
- const typeBadgeColor = FIELD_TYPE_BADGE_COLORS[field.type] ?? FIELD_TYPE_BADGE_COLORS.string;
4764
- return /* @__PURE__ */ jsxRuntime.jsxs(
4765
- "label",
4766
- {
4767
- 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"}`,
4768
- children: [
4769
- /* @__PURE__ */ jsxRuntime.jsx(
4770
- "input",
4771
- {
4772
- type: "checkbox",
4773
- checked: isSelected,
4774
- onChange: () => handleToggleField(field.name),
4775
- className: "h-3.5 w-3.5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600"
4776
- }
4777
- ),
4778
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-xs font-medium text-gray-900 dark:text-white", children: field.name }),
4779
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeBadgeColor}`, children: field.type })
4780
- ]
4781
- },
4782
- field.name
4783
- );
4784
- })
4785
- ] })
4786
- ] }),
4787
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4788
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
4789
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("filtersLabel") }),
4790
- /* @__PURE__ */ jsxRuntime.jsxs(
4791
- "button",
5001
+ "input",
4792
5002
  {
4793
- type: "button",
4794
- onClick: handleAddFilter,
4795
- 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",
4796
- children: [
4797
- /* @__PURE__ */ jsxRuntime.jsx(outline.PlusIcon, { className: "h-3 w-3" }),
4798
- t("addFilter")
4799
- ]
5003
+ type: "text",
5004
+ value: sortKey,
5005
+ onChange: (event) => setSortKey(event.target.value),
5006
+ placeholder: t("sortKeyPlaceholder"),
5007
+ 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"
4800
5008
  }
4801
5009
  )
4802
5010
  ] }),
4803
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("filtersHelp") }),
4804
- filterEntries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: filterEntries.map(([variableName, fieldName], index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
5011
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5012
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("sortOrderLabel") }),
4805
5013
  /* @__PURE__ */ jsxRuntime.jsx(
4806
- "input",
4807
- {
4808
- type: "text",
4809
- value: variableName,
4810
- onChange: (event) => handleUpdateFilterVariable(variableName, event.target.value),
4811
- placeholder: t("variableName"),
4812
- 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"
4813
- }
4814
- ),
4815
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-400", children: "\u2192" }),
4816
- /* @__PURE__ */ jsxRuntime.jsxs(
4817
5014
  "select",
4818
5015
  {
4819
- value: fieldName,
4820
- onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
4821
- 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",
4822
- children: [
4823
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("fieldName") }),
4824
- availableFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: field.name, children: field.name }, field.name))
4825
- ]
4826
- }
4827
- ),
4828
- /* @__PURE__ */ jsxRuntime.jsx(
4829
- "button",
4830
- {
4831
- type: "button",
4832
- onClick: () => handleRemoveFilter(variableName),
4833
- className: "rounded-md p-1 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20",
4834
- children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "h-3.5 w-3.5" })
5016
+ value: sortOrder,
5017
+ onChange: (event) => setSortOrder(event.target.value),
5018
+ 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",
5019
+ children: SORT_ORDER_OPTIONS.map((order) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: order, children: t(`sortOrder_${order}`) }, order))
4835
5020
  }
4836
5021
  )
4837
- ] }, index)) })
5022
+ ] })
4838
5023
  ] }),
4839
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 border-t border-gray-200 pt-4 dark:border-gray-700", children: [
5024
+ showLimitField && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5025
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("limitCountLabel") }),
5026
+ /* @__PURE__ */ jsxRuntime.jsx(
5027
+ "input",
5028
+ {
5029
+ type: "number",
5030
+ value: limitCount,
5031
+ onChange: (event) => setLimitCount(Number(event.target.value)),
5032
+ min: 1,
5033
+ 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"
5034
+ }
5035
+ )
5036
+ ] }),
5037
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
4840
5038
  /* @__PURE__ */ jsxRuntime.jsx(
4841
5039
  "button",
4842
5040
  {
@@ -4851,149 +5049,100 @@ function EntityNodeConfigForm({ config, entities = [], onSave, onCancel }) {
4851
5049
  {
4852
5050
  type: "button",
4853
5051
  onClick: handleSave,
4854
- disabled: selectedFields.length === 0,
4855
- 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",
5052
+ className: "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600",
4856
5053
  children: t("save")
4857
5054
  }
4858
5055
  )
4859
5056
  ] })
4860
5057
  ] });
4861
5058
  }
4862
- var DATASOURCE_LOGOS2 = {
4863
- bigquery: "/logos/datasources/bigquery.svg",
4864
- postgres: "/logos/datasources/postgres.svg",
4865
- snowflake: "/logos/datasources/snowflake.svg",
4866
- mongodb: "/logos/datasources/mongodb.svg",
4867
- redis: "/logos/datasources/redis.svg",
4868
- mysql: "/logos/datasources/mysql.svg",
4869
- clickhouse: "/logos/datasources/clickhouse.svg",
4870
- elasticsearch: "/logos/datasources/elasticsearch.svg",
4871
- duckdb: "/logos/datasources/duckdb.svg",
4872
- sqlite: "/logos/datasources/sqlite.svg",
4873
- mariadb: "/logos/datasources/mariadb.svg",
4874
- oracle: "/logos/datasources/oracle.svg",
4875
- mssql: "/logos/datasources/mssql.svg",
4876
- sqlserver: "/logos/datasources/mssql.svg",
4877
- cassandra: "/logos/datasources/cassandra.svg",
4878
- dynamodb: "/logos/datasources/dynamodb.svg",
4879
- cockroach: "/logos/datasources/cockroachdb.svg",
4880
- supabase: "/logos/datasources/supabase.svg",
4881
- firebase: "/logos/datasources/firebase.svg",
4882
- neo4j: "/logos/datasources/neo4j.svg"
4883
- };
4884
- function getDatasourceLogo2(datasourceId, dialect) {
4885
- const search = (dialect ?? datasourceId).toLowerCase();
4886
- for (const [key, url] of Object.entries(DATASOURCE_LOGOS2)) {
4887
- if (search.includes(key)) return url;
4888
- }
4889
- return null;
4890
- }
4891
- var TYPE_COLORS = {
4892
- string: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
4893
- varchar: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
4894
- text: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
4895
- integer: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
4896
- int: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
4897
- bigint: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
4898
- number: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
4899
- decimal: "bg-indigo-500/10 text-indigo-600 dark:text-indigo-400",
4900
- float: "bg-indigo-500/10 text-indigo-600 dark:text-indigo-400",
4901
- boolean: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
4902
- date: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
4903
- timestamp: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
4904
- datetime: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
4905
- json: "bg-violet-500/10 text-violet-600 dark:text-violet-400",
4906
- jsonb: "bg-violet-500/10 text-violet-600 dark:text-violet-400",
4907
- uuid: "bg-teal-500/10 text-teal-600 dark:text-teal-400",
4908
- array: "bg-pink-500/10 text-pink-600 dark:text-pink-400"
4909
- };
4910
- function SectionHeader({ icon: Icon, title, badge }) {
4911
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
4912
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 text-gray-400 dark:text-gray-500" }),
4913
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: title }),
4914
- badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto rounded-full bg-indigo-500/10 px-2 py-0.5 text-[10px] font-semibold text-indigo-600 dark:text-indigo-400", children: badge })
5059
+ function IterationStartNodeConfigForm({ config, onSave, onCancel }) {
5060
+ const t = chunkYXN2K77G_js.useTranslations("agents.workflow.iterationStartNodeConfig");
5061
+ const [iteratorVariable, setIteratorVariable] = react.useState(config.iteratorVariable);
5062
+ const [itemVariable, setItemVariable] = react.useState(config.itemVariable);
5063
+ const [indexVariable, setIndexVariable] = react.useState(config.indexVariable);
5064
+ const handleSave = () => {
5065
+ onSave({ ...config, iteratorVariable, itemVariable, indexVariable });
5066
+ };
5067
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
5068
+ /* @__PURE__ */ jsxRuntime.jsx(
5069
+ chunkKEUOCEOO_js.FormInput,
5070
+ {
5071
+ type: "text",
5072
+ label: t("iteratorVariableLabel"),
5073
+ value: iteratorVariable,
5074
+ onValueChange: setIteratorVariable,
5075
+ placeholder: t("iteratorVariablePlaceholder")
5076
+ }
5077
+ ),
5078
+ /* @__PURE__ */ jsxRuntime.jsx(
5079
+ chunkKEUOCEOO_js.FormInput,
5080
+ {
5081
+ type: "text",
5082
+ label: t("itemVariableLabel"),
5083
+ value: itemVariable,
5084
+ onValueChange: setItemVariable,
5085
+ placeholder: t("itemVariablePlaceholder")
5086
+ }
5087
+ ),
5088
+ /* @__PURE__ */ jsxRuntime.jsx(
5089
+ chunkKEUOCEOO_js.FormInput,
5090
+ {
5091
+ type: "text",
5092
+ label: t("indexVariableLabel"),
5093
+ value: indexVariable,
5094
+ onValueChange: setIndexVariable,
5095
+ placeholder: t("indexVariablePlaceholder")
5096
+ }
5097
+ ),
5098
+ /* @__PURE__ */ jsxRuntime.jsx(
5099
+ ConfigFormActions,
5100
+ {
5101
+ cancelLabel: t("cancel"),
5102
+ saveLabel: t("save"),
5103
+ onCancel,
5104
+ onSave: handleSave
5105
+ }
5106
+ )
4915
5107
  ] });
4916
5108
  }
4917
- function DatasourceNodeConfigForm({
4918
- nodeId,
4919
- config,
4920
- onSave,
4921
- onCancel,
4922
- datasources,
4923
- onLoadTables,
4924
- onLoadSchema
4925
- }) {
4926
- const t = chunkYXN2K77G_js.useTranslations("agents.workflow.datasourceNodeConfig");
4927
- const [selectedDatasourceId, setSelectedDatasourceId] = react.useState(config.datasourceId ?? "");
4928
- const [selectedTable, setSelectedTable] = react.useState(config.table ?? "");
4929
- const [availableTables, setAvailableTables] = react.useState([]);
4930
- const [availableColumns, setAvailableColumns] = react.useState([]);
4931
- const [selectedColumns, setSelectedColumns] = react.useState([...config.selectedColumns ?? []]);
4932
- const [outputVariable, setOutputVariable] = react.useState(config.outputVariable);
4933
- const [limit, setLimit] = react.useState(config.limit);
4934
- const [filterVariables, setFilterVariables] = react.useState({ ...config.filterVariables });
4935
- const [tableSearch, setTableSearch] = react.useState("");
4936
- const [columnSearch, setColumnSearch] = react.useState("");
4937
- const allColumnNames = availableColumns.map((column) => column.name);
4938
- const allSelected = selectedColumns.length > 0 && selectedColumns.length === allColumnNames.length;
4939
- const selectedDatasource = datasources.find((datasource) => datasource.id === selectedDatasourceId);
4940
- const filteredTables = react.useMemo(
4941
- () => tableSearch ? availableTables.filter((table) => table.toLowerCase().includes(tableSearch.toLowerCase())) : availableTables,
4942
- [availableTables, tableSearch]
4943
- );
4944
- const filteredColumns = react.useMemo(
4945
- () => columnSearch ? availableColumns.filter((column) => column.name.toLowerCase().includes(columnSearch.toLowerCase())) : availableColumns,
4946
- [availableColumns, columnSearch]
5109
+ var FIELD_TYPE_BADGE_COLORS = {
5110
+ string: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
5111
+ number: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
5112
+ boolean: "bg-green-100 text-green-600 dark:bg-green-500/20 dark:text-green-300",
5113
+ date: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
5114
+ object: "bg-purple-100 text-purple-600 dark:bg-purple-500/20 dark:text-purple-300",
5115
+ array: "bg-teal-100 text-teal-600 dark:bg-teal-500/20 dark:text-teal-300"
5116
+ };
5117
+ function EntityNodeConfigForm({ config, entities = [], onSave, onCancel }) {
5118
+ const t = chunkYXN2K77G_js.useTranslations("agents.workflow.entityNodeConfig");
5119
+ const [selectedFields, setSelectedFields] = react.useState([...config.selectedFields]);
5120
+ const [outputVariable, setOutputVariable] = react.useState(config.outputVariable);
5121
+ const [limit, setLimit] = react.useState(config.limit);
5122
+ const [filterVariables, setFilterVariables] = react.useState({ ...config.filterVariables });
5123
+ const entityDefinition = react.useMemo(
5124
+ () => entities.find((entity) => entity.id === config.entityMasterId),
5125
+ [entities, config.entityMasterId]
4947
5126
  );
4948
- const loadTables = react.useCallback(async (datasourceId) => {
4949
- if (!datasourceId) {
4950
- setAvailableTables([]);
4951
- return;
4952
- }
4953
- const tables = await onLoadTables(datasourceId);
4954
- setAvailableTables(tables);
4955
- }, [onLoadTables]);
4956
- const loadSchema = react.useCallback(async (datasourceId, table) => {
4957
- if (!datasourceId || !table) {
4958
- setAvailableColumns([]);
4959
- return;
4960
- }
4961
- const columns = await onLoadSchema(datasourceId, table);
4962
- setAvailableColumns(columns);
4963
- }, [onLoadSchema]);
4964
- react.useEffect(() => {
4965
- if (selectedDatasourceId) loadTables(selectedDatasourceId);
4966
- }, [selectedDatasourceId, loadTables]);
4967
- react.useEffect(() => {
4968
- if (selectedDatasourceId && selectedTable) loadSchema(selectedDatasourceId, selectedTable);
4969
- }, [selectedDatasourceId, selectedTable, loadSchema]);
4970
- const handleDatasourceChange = (datasourceId) => {
4971
- setSelectedDatasourceId(datasourceId);
4972
- setSelectedTable("");
4973
- setAvailableTables([]);
4974
- setAvailableColumns([]);
4975
- setSelectedColumns([]);
4976
- setFilterVariables({});
4977
- setTableSearch("");
4978
- setColumnSearch("");
4979
- };
4980
- const handleTableChange = (table) => {
4981
- setSelectedTable(table);
4982
- setAvailableColumns([]);
4983
- setSelectedColumns([]);
4984
- setFilterVariables({});
4985
- setColumnSearch("");
4986
- };
5127
+ const availableFields = react.useMemo(() => entityDefinition?.fields ?? [], [entityDefinition]);
5128
+ const allFieldNames = react.useMemo(() => availableFields.map((field) => field.name), [availableFields]);
5129
+ const allSelected = selectedFields.length === allFieldNames.length;
5130
+ const gradient = getEntityGradient(config.entityMasterId);
5131
+ const badgeColor = getEntityBadgeColor(config.entityMasterId);
4987
5132
  const handleToggleSelectAll = () => {
4988
- setSelectedColumns(allSelected ? [] : [...allColumnNames]);
5133
+ if (allSelected) {
5134
+ setSelectedFields([]);
5135
+ } else {
5136
+ setSelectedFields([...allFieldNames]);
5137
+ }
4989
5138
  };
4990
- const handleToggleColumn = (columnName) => {
4991
- setSelectedColumns(
4992
- (previous) => previous.includes(columnName) ? previous.filter((name) => name !== columnName) : [...previous, columnName]
5139
+ const handleToggleField = (fieldName) => {
5140
+ setSelectedFields(
5141
+ (previous) => previous.includes(fieldName) ? previous.filter((name) => name !== fieldName) : [...previous, fieldName]
4993
5142
  );
4994
5143
  };
4995
5144
  const handleAddFilter = () => {
4996
- setFilterVariables((previous) => ({ ...previous, [`field_${Object.keys(previous).length}`]: "" }));
5145
+ setFilterVariables((previous) => ({ ...previous, "": "" }));
4997
5146
  };
4998
5147
  const handleUpdateFilterVariable = (oldKey, newKey) => {
4999
5148
  setFilterVariables((previous) => {
@@ -5017,185 +5166,108 @@ function DatasourceNodeConfigForm({
5017
5166
  const handleSave = () => {
5018
5167
  const cleanedFilters = {};
5019
5168
  for (const [key, value] of Object.entries(filterVariables)) {
5020
- if (key.trim() && value.trim()) cleanedFilters[key.trim()] = value.trim();
5169
+ if (key.trim() && value.trim()) {
5170
+ cleanedFilters[key.trim()] = value.trim();
5171
+ }
5021
5172
  }
5022
5173
  onSave({
5023
5174
  ...config,
5024
- datasourceId: selectedDatasourceId,
5025
- dialect: selectedDatasource?.dialect ?? "",
5026
- table: selectedTable,
5027
- selectedColumns,
5175
+ selectedFields,
5028
5176
  outputVariable: outputVariable.trim(),
5029
5177
  limit,
5030
5178
  filterVariables: cleanedFilters
5031
5179
  });
5032
5180
  };
5033
5181
  const filterEntries = Object.entries(filterVariables);
5034
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
5182
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
5035
5183
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5036
- /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { icon: outline.CircleStackIcon, title: t("datasourceLabel"), badge: datasources.length }),
5037
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: datasources.map((datasource) => {
5038
- const isSelected = datasource.id === selectedDatasourceId;
5039
- const logo = getDatasourceLogo2(datasource.id, datasource.dialect);
5040
- return /* @__PURE__ */ jsxRuntime.jsxs(
5041
- "button",
5042
- {
5043
- type: "button",
5044
- onClick: () => handleDatasourceChange(datasource.id),
5045
- 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"}`,
5046
- children: [
5047
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center", children: logo ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logo, alt: datasource.dialect, className: "h-7 w-7" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.ServerStackIcon, { className: "h-6 w-6 text-gray-400" }) }),
5048
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
5049
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs font-semibold text-gray-900 dark:text-white", children: datasource.name }),
5050
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: datasource.dialect })
5051
- ] }),
5052
- isSelected && /* @__PURE__ */ jsxRuntime.jsx(outline.CheckIcon, { className: "h-4 w-4 shrink-0 text-cyan-500 dark:text-cyan-400" })
5053
- ]
5054
- },
5055
- datasource.id
5056
- );
5057
- }) })
5184
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("entityTypeLabel") }),
5185
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
5186
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br ${gradient}`, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-white font-bold", children: (entityDefinition?.label ?? config.entityMasterId ?? "?").charAt(0).toUpperCase() }) }),
5187
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${badgeColor}`, children: entityDefinition?.label ?? config.entityMasterId ?? t("entityTypeLabel") })
5188
+ ] }),
5189
+ !entityDefinition && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-xs text-amber-600 dark:text-amber-400", children: t("entityNotConfigured") })
5058
5190
  ] }),
5059
- selectedDatasourceId && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5060
- /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { icon: outline.TableCellsIcon, title: t("tableLabel"), badge: availableTables.length || void 0 }),
5061
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "liquid-surface rounded-xl border border-white/30 dark:border-white/10", children: [
5062
- /* @__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: [
5063
- /* @__PURE__ */ jsxRuntime.jsx(outline.MagnifyingGlassIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
5064
- /* @__PURE__ */ jsxRuntime.jsx(
5065
- "input",
5066
- {
5067
- type: "text",
5068
- value: tableSearch,
5069
- onChange: (event) => setTableSearch(event.target.value),
5070
- placeholder: t("selectTable"),
5071
- className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
5072
- }
5073
- )
5074
- ] }),
5075
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-36 overflow-y-auto p-1", children: [
5076
- filteredTables.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-3 text-center text-[10px] text-gray-400", children: availableTables.length === 0 ? t("noColumnsAvailable") : "No matches" }),
5077
- filteredTables.map((table) => {
5078
- const isSelected = table === selectedTable;
5079
- return /* @__PURE__ */ jsxRuntime.jsxs(
5080
- "button",
5081
- {
5082
- type: "button",
5083
- onClick: () => handleTableChange(table),
5084
- className: `flex w-full items-center gap-2 rounded-lg px-3 py-1.5 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"}`,
5085
- children: [
5086
- /* @__PURE__ */ jsxRuntime.jsx(outline.TableCellsIcon, { className: "h-3 w-3 shrink-0 text-gray-400" }),
5087
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: table }),
5088
- isSelected && /* @__PURE__ */ jsxRuntime.jsx(outline.CheckIcon, { className: "ml-auto h-3 w-3 shrink-0 text-cyan-500" })
5089
- ]
5090
- },
5091
- table
5092
- );
5093
- })
5094
- ] })
5095
- ] })
5191
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5192
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("outputVariableLabel") }),
5193
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("outputVariableHelp") }),
5194
+ /* @__PURE__ */ jsxRuntime.jsx(
5195
+ "input",
5196
+ {
5197
+ type: "text",
5198
+ value: outputVariable,
5199
+ onChange: (event) => setOutputVariable(event.target.value),
5200
+ placeholder: `${(entityDefinition?.label ?? "entity").replace(/\s+/g, "")}Data`,
5201
+ 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"
5202
+ }
5203
+ )
5096
5204
  ] }),
5097
- selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-3", children: [
5098
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
5099
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-[10px] font-medium text-gray-500 dark:text-gray-400", children: t("outputVariableLabel") }),
5100
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 dark:border-white/10 dark:bg-white/[0.03]", children: [
5101
- /* @__PURE__ */ jsxRuntime.jsx(outline.VariableIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
5102
- /* @__PURE__ */ jsxRuntime.jsx(
5103
- "input",
5104
- {
5105
- type: "text",
5106
- value: outputVariable,
5107
- onChange: (event) => setOutputVariable(event.target.value),
5108
- placeholder: "datasourceResult",
5109
- className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
5110
- }
5111
- )
5112
- ] })
5113
- ] }),
5114
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-24", children: [
5115
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-[10px] font-medium text-gray-500 dark:text-gray-400", children: t("limitLabel") }),
5116
- /* @__PURE__ */ jsxRuntime.jsx(
5117
- "input",
5118
- {
5119
- type: "number",
5120
- value: limit,
5121
- onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
5122
- min: 1,
5123
- max: 1e4,
5124
- className: "w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs text-gray-900 outline-none focus:border-cyan-400 dark:border-white/10 dark:bg-white/[0.03] dark:text-white"
5125
- }
5126
- )
5127
- ] })
5205
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5206
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("limitLabel") }),
5207
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("limitHelp") }),
5208
+ /* @__PURE__ */ jsxRuntime.jsx(
5209
+ "input",
5210
+ {
5211
+ type: "number",
5212
+ value: limit,
5213
+ onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
5214
+ min: 1,
5215
+ max: 1e3,
5216
+ 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"
5217
+ }
5218
+ )
5128
5219
  ] }),
5129
- selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5130
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
5131
- /* @__PURE__ */ jsxRuntime.jsx(
5132
- SectionHeader,
5133
- {
5134
- icon: outline.TableCellsIcon,
5135
- title: t("columnsLabel"),
5136
- badge: `${selectedColumns.length}/${availableColumns.length}`
5137
- }
5138
- ),
5220
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5221
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
5222
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("fieldsLabel") }),
5139
5223
  /* @__PURE__ */ jsxRuntime.jsx(
5140
5224
  "button",
5141
5225
  {
5142
5226
  type: "button",
5143
5227
  onClick: handleToggleSelectAll,
5144
- disabled: availableColumns.length === 0,
5145
- className: "text-[10px] font-semibold text-cyan-600 hover:text-cyan-700 disabled:opacity-40 dark:text-cyan-400 dark:hover:text-cyan-300",
5228
+ className: "text-xs font-medium text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 dark:hover:text-indigo-300",
5146
5229
  children: allSelected ? t("deselectAll") : t("selectAll")
5147
5230
  }
5148
5231
  )
5149
5232
  ] }),
5150
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "liquid-surface rounded-xl border border-white/30 dark:border-white/10", children: [
5151
- /* @__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: [
5152
- /* @__PURE__ */ jsxRuntime.jsx(outline.MagnifyingGlassIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
5153
- /* @__PURE__ */ jsxRuntime.jsx(
5154
- "input",
5233
+ selectedFields.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-amber-600 dark:text-amber-400", children: t("noFieldsSelected") }),
5234
+ /* @__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: [
5235
+ availableFields.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 py-2 text-xs text-gray-500 dark:text-gray-400", children: t("noFieldsSelected") }),
5236
+ availableFields.map((field) => {
5237
+ const isSelected = selectedFields.includes(field.name);
5238
+ const typeBadgeColor = FIELD_TYPE_BADGE_COLORS[field.type] ?? FIELD_TYPE_BADGE_COLORS.string;
5239
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5240
+ "label",
5155
5241
  {
5156
- type: "text",
5157
- value: columnSearch,
5158
- onChange: (event) => setColumnSearch(event.target.value),
5159
- placeholder: "Search columns...",
5160
- className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
5161
- }
5162
- )
5163
- ] }),
5164
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-52 overflow-y-auto p-1", children: [
5165
- filteredColumns.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-3 text-center text-[10px] text-gray-400", children: t("noColumnsAvailable") }),
5166
- filteredColumns.map((column) => {
5167
- const isSelected = selectedColumns.includes(column.name);
5168
- const typeColor = TYPE_COLORS[column.type.toLowerCase()] ?? TYPE_COLORS.string;
5169
- return /* @__PURE__ */ jsxRuntime.jsxs(
5170
- "button",
5171
- {
5172
- type: "button",
5173
- onClick: () => handleToggleColumn(column.name),
5174
- 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"}`,
5175
- children: [
5176
- /* @__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" }) }),
5177
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1 truncate text-xs text-gray-900 dark:text-white", children: [
5178
- column.name,
5179
- column.nullable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-[9px] text-gray-400", children: "?" })
5180
- ] }),
5181
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `shrink-0 rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeColor}`, children: column.type })
5182
- ]
5183
- },
5184
- column.name
5185
- );
5186
- })
5187
- ] })
5242
+ 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"}`,
5243
+ children: [
5244
+ /* @__PURE__ */ jsxRuntime.jsx(
5245
+ "input",
5246
+ {
5247
+ type: "checkbox",
5248
+ checked: isSelected,
5249
+ onChange: () => handleToggleField(field.name),
5250
+ className: "h-3.5 w-3.5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600"
5251
+ }
5252
+ ),
5253
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-xs font-medium text-gray-900 dark:text-white", children: field.name }),
5254
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeBadgeColor}`, children: field.type })
5255
+ ]
5256
+ },
5257
+ field.name
5258
+ );
5259
+ })
5188
5260
  ] })
5189
5261
  ] }),
5190
- selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5191
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
5192
- /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { icon: outline.FunnelIcon, title: t("filtersLabel"), badge: filterEntries.length || void 0 }),
5262
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5263
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
5264
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("filtersLabel") }),
5193
5265
  /* @__PURE__ */ jsxRuntime.jsxs(
5194
5266
  "button",
5195
5267
  {
5196
5268
  type: "button",
5197
5269
  onClick: handleAddFilter,
5198
- className: "flex items-center gap-1 text-[10px] font-semibold text-cyan-600 hover:text-cyan-700 dark:text-cyan-400 dark:hover:text-cyan-300",
5270
+ 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",
5199
5271
  children: [
5200
5272
  /* @__PURE__ */ jsxRuntime.jsx(outline.PlusIcon, { className: "h-3 w-3" }),
5201
5273
  t("addFilter")
@@ -5203,28 +5275,29 @@ function DatasourceNodeConfigForm({
5203
5275
  }
5204
5276
  )
5205
5277
  ] }),
5206
- 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 rounded-lg border border-gray-200 bg-white px-2 py-1.5 dark:border-white/10 dark:bg-white/[0.03]", children: [
5207
- /* @__PURE__ */ jsxRuntime.jsxs(
5208
- "select",
5209
- {
5210
- value: columnName,
5211
- onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
5212
- className: "flex-1 rounded bg-transparent text-xs text-gray-900 outline-none dark:text-white",
5213
- children: [
5214
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("columnName") }),
5215
- availableColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: column.name, children: column.name }, column.name))
5216
- ]
5217
- }
5218
- ),
5219
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-gray-400", children: "=" }),
5278
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("filtersHelp") }),
5279
+ filterEntries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: filterEntries.map(([variableName, fieldName], index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
5220
5280
  /* @__PURE__ */ jsxRuntime.jsx(
5221
5281
  "input",
5222
5282
  {
5223
5283
  type: "text",
5224
5284
  value: variableName,
5225
5285
  onChange: (event) => handleUpdateFilterVariable(variableName, event.target.value),
5226
- placeholder: t("variableReference"),
5227
- className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
5286
+ placeholder: t("variableName"),
5287
+ 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"
5288
+ }
5289
+ ),
5290
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-400", children: "\u2192" }),
5291
+ /* @__PURE__ */ jsxRuntime.jsxs(
5292
+ "select",
5293
+ {
5294
+ value: fieldName,
5295
+ onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
5296
+ 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",
5297
+ children: [
5298
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("fieldName") }),
5299
+ availableFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: field.name, children: field.name }, field.name))
5300
+ ]
5228
5301
  }
5229
5302
  ),
5230
5303
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5232,20 +5305,29 @@ function DatasourceNodeConfigForm({
5232
5305
  {
5233
5306
  type: "button",
5234
5307
  onClick: () => handleRemoveFilter(variableName),
5235
- 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",
5236
- children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "h-3 w-3" })
5308
+ className: "rounded-md p-1 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20",
5309
+ children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "h-3.5 w-3.5" })
5237
5310
  }
5238
5311
  )
5239
5312
  ] }, index)) })
5240
5313
  ] }),
5241
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 border-t border-gray-200/50 pt-4 dark:border-white/5", children: [
5242
- /* @__PURE__ */ jsxRuntime.jsx(chunkKEUOCEOO_js.Button, { outline: true, onClick: onCancel, children: t("cancel") }),
5314
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 border-t border-gray-200 pt-4 dark:border-gray-700", children: [
5315
+ /* @__PURE__ */ jsxRuntime.jsx(
5316
+ "button",
5317
+ {
5318
+ type: "button",
5319
+ onClick: onCancel,
5320
+ 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",
5321
+ children: t("cancel")
5322
+ }
5323
+ ),
5243
5324
  /* @__PURE__ */ jsxRuntime.jsx(
5244
- chunkKEUOCEOO_js.Button,
5325
+ "button",
5245
5326
  {
5246
- color: "cyan",
5327
+ type: "button",
5247
5328
  onClick: handleSave,
5248
- disabled: !selectedDatasourceId || !selectedTable || selectedColumns.length === 0,
5329
+ disabled: selectedFields.length === 0,
5330
+ 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",
5249
5331
  children: t("save")
5250
5332
  }
5251
5333
  )
@@ -5613,18 +5695,8 @@ function LogicNodeModal({ onSave, entities = [], datasources = [], onLoadTables,
5613
5695
  case "iteration_start":
5614
5696
  return /* @__PURE__ */ jsxRuntime.jsx(IterationStartNodeConfigForm, { config, onSave: handleSave, onCancel: closeModal });
5615
5697
  case "datasource":
5616
- return /* @__PURE__ */ jsxRuntime.jsx(
5617
- DatasourceNodeConfigForm,
5618
- {
5619
- nodeId,
5620
- config,
5621
- onSave: handleSave,
5622
- onCancel: closeModal,
5623
- datasources,
5624
- onLoadTables: onLoadTables ?? (async () => []),
5625
- onLoadSchema: onLoadSchema ?? (async () => [])
5626
- }
5627
- );
5698
+ return null;
5699
+ // Datasource uses its own GlassModal with sidebar — rendered separately
5628
5700
  case "entity":
5629
5701
  return /* @__PURE__ */ jsxRuntime.jsx(EntityNodeConfigForm, { config, entities, onSave: handleSave, onCancel: closeModal });
5630
5702
  case "group":
@@ -6056,6 +6128,9 @@ function WorkflowCanvasInner({
6056
6128
  agentTools = [],
6057
6129
  rules,
6058
6130
  entities = [],
6131
+ datasources = [],
6132
+ onLoadTables,
6133
+ onLoadSchema,
6059
6134
  initialGraph,
6060
6135
  onGraphChange,
6061
6136
  onEditTool,
@@ -7412,7 +7487,7 @@ function WorkflowCanvasInner({
7412
7487
  const handleEdgeClick = react.useCallback(() => {
7413
7488
  closeContextMenu();
7414
7489
  }, [closeContextMenu]);
7415
- react.useMemo(() => {
7490
+ const editingLogicNode = react.useMemo(() => {
7416
7491
  if (!editingLogicNodeId) return null;
7417
7492
  const node = nodes.find((matchingNode) => matchingNode.id === editingLogicNodeId);
7418
7493
  if (!node) return null;
@@ -7588,6 +7663,22 @@ function WorkflowCanvasInner({
7588
7663
  },
7589
7664
  entities: allEntities
7590
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
+ }
7591
7682
  )
7592
7683
  ] });
7593
7684
  }
@@ -7789,5 +7880,5 @@ exports.useModalStore = useModalStore;
7789
7880
  exports.useWorkflowBuilderClient = useWorkflowBuilderClient;
7790
7881
  exports.useWorkflowBuilderClientOptional = useWorkflowBuilderClientOptional;
7791
7882
  exports.useWorkflowStore = useWorkflowStore;
7792
- //# sourceMappingURL=chunk-7XITJWOE.js.map
7793
- //# sourceMappingURL=chunk-7XITJWOE.js.map
7883
+ //# sourceMappingURL=chunk-36EAW7JS.js.map
7884
+ //# sourceMappingURL=chunk-36EAW7JS.js.map