♻️ (frontend): replace TableToggleCellRender with TableNodeCellRender for better modularity and maintainability

 (frontend): add table toggle cell render component for node editing modal
 (frontend): add table tooltip render component for node editing modal
 (frontend): add use-column-defs hook for dynamic column definitions
 (frontend): add use-row-data hook for dynamic row data generation

♻️ (editNodeModal): refactor to use custom hooks for columnDefs and rowData
This commit is contained in:
cristhianzl 2024-06-05 17:12:04 -03:00
commit a17910a535
7 changed files with 176 additions and 177 deletions

View file

@ -1,49 +0,0 @@
import { CustomCellEditorProps, CustomCellRendererProps } from "ag-grid-react";
import { classNames, cn, isTimeStampString } from "../../utils/utils";
import ArrayReader from "../arrayReaderComponent";
import DateReader from "../dateReaderComponent";
import NumberReader from "../numberReader";
import ObjectRender from "../objectRender";
import StringReader from "../stringReaderComponent";
import { Badge } from "../ui/badge";
import { cloneDeep } from "lodash";
import { type } from "os";
import {
convertObjToArray,
convertValuesToNumbers,
hasDuplicateKeys,
scapedJSONStringfy,
} from "../../utils/reactflowUtils";
import CodeAreaComponent from "../codeAreaComponent";
import DictComponent from "../dictComponent";
import Dropdown from "../dropdownComponent";
import FloatComponent from "../floatComponent";
import InputFileComponent from "../inputFileComponent";
import InputGlobalComponent from "../inputGlobalComponent";
import InputListComponent from "../inputListComponent";
import IntComponent from "../intComponent";
import KeypairListComponent from "../keypairListComponent";
import PromptAreaComponent from "../promptComponent";
import TextAreaComponent from "../textAreaComponent";
import ToggleShadComponent from "../toggleShadComponent";
import { useState } from "react";
import useFlowStore from "../../stores/flowStore";
export default function TableToggleCellRender({
value: { name, enabled, setEnabled },
}: CustomCellRendererProps) {
const [value, setValue] = useState(enabled);
return (
<ToggleShadComponent
id={"show" + name}
enabled={value}
setEnabled={(e) => {
setValue(e);
setEnabled(e);
}}
size="small"
editNode={true}
/>
);
}

View file

