merge fix
This commit is contained in:
commit
34f5a1300a
73 changed files with 2165 additions and 1531 deletions
|
|
@ -102,35 +102,46 @@ export default function App() {
|
|||
)}
|
||||
</ErrorBoundary>
|
||||
<div></div>
|
||||
<div className="app-div z-40">
|
||||
{tempNotificationList.map((alert) => (
|
||||
<div key={alert.id}>
|
||||
{alert.type === "error" ? (
|
||||
<ErrorAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
list={alert.list}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
) : alert.type === "notice" ? (
|
||||
<NoticeAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
link={alert.link}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
) : (
|
||||
<SuccessAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<div className="app-div">
|
||||
<div className="flex flex-col-reverse" style={{ zIndex: 999 }}>
|
||||
{tempNotificationList.map((alert) => (
|
||||
<div key={alert.id}>
|
||||
{alert.type === "error" && (
|
||||
<ErrorAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
list={alert.list}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="z-40 flex flex-col-reverse">
|
||||
{tempNotificationList.map((alert) => (
|
||||
<div key={alert.id}>
|
||||
{alert.type === "notice" ? (
|
||||
<NoticeAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
link={alert.link}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
) : (
|
||||
alert.type === "success" && (
|
||||
<SuccessAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { NodeToolbar } from "reactflow";
|
||||
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import InputComponent from "../../components/inputComponent";
|
||||
|
|
@ -9,6 +10,7 @@ import Loading from "../../components/ui/loading";
|
|||
import { Textarea } from "../../components/ui/textarea";
|
||||
import Xmark from "../../components/ui/xmark";
|
||||
import {
|
||||
NATIVE_CATEGORIES,
|
||||
RUN_TIMESTAMP_PREFIX,
|
||||
STATUS_BUILD,
|
||||
STATUS_BUILDING,
|
||||
|
|
@ -20,6 +22,7 @@ import { useDarkStore } from "../../stores/darkStore";
|
|||
import useFlowStore from "../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { useTypesStore } from "../../stores/typesStore";
|
||||
import { APIClassType } from "../../types/api";
|
||||
import { validationStatusType } from "../../types/components";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
|
||||
|
|
@ -39,10 +42,12 @@ export default function GenericNode({
|
|||
yPos: number;
|
||||
}): JSX.Element {
|
||||
const types = useTypesStore((state) => state.types);
|
||||
const templates = useTypesStore((state) => state.templates);
|
||||
const deleteNode = useFlowStore((state) => state.deleteNode);
|
||||
const flowPool = useFlowStore((state) => state.flowPool);
|
||||
const buildFlow = useFlowStore((state) => state.buildFlow);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
|
||||
const [inputName, setInputName] = useState(false);
|
||||
|
|
@ -51,6 +56,7 @@ export default function GenericNode({
|
|||
const [nodeDescription, setNodeDescription] = useState(
|
||||
data.node?.description!
|
||||
);
|
||||
const [isOutdated, setIsOutdated] = useState(false);
|
||||
const buildStatus = useFlowStore(
|
||||
(state) => state.flowBuildStatus[data.id]?.status
|
||||
);
|
||||
|
|
@ -65,6 +71,52 @@ export default function GenericNode({
|
|||
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
|
||||
useEffect(() => {
|
||||
// This one should run only once
|
||||
// first check if data.type in NATIVE_CATEGORIES
|
||||
// if not return
|
||||
if (
|
||||
!NATIVE_CATEGORIES.includes(types[data.type]) ||
|
||||
!data.node?.template?.code?.value
|
||||
)
|
||||
return;
|
||||
const thisNodeTemplate = templates[data.type].template;
|
||||
// if the template does not have a code key
|
||||
// return
|
||||
if (!thisNodeTemplate.code) return;
|
||||
const currentCode = thisNodeTemplate.code?.value;
|
||||
const thisNodesCode = data.node!.template?.code?.value;
|
||||
if (currentCode !== thisNodesCode) {
|
||||
setIsOutdated(true);
|
||||
} else {
|
||||
setIsOutdated(false);
|
||||
}
|
||||
// template.code can be undefined
|
||||
}, [data.node?.template?.code?.value]);
|
||||
|
||||
const updateNodeCode = useCallback(
|
||||
(newNodeClass: APIClassType, code: string, name: string) => {
|
||||
setNode(data.id, (oldNode) => {
|
||||
let newNode = cloneDeep(oldNode);
|
||||
|
||||
newNode.data = {
|
||||
...newNode.data,
|
||||
node: newNodeClass,
|
||||
description: newNodeClass.description ?? data.node!.description,
|
||||
display_name: newNodeClass.display_name ?? data.node!.display_name,
|
||||
};
|
||||
|
||||
newNode.data.node.template[name].value = code;
|
||||
setIsOutdated(false);
|
||||
|
||||
return newNode;
|
||||
});
|
||||
|
||||
updateNodeInternals(data.id);
|
||||
},
|
||||
[data.id, data.node, setNode, setIsOutdated]
|
||||
);
|
||||
|
||||
if (!data.node!.template) {
|
||||
setErrorData({
|
||||
title: `Error in component ${data.node!.display_name}`,
|
||||
|
|
@ -305,6 +357,8 @@ export default function GenericNode({
|
|||
showNode={showNode}
|
||||
openAdvancedModal={false}
|
||||
onCloseAdvancedModal={() => {}}
|
||||
updateNodeCode={updateNodeCode}
|
||||
isOutdated={isOutdated}
|
||||
selected={selected}
|
||||
></NodeToolbarComponent>
|
||||
</NodeToolbar>
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ export default function CodeTabsComponent({
|
|||
const dark = useDarkStore((state) => state.dark);
|
||||
const unselectAll = useFlowStore((state) => state.unselectAll);
|
||||
|
||||
const setNodes = useFlowStore((state) => state.setNodes);
|
||||
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import FlowSettingsModal from "../../../../modals/flowSettingsModal";
|
|||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
import { useStoreStore } from "../../../../stores/storeStore";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
import ShadTooltip from "../../../ShadTooltipComponent";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
|
|
@ -34,10 +33,8 @@ export const MenuBar = ({
|
|||
const redo = useFlowsManagerStore((state) => state.redo);
|
||||
const saveLoading = useFlowsManagerStore((state) => state.saveLoading);
|
||||
const [openSettings, setOpenSettings] = useState(false);
|
||||
const n = useFlowStore((state) => state.nodes);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
||||
const validApiKey = useStoreStore((state) => state.validApiKey);
|
||||
const navigate = useNavigate();
|
||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||
|
||||
|
|
@ -46,7 +43,6 @@ export const MenuBar = ({
|
|||
addFlow(true).then((id) => {
|
||||
navigate("/flow/" + id);
|
||||
});
|
||||
// saveFlowStyleInDataBase();
|
||||
} catch (err) {
|
||||
setErrorData(err as { title: string; list?: Array<string> });
|
||||
}
|
||||
|
|
@ -65,7 +61,7 @@ export const MenuBar = ({
|
|||
<div className="round-button-div">
|
||||
<button
|
||||
onClick={() => {
|
||||
removeFunction(n);
|
||||
removeFunction(nodes);
|
||||
navigate(-1);
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export default function Header(): JSX.Element {
|
|||
const removeFlow = useFlowsManagerStore((store) => store.removeFlow);
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
const { id } = useParams();
|
||||
const n = useFlowStore((state) => state.nodes);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
|
||||
const dark = useDarkStore((state) => state.dark);
|
||||
const setDark = useDarkStore((state) => state.setDark);
|
||||
|
|
@ -57,7 +57,7 @@ export default function Header(): JSX.Element {
|
|||
return (
|
||||
<div className="header-arrangement">
|
||||
<div className="header-start-display lg:w-[30%]">
|
||||
<Link to="/" onClick={() => checkForChanges(n)}>
|
||||
<Link to="/" onClick={() => checkForChanges(nodes)}>
|
||||
<span className="ml-4 text-2xl">⛓️</span>
|
||||
</Link>
|
||||
<MenuBar removeFunction={checkForChanges} />
|
||||
|
|
@ -74,7 +74,7 @@ export default function Header(): JSX.Element {
|
|||
}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
checkForChanges(n);
|
||||
checkForChanges(nodes);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Home" className="h-4 w-4" />
|
||||
|
|
@ -100,7 +100,7 @@ export default function Header(): JSX.Element {
|
|||
variant={location.pathname === "/store" ? "primary" : "secondary"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
checkForChanges(n);
|
||||
checkForChanges(nodes);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Store" className="h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const DialogContent = React.forwardRef<
|
|||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 flex w-full max-w-lg translate-x-[-50%] translate-y-[-50%] flex-col 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-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
|
||||
"fixed z-50 flex w-full max-w-lg flex-col 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-left-1/2 data-[state=closed]:slide-out-to-top-[48%] sm:rounded-lg md:w-full",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ export default function RenameLabel(props) {
|
|||
}
|
||||
}
|
||||
resizeInput();
|
||||
return () => {
|
||||
if(isRename) document.removeEventListener("keydown", () => {});
|
||||
};
|
||||
}, [isRename]);
|
||||
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const COMPONENTS_ERROR_ALERT = "Error getting components.";
|
|||
|
||||
// NOTICE
|
||||
export const NOCHATOUTPUT_NOTICE_ALERT =
|
||||
"There is no ChatOutput node in the flow.";
|
||||
"There is no ChatOutput Component in the flow.";
|
||||
export const API_WARNING_NOTICE_ALERT =
|
||||
"Warning: Critical data, JSON file may include API keys.";
|
||||
export const COPIED_NOTICE_ALERT = "API Key copied!";
|
||||
|
|
|
|||
|
|
@ -740,6 +740,16 @@ export const PRIORITY_SIDEBAR_ORDER = [
|
|||
"helpers",
|
||||
"experimental",
|
||||
];
|
||||
export const NATIVE_CATEGORIES = [
|
||||
"inputs",
|
||||
"outputs",
|
||||
"prompts",
|
||||
"data",
|
||||
"prompt",
|
||||
"models",
|
||||
"helpers",
|
||||
"experimental",
|
||||
];
|
||||
/*
|
||||
Data ingestion
|
||||
Basic Prompting
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import axios, { AxiosError, AxiosInstance } from "axios";
|
||||
import { useContext, useEffect } from "react";
|
||||
import { Cookies } from "react-cookie";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { renewAccessToken } from ".";
|
||||
import { BuildStatus } from "../../constants/enums";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
|
|
@ -17,26 +16,28 @@ function ApiInterceptor() {
|
|||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
let { accessToken, login, logout, authenticationErrorCount, autoLogin } =
|
||||
useContext(AuthContext);
|
||||
const navigate = useNavigate();
|
||||
const cookies = new Cookies();
|
||||
|
||||
useEffect(() => {
|
||||
const interceptor = api.interceptors.response.use(
|
||||
(response) => response,
|
||||
async (error: AxiosError) => {
|
||||
if (error.response?.status === 401) {
|
||||
const accessToken = cookies.get("access_token_lf");
|
||||
if (error.response?.status === 403 || error.response?.status === 401) {
|
||||
if (!autoLogin) {
|
||||
const stillRefresh = checkErrorCount();
|
||||
if (!stillRefresh) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
const acceptedRequest = await tryToRenewAccessToken(error);
|
||||
|
||||
if (accessToken && !autoLogin) {
|
||||
checkErrorCount();
|
||||
await tryToRenewAccessToken(error);
|
||||
const accessToken = cookies.get("access_token_lf");
|
||||
|
||||
if (!accessToken && error?.config?.url?.includes("login")) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
return acceptedRequest;
|
||||
}
|
||||
|
||||
if (!accessToken && error?.config?.url?.includes("login")) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
return logout();
|
||||
}
|
||||
await clearBuildVerticesState(error);
|
||||
return Promise.reject(error);
|
||||
|
|
@ -98,11 +99,15 @@ function ApiInterceptor() {
|
|||
if (authenticationErrorCount > 3) {
|
||||
authenticationErrorCount = 0;
|
||||
logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function tryToRenewAccessToken(error: AxiosError) {
|
||||
try {
|
||||
if (window.location.pathname.includes("/login")) return;
|
||||
const res = await renewAccessToken();
|
||||
if (res?.data?.access_token && res?.data?.refresh_token) {
|
||||
login(res?.data?.access_token);
|
||||
|
|
@ -116,7 +121,9 @@ function ApiInterceptor() {
|
|||
return response;
|
||||
}
|
||||
} catch (error) {
|
||||
clearBuildVerticesState(error);
|
||||
logout();
|
||||
return Promise.reject("Authentication error");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { BASE_URL_API } from "../../constants/constants";
|
|||
import { api } from "../../controllers/API/api";
|
||||
import {
|
||||
APIObjectType,
|
||||
APITemplateType,
|
||||
Component,
|
||||
LoginType,
|
||||
Users,
|
||||
|
|
@ -369,11 +370,13 @@ export async function postCustomComponent(
|
|||
|
||||
export async function postCustomComponentUpdate(
|
||||
code: string,
|
||||
template: APITemplateType,
|
||||
field: string,
|
||||
field_value: any
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
return await api.post(`${BASE_URL_API}custom_component/update`, {
|
||||
code,
|
||||
template,
|
||||
field,
|
||||
field_value,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const SvgBotMessageSquare = (props) => (
|
|||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-bot-message-square"
|
||||
className="lucide lucide-bot-message-square"
|
||||
{...props}
|
||||
>
|
||||
<path d="M12 6V2H8" />
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import {
|
|||
import { postCustomComponent, postValidateCode } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import { CodeErrorDataTypeAPI } from "../../types/api";
|
||||
import { codeAreaModalPropsType } from "../../types/components";
|
||||
import BaseModal from "../baseModal";
|
||||
|
|
@ -45,14 +44,12 @@ export default function CodeAreaModal({
|
|||
? [myOpen, mySetOpen]
|
||||
: useState(false);
|
||||
const dark = useDarkStore((state) => state.dark);
|
||||
const unselectAll = useFlowStore((state) => state.unselectAll);
|
||||
const [height, setHeight] = useState<string | null>(null);
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const [error, setError] = useState<{
|
||||
detail: CodeErrorDataTypeAPI;
|
||||
} | null>(null);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
|
||||
useEffect(() => {
|
||||
// if nodeClass.template has more fields other than code and dynamic is true
|
||||
|
|
|
|||
|
|
@ -250,10 +250,20 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
setSearch(event.target.value);
|
||||
}}
|
||||
/>
|
||||
<div className="search-icon">
|
||||
<div
|
||||
className="search-icon "
|
||||
onClick={() => {
|
||||
if (search) {
|
||||
setFilterData(data);
|
||||
setSearch("");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Search"
|
||||
className={"h-5 w-5 stroke-[1.5] text-primary"}
|
||||
name={search ? "X" : "Search"}
|
||||
className={`h-5 w-5 stroke-[1.5] text-primary ${
|
||||
search ? "cursor-pointer" : "cursor-default"
|
||||
}`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "../../../../components/ui/select-custom";
|
||||
import { postCustomComponent } from "../../../../controllers/API";
|
||||
import ConfirmationModal from "../../../../modals/ConfirmationModal";
|
||||
import EditNodeModal from "../../../../modals/EditNodeModal";
|
||||
import ShareModal from "../../../../modals/shareModal";
|
||||
|
|
@ -18,6 +19,7 @@ import { useDarkStore } from "../../../../stores/darkStore";
|
|||
import useFlowStore from "../../../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
import { useStoreStore } from "../../../../stores/storeStore";
|
||||
import { useTypesStore } from "../../../../stores/typesStore";
|
||||
import { APIClassType } from "../../../../types/api";
|
||||
import { nodeToolbarPropsType } from "../../../../types/components";
|
||||
import { FlowType } from "../../../../types/flow";
|
||||
|
|
@ -28,6 +30,7 @@ import {
|
|||
updateFlowPosition,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { classNames, cn } from "../../../../utils/utils";
|
||||
import ToolbarSelectItem from "./toolbarSelectItem";
|
||||
|
||||
export default function NodeToolbarComponent({
|
||||
data,
|
||||
|
|
@ -38,8 +41,10 @@ export default function NodeToolbarComponent({
|
|||
showNode,
|
||||
name = "code",
|
||||
selected,
|
||||
updateNodeCode,
|
||||
setShowState,
|
||||
onCloseAdvancedModal,
|
||||
isOutdated,
|
||||
}: nodeToolbarPropsType): JSX.Element {
|
||||
const nodeLength = Object.keys(data.node!.template).filter(
|
||||
(templateField) =>
|
||||
|
|
@ -56,7 +61,7 @@ export default function NodeToolbarComponent({
|
|||
data.node.template[templateField].type === "dict" ||
|
||||
data.node.template[templateField].type === "NestedDict")
|
||||
).length;
|
||||
|
||||
const templates = useTypesStore((state) => state.templates);
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
||||
const validApiKey = useStoreStore((state) => state.validApiKey);
|
||||
|
|
@ -70,6 +75,7 @@ export default function NodeToolbarComponent({
|
|||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
const setNodes = useFlowStore((state) => state.setNodes);
|
||||
|
||||
const setEdges = useFlowStore((state) => state.setEdges);
|
||||
const unselectAll = useFlowStore((state) => state.unselectAll);
|
||||
const saveComponent = useFlowsManagerStore((state) => state.saveComponent);
|
||||
|
|
@ -79,7 +85,6 @@ export default function NodeToolbarComponent({
|
|||
const [showModalAdvanced, setShowModalAdvanced] = useState(false);
|
||||
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
||||
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
||||
|
||||
const [flowComponent, setFlowComponent] = useState<FlowType>();
|
||||
|
||||
const openInNewTab = (url) => {
|
||||
|
|
@ -170,6 +175,37 @@ export default function NodeToolbarComponent({
|
|||
paneY: nodes.find((node) => node.id === data.id)?.position.y,
|
||||
}
|
||||
);
|
||||
break;
|
||||
case "update":
|
||||
takeSnapshot();
|
||||
// to update we must get the code from the templates in useTypesStore
|
||||
const thisNodeTemplate = templates[data.type].template;
|
||||
// if the template does not have a code key
|
||||
// return
|
||||
if (!thisNodeTemplate.code) return;
|
||||
|
||||
const currentCode = thisNodeTemplate.code.value;
|
||||
if (data.node) {
|
||||
postCustomComponent(currentCode, data.node)
|
||||
.then((apiReturn) => {
|
||||
const { data } = apiReturn;
|
||||
if (data && updateNodeCode) {
|
||||
updateNodeCode(data, currentCode, "code");
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
setNode(data.id, (oldNode) => {
|
||||
let newNode = cloneDeep(oldNode);
|
||||
newNode.data = {
|
||||
...data,
|
||||
};
|
||||
newNode.data.node.template.code.value = currentCode;
|
||||
return newNode;
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
|
@ -411,93 +447,59 @@ export default function NodeToolbarComponent({
|
|||
<SelectContent>
|
||||
{nodeLength > 0 && (
|
||||
<SelectItem value={nodeLength === 0 ? "disabled" : "advanced"}>
|
||||
<div className="flex" data-testid="edit-button-modal">
|
||||
<IconComponent
|
||||
name="Settings2"
|
||||
className="relative top-0.5 mr-2 h-4 w-4 "
|
||||
/>{" "}
|
||||
<span className="">Edit</span>{" "}
|
||||
{navigator.userAgent.toUpperCase().includes("MAC") ? (
|
||||
<IconComponent
|
||||
name="Command"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
) : (
|
||||
<span className="absolute right-[1.15rem] top-[0.40em] stroke-2">
|
||||
Ctrl +{" "}
|
||||
</span>
|
||||
)}
|
||||
<span className="absolute right-2 top-[0.46em]">E</span>
|
||||
</div>
|
||||
<ToolbarSelectItem
|
||||
keyboardKey="E"
|
||||
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
|
||||
shift={false}
|
||||
value={"Edit"}
|
||||
icon={"Settings2"}
|
||||
/>
|
||||
</SelectItem>
|
||||
)}
|
||||
<SelectItem value={"duplicate"}>
|
||||
<div className="flex" data-testid="duplicate-button-modal">
|
||||
<IconComponent
|
||||
name="Copy"
|
||||
className="relative top-0.5 mr-2 h-4 w-4"
|
||||
/>
|
||||
Duplicate
|
||||
{navigator.userAgent.toUpperCase().includes("MAC") ? (
|
||||
<IconComponent
|
||||
name="Command"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
) : (
|
||||
<span className="absolute right-[1.20rem] top-[0.40em] stroke-2">
|
||||
Ctrl +{" "}
|
||||
</span>
|
||||
)}
|
||||
<span className="absolute right-2 top-[0.4em]">D</span>
|
||||
</div>{" "}
|
||||
<ToolbarSelectItem
|
||||
keyboardKey="D"
|
||||
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
|
||||
shift={false}
|
||||
value={"Duplicate"}
|
||||
icon={"Copy"}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectItem value={"copy"}>
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name="Clipboard"
|
||||
className="relative top-0.5 mr-2 h-4 w-4 "
|
||||
/>{" "}
|
||||
<span className="">Copy</span>{" "}
|
||||
{navigator.userAgent.toUpperCase().includes("MAC") ? (
|
||||
<IconComponent
|
||||
name="Command"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
) : (
|
||||
<span className="absolute right-[1.15rem] top-[0.40em] stroke-2">
|
||||
Ctrl +{" "}
|
||||
</span>
|
||||
)}
|
||||
<span className="absolute right-2 top-[0.4em]">C</span>
|
||||
</div>
|
||||
<ToolbarSelectItem
|
||||
keyboardKey="C"
|
||||
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
|
||||
shift={false}
|
||||
value={"Copy"}
|
||||
icon={"Clipboard"}
|
||||
/>
|
||||
</SelectItem>
|
||||
{isOutdated && (
|
||||
<SelectItem value={"update"}>
|
||||
<ToolbarSelectItem
|
||||
keyboardKey="U"
|
||||
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
|
||||
shift={false}
|
||||
value={"Update"}
|
||||
icon={"Code"}
|
||||
/>
|
||||
</SelectItem>
|
||||
)}
|
||||
{hasStore && (
|
||||
<SelectItem
|
||||
value={"Share"}
|
||||
disabled={!hasApiKey || !validApiKey}
|
||||
>
|
||||
<div className="flex" data-testid="share-button-modal">
|
||||
<IconComponent
|
||||
name="Share3"
|
||||
className="relative top-0.5 -m-1 mr-1 h-6 w-6"
|
||||
/>{" "}
|
||||
Share{" "}
|
||||
{navigator.userAgent.toUpperCase().includes("MAC") ? (
|
||||
<IconComponent
|
||||
name="Command"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
) : (
|
||||
<span className="absolute right-[2.10rem] top-[0.43em] stroke-2">
|
||||
Ctrl
|
||||
</span>
|
||||
)}
|
||||
<IconComponent
|
||||
name="ArrowBigUp"
|
||||
className="absolute right-[1.09rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
<span className="absolute right-2 top-[0.45em]">S</span>
|
||||
</div>{" "}
|
||||
<ToolbarSelectItem
|
||||
keyboardKey="S"
|
||||
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
|
||||
shift={true}
|
||||
value={"Share"}
|
||||
icon={"Share3"}
|
||||
styleObj={{
|
||||
iconClasses: "relative top-0.5 -m-1 mr-1 h-6 w-6",
|
||||
}}
|
||||
/>
|
||||
</SelectItem>
|
||||
)}
|
||||
{!hasStore && (
|
||||
|
|
@ -515,28 +517,13 @@ export default function NodeToolbarComponent({
|
|||
value={"documentation"}
|
||||
disabled={data.node?.documentation === ""}
|
||||
>
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name="FileText"
|
||||
className="relative top-0.5 mr-2 h-4 w-4 "
|
||||
/>{" "}
|
||||
<span className="">Docs</span>{" "}
|
||||
{navigator.userAgent.toUpperCase().includes("MAC") ? (
|
||||
<IconComponent
|
||||
name="Command"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
) : (
|
||||
<span className="absolute right-[2.10rem] top-[0.43em] stroke-2">
|
||||
Ctrl
|
||||
</span>
|
||||
)}
|
||||
<IconComponent
|
||||
name="ArrowBigUp"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
<span className="absolute right-2 top-[0.43em]">D</span>
|
||||
</div>
|
||||
<ToolbarSelectItem
|
||||
keyboardKey="D"
|
||||
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
|
||||
shift={true}
|
||||
value={"Docs"}
|
||||
icon={"FileText"}
|
||||
/>
|
||||
</SelectItem>
|
||||
{isMinimal && (
|
||||
<SelectItem value={"show"}>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import { useEffect } from "react";
|
||||
import ForwardedIconComponent from "../../../../../components/genericIconComponent";
|
||||
import { toolbarSelectItemProps } from "../../../../../types/components";
|
||||
|
||||
export default function ToolbarSelectItem({
|
||||
shift,
|
||||
isMac,
|
||||
keyboardKey,
|
||||
value,
|
||||
icon,
|
||||
styleObj,
|
||||
}: toolbarSelectItemProps) {
|
||||
|
||||
return (
|
||||
<div className="flex">
|
||||
<ForwardedIconComponent
|
||||
name={icon}
|
||||
className={`relative top-0.5 mr-2 h-4 w-4 ${styleObj?.iconClasses}`}
|
||||
/>{" "}
|
||||
<span className={styleObj?.valueClasses}>{value}</span>{" "}
|
||||
{isMac ? (
|
||||
<ForwardedIconComponent
|
||||
name="Command"
|
||||
className={`absolute right-[${shift ? "2rem" : "1.15rem"}] top-[0.65em] h-3.5 w-3.5 stroke-2 ${styleObj?.commandClasses}`}
|
||||
></ForwardedIconComponent>
|
||||
) : (
|
||||
<span className={`absolute right-[${shift ? "2.10rem" : "1.15rem"}] top-[0.43em] stroke-2 ${styleObj?.ctrlClasses}`}>
|
||||
{shift ? (
|
||||
"Ctrl"
|
||||
) : (
|
||||
"Ctrl +"
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{shift && (
|
||||
<ForwardedIconComponent
|
||||
name="ArrowBigUp"
|
||||
className={`absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2 ${styleObj?.shiftClasses}`}
|
||||
/>
|
||||
)}
|
||||
<span className={`absolute right-2 top-[0.43em] ${styleObj?.keyClasses}`}>{keyboardKey}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ export default function StorePage(): JSX.Element {
|
|||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response.status === 403 || err.response.status === 401) {
|
||||
if (err.response?.status === 403 || err.response?.status === 401) {
|
||||
setValidApiKey(false);
|
||||
} else {
|
||||
setSearchData([]);
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@
|
|||
}
|
||||
|
||||
.app-div {
|
||||
@apply fixed bottom-5 left-5 flex flex-col-reverse;
|
||||
@apply absolute bottom-5 left-5 flex flex-col-reverse;
|
||||
}
|
||||
|
||||
.chat-input-modal-txtarea {
|
||||
|
|
|
|||
|
|
@ -491,7 +491,13 @@ export type nodeToolbarPropsType = {
|
|||
openAdvancedModal?: boolean;
|
||||
onCloseAdvancedModal?: (close: boolean) => void;
|
||||
selected: boolean;
|
||||
updateNodeCode?: (
|
||||
newNodeClass: APIClassType,
|
||||
code: string,
|
||||
name: string
|
||||
) => void;
|
||||
setShowState: (show: boolean | SetStateAction<boolean>) => void;
|
||||
isOutdated?: boolean;
|
||||
};
|
||||
|
||||
export type parsedDataType = {
|
||||
|
|
@ -682,3 +688,19 @@ export type IOFileInputProps = {
|
|||
field: TemplateVariableType;
|
||||
updateValue: (e: any, type: string) => void;
|
||||
};
|
||||
|
||||
export type toolbarSelectItemProps = {
|
||||
isMac: boolean;
|
||||
shift: boolean;
|
||||
keyboardKey: string;
|
||||
value: string;
|
||||
icon: string;
|
||||
styleObj?: {
|
||||
iconClasses?: string;
|
||||
commandClasses?: string;
|
||||
shiftClasses?: string;
|
||||
ctrlClasses?: string;
|
||||
keyClasses?: string;
|
||||
valueClasses?: string;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,9 +9,15 @@ export const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
|||
console.error("Code not found in the template");
|
||||
return;
|
||||
}
|
||||
const template = data.node?.template;
|
||||
if (!template) {
|
||||
console.error("No template found in the node.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let newTemplate = await postCustomComponentUpdate(
|
||||
code,
|
||||
template,
|
||||
name,
|
||||
data.node?.template[name]?.value
|
||||
)
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ export function buildTweaks(flow: FlowType) {
|
|||
export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
||||
if (!node.data?.node?.template || !Object.keys(node.data.node.template)) {
|
||||
return [
|
||||
"We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!",
|
||||
"We've noticed a potential issue with a Component in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!",
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ export const nodeNames: { [char: string]: string } = {
|
|||
};
|
||||
|
||||
export const nodeIconsLucide: iconsType = {
|
||||
X: X,
|
||||
Notify: Bell,
|
||||
ListFlows: Group,
|
||||
ClearMessageHistory: FileClock,
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ export function getCurlCode(
|
|||
-H 'Content-Type: application/json'\\${
|
||||
!isAuth ? `\n -H 'x-api-key: <your api key>'\\` : ""
|
||||
}
|
||||
-d '{"inputs": ${inputs}, "tweaks": ${
|
||||
-d '{"inputs": [${inputs}], "tweaks": ${
|
||||
tweak && tweak.length > 0
|
||||
? buildTweakObject(tweak)
|
||||
: JSON.stringify(tweaks, null, 2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue