refactor: improve parameter render component (#3995)
* refactor: update dynamic parameter in ParameterRenderComponent to false * refactor: update CodeAreaComponent to use CodeAreaModal for node toolbar * feat: Add EmptyParameterComponent to render empty parameters * refactor: Add types for parameter render component Add typescript types for the parameter render component to improve code readability and maintainability. * feat: Add EmptyParameterComponent to render empty parameters * refactor: Update RefreshParameterComponent to use InputProps Update the RefreshParameterComponent to use the InputProps interface for better code readability and maintainability. * refactor: Update InputProps in parameterRenderComponent/types.ts Update the InputProps interface in parameterRenderComponent/types.ts to remove the Partial<OptionalInputProps> and simplify the composition of input props. This improves code readability and maintainability. * refactor: Update InputProps in parameterRenderComponent/types.ts * refactor: Update parameterRenderComponent/types.ts to use handleOnNewValue instead of onChange Update the parameterRenderComponent/types.ts file to import the handleOnNewValueType from "@/CustomNodes/hooks/use-handle-new-value" and replace the onChange function with handleOnNewValue in the BaseInputProps interface. This change improves code readability and maintainability. * update folder structure * refactor: Update TableModal to support disabled state Update the TableModal component to include a disabled prop, allowing the modal to be disabled when necessary. This improves the flexibility and usability of the component. * refactor: Update parameterRenderComponent/types.ts to include TableComponentType Update the parameterRenderComponent/types.ts file to include the TableComponentType interface, which defines the structure for a table component. This change improves code organization and maintainability. * refactor: Update parameterRenderComponent to use TableNodeComponent from the correct folder * refactor: Update codeAreaComponent imports and props in parameterRenderComponent Update the imports and props in the parameterRenderComponent file to reflect the changes made in the codeAreaComponent file. This refactor improves code organization and maintainability. * refactor: Update parameterRenderComponent/types.ts to include CodeAreaComponentType Update the parameterRenderComponent/types.ts file to include the CodeAreaComponentType interface, which defines the structure for a code area component. This change improves code organization and maintainability. * refactor: Remove unused import of CodeAreaComponent in nodeToolbarComponent Remove the unused import of CodeAreaComponent in the nodeToolbarComponent file to improve code cleanliness and maintainability. * refactor: Remove unused import of CodeAreaComponent in nodeToolbarComponent * refactor: Remove unused import of CodeAreaComponent in nodeToolbarComponent * refactor: Remove unused import of CodeAreaComponent in codeAreaComponent/index.tsx * refactor: Remove unused import of CodeAreaComponent in parameterRenderComponent/index.tsx * refactor: Update floatComponent imports and props in parameterRenderComponent Update the imports and props in the parameterRenderComponent file to reflect the changes made in the floatComponent file. This refactor improves code organization and maintainability. * refactor: Update floatComponent imports and props in parameterRenderComponent * update int component path * update int component type * update toogle location * refactor: Update ToggleComponentType in components/index.ts Remove the ToggleComponentType interface from the components/index.ts file. This change is part of a refactoring effort to remove unused code and improve code organization. * refactor: Update ToggleComponentType in components/index.ts Remove unused ToggleComponentType interface from components/index.ts * refactor: Update ToggleShadComponent to handle new value changes Refactor the ToggleShadComponent to handle new value changes by passing the updated value to the handleOnNewValue function. This improves the functionality and maintainability of the component. * refactor: Move InputFileComponent to parameterRenderComponent/components folder Move the InputFileComponent file from the src/frontend/src/components folder to the src/frontend/src/components/parameterRenderComponent/components folder. This change improves code organization and maintainability. * refactor: Add FileComponentType interface to parameterRenderComponent/types.ts Add the FileComponentType interface to the parameterRenderComponent/types.ts file. This interface defines the fileTypes property for the FileComponentType, allowing for better type checking and documentation. This change improves code organization and maintainability. * refactor: Update InputFileComponent props in parameterRenderComponent Update the props of the InputFileComponent in the parameterRenderComponent file to match the changes made in the index.tsx file. This refactor improves code organization and maintainability. * refactor: Move PromptAreaComponent to parameterRenderComponent/components folder * update types prompt field * refactor: Update PromptAreaComponent to handle new value changes Refactor the PromptAreaComponent to handle new value changes by passing the updated value to the handleOnNewValue function. This improves the functionality and maintainability of the component. * refactor: Move LinkComponent to parameterRenderComponent/components folder * refactor: Add LinkComponentType interface to parameterRenderComponent/types.ts Add the LinkComponentType interface to the parameterRenderComponent/types.ts file. This interface defines the icon and text properties for the LinkComponentType, allowing for better type checking and documentation. This change improves code organization and maintainability. * refactor: Update LinkComponent to use InputProps in parameterRenderComponent Update the LinkComponent in parameterRenderComponent to use the InputProps interface for better type checking and consistency. This refactor improves code organization and maintainability. * refactor: Move KeypairListComponent to parameterRenderComponent/components folder * refactor: Add KeyPairListComponentType interface to parameterRenderComponent/types.ts * refactor: Update KeypairListComponent to use InputProps in parameterRenderComponent Refactor the KeypairListComponent in parameterRenderComponent to use the InputProps interface for better type checking and consistency. This refactor improves code organization and maintainability. * refactor: Move DictComponent to parameterRenderComponent/components folder * refactor: Update KeyPairListComponentType interface in parameterRenderComponent/types.ts * refactor: Update KeypairListComponent to use InputProps in parameterRenderComponent * refactor: Move InputListComponent to parameterRenderComponent/components folder Move the InputListComponent to the parameterRenderComponent/components folder for better code organization and maintainability. * refactor: Add StrRenderComponentType interface to parameterRenderComponent/types.ts * refactor: Move InputListComponent to parameterRenderComponent/components folder * refactor: Move InputListComponent to parameterRenderComponent/components folder * refactor: Move InputListComponent to parameterRenderComponent/components folder Move the InputListComponent to the parameterRenderComponent/components folder for better code organization and maintainability. * refactor: Update InputListComponent to use InputProps in parameterRenderComponent Refactor the InputListComponent in parameterRenderComponent to use the InputProps interface for better type checking and consistency. This refactor improves code organization and maintainability. * refactor: Move IOFieldView to IOModal/components folder Move the IOFieldView component to the IOModal/components folder for better code organization and maintainability. * refactor: Move DropdownComponent to parameterRenderComponent/components folder * refactor: Add DropDownComponentType interface to parameterRenderComponent/types.ts * refactor: Update DropdownComponent import in StrRenderComponent Update the import statement for DropdownComponent in StrRenderComponent to reflect its new location in the parameterRenderComponent/components folder. This refactor improves code organization and maintainability. * refactor: Update StrRenderComponent to use baseInputProps Refactor the StrRenderComponent in parameterRenderComponent to use the baseInputProps object instead of individual props for better code organization and maintainability. * refactor: Update StrRenderComponent to use TextAreaComponent from correct location Update the import statement for TextAreaComponent in StrRenderComponent to reflect its new location in the parameterRenderComponent/components folder. This refactor improves code organization and maintainability. * remove unused imports * refactor: Add TextAreaComponentType interface to parameterRenderComponent/types.ts * refactor: Update TextAreaComponent to use handleOnNewValue instead of onChange Refactor the TextAreaComponent in parameterRenderComponent to use the handleOnNewValue function instead of the onChange function for better code consistency. This change aligns with the recent updates to the component's props and improves maintainability. * refactor: Update StrRenderComponent to use baseInputProps Refactor the StrRenderComponent in parameterRenderComponent to use the baseInputProps object instead of individual props for better code organization and maintainability. * refactor: Move inputGlobalComponent to parameterRenderComponent/components folder Move the inputGlobalComponent to the parameterRenderComponent/components folder to improve code organization and maintainability. * refactor: Move inputGlobalComponent to parameterRenderComponent/components folder * refactor: Update InputGlobalComponent to use handleOnNewValue instead of onChange Refactor the InputGlobalComponent in parameterRenderComponent to use the handleOnNewValue function instead of the onChange function for better code consistency. This change aligns with the recent updates to the component's props and improves maintainability. * refactor: Update StrRenderComponent to use baseInputProps Refactor the StrRenderComponent in parameterRenderComponent to use the baseInputProps object instead of individual props for better code organization and maintainability. * refactor: Move multiselectComponent to parameterRenderComponent/components folder Move the multiselectComponent to the parameterRenderComponent/components folder to improve code organization and maintainability. * refactor: Move MultiselectComponent to parameterRenderComponent/components folder Move the MultiselectComponent to the parameterRenderComponent/components folder to improve code organization and maintainability. * refactor: Move MultiselectComponent to parameterRenderComponent/components folder * refactor: Move MultiselectComponent to parameterRenderComponent/components folder * refactor: Remove unused code in StrRenderComponent * refactor: Remove unused code in StrRenderComponent * refactor: Remove unused code in StrRenderComponent * [autofix.ci] apply automated fixes * ✨ (tableInputComponent.spec.ts): add ua-parser-js library to parse user agent information for better control handling based on OS 🔧 (tableInputComponent.spec.ts): update key press event to use the correct control key based on the user's operating system for textarea selection. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
This commit is contained in:
parent
94a647f60d
commit
12a381a3fa
31 changed files with 642 additions and 651 deletions
|
|
@ -2,7 +2,7 @@ import { PopoverAnchor } from "@radix-ui/react-popover";
|
|||
import Fuse from "fuse.js";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
||||
import { DropDownComponentType } from "../../types/components";
|
||||
import { DropDownComponent } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import { default as ForwardedIconComponent } from "../genericIconComponent";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
|
|
@ -31,7 +31,7 @@ export default function Dropdown({
|
|||
editNode = false,
|
||||
id = "",
|
||||
children,
|
||||
}: DropDownComponentType): JSX.Element {
|
||||
}: DropDownComponent): JSX.Element {
|
||||
const [open, setOpen] = useState(children ? true : false);
|
||||
|
||||
const refButton = useRef<HTMLButtonElement>(null);
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
|
||||
import { InputFieldType } from "@/types/api";
|
||||
import Dropdown from "../../../dropdownComponent";
|
||||
import InputGlobalComponent from "../../../inputGlobalComponent";
|
||||
import InputListComponent from "../../../inputListComponent";
|
||||
import MultiselectComponent from "../../../multiselectComponent";
|
||||
import TextAreaComponent from "../../../textAreaComponent";
|
||||
|
||||
export function StrRenderComponent({
|
||||
templateData,
|
||||
value,
|
||||
name,
|
||||
disabled,
|
||||
handleOnNewValue,
|
||||
editNode,
|
||||
id,
|
||||
}: {
|
||||
templateData: Partial<InputFieldType>;
|
||||
value: any;
|
||||
name: string;
|
||||
disabled: boolean;
|
||||
handleOnNewValue: handleOnNewValueType;
|
||||
editNode: boolean;
|
||||
id: string;
|
||||
}) {
|
||||
const onChange = (value: any, dbValue?: boolean, skipSnapshot?: boolean) => {
|
||||
handleOnNewValue({ value, load_from_db: dbValue }, { skipSnapshot });
|
||||
};
|
||||
|
||||
if (!templateData.options) {
|
||||
return templateData?.list ? (
|
||||
<InputListComponent
|
||||
componentName={name ?? undefined}
|
||||
editNode={editNode}
|
||||
disabled={disabled}
|
||||
value={value || [""]}
|
||||
onChange={onChange}
|
||||
id={`inputlist_${id}`}
|
||||
/>
|
||||
) : templateData.multiline ? (
|
||||
<TextAreaComponent
|
||||
password={templateData.password}
|
||||
updateVisibility={() => {
|
||||
if (templateData.password !== undefined) {
|
||||
handleOnNewValue(
|
||||
{ password: !templateData.password },
|
||||
{ skipSnapshot: true },
|
||||
);
|
||||
}
|
||||
}}
|
||||
id={`textarea_${id}`}
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
value={value ?? ""}
|
||||
onChange={onChange}
|
||||
/>
|
||||
) : (
|
||||
<InputGlobalComponent
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
onChange={onChange}
|
||||
name={name}
|
||||
data={templateData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!!templateData.options && !!templateData?.list) {
|
||||
return (
|
||||
<MultiselectComponent
|
||||
editNode={editNode}
|
||||
disabled={disabled}
|
||||
options={
|
||||
(Array.isArray(templateData.options)
|
||||
? templateData.options
|
||||
: [templateData.options]) || []
|
||||
}
|
||||
combobox={templateData.combobox}
|
||||
value={
|
||||
(Array.isArray(templateData.value)
|
||||
? templateData.value
|
||||
: [templateData.value]) || []
|
||||
}
|
||||
id={`multiselect_${id}`}
|
||||
onSelect={onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!!templateData.options) {
|
||||
return (
|
||||
<Dropdown
|
||||
editNode={editNode}
|
||||
options={templateData.options}
|
||||
onSelect={onChange}
|
||||
combobox={templateData.combobox}
|
||||
value={value || ""}
|
||||
id={`dropdown_${id}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,19 +4,20 @@ import { DataTypeDefinition, SelectionChangedEvent } from "ag-grid-community";
|
|||
import { AgGridReact } from "ag-grid-react";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { ForwardedIconComponent } from "../../components/genericIconComponent";
|
||||
import { TableComponentType } from "../../types/components";
|
||||
import { Button } from "../ui/button";
|
||||
import { ForwardedIconComponent } from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { InputProps, TableComponentType } from "../../types";
|
||||
|
||||
export default function TableNodeComponent({
|
||||
tableTitle,
|
||||
description,
|
||||
value,
|
||||
onChange,
|
||||
editNode = false,
|
||||
id = "",
|
||||
columns,
|
||||
}: TableComponentType): JSX.Element {
|
||||
handleOnNewValue,
|
||||
disabled = false,
|
||||
}: InputProps<any[], TableComponentType>): JSX.Element {
|
||||
const dataTypeDefinitions: {
|
||||
[cellDataType: string]: DataTypeDefinition<any>;
|
||||
} = useMemo(() => {
|
||||
|
|
@ -68,7 +69,7 @@ export default function TableNodeComponent({
|
|||
if (agGrid.current && !agGrid.current.api.isDestroyed()) {
|
||||
const rows: any = [];
|
||||
agGrid.current.api.forEachNode((node) => rows.push(node.data));
|
||||
onChange(rows);
|
||||
handleOnNewValue({ value: rows });
|
||||
}
|
||||
}
|
||||
function deleteRow() {
|
||||
|
|
@ -85,7 +86,7 @@ export default function TableNodeComponent({
|
|||
const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data));
|
||||
setSelectedNodes([]);
|
||||
const rows: any = [];
|
||||
onChange([...value, ...toDuplicate]);
|
||||
handleOnNewValue({ value: [...value, ...toDuplicate] });
|
||||
}
|
||||
}
|
||||
function addRow() {
|
||||
|
|
@ -93,7 +94,7 @@ export default function TableNodeComponent({
|
|||
componentColumns.forEach((column) => {
|
||||
newRow[column.name] = null;
|
||||
});
|
||||
onChange([...value, newRow]);
|
||||
handleOnNewValue({ value: [...value, newRow] });
|
||||
}
|
||||
|
||||
function updateComponent() {
|
||||
|
|
@ -111,7 +112,11 @@ export default function TableNodeComponent({
|
|||
});
|
||||
|
||||
return (
|
||||
<div className={"flex w-full items-center"}>
|
||||
<div
|
||||
className={
|
||||
"flex w-full items-center" + (disabled ? " cursor-not-allowed" : "")
|
||||
}
|
||||
>
|
||||
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
|
||||
<TableModal
|
||||
dataTypeDefinitions={dataTypeDefinitions}
|
||||
|
|
@ -135,9 +140,13 @@ export default function TableNodeComponent({
|
|||
rowData={value}
|
||||
>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
variant="primary"
|
||||
size={editNode ? "xs" : "default"}
|
||||
className="w-full"
|
||||
className={
|
||||
"w-full " +
|
||||
(disabled ? "pointer-events-none cursor-not-allowed" : "")
|
||||
}
|
||||
>
|
||||
<ForwardedIconComponent name="Table" className="mt-px h-4 w-4" />
|
||||
<span className="font-normal">Open Table</span>
|
||||
|
|
@ -1,30 +1,26 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import CodeAreaModal from "../../modals/codeAreaModal";
|
||||
import { CodeAreaComponentType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import CodeAreaModal from "../../../../modals/codeAreaModal";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { InputProps } from "../../types";
|
||||
|
||||
export default function CodeAreaComponent({
|
||||
value,
|
||||
onChange,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
editNode = false,
|
||||
nodeClass,
|
||||
dynamic,
|
||||
setNodeClass,
|
||||
handleNodeClass,
|
||||
id = "",
|
||||
readonly = false,
|
||||
open,
|
||||
setOpen,
|
||||
}: CodeAreaComponentType) {
|
||||
}: InputProps<string>) {
|
||||
const [componentValue, setComponentValue] = useState(
|
||||
typeof value == "string" ? value : JSON.stringify(value),
|
||||
);
|
||||
useEffect(() => {
|
||||
if (disabled && componentValue !== "") {
|
||||
setComponentValue("");
|
||||
onChange("", undefined, true);
|
||||
handleOnNewValue({ value: "" }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -33,7 +29,7 @@ export default function CodeAreaComponent({
|
|||
}, [value]);
|
||||
|
||||
const handleValueChange = (newValue) => {
|
||||
onChange(newValue);
|
||||
handleOnNewValue({ value: newValue });
|
||||
};
|
||||
|
||||
const renderInputText = () => (
|
||||
|
|
@ -68,13 +64,10 @@ export default function CodeAreaComponent({
|
|||
return (
|
||||
<div className={cn("w-full", disabled && "pointer-events-none")}>
|
||||
<CodeAreaModal
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
readonly={readonly}
|
||||
dynamic={dynamic}
|
||||
dynamic={false}
|
||||
value={value}
|
||||
nodeClass={nodeClass}
|
||||
setNodeClass={setNodeClass!}
|
||||
setNodeClass={handleNodeClass!}
|
||||
setValue={handleValueChange}
|
||||
>
|
||||
<div className="flex w-full items-center gap-3">
|
||||
|
|
@ -1,30 +1,27 @@
|
|||
import { useEffect } from "react";
|
||||
import { DictComponentType } from "../../types/components";
|
||||
|
||||
import DictAreaModal from "../../modals/dictAreaModal";
|
||||
import { classNames, cn } from "../../utils/utils";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import DictAreaModal from "../../../../modals/dictAreaModal";
|
||||
import { classNames, cn } from "../../../../utils/utils";
|
||||
import ForwardedIconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { InputProps } from "../../types";
|
||||
|
||||
export default function DictComponent({
|
||||
value = [],
|
||||
onChange,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
editNode = false,
|
||||
id = "",
|
||||
}: DictComponentType): JSX.Element {
|
||||
// Create a reference to the value
|
||||
|
||||
}: InputProps<object | object[] | string>): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (disabled) {
|
||||
onChange({});
|
||||
handleOnNewValue({ value: {} }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
value.length > 1 && editNode ? "my-1" : "",
|
||||
"flex w-full flex-col gap-3",
|
||||
disabled ? "pointer-events-none" : "",
|
||||
)}
|
||||
|
|
@ -32,9 +29,9 @@ export default function DictComponent({
|
|||
{
|
||||
<div className="flex w-full gap-3" data-testid={id}>
|
||||
<DictAreaModal
|
||||
value={value}
|
||||
value={(value || "").toString() === "{}" ? {} : value}
|
||||
onChange={(obj) => {
|
||||
onChange(obj);
|
||||
handleOnNewValue({ value: obj });
|
||||
}}
|
||||
disabled={disabled}
|
||||
>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import Dropdown from "../../../dropdownComponent";
|
||||
import { DropDownComponentType, InputProps } from "../../types";
|
||||
|
||||
export default function DropdownComponent({
|
||||
id,
|
||||
value,
|
||||
editNode,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
combobox,
|
||||
options,
|
||||
}: InputProps<string, DropDownComponentType>) {
|
||||
const onChange = (value: any, dbValue?: boolean, skipSnapshot?: boolean) => {
|
||||
handleOnNewValue({ value, load_from_db: dbValue }, { skipSnapshot });
|
||||
};
|
||||
return (
|
||||
<Dropdown
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
options={options}
|
||||
onSelect={onChange}
|
||||
combobox={combobox}
|
||||
value={value || ""}
|
||||
id={`dropdown_${id}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { InputProps } from "../../types";
|
||||
|
||||
export function EmptyParameterComponent({
|
||||
id,
|
||||
value,
|
||||
editNode,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
}: InputProps) {
|
||||
return <div id={id}>{String(value)}</div>;
|
||||
}
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
import { useEffect } from "react";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { Input } from "../ui/input";
|
||||
import { handleKeyDown } from "../../../../utils/reactflowUtils";
|
||||
import { Input } from "../../../ui/input";
|
||||
import { FloatComponentType, InputProps } from "../../types";
|
||||
|
||||
export default function FloatComponent({
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
rangeSpec,
|
||||
editNode = false,
|
||||
}: FloatComponentType): JSX.Element {
|
||||
handleOnNewValue,
|
||||
}: InputProps<string, FloatComponentType>): JSX.Element {
|
||||
const step = rangeSpec?.step ?? 0.1;
|
||||
const min = rangeSpec?.min ?? -2;
|
||||
const max = rangeSpec?.max ?? 2;
|
||||
// Clear component state
|
||||
useEffect(() => {
|
||||
if (disabled && value !== "") {
|
||||
onChange("", undefined, true);
|
||||
handleOnNewValue({ value: "" }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ export default function FloatComponent({
|
|||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
onChange(Number(event.target.value));
|
||||
handleOnNewValue({ value: Number(event.target.value) });
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -7,12 +7,12 @@ import {
|
|||
CONSOLE_ERROR_MSG,
|
||||
INVALID_FILE_ALERT,
|
||||
INVALID_FILE_SIZE_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { FileComponentType } from "../../types/components";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
} from "../../../../constants/alerts_constants";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { FileComponentType, InputProps } from "../../types";
|
||||
|
||||
export default function InputFileComponent({
|
||||
value,
|
||||
|
|
@ -21,7 +21,7 @@ export default function InputFileComponent({
|
|||
fileTypes,
|
||||
editNode = false,
|
||||
id,
|
||||
}: FileComponentType): JSX.Element {
|
||||
}: InputProps<string, FileComponentType>): JSX.Element {
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const { validateFileSize } = useFileSizeValidator(setErrorData);
|
||||
|
|
@ -3,34 +3,39 @@ import {
|
|||
useGetGlobalVariables,
|
||||
} from "@/controllers/API/queries/variables";
|
||||
import { useEffect } from "react";
|
||||
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { InputGlobalComponentType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import GlobalVariableModal from "../GlobalVariableModal/GlobalVariableModal";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import InputComponent from "../inputComponent";
|
||||
import { CommandItem } from "../ui/command";
|
||||
import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
import GlobalVariableModal from "../../../GlobalVariableModal/GlobalVariableModal";
|
||||
import ForwardedIconComponent from "../../../genericIconComponent";
|
||||
import InputComponent from "../../../inputComponent";
|
||||
import { CommandItem } from "../../../ui/command";
|
||||
import { InputGlobalComponentType, InputProps } from "../../types";
|
||||
|
||||
export default function InputGlobalComponent({
|
||||
disabled,
|
||||
onChange,
|
||||
name,
|
||||
data,
|
||||
handleOnNewValue,
|
||||
value,
|
||||
id,
|
||||
load_from_db,
|
||||
password,
|
||||
editNode = false,
|
||||
}: InputGlobalComponentType): JSX.Element {
|
||||
}: InputProps<string, InputGlobalComponentType>): JSX.Element {
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
|
||||
const { data: globalVariables } = useGetGlobalVariables();
|
||||
const { mutate: mutateDeleteGlobalVariable } = useDeleteGlobalVariables();
|
||||
|
||||
useEffect(() => {
|
||||
if (data && globalVariables)
|
||||
if (globalVariables)
|
||||
if (
|
||||
data.load_from_db &&
|
||||
!globalVariables.find((variable) => variable.name === data.value)
|
||||
load_from_db &&
|
||||
!globalVariables.find((variable) => variable.name === value)
|
||||
) {
|
||||
onChange("", false, true);
|
||||
handleOnNewValue(
|
||||
{ value: "", load_from_db: false },
|
||||
{ skipSnapshot: true },
|
||||
);
|
||||
}
|
||||
}, [globalVariables]);
|
||||
|
||||
|
|
@ -42,8 +47,8 @@ export default function InputGlobalComponent({
|
|||
{ id },
|
||||
{
|
||||
onSuccess: () => {
|
||||
if (data?.value === key && data?.load_from_db) {
|
||||
onChange("", false);
|
||||
if (value === key && load_from_db) {
|
||||
handleOnNewValue({ value: "", load_from_db: false });
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
|
|
@ -63,11 +68,11 @@ export default function InputGlobalComponent({
|
|||
}
|
||||
return (
|
||||
<InputComponent
|
||||
id={"input-" + name}
|
||||
id={id}
|
||||
editNode={editNode}
|
||||
disabled={disabled}
|
||||
password={data.password ?? false}
|
||||
value={data.value ?? ""}
|
||||
password={password ?? false}
|
||||
value={value ?? ""}
|
||||
options={globalVariables?.map((variable) => variable.name) ?? []}
|
||||
optionsPlaceholder={"Global Variables"}
|
||||
optionsIcon="Globe"
|
||||
|
|
@ -110,19 +115,23 @@ export default function InputGlobalComponent({
|
|||
</DeleteConfirmationModal>
|
||||
)}
|
||||
selectedOption={
|
||||
data?.load_from_db &&
|
||||
load_from_db &&
|
||||
globalVariables &&
|
||||
globalVariables
|
||||
?.map((variable) => variable.name)
|
||||
.includes(data?.value ?? "")
|
||||
? data?.value
|
||||
globalVariables?.map((variable) => variable.name).includes(value ?? "")
|
||||
? value
|
||||
: ""
|
||||
}
|
||||
setSelectedOption={(value) => {
|
||||
onChange(value, value !== "" ? true : false);
|
||||
handleOnNewValue({
|
||||
value: value,
|
||||
load_from_db: value !== "" ? true : false,
|
||||
});
|
||||
}}
|
||||
onChange={(value, skipSnapshot) => {
|
||||
onChange(value, false, skipSnapshot);
|
||||
handleOnNewValue(
|
||||
{ value: value, load_from_db: false },
|
||||
{ skipSnapshot },
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
@ -1,24 +1,23 @@
|
|||
import { useEffect } from "react";
|
||||
import { InputListComponentType } from "../../types/components";
|
||||
|
||||
import _ from "lodash";
|
||||
import { classNames, cn } from "../../utils/utils";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import { Input } from "../ui/input";
|
||||
import { classNames, cn } from "../../../../utils/utils";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { Input } from "../../../ui/input";
|
||||
import { InputListComponentType, InputProps } from "../../types";
|
||||
|
||||
export default function InputListComponent({
|
||||
value,
|
||||
onChange,
|
||||
value = [""],
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
editNode = false,
|
||||
componentName,
|
||||
playgroundDisabled,
|
||||
id,
|
||||
}: InputListComponentType): JSX.Element {
|
||||
}: InputProps<string[], InputListComponentType>): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (disabled && value.length > 0 && value[0] !== "") {
|
||||
onChange([""], undefined, true);
|
||||
handleOnNewValue({ value: [""] }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -32,26 +31,26 @@ export default function InputListComponent({
|
|||
const handleInputChange = (index, newValue) => {
|
||||
const newInputList = _.cloneDeep(value);
|
||||
newInputList[index] = newValue;
|
||||
onChange(newInputList);
|
||||
handleOnNewValue({ value: newInputList });
|
||||
};
|
||||
|
||||
const addNewInput = (e) => {
|
||||
e.preventDefault();
|
||||
const newInputList = _.cloneDeep(value);
|
||||
newInputList.push("");
|
||||
onChange(newInputList);
|
||||
handleOnNewValue({ value: newInputList });
|
||||
};
|
||||
|
||||
const removeInput = (index, e) => {
|
||||
e.preventDefault();
|
||||
const newInputList = _.cloneDeep(value);
|
||||
newInputList.splice(index, 1);
|
||||
onChange(newInputList);
|
||||
handleOnNewValue({ value: newInputList });
|
||||
};
|
||||
|
||||
const getButtonClassName = () =>
|
||||
classNames(
|
||||
disabled || playgroundDisabled
|
||||
disabled
|
||||
? "cursor-not-allowed text-muted-foreground"
|
||||
: "text-primary hover:text-accent-foreground",
|
||||
);
|
||||
|
|
@ -69,7 +68,7 @@ export default function InputListComponent({
|
|||
{value.map((singleValue, index) => (
|
||||
<div key={index} className="flex w-full gap-3">
|
||||
<Input
|
||||
disabled={disabled || playgroundDisabled}
|
||||
disabled={disabled}
|
||||
type="text"
|
||||
value={singleValue}
|
||||
className={editNode ? "input-edit-node" : ""}
|
||||
|
|
@ -82,7 +81,7 @@ export default function InputListComponent({
|
|||
className={getButtonClassName()}
|
||||
onClick={index === 0 ? addNewInput : (e) => removeInput(index, e)}
|
||||
data-testid={getTestId(index === 0 ? "plus" : "minus", index)}
|
||||
disabled={disabled || playgroundDisabled}
|
||||
disabled={disabled}
|
||||
>
|
||||
<IconComponent
|
||||
name={index === 0 ? "Plus" : "X"}
|
||||
|
|
@ -7,24 +7,24 @@ import {
|
|||
NumberInputStepper,
|
||||
} from "@chakra-ui/number-input";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { IntComponentType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { handleKeyDown } from "../../../../utils/reactflowUtils";
|
||||
import { InputProps, IntComponentType } from "../../types";
|
||||
|
||||
export default function IntComponent({
|
||||
value,
|
||||
onChange,
|
||||
handleOnNewValue,
|
||||
rangeSpec,
|
||||
disabled,
|
||||
editNode = false,
|
||||
id = "",
|
||||
}: IntComponentType): JSX.Element {
|
||||
}: InputProps<number, IntComponentType>): JSX.Element {
|
||||
const min = -Infinity;
|
||||
// Clear component state
|
||||
useEffect(() => {
|
||||
if (disabled && value !== 0) {
|
||||
onChange(0, undefined, true);
|
||||
handleOnNewValue({ value: 0 }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled, onChange]);
|
||||
}, [disabled, handleOnNewValue]);
|
||||
|
||||
const [cursor, setCursor] = useState<number | null>(null);
|
||||
const ref = useRef<HTMLInputElement>(null);
|
||||
|
|
@ -35,7 +35,7 @@ export default function IntComponent({
|
|||
|
||||
const handleChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setCursor(e.target.selectionStart);
|
||||
onChange(Number(e.target.value));
|
||||
handleOnNewValue({ value: Number(e.target.value) });
|
||||
};
|
||||
|
||||
const getStepValue = () => {
|
||||
|
|
@ -58,7 +58,7 @@ export default function IntComponent({
|
|||
};
|
||||
|
||||
const handleNumberChange = (newValue) => {
|
||||
onChange(Number(newValue));
|
||||
handleOnNewValue({ value: Number(newValue) });
|
||||
};
|
||||
|
||||
const handleInputChange = (event) => {
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { KeyPairListComponentType } from "../../types/components";
|
||||
|
||||
import {
|
||||
convertObjToArray,
|
||||
|
|
@ -7,20 +6,24 @@ import {
|
|||
hasDuplicateKeys,
|
||||
} from "@/utils/reactflowUtils";
|
||||
import { cloneDeep } from "lodash";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Input } from "../ui/input";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Input } from "../../../ui/input";
|
||||
import { InputProps, KeyPairListComponentType } from "../../types";
|
||||
|
||||
export default function KeypairListComponent({
|
||||
value,
|
||||
onChange,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
editNode = false,
|
||||
isList = true,
|
||||
id,
|
||||
}: KeyPairListComponentType): JSX.Element {
|
||||
}: InputProps<
|
||||
object[] | object | string,
|
||||
KeyPairListComponentType
|
||||
>): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (disabled && value.length > 0 && value[0] !== "") {
|
||||
onChange([{ "": "" }]);
|
||||
handleOnNewValue({ value: [{ "": "" }] }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -37,8 +40,8 @@ export default function KeypairListComponent({
|
|||
const valueToNumbers = convertValuesToNumbers(newValue);
|
||||
setDuplicateKey(hasDuplicateKeys(valueToNumbers));
|
||||
if (isList) {
|
||||
onChange(valueToNumbers);
|
||||
} else onChange(valueToNumbers[0]);
|
||||
handleOnNewValue({ value: valueToNumbers });
|
||||
} else handleOnNewValue({ value: valueToNumbers[0] });
|
||||
};
|
||||
|
||||
const handleChangeKey = (event, idx) => {
|
||||
|
|
@ -64,13 +67,13 @@ export default function KeypairListComponent({
|
|||
const addNewKeyValuePair = () => {
|
||||
const newValues = cloneDeep(values);
|
||||
newValues.push({ "": "" });
|
||||
onChange(newValues);
|
||||
handleOnNewValue({ value: newValues });
|
||||
};
|
||||
|
||||
const removeKeyValuePair = (index) => {
|
||||
const newValues = cloneDeep(values);
|
||||
newValues.splice(index, 1);
|
||||
onChange(newValues);
|
||||
handleOnNewValue({ value: newValues });
|
||||
};
|
||||
|
||||
const getInputClassName = (isEditNode, isDuplicateKey) => {
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
import { LinkComponentType } from "@/types/components";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { classNames } from "../../utils/utils";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import { classNames } from "../../../../utils/utils";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { InputProps, LinkComponentType } from "../../types";
|
||||
|
||||
const DEFAULT_ICON = "ExternalLink";
|
||||
|
||||
|
|
@ -10,21 +9,17 @@ export default function LinkComponent({
|
|||
value,
|
||||
disabled = false,
|
||||
id = "",
|
||||
}: LinkComponentType): JSX.Element {
|
||||
const [componentValue, setComponentValue] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
setComponentValue(value);
|
||||
}, [value]);
|
||||
|
||||
const handleOpenLink = useCallback(() => {
|
||||
if (componentValue?.value) {
|
||||
const url = !/^https?:\/\//i.test(componentValue.value)
|
||||
? `https://${componentValue.value}`
|
||||
: componentValue.value;
|
||||
text,
|
||||
icon,
|
||||
editNode = false,
|
||||
handleOnNewValue,
|
||||
}: InputProps<string, LinkComponentType>): JSX.Element {
|
||||
function handleOpenLink() {
|
||||
if (value) {
|
||||
const url = !/^https?:\/\//i.test(value) ? `https://${value}` : value;
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
}, [componentValue]);
|
||||
}
|
||||
|
||||
const buttonClassName = classNames(
|
||||
"nopan w-full shrink-0",
|
||||
|
|
@ -49,16 +44,13 @@ export default function LinkComponent({
|
|||
<Button
|
||||
data-testid={id}
|
||||
onClick={handleOpenLink}
|
||||
disabled={disabled || !componentValue}
|
||||
disabled={disabled || !value}
|
||||
type="button"
|
||||
variant="primary"
|
||||
size="sm"
|
||||
className={buttonClassName}
|
||||
>
|
||||
<ButtonContent
|
||||
icon={componentValue?.icon ?? DEFAULT_ICON}
|
||||
text={componentValue?.text ?? ""}
|
||||
/>
|
||||
<ButtonContent icon={icon ?? DEFAULT_ICON} text={text ?? ""} />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -1,42 +1,42 @@
|
|||
import { PopoverAnchor } from "@radix-ui/react-popover";
|
||||
import Fuse from "fuse.js";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { MultiselectComponentType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import { default as ForwardedIconComponent } from "../genericIconComponent";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
import { default as ForwardedIconComponent } from "../../../genericIconComponent";
|
||||
import ShadTooltip from "../../../shadTooltipComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "../ui/command";
|
||||
} from "../../../ui/command";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverContentWithoutPortal,
|
||||
PopoverTrigger,
|
||||
} from "../ui/popover";
|
||||
} from "../../../ui/popover";
|
||||
import { InputProps, MultiselectComponentType } from "../../types";
|
||||
|
||||
export default function MultiselectComponent({
|
||||
disabled,
|
||||
isLoading,
|
||||
value,
|
||||
options: defaultOptions,
|
||||
handleOnNewValue,
|
||||
combobox,
|
||||
onSelect,
|
||||
editNode = false,
|
||||
id = "",
|
||||
children,
|
||||
}: MultiselectComponentType): JSX.Element {
|
||||
const [open, setOpen] = useState(children ? true : false);
|
||||
}: InputProps<string[], MultiselectComponentType>): JSX.Element {
|
||||
const [open, setOpen] = useState(false);
|
||||
const treatedValue = typeof value === "string" ? [value] : value;
|
||||
|
||||
const refButton = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const PopoverContentDropdown =
|
||||
children || editNode ? PopoverContent : PopoverContentWithoutPortal;
|
||||
const PopoverContentDropdown = editNode
|
||||
? PopoverContent
|
||||
: PopoverContentWithoutPortal;
|
||||
|
||||
const [customValues, setCustomValues] = useState<string[]>([]);
|
||||
const [searchValue, setSearchValue] = useState("");
|
||||
|
|
@ -46,7 +46,7 @@ export default function MultiselectComponent({
|
|||
const [options, setOptions] = useState<string[]>(defaultOptions);
|
||||
|
||||
const fuseOptions = new Fuse(options, { keys: ["name", "value"] });
|
||||
const fuseValues = new Fuse(value, { keys: ["name", "value"] });
|
||||
const fuseValues = new Fuse(treatedValue, { keys: ["name", "value"] });
|
||||
|
||||
const searchRoleByTerm = async (v: string) => {
|
||||
const fuse = onlySelected ? fuseValues : fuseOptions;
|
||||
|
|
@ -57,14 +57,14 @@ export default function MultiselectComponent({
|
|||
v
|
||||
? filtered
|
||||
: onlySelected
|
||||
? options.filter((x) => value.includes(x))
|
||||
? options.filter((x) => treatedValue.includes(x))
|
||||
: options,
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (disabled && value.length > 0 && value[0] !== "") {
|
||||
onSelect([], undefined, true);
|
||||
if (disabled && treatedValue.length > 0 && treatedValue[0] !== "") {
|
||||
handleOnNewValue({ value: [] }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -77,9 +77,11 @@ export default function MultiselectComponent({
|
|||
}, [options]);
|
||||
|
||||
useEffect(() => {
|
||||
setCustomValues(value.filter((v) => !defaultOptions.includes(v)) ?? []);
|
||||
setCustomValues(
|
||||
treatedValue.filter((v) => !defaultOptions.includes(v)) ?? [],
|
||||
);
|
||||
setOptions([
|
||||
...value.filter((v) => !defaultOptions.includes(v) && v),
|
||||
...treatedValue.filter((v) => !defaultOptions.includes(v) && v),
|
||||
...defaultOptions,
|
||||
]);
|
||||
}, [value]);
|
||||
|
|
@ -93,10 +95,12 @@ export default function MultiselectComponent({
|
|||
}, [open]);
|
||||
|
||||
const handleOptionSelect = (currentValue) => {
|
||||
if (value.includes(currentValue)) {
|
||||
onSelect(value.filter((v) => v !== currentValue));
|
||||
if (treatedValue.includes(currentValue)) {
|
||||
handleOnNewValue({
|
||||
value: treatedValue.filter((v) => v !== currentValue),
|
||||
});
|
||||
} else {
|
||||
onSelect([...value, currentValue]);
|
||||
handleOnNewValue({ value: [...treatedValue, currentValue] });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -118,8 +122,9 @@ export default function MultiselectComponent({
|
|||
)}
|
||||
>
|
||||
<span className="truncate" data-testid={`value-dropdown-${id}`}>
|
||||
{value.length > 0 && options.find((option) => value.includes(option))
|
||||
? value.join(", ")
|
||||
{treatedValue.length > 0 &&
|
||||
options.find((option) => treatedValue.includes(option))
|
||||
? treatedValue.join(", ")
|
||||
: "Choose an option..."}
|
||||
</span>
|
||||
<ForwardedIconComponent
|
||||
|
|
@ -177,7 +182,7 @@ export default function MultiselectComponent({
|
|||
name="Check"
|
||||
className={cn(
|
||||
"ml-auto h-4 w-4 shrink-0 text-primary",
|
||||
value.includes(option) ? "opacity-100" : "opacity-0",
|
||||
treatedValue.includes(option) ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
|
|
@ -189,11 +194,7 @@ export default function MultiselectComponent({
|
|||
);
|
||||
|
||||
if (Object.keys(options).length === 0 && !combobox) {
|
||||
return isLoading ? (
|
||||
<div>
|
||||
<span className="text-sm italic">Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
return (
|
||||
<div>
|
||||
<span className="text-sm italic">
|
||||
No parameters are available for display.
|
||||
|
|
@ -203,22 +204,14 @@ export default function MultiselectComponent({
|
|||
}
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={children ? () => {} : setOpen}>
|
||||
{children ? (
|
||||
<PopoverAnchor>{children}</PopoverAnchor>
|
||||
) : (
|
||||
renderDropdownTrigger()
|
||||
)}
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
{renderDropdownTrigger()}
|
||||
<PopoverContentDropdown
|
||||
onOpenAutoFocus={(event) => event.preventDefault()}
|
||||
side="bottom"
|
||||
avoidCollisions={!!children}
|
||||
avoidCollisions={false}
|
||||
className="noflow nowheel nopan nodelete nodrag p-0"
|
||||
style={
|
||||
children
|
||||
? {}
|
||||
: { minWidth: refButton?.current?.clientWidth ?? "200px" }
|
||||
}
|
||||
style={{ minWidth: refButton?.current?.clientWidth ?? "200px" }}
|
||||
>
|
||||
<Command>
|
||||
{renderSearchInput()}
|
||||
|
|
@ -1,24 +1,24 @@
|
|||
import PromptModal from "@/modals/promptModal";
|
||||
import { useEffect } from "react";
|
||||
import { PromptAreaComponentType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { InputProps, PromptAreaComponentType } from "../../types";
|
||||
|
||||
export default function PromptAreaComponent({
|
||||
field_name,
|
||||
setNodeClass,
|
||||
nodeClass,
|
||||
handleOnNewValue,
|
||||
handleNodeClass,
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
editNode = false,
|
||||
id = "",
|
||||
readonly = false,
|
||||
}: PromptAreaComponentType): JSX.Element {
|
||||
}: InputProps<string, PromptAreaComponentType>): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (disabled && value !== "") {
|
||||
onChange("", undefined, true);
|
||||
handleOnNewValue({ value: "" }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -59,9 +59,9 @@ export default function PromptAreaComponent({
|
|||
field_name={field_name}
|
||||
readonly={readonly}
|
||||
value={value}
|
||||
setValue={onChange}
|
||||
setValue={() => handleOnNewValue({ value: "" })}
|
||||
nodeClass={nodeClass}
|
||||
setNodeClass={setNodeClass}
|
||||
setNodeClass={handleNodeClass}
|
||||
>
|
||||
<Button unstyled className="w-full">
|
||||
<div className="flex w-full items-center gap-3">
|
||||
|
|
@ -2,6 +2,8 @@ import { RefreshButton } from "@/components/ui/refreshButton";
|
|||
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
|
||||
import { mutateTemplate } from "@/CustomNodes/helpers/mutate-template";
|
||||
import useAlertStore from "@/stores/alertStore";
|
||||
import { APIClassType, InputFieldType } from "@/types/api";
|
||||
import { InputProps } from "../../types";
|
||||
|
||||
export function RefreshParameterComponent({
|
||||
children,
|
||||
|
|
@ -12,6 +14,15 @@ export function RefreshParameterComponent({
|
|||
handleNodeClass,
|
||||
nodeId,
|
||||
name,
|
||||
}: {
|
||||
children: React.ReactElement<InputProps>;
|
||||
templateData: Partial<InputFieldType>;
|
||||
disabled: boolean;
|
||||
nodeClass: APIClassType;
|
||||
editNode: boolean;
|
||||
handleNodeClass: (value: any, code?: string, type?: string) => void;
|
||||
nodeId: string;
|
||||
name: string;
|
||||
}) {
|
||||
const postTemplateValue = usePostTemplateValue({
|
||||
parameterId: name,
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { InputProps, StrRenderComponentType } from "../../types";
|
||||
import DropdownComponent from "../dropdownComponent";
|
||||
import InputGlobalComponent from "../inputGlobalComponent";
|
||||
import TextAreaComponent from "../textAreaComponent";
|
||||
|
||||
export function StrRenderComponent({
|
||||
templateData,
|
||||
name,
|
||||
...baseInputProps
|
||||
}: InputProps<string, StrRenderComponentType>) {
|
||||
const { handleOnNewValue, id, disabled, editNode, value } = baseInputProps;
|
||||
|
||||
if (!templateData.options) {
|
||||
return templateData.multiline ? (
|
||||
<TextAreaComponent
|
||||
{...baseInputProps}
|
||||
password={templateData.password}
|
||||
updateVisibility={() => {
|
||||
if (templateData.password !== undefined) {
|
||||
handleOnNewValue(
|
||||
{ password: !templateData.password },
|
||||
{ skipSnapshot: true },
|
||||
);
|
||||
}
|
||||
}}
|
||||
id={`textarea_${id}`}
|
||||
/>
|
||||
) : (
|
||||
<InputGlobalComponent
|
||||
{...baseInputProps}
|
||||
password={templateData.password}
|
||||
load_from_db={templateData.load_from_db}
|
||||
id={"input-" + name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!!templateData.options) {
|
||||
return (
|
||||
<DropdownComponent
|
||||
{...baseInputProps}
|
||||
options={templateData.options}
|
||||
combobox={templateData.combobox}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +1,24 @@
|
|||
import ComponentTextModal from "@/modals/textAreaModal";
|
||||
import { classNames } from "@/utils/utils";
|
||||
import { useEffect } from "react";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import { Textarea } from "../ui/textarea";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { Textarea } from "../../../ui/textarea";
|
||||
import { InputProps, TextAreaComponentType } from "../../types";
|
||||
|
||||
export default function TextAreaComponent({
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
handleOnNewValue,
|
||||
editNode = false,
|
||||
id = "",
|
||||
password,
|
||||
updateVisibility,
|
||||
}: TextAreaComponentType): JSX.Element {
|
||||
}: InputProps<string, TextAreaComponentType>): JSX.Element {
|
||||
// Clear text area
|
||||
useEffect(() => {
|
||||
if (disabled && value !== "") {
|
||||
onChange("", undefined, true);
|
||||
handleOnNewValue({ value: "" }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ export default function TextAreaComponent({
|
|||
)}
|
||||
rows={1}
|
||||
placeholder="Type something..."
|
||||
onChange={(event) => onChange(event.target.value)}
|
||||
onChange={(event) => handleOnNewValue({ value: event.target.value })}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
@ -46,19 +46,21 @@ export default function TextAreaComponent({
|
|||
<ComponentTextModal
|
||||
changeVisibility={updateVisibility}
|
||||
value={value}
|
||||
setValue={(value) => onChange(value)}
|
||||
setValue={(value) => handleOnNewValue({ value: value })}
|
||||
disabled={disabled}
|
||||
password={password}
|
||||
>
|
||||
<div className={classNames("flex items-center")}>
|
||||
<Button unstyled>
|
||||
<Button unstyled disabled={disabled}>
|
||||
<IconComponent
|
||||
strokeWidth={1.5}
|
||||
id={id}
|
||||
name="ExternalLink"
|
||||
className={classNames(
|
||||
"icons-parameters-comp shrink-0",
|
||||
disabled ? "text-ring" : "hover:text-accent-foreground",
|
||||
disabled
|
||||
? "cursor-not-allowed text-ring"
|
||||
: "hover:text-accent-foreground",
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
import { ToggleComponentType } from "../../types/components";
|
||||
import { Switch } from "../ui/switch";
|
||||
import { Switch } from "../../../ui/switch";
|
||||
import { InputProps, ToggleComponentType } from "../../types";
|
||||
|
||||
export default function ToggleShadComponent({
|
||||
enabled,
|
||||
setEnabled,
|
||||
value,
|
||||
editNode,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
size,
|
||||
id = "",
|
||||
}: ToggleComponentType): JSX.Element {
|
||||
showToogle,
|
||||
id,
|
||||
}: InputProps<boolean, ToggleComponentType>): JSX.Element {
|
||||
let scaleX, scaleY;
|
||||
switch (size) {
|
||||
case "small":
|
||||
|
|
@ -23,8 +25,14 @@ export default function ToggleShadComponent({
|
|||
scaleY = 1;
|
||||
break;
|
||||
default:
|
||||
scaleX = 1;
|
||||
scaleY = 1;
|
||||
if (editNode) {
|
||||
scaleX = 0.6;
|
||||
scaleY = 0.6;
|
||||
} else {
|
||||
scaleX = 1;
|
||||
scaleY = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -36,9 +44,12 @@ export default function ToggleShadComponent({
|
|||
}}
|
||||
disabled={disabled}
|
||||
className=""
|
||||
checked={enabled}
|
||||
checked={value}
|
||||
onCheckedChange={(isEnabled: boolean) => {
|
||||
setEnabled(isEnabled);
|
||||
const data = showToogle
|
||||
? { advanced: !isEnabled }
|
||||
: { value: isEnabled };
|
||||
handleOnNewValue(data);
|
||||
}}
|
||||
></Switch>
|
||||
);
|
||||
|
|
@ -2,18 +2,22 @@ import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
|
|||
import { TEXT_FIELD_TYPES } from "@/constants/constants";
|
||||
import { APIClassType, InputFieldType } from "@/types/api";
|
||||
import { useMemo } from "react";
|
||||
import TableNodeComponent from "../TableNodeComponent";
|
||||
import CodeAreaComponent from "../codeAreaComponent";
|
||||
import DictComponent from "../dictComponent";
|
||||
import FloatComponent from "../floatComponent";
|
||||
import InputFileComponent from "../inputFileComponent";
|
||||
import IntComponent from "../intComponent";
|
||||
import KeypairListComponent from "../keypairListComponent";
|
||||
import LinkComponent from "../linkComponent";
|
||||
import PromptAreaComponent from "../promptComponent";
|
||||
import ToggleShadComponent from "../toggleShadComponent";
|
||||
import { RefreshParameterComponent } from "./component/refreshParameterComponent";
|
||||
import { StrRenderComponent } from "./component/strRenderComponent";
|
||||
import TableNodeComponent from "./components/TableNodeComponent";
|
||||
import CodeAreaComponent from "./components/codeAreaComponent";
|
||||
import DictComponent from "./components/dictComponent";
|
||||
import { EmptyParameterComponent } from "./components/emptyParameterComponent";
|
||||
import FloatComponent from "./components/floatComponent";
|
||||
import InputFileComponent from "./components/inputFileComponent";
|
||||
import InputListComponent from "./components/inputListComponent";
|
||||
import IntComponent from "./components/intComponent";
|
||||
import KeypairListComponent from "./components/keypairListComponent";
|
||||
import LinkComponent from "./components/linkComponent";
|
||||
import MultiselectComponent from "./components/multiselectComponent";
|
||||
import PromptAreaComponent from "./components/promptComponent";
|
||||
import { RefreshParameterComponent } from "./components/refreshParameterComponent";
|
||||
import { StrRenderComponent } from "./components/strRenderComponent";
|
||||
import ToggleShadComponent from "./components/toggleShadComponent";
|
||||
import { InputProps } from "./types";
|
||||
|
||||
export function ParameterRenderComponent({
|
||||
handleOnNewValue,
|
||||
|
|
@ -36,10 +40,6 @@ export function ParameterRenderComponent({
|
|||
nodeClass: APIClassType;
|
||||
disabled: boolean;
|
||||
}) {
|
||||
const onChange = (value: any) => {
|
||||
handleOnNewValue({ value });
|
||||
};
|
||||
|
||||
const id = (
|
||||
templateData.type +
|
||||
"_" +
|
||||
|
|
@ -47,6 +47,123 @@ export function ParameterRenderComponent({
|
|||
templateData.name
|
||||
).toLowerCase();
|
||||
|
||||
const renderComponent = (): React.ReactElement<InputProps> => {
|
||||
const baseInputProps: InputProps = {
|
||||
id,
|
||||
value: templateValue,
|
||||
editNode,
|
||||
handleOnNewValue,
|
||||
disabled,
|
||||
nodeClass,
|
||||
handleNodeClass,
|
||||
readonly: templateData.readonly,
|
||||
};
|
||||
if (TEXT_FIELD_TYPES.includes(templateData.type ?? "")) {
|
||||
if (templateData.list) {
|
||||
if (!templateData.options) {
|
||||
return (
|
||||
<InputListComponent
|
||||
{...baseInputProps}
|
||||
componentName={name}
|
||||
id={`inputlist_${id}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (!!templateData.options) {
|
||||
return (
|
||||
<MultiselectComponent
|
||||
{...baseInputProps}
|
||||
combobox={templateData.combobox}
|
||||
options={
|
||||
(Array.isArray(templateData.options)
|
||||
? templateData.options
|
||||
: [templateData.options]) || []
|
||||
}
|
||||
id={`multiselect_${id}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<StrRenderComponent
|
||||
{...baseInputProps}
|
||||
templateData={templateData}
|
||||
name={name}
|
||||
editNode={editNode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
switch (templateData.type) {
|
||||
case "NestedDict":
|
||||
return <DictComponent {...baseInputProps} id={`dict_${id}`} />;
|
||||
case "dict":
|
||||
return (
|
||||
<KeypairListComponent
|
||||
{...baseInputProps}
|
||||
isList={templateData.list ?? false}
|
||||
id={`keypair_${id}`}
|
||||
/>
|
||||
);
|
||||
case "bool":
|
||||
return <ToggleShadComponent {...baseInputProps} id={`toggle_${id}`} />;
|
||||
case "link":
|
||||
return (
|
||||
<LinkComponent
|
||||
{...baseInputProps}
|
||||
icon={templateData.icon}
|
||||
text={templateData.text}
|
||||
id={`link_${id}`}
|
||||
/>
|
||||
);
|
||||
case "float":
|
||||
return (
|
||||
<FloatComponent
|
||||
{...baseInputProps}
|
||||
id={`float_${id}`}
|
||||
rangeSpec={templateData.range_spec}
|
||||
/>
|
||||
);
|
||||
case "int":
|
||||
return (
|
||||
<IntComponent
|
||||
{...baseInputProps}
|
||||
rangeSpec={templateData.range_spec}
|
||||
id={`int_${id}`}
|
||||
/>
|
||||
);
|
||||
case "file":
|
||||
return (
|
||||
<InputFileComponent
|
||||
{...baseInputProps}
|
||||
fileTypes={templateData.fileTypes}
|
||||
id={`inputfile_${id}`}
|
||||
/>
|
||||
);
|
||||
case "prompt":
|
||||
return (
|
||||
<PromptAreaComponent
|
||||
{...baseInputProps}
|
||||
readonly={!!nodeClass.flow}
|
||||
field_name={name}
|
||||
id={`promptarea_${id}`}
|
||||
/>
|
||||
);
|
||||
case "code":
|
||||
return <CodeAreaComponent {...baseInputProps} id={`codearea_${id}`} />;
|
||||
case "table":
|
||||
return (
|
||||
<TableNodeComponent
|
||||
{...baseInputProps}
|
||||
description={templateData.info || "Add or edit data"}
|
||||
columns={templateData?.table_schema?.columns}
|
||||
tableTitle={templateData?.display_name ?? "Table"}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return <EmptyParameterComponent {...baseInputProps} />;
|
||||
}
|
||||
};
|
||||
|
||||
return useMemo(
|
||||
() => (
|
||||
<RefreshParameterComponent
|
||||
|
|
@ -58,113 +175,7 @@ export function ParameterRenderComponent({
|
|||
handleNodeClass={handleNodeClass}
|
||||
name={name}
|
||||
>
|
||||
{TEXT_FIELD_TYPES.includes(templateData.type ?? "") ? (
|
||||
<StrRenderComponent
|
||||
templateData={templateData}
|
||||
value={templateValue}
|
||||
name={name}
|
||||
disabled={disabled}
|
||||
handleOnNewValue={handleOnNewValue}
|
||||
id={id}
|
||||
editNode={editNode}
|
||||
/>
|
||||
) : templateData.type === "NestedDict" ? (
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
value={
|
||||
(templateValue || "").toString() === "{}" ? {} : templateValue
|
||||
}
|
||||
onChange={onChange}
|
||||
id={`dict_${id}`}
|
||||
/>
|
||||
) : templateData.type === "dict" ? (
|
||||
<KeypairListComponent
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
value={templateValue}
|
||||
onChange={onChange}
|
||||
isList={templateData.list ?? false}
|
||||
id={`keypair_${id}`}
|
||||
/>
|
||||
) : templateData.type === "bool" ? (
|
||||
<ToggleShadComponent
|
||||
id={`toggle_${id}`}
|
||||
disabled={disabled}
|
||||
enabled={templateValue}
|
||||
setEnabled={onChange}
|
||||
size={editNode ? "small" : "large"}
|
||||
/>
|
||||
) : templateData.type === "link" ? (
|
||||
<LinkComponent
|
||||
value={templateData}
|
||||
onChange={onChange}
|
||||
id={`link_${id}`}
|
||||
/>
|
||||
) : templateData.type === "float" ? (
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
rangeSpec={templateData.range_spec}
|
||||
value={templateValue ?? ""}
|
||||
onChange={onChange}
|
||||
id={`float_${id}`}
|
||||
/>
|
||||
) : templateData.type === "int" ? (
|
||||
<IntComponent
|
||||
rangeSpec={templateData.range_spec}
|
||||
id={`int_${id}`}
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
value={templateValue ?? 0}
|
||||
onChange={onChange}
|
||||
/>
|
||||
) : templateData.type === "file" ? (
|
||||
<InputFileComponent
|
||||
editNode={editNode}
|
||||
disabled={disabled}
|
||||
value={templateValue ?? ""}
|
||||
handleOnNewValue={handleOnNewValue}
|
||||
fileTypes={templateData.fileTypes}
|
||||
id={`inputfile_${id}`}
|
||||
/>
|
||||
) : templateData.type === "prompt" ? (
|
||||
<PromptAreaComponent
|
||||
readonly={nodeClass.flow ? true : false}
|
||||
field_name={name}
|
||||
editNode={editNode}
|
||||
disabled={disabled}
|
||||
nodeClass={nodeClass}
|
||||
setNodeClass={handleNodeClass}
|
||||
value={templateValue ?? ""}
|
||||
onChange={onChange}
|
||||
id={`promptarea_${id}`}
|
||||
/>
|
||||
) : templateData.type === "code" ? (
|
||||
<CodeAreaComponent
|
||||
readonly={nodeClass.flow && templateData.dynamic ? true : false}
|
||||
dynamic={templateData.dynamic ?? false}
|
||||
setNodeClass={handleNodeClass}
|
||||
nodeClass={nodeClass}
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
value={templateValue ?? ""}
|
||||
onChange={onChange}
|
||||
id={`codearea_${id}`}
|
||||
/>
|
||||
) : templateData.type === "Any" ? (
|
||||
<>-</>
|
||||
) : templateData.type === "table" ? (
|
||||
<TableNodeComponent
|
||||
description={templateData.info || "Add or edit data"}
|
||||
columns={templateData?.table_schema?.columns}
|
||||
onChange={onChange}
|
||||
tableTitle={templateData?.display_name ?? "Table"}
|
||||
value={templateValue}
|
||||
/>
|
||||
) : (
|
||||
String(templateValue)
|
||||
)}
|
||||
{renderComponent()}
|
||||
</RefreshParameterComponent>
|
||||
),
|
||||
[templateData, disabled, nodeId, editNode, nodeClass, name, templateValue],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
|
||||
import { APIClassType, InputFieldType } from "@/types/api";
|
||||
import { RangeSpecType } from "@/types/components";
|
||||
import { ColumnField } from "@/types/utils/functions";
|
||||
|
||||
// Base type for RefreshParameterComponent children
|
||||
export type BaseInputProps<valueType = any> = {
|
||||
id: string;
|
||||
value: valueType;
|
||||
editNode: boolean;
|
||||
handleOnNewValue: handleOnNewValueType;
|
||||
disabled: boolean;
|
||||
nodeClass?: APIClassType;
|
||||
handleNodeClass?: (value: any, code?: string, type?: string) => void;
|
||||
readonly?: boolean;
|
||||
};
|
||||
|
||||
// Generic type for composing input props
|
||||
export type InputProps<valueType = any, T = {}> = BaseInputProps<valueType> & T;
|
||||
|
||||
export type TableComponentType = {
|
||||
description: string;
|
||||
tableTitle: string;
|
||||
columns?: ColumnField[];
|
||||
};
|
||||
|
||||
export type FloatComponentType = {
|
||||
rangeSpec: RangeSpecType;
|
||||
};
|
||||
|
||||
export type IntComponentType = {
|
||||
rangeSpec: RangeSpecType;
|
||||
};
|
||||
export type ToggleComponentType = {
|
||||
size?: "small" | "medium" | "large";
|
||||
showToogle?: boolean;
|
||||
};
|
||||
|
||||
export type FileComponentType = {
|
||||
fileTypes: Array<string>;
|
||||
};
|
||||
|
||||
export type PromptAreaComponentType = {
|
||||
field_name?: string;
|
||||
};
|
||||
|
||||
export type LinkComponentType = {
|
||||
icon?: string;
|
||||
text?: string;
|
||||
};
|
||||
|
||||
export type KeyPairListComponentType = {
|
||||
value: any;
|
||||
isList?: boolean;
|
||||
};
|
||||
|
||||
export type StrRenderComponentType = {
|
||||
templateData: Partial<InputFieldType>;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type InputListComponentType = {
|
||||
componentName?: string;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type DropDownComponentType = {
|
||||
combobox?: boolean;
|
||||
options: string[];
|
||||
};
|
||||
|
||||
export type TextAreaComponentType = {
|
||||
password?: boolean;
|
||||
updateVisibility?: () => void;
|
||||
};
|
||||
|
||||
export type InputGlobalComponentType = {
|
||||
load_from_db: boolean | undefined;
|
||||
password: boolean | undefined;
|
||||
};
|
||||
export type MultiselectComponentType = {
|
||||
options: string[];
|
||||
combobox?: boolean;
|
||||
};
|
||||
|
|
@ -3,7 +3,7 @@ import ShadTooltip from "@/components/shadTooltipComponent";
|
|||
import useFlowStore from "@/stores/flowStore";
|
||||
import { isTargetHandleConnected } from "@/utils/reactflowUtils";
|
||||
import { CustomCellRendererProps } from "ag-grid-react";
|
||||
import ToggleShadComponent from "../../../toggleShadComponent";
|
||||
import ToggleShadComponent from "../../../parameterRenderComponent/components/toggleShadComponent";
|
||||
|
||||
export default function TableAdvancedToggleCellRender({
|
||||
value: { nodeId, parameterId },
|
||||
|
|
@ -38,14 +38,13 @@ export default function TableAdvancedToggleCellRender({
|
|||
<div>
|
||||
<div className="flex h-full items-center">
|
||||
<ToggleShadComponent
|
||||
id={"show" + parameterId}
|
||||
disabled={disabled}
|
||||
enabled={!parameter.advanced}
|
||||
setEnabled={(e) => {
|
||||
handleOnNewValue({ advanced: !e });
|
||||
}}
|
||||
size="small"
|
||||
value={!parameter.advanced}
|
||||
handleOnNewValue={handleOnNewValue}
|
||||
editNode={true}
|
||||
showToogle
|
||||
size="small"
|
||||
id={"show" + parameterId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import { ElementRef, forwardRef, useRef, useState } from "react";
|
|||
import {
|
||||
DEFAULT_TABLE_ALERT_MSG,
|
||||
DEFAULT_TABLE_ALERT_TITLE,
|
||||
NO_COLUMN_DEFINITION_ALERT_DESCRIPTION,
|
||||
NO_COLUMN_DEFINITION_ALERT_TITLE,
|
||||
} from "../../constants/constants";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
import "../../style/ag-theme-shadcn.css"; // Custom CSS applied to the grid
|
||||
|
|
@ -149,6 +151,25 @@ const TableComponent = forwardRef<
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (colDef.length === 0) {
|
||||
{
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-md border">
|
||||
<Alert variant={"default"} className="w-fit">
|
||||
<ForwardedIconComponent
|
||||
name="AlertCircle"
|
||||
className="h-5 w-5 text-primary"
|
||||
/>
|
||||
<AlertTitle>{NO_COLUMN_DEFINITION_ALERT_TITLE}</AlertTitle>
|
||||
<AlertDescription>
|
||||
{NO_COLUMN_DEFINITION_ALERT_DESCRIPTION}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -855,6 +855,11 @@ export const DEFAULT_TABLE_ALERT_MSG = `Oops! It seems there's no data to displa
|
|||
|
||||
export const DEFAULT_TABLE_ALERT_TITLE = "No Data Available";
|
||||
|
||||
export const NO_COLUMN_DEFINITION_ALERT_TITLE = "No Column Definitions";
|
||||
|
||||
export const NO_COLUMN_DEFINITION_ALERT_DESCRIPTION =
|
||||
"There are no column definitions available for this table.";
|
||||
|
||||
export const LOCATIONS_TO_RETURN = ["/flow/", "/settings/"];
|
||||
|
||||
export const MAX_BATCH_SIZE = 50;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { IOJSONInputComponentType } from "@/types/components";
|
||||
import { useEffect, useRef } from "react";
|
||||
import JsonView from "react18-json-view";
|
||||
import { useDarkStore } from "../../../../../../stores/darkStore";
|
||||
import { DictComponentType } from "../../../../../../types/components";
|
||||
|
||||
export default function IoJsonInput({
|
||||
value = [],
|
||||
onChange,
|
||||
left,
|
||||
output,
|
||||
}: DictComponentType): JSX.Element {
|
||||
}: IOJSONInputComponentType): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (value) onChange(value);
|
||||
}, [value]);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import useHandleNewValue from "@/CustomNodes/hooks/use-handle-new-value";
|
||||
import { NodeType } from "@/types/flow";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { useState } from "react";
|
||||
import ImageViewer from "../../../../components/ImageViewer";
|
||||
import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
||||
import DataOutputComponent from "../../../../components/dataOutputComponent";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import InputListComponent from "../../../../components/parameterRenderComponent/components/inputListComponent";
|
||||
import PdfViewer from "../../../../components/pdfViewer";
|
||||
import { Textarea } from "../../../../components/ui/textarea";
|
||||
import { PDFViewConstant } from "../../../../constants/constants";
|
||||
|
|
@ -33,14 +35,14 @@ export default function IOFieldView({
|
|||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
const flowPool = useFlowStore((state) => state.flowPool);
|
||||
const node = nodes.find((node) => node.id === fieldId);
|
||||
const node: NodeType | undefined = nodes.find((node) => node.id === fieldId);
|
||||
const flowPoolNode = (flowPool[node!.id] ?? [])[
|
||||
(flowPool[node!.id]?.length ?? 1) - 1
|
||||
];
|
||||
const handleChangeSelect = (e) => {
|
||||
if (node) {
|
||||
let newNode = cloneDeep(node);
|
||||
if (newNode.data.node.template.separator) {
|
||||
if (newNode.data.node?.template.separator) {
|
||||
newNode.data.node.template.separator.value = e;
|
||||
setNode(newNode.id, newNode);
|
||||
}
|
||||
|
|
@ -53,6 +55,14 @@ export default function IOFieldView({
|
|||
(flowPool[node!.id] ?? [])[(flowPool[node!.id]?.length ?? 1) - 1]?.data
|
||||
.results.text ?? "";
|
||||
|
||||
const { handleOnNewValue } = node?.data.node
|
||||
? useHandleNewValue({
|
||||
node: node.data.node,
|
||||
nodeId: node.id,
|
||||
name: "input_value",
|
||||
})
|
||||
: { handleOnNewValue: (value: any, options?: any) => {} };
|
||||
|
||||
function handleOutputType() {
|
||||
if (!node) return <>"No node found!"</>;
|
||||
switch (type) {
|
||||
|
|
@ -129,14 +139,10 @@ export default function IOFieldView({
|
|||
return (
|
||||
<>
|
||||
<InputListComponent
|
||||
id={`playground_${node.id}_input_list`}
|
||||
editNode={false}
|
||||
value={node.data.node!.template["input_value"]?.value}
|
||||
onChange={(e) => {
|
||||
if (node) {
|
||||
let newNode = cloneDeep(node);
|
||||
newNode.data.node!.template["input_value"].value = e;
|
||||
setNode(node.id, newNode);
|
||||
}
|
||||
}}
|
||||
handleOnNewValue={handleOnNewValue}
|
||||
disabled={false}
|
||||
/>
|
||||
</>
|
||||
|
|
@ -236,16 +242,11 @@ export default function IOFieldView({
|
|||
return (
|
||||
<>
|
||||
<InputListComponent
|
||||
id={`playground_${node.id}_output_list`}
|
||||
editNode={false}
|
||||
value={node.data.node!.template["input_value"]?.value}
|
||||
onChange={(e) => {
|
||||
if (node) {
|
||||
let newNode = cloneDeep(node);
|
||||
newNode.data.node!.template["input_value"].value = e;
|
||||
setNode(node.id, newNode);
|
||||
}
|
||||
}}
|
||||
playgroundDisabled
|
||||
disabled={false}
|
||||
handleOnNewValue={handleOnNewValue}
|
||||
disabled={true}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,36 +10,42 @@ import BaseModal from "../baseModal";
|
|||
interface TableModalProps extends TableComponentProps {
|
||||
tableTitle: string;
|
||||
description: string;
|
||||
disabled?: boolean;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const TableModal = forwardRef<
|
||||
ElementRef<typeof TableComponent>,
|
||||
TableModalProps
|
||||
>(({ tableTitle, description, children, ...props }: TableModalProps, ref) => {
|
||||
return (
|
||||
<BaseModal>
|
||||
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header description={description}>
|
||||
<span className="pr-2">{tableTitle}</span>
|
||||
<ForwardedIconComponent name="Table" className="mr-2 h-4 w-4" />
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
<TableComponent
|
||||
className="h-full w-full"
|
||||
ref={ref}
|
||||
{...props}
|
||||
></TableComponent>
|
||||
</BaseModal.Content>
|
||||
<BaseModal.Footer>
|
||||
<DialogClose>
|
||||
<div className="flex w-full justify-end gap-2 pt-2">
|
||||
<Button>Close</Button>
|
||||
</div>
|
||||
</DialogClose>
|
||||
</BaseModal.Footer>
|
||||
</BaseModal>
|
||||
);
|
||||
});
|
||||
>(
|
||||
(
|
||||
{ tableTitle, description, children, disabled, ...props }: TableModalProps,
|
||||
ref,
|
||||
) => {
|
||||
return (
|
||||
<BaseModal disable={disabled}>
|
||||
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header description={description}>
|
||||
<span className="pr-2">{tableTitle}</span>
|
||||
<ForwardedIconComponent name="Table" className="mr-2 h-4 w-4" />
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
<TableComponent
|
||||
className="h-full w-full"
|
||||
ref={ref}
|
||||
{...props}
|
||||
></TableComponent>
|
||||
</BaseModal.Content>
|
||||
<BaseModal.Footer>
|
||||
<DialogClose>
|
||||
<div className="flex w-full justify-end gap-2 pt-2">
|
||||
<Button>Close</Button>
|
||||
</div>
|
||||
</DialogClose>
|
||||
</BaseModal.Footer>
|
||||
</BaseModal>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export default TableModal;
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value";
|
|||
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
|
||||
import { usePostRetrieveVertexOrder } from "@/controllers/API/queries/vertex";
|
||||
import useAddFlow from "@/hooks/flows/use-add-flow";
|
||||
import CodeAreaModal from "@/modals/codeAreaModal";
|
||||
import { APIClassType } from "@/types/api";
|
||||
import _, { cloneDeep } from "lodash";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useUpdateNodeInternals } from "reactflow";
|
||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import IconComponent from "../../../../components/genericIconComponent";
|
||||
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||
import {
|
||||
|
|
@ -638,22 +638,17 @@ export default function NodeToolbarComponent({
|
|||
{hasCode && (
|
||||
<div className="hidden">
|
||||
{openModal && (
|
||||
<CodeAreaComponent
|
||||
<CodeAreaModal
|
||||
setValue={handleOnNewValue}
|
||||
open={openModal}
|
||||
setOpen={setOpenModal}
|
||||
readonly={
|
||||
data.node?.flow && data.node.template[name].dynamic
|
||||
? true
|
||||
: false
|
||||
}
|
||||
dynamic={data.node?.template[name].dynamic ?? false}
|
||||
dynamic={true}
|
||||
setNodeClass={handleNodeClass}
|
||||
nodeClass={data.node}
|
||||
disabled={false}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"code-input-node-toolbar-" + name}
|
||||
/>
|
||||
>
|
||||
<></>
|
||||
</CodeAreaModal>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -42,15 +42,7 @@ export type InputComponentType = {
|
|||
isObjectOption?: boolean;
|
||||
onChangeFolderName?: (e: any) => void;
|
||||
};
|
||||
export type ToggleComponentType = {
|
||||
enabled: boolean;
|
||||
setEnabled: (state: boolean) => void;
|
||||
disabled?: boolean | undefined;
|
||||
size: "small" | "medium" | "large";
|
||||
id?: string;
|
||||
editNode?: boolean;
|
||||
};
|
||||
export type DropDownComponentType = {
|
||||
export type DropDownComponent = {
|
||||
disabled?: boolean;
|
||||
isLoading?: boolean;
|
||||
value: string;
|
||||
|
|
@ -61,17 +53,6 @@ export type DropDownComponentType = {
|
|||
id?: string;
|
||||
children?: ReactNode;
|
||||
};
|
||||
export type MultiselectComponentType = {
|
||||
disabled?: boolean;
|
||||
isLoading?: boolean;
|
||||
value: string[];
|
||||
combobox?: boolean;
|
||||
options: string[];
|
||||
onSelect: (value: string[], dbValue?: boolean, snapshot?: boolean) => void;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
children?: ReactNode;
|
||||
};
|
||||
export type ParameterComponentType = {
|
||||
selected?: boolean;
|
||||
data: NodeDataType;
|
||||
|
|
@ -124,73 +105,12 @@ export type NodeInputFieldComponentType = {
|
|||
showNode: boolean;
|
||||
};
|
||||
|
||||
export type InputListComponentType = {
|
||||
value: string[];
|
||||
onChange: (value: string[], dbValue?: boolean, snapshot?: boolean) => void;
|
||||
disabled: boolean;
|
||||
editNode?: boolean;
|
||||
componentName?: string;
|
||||
playgroundDisabled?: boolean;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type InputGlobalComponentType = {
|
||||
disabled: boolean;
|
||||
onChange: (value: string, dbValue: boolean, snapshot?: boolean) => void;
|
||||
name: string;
|
||||
data: Partial<InputFieldType>;
|
||||
editNode?: boolean;
|
||||
playgroundDisabled?: boolean;
|
||||
};
|
||||
|
||||
export type KeyPairListComponentType = {
|
||||
value: any;
|
||||
onChange: (value: Object[]) => void;
|
||||
disabled: boolean;
|
||||
editNode?: boolean;
|
||||
editNodeModal?: boolean;
|
||||
isList?: boolean;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type DictComponentType = {
|
||||
export type IOJSONInputComponentType = {
|
||||
value: any;
|
||||
onChange: (value) => void;
|
||||
disabled?: boolean;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
left?: boolean;
|
||||
output?: boolean;
|
||||
};
|
||||
|
||||
export type TextAreaComponentType = {
|
||||
field_name?: string;
|
||||
nodeClass?: APIClassType;
|
||||
setNodeClass?: (value: APIClassType) => void;
|
||||
disabled: boolean;
|
||||
onChange: (
|
||||
value: string[] | string,
|
||||
dbValue?: boolean,
|
||||
skipSnapshot?: boolean,
|
||||
) => void;
|
||||
value: string;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
readonly?: boolean;
|
||||
password?: boolean;
|
||||
updateVisibility?: () => void;
|
||||
};
|
||||
|
||||
export type TableComponentType = {
|
||||
description: string;
|
||||
tableTitle: string;
|
||||
onChange: (value: any[]) => void;
|
||||
value: any[];
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
columns?: ColumnField[];
|
||||
};
|
||||
|
||||
export type outputComponentType = {
|
||||
types: string[];
|
||||
selected: string;
|
||||
|
|
@ -201,51 +121,6 @@ export type outputComponentType = {
|
|||
proxy?: OutputFieldProxyType;
|
||||
};
|
||||
|
||||
export type PromptAreaComponentType = {
|
||||
field_name?: string;
|
||||
nodeClass?: APIClassType;
|
||||
setNodeClass?: (value: APIClassType) => void;
|
||||
disabled: boolean;
|
||||
onChange: (
|
||||
value: string[] | string,
|
||||
dbValue?: boolean,
|
||||
skipSnapshot?: boolean,
|
||||
) => void;
|
||||
value: string;
|
||||
readonly?: boolean;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type CodeAreaComponentType = {
|
||||
setOpenModal?: (bool: boolean) => void;
|
||||
disabled: boolean;
|
||||
onChange: (
|
||||
value: string[] | string,
|
||||
dbValue?: boolean,
|
||||
skipSnapshot?: boolean,
|
||||
) => void;
|
||||
value: string;
|
||||
editNode?: boolean;
|
||||
nodeClass?: APIClassType;
|
||||
setNodeClass?: (value: APIClassType, type: string) => void;
|
||||
dynamic?: boolean;
|
||||
id?: string;
|
||||
readonly?: boolean;
|
||||
open?: boolean;
|
||||
setOpen?: (open: boolean) => void;
|
||||
};
|
||||
|
||||
export type FileComponentType = {
|
||||
IOInputProps?;
|
||||
disabled: boolean;
|
||||
handleOnNewValue: handleOnNewValueType;
|
||||
value: string;
|
||||
fileTypes: Array<string>;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type DisclosureComponentType = {
|
||||
children: ReactNode;
|
||||
defaultOpen: boolean;
|
||||
|
|
@ -278,15 +153,6 @@ export type IntComponentType = {
|
|||
id?: string;
|
||||
};
|
||||
|
||||
export type FloatComponentType = {
|
||||
value: string;
|
||||
disabled?: boolean;
|
||||
onChange: (value: string, dbValue?: boolean, skipSnapshot?: boolean) => void;
|
||||
rangeSpec: RangeSpecType;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type FilePreviewType = {
|
||||
loading: boolean;
|
||||
file: File;
|
||||
|
|
@ -881,11 +747,3 @@ export type handleSelectPropsType = {
|
|||
setLockChat: (lock: boolean) => void;
|
||||
setChatHistory: (chatHistory: ChatMessageType) => void;
|
||||
};
|
||||
|
||||
export type LinkComponentType = {
|
||||
value: Partial<InputFieldType>;
|
||||
onChange: (value: string) => void;
|
||||
disabled?: boolean;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import uaParser from "ua-parser-js";
|
||||
|
||||
test("user must be able to interact with table input component", async ({
|
||||
page,
|
||||
|
|
@ -26,6 +27,14 @@ test("user must be able to interact with table input component", async ({
|
|||
const secondRandomText = Math.random().toString(36).substring(7);
|
||||
const thirdRandomText = Math.random().toString(36).substring(7);
|
||||
|
||||
const getUA = await page.evaluate(() => navigator.userAgent);
|
||||
const userAgentInfo = uaParser(getUA);
|
||||
let control = "Control";
|
||||
|
||||
if (userAgentInfo.os.name.includes("Mac")) {
|
||||
control = "Meta";
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.getByText("New Project", { exact: true }).click();
|
||||
await page.waitForTimeout(3000);
|
||||
|
|
@ -99,7 +108,7 @@ class CustomComponent(Component):
|
|||
return data
|
||||
`;
|
||||
|
||||
await page.locator("textarea").press("Control+a");
|
||||
await page.locator("textarea").press(`${control}+a`);
|
||||
await page.locator("textarea").fill(customCodeWithError);
|
||||
|
||||
await page.getByText("Check & Save").last().click();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue