From 5d1ad2e7b00319875ff9fb782c7d717d23b0b20f Mon Sep 17 00:00:00 2001 From: Tejabudumuru3 Date: Tue, 4 Aug 2026 23:06:34 +0530 Subject: [PATCH] feat: implement filter node executor with support for deduplication, comparison, and GROUPING operations --- apps/web/app/lib/nodeConfigs/filter.action.ts | 3 +- .../workflows/[id]/components/ConfigModal.tsx | 32 ++++++++---- packages/common/src/index.ts | 3 +- packages/nodes/src/filter/filter.executor.ts | 49 ++++++++++++++++++- 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/apps/web/app/lib/nodeConfigs/filter.action.ts b/apps/web/app/lib/nodeConfigs/filter.action.ts index 50eb112..041a8da 100644 --- a/apps/web/app/lib/nodeConfigs/filter.action.ts +++ b/apps/web/app/lib/nodeConfigs/filter.action.ts @@ -15,7 +15,8 @@ export const filterActionConfig: NodeConfig = { options: [ { label: "Remove Duplicates from Provided Data(Single List)", id: "unique_rows" }, { label: "Find New Data Only (Compare Two Lists)", id: "new_data_only" }, - { label: "Find Existing Data Only (Compare Two Lists)", id: "existing_data_only" } + { label: "Find Existing Data Only (Compare Two Lists)", id: "existing_data_only" }, + { label: "Group Data By Key", id: "group_by" }, ], required: true, defaultValue: "unique_rows", diff --git a/apps/web/app/workflows/[id]/components/ConfigModal.tsx b/apps/web/app/workflows/[id]/components/ConfigModal.tsx index 06e772a..5d32a2a 100644 --- a/apps/web/app/workflows/[id]/components/ConfigModal.tsx +++ b/apps/web/app/workflows/[id]/components/ConfigModal.tsx @@ -60,7 +60,7 @@ export default function ConfigModal({ // Get all tested outputs from Redux (for variable resolution) const allTestedOutputs = useAppSelector(selectAllOutputs); - + const availableNodes = Object.entries(allTestedOutputs).map(([id, output]) => ({ id, name: output.nodeName || 'Node' @@ -364,6 +364,18 @@ export default function ConfigModal({ setConfig(loadedConfig) const nodeConfig = getNodeConfig(selectedNode.name || selectedNode.actionType); + let finalConfig = { ...loadedConfig }; + + if (nodeConfig?.fields) { + for (const field of nodeConfig.fields) { + if (field.defaultValue !== undefined && finalConfig[field.name] === undefined) { + finalConfig[field.name] = field.defaultValue; + } + } + } + setConfig(finalConfig); + dispatchConfig(finalConfig); + if (nodeConfig?.fields) { for (const field of nodeConfig.fields) { if (field.fetchOptions && field.dependsOn && loadedConfig[field.dependsOn]) { @@ -384,7 +396,7 @@ export default function ConfigModal({ .finally(() => setIsLoadingHeaders(false)); } } - }, [selectedNode]); + }, [selectedNode?.id]); if (!isOpen || !selectedNode) return null; @@ -436,7 +448,7 @@ export default function ConfigModal({ if (Array.isArray(data[0])) { return data[0].map((h: any) => String(h)); } - + const keys: string[] = []; const extractKeysRecursive = (obj: any, prefix = "") => { for (const key in obj) { @@ -451,7 +463,7 @@ export default function ConfigModal({ } } }; - + extractKeysRecursive(data[0]); return Array.from(new Set(keys)); }; @@ -461,19 +473,19 @@ export default function ConfigModal({ if (field.type === "dynamic_schema_dropdown") { let options: string[] = ["(No Data Mapped)"]; - + const dependentFieldName = field.name === "sourceKey" ? "sourceData" : "referenceData"; const dependentFieldValue = config[dependentFieldName]; - + if (dependentFieldValue && typeof dependentFieldValue === 'string') { const interpolationContext = buildTestContext(); const resolvedConfig = resolveConfigVariables({ temp: dependentFieldValue }, interpolationContext); const resolvedData = resolvedConfig.temp; - + if (resolvedData !== dependentFieldValue) { - options = extractSchemaKeys(resolvedData); + options = extractSchemaKeys(resolvedData); } else { - options = ["(Test Node to Load Options)"]; + options = ["(Test Node to Load Options)"]; } } @@ -499,7 +511,7 @@ export default function ConfigModal({ let val = opt; if (opt === "(Value Itself)") val = "__value__"; else if (opt.startsWith("(")) val = ""; - + return (