code format

This commit is contained in:
anovazzi1 2023-09-18 20:37:01 -03:00
commit fda2047fec
24 changed files with 204 additions and 119 deletions

View file

@ -33,7 +33,7 @@ import {
nodeIconsLucide, nodeIconsLucide,
nodeNames, nodeNames,
} from "../../../../utils/styleUtils"; } from "../../../../utils/styleUtils";
import { classNames, extractIdFromLongId, groupByFamily } from "../../../../utils/utils"; import { classNames, groupByFamily } from "../../../../utils/utils";
export default function ParameterComponent({ export default function ParameterComponent({
left, left,
@ -48,7 +48,7 @@ export default function ParameterComponent({
required = false, required = false,
optionalHandle = null, optionalHandle = null,
info = "", info = "",
proxy proxy,
}: ParameterComponentType): JSX.Element { }: ParameterComponentType): JSX.Element {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const refHtml = useRef<HTMLDivElement & ReactNode>(null); const refHtml = useRef<HTMLDivElement & ReactNode>(null);
@ -185,10 +185,13 @@ export default function ParameterComponent({
(info !== "" ? " flex items-center" : "") (info !== "" ? " flex items-center" : "")
} }
> >
{proxy ? (<ShadTooltip content={<span>{proxy.id}</span>}> {proxy ? (
<ShadTooltip content={<span>{proxy.id}</span>}>
<span>{title}</span> <span>{title}</span>
</ShadTooltip>):title} </ShadTooltip>
) : (
title
)}
<span className="text-status-red">{required ? " *" : ""}</span> <span className="text-status-red">{required ? " *" : ""}</span>
<div className=""> <div className="">
{info !== "" && ( {info !== "" && (
@ -302,7 +305,11 @@ export default function ParameterComponent({
) : left === true && type === "code" ? ( ) : left === true && type === "code" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<CodeAreaComponent <CodeAreaComponent
readonly={data.node?.flow && data.node.template[name].dynamic?true:false} readonly={
data.node?.flow && data.node.template[name].dynamic
? true
: false
}
dynamic={data.node?.template[name].dynamic ?? false} dynamic={data.node?.template[name].dynamic ?? false}
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
data.node = nodeClass; data.node = nodeClass;
@ -338,7 +345,11 @@ export default function ParameterComponent({
) : left === true && type === "prompt" ? ( ) : left === true && type === "prompt" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<PromptAreaComponent <PromptAreaComponent
readonly={data.node?.flow && data.node.template[name].dynamic?true:false} readonly={
data.node?.flow && data.node.template[name].dynamic
? true
: false
}
field_name={name} field_name={name}
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
data.node = nodeClass; data.node = nodeClass;

View file

@ -1,21 +1,26 @@
import { cloneDeep, get } from "lodash"; import { cloneDeep } from "lodash";
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { NodeToolbar, XYPosition, useUpdateNodeInternals } from "reactflow"; import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
import ShadTooltip from "../../components/ShadTooltipComponent"; import ShadTooltip from "../../components/ShadTooltipComponent";
import Tooltip from "../../components/TooltipComponent"; import Tooltip from "../../components/TooltipComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import InputComponent from "../../components/inputComponent";
import { Textarea } from "../../components/ui/textarea";
import { useSSE } from "../../contexts/SSEContext"; import { useSSE } from "../../contexts/SSEContext";
import { TabsContext } from "../../contexts/tabsContext"; import { TabsContext } from "../../contexts/tabsContext";
import { typesContext } from "../../contexts/typesContext"; import { typesContext } from "../../contexts/typesContext";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import { validationStatusType } from "../../types/components"; import { validationStatusType } from "../../types/components";
import { NodeDataType } from "../../types/flow"; import { NodeDataType } from "../../types/flow";
import { cleanEdges, getGroupStatus, handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils"; import {
cleanEdges,
getGroupStatus,
handleKeyDown,
scapedJSONStringfy,
} from "../../utils/reactflowUtils";
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
import { classNames, toTitleCase } from "../../utils/utils"; import { classNames, toTitleCase } from "../../utils/utils";
import ParameterComponent from "./components/parameterComponent"; import ParameterComponent from "./components/parameterComponent";
import InputComponent from "../../components/inputComponent";
import { Textarea } from "../../components/ui/textarea";
export default function GenericNode({ export default function GenericNode({
data: olddata, data: olddata,
@ -66,7 +71,9 @@ export default function GenericNode({
// New useEffect to watch for changes in sseData and update validation status // New useEffect to watch for changes in sseData and update validation status
useEffect(() => { useEffect(() => {
const relevantData = data.node?.flow ? getGroupStatus(data.node.flow, sseData) : sseData[data.id]; const relevantData = data.node?.flow
? getGroupStatus(data.node.flow, sseData)
: sseData[data.id];
if (relevantData) { if (relevantData) {
// Extract validation information from relevantData and update the validationStatus state // Extract validation information from relevantData and update the validationStatus state
setValidationStatus(relevantData); setValidationStatus(relevantData);
@ -105,8 +112,8 @@ export default function GenericNode({
iconColor={`${nodeColors[types[data.type]]}`} iconColor={`${nodeColors[types[data.type]]}`}
/> />
<div className="generic-node-tooltip-div"> <div className="generic-node-tooltip-div">
{data.node?.flow && inputName ? {data.node?.flow && inputName ? (
<div > <div>
<InputComponent <InputComponent
autoFocus autoFocus
onBlur={() => { onBlur={() => {
@ -123,13 +130,17 @@ export default function GenericNode({
password={false} password={false}
blurOnEnter={true} blurOnEnter={true}
/> />
</div> : <ShadTooltip content={data.node?.display_name}> </div>
<div className="generic-node-tooltip-div text-primary" onDoubleClick={() => setInputName(true)}> ) : (
<ShadTooltip content={data.node?.display_name}>
<div
className="generic-node-tooltip-div text-primary"
onDoubleClick={() => setInputName(true)}
>
{data.node?.display_name} {data.node?.display_name}
</div> </div>
</ShadTooltip> </ShadTooltip>
} )}
</div> </div>
</div> </div>
<div className="round-button-div"> <div className="round-button-div">
@ -151,10 +162,10 @@ export default function GenericNode({
<div className="max-h-96 overflow-auto"> <div className="max-h-96 overflow-auto">
{typeof validationStatus.params === "string" {typeof validationStatus.params === "string"
? validationStatus.params ? validationStatus.params
.split("\n") .split("\n")
.map((line: string, index: number) => ( .map((line: string, index: number) => (
<div key={index}>{line}</div> <div key={index}>{line}</div>
)) ))
: ""} : ""}
</div> </div>
) )
@ -192,7 +203,7 @@ export default function GenericNode({
</div> </div>
<div className="generic-node-desc"> <div className="generic-node-desc">
{data.node?.flow && inputDescription ? {data.node?.flow && inputDescription ? (
<Textarea <Textarea
autoFocus autoFocus
onBlur={() => { onBlur={() => {
@ -205,10 +216,15 @@ export default function GenericNode({
} }
}} }}
value={nodeDescription} value={nodeDescription}
onChange={(e)=>setNodeDescription(e.target.value)} onChange={(e) => setNodeDescription(e.target.value)}
onKeyDown={(e) => { onKeyDown={(e) => {
handleKeyDown(e, nodeDescription, ""); handleKeyDown(e, nodeDescription, "");
if(e.key === "Enter" && e.shiftKey === false && e.ctrlKey === false && e.altKey === false){ if (
e.key === "Enter" &&
e.shiftKey === false &&
e.ctrlKey === false &&
e.altKey === false
) {
setInputDescription(false); setInputDescription(false);
if (nodeDescription.trim() !== "") { if (nodeDescription.trim() !== "") {
setNodeDescription(nodeDescription); setNodeDescription(nodeDescription);
@ -218,9 +234,15 @@ export default function GenericNode({
} }
} }
}} }}
/> : />
<div className="generic-node-desc-text" onDoubleClick={() => setInputDescription(true)}>{data.node?.description}</div> ) : (
} <div
className="generic-node-desc-text"
onDoubleClick={() => setInputDescription(true)}
>
{data.node?.description}
</div>
)}
<> <>
{Object.keys(data.node!.template) {Object.keys(data.node!.template)
@ -228,7 +250,7 @@ export default function GenericNode({
.map((templateField: string, idx) => ( .map((templateField: string, idx) => (
<div key={idx}> <div key={idx}>
{data.node!.template[templateField].show && {data.node!.template[templateField].show &&
!data.node!.template[templateField].advanced ? ( !data.node!.template[templateField].advanced ? (
<ParameterComponent <ParameterComponent
key={scapedJSONStringfy({ key={scapedJSONStringfy({
inputTypes: inputTypes:
@ -242,7 +264,7 @@ export default function GenericNode({
setData={setData} setData={setData}
color={ color={
nodeColors[ nodeColors[
types[data.node?.template[templateField].type!] types[data.node?.template[templateField].type!]
] ?? ] ??
nodeColors[data.node?.template[templateField].type!] ?? nodeColors[data.node?.template[templateField].type!] ??
nodeColors.unknown nodeColors.unknown
@ -251,8 +273,8 @@ export default function GenericNode({
data.node?.template[templateField].display_name data.node?.template[templateField].display_name
? data.node.template[templateField].display_name ? data.node.template[templateField].display_name
: data.node?.template[templateField].name : data.node?.template[templateField].name
? toTitleCase(data.node.template[templateField].name) ? toTitleCase(data.node.template[templateField].name)
: toTitleCase(templateField) : toTitleCase(templateField)
} }
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}

View file

@ -12,7 +12,7 @@ export default function CodeAreaComponent({
nodeClass, nodeClass,
dynamic, dynamic,
setNodeClass, setNodeClass,
readonly=false readonly = false,
}: CodeAreaComponentType) { }: CodeAreaComponentType) {
const [myValue, setMyValue] = useState( const [myValue, setMyValue] = useState(
typeof value == "string" ? value : JSON.stringify(value) typeof value == "string" ? value : JSON.stringify(value)

View file

@ -180,7 +180,7 @@ export default function CodeTabsComponent({
key={idx} // Remember to add a unique key prop key={idx} // Remember to add a unique key prop
> >
{idx < 4 ? ( {idx < 4 ? (
<div className="w-full h-full flex flex-col"> <div className="flex h-full w-full flex-col">
{tab.description && ( {tab.description && (
<div <div
className="mb-2 w-full text-left text-sm" className="mb-2 w-full text-left text-sm"
@ -633,7 +633,14 @@ export default function CodeTabsComponent({
> >
<div className="mx-auto"> <div className="mx-auto">
<PromptAreaComponent <PromptAreaComponent
readonly={node.data.node?.flow && node.data.node.template[templateField].dynamic? true : false} readonly={
node.data.node?.flow &&
node.data.node.template[
templateField
].dynamic
? true
: false
}
editNode={true} editNode={true}
disabled={false} disabled={false}
value={ value={
@ -689,7 +696,14 @@ export default function CodeTabsComponent({
> >
<div className="mx-auto"> <div className="mx-auto">
<CodeAreaComponent <CodeAreaComponent
readonly={node.data.node?.flow && node.data.node.template[templateField].dynamic? true : false} readonly={
node.data.node?.flow &&
node.data.node.template[
templateField
].dynamic
? true
: false
}
disabled={false} disabled={false}
editNode={true} editNode={true}
value={ value={

View file

@ -139,9 +139,7 @@ export default function Header(): JSX.Element {
<button <button
className={ className={
"h-7 w-7 rounded-full focus-visible:outline-0 " + "h-7 w-7 rounded-full focus-visible:outline-0 " +
gradients[ gradients[gradientIndex]
gradientIndex
]
} }
/> />
</DropdownMenuTrigger> </DropdownMenuTrigger>

View file

@ -6,7 +6,7 @@ import { classNames } from "../../utils/utils";
import { Input } from "../ui/input"; import { Input } from "../ui/input";
export default function InputComponent({ export default function InputComponent({
autoFocus =false, autoFocus = false,
onBlur, onBlur,
value, value,
onChange, onChange,
@ -17,7 +17,7 @@ export default function InputComponent({
editNode = false, editNode = false,
placeholder = "Type something...", placeholder = "Type something...",
className, className,
blurOnEnter=false blurOnEnter = false,
}: InputComponentType): JSX.Element { }: InputComponentType): JSX.Element {
const [pwdVisible, setPwdVisible] = useState(false); const [pwdVisible, setPwdVisible] = useState(false);
const refInput = useRef<HTMLInputElement>(null); const refInput = useRef<HTMLInputElement>(null);
@ -33,8 +33,8 @@ export default function InputComponent({
{isForm ? ( {isForm ? (
<Form.Control asChild> <Form.Control asChild>
<Input <Input
ref={refInput} ref={refInput}
onBlur={onBlur} onBlur={onBlur}
autoFocus={autoFocus} autoFocus={autoFocus}
type={password && !pwdVisible ? "password" : "text"} type={password && !pwdVisible ? "password" : "text"}
value={value} value={value}
@ -55,7 +55,7 @@ export default function InputComponent({
}} }}
onKeyDown={(e) => { onKeyDown={(e) => {
handleKeyDown(e, value, ""); handleKeyDown(e, value, "");
if(blurOnEnter && e.key === "Enter") refInput.current?.blur(); if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
}} }}
/> />
</Form.Control> </Form.Control>
@ -83,7 +83,7 @@ export default function InputComponent({
}} }}
onKeyDown={(e) => { onKeyDown={(e) => {
handleKeyDown(e, value, ""); handleKeyDown(e, value, "");
if(blurOnEnter && e.key === "Enter") refInput.current?.blur(); if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
}} }}
/> />
)} )}

View file

@ -14,7 +14,7 @@ export default function PromptAreaComponent({
onChange, onChange,
disabled, disabled,
editNode = false, editNode = false,
readonly=false readonly = false,
}: TextAreaComponentType): JSX.Element { }: TextAreaComponentType): JSX.Element {
useEffect(() => { useEffect(() => {
if (disabled) { if (disabled) {

View file

@ -27,7 +27,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay <DialogPrimitive.Overlay
ref={ref} ref={ref}
className={cn( className={cn(
"fixed top-0 right-0 left-0 bottom-0 overflow-auto inset-0 z-50 bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className className
)} )}
{...props} {...props}
@ -44,7 +44,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content <DialogPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"noundo nocopy flex text-start overflow-auto z-50 justify-center items-left flex-col w-full max-w-lg gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-bottom-[48%] data-[state=open]:slide-in-from-bottom-[48%] sm:rounded-lg md:w-full", "noundo nocopy items-left z-50 flex w-full max-w-lg flex-col justify-center gap-4 overflow-auto border bg-background p-6 text-start shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-bottom-[48%] data-[state=open]:slide-in-from-bottom-[48%] sm:rounded-lg md:w-full",
className className
)} )}
{...props} {...props}

View file

@ -28,9 +28,7 @@ export function DarkProvider({ children }) {
fetchStars(); fetchStars();
const min = 0; const min = 0;
const max = 30; const max = 30;
setGradientIndex( setGradientIndex(Math.floor(Math.random() * (max - min + 1)) + min);
Math.floor(Math.random() * (max - min + 1)) + min
)
}, []); }, []);
useEffect(() => { useEffect(() => {

View file

@ -52,7 +52,7 @@ const TabsContextInitialValue: TabsContextType = {
isLoading: true, isLoading: true,
flows: [], flows: [],
removeFlow: (id: string) => {}, removeFlow: (id: string) => {},
addFlow: async (newProject:boolean,flowData?: FlowType) => "", addFlow: async (newProject: boolean, flowData?: FlowType) => "",
updateFlow: (newFlow: FlowType) => {}, updateFlow: (newFlow: FlowType) => {},
incrementNodeId: () => uid(), incrementNodeId: () => uid(),
downloadFlow: (flow: FlowType) => {}, downloadFlow: (flow: FlowType) => {},
@ -324,7 +324,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// parse the text into a JSON object // parse the text into a JSON object
let flow: FlowType = JSON.parse(text); let flow: FlowType = JSON.parse(text);
id = await addFlow(newProject,flow); id = await addFlow(newProject, flow);
} else { } else {
// create a file input // create a file input
const input = document.createElement("input"); const input = document.createElement("input");
@ -339,7 +339,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const currentfile = (e.target as HTMLInputElement).files![0]; const currentfile = (e.target as HTMLInputElement).files![0];
let text = await currentfile.text(); let text = await currentfile.text();
let flow: FlowType = JSON.parse(text); let flow: FlowType = JSON.parse(text);
const flowId = await addFlow(newProject,flow); const flowId = await addFlow(newProject, flow);
resolve(flowId); resolve(flowId);
} }
}; };
@ -486,7 +486,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const addFlow = async ( const addFlow = async (
newProject?: Boolean, newProject?: Boolean,
flow?: FlowType, flow?: FlowType
): Promise<String | undefined> => { ): Promise<String | undefined> => {
if (newProject) { if (newProject) {
let flowData = extractDataFromFlow(flow!); let flowData = extractDataFromFlow(flow!);

View file

@ -140,9 +140,9 @@ const EditNodeModal = forwardRef(
<TableRow key={index} className="h-10"> <TableRow key={index} className="h-10">
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3"> <TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
{myData.node?.template[templateParam].display_name {myData.node?.template[templateParam].display_name
? myData.node.template[templateParam].display_name ? myData.node.template[templateParam]
: myData.node?.template[templateParam] .display_name
.name} : myData.node?.template[templateParam].name}
</TableCell> </TableCell>
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground "> <TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
{myData.node?.template[templateParam].type === {myData.node?.template[templateParam].type ===
@ -297,7 +297,13 @@ const EditNodeModal = forwardRef(
"prompt" ? ( "prompt" ? (
<div className="mx-auto"> <div className="mx-auto">
<PromptAreaComponent <PromptAreaComponent
readonly={myData.node?.flow && myData.node.template[templateParam].dynamic? true : false} readonly={
myData.node?.flow &&
myData.node.template[templateParam]
.dynamic
? true
: false
}
field_name={templateParam} field_name={templateParam}
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
@ -318,7 +324,13 @@ const EditNodeModal = forwardRef(
"code" ? ( "code" ? (
<div className="mx-auto"> <div className="mx-auto">
<CodeAreaComponent <CodeAreaComponent
readonly={myData.node?.flow && myData.node.template[templateParam].dynamic? true : false} readonly={
myData.node?.flow &&
myData.node.template[templateParam]
.dynamic
? true
: false
}
dynamic={ dynamic={
data.node!.template[templateParam] data.node!.template[templateParam]
.dynamic ?? false .dynamic ?? false

View file

@ -23,14 +23,13 @@ export default function CodeAreaModal({
setNodeClass, setNodeClass,
children, children,
dynamic, dynamic,
readonly=false readonly = false,
}: codeAreaModalPropsType): JSX.Element { }: codeAreaModalPropsType): JSX.Element {
const [code, setCode] = useState(value); const [code, setCode] = useState(value);
const { dark } = useContext(darkContext); const { dark } = useContext(darkContext);
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
const [height, setHeight] = useState<string | null>(null); const [height, setHeight] = useState<string | null>(null);
const { setErrorData, setSuccessData } = const { setErrorData, setSuccessData } = useContext(alertContext);
useContext(alertContext);
const [error, setError] = useState<{ const [error, setError] = useState<{
detail: { error: string | undefined; traceback: string | undefined }; detail: { error: string | undefined; traceback: string | undefined };
} | null>(null); } | null>(null);
@ -183,7 +182,12 @@ export default function CodeAreaModal({
</div> </div>
</div> </div>
<div className="flex h-fit w-full justify-end"> <div className="flex h-fit w-full justify-end">
<Button disabled={readonly} className="mt-3" onClick={handleClick} type="submit"> <Button
disabled={readonly}
className="mt-3"
onClick={handleClick}
type="submit"
>
Check & Save Check & Save
</Button> </Button>
</div> </div>

View file

@ -27,7 +27,7 @@ import { AuthContext } from "../../contexts/authContext";
import { TabsContext } from "../../contexts/tabsContext"; import { TabsContext } from "../../contexts/tabsContext";
import { getBuildStatus } from "../../controllers/API"; import { getBuildStatus } from "../../controllers/API";
import { TabsState } from "../../types/tabs"; import { TabsState } from "../../types/tabs";
import { validateNodes,processFlow } from "../../utils/reactflowUtils"; import { processFlow, validateNodes } from "../../utils/reactflowUtils";
export default function FormModal({ export default function FormModal({
flow, flow,
@ -368,7 +368,7 @@ export default function FormModal({
tabsState[flow.id].formKeysData.template tabsState[flow.id].formKeysData.template
); );
sendAll({ sendAll({
... processFlow(reactFlowInstance?.toObject()!), ...processFlow(reactFlowInstance?.toObject()!),
inputs: inputs!, inputs: inputs!,
chatHistory, chatHistory,
name: flow.name, name: flow.name,

View file

@ -34,7 +34,7 @@ export default function GenericModal({
nodeClass, nodeClass,
setNodeClass, setNodeClass,
children, children,
readonly=false, readonly = false,
}: genericModalPropsType): JSX.Element { }: genericModalPropsType): JSX.Element {
const [myButtonText] = useState(buttonText); const [myButtonText] = useState(buttonText);
const [myModalTitle] = useState(modalTitle); const [myModalTitle] = useState(modalTitle);
@ -285,7 +285,7 @@ export default function GenericModal({
)} )}
</div> </div>
<Button <Button
disabled={readonly} disabled={readonly}
onClick={() => { onClick={() => {
switch (myModalType) { switch (myModalType) {
case TypeModal.TEXT: case TypeModal.TEXT:

View file

@ -86,7 +86,7 @@ export default function CommunityPage(): JSX.Element {
size="sm" size="sm"
className="whitespace-nowrap " className="whitespace-nowrap "
onClick={() => { onClick={() => {
addFlow(true,flow).then((id) => { addFlow(true, flow).then((id) => {
navigate("/flow/" + id); navigate("/flow/" + id);
}); });
}} }}

View file

@ -44,8 +44,8 @@ import {
} from "../../../../utils/reactflowUtils"; } from "../../../../utils/reactflowUtils";
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils"; import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
import ConnectionLineComponent from "../ConnectionLineComponent"; import ConnectionLineComponent from "../ConnectionLineComponent";
import ExtraSidebar from "../extraSidebarComponent";
import SelectionMenu from "../SelectionMenuComponent"; import SelectionMenu from "../SelectionMenuComponent";
import ExtraSidebar from "../extraSidebarComponent";
const nodeTypes = { const nodeTypes = {
genericNode: GenericNode, genericNode: GenericNode,
@ -444,30 +444,47 @@ export default function Page({
[&>button]:border-b-border hover:[&>button]:bg-border" [&>button]:border-b-border hover:[&>button]:bg-border"
></Controls> ></Controls>
)} )}
<SelectionMenu isVisible={selectionMenuVisible} nodes={lastSelection?.nodes} <SelectionMenu
onClick={()=>{ isVisible={selectionMenuVisible}
if(validateSelection(lastSelection!,edges).length===0){ nodes={lastSelection?.nodes}
const {newFlow} = generateFlow(lastSelection!,reactFlowInstance!,getRandomName()); onClick={() => {
const newGroupNode = generateNodeFromFlow(newFlow) if (
setNodes((oldNodes)=>[...oldNodes.filter((oldNodes)=>!lastSelection?.nodes.some((selectionNode)=>selectionNode.id===oldNodes.id)),newGroupNode]) validateSelection(lastSelection!, edges).length === 0
setEdges((oldEdges) => ) {
oldEdges.filter( const { newFlow } = generateFlow(
(oldEdge) => lastSelection!,
!lastSelection!.nodes.some( reactFlowInstance!,
(selectionNode) => getRandomName()
selectionNode.id === oldEdge.target || );
selectionNode.id === oldEdge.source const newGroupNode = generateNodeFromFlow(newFlow);
setNodes((oldNodes) => [
...oldNodes.filter(
(oldNodes) =>
!lastSelection?.nodes.some(
(selectionNode) =>
selectionNode.id === oldNodes.id
)
),
newGroupNode,
]);
setEdges((oldEdges) =>
oldEdges.filter(
(oldEdge) =>
!lastSelection!.nodes.some(
(selectionNode) =>
selectionNode.id === oldEdge.target ||
selectionNode.id === oldEdge.source
)
) )
) );
); } else {
} setErrorData({
else{ title: "Invalid selection",
setErrorData({ list: validateSelection(lastSelection!, edges),
title: "Invalid selection", });
list: validateSelection(lastSelection!,edges), }
}); }}
} />
}}/>
</ReactFlow> </ReactFlow>
{!view && ( {!view && (
<Chat flow={flow} reactFlowInstance={reactFlowInstance!} /> <Chat flow={flow} reactFlowInstance={reactFlowInstance!} />

View file

@ -1,4 +1,4 @@
import {useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { NodeToolbar } from "reactflow"; import { NodeToolbar } from "reactflow";
import IconComponent from "../../../../components/genericIconComponent"; import IconComponent from "../../../../components/genericIconComponent";
export default function SelectionMenu({ onClick, nodes, isVisible }) { export default function SelectionMenu({ onClick, nodes, isVisible }) {

View file

@ -5,8 +5,11 @@ import IconComponent from "../../../../components/genericIconComponent";
import { TabsContext } from "../../../../contexts/tabsContext"; import { TabsContext } from "../../../../contexts/tabsContext";
import EditNodeModal from "../../../../modals/EditNodeModal"; import EditNodeModal from "../../../../modals/EditNodeModal";
import { nodeToolbarPropsType } from "../../../../types/components"; import { nodeToolbarPropsType } from "../../../../types/components";
import {
expandGroupNode,
updateFlowPosition,
} from "../../../../utils/reactflowUtils";
import { classNames } from "../../../../utils/utils"; import { classNames } from "../../../../utils/utils";
import { expandGroupNode, ungroupNode, updateFlowPosition } from "../../../../utils/reactflowUtils";
export default function NodeToolbarComponent({ export default function NodeToolbarComponent({
data, data,
@ -82,9 +85,9 @@ export default function NodeToolbarComponent({
<a <a
className={classNames( className={classNames(
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" + "relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(data.node?.documentation === "" (data.node?.documentation === ""
? " text-muted-foreground" ? " text-muted-foreground"
: " text-foreground") : " text-foreground")
)} )}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
@ -110,9 +113,10 @@ export default function NodeToolbarComponent({
<div <div
className={classNames( className={classNames(
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" + "relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(nodeLength == 0 (nodeLength == 0
? " text-muted-foreground" ? " text-muted-foreground"
: " text-foreground") +(isGroup?"":" rounded-r-md") : " text-foreground") +
(isGroup ? "" : " rounded-r-md")
)} )}
> >
<IconComponent name="Settings2" className="h-4 w-4 " /> <IconComponent name="Settings2" className="h-4 w-4 " />
@ -128,8 +132,8 @@ export default function NodeToolbarComponent({
)} )}
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
updateFlowPosition(position,data.node?.flow!) updateFlowPosition(position, data.node?.flow!);
expandGroupNode(data,reactFlowInstance) expandGroupNode(data, reactFlowInstance);
}} }}
> >
<IconComponent name="Ungroup" className="h-4 w-4" /> <IconComponent name="Ungroup" className="h-4 w-4" />

View file

@ -17,8 +17,14 @@ export type APIClassType = {
beta?: boolean; beta?: boolean;
documentation: string; documentation: string;
error?: string; error?: string;
flow?:FlowType; flow?: FlowType;
[key: string]: Array<string> | string | APITemplateType | boolean | FlowType | undefined; [key: string]:
| Array<string>
| string
| APITemplateType
| boolean
| FlowType
| undefined;
}; };
export type TemplateVariableType = { export type TemplateVariableType = {
@ -30,8 +36,8 @@ export type TemplateVariableType = {
readonly: boolean; readonly: boolean;
multiline?: boolean; multiline?: boolean;
value?: any; value?: any;
dynamic?:boolean; dynamic?: boolean;
proxy?:{id:string,field:string} proxy?: { id: string; field: string };
input_types?: Array<string>; input_types?: Array<string>;
[key: string]: any; [key: string]: any;
}; };

View file

@ -49,7 +49,7 @@ export type ParameterComponentType = {
dataContext?: typesContextType; dataContext?: typesContextType;
optionalHandle?: Array<String> | null; optionalHandle?: Array<String> | null;
info?: string; info?: string;
proxy?: {field: string, id: string}; proxy?: { field: string; id: string };
}; };
export type InputListComponentType = { export type InputListComponentType = {
value: string[]; value: string[];
@ -395,7 +395,7 @@ export type nodeToolbarPropsType = {
data: NodeDataType; data: NodeDataType;
deleteNode: (idx: string) => void; deleteNode: (idx: string) => void;
setData: (newState: NodeDataType) => void; setData: (newState: NodeDataType) => void;
position:XYPosition; position: XYPosition;
}; };
export type parsedDataType = { export type parsedDataType = {

View file

@ -50,5 +50,5 @@ export type targetHandleType = {
type: string; type: string;
fieldName: string; fieldName: string;
id: string; id: string;
proxy?:{field:string, id:string} proxy?: { field: string; id: string };
}; };

View file

@ -1,6 +1,5 @@
import { Edge, Node } from "reactflow"; import { Edge, Node } from "reactflow";
import { FlowType, NodeType } from "../flow"; import { FlowType, NodeType } from "../flow";
import { generateFlow } from "../../utils/reactflowUtils";
export type cleanEdgesType = { export type cleanEdgesType = {
flow: { flow: {
@ -20,9 +19,9 @@ export type updateEdgesHandleIdsType = {
edges: Edge[]; edges: Edge[];
}; };
export type generateFlowType = { newFlow: FlowType; removedEdges: Edge[] } export type generateFlowType = { newFlow: FlowType; removedEdges: Edge[] };
export type findLastNodeType = { export type findLastNodeType = {
nodes: NodeType[]; nodes: NodeType[];
edges: Edge[]; edges: Edge[];
} };

View file

@ -32,6 +32,7 @@ import {
Gift, Gift,
GitFork, GitFork,
GithubIcon, GithubIcon,
Group,
Hammer, Hammer,
HelpCircle, HelpCircle,
Home, Home,
@ -63,6 +64,7 @@ import {
TerminalSquare, TerminalSquare,
Trash2, Trash2,
Undo, Undo,
Ungroup,
Unplug, Unplug,
Upload, Upload,
UserCog2, UserCog2,
@ -75,8 +77,6 @@ import {
X, X,
XCircle, XCircle,
Zap, Zap,
Group,
Ungroup
} from "lucide-react"; } from "lucide-react";
import { FaApple, FaGithub } from "react-icons/fa"; import { FaApple, FaGithub } from "react-icons/fa";
import { AirbyteIcon } from "../icons/Airbyte"; import { AirbyteIcon } from "../icons/Airbyte";
@ -305,5 +305,5 @@ export const nodeIconsLucide: iconsType = {
Unplug, Unplug,
Group, Group,
ChevronUp, ChevronUp,
Ungroup Ungroup,
}; };