@ -1,33 +1,26 @@
import { CustomCellEditorProps, CustomCellRendererProps } from "ag-grid-react";
import { classNames, cn, isTimeStampString } from "../../utils/utils";
import ArrayReader from "../arrayReaderComponent";
import DateReader from "../dateReaderComponent";
import NumberReader from "../numberReader";
import ObjectRender from "../objectRender";
import StringReader from "../stringReaderComponent";
import { Badge } from "../ui/badge";
import { CustomCellRendererProps } from "ag-grid-react";
import { cloneDeep } from "lodash";
import { type } from "os";
import { useState } from "react";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import DictComponent from "../../../../components/dictComponent";
import Dropdown from "../../../../components/dropdownComponent";
import FloatComponent from "../../../../components/floatComponent";
import InputFileComponent from "../../../../components/inputFileComponent";
import InputGlobalComponent from "../../../../components/inputGlobalComponent";
import InputListComponent from "../../../../components/inputListComponent";
import IntComponent from "../../../../components/intComponent";
import KeypairListComponent from "../../../../components/keypairListComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import useFlowStore from "../../../../stores/flowStore";
import {
convertObjToArray,
convertValuesToNumbers,
hasDuplicateKeys,
scapedJSONStringfy,
} from "../../utils/reactflowUtils";
import CodeAreaComponent from "../codeAreaComponent";
import DictComponent from "../dictComponent";
import Dropdown from "../dropdownComponent";
import FloatComponent from "../floatComponent";
import InputFileComponent from "../inputFileComponent";
import InputGlobalComponent from "../inputGlobalComponent";
import InputListComponent from "../inputListComponent";
import IntComponent from "../intComponent";
import KeypairListComponent from "../keypairListComponent";
import PromptAreaComponent from "../promptComponent";
import TextAreaComponent from "../textAreaComponent";
import ToggleShadComponent from "../toggleShadComponent";
import { useState } from "react";
import useFlowStore from "../../stores/flowStore";
} from "../../../../utils/reactflowUtils";
import { classNames } from "../../../../utils/utils";
export default function TableNodeCellRender({
node: { data },
@ -70,8 +63,8 @@ export default function TableNodeCellRender({
...id,
proxy: templateData.proxy,
}
: id,
),
: id
)
) ?? false;
function getCellType() {
switch (templateData.type) {
@ -142,7 +135,7 @@ export default function TableNodeCellRender({
<div
className={classNames(
"max-h-48 w-full overflow-auto custom-scroll",
templateValue?.length > 1 ? "my-3" : "",
templateValue?.length > 1 ? "my-3" : ""
)}
>
<KeypairListComponent

View file

@ -0,0 +1,22 @@
import { CustomCellRendererProps } from "ag-grid-react";
import { useState } from "react";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
export default function TableToggleCellRender({
value: { name, enabled, setEnabled },
}: CustomCellRendererProps) {
const [value, setValue] = useState(enabled);
return (
<ToggleShadComponent
id={"show" + name}
enabled={value}
setEnabled={(e) => {
setValue(e);
setEnabled(e);
}}
size="small"
editNode={true}
/>
);
}

View file

@ -0,0 +1,86 @@
import { ColDef, ValueGetterParams } from "ag-grid-community";
import { useMemo } from "react";
import TableAutoCellRender from "../../../components/tableAutoCellRender";
import TableNodeCellRender from "../components/tableNodeCellRender";
import TableToggleCellRender from "../components/tableToggleCellRender";
import TableTooltipRender from "../components/tableTooltipRender";
const useColumnDefs = (
myData: any,
handleOnNewValue: (newValue: any, name: string) => void,
changeAdvanced: (n: string) => void
) => {
const columnDefs: ColDef[] = useMemo(
() => [
{
headerName: "Name",
field: "display_name",
valueGetter: (params) => {
const templateParam = params.data;
return (
(templateParam.display_name
? templateParam.display_name
: templateParam.name) ?? params.data.key
);
},
cellRenderer: TableAutoCellRender,
flex: 1,
resizable: false,
cellClass: "no-border",
},
{
headerName: "Description",
field: "info",
tooltipField: "info",
tooltipComponent: TableTooltipRender,
cellRenderer: TableAutoCellRender,
autoHeight: true,
flex: 2,
resizable: false,
cellClass: "no-border",
},
{
headerName: "Value",
field: "value",
cellRenderer: TableNodeCellRender,
valueGetter: (params: ValueGetterParams) => {
return {
value: params.data.value,
nodeClass: myData.current.node,
handleOnNewValue: handleOnNewValue,
handleOnChangeDb: (value, key) => {
myData.current.node!.template[key].load_from_db = value;
},
};
},
minWidth: 330,
flex: 1,
resizable: false,
cellClass: "no-border",
},
{
headerName: "Show",
field: "advanced",
cellRenderer: TableToggleCellRender,
valueGetter: (params: ValueGetterParams) => {
return {
name: params.data.name,
enabled: !params.data.advanced,
setEnabled: () => {
changeAdvanced(params.data.key);
},
};
},
editable: false,
maxWidth: 80,
resizable: false,
cellClass: "no-border",
},
],
[]
);
return columnDefs;
};
export default useColumnDefs;

View file

@ -0,0 +1,37 @@
import { useMemo } from "react";
import { LANGFLOW_SUPPORTED_TYPES } from "../../../constants/constants";
import { TemplateVariableType } from "../../../types/api";
const useRowData = (myData) => {
const rowData = useMemo(() => {
return Object.keys(myData.current.node!.template)
.filter((key: string) => {
const templateParam = myData.current.node!.template[
key
] as TemplateVariableType;
return (
key.charAt(0) !== "_" &&
templateParam.show &&
LANGFLOW_SUPPORTED_TYPES.has(templateParam.type) &&
!(
(key === "code" && templateParam.type === "code") ||
(key.includes("code") && templateParam.proxy)
)
);
})
.map((key: string) => {
const templateParam = myData.current.node!.template[
key
] as TemplateVariableType;
return {
...templateParam,
key: key,
id: key,
};
});
}, [myData.current.node!.template]);
return rowData;
};
export default useRowData;

View file

@ -1,18 +1,13 @@
import { ColDef, ValueGetterParams } from "ag-grid-community";
import { ColDef } from "ag-grid-community";
import { forwardRef, useEffect, useRef } from "react";
import IconComponent from "../../components/genericIconComponent";
import TableAutoCellRender from "../../components/tableAutoCellRender";
import TableComponent from "../../components/tableComponent";
import TableNodeCellRender from "../../components/tableNodeCellRender";
import TableTooltipRender from "../../components/tableTooltipRender";
import ToggleShadComponent from "../../components/toggleShadComponent";
import { Badge } from "../../components/ui/badge";
import { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
import useFlowStore from "../../stores/flowStore";
import { TemplateVariableType } from "../../types/api";
import { NodeDataType } from "../../types/flow";
import BaseModal from "../baseModal";
import TableToggleCellRender from "../../components/tableToggleCellRender";
import useColumnDefs from "./hooks/use-column-defs";
import useRowData from "./hooks/use-row-data";
const EditNodeModal = forwardRef(
(
@ -27,7 +22,7 @@ const EditNodeModal = forwardRef(
setOpen: (open: boolean) => void;
data: NodeDataType;
},
ref,
ref
) => {
const nodes = useFlowStore((state) => state.nodes);
@ -52,98 +47,13 @@ const EditNodeModal = forwardRef(
}
}, [open]);
const rowData = Object.keys(myData.current.node!.template)
.filter((key: string) => {
const templateParam = myData.current.node!.template[
key
] as TemplateVariableType;
return (
key.charAt(0) !== "_" &&
templateParam.show &&
LANGFLOW_SUPPORTED_TYPES.has(templateParam.type) &&
!(
(key === "code" && templateParam.type === "code") ||
(key.includes("code") && templateParam.proxy)
)
);
})
.map((key: string) => {
const templateParam = myData.current.node!.template[
key
] as TemplateVariableType;
return {
...templateParam,
key: key,
id: key,
};
});
const rowData = useRowData(myData);
const columnDefs: ColDef[] = [
{
headerName: "Name",
field: "display_name",
valueGetter: (params) => {
const templateParam = params.data;
return (
(templateParam.display_name
? templateParam.display_name
: templateParam.name) ?? params.data.key
);
},
cellRenderer: TableAutoCellRender,
flex: 1,
resizable: false,
cellClass: "no-border",
},
{
headerName: "Description",
field: "info",
tooltipField: "info",
tooltipComponent: TableTooltipRender,
cellRenderer: TableAutoCellRender,
autoHeight: true,
flex: 2,
resizable: false,
cellClass: "no-border",
},
{
headerName: "Value",
field: "value",
cellRenderer: TableNodeCellRender,
valueGetter: (params: ValueGetterParams) => {
return {
value: params.data.value,
nodeClass: myData.current.node,
handleOnNewValue: handleOnNewValue,
handleOnChangeDb: (value, key) => {
myData.current.node!.template[key].load_from_db = value;
},
};
},
minWidth: 330,
flex: 1,
resizable: false,
cellClass: "no-border",
},
{
headerName: "Show",
field: "advanced",
cellRenderer: TableToggleCellRender,
valueGetter: (params: ValueGetterParams) => {
return {
name: params.data.name,
enabled: !params.data.advanced,
setEnabled: () => {
changeAdvanced(params.data.key);
},
};
},
editable: false,
maxWidth: 80,
resizable: false,
cellClass: "no-border",
},
];
const columnDefs: ColDef[] = useColumnDefs(
myData,
handleOnNewValue,
changeAdvanced
);
return (
<BaseModal
@ -200,7 +110,7 @@ const EditNodeModal = forwardRef(
<BaseModal.Footer submit={{ label: "Save Changes" }} />
</BaseModal>
);
},
}
);
export default EditNodeModal;