From d0b74dca205565ea3b3b039b519cc06b567cf0eb Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 11 Jul 2024 11:30:24 -0300 Subject: [PATCH 01/53] feat: add Table component and related functionality This commit adds the Table component and related functionality to the codebase. The Table component is used to display tabular data and includes features such as pagination, row deletion, row duplication, and adding new rows. The TableOptions component is also added to provide options for resetting the grid and adding new rows. Additionally, the necessary types and interfaces are updated to support the Table component. This feature enhances the user experience by allowing them to interact with tabular data in a more intuitive way. --- .../components/parameterComponent/index.tsx | 18 +++++++--- .../components/TableNodeComponent/index.tsx | 34 +++++++++++++++++++ .../components/TableOptions/index.tsx | 16 +++++++++ .../src/components/tableComponent/index.tsx | 2 ++ src/frontend/src/types/components/index.ts | 17 ++++++++++ src/frontend/src/utils/styleUtils.ts | 2 ++ 6 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 src/frontend/src/components/TableNodeComponent/index.tsx diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 7da923df604..3b5683c338b 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -54,6 +54,7 @@ import OutputComponent from "../OutputComponent"; import HandleRenderComponent from "../handleRenderComponent"; import OutputModal from "../outputModal"; import { TEXT_FIELD_TYPES } from "./constants"; +import TableNodeComponent from "@/components/TableNodeComponent"; export default function ParameterComponent({ left, @@ -279,7 +280,7 @@ export default function ParameterComponent({ className={ "relative mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2" + ((name === "code" && type === "code") || - (name.includes("code") && proxy) + (name.includes("code") && proxy) ? " hidden" : "") } @@ -423,7 +424,7 @@ export default function ParameterComponent({ disabled={disabled} value={ !data.node!.template[name]?.value || - data.node!.template[name]?.value === "" + data.node!.template[name]?.value === "" ? [""] : data.node!.template[name]?.value } @@ -524,6 +525,15 @@ export default function ParameterComponent({ /> + +
+ +
+
+
+ + + + {tableTitle} + + + + + +
+ + ); +} diff --git a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx index 05d3ea2719f..989ed725a0d 100644 --- a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx +++ b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx @@ -9,10 +9,12 @@ export default function TableOptions({ deleteRow, hasSelection, stateChange, + addRow, }: { resetGrid: () => void; duplicateRow?: () => void; deleteRow?: () => void; + addRow?: ()=>void; hasSelection: boolean; stateChange: boolean; }): JSX.Element { @@ -38,6 +40,20 @@ export default function TableOptions({ + {addRow && ( +
+ + + +
+ )} {duplicateRow && (
void; onDuplicate?: () => void; + onAddRow?: ()=>void; } const TableComponent = forwardRef< @@ -180,6 +181,7 @@ const TableComponent = forwardRef< hasSelection={realRef.current?.api?.getSelectedRows().length > 0} duplicateRow={props.onDuplicate ? props.onDuplicate : undefined} deleteRow={props.onDelete ? props.onDelete : undefined} + addRow={props.onAddRow?props.onAddRow:undefined} resetGrid={() => { resetGrid(realRef, initialColumnDefs); setTimeout(() => { diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 7c5c60579f0..ff8f9733857 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -10,6 +10,7 @@ import { import { ChatMessageType } from "../chat"; import { FlowStyleType, FlowType, NodeDataType, NodeType } from "../flow/index"; import { sourceHandleType, targetHandleType } from "./../flow/index"; +import { ColDef } from "ag-grid-community"; export type InputComponentType = { name?: string; autoFocus?: boolean; @@ -134,6 +135,22 @@ export type TextAreaComponentType = { readonly?: boolean; }; +interface BackendColumnType extends ColDef { + format:string; +} + + +export type TableComponentType = { + tableTitle:string; + onChange: ( + value: any[], + ) => void; + value: any[]; + editNode?: boolean; + id?: string; + columns:BackendColumnType[]; +}; + export type outputComponentType = { types: string[]; selected: string; diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 6ad2d94f00a..d021dc65c29 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -133,6 +133,7 @@ import { SquarePen, Store, SunIcon, + Table, TerminalIcon, TerminalSquare, TextCursorInput, @@ -581,4 +582,5 @@ export const nodeIconsLucide: iconsType = { PGVector: CpuIcon, Confluence: ConfluenceIcon, FreezeAll: freezeAllIcon, + Table: Table, }; From a904ae3727ff9b52952d370f7cbf6faadc083b51 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 11 Jul 2024 11:37:41 -0300 Subject: [PATCH 02/53] feat: add Edit Data trigger to TableNodeComponent --- src/frontend/src/components/TableNodeComponent/index.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 6123013938a..8ffd1df6799 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -27,6 +27,11 @@ export default function TableNodeComponent({ + +
+ Edit Data +
+
From e4bb1d73b1da251ffc68ea6d390496cd8029cd1f Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 14:39:14 +0000 Subject: [PATCH 03/53] [autofix.ci] apply automated fixes --- .../components/parameterComponent/index.tsx | 19 +++--- .../components/TableNodeComponent/index.tsx | 60 +++++++++---------- .../components/TableOptions/index.tsx | 6 +- .../src/components/tableComponent/index.tsx | 4 +- src/frontend/src/types/components/index.ts | 15 ++--- 5 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 3b5683c338b..385db6b237e 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -1,3 +1,4 @@ +import TableNodeComponent from "@/components/TableNodeComponent"; import { cloneDeep } from "lodash"; import { ReactNode, useEffect, useRef, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; @@ -54,7 +55,6 @@ import OutputComponent from "../OutputComponent"; import HandleRenderComponent from "../handleRenderComponent"; import OutputModal from "../outputModal"; import { TEXT_FIELD_TYPES } from "./constants"; -import TableNodeComponent from "@/components/TableNodeComponent"; export default function ParameterComponent({ left, @@ -280,7 +280,7 @@ export default function ParameterComponent({ className={ "relative mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2" + ((name === "code" && type === "code") || - (name.includes("code") && proxy) + (name.includes("code") && proxy) ? " hidden" : "") } @@ -424,7 +424,7 @@ export default function ParameterComponent({ disabled={disabled} value={ !data.node!.template[name]?.value || - data.node!.template[name]?.value === "" + data.node!.template[name]?.value === "" ? [""] : data.node!.template[name]?.value } @@ -527,10 +527,11 @@ export default function ParameterComponent({
-
@@ -658,7 +659,7 @@ export default function ParameterComponent({ editNode={false} value={ !data.node!.template[name]?.value || - !Object.keys(data.node!.template[name]?.value || {}).length + !Object.keys(data.node!.template[name]?.value || {}).length ? {} : data.node!.template[name]?.value } @@ -675,7 +676,7 @@ export default function ParameterComponent({ editNode={false} value={ !data.node!.template[name]?.value || - !Object.keys(data.node!.template[name]?.value || {}).length + !Object.keys(data.node!.template[name]?.value || {}).length ? [{ "": "" }] : convertObjToArray(data.node!.template[name]?.value, type!) } diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 8ffd1df6799..d1a00afdeb7 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,39 +1,37 @@ import BaseModal from "@/modals/baseModal"; +import IconComponent from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; import TableComponent from "../tableComponent"; -import IconComponent from "../../components/genericIconComponent"; export default function TableNodeComponent({ - tableTitle, - value, - onChange, - editNode = false, - id = "", - columns + tableTitle, + value, + onChange, + editNode = false, + id = "", + columns, }: TableComponentType): JSX.Element { - function deleteRow() {} - function duplicateRow() {} - function addRow() {} - function editRow() {} - return ( -
-
- - - - {tableTitle} - - - - - -
- Edit Data -
-
-
+ function deleteRow() {} + function duplicateRow() {} + function addRow() {} + function editRow() {} + return ( +
+
+ + + + {tableTitle} + + + + +
+ Edit Data
-
- ); + + +
+
+ ); } diff --git a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx index 989ed725a0d..33f8248b050 100644 --- a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx +++ b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx @@ -14,7 +14,7 @@ export default function TableOptions({ resetGrid: () => void; duplicateRow?: () => void; deleteRow?: () => void; - addRow?: ()=>void; + addRow?: () => void; hasSelection: boolean; stateChange: boolean; }): JSX.Element { @@ -42,9 +42,7 @@ export default function TableOptions({
{addRow && (
- + - -
{addRow && (
@@ -95,6 +76,25 @@ export default function TableOptions({
)}{" "} +
+ + + +
); From 58e6c5b3074957cdc0098ee640286a657997eb71 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:18:10 +0000 Subject: [PATCH 14/53] [autofix.ci] apply automated fixes --- .../components/TableNodeComponent/index.tsx | 75 +++++++++++-------- .../components/tableAutoCellRender/index.tsx | 8 +- src/frontend/src/types/components/index.ts | 2 +- src/frontend/src/utils/utils.ts | 17 ++--- 4 files changed, 54 insertions(+), 48 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index b27a2252ca1..ba0f69e8c30 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,43 +1,52 @@ import BaseModal from "@/modals/baseModal"; +import { FormatColumns } from "@/utils/utils"; import IconComponent from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; import TableComponent from "../tableComponent"; -import { FormatColumns } from "@/utils/utils"; export default function TableNodeComponent({ - tableTitle, - value, - onChange, - editNode = false, - id = "", - columns, + tableTitle, + value, + onChange, + editNode = false, + id = "", + columns, }: TableComponentType): JSX.Element { - function deleteRow() { } - function duplicateRow() { } - function addRow() { } - function editRow() { } + function deleteRow() {} + function duplicateRow() {} + function addRow() {} + function editRow() {} - const AgColumns = FormatColumns(columns); - console.log("AgColumns", AgColumns); - return ( -
-
- - - - {tableTitle} - - - - - - -
- Edit Data -
-
-
+ const AgColumns = FormatColumns(columns); + console.log("AgColumns", AgColumns); + return ( +
+
+ + + + {tableTitle} + + + + + + +
+ Edit Data
-
- ); + + +
+
+ ); } diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index 3d371b0d77f..e9fcd3d53e0 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -6,18 +6,18 @@ import ObjectRender from "../../../objectRender"; import StringReader from "../../../stringReaderComponent"; import { Badge } from "../../../ui/badge"; -interface CustomCellRender extends CustomCellRendererProps{ - formatter?:"json" +interface CustomCellRender extends CustomCellRendererProps { + formatter?: "json"; } export default function TableAutoCellRender({ value, setValue, colDef, - formatter + formatter, }: CustomCellRender) { function getCellType() { - const format:string = formatter?formatter:typeof value + const format: string = formatter ? formatter : typeof value; switch (format) { case "object": if (value === null) { diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index a7a4f7820c5..4462ad1f2af 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -10,8 +10,8 @@ import { } from "../api"; import { ChatMessageType } from "../chat"; import { FlowStyleType, FlowType, NodeDataType, NodeType } from "../flow/index"; -import { sourceHandleType, targetHandleType } from "./../flow/index"; import { ColumnField } from "../utils/functions"; +import { sourceHandleType, targetHandleType } from "./../flow/index"; export type InputComponentType = { name?: string; autoFocus?: boolean; diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index af93ca19676..f42978df705 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -1,3 +1,4 @@ +import { ColumnField } from "@/types/utils/functions"; import { BaseCellDataType, ColDef, ColGroupDef } from "ag-grid-community"; import clsx, { ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; @@ -12,7 +13,6 @@ import { import { NodeType } from "../types/flow"; import { FlowState } from "../types/tabs"; import { isErrorLog } from "../types/utils/typeCheckingUtils"; -import { ColumnField } from "@/types/utils/functions"; export function classNames(...classes: Array): string { return classes.filter(Boolean).join(" "); @@ -473,26 +473,23 @@ export function isEndpointNameValid(name: string, maxLength: number): boolean { ); } -export function FormatColumns(columns:ColumnField[]):(ColDef)[]{ - - const basic_types = new Set(["date","text","number"]) - +export function FormatColumns(columns: ColumnField[]): ColDef[] { + const basic_types = new Set(["date", "text", "number"]); const colDefs = columns.map((col, index) => { - let newCol:ColDef = { + let newCol: ColDef = { headerName: col.display_name, field: col.name, sortable: col.sortable, filter: col.filterable, }; if (col.formatter) { - if(basic_types.has(col.formatter)){ + if (basic_types.has(col.formatter)) { newCol.cellDataType = col.formatter; - } - else{ + } else { newCol.cellRendererParams = { formatter: col.formatter, - } + }; newCol.cellRenderer = TableAutoCellRender; } } From 86b1dfa08622eaf346ac6b37c0eb98e077553b7a Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 12 Jul 2024 00:02:32 -0300 Subject: [PATCH 15/53] feat: Update TableNodeComponent and TableComponent This commit updates the TableNodeComponent and TableComponent to improve column handling and customization options. It utilizes the FormatColumns function from utils.ts for flexible and customizable column formatting in the table. The TableComponent now has a new prop, displayEmptyAlert, to control the display of an alert when the table has no data. These enhancements enhance the flexibility and customization options of the table components. --- .../components/TableNodeComponent/index.tsx | 111 +++++++++++------- .../src/components/tableComponent/index.tsx | 6 +- src/frontend/src/types/utils/functions.ts | 1 - 3 files changed, 73 insertions(+), 45 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index ba0f69e8c30..4f81f669994 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -3,50 +3,79 @@ import { FormatColumns } from "@/utils/utils"; import IconComponent from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; import TableComponent from "../tableComponent"; +import { SelectionChangedEvent } from "ag-grid-community"; +import { useRef, useState } from "react"; +import { AgGridReact } from "ag-grid-react"; +import { set } from "lodash"; export default function TableNodeComponent({ - tableTitle, - value, - onChange, - editNode = false, - id = "", - columns, + tableTitle, + value, + onChange, + editNode = false, + id = "", + columns, }: TableComponentType): JSX.Element { - function deleteRow() {} - function duplicateRow() {} - function addRow() {} - function editRow() {} + const [selectedNodes, setSelectedNodes] = useState>([]); + const agGrid = useRef(null); + const AgColumns = FormatColumns(columns); + function deleteRow() { + if(agGrid.current && selectedNodes.length > 0){ + agGrid.current.api.applyTransaction({remove: selectedNodes.map((node) => node.data)}); + setSelectedNodes([]); - const AgColumns = FormatColumns(columns); - console.log("AgColumns", AgColumns); - return ( -
-
- - - - {tableTitle} - - - - - - -
- Edit Data + const rows:any = [] + agGrid.current.api.forEachNode((node) => rows.push(node.data)); + onChange(rows); + } + } + function duplicateRow() { } + function addRow() { + const newRow = {}; + columns.forEach((column) => { + newRow[column.name] = null; + }); + onChange([...value, newRow]); + } + + function editRow() { + + } + + return ( +
+
+ + + + {tableTitle} + + + { + setSelectedNodes(event.api.getSelectedNodes()); + }} + rowSelection="multiple" + suppressRowClickSelection={true} editable={true} + pagination={true} + addRow={addRow} + onDelete={deleteRow} + onDuplicate={duplicateRow} + displayEmptyAlert={false} + className="h-full w-full" + columnDefs={AgColumns} + rowData={value} + > + + + +
+ Edit Data +
+
+
- - -
-
- ); +
+ ); } diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx index e5a68f0872e..b9b99e2f97e 100644 --- a/src/frontend/src/components/tableComponent/index.tsx +++ b/src/frontend/src/components/tableComponent/index.tsx @@ -33,7 +33,7 @@ interface TableComponentProps extends AgGridReactProps { pagination?: boolean; onDelete?: () => void; onDuplicate?: () => void; - onAddRow?: () => void; + addRow?: () => void; } const TableComponent = forwardRef< @@ -95,7 +95,7 @@ const TableComponent = forwardRef< }); const gridRef = useRef(null); // @ts-ignore - const realRef: React.MutableRefObject = ref?.current + const realRef: React.MutableRefObject = ref?.current!==undefined ? ref : gridRef; const dark = useDarkStore((state) => state.dark); @@ -183,7 +183,7 @@ const TableComponent = forwardRef< hasSelection={realRef.current?.api?.getSelectedRows().length > 0} duplicateRow={props.onDuplicate ? props.onDuplicate : undefined} deleteRow={props.onDelete ? props.onDelete : undefined} - addRow={props.onAddRow ? props.onAddRow : undefined} + addRow={props.addRow ? props.addRow : undefined} resetGrid={() => { resetGrid(realRef, initialColumnDefs); setTimeout(() => { diff --git a/src/frontend/src/types/utils/functions.ts b/src/frontend/src/types/utils/functions.ts index 29e5ac5ca13..989476bddbb 100644 --- a/src/frontend/src/types/utils/functions.ts +++ b/src/frontend/src/types/utils/functions.ts @@ -13,7 +13,6 @@ enum FormatterType { date = "date", text = "text", number = "number", - currency = "currency", json = "json", } From 155ee704713ee75c804e0e5b04e8ab730020f257 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 11 Jul 2024 18:34:01 -0300 Subject: [PATCH 16/53] feat: initialize table field values as DataFrame --- src/backend/base/langflow/graph/vertex/base.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/backend/base/langflow/graph/vertex/base.py b/src/backend/base/langflow/graph/vertex/base.py index a8cf5a77123..7635057a1fc 100644 --- a/src/backend/base/langflow/graph/vertex/base.py +++ b/src/backend/base/langflow/graph/vertex/base.py @@ -7,6 +7,7 @@ from enum import Enum from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, Dict, Iterator, List, Mapping, Optional, Set +import pandas as pd from loguru import logger from langflow.exceptions.component import ComponentBuildException @@ -373,6 +374,13 @@ def _build_params(self): params[field_name] = val elif isinstance(val, str): params[field_name] = val != "" + elif field.get("type") == "table" and val is not None: + # check if the value is a list of dicts + # if it is, create a pandas dataframe from it + if isinstance(val, list) and all(isinstance(item, dict) for item in val): + params[field_name] = pd.DataFrame(val) + else: + raise ValueError(f"Invalid value type {type(val)} for field {field_name}") elif val is not None and val != "": params[field_name] = val From ffddc395b7951032be6747ced975371561207402 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 12 Jul 2024 11:00:54 -0300 Subject: [PATCH 17/53] feat: Enhance TableNodeComponent with duplicateRow function This commit enhances the TableNodeComponent by adding the duplicateRow function. This function allows users to duplicate selected rows in the table. When called, it clones the selected nodes and adds the duplicated rows to the table. This feature enhances the flexibility and customization options of the TableNodeComponent. --- .../src/components/TableNodeComponent/index.tsx | 14 +++++++++++--- .../components/tableAutoCellRender/index.tsx | 4 +++- .../src/components/tableComponent/index.tsx | 5 +++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 4f81f669994..1cb0ae46ef1 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -6,7 +6,7 @@ import TableComponent from "../tableComponent"; import { SelectionChangedEvent } from "ag-grid-community"; import { useRef, useState } from "react"; import { AgGridReact } from "ag-grid-react"; -import { set } from "lodash"; +import { cloneDeep, set } from "lodash"; export default function TableNodeComponent({ tableTitle, @@ -29,7 +29,14 @@ export default function TableNodeComponent({ onChange(rows); } } - function duplicateRow() { } + function duplicateRow() { + if(agGrid.current && selectedNodes.length > 0){ + const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data)); + setSelectedNodes([]); + const rows:any = [] + onChange([...value, ...toDuplicate]); + } + } function addRow() { const newRow = {}; columns.forEach((column) => { @@ -56,8 +63,9 @@ export default function TableNodeComponent({ onSelectionChanged={(event: SelectionChangedEvent) => { setSelectedNodes(event.api.getSelectedNodes()); }} + editable={true} rowSelection="multiple" - suppressRowClickSelection={true} editable={true} + suppressRowClickSelection={true} pagination={true} addRow={addRow} onDelete={deleteRow} diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index e9fcd3d53e0..1c95368d336 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -18,6 +18,7 @@ export default function TableAutoCellRender({ }: CustomCellRender) { function getCellType() { const format: string = formatter ? formatter : typeof value; + console.log("format", format); switch (format) { case "object": if (value === null) { @@ -27,7 +28,7 @@ export default function TableAutoCellRender({ } else { return ; } - case "string": + case "string"||"text": if (isTimeStampString(value)) { return ; } @@ -57,6 +58,7 @@ export default function TableAutoCellRender({ ); } else { + console.log("coldDef", colDef); return ( ; + columnDefs: NonNullable[]>; rowData: NonNullable; displayEmptyAlert?: boolean; alertTitle?: string; @@ -82,7 +83,7 @@ const TableComponent = forwardRef< onUpdate: (value: any) => void; editableCell: boolean; }> - ).find((field) => field.field === newCol.headerName); + ).find((field) => field.field === newCol.field); if (field) { newCol = { ...newCol, From 2a5a80b25930f9bcfed440876588c0e48b43b8ae Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 03:03:53 +0000 Subject: [PATCH 18/53] [autofix.ci] apply automated fixes --- .../components/TableNodeComponent/index.tsx | 142 +++++++++--------- .../src/components/tableComponent/index.tsx | 5 +- 2 files changed, 69 insertions(+), 78 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 1cb0ae46ef1..8bf71d15338 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,89 +1,81 @@ import BaseModal from "@/modals/baseModal"; import { FormatColumns } from "@/utils/utils"; +import { SelectionChangedEvent } from "ag-grid-community"; +import { AgGridReact } from "ag-grid-react"; +import { useRef, useState } from "react"; import IconComponent from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; import TableComponent from "../tableComponent"; -import { SelectionChangedEvent } from "ag-grid-community"; -import { useRef, useState } from "react"; -import { AgGridReact } from "ag-grid-react"; -import { cloneDeep, set } from "lodash"; export default function TableNodeComponent({ - tableTitle, - value, - onChange, - editNode = false, - id = "", - columns, + tableTitle, + value, + onChange, + editNode = false, + id = "", + columns, }: TableComponentType): JSX.Element { - const [selectedNodes, setSelectedNodes] = useState>([]); - const agGrid = useRef(null); - const AgColumns = FormatColumns(columns); - function deleteRow() { - if(agGrid.current && selectedNodes.length > 0){ - agGrid.current.api.applyTransaction({remove: selectedNodes.map((node) => node.data)}); - setSelectedNodes([]); + const [selectedNodes, setSelectedNodes] = useState>([]); + const agGrid = useRef(null); + const AgColumns = FormatColumns(columns); + function deleteRow() { + if (agGrid.current && selectedNodes.length > 0) { + agGrid.current.api.applyTransaction({ + remove: selectedNodes.map((node) => node.data), + }); + setSelectedNodes([]); - const rows:any = [] - agGrid.current.api.forEachNode((node) => rows.push(node.data)); - onChange(rows); - } - } - function duplicateRow() { - if(agGrid.current && selectedNodes.length > 0){ - const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data)); - setSelectedNodes([]); - const rows:any = [] - onChange([...value, ...toDuplicate]); - } - } - function addRow() { - const newRow = {}; - columns.forEach((column) => { - newRow[column.name] = null; - }); - onChange([...value, newRow]); + const rows: any = []; + agGrid.current.api.forEachNode((node) => rows.push(node.data)); + onChange(rows); } + } + function duplicateRow() {} + function addRow() { + const newRow = {}; + columns.forEach((column) => { + newRow[column.name] = null; + }); + onChange([...value, newRow]); + } - function editRow() { - - } + function editRow() {} - return ( -
-
- - - - {tableTitle} - - - { - setSelectedNodes(event.api.getSelectedNodes()); - }} - editable={true} - rowSelection="multiple" - suppressRowClickSelection={true} - pagination={true} - addRow={addRow} - onDelete={deleteRow} - onDuplicate={duplicateRow} - displayEmptyAlert={false} - className="h-full w-full" - columnDefs={AgColumns} - rowData={value} - > - - - -
- Edit Data -
-
-
+ return ( +
+
+ + + + {tableTitle} + + + { + setSelectedNodes(event.api.getSelectedNodes()); + }} + rowSelection="multiple" + suppressRowClickSelection={true} + editable={true} + pagination={true} + addRow={addRow} + onDelete={deleteRow} + onDuplicate={duplicateRow} + displayEmptyAlert={false} + className="h-full w-full" + columnDefs={AgColumns} + rowData={value} + > + + + +
+ Edit Data
-
- ); + + +
+
+ ); } diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx index 2318dda1673..3566b41395d 100644 --- a/src/frontend/src/components/tableComponent/index.tsx +++ b/src/frontend/src/components/tableComponent/index.tsx @@ -96,9 +96,8 @@ const TableComponent = forwardRef< }); const gridRef = useRef(null); // @ts-ignore - const realRef: React.MutableRefObject = ref?.current!==undefined - ? ref - : gridRef; + const realRef: React.MutableRefObject = + ref?.current !== undefined ? ref : gridRef; const dark = useDarkStore((state) => state.dark); const initialColumnDefs = useRef(colDef); const [columnStateChange, setColumnStateChange] = useState(false); From caafa75c16b5d280859be36dd624475352696324 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 12 Jul 2024 11:41:51 -0300 Subject: [PATCH 19/53] feat: Remove "text" from basic_types in FormatColumns function This commit removes the "text" value from the basic_types set in the FormatColumns function in utils.ts. The basic_types set is used to determine the column type for formatting in the table. By removing "text", we ensure that only "date" and "number" types are considered as basic types. This change improves the accuracy and consistency of column formatting in the table. --- .../components/TableNodeComponent/index.tsx | 35 +++++++++++++++---- .../stringReaderComponent/index.tsx | 4 +-- .../components/tableAutoCellRender/index.tsx | 8 ++--- .../src/components/tableComponent/index.tsx | 3 +- src/frontend/src/utils/utils.ts | 3 +- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 8bf71d15338..abff0d63350 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -2,6 +2,7 @@ import BaseModal from "@/modals/baseModal"; import { FormatColumns } from "@/utils/utils"; import { SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; +import { cloneDeep } from "lodash"; import { useRef, useState } from "react"; import IconComponent from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; @@ -18,19 +19,31 @@ export default function TableNodeComponent({ const [selectedNodes, setSelectedNodes] = useState>([]); const agGrid = useRef(null); const AgColumns = FormatColumns(columns); + + function setAllRows() { + if (agGrid.current) { + const rows: any = []; + agGrid.current.api.forEachNode((node) => rows.push(node.data)); + onChange(rows); + } + } function deleteRow() { if (agGrid.current && selectedNodes.length > 0) { agGrid.current.api.applyTransaction({ remove: selectedNodes.map((node) => node.data), }); setSelectedNodes([]); - + setAllRows(); + } + } + function duplicateRow() { + if (agGrid.current && selectedNodes.length > 0) { + const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data)); + setSelectedNodes([]); const rows: any = []; - agGrid.current.api.forEachNode((node) => rows.push(node.data)); - onChange(rows); + onChange([...value, ...toDuplicate]); } } - function duplicateRow() {} function addRow() { const newRow = {}; columns.forEach((column) => { @@ -39,7 +52,17 @@ export default function TableNodeComponent({ onChange([...value, newRow]); } - function editRow() {} + function updateComponente() { + setAllRows(); + } + const editable = columns.map((column) => { + const is_text = column.formatter && column.formatter === "text"; + return { + field: column.name, + onUpdate: updateComponente, + editableCell: is_text ? false : true, + }; + }); return (
@@ -57,7 +80,7 @@ export default function TableNodeComponent({ }} rowSelection="multiple" suppressRowClickSelection={true} - editable={true} + editable={editable} pagination={true} addRow={addRow} onDelete={deleteRow} diff --git a/src/frontend/src/components/stringReaderComponent/index.tsx b/src/frontend/src/components/stringReaderComponent/index.tsx index dfcb15b5486..901c24171d1 100644 --- a/src/frontend/src/components/stringReaderComponent/index.tsx +++ b/src/frontend/src/components/stringReaderComponent/index.tsx @@ -6,12 +6,12 @@ export default function StringReader({ setValue, editable = false, }: { - string: string; + string: string|null; setValue: (value: string) => void; editable: boolean; }): JSX.Element { return ( - + {string} ); diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index 1c95368d336..b12c98ee4a7 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -17,8 +17,9 @@ export default function TableAutoCellRender({ formatter, }: CustomCellRender) { function getCellType() { - const format: string = formatter ? formatter : typeof value; - console.log("format", format); + let format: string = formatter ? formatter : typeof value; + //convert text to string to bind to the string reader + format=format==="text"?"string":format; switch (format) { case "object": if (value === null) { @@ -28,7 +29,7 @@ export default function TableAutoCellRender({ } else { return ; } - case "string"||"text": + case "string": if (isTimeStampString(value)) { return ; } @@ -58,7 +59,6 @@ export default function TableAutoCellRender({ ); } else { - console.log("coldDef", colDef); return ( = - ref?.current !== undefined ? ref : gridRef; + const realRef: React.MutableRefObject = ref?.current !== undefined ? ref : gridRef; const dark = useDarkStore((state) => state.dark); const initialColumnDefs = useRef(colDef); const [columnStateChange, setColumnStateChange] = useState(false); diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index f42978df705..ca2b9439958 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -474,8 +474,7 @@ export function isEndpointNameValid(name: string, maxLength: number): boolean { } export function FormatColumns(columns: ColumnField[]): ColDef[] { - const basic_types = new Set(["date", "text", "number"]); - + const basic_types = new Set(["date", "number"]); const colDefs = columns.map((col, index) => { let newCol: ColDef = { headerName: col.display_name, From 8ea5ecb0cc9cd7593c9f47f94c7c17ec1b838892 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 12 Jul 2024 12:19:22 -0300 Subject: [PATCH 20/53] fix: alingment bug on AgGrid cell --- .../GenericNode/components/parameterComponent/index.tsx | 1 + src/frontend/src/components/TableNodeComponent/index.tsx | 6 ++++-- src/frontend/src/components/stringReaderComponent/index.tsx | 3 ++- src/frontend/src/types/components/index.ts | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 73496193a6e..5780b661be5 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -528,6 +528,7 @@ export default function ParameterComponent({
- - {tableTitle} +
+ + {tableTitle} +
- {string} + {/* INVISIBLE CHARACTER TO PREVENT AGgrid bug */} + {string??"‎"} ); } diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 4462ad1f2af..e2c419fa5a2 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -137,6 +137,7 @@ export type TextAreaComponentType = { }; export type TableComponentType = { + description: string; tableTitle: string; onChange: (value: any[]) => void; value: any[]; From 498bbb0bea71a6ae2a29139a381d79e994f4b9d3 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 14:43:04 +0000 Subject: [PATCH 21/53] [autofix.ci] apply automated fixes --- .../src/components/stringReaderComponent/index.tsx | 7 +++---- .../components/tableAutoCellRender/index.tsx | 2 +- src/frontend/src/components/tableComponent/index.tsx | 5 +++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/components/stringReaderComponent/index.tsx b/src/frontend/src/components/stringReaderComponent/index.tsx index 95db7872064..877ed899ca4 100644 --- a/src/frontend/src/components/stringReaderComponent/index.tsx +++ b/src/frontend/src/components/stringReaderComponent/index.tsx @@ -1,4 +1,3 @@ -import { ColDef, Column } from "ag-grid-community"; import TextModal from "../../modals/textModal"; export default function StringReader({ @@ -6,14 +5,14 @@ export default function StringReader({ setValue, editable = false, }: { - string: string|null; + string: string | null; setValue: (value: string) => void; editable: boolean; }): JSX.Element { return ( - + {/* INVISIBLE CHARACTER TO PREVENT AGgrid bug */} - {string??"‎"} + {string ?? "‎"} ); } diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index b12c98ee4a7..57127245765 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -19,7 +19,7 @@ export default function TableAutoCellRender({ function getCellType() { let format: string = formatter ? formatter : typeof value; //convert text to string to bind to the string reader - format=format==="text"?"string":format; + format = format === "text" ? "string" : format; switch (format) { case "object": if (value === null) { diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx index 40b2ef24520..d83013cf09c 100644 --- a/src/frontend/src/components/tableComponent/index.tsx +++ b/src/frontend/src/components/tableComponent/index.tsx @@ -1,3 +1,4 @@ +import { ColDef } from "ag-grid-community"; import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid import "ag-grid-community/styles/ag-theme-quartz.css"; // Optional Theme applied to the grid import { AgGridReact, AgGridReactProps } from "ag-grid-react"; @@ -15,7 +16,6 @@ import ForwardedIconComponent from "../genericIconComponent"; import { Alert, AlertDescription, AlertTitle } from "../ui/alert"; import TableOptions from "./components/TableOptions"; import resetGrid from "./utils/reset-grid-columns"; -import { ColDef } from "ag-grid-community"; interface TableComponentProps extends AgGridReactProps { columnDefs: NonNullable[]>; @@ -96,7 +96,8 @@ const TableComponent = forwardRef< }); const gridRef = useRef(null); // @ts-ignore - const realRef: React.MutableRefObject = ref?.current !== undefined ? ref : gridRef; + const realRef: React.MutableRefObject = + ref?.current !== undefined ? ref : gridRef; const dark = useDarkStore((state) => state.dark); const initialColumnDefs = useRef(colDef); const [columnStateChange, setColumnStateChange] = useState(false); From e24a8ee9d68e1613c9a98cd24b7851785f815529 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:23:44 +0000 Subject: [PATCH 22/53] [autofix.ci] apply automated fixes --- .../GenericNode/components/parameterComponent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 5780b661be5..de6a6d28245 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -528,7 +528,7 @@ export default function ParameterComponent({
Date: Tue, 16 Jul 2024 14:53:19 -0300 Subject: [PATCH 23/53] Styled the Open Table button on TableNodeComponent --- .../src/components/TableNodeComponent/index.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 0c6f2098be4..dc4749d6117 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -4,9 +4,12 @@ import { SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; import { cloneDeep } from "lodash"; import { useRef, useState } from "react"; -import IconComponent from "../../components/genericIconComponent"; +import IconComponent, { + ForwardedIconComponent, +} from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; import TableComponent from "../tableComponent"; +import { Button } from "../ui/button"; export default function TableNodeComponent({ tableTitle, @@ -94,10 +97,11 @@ export default function TableNodeComponent({ > - -
- Edit Data -
+ +
From 5f5b2349ed0d9c85dbb56a45a268a01ef2b6f0ba Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:02:24 -0300 Subject: [PATCH 24/53] Fixed type of ref on tableComponent --- .../src/components/tableComponent/index.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx index d83013cf09c..9de96cdd142 100644 --- a/src/frontend/src/components/tableComponent/index.tsx +++ b/src/frontend/src/components/tableComponent/index.tsx @@ -17,7 +17,7 @@ import { Alert, AlertDescription, AlertTitle } from "../ui/alert"; import TableOptions from "./components/TableOptions"; import resetGrid from "./utils/reset-grid-columns"; -interface TableComponentProps extends AgGridReactProps { +export interface TableComponentProps extends AgGridReactProps { columnDefs: NonNullable[]>; rowData: NonNullable; displayEmptyAlert?: boolean; @@ -94,10 +94,9 @@ const TableComponent = forwardRef< } return newCol; }); - const gridRef = useRef(null); // @ts-ignore const realRef: React.MutableRefObject = - ref?.current !== undefined ? ref : gridRef; + useRef(null); const dark = useDarkStore((state) => state.dark); const initialColumnDefs = useRef(colDef); const [columnStateChange, setColumnStateChange] = useState(false); @@ -164,7 +163,15 @@ const TableComponent = forwardRef< }} animateRows={false} columnDefs={colDef} - ref={realRef} + ref={(node) => { + if (!node) return; + realRef.current = node; + if (typeof ref === "function") { + ref(node); + } else if (ref) { + ref.current = node; + } + }} onGridReady={onGridReady} onColumnMoved={onColumnMoved} onStateUpdated={(e) => { From f7d5b68bf282848e38b2fc15c13d901a5c90ac6b Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:10:02 -0300 Subject: [PATCH 25/53] Creaed a TableModal component, that receives the props that are passed to the Table, as well as a title, and creates a modal --- src/frontend/src/modals/tableModal/index.tsx | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/frontend/src/modals/tableModal/index.tsx diff --git a/src/frontend/src/modals/tableModal/index.tsx b/src/frontend/src/modals/tableModal/index.tsx new file mode 100644 index 00000000000..33023c9a995 --- /dev/null +++ b/src/frontend/src/modals/tableModal/index.tsx @@ -0,0 +1,38 @@ +import ForwardedIconComponent from "@/components/genericIconComponent"; +import TableComponent, { + TableComponentProps, +} from "@/components/tableComponent"; +import { ElementRef, forwardRef } from "react"; +import BaseModal from "../baseModal"; + +interface TableModalProps extends TableComponentProps { + tableTitle: string; + children: React.ReactNode; +} + +const TableModal = forwardRef< + ElementRef, + TableModalProps +>(({ tableTitle, children, ...props }: TableModalProps, ref) => { + return ( + + +
+ + {tableTitle} +
+
+ + + + + {children} +
+ ); +}); + +export default TableModal; From 0dbf0127c56cbfdce004669b10f4a9ed42e579e8 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:10:14 -0300 Subject: [PATCH 26/53] Used the TableModal on the TableNodeComponent --- .../components/TableNodeComponent/index.tsx | 58 ++++++++----------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index dc4749d6117..1a5721320f6 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,4 +1,5 @@ import BaseModal from "@/modals/baseModal"; +import TableModal from "@/modals/tableModal"; import { FormatColumns } from "@/utils/utils"; import { SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; @@ -70,40 +71,29 @@ export default function TableNodeComponent({ return (
- - -
- - {tableTitle} -
-
- - { - setSelectedNodes(event.api.getSelectedNodes()); - }} - rowSelection="multiple" - suppressRowClickSelection={true} - editable={editable} - pagination={true} - addRow={addRow} - onDelete={deleteRow} - onDuplicate={duplicateRow} - displayEmptyAlert={false} - className="h-full w-full" - columnDefs={AgColumns} - rowData={value} - > - - - - - -
+ { + setSelectedNodes(event.api.getSelectedNodes()); + }} + rowSelection="multiple" + suppressRowClickSelection={true} + editable={editable} + pagination={true} + addRow={addRow} + onDelete={deleteRow} + onDuplicate={duplicateRow} + displayEmptyAlert={false} + className="h-full w-full" + columnDefs={AgColumns} + rowData={value} + > + +
); From 56690e7e5085b7d4dff06b8bc852298c522aaf21 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:14:41 -0300 Subject: [PATCH 27/53] Fixed looks of TableModal --- src/frontend/src/modals/tableModal/index.tsx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/modals/tableModal/index.tsx b/src/frontend/src/modals/tableModal/index.tsx index 33023c9a995..f056cf2feb0 100644 --- a/src/frontend/src/modals/tableModal/index.tsx +++ b/src/frontend/src/modals/tableModal/index.tsx @@ -2,7 +2,9 @@ import ForwardedIconComponent from "@/components/genericIconComponent"; import TableComponent, { TableComponentProps, } from "@/components/tableComponent"; -import { ElementRef, forwardRef } from "react"; +import { Button } from "@/components/ui/button"; +import { DialogClose } from "@radix-ui/react-dialog"; +import { ElementRef, forwardRef, useState } from "react"; import BaseModal from "../baseModal"; interface TableModalProps extends TableComponentProps { @@ -16,11 +18,10 @@ const TableModal = forwardRef< >(({ tableTitle, children, ...props }: TableModalProps, ref) => { return ( + {children} -
- - {tableTitle} -
+ {tableTitle} +
- - {children} + + +
+ +
+
+
); }); From 4df6b6d68dbe9cfbcb51333d70c82b2d87bf4147 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:17:28 -0300 Subject: [PATCH 28/53] Added description set on tableModal --- src/frontend/src/modals/tableModal/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/modals/tableModal/index.tsx b/src/frontend/src/modals/tableModal/index.tsx index f056cf2feb0..9994ce4ea52 100644 --- a/src/frontend/src/modals/tableModal/index.tsx +++ b/src/frontend/src/modals/tableModal/index.tsx @@ -9,17 +9,18 @@ import BaseModal from "../baseModal"; interface TableModalProps extends TableComponentProps { tableTitle: string; + description: string; children: React.ReactNode; } const TableModal = forwardRef< ElementRef, TableModalProps ->(({ tableTitle, children, ...props }: TableModalProps, ref) => { +>(({ tableTitle, description, children, ...props }: TableModalProps, ref) => { return ( {children} - + {tableTitle} From 1cfed200e0f402ea1133b6375fd784bd3afccd6c Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:17:39 -0300 Subject: [PATCH 29/53] Add description field to TableNodeComponent --- src/frontend/src/components/TableNodeComponent/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 1a5721320f6..02b00c98490 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -14,6 +14,7 @@ import { Button } from "../ui/button"; export default function TableNodeComponent({ tableTitle, + description, value, onChange, editNode = false, @@ -73,6 +74,7 @@ export default function TableNodeComponent({
{ setSelectedNodes(event.api.getSelectedNodes()); From 924ec7f0cfc32514bf8194957973dc36ab421d3d Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:18:23 -0300 Subject: [PATCH 30/53] Fixed text of description if info is not provided --- .../GenericNode/components/parameterComponent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index de6a6d28245..52ac79087c5 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -528,7 +528,7 @@ export default function ParameterComponent({
Date: Tue, 16 Jul 2024 15:24:06 -0300 Subject: [PATCH 31/53] Added TableComponent in tableNodeCellRenderer --- .../components/tableNodeCellRender/index.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx index 83c1d1d253e..8926438b97e 100644 --- a/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx @@ -1,3 +1,4 @@ +import TableNodeComponent from "@/components/TableNodeComponent"; import { CustomCellRendererProps } from "ag-grid-react"; import { cloneDeep } from "lodash"; import { useState } from "react"; @@ -138,6 +139,19 @@ export default function TableNodeCellRender({ editNode={true} /> ); + case "table": + return ( + { + handleOnNewValue(value, templateData.key); + }} + editNode + tableTitle={templateData.display_name ?? "Table"} + value={templateValue} + /> + ); case "float": return ( From e784a7b0e0633a2b172df628abb56b4e48966da2 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:24:15 -0300 Subject: [PATCH 32/53] Added styling based on editNode --- src/frontend/src/components/TableNodeComponent/index.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 02b00c98490..1d01942b17e 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,6 +1,6 @@ import BaseModal from "@/modals/baseModal"; import TableModal from "@/modals/tableModal"; -import { FormatColumns } from "@/utils/utils"; +import { cn, FormatColumns } from "@/utils/utils"; import { SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; import { cloneDeep } from "lodash"; @@ -91,7 +91,11 @@ export default function TableNodeComponent({ columnDefs={AgColumns} rowData={value} > - From 953b4263502731a11e230e2c107532c503d7fe86 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 16 Jul 2024 15:26:54 -0300 Subject: [PATCH 33/53] Added Auto Size to table modal --- src/frontend/src/components/TableNodeComponent/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 1d01942b17e..63b89f5d3b5 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -73,6 +73,7 @@ export default function TableNodeComponent({
Date: Tue, 16 Jul 2024 20:10:53 -0300 Subject: [PATCH 34/53] refactor: update TableOptions component styling and behavior - Update TableOptions component to dynamically apply text color based on selection - Remove unnecessary console.log statement - Improve hover behavior for the Trash2 icon --- .../tableComponent/components/TableOptions/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx index 124aefabb07..71ea7bd32aa 100644 --- a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx +++ b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx @@ -47,7 +47,7 @@ export default function TableOptions({ @@ -68,8 +68,10 @@ export default function TableOptions({ From 130cb0a97289733d4a3aade29c42562faeacedd8 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 16 Jul 2024 20:11:03 -0300 Subject: [PATCH 35/53] chore: Remove unnecessary imports and initialize empty columns array in TableNodeComponent --- .../src/components/TableNodeComponent/index.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 63b89f5d3b5..faca9e97f94 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,15 +1,11 @@ -import BaseModal from "@/modals/baseModal"; import TableModal from "@/modals/tableModal"; -import { cn, FormatColumns } from "@/utils/utils"; +import { FormatColumns } from "@/utils/utils"; import { SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; import { cloneDeep } from "lodash"; import { useRef, useState } from "react"; -import IconComponent, { - ForwardedIconComponent, -} from "../../components/genericIconComponent"; +import { ForwardedIconComponent } from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; -import TableComponent from "../tableComponent"; import { Button } from "../ui/button"; export default function TableNodeComponent({ @@ -21,6 +17,9 @@ export default function TableNodeComponent({ id = "", columns, }: TableComponentType): JSX.Element { + if (!columns) { + columns = []; + } const [selectedNodes, setSelectedNodes] = useState>([]); const agGrid = useRef(null); const AgColumns = FormatColumns(columns); From b9590537046890d792fa4a2ce68d85c38a38ff98 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 16 Jul 2024 20:11:12 -0300 Subject: [PATCH 36/53] feat: Add default values for sortable and filterable in Column model The code changes in `table.py` modify the `Column` model in the `langflow.schema` module. The `sortable` and `filterable` attributes of the `Column` model now have default values of `True`. This change ensures that new instances of the `Column` model will have these attributes set to `True` by default. Based on the recent user commits and repository commits, the commit message follows the established convention of using a prefix to indicate the type of change (`feat` for a new feature) and provides a clear and concise description of the changes made. --- src/backend/base/langflow/schema/table.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/base/langflow/schema/table.py b/src/backend/base/langflow/schema/table.py index 9fd1890c2e4..a26dd737f20 100644 --- a/src/backend/base/langflow/schema/table.py +++ b/src/backend/base/langflow/schema/table.py @@ -1,7 +1,7 @@ from enum import Enum from typing import List, Optional -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field, field_validator class FormatterType(str, Enum): @@ -14,8 +14,8 @@ class FormatterType(str, Enum): class Column(BaseModel): display_name: str name: str - sortable: bool - filterable: bool + sortable: bool = Field(default=True) + filterable: bool = Field(default=True) formatter: Optional[FormatterType | str] = None @field_validator("formatter") From 5daab256a1d282c569c40e5270b8130f162e1541 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 16 Jul 2024 20:11:38 -0300 Subject: [PATCH 37/53] feat(utils.ts): add check for empty columns array in FormatColumns function to prevent errors --- src/frontend/src/utils/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index ca2b9439958..a6725cb59ec 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -1,5 +1,5 @@ import { ColumnField } from "@/types/utils/functions"; -import { BaseCellDataType, ColDef, ColGroupDef } from "ag-grid-community"; +import { ColDef, ColGroupDef } from "ag-grid-community"; import clsx, { ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; import TableAutoCellRender from "../components/tableComponent/components/tableAutoCellRender"; @@ -474,6 +474,7 @@ export function isEndpointNameValid(name: string, maxLength: number): boolean { } export function FormatColumns(columns: ColumnField[]): ColDef[] { + if (!columns) return []; const basic_types = new Set(["date", "number"]); const colDefs = columns.map((col, index) => { let newCol: ColDef = { From 3fc5286343397b5e663567a1da3888958da3df9c Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 16 Jul 2024 20:11:47 -0300 Subject: [PATCH 38/53] feat: Add validation for TableInput value in inputs.py The code changes in `inputs.py` add a validation function for the `value` attribute of the `TableInput` class. The function checks if the value is a list of dictionaries and raises a `ValueError` if it is not. This ensures that the `TableInput` instances have a valid value that is a list of dictionaries. Based on the recent user commits and repository commits, the commit message follows the established convention of using a prefix to indicate the type of change (`feat` for a new feature) and provides a clear and concise description of the changes made. --- src/backend/base/langflow/inputs/inputs.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/base/langflow/inputs/inputs.py b/src/backend/base/langflow/inputs/inputs.py index 96a8d1dd506..328c3f769da 100644 --- a/src/backend/base/langflow/inputs/inputs.py +++ b/src/backend/base/langflow/inputs/inputs.py @@ -27,6 +27,15 @@ class TableInput(BaseInputMixin, MetadataTraceMixin, TableMixin, ListableInputMi field_type: Optional[SerializableFieldTypes] = FieldTypes.TABLE is_list: bool = True + @field_validator("value") + @classmethod + def validate_value(cls, v: Any, _info): + # Check if value is a list of dicts + if isinstance(v, list): + if not all(isinstance(item, (dict, Data)) for item in v): + raise ValueError("TableInput must be a list of dictionaries") + return v + class HandleInput(BaseInputMixin, ListableInputMixin, MetadataTraceMixin): """ From b5f6e85f2ea24dd7ce83349a1fbcd04891b629b5 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 23:13:11 +0000 Subject: [PATCH 39/53] [autofix.ci] apply automated fixes --- .../tableComponent/components/TableOptions/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx index 71ea7bd32aa..f73b23bb0aa 100644 --- a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx +++ b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx @@ -47,7 +47,10 @@ export default function TableOptions({ From 13c7c8a9ad6b385d2394a96132d2e323eb6c4ebf Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 17 Jul 2024 12:37:10 -0300 Subject: [PATCH 40/53] feat: extend editable field to json field --- .../src/components/TableNodeComponent/index.tsx | 4 ++-- src/frontend/src/components/objectRender/index.tsx | 14 +++++++++----- .../components/tableAutoCellRender/index.tsx | 13 +++++-------- .../src/components/tableComponent/index.tsx | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index faca9e97f94..f5d66e240d4 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -60,11 +60,11 @@ export default function TableNodeComponent({ setAllRows(); } const editable = columns.map((column) => { - const is_text = column.formatter && column.formatter === "text"; + const isCustomEdit = column.formatter && (column.formatter === "text" || column.formatter === "json"); return { field: column.name, onUpdate: updateComponente, - editableCell: is_text ? false : true, + editableCell: isCustomEdit ? false : true, }; }); diff --git a/src/frontend/src/components/objectRender/index.tsx b/src/frontend/src/components/objectRender/index.tsx index 36d2c59d4b8..fc57c88ec78 100644 --- a/src/frontend/src/components/objectRender/index.tsx +++ b/src/frontend/src/components/objectRender/index.tsx @@ -1,12 +1,16 @@ import DictAreaModal from "../../modals/dictAreaModal"; -export default function ObjectRender({ object }: { object: any }): JSX.Element { - //TODO check object type - +export default function ObjectRender({ object, setValue }: { + object: any, + setValue?: (value: any) => void; +}): JSX.Element { + let preview = (object === null || object === undefined) ? "‎" : JSON.stringify(object); + if (object === null || object === undefined) { + } return ( - +
-
{JSON.stringify(object)}
+
{preview}
); diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index 57127245765..c5a89b6b1f2 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -7,7 +7,7 @@ import StringReader from "../../../stringReaderComponent"; import { Badge } from "../../../ui/badge"; interface CustomCellRender extends CustomCellRendererProps { - formatter?: "json"; + formatter?: "json" | "text"; } export default function TableAutoCellRender({ @@ -20,15 +20,12 @@ export default function TableAutoCellRender({ let format: string = formatter ? formatter : typeof value; //convert text to string to bind to the string reader format = format === "text" ? "string" : format; + format = format === "json" ? "object" : format; + switch (format) { case "object": - if (value === null) { - return String(value); - } else if (Array.isArray(value)) { - return ; - } else { - return ; - } + return ; + case "string": if (isTimeStampString(value)) { return ; diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx index 9de96cdd142..de6a807d4e3 100644 --- a/src/frontend/src/components/tableComponent/index.tsx +++ b/src/frontend/src/components/tableComponent/index.tsx @@ -66,7 +66,7 @@ const TableComponent = forwardRef< (typeof props.editable === "boolean" && props.editable) || (Array.isArray(props.editable) && props.editable.every((field) => typeof field === "string") && - (props.editable as Array).includes(newCol.headerName ?? "")) + (props.editable as Array).includes(newCol.field ?? "")) ) { newCol = { ...newCol, From 1430e7d6b8e96e2465352448630995e51315f3d9 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:45:22 +0000 Subject: [PATCH 41/53] [autofix.ci] apply automated fixes --- .../src/components/TableNodeComponent/index.tsx | 4 +++- src/frontend/src/components/objectRender/index.tsx | 12 ++++++++---- .../components/tableAutoCellRender/index.tsx | 7 ++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index f5d66e240d4..4f096828fad 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -60,7 +60,9 @@ export default function TableNodeComponent({ setAllRows(); } const editable = columns.map((column) => { - const isCustomEdit = column.formatter && (column.formatter === "text" || column.formatter === "json"); + const isCustomEdit = + column.formatter && + (column.formatter === "text" || column.formatter === "json"); return { field: column.name, onUpdate: updateComponente, diff --git a/src/frontend/src/components/objectRender/index.tsx b/src/frontend/src/components/objectRender/index.tsx index fc57c88ec78..c0b8e1e3bb8 100644 --- a/src/frontend/src/components/objectRender/index.tsx +++ b/src/frontend/src/components/objectRender/index.tsx @@ -1,14 +1,18 @@ import DictAreaModal from "../../modals/dictAreaModal"; -export default function ObjectRender({ object, setValue }: { - object: any, +export default function ObjectRender({ + object, + setValue, +}: { + object: any; setValue?: (value: any) => void; }): JSX.Element { - let preview = (object === null || object === undefined) ? "‎" : JSON.stringify(object); + let preview = + object === null || object === undefined ? "‎" : JSON.stringify(object); if (object === null || object === undefined) { } return ( - +
{preview}
diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index c5a89b6b1f2..91b3a3da2e8 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -24,7 +24,12 @@ export default function TableAutoCellRender({ switch (format) { case "object": - return ; + return ( + + ); case "string": if (isTimeStampString(value)) { From c9b398b9a9ec757e919b9ceb5c06b286830cb873 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 18 Jul 2024 09:44:00 -0300 Subject: [PATCH 42/53] feat: Add validation for TableInput value in inputs.py --- src/backend/base/langflow/inputs/inputs.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/backend/base/langflow/inputs/inputs.py b/src/backend/base/langflow/inputs/inputs.py index 328c3f769da..d6a5c042312 100644 --- a/src/backend/base/langflow/inputs/inputs.py +++ b/src/backend/base/langflow/inputs/inputs.py @@ -31,9 +31,14 @@ class TableInput(BaseInputMixin, MetadataTraceMixin, TableMixin, ListableInputMi @classmethod def validate_value(cls, v: Any, _info): # Check if value is a list of dicts - if isinstance(v, list): - if not all(isinstance(item, (dict, Data)) for item in v): - raise ValueError("TableInput must be a list of dictionaries") + if not isinstance(v, list): + raise ValueError(f"TableInput value must be a list of dictionaries or Data. Value '{v}' is not a list.") + + for item in v: + if not isinstance(item, (dict, Data)): + raise ValueError( + f"TableInput value must be a list of dictionaries or Data. Item '{item}' is not a dictionary or Data." + ) return v From ec98ec8a14b8236d2eba5f3c3c61fb7bcf1e74b5 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 18 Jul 2024 09:44:13 -0300 Subject: [PATCH 43/53] feat(validate.py): add exception handling to catch and re-raise ValidationError with a more informative error message --- src/backend/base/langflow/utils/validate.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/base/langflow/utils/validate.py b/src/backend/base/langflow/utils/validate.py index 30358eb48c9..69c7046e777 100644 --- a/src/backend/base/langflow/utils/validate.py +++ b/src/backend/base/langflow/utils/validate.py @@ -4,6 +4,8 @@ from types import FunctionType from typing import Dict, List, Optional, Union +from pydantic import ValidationError + from langflow.field_typing.constants import CUSTOM_COMPONENT_SUPPORTED_TYPES @@ -168,8 +170,11 @@ def create_class(code, class_name): class_code = extract_class_code(module, class_name) compiled_class = compile_class_code(class_code) - - return build_class_constructor(compiled_class, exec_globals, class_name) + try: + return build_class_constructor(compiled_class, exec_globals, class_name) + except ValidationError as e: + error_message = "\n".join([error["msg"].split(",", 1)[1] for error in e.errors()]) + raise ValueError(error_message) from e def create_type_ignore_class(): From f39e3eb0be4632c7a759f2f79fbfc8d3e120ca56 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 18 Jul 2024 09:45:33 -0300 Subject: [PATCH 44/53] chore: Refactor error message in build_custom_component_template function --- src/backend/base/langflow/custom/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/base/langflow/custom/utils.py b/src/backend/base/langflow/custom/utils.py index bf379206113..d721bc275dc 100644 --- a/src/backend/base/langflow/custom/utils.py +++ b/src/backend/base/langflow/custom/utils.py @@ -421,7 +421,7 @@ def build_custom_component_template( raise HTTPException( status_code=400, detail={ - "error": (f"Something went wrong while building the custom component. Hints: {str(exc)}"), + "error": (f"Error building Component: {str(exc)}"), "traceback": traceback.format_exc(), }, ) from exc From 8cf13116f916a56ea2747d61f0080344f4ebfcb6 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 18 Jul 2024 10:11:55 -0300 Subject: [PATCH 45/53] fix(validate.py): improve error message formatting in create_class function Refactor the error message formatting in the `create_class` function in `validate.py` to improve readability and clarity. Instead of using a list comprehension to extract the error messages, the code now uses a nested list comprehension to split the error messages and extract the relevant information. This change ensures that the error message is properly formatted and provides more informative details about the validation errors. Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: Lucas Oliveira --- src/backend/base/langflow/utils/validate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/base/langflow/utils/validate.py b/src/backend/base/langflow/utils/validate.py index 69c7046e777..7a0eef7b4a5 100644 --- a/src/backend/base/langflow/utils/validate.py +++ b/src/backend/base/langflow/utils/validate.py @@ -173,7 +173,8 @@ def create_class(code, class_name): try: return build_class_constructor(compiled_class, exec_globals, class_name) except ValidationError as e: - error_message = "\n".join([error["msg"].split(",", 1)[1] for error in e.errors()]) + messages = [error["msg"].split(",", 1) for error in e.errors()] + error_message = "\n".join([message[1] if len(message) > 1 else message[0] for message in messages]) raise ValueError(error_message) from e From 88d0d94a848a58a8ae596325906f6290296bf9cd Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 18 Jul 2024 10:12:04 -0300 Subject: [PATCH 46/53] feat: Update TableMixin to support TableSchema or list of Columns The TableMixin class in input_mixin.py has been updated to support either a TableSchema object or a list of Columns for the table_schema attribute. This change allows for more flexibility in defining the table schema for input validation. --- src/backend/base/langflow/inputs/input_mixin.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/backend/base/langflow/inputs/input_mixin.py b/src/backend/base/langflow/inputs/input_mixin.py index 4338c5af983..d3a34ee2d79 100644 --- a/src/backend/base/langflow/inputs/input_mixin.py +++ b/src/backend/base/langflow/inputs/input_mixin.py @@ -5,7 +5,7 @@ from langflow.field_typing.range_spec import RangeSpec from langflow.inputs.validators import CoalesceBool -from langflow.schema.table import TableSchema +from langflow.schema.table import Column, TableSchema class FieldTypes(str, Enum): @@ -141,4 +141,13 @@ class MultilineMixin(BaseModel): class TableMixin(BaseModel): - table_schema: Optional[TableSchema] = None + table_schema: Optional[TableSchema | list[Column]] = None + + @field_validator("table_schema") + @classmethod + def validate_table_schema(cls, v): + if isinstance(v, list) and all(isinstance(column, Column) for column in v): + return TableSchema(columns=v) + if isinstance(v, TableSchema): + return v + raise ValueError("table_schema must be a TableSchema or a list of Columns") From df98ae9e95c7a7f6a5207be0229a0b26cd47f793 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 18 Jul 2024 16:38:47 -0300 Subject: [PATCH 47/53] feat: Update TableNodeComponent to generate backend columns from value Refactor the TableNodeComponent to generate backend columns from the value when the columns prop is not provided. This change ensures that the component can handle dynamic column generation based on the value, improving flexibility and usability. Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: Lucas Oliveira --- src/frontend/src/components/TableNodeComponent/index.tsx | 9 +++++---- src/frontend/src/types/components/index.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 4f096828fad..c872fbe103c 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,5 +1,5 @@ import TableModal from "@/modals/tableModal"; -import { FormatColumns } from "@/utils/utils"; +import { FormatColumns, generateBackendColumnsFromValue } from "@/utils/utils"; import { SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; import { cloneDeep } from "lodash"; @@ -22,7 +22,8 @@ export default function TableNodeComponent({ } const [selectedNodes, setSelectedNodes] = useState>([]); const agGrid = useRef(null); - const AgColumns = FormatColumns(columns); + const componentColumns = columns?columns:generateBackendColumnsFromValue(value??[]); + const AgColumns = FormatColumns(componentColumns); function setAllRows() { if (agGrid.current) { @@ -50,7 +51,7 @@ export default function TableNodeComponent({ } function addRow() { const newRow = {}; - columns.forEach((column) => { + componentColumns.forEach((column) => { newRow[column.name] = null; }); onChange([...value, newRow]); @@ -59,7 +60,7 @@ export default function TableNodeComponent({ function updateComponente() { setAllRows(); } - const editable = columns.map((column) => { + const editable = componentColumns.map((column) => { const isCustomEdit = column.formatter && (column.formatter === "text" || column.formatter === "json"); diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index e2c419fa5a2..ef785b5de6a 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -143,7 +143,7 @@ export type TableComponentType = { value: any[]; editNode?: boolean; id?: string; - columns: ColumnField[]; + columns?: ColumnField[]; }; export type outputComponentType = { From 264bd9fd9a080d2b600d92fa61d514c89fd68f79 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 18 Jul 2024 16:38:56 -0300 Subject: [PATCH 48/53] Refactor extractColumnsFromRows function to return only ColDef objects The extractColumnsFromRows function in utils.ts has been refactored to return only ColDef objects instead of a combination of ColDef and ColGroupDef objects. This change simplifies the function's return type and improves consistency in the codebase. Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: Lucas Oliveira --- src/frontend/src/utils/utils.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index a6725cb59ec..384cc439183 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -358,7 +358,7 @@ export function extractColumnsFromRows( rows: object[], mode: "intersection" | "union", excludeColumns?: Array, -): (ColDef | ColGroupDef)[] { +): (ColDef)[] { let columnsKeys: { [key: string]: ColDef | ColGroupDef } = {}; if (rows.length === 0) { return []; @@ -498,3 +498,17 @@ export function FormatColumns(columns: ColumnField[]): ColDef[] { return colDefs; } + + +export function generateBackendColumnsFromValue(rows:Object[]):ColumnField[]{ + const columns = extractColumnsFromRows(rows, "union"); + return columns.map((column) => { + return { + name: column.field??"", + display_name: column.headerName??"", + sortable: true, + filterable: true, + }; + }); + +} From 46e61b524fcb44d508474721374809c16efbe51b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 19:50:06 +0000 Subject: [PATCH 49/53] [autofix.ci] apply automated fixes --- .../src/components/TableNodeComponent/index.tsx | 4 +++- src/frontend/src/utils/utils.ts | 10 ++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index c872fbe103c..21d1ad23b80 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -22,7 +22,9 @@ export default function TableNodeComponent({ } const [selectedNodes, setSelectedNodes] = useState>([]); const agGrid = useRef(null); - const componentColumns = columns?columns:generateBackendColumnsFromValue(value??[]); + const componentColumns = columns + ? columns + : generateBackendColumnsFromValue(value ?? []); const AgColumns = FormatColumns(componentColumns); function setAllRows() { diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index 384cc439183..38c3be185fb 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -358,7 +358,7 @@ export function extractColumnsFromRows( rows: object[], mode: "intersection" | "union", excludeColumns?: Array, -): (ColDef)[] { +): ColDef[] { let columnsKeys: { [key: string]: ColDef | ColGroupDef } = {}; if (rows.length === 0) { return []; @@ -499,16 +499,14 @@ export function FormatColumns(columns: ColumnField[]): ColDef[] { return colDefs; } - -export function generateBackendColumnsFromValue(rows:Object[]):ColumnField[]{ +export function generateBackendColumnsFromValue(rows: Object[]): ColumnField[] { const columns = extractColumnsFromRows(rows, "union"); return columns.map((column) => { return { - name: column.field??"", - display_name: column.headerName??"", + name: column.field ?? "", + display_name: column.headerName ?? "", sortable: true, filterable: true, }; }); - } From cdf240e90330726495b972953c654e2ea7d35f08 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 19 Jul 2024 13:17:05 -0300 Subject: [PATCH 50/53] refactor: Generate backend columns from value in TableNodeComponent Refactor the TableNodeComponent to generate backend columns from the value when the columns prop is not provided. This change ensures that the component can handle dynamic column generation based on the value, improving flexibility and usability. --- .../src/components/TableNodeComponent/index.tsx | 5 +---- src/frontend/src/types/utils/functions.ts | 2 +- src/frontend/src/utils/utils.ts | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 21d1ad23b80..2a5763931ef 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -17,16 +17,13 @@ export default function TableNodeComponent({ id = "", columns, }: TableComponentType): JSX.Element { - if (!columns) { - columns = []; - } const [selectedNodes, setSelectedNodes] = useState>([]); const agGrid = useRef(null); const componentColumns = columns ? columns : generateBackendColumnsFromValue(value ?? []); - const AgColumns = FormatColumns(componentColumns); + const AgColumns = FormatColumns(componentColumns); function setAllRows() { if (agGrid.current) { const rows: any = []; diff --git a/src/frontend/src/types/utils/functions.ts b/src/frontend/src/types/utils/functions.ts index 989476bddbb..077d7c767d6 100644 --- a/src/frontend/src/types/utils/functions.ts +++ b/src/frontend/src/types/utils/functions.ts @@ -9,7 +9,7 @@ export type getCodesObjProps = { export type getCodesObjReturn = Array<{ name: string; code: string }>; -enum FormatterType { +export enum FormatterType { date = "date", text = "text", number = "number", diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index 38c3be185fb..baadfc7bd6c 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -1,4 +1,4 @@ -import { ColumnField } from "@/types/utils/functions"; +import { ColumnField, FormatterType } from "@/types/utils/functions"; import { ColDef, ColGroupDef } from "ag-grid-community"; import clsx, { ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; @@ -502,11 +502,24 @@ export function FormatColumns(columns: ColumnField[]): ColDef[] { export function generateBackendColumnsFromValue(rows: Object[]): ColumnField[] { const columns = extractColumnsFromRows(rows, "union"); return columns.map((column) => { - return { + const newColumn: ColumnField = { name: column.field ?? "", display_name: column.headerName ?? "", sortable: true, filterable: true, }; + if (rows[0] && rows[0][column.field ?? ""]) { + const value = rows[0][column.field ?? ""] as any; + if (typeof value === "string") { + if (isTimeStampString(value)) { + newColumn.formatter = FormatterType.date; + } else { + newColumn.formatter = FormatterType.text; + } + } else if (typeof value === "object") { + newColumn.formatter = FormatterType.json; + } + } + return newColumn; }); } From bb04ddc3af6340fbdb1e82a3eadd229c4391f02e Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 19 Jul 2024 14:20:07 -0300 Subject: [PATCH 51/53] feat: Update TableNodeComponent to handle number and date properly --- .../components/TableNodeComponent/index.tsx | 46 +++++++++++++++++-- src/frontend/src/utils/utils.ts | 12 ++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 2a5763931ef..53b6aa98d5f 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -1,9 +1,9 @@ import TableModal from "@/modals/tableModal"; import { FormatColumns, generateBackendColumnsFromValue } from "@/utils/utils"; -import { SelectionChangedEvent } from "ag-grid-community"; +import { DataTypeDefinition, SelectionChangedEvent } from "ag-grid-community"; import { AgGridReact } from "ag-grid-react"; import { cloneDeep } from "lodash"; -import { useRef, useState } from "react"; +import { useMemo, useRef, useState } from "react"; import { ForwardedIconComponent } from "../../components/genericIconComponent"; import { TableComponentType } from "../../types/components"; import { Button } from "../ui/button"; @@ -17,12 +17,51 @@ export default function TableNodeComponent({ id = "", columns, }: TableComponentType): JSX.Element { + const dataTypeDefinitions: { + [cellDataType: string]: DataTypeDefinition; + } = useMemo(() => { + return { + // override `date` to handle custom date format `dd/mm/yyyy` + "date": { + baseDataType: 'date', + extendsDataType: 'date', + valueParser: params => { + if (params.newValue == null) { + return null; + } + // convert from `dd/mm/yyyy` + const dateParts = params.newValue.split('/'); + return dateParts.length === 3 ? new Date( + parseInt(dateParts[2]), + parseInt(dateParts[1]) - 1, + parseInt(dateParts[0]) + ) : null; + }, + valueFormatter: params => { + let date = params.value; + if (typeof params.value === 'string') { + date = new Date(params.value); + } + // convert to `dd/mm/yyyy` + return date == null + ? "‎" + : `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; + }, + }, + "number": { + baseDataType: 'number', + extendsDataType: 'number', + valueFormatter: params => params.value == null + ? "‎" + : `${params.value}`, + } + }; + }, []); const [selectedNodes, setSelectedNodes] = useState>([]); const agGrid = useRef(null); const componentColumns = columns ? columns : generateBackendColumnsFromValue(value ?? []); - const AgColumns = FormatColumns(componentColumns); function setAllRows() { if (agGrid.current) { @@ -74,6 +113,7 @@ export default function TableNodeComponent({
Date: Fri, 19 Jul 2024 14:30:27 -0300 Subject: [PATCH 52/53] fix bug that delete all rows on modal close --- src/frontend/src/components/TableNodeComponent/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 53b6aa98d5f..014ed7c112d 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -64,7 +64,7 @@ export default function TableNodeComponent({ : generateBackendColumnsFromValue(value ?? []); const AgColumns = FormatColumns(componentColumns); function setAllRows() { - if (agGrid.current) { + if (agGrid.current && !agGrid.current.api.isDestroyed( )) { const rows: any = []; agGrid.current.api.forEachNode((node) => rows.push(node.data)); onChange(rows); @@ -95,7 +95,7 @@ export default function TableNodeComponent({ onChange([...value, newRow]); } - function updateComponente() { + function updateComponent() { setAllRows(); } const editable = componentColumns.map((column) => { @@ -104,7 +104,7 @@ export default function TableNodeComponent({ (column.formatter === "text" || column.formatter === "json"); return { field: column.name, - onUpdate: updateComponente, + onUpdate: updateComponent, editableCell: isCustomEdit ? false : true, }; }); From 94a0970ede83da40ff3109b6e931fc77d5f34ff1 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:01:25 +0000 Subject: [PATCH 53/53] [autofix.ci] apply automated fixes --- .../components/TableNodeComponent/index.tsx | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/frontend/src/components/TableNodeComponent/index.tsx b/src/frontend/src/components/TableNodeComponent/index.tsx index 014ed7c112d..6c179ec6ecd 100644 --- a/src/frontend/src/components/TableNodeComponent/index.tsx +++ b/src/frontend/src/components/TableNodeComponent/index.tsx @@ -22,24 +22,26 @@ export default function TableNodeComponent({ } = useMemo(() => { return { // override `date` to handle custom date format `dd/mm/yyyy` - "date": { - baseDataType: 'date', - extendsDataType: 'date', - valueParser: params => { + date: { + baseDataType: "date", + extendsDataType: "date", + valueParser: (params) => { if (params.newValue == null) { return null; } // convert from `dd/mm/yyyy` - const dateParts = params.newValue.split('/'); - return dateParts.length === 3 ? new Date( - parseInt(dateParts[2]), - parseInt(dateParts[1]) - 1, - parseInt(dateParts[0]) - ) : null; + const dateParts = params.newValue.split("/"); + return dateParts.length === 3 + ? new Date( + parseInt(dateParts[2]), + parseInt(dateParts[1]) - 1, + parseInt(dateParts[0]), + ) + : null; }, - valueFormatter: params => { + valueFormatter: (params) => { let date = params.value; - if (typeof params.value === 'string') { + if (typeof params.value === "string") { date = new Date(params.value); } // convert to `dd/mm/yyyy` @@ -48,13 +50,12 @@ export default function TableNodeComponent({ : `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; }, }, - "number": { - baseDataType: 'number', - extendsDataType: 'number', - valueFormatter: params => params.value == null - ? "‎" - : `${params.value}`, - } + number: { + baseDataType: "number", + extendsDataType: "number", + valueFormatter: (params) => + params.value == null ? "‎" : `${params.value}`, + }, }; }, []); const [selectedNodes, setSelectedNodes] = useState>([]); @@ -64,7 +65,7 @@ export default function TableNodeComponent({ : generateBackendColumnsFromValue(value ?? []); const AgColumns = FormatColumns(componentColumns); function setAllRows() { - if (agGrid.current && !agGrid.current.api.isDestroyed( )) { + if (agGrid.current && !agGrid.current.api.isDestroyed()) { const rows: any = []; agGrid.current.api.forEachNode((node) => rows.push(node.data)); onChange(rows);