Merge branch 'fix/minor_bugs' into fix/api_settings
This commit is contained in:
commit
ed845f5eb5
30 changed files with 1123 additions and 834 deletions
6
src/frontend/package-lock.json
generated
6
src/frontend/package-lock.json
generated
|
|
@ -40,6 +40,7 @@
|
|||
"class-variance-authority": "^0.6.1",
|
||||
"clsx": "^1.2.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"debounce-promise": "^3.1.2",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.17.19",
|
||||
|
|
@ -5670,6 +5671,11 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/debounce-promise": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/debounce-promise/-/debounce-promise-3.1.2.tgz",
|
||||
"integrity": "sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
"class-variance-authority": "^0.6.1",
|
||||
"clsx": "^1.2.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"debounce-promise": "^3.1.2",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.17.19",
|
||||
|
|
|
|||
|
|
@ -222,12 +222,19 @@ export default function App() {
|
|||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
) : alert.type === "notice" ? (
|
||||
<NoticeAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
link={alert.link}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
) : (
|
||||
alert.type === "notice" && (
|
||||
<NoticeAlert
|
||||
alert.type === "success" && (
|
||||
<SuccessAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
link={alert.link}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
|
|
@ -236,20 +243,6 @@ export default function App() {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="z-40 flex flex-col-reverse">
|
||||
{tempNotificationList.map((alert) => (
|
||||
<div key={alert.id}>
|
||||
{alert.type === "success" && (
|
||||
<SuccessAlert
|
||||
key={alert.id}
|
||||
title={alert.title}
|
||||
id={alert.id}
|
||||
removeAlert={removeAlert}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ export default function IOModal({
|
|||
await buildFlow({
|
||||
input_value: chatValue,
|
||||
startNodeId: chatInput?.id,
|
||||
silent: true,
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
setLockChat(false);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
export const switchCaseModalSize = (size: string) => {
|
||||
let minWidth: string;
|
||||
let height: string;
|
||||
switch (size) {
|
||||
case "x-small":
|
||||
minWidth = "min-w-[20vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
case "smaller":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-[11rem]";
|
||||
break;
|
||||
case "smaller-h-full":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
case "small":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-[40vh]";
|
||||
break;
|
||||
case "small-h-full":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
case "medium":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-[60vh]";
|
||||
break;
|
||||
case "medium-h-full":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-full";
|
||||
|
||||
break;
|
||||
case "large":
|
||||
minWidth = "min-w-[85vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
case "three-cards":
|
||||
minWidth = "min-w-[1066px]";
|
||||
height = "h-fit";
|
||||
break;
|
||||
case "large-thin":
|
||||
minWidth = "min-w-[65vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
|
||||
case "md-thin":
|
||||
minWidth = "min-w-[85vw]";
|
||||
height = "h-[70vh]";
|
||||
break;
|
||||
|
||||
case "sm-thin":
|
||||
minWidth = "min-w-[65vw]";
|
||||
height = "h-[70vh]";
|
||||
break;
|
||||
|
||||
case "large-h-full":
|
||||
minWidth = "min-w-[80vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
default:
|
||||
minWidth = "min-w-[80vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
}
|
||||
return { minWidth, height };
|
||||
};
|
||||
|
|
@ -16,10 +16,10 @@ import {
|
|||
} from "../../components/ui/dialog-with-no-close";
|
||||
|
||||
import { DialogClose } from "@radix-ui/react-dialog";
|
||||
import ForwardedIconComponent from "../../components/genericIconComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { modalHeaderType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import { switchCaseModalSize } from "./helpers/switch-case-size";
|
||||
import * as Form from "@radix-ui/react-form";
|
||||
|
||||
type ContentProps = { children: ReactNode };
|
||||
|
|
@ -149,71 +149,7 @@ function BaseModal({
|
|||
(child) => (child as React.ReactElement).type === Footer,
|
||||
);
|
||||
|
||||
let minWidth: string;
|
||||
let height: string;
|
||||
|
||||
switch (size) {
|
||||
case "x-small":
|
||||
minWidth = "min-w-[20vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
case "smaller":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-[11rem]";
|
||||
break;
|
||||
case "smaller-h-full":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
case "small":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-[40vh]";
|
||||
break;
|
||||
case "small-h-full":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
case "medium":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-[60vh]";
|
||||
break;
|
||||
case "medium-h-full":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-full";
|
||||
|
||||
break;
|
||||
case "large":
|
||||
minWidth = "min-w-[85vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
case "three-cards":
|
||||
minWidth = "min-w-[1066px]";
|
||||
height = "h-fit";
|
||||
break;
|
||||
case "large-thin":
|
||||
minWidth = "min-w-[65vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
|
||||
case "md-thin":
|
||||
minWidth = "min-w-[85vw]";
|
||||
height = "h-[70vh]";
|
||||
break;
|
||||
|
||||
case "sm-thin":
|
||||
minWidth = "min-w-[65vw]";
|
||||
height = "h-[70vh]";
|
||||
break;
|
||||
|
||||
case "large-h-full":
|
||||
minWidth = "min-w-[80vw]";
|
||||
height = "h-full";
|
||||
break;
|
||||
default:
|
||||
minWidth = "min-w-[80vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
}
|
||||
let { minWidth, height } = switchCaseModalSize(size);
|
||||
|
||||
useEffect(() => {
|
||||
if (onChangeOpenModal) {
|
||||
|
|
|
|||
|
|
@ -16,41 +16,15 @@ export default function FlowLogsModal({
|
|||
open,
|
||||
setOpen,
|
||||
}: FlowSettingsPropsType): JSX.Element {
|
||||
const saveFlow = useFlowsManagerStore((state) => state.saveFlow);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const setNoticeData = useAlertStore((state) => state.setNoticeData);
|
||||
|
||||
useEffect(() => {
|
||||
setName(currentFlow!.name);
|
||||
setDescription(currentFlow!.description);
|
||||
}, [currentFlow!.name, currentFlow!.description, open]);
|
||||
|
||||
const [name, setName] = useState(currentFlow!.name);
|
||||
const [description, setDescription] = useState(currentFlow!.description);
|
||||
const [columns, setColumns] = useState<Array<ColDef | ColGroupDef>>([]);
|
||||
const [rows, setRows] = useState<any>([]);
|
||||
const [activeTab, setActiveTab] = useState("Executions");
|
||||
const noticed = useRef(false);
|
||||
|
||||
function handleClick(): void {
|
||||
currentFlow!.name = name;
|
||||
currentFlow!.description = description;
|
||||
saveFlow(currentFlow!)
|
||||
?.then(() => {
|
||||
setOpen(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
useAlertStore.getState().setErrorData({
|
||||
title: "Error while saving changes",
|
||||
list: [(err as AxiosError).response?.data.detail ?? ""],
|
||||
});
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (activeTab === "Executions") {
|
||||
getTransactionTable(currentFlowId, "union").then((data) => {
|
||||
|
|
@ -86,16 +60,6 @@ export default function FlowLogsModal({
|
|||
}
|
||||
}, [open, activeTab]);
|
||||
|
||||
const [nameLists, setNameList] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const tempNameList: string[] = [];
|
||||
flows.forEach((flow: FlowType) => {
|
||||
if ((flow.is_component ?? false) === false) tempNameList.push(flow.name);
|
||||
});
|
||||
setNameList(tempNameList.filter((name) => name !== currentFlow!.name));
|
||||
}, [flows]);
|
||||
|
||||
return (
|
||||
<BaseModal open={open} setOpen={setOpen} size="large">
|
||||
<BaseModal.Header description="Inspect component executions and monitor sent messages in the playground.">
|
||||
|
|
|
|||
|
|
@ -23,14 +23,16 @@ export default function FlowSettingsModal({
|
|||
const [name, setName] = useState(currentFlow!.name);
|
||||
const [description, setDescription] = useState(currentFlow!.description);
|
||||
const [endpoint_name, setEndpointName] = useState(currentFlow!.endpoint_name);
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
function handleClick(): void {
|
||||
setIsSaving(true);
|
||||
currentFlow!.name = name;
|
||||
currentFlow!.description = description;
|
||||
currentFlow!.endpoint_name = endpoint_name;
|
||||
saveFlow(currentFlow!)
|
||||
?.then(() => {
|
||||
setOpen(false);
|
||||
setIsSaving(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
useAlertStore.getState().setErrorData({
|
||||
|
|
@ -79,6 +81,7 @@ export default function FlowSettingsModal({
|
|||
label: "Save",
|
||||
disabled: nameLists.includes(name) && name !== currentFlow!.name,
|
||||
dataTestId: "save-flow-settings",
|
||||
loading: isSaving,
|
||||
}}
|
||||
/>
|
||||
</BaseModal>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
||||
|
||||
const GeneralPageHeaderComponent = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
|
||||
<div className="flex w-full flex-col">
|
||||
<h2 className="flex items-center text-lg font-semibold tracking-tight">
|
||||
General
|
||||
<ForwardedIconComponent
|
||||
name="SlidersHorizontal"
|
||||
className="ml-2 h-5 w-5 text-primary"
|
||||
/>
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Manage settings related to Langflow and your account.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default GeneralPageHeaderComponent;
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
import * as Form from "@radix-ui/react-form";
|
||||
import InputComponent from "../../../../../../components/inputComponent";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../../../../components/ui/card";
|
||||
|
||||
type PasswordFormComponentProps = {
|
||||
password: string;
|
||||
cnfPassword: string;
|
||||
handleInput: (event: any) => void;
|
||||
handlePatchPassword: (
|
||||
password: string,
|
||||
cnfPassword: string,
|
||||
handleInput: any,
|
||||
) => void;
|
||||
};
|
||||
const PasswordFormComponent = ({
|
||||
password,
|
||||
cnfPassword,
|
||||
handleInput,
|
||||
handlePatchPassword,
|
||||
}: PasswordFormComponentProps) => {
|
||||
return (
|
||||
<>
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
handlePatchPassword(password, cnfPassword, handleInput);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Card x-chunk="dashboard-04-chunk-2">
|
||||
<CardHeader>
|
||||
<CardTitle>Password</CardTitle>
|
||||
<CardDescription>
|
||||
Type your new password and confirm it.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex w-full gap-4">
|
||||
<Form.Field name="password" className="w-full">
|
||||
<InputComponent
|
||||
id="pasword"
|
||||
onChange={(value) => {
|
||||
handleInput({ target: { name: "password", value } });
|
||||
}}
|
||||
value={password}
|
||||
isForm
|
||||
password={true}
|
||||
placeholder="Password"
|
||||
className="w-full"
|
||||
/>
|
||||
<Form.Message match="valueMissing" className="field-invalid">
|
||||
Please enter your password
|
||||
</Form.Message>
|
||||
</Form.Field>
|
||||
<Form.Field name="cnfPassword" className="w-full">
|
||||
<InputComponent
|
||||
id="cnfPassword"
|
||||
onChange={(value) => {
|
||||
handleInput({
|
||||
target: { name: "cnfPassword", value },
|
||||
});
|
||||
}}
|
||||
value={cnfPassword}
|
||||
isForm
|
||||
password={true}
|
||||
placeholder="Confirm Password"
|
||||
className="w-full"
|
||||
/>
|
||||
|
||||
<Form.Message className="field-invalid" match="valueMissing">
|
||||
Please confirm your password
|
||||
</Form.Message>
|
||||
</Form.Field>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Form.Submit asChild>
|
||||
<Button type="submit">Save</Button>
|
||||
</Form.Submit>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Form.Root>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default PasswordFormComponent;
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
import * as Form from "@radix-ui/react-form";
|
||||
import GradientChooserComponent from "../../../../../../components/gradientChooserComponent";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../../../../components/ui/card";
|
||||
import { gradients } from "../../../../../../utils/styleUtils";
|
||||
|
||||
type ProfileGradientFormComponentProps = {
|
||||
gradient: string;
|
||||
handleInput: (event: any) => void;
|
||||
handlePatchGradient: (gradient: string) => void;
|
||||
userData: any;
|
||||
};
|
||||
const ProfileGradientFormComponent = ({
|
||||
gradient,
|
||||
handleInput,
|
||||
handlePatchGradient,
|
||||
userData,
|
||||
}: ProfileGradientFormComponentProps) => {
|
||||
return (
|
||||
<>
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
handlePatchGradient(gradient);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Card x-chunk="dashboard-04-chunk-1">
|
||||
<CardHeader>
|
||||
<CardTitle>Profile Gradient</CardTitle>
|
||||
<CardDescription>
|
||||
Choose the gradient that appears as your profile picture.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="py-2">
|
||||
<GradientChooserComponent
|
||||
value={
|
||||
gradient == ""
|
||||
? userData?.profile_image ??
|
||||
gradients[
|
||||
parseInt(userData?.id ?? "", 30) % gradients.length
|
||||
]
|
||||
: gradient
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleInput({ target: { name: "gradient", value } });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Form.Submit asChild>
|
||||
<Button type="submit">Save</Button>
|
||||
</Form.Submit>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Form.Root>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default ProfileGradientFormComponent;
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
import * as Form from "@radix-ui/react-form";
|
||||
import InputComponent from "../../../../../../components/inputComponent";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../../../../components/ui/card";
|
||||
import {
|
||||
CREATE_API_KEY,
|
||||
INSERT_API_KEY,
|
||||
INVALID_API_KEY,
|
||||
NO_API_KEY,
|
||||
} from "../../../../../../constants/constants";
|
||||
|
||||
type StoreApiKeyFormComponentProps = {
|
||||
apikey: string;
|
||||
handleInput: (event: any) => void;
|
||||
handleSaveKey: (apikey: string, handleInput: any) => void;
|
||||
loadingApiKey: boolean;
|
||||
validApiKey: boolean;
|
||||
hasApiKey: boolean;
|
||||
};
|
||||
const StoreApiKeyFormComponent = ({
|
||||
apikey,
|
||||
handleInput,
|
||||
handleSaveKey,
|
||||
loadingApiKey,
|
||||
validApiKey,
|
||||
hasApiKey,
|
||||
}: StoreApiKeyFormComponentProps) => {
|
||||
return (
|
||||
<>
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault();
|
||||
handleSaveKey(apikey, handleInput);
|
||||
}}
|
||||
>
|
||||
<Card x-chunk="dashboard-04-chunk-2" id="api">
|
||||
<CardHeader>
|
||||
<CardTitle>Store API Key</CardTitle>
|
||||
<CardDescription>
|
||||
{(hasApiKey && !validApiKey
|
||||
? INVALID_API_KEY
|
||||
: !hasApiKey
|
||||
? NO_API_KEY
|
||||
: "") + INSERT_API_KEY}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex w-full flex-col gap-3">
|
||||
<div className="flex w-full gap-4">
|
||||
<Form.Field name="apikey" className="w-full">
|
||||
<InputComponent
|
||||
id="apikey"
|
||||
onChange={(value) => {
|
||||
handleInput({ target: { name: "apikey", value } });
|
||||
}}
|
||||
value={apikey}
|
||||
isForm
|
||||
password={true}
|
||||
placeholder="Insert your API Key"
|
||||
className="w-full"
|
||||
/>
|
||||
<Form.Message match="valueMissing" className="field-invalid">
|
||||
Please enter your API Key
|
||||
</Form.Message>
|
||||
</Form.Field>
|
||||
</div>
|
||||
<span className="pr-1 text-xs text-muted-foreground">
|
||||
{CREATE_API_KEY}{" "}
|
||||
<a
|
||||
className="text-high-indigo underline"
|
||||
href="https://langflow.store/"
|
||||
target="_blank"
|
||||
>
|
||||
langflow.store
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Form.Submit asChild>
|
||||
<Button
|
||||
loading={loadingApiKey}
|
||||
type="submit"
|
||||
data-testid="api-key-save-button-store"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Form.Submit>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Form.Root>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default StoreApiKeyFormComponent;
|
||||
|
|
@ -1,25 +1,6 @@
|
|||
import * as Form from "@radix-ui/react-form";
|
||||
import { useContext, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import ForwardedIconComponent from "../../../../components/genericIconComponent";
|
||||
import GradientChooserComponent from "../../../../components/gradientChooserComponent";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../../components/ui/card";
|
||||
import {
|
||||
CONTROL_PATCH_USER_STATE,
|
||||
CREATE_API_KEY,
|
||||
INSERT_API_KEY,
|
||||
INVALID_API_KEY,
|
||||
NO_API_KEY,
|
||||
} from "../../../../constants/constants";
|
||||
import { CONTROL_PATCH_USER_STATE } from "../../../../constants/constants";
|
||||
import { AuthContext } from "../../../../contexts/authContext";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
|
|
@ -28,21 +9,26 @@ import {
|
|||
inputHandlerEventType,
|
||||
patchUserInputStateType,
|
||||
} from "../../../../types/components";
|
||||
import { gradients } from "../../../../utils/styleUtils";
|
||||
import usePatchGradient from "../hooks/use-patch-gradient";
|
||||
import usePatchPassword from "../hooks/use-patch-password";
|
||||
import useSaveKey from "../hooks/use-save-key";
|
||||
import useScrollToElement from "../hooks/use-scroll-to-element";
|
||||
import GeneralPageHeaderComponent from "./components/GeneralPageHeader";
|
||||
import PasswordFormComponent from "./components/PasswordForm";
|
||||
import ProfileGradientFormComponent from "./components/ProfileGradientForm";
|
||||
import StoreApiKeyFormComponent from "./components/StoreApiKeyForm";
|
||||
|
||||
export default function GeneralPage() {
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId,
|
||||
(state) => state.setCurrentFlowId,
|
||||
);
|
||||
|
||||
const { scrollId } = useParams();
|
||||
|
||||
const [inputState, setInputState] = useState<patchUserInputStateType>(
|
||||
CONTROL_PATCH_USER_STATE,
|
||||
CONTROL_PATCH_USER_STATE,
|
||||
);
|
||||
|
||||
const { autoLogin } = useContext(AuthContext);
|
||||
|
|
@ -91,192 +77,33 @@ export default function GeneralPage() {
|
|||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col gap-6">
|
||||
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
|
||||
<div className="flex w-full flex-col">
|
||||
<h2 className="flex items-center text-lg font-semibold tracking-tight">
|
||||
General
|
||||
<ForwardedIconComponent
|
||||
name="SlidersHorizontal"
|
||||
className="ml-2 h-5 w-5 text-primary"
|
||||
/>
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Manage settings related to Langflow and your account.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<GeneralPageHeaderComponent />
|
||||
|
||||
<div className="grid gap-6">
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
handlePatchGradient(gradient);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Card x-chunk="dashboard-04-chunk-1">
|
||||
<CardHeader>
|
||||
<CardTitle>Profile Gradient</CardTitle>
|
||||
<CardDescription>
|
||||
Choose the gradient that appears as your profile picture.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="py-2">
|
||||
<GradientChooserComponent
|
||||
value={
|
||||
gradient == ""
|
||||
? userData?.profile_image ??
|
||||
gradients[
|
||||
parseInt(userData?.id ?? "", 30) % gradients.length
|
||||
]
|
||||
: gradient
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleInput({ target: { name: "gradient", value } });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Form.Submit asChild>
|
||||
<Button type="submit">Save</Button>
|
||||
</Form.Submit>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Form.Root>
|
||||
{!autoLogin && (
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
handlePatchPassword(password, cnfPassword, handleInput);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Card x-chunk="dashboard-04-chunk-2">
|
||||
<CardHeader>
|
||||
<CardTitle>Password</CardTitle>
|
||||
<CardDescription>
|
||||
Type your new password and confirm it.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex w-full gap-4">
|
||||
<Form.Field name="password" className="w-full">
|
||||
<InputComponent
|
||||
id="pasword"
|
||||
onChange={(value) => {
|
||||
handleInput({ target: { name: "password", value } });
|
||||
}}
|
||||
value={password}
|
||||
isForm
|
||||
password={true}
|
||||
placeholder="Password"
|
||||
className="w-full"
|
||||
/>
|
||||
<Form.Message
|
||||
match="valueMissing"
|
||||
className="field-invalid"
|
||||
>
|
||||
Please enter your password
|
||||
</Form.Message>
|
||||
</Form.Field>
|
||||
<Form.Field name="cnfPassword" className="w-full">
|
||||
<InputComponent
|
||||
id="cnfPassword"
|
||||
onChange={(value) => {
|
||||
handleInput({
|
||||
target: { name: "cnfPassword", value },
|
||||
});
|
||||
}}
|
||||
value={cnfPassword}
|
||||
isForm
|
||||
password={true}
|
||||
placeholder="Confirm Password"
|
||||
className="w-full"
|
||||
/>
|
||||
<ProfileGradientFormComponent
|
||||
gradient={gradient}
|
||||
handleInput={handleInput}
|
||||
handlePatchGradient={handlePatchGradient}
|
||||
userData={userData}
|
||||
/>
|
||||
|
||||
<Form.Message
|
||||
className="field-invalid"
|
||||
match="valueMissing"
|
||||
>
|
||||
Please confirm your password
|
||||
</Form.Message>
|
||||
</Form.Field>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Form.Submit asChild>
|
||||
<Button type="submit">Save</Button>
|
||||
</Form.Submit>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Form.Root>
|
||||
{!autoLogin && (
|
||||
<PasswordFormComponent
|
||||
password={password}
|
||||
cnfPassword={cnfPassword}
|
||||
handleInput={handleInput}
|
||||
handlePatchPassword={handlePatchPassword}
|
||||
/>
|
||||
)}
|
||||
{hasStore && (
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault();
|
||||
handleSaveKey(apikey, handleInput);
|
||||
}}
|
||||
>
|
||||
<Card x-chunk="dashboard-04-chunk-2" id="api">
|
||||
<CardHeader>
|
||||
<CardTitle>Store API Key</CardTitle>
|
||||
<CardDescription>
|
||||
{(hasApiKey && !validApiKey
|
||||
? INVALID_API_KEY
|
||||
: !hasApiKey
|
||||
? NO_API_KEY
|
||||
: "") + INSERT_API_KEY}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex w-full flex-col gap-3">
|
||||
<div className="flex w-full gap-4">
|
||||
<Form.Field name="apikey" className="w-full">
|
||||
<InputComponent
|
||||
id="apikey"
|
||||
onChange={(value) => {
|
||||
handleInput({ target: { name: "apikey", value } });
|
||||
}}
|
||||
value={apikey}
|
||||
isForm
|
||||
password={true}
|
||||
placeholder="Insert your API Key"
|
||||
className="w-full"
|
||||
/>
|
||||
<Form.Message
|
||||
match="valueMissing"
|
||||
className="field-invalid"
|
||||
>
|
||||
Please enter your API Key
|
||||
</Form.Message>
|
||||
</Form.Field>
|
||||
</div>
|
||||
<span className="pr-1 text-xs text-muted-foreground">
|
||||
{CREATE_API_KEY}{" "}
|
||||
<a
|
||||
className="text-high-indigo underline"
|
||||
href="https://langflow.store/"
|
||||
target="_blank"
|
||||
>
|
||||
langflow.store
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Form.Submit asChild>
|
||||
<Button
|
||||
loading={loadingApiKey}
|
||||
type="submit"
|
||||
data-testid="api-key-save-button-store"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Form.Submit>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Form.Root>
|
||||
<StoreApiKeyFormComponent
|
||||
apikey={apikey}
|
||||
handleInput={handleInput}
|
||||
handleSaveKey={handleSaveKey}
|
||||
loadingApiKey={loadingApiKey}
|
||||
validApiKey={validApiKey}
|
||||
hasApiKey={hasApiKey}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -430,10 +430,12 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
startNodeId,
|
||||
stopNodeId,
|
||||
input_value,
|
||||
silent,
|
||||
}: {
|
||||
startNodeId?: string;
|
||||
stopNodeId?: string;
|
||||
input_value?: string;
|
||||
silent?: boolean;
|
||||
}) => {
|
||||
get().setIsBuilding(true);
|
||||
const currentFlow = useFlowsManagerStore.getState().currentFlow;
|
||||
|
|
@ -536,19 +538,23 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
startNodeId,
|
||||
stopNodeId,
|
||||
onGetOrderSuccess: () => {
|
||||
setNoticeData({ title: "Running components" });
|
||||
if (!silent) {
|
||||
setNoticeData({ title: "Running components" });
|
||||
}
|
||||
},
|
||||
onBuildComplete: (allNodesValid) => {
|
||||
const nodeId = startNodeId || stopNodeId;
|
||||
if (nodeId && allNodesValid) {
|
||||
setSuccessData({
|
||||
title: `${
|
||||
get().nodes.find((node) => node.id === nodeId)?.data.node
|
||||
?.display_name
|
||||
} built successfully`,
|
||||
});
|
||||
} else {
|
||||
setSuccessData({ title: FLOW_BUILD_SUCCESS_ALERT });
|
||||
if (!silent) {
|
||||
if (nodeId && allNodesValid) {
|
||||
setSuccessData({
|
||||
title: `${
|
||||
get().nodes.find((node) => node.id === nodeId)?.data.node
|
||||
?.display_name
|
||||
} built successfully`,
|
||||
});
|
||||
} else {
|
||||
setSuccessData({ title: FLOW_BUILD_SUCCESS_ALERT });
|
||||
}
|
||||
}
|
||||
get().setIsBuilding(false);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { cloneDeep, debounce } from "lodash";
|
||||
import { cloneDeep } from "lodash";
|
||||
import * as debounce from "debounce-promise";
|
||||
import { Edge, Node, Viewport, XYPosition } from "reactflow";
|
||||
import { create } from "zustand";
|
||||
import { SAVE_DEBOUNCE_TIME } from "../constants/constants";
|
||||
|
|
|
|||
|
|
@ -106,11 +106,12 @@ export type FlowStoreType = {
|
|||
startNodeId,
|
||||
stopNodeId,
|
||||
input_value,
|
||||
silent,
|
||||
}: {
|
||||
nodeId?: string;
|
||||
startNodeId?: string;
|
||||
stopNodeId?: string;
|
||||
input_value?: string;
|
||||
silent?: boolean;
|
||||
}) => Promise<void>;
|
||||
getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport };
|
||||
updateVerticesBuild: (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue