Updated global variables to ShadCN and updated logic to show variables as different things
This commit is contained in:
parent
50d27eeaa0
commit
d003be4fe2
7 changed files with 202 additions and 169 deletions
14
src/frontend/package-lock.json
generated
14
src/frontend/package-lock.json
generated
|
|
@ -42,6 +42,7 @@
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"class-variance-authority": "^0.6.1",
|
"class-variance-authority": "^0.6.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
|
"cmdk": "^1.0.0",
|
||||||
"dompurify": "^3.0.5",
|
"dompurify": "^3.0.5",
|
||||||
"esbuild": "^0.17.19",
|
"esbuild": "^0.17.19",
|
||||||
"framer-motion": "^11.0.6",
|
"framer-motion": "^11.0.6",
|
||||||
|
|
@ -4797,6 +4798,19 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cmdk": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-dialog": "1.0.5",
|
||||||
|
"@radix-ui/react-primitive": "1.0.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^18.0.0",
|
||||||
|
"react-dom": "^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/code-block-writer": {
|
"node_modules/code-block-writer": {
|
||||||
"version": "12.0.0",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"class-variance-authority": "^0.6.1",
|
"class-variance-authority": "^0.6.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
|
"cmdk": "^1.0.0",
|
||||||
"dompurify": "^3.0.5",
|
"dompurify": "^3.0.5",
|
||||||
"esbuild": "^0.17.19",
|
"esbuild": "^0.17.19",
|
||||||
"framer-motion": "^11.0.6",
|
"framer-motion": "^11.0.6",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import PromptAreaComponent from "../../../../components/promptComponent";
|
||||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||||
import { Button } from "../../../../components/ui/button";
|
import { Button } from "../../../../components/ui/button";
|
||||||
|
import { CommandItem } from "../../../../components/ui/command";
|
||||||
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
||||||
import {
|
import {
|
||||||
INPUT_HANDLER_HOVER,
|
INPUT_HANDLER_HOVER,
|
||||||
|
|
@ -23,6 +24,7 @@ import {
|
||||||
OUTPUT_HANDLER_HOVER,
|
OUTPUT_HANDLER_HOVER,
|
||||||
TOOLTIP_EMPTY,
|
TOOLTIP_EMPTY,
|
||||||
} from "../../../../constants/constants";
|
} from "../../../../constants/constants";
|
||||||
|
import AddNewVariableButton from "../../../../pages/globalVariablesPage/components/addNewVariableButton";
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||||
|
|
@ -46,7 +48,7 @@ import {
|
||||||
nodeIconsLucide,
|
nodeIconsLucide,
|
||||||
nodeNames,
|
nodeNames,
|
||||||
} from "../../../../utils/styleUtils";
|
} from "../../../../utils/styleUtils";
|
||||||
import { classNames, groupByFamily } from "../../../../utils/utils";
|
import { classNames, cn, groupByFamily } from "../../../../utils/utils";
|
||||||
|
|
||||||
export default function ParameterComponent({
|
export default function ParameterComponent({
|
||||||
left,
|
left,
|
||||||
|
|
@ -386,7 +388,7 @@ export default function ParameterComponent({
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"w-full truncate text-sm flex items-center" +
|
"flex w-full items-center truncate text-sm" +
|
||||||
(left ? "" : " text-end")
|
(left ? "" : " text-end")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
@ -546,33 +548,47 @@ export default function ParameterComponent({
|
||||||
password={data.node?.template[name].password ?? false}
|
password={data.node?.template[name].password ?? false}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
options={globalVariablesEntries}
|
options={globalVariablesEntries}
|
||||||
onChange={(value) => {
|
optionsPlaceholder={"Global Variables"}
|
||||||
handleOnNewValue(value);
|
optionsButton={
|
||||||
if (globalVariablesEntries.includes(value)) {
|
<AddNewVariableButton>
|
||||||
setNoticeData({
|
<CommandItem value={"new"}>
|
||||||
title: `the value inserted in ${data.node?.display_name} is a global variable, \n
|
<IconComponent
|
||||||
the real value will be update on run`,
|
name="Plus"
|
||||||
});
|
className={cn("mr-2 h-4 w-4 text-primary")}
|
||||||
setNode(data.id, (oldNode) => {
|
aria-hidden="true"
|
||||||
let newNode = cloneDeep(oldNode);
|
/>
|
||||||
newNode.data = {
|
Add New Variable
|
||||||
...newNode.data,
|
</CommandItem>
|
||||||
};
|
</AddNewVariableButton>
|
||||||
newNode.data.node.template[name].load_from_db = true;
|
}
|
||||||
return newNode;
|
selectedOption={
|
||||||
});
|
data?.node?.template[name].load_from_db ?? false
|
||||||
} else {
|
? data?.node?.template[name].value
|
||||||
setNode(data.id, (oldNode) => {
|
: ""
|
||||||
let newNode = cloneDeep(oldNode);
|
}
|
||||||
newNode.data = {
|
setSelectedOption={(value) => {
|
||||||
...newNode.data,
|
handleOnNewValue(value);
|
||||||
};
|
setNode(data.id, (oldNode) => {
|
||||||
newNode.data.node.template[name].load_from_db = false;
|
let newNode = cloneDeep(oldNode);
|
||||||
return newNode;
|
newNode.data = {
|
||||||
});
|
...newNode.data,
|
||||||
}
|
};
|
||||||
//mark as global variable
|
newNode.data.node.template[name].load_from_db =
|
||||||
}}
|
value === "" ? false : true;
|
||||||
|
return newNode;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onChange={(value) => {
|
||||||
|
handleOnNewValue(value);
|
||||||
|
setNode(data.id, (oldNode) => {
|
||||||
|
let newNode = cloneDeep(oldNode);
|
||||||
|
newNode.data = {
|
||||||
|
...newNode.data,
|
||||||
|
};
|
||||||
|
newNode.data.node.template[name].load_from_db = false;
|
||||||
|
return newNode;
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{data.node?.template[name].refresh_button && (
|
{data.node?.template[name].refresh_button && (
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
import { Listbox, Transition } from "@headlessui/react";
|
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { Fragment, useEffect, useRef, useState } from "react";
|
import { PopoverAnchor } from "@radix-ui/react-popover";
|
||||||
import AddNewVariableButton from "../../pages/globalVariablesPage/components/addNewVariableButton";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { InputComponentType } from "../../types/components";
|
import { InputComponentType } from "../../types/components";
|
||||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||||
import { classNames, cn } from "../../utils/utils";
|
import { classNames, cn } from "../../utils/utils";
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from "../ui/command";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
import { Separator } from "../ui/separator";
|
import { Popover, PopoverContentWithoutPortal } from "../ui/popover";
|
||||||
|
|
||||||
export default function InputComponent({
|
export default function InputComponent({
|
||||||
autoFocus = false,
|
autoFocus = false,
|
||||||
|
|
@ -23,7 +30,11 @@ export default function InputComponent({
|
||||||
className,
|
className,
|
||||||
id = "",
|
id = "",
|
||||||
blurOnEnter = false,
|
blurOnEnter = false,
|
||||||
|
selectedOption,
|
||||||
|
setSelectedOption,
|
||||||
options = [],
|
options = [],
|
||||||
|
optionsPlaceholder = "Search options...",
|
||||||
|
optionsButton,
|
||||||
}: 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);
|
||||||
|
|
@ -36,10 +47,6 @@ export default function InputComponent({
|
||||||
}
|
}
|
||||||
}, [disabled]);
|
}, [disabled]);
|
||||||
|
|
||||||
const filteredOptions = options.filter((option) =>
|
|
||||||
option.toLowerCase().includes(value.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
function onInputLostFocus(event): void {
|
function onInputLostFocus(event): void {
|
||||||
if (onBlur) onBlur(event);
|
if (onBlur) onBlur(event);
|
||||||
}
|
}
|
||||||
|
|
@ -81,144 +88,118 @@ export default function InputComponent({
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Input
|
<Popover open={showOptions} onOpenChange={setShowOptions}>
|
||||||
id={id}
|
<PopoverAnchor>
|
||||||
ref={refInput}
|
<Input
|
||||||
type="text"
|
id={id}
|
||||||
onBlur={onInputLostFocus}
|
ref={refInput}
|
||||||
value={value}
|
type="text"
|
||||||
autoFocus={autoFocus}
|
onBlur={onInputLostFocus}
|
||||||
disabled={disabled}
|
value={value}
|
||||||
required={required}
|
autoFocus={autoFocus}
|
||||||
className={classNames(
|
disabled={disabled || selectedOption !== ""}
|
||||||
password && !pwdVisible && value !== ""
|
onClick={() => {
|
||||||
? " text-clip password "
|
selectedOption !== "" && setShowOptions(true);
|
||||||
: "",
|
}}
|
||||||
editNode ? " input-edit-node " : "",
|
required={required}
|
||||||
password && editNode ? "pr-8" : "",
|
className={classNames(
|
||||||
password && !editNode ? "pr-10" : "",
|
password && !pwdVisible && value !== ""
|
||||||
className!
|
? " text-clip password "
|
||||||
)}
|
: "",
|
||||||
placeholder={password && editNode ? "Key" : placeholder}
|
editNode ? " input-edit-node " : "",
|
||||||
onChange={(e) => {
|
password && editNode ? "pr-8" : "",
|
||||||
onChange(e.target.value);
|
password && !editNode ? "pr-10" : "",
|
||||||
}}
|
className!
|
||||||
onKeyDown={(e) => {
|
)}
|
||||||
handleKeyDown(e, value, "");
|
placeholder={password && editNode ? "Key" : placeholder}
|
||||||
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
|
onChange={(e) => {
|
||||||
}}
|
onChange(e.target.value);
|
||||||
data-testid={editNode ? id + "-edit" : id}
|
}}
|
||||||
/>
|
onKeyDown={(e) => {
|
||||||
<Listbox
|
handleKeyDown(e, value, "");
|
||||||
onChange={(val) => {
|
if (blurOnEnter && e.key === "Enter")
|
||||||
onChange(val);
|
refInput.current?.blur();
|
||||||
}}
|
}}
|
||||||
>
|
data-testid={editNode ? id + "-edit" : id}
|
||||||
<>
|
/>
|
||||||
<div className={"relative mt-1 "}>
|
</PopoverAnchor>
|
||||||
<Transition
|
<PopoverContentWithoutPortal
|
||||||
show={showOptions}
|
className="nocopy nopan nodelete nodrag noundo p-0"
|
||||||
as={Fragment}
|
style={{ minWidth: refInput?.current?.clientWidth ?? "200px" }}
|
||||||
leave="transition ease-in duration-100"
|
side="bottom"
|
||||||
leaveFrom="opacity-100"
|
align="center"
|
||||||
leaveTo="opacity-0"
|
>
|
||||||
>
|
<Command>
|
||||||
<Listbox.Options
|
<CommandInput placeholder={optionsPlaceholder} />
|
||||||
className={classNames(
|
<CommandList>
|
||||||
editNode
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
? "dropdown-component-true-options nowheel custom-scroll"
|
<CommandGroup defaultChecked={false}>
|
||||||
: "dropdown-component-false-options nowheel custom-scroll",
|
{options.map((option, id) => (
|
||||||
false ? "mb-2 w-[250px]" : "absolute w-full"
|
<CommandItem
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-between px-4 pb-3 pt-2 font-semibold">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<IconComponent name="Globe" className="h-4 w-4" />
|
|
||||||
Global Variables
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<AddNewVariableButton>
|
|
||||||
<button className="text-muted-foreground hover:text-accent-foreground">
|
|
||||||
<IconComponent name="Plus" className="h-5 w-5" />
|
|
||||||
</button>
|
|
||||||
</AddNewVariableButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Separator />
|
|
||||||
{filteredOptions.map((option, id) => (
|
|
||||||
<Listbox.Option
|
|
||||||
key={id}
|
key={id}
|
||||||
className={({ active }) =>
|
|
||||||
classNames(
|
|
||||||
active ? " bg-accent" : "",
|
|
||||||
editNode
|
|
||||||
? "dropdown-component-false-option"
|
|
||||||
: "dropdown-component-true-option",
|
|
||||||
" hover:bg-accent"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
value={option}
|
value={option}
|
||||||
|
onSelect={(currentValue) => {
|
||||||
|
setSelectedOption &&
|
||||||
|
setSelectedOption(
|
||||||
|
currentValue === selectedOption
|
||||||
|
? ""
|
||||||
|
: currentValue
|
||||||
|
);
|
||||||
|
setShowOptions(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{({ selected, active }) => (
|
<IconComponent
|
||||||
<>
|
name="Check"
|
||||||
<span
|
className={cn(
|
||||||
className={classNames(
|
"mr-2 h-4 w-4 text-primary",
|
||||||
selected ? "font-semibold" : "font-normal",
|
selectedOption === option
|
||||||
"block truncate "
|
? "opacity-100"
|
||||||
)}
|
: "opacity-0"
|
||||||
data-testid={`${option}-${id ?? ""}-option`}
|
)}
|
||||||
>
|
aria-hidden="true"
|
||||||
{option}
|
/>
|
||||||
</span>
|
{option}
|
||||||
|
</CommandItem>
|
||||||
{selected ? (
|
|
||||||
<span
|
|
||||||
className={classNames(
|
|
||||||
"dropdown-component-choosal"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<IconComponent
|
|
||||||
name="Check"
|
|
||||||
className={
|
|
||||||
"dropdown-component-check-icon text-foreground"
|
|
||||||
}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Listbox.Option>
|
|
||||||
))}
|
))}
|
||||||
</Listbox.Options>
|
{optionsButton && optionsButton}
|
||||||
</Transition>
|
</CommandGroup>
|
||||||
</div>
|
</CommandList>
|
||||||
</>
|
</Command>
|
||||||
</Listbox>
|
</PopoverContentWithoutPortal>
|
||||||
|
</Popover>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-auto absolute inset-y-0 h-full w-full",
|
||||||
|
selectedOption !== "" ? "" : "hidden"
|
||||||
|
)}
|
||||||
|
onClick={
|
||||||
|
selectedOption !== ""
|
||||||
|
? (e) => {
|
||||||
|
setShowOptions((old) => !old);
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
: () => {}
|
||||||
|
}
|
||||||
|
></div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{options.length > 0 && (
|
<span
|
||||||
<span
|
className={cn(
|
||||||
className={cn(
|
password ? "right-8" : "right-0",
|
||||||
password ? "right-8" : "right-0",
|
"absolute inset-y-0 flex items-center pr-2"
|
||||||
"absolute inset-y-0 flex items-center pr-2"
|
)}
|
||||||
)}
|
>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setShowOptions(!showOptions);
|
||||||
|
}}
|
||||||
|
className="text-muted-foreground hover:text-accent-foreground"
|
||||||
>
|
>
|
||||||
<button
|
<IconComponent name="Globe" className="h-4 w-4" aria-hidden="true" />
|
||||||
onClick={() => {
|
</button>
|
||||||
setShowOptions(!showOptions);
|
</span>
|
||||||
}}
|
|
||||||
className="text-muted-foreground hover:text-accent-foreground"
|
|
||||||
>
|
|
||||||
<IconComponent
|
|
||||||
name="Globe"
|
|
||||||
className="h-4 w-4"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{password && (
|
{password && (
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ const CommandItem = React.forwardRef<
|
||||||
<CommandPrimitive.Item
|
<CommandPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,21 @@ const PopoverContent = React.forwardRef<
|
||||||
));
|
));
|
||||||
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
||||||
|
|
||||||
export { Popover, PopoverContent, PopoverTrigger };
|
const PopoverContentWithoutPortal = React.forwardRef<
|
||||||
|
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||||
|
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
||||||
|
<PopoverPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
align={align}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={cn(
|
||||||
|
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
PopoverContentWithoutPortal.displayName = PopoverPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
export { Popover, PopoverContent, PopoverContentWithoutPortal, PopoverTrigger };
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,11 @@ export type InputComponentType = {
|
||||||
className?: string;
|
className?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
blurOnEnter?: boolean;
|
blurOnEnter?: boolean;
|
||||||
|
optionsPlaceholder?: string;
|
||||||
options?: string[];
|
options?: string[];
|
||||||
|
optionsButton?: ReactElement;
|
||||||
|
selectedOption?: string;
|
||||||
|
setSelectedOption?: (value: string) => void;
|
||||||
};
|
};
|
||||||
export type ToggleComponentType = {
|
export type ToggleComponentType = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue