UI Improvements: tooltip, classes icons e icons (#404)
This commit is contained in:
commit
188ae61c79
14 changed files with 223 additions and 71 deletions
32
src/frontend/package-lock.json
generated
32
src/frontend/package-lock.json
generated
|
|
@ -32,6 +32,7 @@
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"react-tabs": "^6.0.0",
|
"react-tabs": "^6.0.0",
|
||||||
|
"react-tooltip": "^5.13.1",
|
||||||
"reactflow": "^11.5.5",
|
"reactflow": "^11.5.5",
|
||||||
"rehype-mathjax": "^4.0.2",
|
"rehype-mathjax": "^4.0.2",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
|
|
@ -897,6 +898,19 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@floating-ui/core": {
|
||||||
|
"version": "1.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.6.tgz",
|
||||||
|
"integrity": "sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg=="
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/dom": {
|
||||||
|
"version": "1.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.9.tgz",
|
||||||
|
"integrity": "sha512-sosQxsqgxMNkV3C+3UqTS6LxP7isRLwX8WMepp843Rb3/b0Wz8+MdUkxJksByip3C2WwLugLHN1b4ibn//zKwQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/core": "^1.2.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@headlessui/react": {
|
"node_modules/@headlessui/react": {
|
||||||
"version": "1.7.10",
|
"version": "1.7.10",
|
||||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.10.tgz",
|
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.10.tgz",
|
||||||
|
|
@ -2938,6 +2952,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz",
|
||||||
"integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g=="
|
"integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g=="
|
||||||
},
|
},
|
||||||
|
"node_modules/classnames": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
|
||||||
|
},
|
||||||
"node_modules/client-only": {
|
"node_modules/client-only": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
|
|
@ -6265,6 +6284,19 @@
|
||||||
"react": "^18.0.0"
|
"react": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-tooltip": {
|
||||||
|
"version": "5.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.13.1.tgz",
|
||||||
|
"integrity": "sha512-9NstDFdjyy6cIH9zjeT70zXTHlW/TIGCOWQmhkAyqLFeQioLg1FXvb9ec7AxSpn0zyFUkFSLdFYxZRuewti3Aw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/dom": "^1.0.0",
|
||||||
|
"classnames": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.14.0",
|
||||||
|
"react-dom": ">=16.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-transition-group": {
|
"node_modules/react-transition-group": {
|
||||||
"version": "4.4.5",
|
"version": "4.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"react-tabs": "^6.0.0",
|
"react-tabs": "^6.0.0",
|
||||||
|
"react-tooltip": "^5.13.1",
|
||||||
"reactflow": "^11.5.5",
|
"reactflow": "^11.5.5",
|
||||||
"rehype-mathjax": "^4.0.2",
|
"rehype-mathjax": "^4.0.2",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ export default function ParameterComponent({
|
||||||
) : left === true && type === "float" ? (
|
) : left === true && type === "float" ? (
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
disableCopyPaste={true}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t) => {
|
onChange={(t) => {
|
||||||
data.node.template[name].value = t;
|
data.node.template[name].value = t;
|
||||||
|
|
@ -184,6 +185,7 @@ export default function ParameterComponent({
|
||||||
) : left === true && type === "int" ? (
|
) : left === true && type === "int" ? (
|
||||||
<IntComponent
|
<IntComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
disableCopyPaste={true}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t) => {
|
onChange={(t) => {
|
||||||
data.node.template[name].value = t;
|
data.node.template[name].value = t;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import NodeModal from "../../modals/NodeModal";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { TabsContext } from "../../contexts/tabsContext";
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
import { debounce } from "../../utils";
|
import { debounce } from "../../utils";
|
||||||
|
import TooltipReact from "../../components/ReactTooltipComponent";
|
||||||
import Tooltip from "../../components/TooltipComponent";
|
import Tooltip from "../../components/TooltipComponent";
|
||||||
export default function GenericNode({
|
export default function GenericNode({
|
||||||
data,
|
data,
|
||||||
|
|
@ -112,50 +113,15 @@ export default function GenericNode({
|
||||||
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
|
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Tooltip title={data.type} placement="top">
|
<div className="ml-2 truncate">
|
||||||
<div className="ml-2 truncate">{data.type}</div>
|
<TooltipReact
|
||||||
</Tooltip>
|
delayShow={1000}
|
||||||
<div>
|
selector={`node-selector-${data.type}`}
|
||||||
<Tooltip
|
htmlContent={data.type}
|
||||||
title={
|
position="top"
|
||||||
!validationStatus ? (
|
|
||||||
"Validating..."
|
|
||||||
) : (
|
|
||||||
<div className="max-h-96 overflow-auto">
|
|
||||||
{validationStatus.params.split("\n").map((line, index) => (
|
|
||||||
<div key={index}>{line}</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<div className="relative h-5 w-5">
|
<div className="ml-2 truncate">{data.type}</div>
|
||||||
<CheckCircleIcon
|
</TooltipReact>
|
||||||
className={classNames(
|
|
||||||
validationStatus && validationStatus.valid
|
|
||||||
? "text-green-500 opacity-100"
|
|
||||||
: "animate-spin text-green-500 opacity-0",
|
|
||||||
"absolute w-5 transition-all duration-200 ease-in-out hover:text-gray-500 hover:dark:text-gray-300"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<ExclamationCircleIcon
|
|
||||||
className={classNames(
|
|
||||||
validationStatus && !validationStatus.valid
|
|
||||||
? "text-red-500 opacity-100"
|
|
||||||
: "animate-spin text-red-500 opacity-0",
|
|
||||||
"absolute w-5 transition-all duration-200 ease-in-out hover:text-gray-500 hover:dark:text-gray-600"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<EllipsisHorizontalCircleIcon
|
|
||||||
className={classNames(
|
|
||||||
!validationStatus
|
|
||||||
? "text-yellow-500 opacity-100"
|
|
||||||
: "animate-spin text-yellow-500 opacity-0",
|
|
||||||
"absolute w-5 transition-all duration-300 ease-in-out hover:text-gray-500 hover:dark:text-gray-600"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
|
|
@ -183,17 +149,61 @@ export default function GenericNode({
|
||||||
)
|
)
|
||||||
? ""
|
? ""
|
||||||
: "hidden",
|
: "hidden",
|
||||||
"h-6 w-6 hover:animate-spin dark:text-gray-300"
|
"w-5 h-5 dark:text-gray-300"
|
||||||
)}
|
)}
|
||||||
></Cog6ToothIcon>
|
></Cog6ToothIcon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
deleteNode(data.id);
|
deleteNode(data.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TrashIcon className="h-6 w-6 hover:text-red-500 dark:text-gray-300 dark:hover:text-red-500"></TrashIcon>
|
<TrashIcon className="w-5 h-5 dark:text-gray-300"></TrashIcon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
!validationStatus ? (
|
||||||
|
"Validating..."
|
||||||
|
) : (
|
||||||
|
<div className="max-h-96 overflow-auto">
|
||||||
|
{validationStatus.params.split("\n").map((line, index) => (
|
||||||
|
<div key={index}>{line}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="w-5 h-5 relative top-[3px]">
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
validationStatus && validationStatus.valid
|
||||||
|
? "w-4 h-4 rounded-full bg-green-500 opacity-100"
|
||||||
|
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||||
|
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
validationStatus && !validationStatus.valid
|
||||||
|
? "w-4 h-4 rounded-full bg-yellow-500 opacity-100"
|
||||||
|
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||||
|
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
!validationStatus
|
||||||
|
? "w-4 h-4 rounded-full bg-red-500 opacity-100"
|
||||||
|
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||||
|
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
54
src/frontend/src/components/ReactTooltipComponent/index.tsx
Normal file
54
src/frontend/src/components/ReactTooltipComponent/index.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
"use client";
|
||||||
|
import type { FC } from "react";
|
||||||
|
import React from "react";
|
||||||
|
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||||
|
import "react-tooltip/dist/react-tooltip.css";
|
||||||
|
import { classNames } from "../../utils";
|
||||||
|
|
||||||
|
type TooltipProps = {
|
||||||
|
selector: string;
|
||||||
|
content?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
htmlContent?: React.ReactNode;
|
||||||
|
className?: string; // This should use !impornant to override the default styles eg: '!bg-white'
|
||||||
|
position?: "top" | "right" | "bottom" | "left";
|
||||||
|
clickable?: boolean;
|
||||||
|
children: React.ReactNode;
|
||||||
|
delayShow?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TooltipReact: FC<TooltipProps> = ({
|
||||||
|
selector,
|
||||||
|
content,
|
||||||
|
disabled,
|
||||||
|
position = "top",
|
||||||
|
children,
|
||||||
|
htmlContent,
|
||||||
|
className,
|
||||||
|
clickable,
|
||||||
|
delayShow,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="tooltip-container">
|
||||||
|
{React.cloneElement(children as React.ReactElement, {
|
||||||
|
"data-tooltip-id": selector,
|
||||||
|
})}
|
||||||
|
<ReactTooltip
|
||||||
|
id={selector}
|
||||||
|
content={content}
|
||||||
|
className={classNames(
|
||||||
|
"!bg-white !text-xs !font-normal !text-gray-700 !shadow-md !opacity-100 z-20",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
place={position}
|
||||||
|
clickable={clickable}
|
||||||
|
isOpen={disabled ? false : undefined}
|
||||||
|
delayShow={delayShow}
|
||||||
|
>
|
||||||
|
{htmlContent && htmlContent}
|
||||||
|
</ReactTooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TooltipReact;
|
||||||
|
|
@ -5,9 +5,12 @@ import { TabsContext } from "../../contexts/tabsContext";
|
||||||
export default function FloatComponent({
|
export default function FloatComponent({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
disableCopyPaste = false,
|
||||||
disabled,
|
disabled,
|
||||||
}: FloatComponentType) {
|
}: FloatComponentType) {
|
||||||
const [myValue, setMyValue] = useState(value ?? "");
|
const [myValue, setMyValue] = useState(value ?? "");
|
||||||
|
const { setDisableCopyPaste } = useContext(TabsContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
setMyValue("");
|
setMyValue("");
|
||||||
|
|
@ -15,8 +18,18 @@ export default function FloatComponent({
|
||||||
}
|
}
|
||||||
}, [disabled, onChange]);
|
}, [disabled, onChange]);
|
||||||
return (
|
return (
|
||||||
<div className={"w-full " + (disabled ? "pointer-events-none cursor-not-allowed" : "")}>
|
<div
|
||||||
|
className={
|
||||||
|
"w-full " + (disabled ? "pointer-events-none cursor-not-allowed" : "")
|
||||||
|
}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
|
onFocus={() => {
|
||||||
|
if (disableCopyPaste) setDisableCopyPaste(true);
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
if (disableCopyPaste) setDisableCopyPaste(false);
|
||||||
|
}}
|
||||||
type="number"
|
type="number"
|
||||||
value={myValue}
|
value={myValue}
|
||||||
className={
|
className={
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,12 @@ import { TabsContext } from "../../contexts/tabsContext";
|
||||||
export default function IntComponent({
|
export default function IntComponent({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
disableCopyPaste = false,
|
||||||
disabled,
|
disabled,
|
||||||
}: FloatComponentType) {
|
}: FloatComponentType) {
|
||||||
const [myValue, setMyValue] = useState(value ?? "");
|
const [myValue, setMyValue] = useState(value ?? "");
|
||||||
|
const { setDisableCopyPaste } = useContext(TabsContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
setMyValue("");
|
setMyValue("");
|
||||||
|
|
@ -16,18 +19,32 @@ export default function IntComponent({
|
||||||
}, [disabled, onChange]);
|
}, [disabled, onChange]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={"w-full " + (
|
className={
|
||||||
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
|
"w-full " +
|
||||||
)}
|
(disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full")
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
onFocus={() => {
|
||||||
|
if (disableCopyPaste) setDisableCopyPaste(true);
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
if (disableCopyPaste) setDisableCopyPaste(false);
|
||||||
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
|
console.log(event);
|
||||||
if (
|
if (
|
||||||
event.key !== "Backspace" &&
|
event.key !== "Backspace" &&
|
||||||
event.key !== "Enter" &&
|
event.key !== "Enter" &&
|
||||||
event.key !== "Delete" &&
|
event.key !== "Delete" &&
|
||||||
event.key !== "ArrowLeft" &&
|
event.key !== "ArrowLeft" &&
|
||||||
event.key !== "ArrowRight" &&
|
event.key !== "ArrowRight" &&
|
||||||
|
event.key !== "Control" &&
|
||||||
|
event.key !== "Meta" &&
|
||||||
|
event.key !== "Shift" &&
|
||||||
|
event.key !== "c" &&
|
||||||
|
event.key !== "v" &&
|
||||||
|
event.key !== "a" &&
|
||||||
!/^[-]?\d*$/.test(event.key)
|
!/^[-]?\d*$/.test(event.key)
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
cookieObject.flows.forEach((flow) => {
|
cookieObject.flows.forEach((flow) => {
|
||||||
flow.data.edges.forEach((edge) => {
|
flow.data.edges.forEach((edge) => {
|
||||||
edge.className = "";
|
edge.className = "";
|
||||||
edge.style = { stroke: "#222222" };
|
edge.style = { stroke: "#555555" };
|
||||||
});
|
});
|
||||||
flow.data.nodes.forEach((node) => {
|
flow.data.nodes.forEach((node) => {
|
||||||
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
|
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
|
||||||
|
|
@ -285,7 +285,12 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
sourceHandle,
|
sourceHandle,
|
||||||
targetHandle,
|
targetHandle,
|
||||||
id,
|
id,
|
||||||
className: "animate-pulse",
|
style: { stroke: "inherit" },
|
||||||
|
className:
|
||||||
|
targetHandle.split("|")[0] === "Text"
|
||||||
|
? "stroke-gray-800 dark:stroke-gray-300"
|
||||||
|
: "stroke-gray-900 dark:stroke-gray-200",
|
||||||
|
animated: targetHandle.split("|")[0] === "Text",
|
||||||
selected: false,
|
selected: false,
|
||||||
},
|
},
|
||||||
edges.map((e) => ({ ...e, selected: false }))
|
edges.map((e) => ({ ...e, selected: false }))
|
||||||
|
|
@ -301,8 +306,12 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
const description = flow?.description ? flow.description : "";
|
const description = flow?.description ? flow.description : "";
|
||||||
if (data) {
|
if (data) {
|
||||||
data.edges.forEach((edge) => {
|
data.edges.forEach((edge) => {
|
||||||
edge.className = "";
|
edge.style = { stroke: "inherit" };
|
||||||
edge.style = { stroke: "#222222" };
|
edge.className =
|
||||||
|
edge.targetHandle.split("|")[0] === "Text"
|
||||||
|
? "stroke-gray-800 dark:stroke-gray-300"
|
||||||
|
: "stroke-gray-900 dark:stroke-gray-200";
|
||||||
|
edge.animated = edge.targetHandle.split("|")[0] === "Text";
|
||||||
});
|
});
|
||||||
data.nodes.forEach((node) => {
|
data.nodes.forEach((node) => {
|
||||||
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
|
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
|
||||||
|
|
|
||||||
|
|
@ -151,13 +151,12 @@ export default function ChatMessage({
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full flex items-center">
|
<div className="w-full flex items-center">
|
||||||
<div className="text-start inline-block px-3 text-sm text-gray-600 dark:text-white">
|
<div className="text-start inline-block px-3 text-sm text-gray-600 dark:text-white">
|
||||||
<ReactMarkdown
|
<span
|
||||||
remarkPlugins={[remarkGfm, remarkMath]}
|
className="text-gray-600 dark:text-gray-200"
|
||||||
rehypePlugins={[rehypeMathjax]}
|
dangerouslySetInnerHTML={{
|
||||||
className="markdown prose dark:prose-invert text-gray-600 dark:text-gray-200"
|
__html: message.replace(/\n/g, "<br>"),
|
||||||
>
|
}}
|
||||||
{message}
|
></span>
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ export default function ExportModal() {
|
||||||
as="h3"
|
as="h3"
|
||||||
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
|
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
|
||||||
>
|
>
|
||||||
Export as
|
Export
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ export default function ImportModal() {
|
||||||
as="h3"
|
as="h3"
|
||||||
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
|
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
|
||||||
>
|
>
|
||||||
{showExamples ? "Select an example" : "Import from"}
|
{showExamples ? "Select an example" : "Import"}
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { nodeColors, nodeIcons, nodeNames } from "../../../../utils";
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { typesContext } from "../../../../contexts/typesContext";
|
import { typesContext } from "../../../../contexts/typesContext";
|
||||||
import { APIClassType, APIObjectType } from "../../../../types/api";
|
import { APIClassType, APIObjectType } from "../../../../types/api";
|
||||||
import Tooltip from "../../../../components/TooltipComponent";
|
import TooltipReact from "../../../../components/ReactTooltipComponent";
|
||||||
|
|
||||||
export default function ExtraSidebar() {
|
export default function ExtraSidebar() {
|
||||||
const { data } = useContext(typesContext);
|
const { data } = useContext(typesContext);
|
||||||
|
|
@ -15,7 +15,9 @@ export default function ExtraSidebar() {
|
||||||
) {
|
) {
|
||||||
//start drag event
|
//start drag event
|
||||||
var crt = event.currentTarget.cloneNode(true);
|
var crt = event.currentTarget.cloneNode(true);
|
||||||
crt.style.position = "absolute"; crt.style.top = "-500px"; crt.style.right = "-500px";
|
crt.style.position = "absolute";
|
||||||
|
crt.style.top = "-500px";
|
||||||
|
crt.style.right = "-500px";
|
||||||
crt.classList.add("cursor-grabbing");
|
crt.classList.add("cursor-grabbing");
|
||||||
document.body.appendChild(crt);
|
document.body.appendChild(crt);
|
||||||
event.dataTransfer.setDragImage(crt, 0, 0);
|
event.dataTransfer.setDragImage(crt, 0, 0);
|
||||||
|
|
@ -38,8 +40,14 @@ export default function ExtraSidebar() {
|
||||||
{Object.keys(data[d])
|
{Object.keys(data[d])
|
||||||
.sort()
|
.sort()
|
||||||
.map((t: string, k) => (
|
.map((t: string, k) => (
|
||||||
<Tooltip title={t.length > 21 ? t : ""} placement="right">
|
<TooltipReact
|
||||||
<div key={k}>
|
selector={t}
|
||||||
|
htmlContent={t}
|
||||||
|
position="right"
|
||||||
|
delayShow={1500}
|
||||||
|
key={k}
|
||||||
|
>
|
||||||
|
<div key={k} data-tooltip-id={t}>
|
||||||
<div
|
<div
|
||||||
draggable
|
draggable
|
||||||
className={" cursor-grab border-l-8 rounded-l-md"}
|
className={" cursor-grab border-l-8 rounded-l-md"}
|
||||||
|
|
@ -54,7 +62,9 @@ export default function ExtraSidebar() {
|
||||||
}
|
}
|
||||||
onDragEnd={() => {
|
onDragEnd={() => {
|
||||||
document.body.removeChild(
|
document.body.removeChild(
|
||||||
document.getElementsByClassName("cursor-grabbing")[0]
|
document.getElementsByClassName(
|
||||||
|
"cursor-grabbing"
|
||||||
|
)[0]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -66,7 +76,7 @@ export default function ExtraSidebar() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</TooltipReact>
|
||||||
))}
|
))}
|
||||||
{Object.keys(data[d]).length === 0 && (
|
{Object.keys(data[d]).length === 0 && (
|
||||||
<div className="text-gray-400 text-center">Coming soon</div>
|
<div className="text-gray-400 text-center">Coming soon</div>
|
||||||
|
|
|
||||||
|
|
@ -151,10 +151,11 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
addEdge(
|
addEdge(
|
||||||
{
|
{
|
||||||
...params,
|
...params,
|
||||||
style:
|
style: { stroke: "inherit" },
|
||||||
|
className:
|
||||||
params.targetHandle.split("|")[0] === "Text"
|
params.targetHandle.split("|")[0] === "Text"
|
||||||
? { stroke: "#333333", strokeWidth: 2 }
|
? "stroke-gray-800 dark:stroke-gray-300"
|
||||||
: { stroke: "#222222" },
|
: "stroke-gray-900 dark:stroke-gray-200",
|
||||||
animated: params.targetHandle.split("|")[0] === "Text",
|
animated: params.targetHandle.split("|")[0] === "Text",
|
||||||
},
|
},
|
||||||
eds
|
eds
|
||||||
|
|
@ -323,6 +324,7 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChangeMod}
|
onEdgesChange={onEdgesChangeMod}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
|
disableKeyboardA11y={true}
|
||||||
onLoad={setReactFlowInstance}
|
onLoad={setReactFlowInstance}
|
||||||
onInit={setReactFlowInstance}
|
onInit={setReactFlowInstance}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
|
|
@ -339,6 +341,8 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
onDrop={onDrop}
|
onDrop={onDrop}
|
||||||
onNodesDelete={onDelete}
|
onNodesDelete={onDelete}
|
||||||
onSelectionChange={onSelectionChange}
|
onSelectionChange={onSelectionChange}
|
||||||
|
nodesDraggable={!disableCopyPaste}
|
||||||
|
panOnDrag={!disableCopyPaste}
|
||||||
selectNodesOnDrag={false}
|
selectNodesOnDrag={false}
|
||||||
>
|
>
|
||||||
<Background className="dark:bg-gray-900" />
|
<Background className="dark:bg-gray-900" />
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ export type DisclosureComponentType = {
|
||||||
export type FloatComponentType = {
|
export type FloatComponentType = {
|
||||||
value: string;
|
value: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
disableCopyPaste?: boolean;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue