Merge zustand/io/migration into codeShortcut
This commit is contained in:
commit
2760bd5428
122 changed files with 2731 additions and 2020 deletions
4
src/frontend/.gitignore
vendored
4
src/frontend/.gitignore
vendored
|
|
@ -24,3 +24,7 @@ yarn-error.log*
|
|||
/test-results/
|
||||
/playwright-report/*/
|
||||
/playwright/.cache/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
27
src/frontend/package-lock.json
generated
27
src/frontend/package-lock.json
generated
|
|
@ -48,6 +48,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.331.0",
|
||||
"moment": "^2.29.4",
|
||||
"playwright": "^1.42.0",
|
||||
"react": "^18.2.0",
|
||||
"react-ace": "^10.1.0",
|
||||
"react-cookie": "^4.1.1",
|
||||
|
|
@ -77,7 +78,7 @@
|
|||
"zustand": "^4.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.41.2",
|
||||
"@playwright/test": "^1.42.0",
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.80",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
|
|
@ -1492,12 +1493,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.41.2",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
|
||||
"integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==",
|
||||
"version": "1.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0.tgz",
|
||||
"integrity": "sha512-2k1HzC28Fs+HiwbJOQDUwrWMttqSLUVdjCqitBOjdCD0svWOMQUVqrXX6iFD7POps6xXAojsX/dGBpKnjZctLA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.41.2"
|
||||
"playwright": "1.42.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -8719,12 +8720,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.41.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz",
|
||||
"integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==",
|
||||
"dev": true,
|
||||
"version": "1.42.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz",
|
||||
"integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.41.2"
|
||||
"playwright-core": "1.42.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -8737,10 +8737,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.41.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz",
|
||||
"integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==",
|
||||
"dev": true,
|
||||
"version": "1.42.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz",
|
||||
"integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.331.0",
|
||||
"moment": "^2.29.4",
|
||||
"playwright": "^1.42.0",
|
||||
"react": "^18.2.0",
|
||||
"react-ace": "^10.1.0",
|
||||
"react-cookie": "^4.1.1",
|
||||
|
|
@ -99,7 +100,7 @@
|
|||
},
|
||||
"proxy": "http://127.0.0.1:7860",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.41.2",
|
||||
"@playwright/test": "^1.42.0",
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.80",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@
|
|||
<li>
|
||||
<a href="./e2e/index.html">e2e report</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./onlyFront/index.html">frontEnd Only report</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -27,8 +27,16 @@ terminate_process_by_port() {
|
|||
echo "Process terminated."
|
||||
}
|
||||
|
||||
delete_temp() {
|
||||
cd ../../
|
||||
echo "Deleting temp database"
|
||||
rm temp
|
||||
echo "Temp database deleted."
|
||||
}
|
||||
|
||||
|
||||
# Trap signals to ensure cleanup on script termination
|
||||
trap 'terminate_process_by_port 7860; terminate_process_by_port 3000' EXIT
|
||||
trap 'terminate_process_by_port 7860; terminate_process_by_port 3000; delete_temp' EXIT
|
||||
|
||||
# install playwright if there is not installed yet
|
||||
npx playwright install
|
||||
|
|
@ -42,26 +50,16 @@ make frontend &
|
|||
# Give some time for the frontend to start (adjust sleep duration as needed)
|
||||
sleep 10
|
||||
|
||||
# Navigate to the test directory
|
||||
cd src/frontend
|
||||
|
||||
# Run frontend only Playwright tests with or without UI based on the --ui flag
|
||||
if [ "$ui" = true ]; then
|
||||
PLAYWRIGHT_HTML_REPORT=playwright-report/onlyFront npx playwright test tests/onlyFront --ui --project=chromium
|
||||
else
|
||||
PLAYWRIGHT_HTML_REPORT=playwright-report/onlyFront npx playwright test tests/onlyFront --project=chromium
|
||||
fi
|
||||
|
||||
# Navigate back to the project root directory
|
||||
cd ../../
|
||||
#install backend
|
||||
poetry install --extras deploy
|
||||
|
||||
# Start the backend using 'make backend' in the background
|
||||
make backend &
|
||||
LANGFLOW_DATABASE_URL=sqlite:///./temp LANGFLOW_AUTO_LOGIN=True poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser &
|
||||
|
||||
# Give some time for the backend to start (adjust sleep duration as needed)
|
||||
sleep 25
|
||||
|
||||
# Navigate back to the test directory
|
||||
# Navigate to the test directory
|
||||
cd src/frontend
|
||||
|
||||
# Run Playwright tests with or without UI based on the --ui flag
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@ import PromptAreaComponent from "../../../../components/promptComponent";
|
|||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
||||
import {
|
||||
INPUT_HANDLER_HOVER,
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
OUTPUT_HANDLER_HOVER,
|
||||
TOOLTIP_EMPTY,
|
||||
inputHandleHover,
|
||||
outputHandleHover,
|
||||
} from "../../../../constants/constants";
|
||||
import { postCustomComponentUpdate } from "../../../../controllers/API";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
|
|
@ -68,7 +69,7 @@ export default function ParameterComponent({
|
|||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const flow = currentFlow?.data?.nodes ?? null;
|
||||
|
||||
const groupedEdge = useRef(null);
|
||||
|
|
@ -85,7 +86,12 @@ export default function ParameterComponent({
|
|||
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
|
||||
const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
||||
const handleUpdateValues = async (
|
||||
name: string,
|
||||
data: NodeDataType,
|
||||
delayAnimation: boolean = true
|
||||
) => {
|
||||
setIsLoading(true);
|
||||
const code = data.node?.template["code"]?.value;
|
||||
if (!code) {
|
||||
console.error("Code not found in the template");
|
||||
|
|
@ -95,13 +101,48 @@ export default function ParameterComponent({
|
|||
try {
|
||||
const res = await postCustomComponentUpdate(code, name);
|
||||
if (res.status === 200 && data.node?.template) {
|
||||
data.node!.template[name] = res.data.template[name];
|
||||
setNode(data.id, (oldNode) => {
|
||||
let newNode = cloneDeep(oldNode);
|
||||
|
||||
newNode.data = {
|
||||
...newNode.data,
|
||||
};
|
||||
|
||||
newNode.data.node.template[name] = res.data.template[name];
|
||||
|
||||
return newNode;
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
setErrorData(err as { title: string; list?: Array<string> });
|
||||
}
|
||||
|
||||
renderTooltips();
|
||||
if (delayAnimation) {
|
||||
try {
|
||||
// Wait for at least 500 milliseconds
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
// Continue with the request
|
||||
// If the request takes longer than 500 milliseconds, it will not wait an additional 500 milliseconds
|
||||
} catch (error) {
|
||||
console.error("Error occurred while waiting for refresh:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
} else setIsLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
function fetchData() {
|
||||
if (
|
||||
data.node?.template[name]?.refresh &&
|
||||
Object.keys(data.node?.template[name]?.options ?? {}).length === 0
|
||||
) {
|
||||
handleUpdateValues(name, data, false);
|
||||
}
|
||||
}
|
||||
fetchData();
|
||||
}, []);
|
||||
const handleOnNewValue = (
|
||||
newValue: string | string[] | boolean | Object[]
|
||||
): void => {
|
||||
|
|
@ -182,7 +223,7 @@ export default function ParameterComponent({
|
|||
return (
|
||||
<div key={index}>
|
||||
{index === 0 && (
|
||||
<span>{left ? inputHandleHover : outputHandleHover}</span>
|
||||
<span>{left ? INPUT_HANDLER_HOVER : OUTPUT_HANDLER_HOVER}</span>
|
||||
)}
|
||||
<span
|
||||
key={index}
|
||||
|
|
@ -212,15 +253,15 @@ export default function ParameterComponent({
|
|||
{item.display_name === "" ? "" : " - "}
|
||||
{item.display_name.split(", ").length > 2
|
||||
? item.display_name.split(", ").map((el, index) => (
|
||||
<React.Fragment key={el + index}>
|
||||
<span>
|
||||
{index ===
|
||||
<React.Fragment key={el + name}>
|
||||
<span>
|
||||
{index ===
|
||||
item.display_name.split(", ").length - 1
|
||||
? el
|
||||
: (el += `, `)}
|
||||
</span>
|
||||
</React.Fragment>
|
||||
))
|
||||
? el
|
||||
: (el += `, `)}
|
||||
</span>
|
||||
</React.Fragment>
|
||||
))
|
||||
: item.display_name}
|
||||
</span>
|
||||
) : (
|
||||
|
|
@ -229,14 +270,14 @@ export default function ParameterComponent({
|
|||
{item.type === "" ? "" : " - "}
|
||||
{item.type.split(", ").length > 2
|
||||
? item.type.split(", ").map((el, index) => (
|
||||
<React.Fragment key={el + index}>
|
||||
<span>
|
||||
{index === item.type.split(", ").length - 1
|
||||
? el
|
||||
: (el += `, `)}
|
||||
</span>
|
||||
</React.Fragment>
|
||||
))
|
||||
<React.Fragment key={el + name}>
|
||||
<span>
|
||||
{index === item.type.split(", ").length - 1
|
||||
? el
|
||||
: (el += `, `)}
|
||||
</span>
|
||||
</React.Fragment>
|
||||
))
|
||||
: item.type}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -304,24 +345,31 @@ export default function ParameterComponent({
|
|||
ref={ref}
|
||||
className={
|
||||
"relative mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2" +
|
||||
(name === "code" ? " hidden " : "")
|
||||
((name === "code" && type === "code") ||
|
||||
(name.includes("code") && proxy)
|
||||
? " hidden "
|
||||
: "")
|
||||
}
|
||||
>
|
||||
<>
|
||||
<div
|
||||
className={
|
||||
"w-full truncate text-sm" +
|
||||
(left ? "" : " text-end") +
|
||||
(left ? "" : " gap-2 flex justify-end items-center") +
|
||||
(info !== "" ? " flex items-center" : "")
|
||||
}
|
||||
>
|
||||
{!left && data.node?.pinned &&
|
||||
<div>
|
||||
<IconComponent className="w-5 h-5 text-ice" name={"Snowflake"} />
|
||||
</div>}
|
||||
{proxy ? (
|
||||
<ShadTooltip content={<span>{proxy.id}</span>}>
|
||||
<span>{title}</span>
|
||||
<span className={!left && data.node?.pinned?" text-ice":""}>{title}</span>
|
||||
</ShadTooltip>
|
||||
) : (
|
||||
title
|
||||
)}
|
||||
<span className={!left && data.node?.pinned?" text-ice":""}>{title}</span>
|
||||
)}
|
||||
<span className={(info === "" ? "" : "ml-1 ") + " text-status-red"}>
|
||||
{required ? " *" : ""}
|
||||
</span>
|
||||
|
|
@ -383,20 +431,35 @@ export default function ParameterComponent({
|
|||
)}
|
||||
|
||||
{left === true &&
|
||||
type === "str" &&
|
||||
!data.node?.template[name].options ? (
|
||||
type === "str" &&
|
||||
!data.node?.template[name].options ? (
|
||||
<div className="mt-2 w-full">
|
||||
{data.node?.template[name].list ? (
|
||||
<InputListComponent
|
||||
disabled={disabled}
|
||||
value={
|
||||
!data.node.template[name].value ||
|
||||
data.node.template[name].value === ""
|
||||
? [""]
|
||||
: data.node.template[name].value
|
||||
}
|
||||
onChange={handleOnNewValue}
|
||||
/>
|
||||
<div className="w-5/6 flex-grow">
|
||||
<InputListComponent
|
||||
disabled={disabled}
|
||||
value={
|
||||
!data.node.template[name].value ||
|
||||
data.node.template[name].value === ""
|
||||
? [""]
|
||||
: data.node.template[name].value
|
||||
}
|
||||
onChange={handleOnNewValue}
|
||||
/>
|
||||
{data.node?.template[name].refresh && (
|
||||
<div className="w-1/6">
|
||||
<RefreshButton
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
data={data}
|
||||
className="extra-side-bar-buttons ml-2 mt-1"
|
||||
handleUpdateValues={handleUpdateValues}
|
||||
id={"refresh-button-" + name}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : data.node?.template[name].multiline ? (
|
||||
<TextAreaComponent
|
||||
disabled={disabled}
|
||||
|
|
@ -409,7 +472,7 @@ export default function ParameterComponent({
|
|||
<div className="mt-2 flex w-full items-center">
|
||||
<div className="w-5/6 flex-grow">
|
||||
<InputComponent
|
||||
id={"input-" + index}
|
||||
id={"input-" + name}
|
||||
disabled={disabled}
|
||||
password={data.node?.template[name].password ?? false}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
|
|
@ -417,14 +480,17 @@ export default function ParameterComponent({
|
|||
/>
|
||||
</div>
|
||||
{data.node?.template[name].refresh && (
|
||||
<button
|
||||
className="extra-side-bar-buttons ml-2 mt-1 w-1/6"
|
||||
onClick={() => {
|
||||
handleUpdateValues(name, data);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="RefreshCcw" />
|
||||
</button>
|
||||
<div className="w-1/6">
|
||||
<RefreshButton
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
data={data}
|
||||
className="extra-side-bar-buttons ml-2 mt-1"
|
||||
handleUpdateValues={handleUpdateValues}
|
||||
id={"refresh-button-" + name}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -432,11 +498,12 @@ export default function ParameterComponent({
|
|||
) : left === true && type === "bool" ? (
|
||||
<div className="mt-2 w-full">
|
||||
<ToggleShadComponent
|
||||
id={"toggle-" + index}
|
||||
id={"toggle-" + name}
|
||||
disabled={disabled}
|
||||
enabled={data.node?.template[name].value ?? false}
|
||||
setEnabled={handleOnNewValue}
|
||||
size="large"
|
||||
editNode={false}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "float" ? (
|
||||
|
|
@ -450,26 +517,31 @@ export default function ParameterComponent({
|
|||
</div>
|
||||
) : left === true &&
|
||||
type === "str" &&
|
||||
data.node?.template[name].options ? (
|
||||
(data.node?.template[name].options ||
|
||||
data.node?.template[name]?.refresh) ? (
|
||||
// TODO: Improve CSS
|
||||
<div className="mt-2 flex w-full items-center">
|
||||
<div className="w-5/6 flex-grow">
|
||||
<Dropdown
|
||||
isLoading={isLoading}
|
||||
options={data.node.template[name].options}
|
||||
onSelect={handleOnNewValue}
|
||||
value={data.node.template[name].value ?? "Choose an option"}
|
||||
id={"dropdown-" + index}
|
||||
id={"dropdown-" + name}
|
||||
/>
|
||||
</div>
|
||||
{data.node?.template[name].refresh && (
|
||||
<button
|
||||
className="extra-side-bar-buttons ml-2 mt-1 w-1/6"
|
||||
onClick={() => {
|
||||
handleUpdateValues(name, data);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="RefreshCcw" />
|
||||
</button>
|
||||
<div className="w-1/6">
|
||||
<RefreshButton
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
data={data}
|
||||
className="extra-side-bar-buttons ml-2 mt-1"
|
||||
handleUpdateValues={handleUpdateValues}
|
||||
id={"refresh-button-" + name}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : left === true && type === "code" ? (
|
||||
|
|
@ -486,7 +558,7 @@ export default function ParameterComponent({
|
|||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"code-input-" + index}
|
||||
id={"code-input-" + name}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "file" ? (
|
||||
|
|
@ -507,7 +579,7 @@ export default function ParameterComponent({
|
|||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"int-input-" + index}
|
||||
id={"int-input-" + name}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "prompt" ? (
|
||||
|
|
@ -520,8 +592,8 @@ export default function ParameterComponent({
|
|||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"prompt-input-" + index}
|
||||
data-testid={"prompt-input-" + index}
|
||||
id={"prompt-input-" + name}
|
||||
data-testid={"prompt-input-" + name}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "NestedDict" ? (
|
||||
|
|
@ -531,10 +603,10 @@ export default function ParameterComponent({
|
|||
editNode={false}
|
||||
value={
|
||||
!data.node!.template[name].value ||
|
||||
data.node!.template[name].value?.toString() === "{}"
|
||||
data.node!.template[name].value?.toString() === "{}"
|
||||
? {
|
||||
yourkey: "value",
|
||||
}
|
||||
yourkey: "value",
|
||||
}
|
||||
: data.node!.template[name].value
|
||||
}
|
||||
onChange={handleOnNewValue}
|
||||
|
|
@ -548,7 +620,7 @@ export default function ParameterComponent({
|
|||
editNode={false}
|
||||
value={
|
||||
data.node!.template[name].value?.length === 0 ||
|
||||
!data.node!.template[name].value
|
||||
!data.node!.template[name].value
|
||||
? [{ "": "" }]
|
||||
: convertObjToArray(data.node!.template[name].value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ import Loading from "../../components/ui/loading";
|
|||
import { Textarea } from "../../components/ui/textarea";
|
||||
import Xmark from "../../components/ui/xmark";
|
||||
import {
|
||||
RUN_TIMESTAMP_PREFIX,
|
||||
STATUS_BUILD,
|
||||
STATUS_BUILDING,
|
||||
priorityFields,
|
||||
statusBuild,
|
||||
statusBuilding,
|
||||
} from "../../constants/constants";
|
||||
import { BuildStatus } from "../../constants/enums";
|
||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
|
|
@ -49,11 +50,18 @@ export default function GenericNode({
|
|||
const [nodeDescription, setNodeDescription] = useState(
|
||||
data.node?.description!
|
||||
);
|
||||
const buildStatus = useFlowStore((state) => state.flowBuildStatus[data.id]);
|
||||
const buildStatus = useFlowStore(
|
||||
(state) => state.flowBuildStatus[data.id]?.status
|
||||
);
|
||||
const lastRunTime = useFlowStore(
|
||||
(state) => state.flowBuildStatus[data.id]?.timestamp
|
||||
);
|
||||
const [validationStatus, setValidationStatus] =
|
||||
useState<validationStatusType | null>(null);
|
||||
const [handles, setHandles] = useState<number>(0);
|
||||
|
||||
const [validationString, setValidationString] = useState<string>("");
|
||||
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
|
||||
function countHandles(): void {
|
||||
|
|
@ -100,7 +108,7 @@ export default function GenericNode({
|
|||
if (duration === undefined) {
|
||||
return "";
|
||||
} else {
|
||||
return `Duration: ${duration}`;
|
||||
return `${duration}`;
|
||||
}
|
||||
};
|
||||
const durationString = getDurationString(validationStatus?.data.duration);
|
||||
|
|
@ -126,6 +134,18 @@ export default function GenericNode({
|
|||
}
|
||||
}, [flowPool[data.id], data.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (validationStatus?.params) {
|
||||
// if it is not a string turn it into a string
|
||||
let newValidationString = validationStatus.params;
|
||||
if (typeof newValidationString !== "string") {
|
||||
newValidationString = JSON.stringify(validationStatus.params);
|
||||
}
|
||||
|
||||
setValidationString(newValidationString);
|
||||
}
|
||||
}, [validationStatus, validationStatus?.params]);
|
||||
|
||||
const showNode = data.showNode ?? true;
|
||||
|
||||
const nameEditable = true;
|
||||
|
|
@ -332,8 +352,8 @@ export default function GenericNode({
|
|||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="group flex items-center gap-2.5">
|
||||
<ShadTooltip content={data.id}>
|
||||
<div className="group flex items-start gap-1.5">
|
||||
<ShadTooltip content={data.node?.display_name}>
|
||||
<div
|
||||
onDoubleClick={(event) => {
|
||||
if (nameEditable) {
|
||||
|
|
@ -359,8 +379,8 @@ export default function GenericNode({
|
|||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Pencil"
|
||||
className="hidden h-4 w-4 animate-pulse text-status-blue group-hover:block"
|
||||
name="PencilLine"
|
||||
className="hidden h-3 w-3 text-status-blue group-hover:block"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -390,13 +410,34 @@ export default function GenericNode({
|
|||
})}
|
||||
data={data}
|
||||
color={
|
||||
nodeColors[
|
||||
types[data.node?.template[templateField].type!]
|
||||
] ??
|
||||
nodeColors[
|
||||
data.node?.template[templateField].type!
|
||||
] ??
|
||||
nodeColors.unknown
|
||||
data.node?.template[templateField].input_types &&
|
||||
data.node?.template[templateField].input_types!
|
||||
.length > 0
|
||||
? nodeColors[
|
||||
data.node?.template[templateField]
|
||||
.input_types![
|
||||
data.node?.template[templateField]
|
||||
.input_types!.length - 1
|
||||
]
|
||||
] ??
|
||||
nodeColors[
|
||||
types[
|
||||
data.node?.template[templateField]
|
||||
.input_types![
|
||||
data.node?.template[templateField]
|
||||
.input_types!.length - 1
|
||||
]
|
||||
]
|
||||
]
|
||||
: nodeColors[
|
||||
data.node?.template[templateField].type!
|
||||
] ??
|
||||
nodeColors[
|
||||
types[
|
||||
data.node?.template[templateField].type!
|
||||
]
|
||||
] ??
|
||||
nodeColors.unknown
|
||||
}
|
||||
title={getFieldTitle(
|
||||
data.node?.template!,
|
||||
|
|
@ -458,38 +499,55 @@ export default function GenericNode({
|
|||
)}
|
||||
</div>
|
||||
{showNode && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
className={"group h-9 px-1.5"}
|
||||
onClick={() => {
|
||||
if (buildStatus === BuildStatus.BUILDING || isBuilding)
|
||||
return;
|
||||
setValidationStatus(null);
|
||||
buildFlow({ nodeId: data.id });
|
||||
}}
|
||||
>
|
||||
<Button variant="secondary" className={"group h-9 px-1.5"}>
|
||||
<div>
|
||||
<ShadTooltip
|
||||
content={
|
||||
buildStatus === BuildStatus.BUILDING ? (
|
||||
<span> {statusBuilding} </span>
|
||||
<span> {STATUS_BUILDING} </span>
|
||||
) : !validationStatus ? (
|
||||
<span className="flex">{statusBuild}</span>
|
||||
<span className="flex">{STATUS_BUILD}</span>
|
||||
) : (
|
||||
<div className="max-h-96 overflow-auto">
|
||||
{typeof validationStatus.params === "string"
|
||||
? `${durationString}\n${validationStatus.params}`
|
||||
.split("\n")
|
||||
.map((line, index) => (
|
||||
<div key={index}>{line}</div>
|
||||
))
|
||||
: durationString}
|
||||
<div className="max-h-100">
|
||||
<div>
|
||||
{lastRunTime && (
|
||||
<div className="justify-left flex text-muted-foreground">
|
||||
<div>{RUN_TIMESTAMP_PREFIX}</div>
|
||||
<div className="ml-1 text-status-blue">
|
||||
{lastRunTime}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="justify-left flex text-muted-foreground">
|
||||
<div>Duration:</div>
|
||||
<div className="ml-1 text-status-blue">
|
||||
{validationStatus?.data.duration}
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span className="flex justify-center text-muted-foreground ">
|
||||
Output
|
||||
</span>
|
||||
<div className="max-h-96 overflow-auto custom-scroll">
|
||||
{validationString.split("\n").map((line, index) => (
|
||||
<div key={index}>{line}</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
side="bottom"
|
||||
>
|
||||
<div className="generic-node-status-position flex items-center justify-center">
|
||||
<div
|
||||
onClick={() => {
|
||||
if (buildStatus === BuildStatus.BUILDING || isBuilding)
|
||||
return;
|
||||
setValidationStatus(null);
|
||||
buildFlow({ stopNodeId: data.id });
|
||||
}}
|
||||
className="generic-node-status-position flex items-center justify-center"
|
||||
>
|
||||
{renderIconStatus(buildStatus, validationStatus)}
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
|
|
@ -607,13 +665,18 @@ export default function GenericNode({
|
|||
data.node?.template[templateField].input_types!
|
||||
.length > 0
|
||||
? nodeColors[
|
||||
data.node?.template[templateField]
|
||||
.input_types![0]
|
||||
data.node?.template[templateField].input_types![
|
||||
data.node?.template[templateField]
|
||||
.input_types!.length - 1
|
||||
]
|
||||
] ??
|
||||
nodeColors[
|
||||
types[
|
||||
data.node?.template[templateField]
|
||||
.input_types![0]
|
||||
.input_types![
|
||||
data.node?.template[templateField]
|
||||
.input_types!.length - 1
|
||||
]
|
||||
]
|
||||
]
|
||||
: nodeColors[
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {
|
|||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "../../components/ui/popover";
|
||||
import { zeroNotifications } from "../../constants/constants";
|
||||
import { ZERO_NOTIFICATIONS } from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { AlertDropdownType } from "../../types/alerts";
|
||||
import SingleAlert from "./components/singleAlertComponent";
|
||||
|
|
@ -70,7 +70,7 @@ export default function AlertDropdown({
|
|||
))
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center pb-16 text-ring">
|
||||
{zeroNotifications}
|
||||
{ZERO_NOTIFICATIONS}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -49,8 +49,10 @@ export default function AccordionComponent({
|
|||
>
|
||||
{trigger}
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="AccordionContent flex flex-col">
|
||||
{children}
|
||||
<AccordionContent>
|
||||
<div className="AccordionContent flex flex-col">
|
||||
{children}
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
CHAT_FORM_DIALOG_SUBTITLE,
|
||||
outputsModalTitle,
|
||||
textInputModalTitle,
|
||||
OUTPUTS_MODAL_TITLE,
|
||||
TEXT_INPUT_MODAL_TITLE,
|
||||
} from "../../constants/constants";
|
||||
import BaseModal from "../../modals/baseModal";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { NodeType } from "../../types/flow";
|
||||
import { updateVerticesOrder } from "../../utils/buildUtils";
|
||||
import { cn } from "../../utils/utils";
|
||||
import AccordionComponent from "../AccordionComponent";
|
||||
import IOInputField from "../IOInputField";
|
||||
import IOOutputView from "../IOOutputView";
|
||||
import ShadTooltip from "../ShadTooltipComponent";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import NewChatView from "../newChatView";
|
||||
import { Badge } from "../ui/badge";
|
||||
|
|
@ -50,6 +52,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
const [chatValue, setChatValue] = useState("");
|
||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
|
||||
async function updateVertices() {
|
||||
return updateVerticesOrder(currentFlow!.id, null);
|
||||
|
|
@ -67,12 +70,22 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
setLockChat(true);
|
||||
setChatValue("");
|
||||
for (let i = 0; i < count; i++) {
|
||||
await buildFlow({ input_value: chatValue }).catch((err) => {
|
||||
await buildFlow({
|
||||
input_value: chatValue,
|
||||
startNodeId: chatInput?.id,
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
setLockChat(false);
|
||||
});
|
||||
}
|
||||
setLockChat(false);
|
||||
if (chatInput) {
|
||||
setNode(chatInput.id, (node: NodeType) => {
|
||||
const newNode = { ...node };
|
||||
newNode.data.node!.template["input_value"].value = chatValue;
|
||||
return newNode;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -134,7 +147,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
>
|
||||
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
||||
<IconComponent className="h-4 w-4" name={"Type"} />
|
||||
{textInputModalTitle}
|
||||
{TEXT_INPUT_MODAL_TITLE}
|
||||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
|
|
@ -195,7 +208,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
>
|
||||
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
||||
<IconComponent className="h-4 w-4" name={"FileType2"} />
|
||||
{outputsModalTitle}
|
||||
{OUTPUTS_MODAL_TITLE}
|
||||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
|
|
@ -213,9 +226,16 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
<AccordionComponent
|
||||
trigger={
|
||||
<div className="file-component-badge-div">
|
||||
<Badge variant="gray" size="md">
|
||||
{output.id}
|
||||
</Badge>
|
||||
<ShadTooltip
|
||||
content={output.id}
|
||||
styleClasses="z-50"
|
||||
>
|
||||
<div>
|
||||
<Badge variant="gray" size="md">
|
||||
{node.data.node.display_name}
|
||||
</Badge>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
{haveChat && (
|
||||
<div
|
||||
className="-mb-1 pr-4"
|
||||
|
|
@ -255,7 +275,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
)}
|
||||
|
||||
{haveChat ? (
|
||||
<div className="flex h-full w-full">
|
||||
<div className="flex h-full min-w-96 flex-grow">
|
||||
{selectedViewField && (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -272,7 +292,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
</button>
|
||||
{selectedViewField.type}
|
||||
</div>
|
||||
<div className="h-full">
|
||||
<div className="h-full w-full">
|
||||
{inputs.some(
|
||||
(input) => input.id === selectedViewField.id
|
||||
) ? (
|
||||
|
|
@ -308,28 +328,30 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
<div className="absolute bottom-8 right-8"></div>
|
||||
)}
|
||||
</div>
|
||||
{!haveChat && (
|
||||
<div className="flex w-full justify-end pt-6">
|
||||
<Button
|
||||
variant={"outline"}
|
||||
className="flex gap-2 px-3"
|
||||
onClick={() => sendMessage(1)}
|
||||
>
|
||||
<IconComponent
|
||||
name={isBuilding ? "Loader2" : "Play"}
|
||||
className={cn(
|
||||
"h-4 w-4",
|
||||
isBuilding
|
||||
? "animate-spin"
|
||||
: "fill-current text-medium-indigo"
|
||||
)}
|
||||
/>
|
||||
Run Flow
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</BaseModal.Content>
|
||||
<BaseModal.Footer>
|
||||
{!haveChat && (
|
||||
<div className="flex w-full justify-end pt-6">
|
||||
<Button
|
||||
variant={"outline"}
|
||||
className="flex gap-2 px-3"
|
||||
onClick={() => sendMessage(1)}
|
||||
>
|
||||
<IconComponent
|
||||
name={isBuilding ? "Loader2" : "Play"}
|
||||
className={cn(
|
||||
"h-4 w-4",
|
||||
isBuilding
|
||||
? "animate-spin"
|
||||
: "fill-current text-medium-indigo"
|
||||
)}
|
||||
/>
|
||||
Run Flow
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</BaseModal.Footer>
|
||||
</BaseModal>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ export default function CodeAreaComponent({
|
|||
setNodeClass,
|
||||
id = "",
|
||||
readonly = false,
|
||||
openModal,
|
||||
selected,
|
||||
setOpenModal,
|
||||
open,
|
||||
setOpen,
|
||||
}: CodeAreaComponentType) {
|
||||
const [myValue, setMyValue] = useState(
|
||||
typeof value == "string" ? value : JSON.stringify(value)
|
||||
|
|
@ -35,9 +34,8 @@ export default function CodeAreaComponent({
|
|||
return (
|
||||
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
|
||||
<CodeAreaModal
|
||||
selected={selected}
|
||||
openModal={openModal}
|
||||
setOpenModal={setOpenModal}
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
readonly={readonly}
|
||||
dynamic={dynamic}
|
||||
value={myValue}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ export default function CodeTabsComponent({
|
|||
<Tabs
|
||||
value={activeTab}
|
||||
className={
|
||||
"api-modal-tabs " +
|
||||
"api-modal-tabs m-0 inset-0 " +
|
||||
(isMessage ? "dark " : "") +
|
||||
(dark && isMessage ? "bg-background" : "")
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ export default function CodeTabsComponent({
|
|||
) : (
|
||||
<IconComponent name="Clipboard" className="h-4 w-4" />
|
||||
)}
|
||||
{isCopied ? "Copied!" : "Copy code"}
|
||||
{isCopied ? "Copied!" : "Copy Code"}
|
||||
</button>
|
||||
<button
|
||||
className="flex items-center gap-1.5 rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"
|
||||
|
|
@ -193,9 +193,9 @@ export default function CodeTabsComponent({
|
|||
></div>
|
||||
)}
|
||||
<SyntaxHighlighter
|
||||
className="mt-0 h-full w-full overflow-auto custom-scroll"
|
||||
language={tab.mode}
|
||||
language={tab.language}
|
||||
style={oneDark}
|
||||
className="mt-0 h-full overflow-auto custom-scroll rounded-sm text-left"
|
||||
>
|
||||
{tab.code}
|
||||
</SyntaxHighlighter>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { classNames } from "../../utils/utils";
|
|||
import IconComponent from "../genericIconComponent";
|
||||
|
||||
export default function Dropdown({
|
||||
isLoading,
|
||||
value,
|
||||
options,
|
||||
onSelect,
|
||||
|
|
@ -129,11 +130,17 @@ export default function Dropdown({
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
<span className="text-sm italic">
|
||||
No parameters are available for display.
|
||||
</span>
|
||||
</div>
|
||||
{(!isLoading && (
|
||||
<div>
|
||||
<span className="text-sm italic">
|
||||
No parameters are available for display.
|
||||
</span>
|
||||
</div>
|
||||
)) || (
|
||||
<div>
|
||||
<span className="text-sm italic">Loading...</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Node } from "reactflow";
|
||||
import { savedHover } from "../../../../constants/constants";
|
||||
import { SAVED_HOVER } from "../../../../constants/constants";
|
||||
import FlowSettingsModal from "../../../../modals/flowSettingsModal";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
|
|
@ -138,7 +138,7 @@ export const MenuBar = ({
|
|||
</div>
|
||||
<ShadTooltip
|
||||
content={
|
||||
savedHover +
|
||||
SAVED_HOVER +
|
||||
new Date(currentFlow.updated_at ?? "").toLocaleString("en-US", {
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ export default function InputComponent({
|
|||
handleKeyDown(e, value, "");
|
||||
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
|
||||
}}
|
||||
data-testid={editNode ? id + "-edit" : id}
|
||||
/>
|
||||
)}
|
||||
{password && (
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export default function IntComponent({
|
|||
onChange={(event) => {
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
data-testid={id}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useEffect, useState } from "react";
|
|||
import IconComponent from "../../../components/genericIconComponent";
|
||||
import { Textarea } from "../../../components/ui/textarea";
|
||||
import {
|
||||
chatInputPlaceholder,
|
||||
chatInputPlaceholderSend,
|
||||
CHAT_INPUT_PLACEHOLDER,
|
||||
CHAT_INPUT_PLACEHOLDER_SEND,
|
||||
} from "../../../constants/constants";
|
||||
import useFlowsManagerStore from "../../../stores/flowsManagerStore";
|
||||
import { chatInputType } from "../../../types/components";
|
||||
|
|
@ -84,7 +84,7 @@ export default function ChatInput({
|
|||
"form-modal-lockchat"
|
||||
)}
|
||||
placeholder={
|
||||
noInput ? chatInputPlaceholder : chatInputPlaceholderSend
|
||||
noInput ? CHAT_INPUT_PLACEHOLDER : CHAT_INPUT_PLACEHOLDER_SEND
|
||||
}
|
||||
/>
|
||||
<div className="form-modal-send-icon-position">
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export function CodeBlock({ language, value }: Props): JSX.Element {
|
|||
<div className="flex items-center">
|
||||
<button className="code-block-modal-button" onClick={copyToClipboard}>
|
||||
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
|
||||
{isCopied ? "Copied!" : "Copy code"}
|
||||
{isCopied ? "Copied!" : "Copy Code"}
|
||||
</button>
|
||||
<button className="code-block-modal-button" onClick={downloadAsFile}>
|
||||
<IconDownload size={18} />
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export default function ChatMessage({
|
|||
chat.isSend ? "" : " "
|
||||
)}
|
||||
>
|
||||
<div className={classNames("form-modal-chatbot-icon ")}>
|
||||
<div className={classNames("form-modal-chatbot-icon")}>
|
||||
{!chat.isSend ? (
|
||||
<div className="form-modal-chat-image">
|
||||
<div className="form-modal-chat-bot-icon ">
|
||||
|
|
@ -134,7 +134,7 @@ export default function ChatMessage({
|
|||
)}
|
||||
</div>
|
||||
{!chat.isSend ? (
|
||||
<div className="form-modal-chat-text-position">
|
||||
<div className="form-modal-chat-text-position flex-grow min-w-96">
|
||||
<div className="form-modal-chat-text">
|
||||
{hidden && chat.thought && chat.thought !== "" && (
|
||||
<div
|
||||
|
|
@ -155,9 +155,9 @@ export default function ChatMessage({
|
|||
/>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
|
||||
<div className="w-full">
|
||||
<div className="w-full dark:text-white">
|
||||
<div className="w-full">
|
||||
<div className="w-full flex flex-col">
|
||||
<div className="w-full flex flex-col dark:text-white">
|
||||
<div className="w-full flex flex-col">
|
||||
{useMemo(
|
||||
() =>
|
||||
chatMessage === "" && lockChat ? (
|
||||
|
|
@ -169,7 +169,7 @@ export default function ChatMessage({
|
|||
<Markdown
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
rehypePlugins={[rehypeMathjax]}
|
||||
className="markdown prose min-w-full text-primary word-break-break-word
|
||||
className="markdown flex flex-col prose text-primary word-break-break-word
|
||||
dark:prose-invert"
|
||||
components={{
|
||||
pre({ node, ...props }) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useEffect, useRef, useState } from "react";
|
|||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { NOCHATOUTPUT_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||
import {
|
||||
chatFirstInitialText,
|
||||
chatSecondInitialText,
|
||||
CHAT_FIRST_INITIAL_TEXT,
|
||||
CHAT_SECOND_INITIAL_TEXT,
|
||||
} from "../../constants/constants";
|
||||
import { deleteFlowPool } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
|
|
@ -182,14 +182,14 @@ export default function NewChatView({
|
|||
<br />
|
||||
<div className="langflow-chat-desc">
|
||||
<span className="langflow-chat-desc-span">
|
||||
{chatFirstInitialText}{" "}
|
||||
{CHAT_FIRST_INITIAL_TEXT}{" "}
|
||||
<span>
|
||||
<IconComponent
|
||||
name="MessageSquare"
|
||||
className="mx-1 inline h-5 w-5 animate-bounce "
|
||||
/>
|
||||
</span>{" "}
|
||||
{chatSecondInitialText}
|
||||
{CHAT_SECOND_INITIAL_TEXT}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useEffect } from "react";
|
||||
import { editTextModalTitle } from "../../constants/constants";
|
||||
import { EDIT_TEXT_MODAL_TITLE } from "../../constants/constants";
|
||||
import { TypeModal } from "../../constants/enums";
|
||||
import GenericModal from "../../modals/genericModal";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
|
|
@ -38,7 +38,7 @@ export default function TextAreaComponent({
|
|||
<GenericModal
|
||||
type={TypeModal.TEXT}
|
||||
buttonText="Finish Editing"
|
||||
modalTitle={editTextModalTitle}
|
||||
modalTitle={EDIT_TEXT_MODAL_TITLE}
|
||||
value={value}
|
||||
setValue={(value: string) => {
|
||||
onChange(value);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export default function ToggleShadComponent({
|
|||
disabled,
|
||||
size,
|
||||
id = "",
|
||||
editNode = false,
|
||||
}: ToggleComponentType): JSX.Element {
|
||||
let scaleX, scaleY;
|
||||
switch (size) {
|
||||
|
|
@ -31,6 +32,7 @@ export default function ToggleShadComponent({
|
|||
<div className={disabled ? "pointer-events-none cursor-not-allowed " : ""}>
|
||||
<Switch
|
||||
id={id}
|
||||
data-testid={id}
|
||||
style={{
|
||||
transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const DialogContent = React.forwardRef<
|
|||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] 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",
|
||||
"flex flex-col fixed left-[50%] top-[50%] z-50 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] 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",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
51
src/frontend/src/components/ui/refreshButton.tsx
Normal file
51
src/frontend/src/components/ui/refreshButton.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { cn } from "../../utils/utils";
|
||||
|
||||
function RefreshButton({
|
||||
isLoading,
|
||||
disabled,
|
||||
name,
|
||||
data,
|
||||
handleUpdateValues,
|
||||
className,
|
||||
id,
|
||||
}: {
|
||||
isLoading: boolean;
|
||||
disabled: boolean;
|
||||
name: string;
|
||||
data: NodeDataType;
|
||||
className?: string;
|
||||
handleUpdateValues: (name: string, data: NodeDataType) => void;
|
||||
id: string;
|
||||
}) {
|
||||
const handleClick = async () => {
|
||||
if (disabled) return;
|
||||
handleUpdateValues(name, data);
|
||||
};
|
||||
|
||||
const classNames = cn(
|
||||
className,
|
||||
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
||||
);
|
||||
|
||||
// icon class name should take into account the disabled state and the loading state
|
||||
const disabledIconTextClass = disabled ? "text-muted-foreground" : "";
|
||||
const iconClassName = cn(
|
||||
"h-4 w-4",
|
||||
isLoading ? "animate-spin" : "animate-wiggle",
|
||||
disabledIconTextClass
|
||||
);
|
||||
|
||||
return (
|
||||
<button className={classNames} onClick={handleClick} id={id}>
|
||||
<IconComponent
|
||||
name={isLoading ? "Loader2" : "RefreshCcw"}
|
||||
className={iconClassName}
|
||||
id={id + "-icon"}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export { RefreshButton };
|
||||
|
|
@ -56,3 +56,6 @@ export const USER_ADD_SUCCESS_ALERT = "Success! New user added!";
|
|||
export const DEL_KEY_SUCCESS_ALERT = "Success! Key deleted!";
|
||||
export const FLOW_BUILD_SUCCESS_ALERT = `Flow built successfully`;
|
||||
export const SAVE_SUCCESS_ALERT = "Changes saved successfully!";
|
||||
|
||||
// Generic Node
|
||||
|
||||
|
|
|
|||
|
|
@ -25,10 +25,18 @@ export const INVALID_CHARACTERS = [
|
|||
|
||||
/**
|
||||
* regex to highlight the variables in the text
|
||||
* @constant
|
||||
* @constant regexHighlight
|
||||
* @type {RegExp}
|
||||
* @default
|
||||
* @example
|
||||
* {{variable}} or {variable}
|
||||
* @returns {RegExp}
|
||||
* @description
|
||||
* This regex is used to highlight the variables in the text.
|
||||
* It matches the variables in the text that are between {{}} or {}.
|
||||
*/
|
||||
|
||||
export const regexHighlight = /\{([^}]+)\}/g;
|
||||
export const regexHighlight = /\{\{(.*?)\}\}|\{([^{}]+)\}/g;
|
||||
export const specialCharsRegex = /[!@#$%^&*()\-_=+[\]{}|;:'",.<>/?\\`´]/;
|
||||
|
||||
export const programmingLanguages: languageMap = {
|
||||
|
|
@ -683,38 +691,39 @@ export const priorityFields = new Set(["code", "template"]);
|
|||
export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]);
|
||||
export const OUTPUT_TYPES = new Set(["ChatOutput", "TextOutput"]);
|
||||
|
||||
export const chatFirstInitialText =
|
||||
export const CHAT_FIRST_INITIAL_TEXT =
|
||||
"Start a conversation and click the agent's thoughts";
|
||||
|
||||
export const chatSecondInitialText = "to inspect the chaining process.";
|
||||
export const CHAT_SECOND_INITIAL_TEXT = "to inspect the chaining process.";
|
||||
|
||||
export const zeroNotifications = "No new notifications";
|
||||
export const ZERO_NOTIFICATIONS = "No new notifications";
|
||||
|
||||
export const successBuild = "Built sucessfully ✨";
|
||||
export const SUCCESS_BUILD = "Built sucessfully ✨";
|
||||
|
||||
export const alertSaveWApi =
|
||||
export const ALERT_SAVE_WITH_API =
|
||||
"Caution: Uncheck this box only removes API keys from fields specifically designated for API keys.";
|
||||
|
||||
export const saveWApiCheckbox = "Save with my API keys";
|
||||
export const editTextModalTitle = "Edit Text";
|
||||
export const editTextPlaceholder = "Type message here.";
|
||||
export const inputHandleHover = "Avaliable input components:";
|
||||
export const outputHandleHover = "Avaliable output components:";
|
||||
export const textInputModalTitle = "Text Inputs";
|
||||
export const outputsModalTitle = "Text Outputs";
|
||||
export const langflowChatTitle = "Langflow Chat";
|
||||
export const chatInputPlaceholder =
|
||||
export const SAVE_WITH_API_CHECKBOX = "Save with my API keys";
|
||||
export const EDIT_TEXT_MODAL_TITLE = "Edit Text";
|
||||
export const EDIT_TEXT_PLACEHOLDER = "Type message here.";
|
||||
export const INPUT_HANDLER_HOVER = "Avaliable input components:";
|
||||
export const OUTPUT_HANDLER_HOVER = "Avaliable output components:";
|
||||
export const TEXT_INPUT_MODAL_TITLE = "Text Inputs";
|
||||
export const OUTPUTS_MODAL_TITLE = "Text Outputs";
|
||||
export const LANGFLOW_CHAT_TITLE = "Langflow Chat";
|
||||
export const CHAT_INPUT_PLACEHOLDER =
|
||||
"No chat input variables found. Click to run your flow.";
|
||||
export const chatInputPlaceholderSend = "Send a message...";
|
||||
export const editCodeTitle = "Edit Code";
|
||||
export const myCollectionDesc =
|
||||
"Manage your personal projects. Download or upload your collection.";
|
||||
export const storeDesc = "Search flows and components from the community.";
|
||||
export const storeTitle = "Langflow Store";
|
||||
export const noApi = "You don't have an API key. ";
|
||||
export const insertApi = "Insert your Langflow API key.";
|
||||
export const invalidApi = "Your API key is not valid. ";
|
||||
export const createApi = `Don’t have an API key? Sign up at`;
|
||||
export const statusBuild = "Build to validate status.";
|
||||
export const statusBuilding = "Building...";
|
||||
export const savedHover = "Last saved at ";
|
||||
export const CHAT_INPUT_PLACEHOLDER_SEND = "Send a message...";
|
||||
export const EDIT_CODE_TITLE = "Edit Code";
|
||||
export const MY_COLLECTION_DESC =
|
||||
"Manage your personal projects. Download and upload entire collections.";
|
||||
export const STORE_DESC = "Explore community-shared flows and components.";
|
||||
export const STORE_TITLE = "Langflow Store";
|
||||
export const NO_API_KEY = "You don't have an API key. ";
|
||||
export const INSERT_API_KEY = "Insert your Langflow API key.";
|
||||
export const INVALID_API_KEY = "Your API key is not valid. ";
|
||||
export const CREATE_API_KEY = `Don’t have an API key? Sign up at`;
|
||||
export const STATUS_BUILD = "Build to validate status.";
|
||||
export const STATUS_BUILDING = "Building...";
|
||||
export const SAVED_HOVER = "Last saved at ";
|
||||
export const RUN_TIMESTAMP_PREFIX = "Last Run: ";
|
||||
|
|
|
|||
|
|
@ -856,13 +856,16 @@ export async function requestLogout() {
|
|||
|
||||
export async function getVerticesOrder(
|
||||
flowId: string,
|
||||
nodeId?: string | null
|
||||
startNodeId?: string | null,
|
||||
stopNodeId?: string | null
|
||||
): Promise<AxiosResponse<VerticesOrderTypeAPI>> {
|
||||
// nodeId is optional and is a query parameter
|
||||
// if nodeId is not provided, the API will return all vertices
|
||||
const config = {};
|
||||
if (nodeId) {
|
||||
config["params"] = { component_id: nodeId };
|
||||
if (stopNodeId) {
|
||||
config["params"] = { stop_component_id: stopNodeId };
|
||||
} else if (startNodeId) {
|
||||
config["params"] = { start_component_id: startNodeId };
|
||||
}
|
||||
return await api.get(`${BASE_URL_API}build/${flowId}/vertices`, config);
|
||||
}
|
||||
|
|
@ -872,6 +875,7 @@ export async function postBuildVertex(
|
|||
vertexId: string,
|
||||
input_value: string
|
||||
): Promise<AxiosResponse<VertexBuildTypeAPI>> {
|
||||
// input_value is optional and is a query parameter
|
||||
return await api.post(
|
||||
`${BASE_URL_API}build/${flowId}/vertices/${vertexId}`,
|
||||
input_value ? { inputs: { input_value: input_value } } : undefined
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ function ConfirmationModal({
|
|||
setModalOpen(false);
|
||||
onConfirm(index, data);
|
||||
}}
|
||||
data-testid="replace-button"
|
||||
>
|
||||
{confirmationText}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ export default function DeleteConfirmationModal({
|
|||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<span>
|
||||
Are you sure you want to delete this {description ?? "component"}?
|
||||
Confirm deletion of {description ?? "component"}?
|
||||
<br></br>
|
||||
This action cannot be undone.
|
||||
Note: This action is irreversible.
|
||||
</span>
|
||||
<DialogFooter>
|
||||
<DialogClose>
|
||||
|
|
|
|||
|
|
@ -165,7 +165,8 @@ const EditNodeModal = forwardRef(
|
|||
)
|
||||
) ?? false;
|
||||
return (
|
||||
<TableRow key={index} className="h-10">
|
||||
<TableRow key={index} className={"h-10 " + ((templateParam==="code" && myData.node?.template[templateParam].type==="code") || (templateParam.includes("code") && myData.node?.template[templateParam].proxy) ? " hidden " : "")
|
||||
}>
|
||||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||
<ShadTooltip
|
||||
content={
|
||||
|
|
@ -242,7 +243,11 @@ const EditNodeModal = forwardRef(
|
|||
/>
|
||||
) : (
|
||||
<InputComponent
|
||||
id={"input-" + index}
|
||||
id={
|
||||
"input-" +
|
||||
myData.node.template[templateParam]
|
||||
.name
|
||||
}
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
password={
|
||||
|
|
@ -338,7 +343,10 @@ const EditNodeModal = forwardRef(
|
|||
<div className="ml-auto">
|
||||
{" "}
|
||||
<ToggleShadComponent
|
||||
id={"toggle-edit-" + index}
|
||||
id={
|
||||
"toggle-edit-" +
|
||||
myData.node.template[templateParam].name
|
||||
}
|
||||
disabled={disabled}
|
||||
enabled={
|
||||
myData.node.template[templateParam]
|
||||
|
|
@ -351,6 +359,7 @@ const EditNodeModal = forwardRef(
|
|||
);
|
||||
}}
|
||||
size="small"
|
||||
editNode={true}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
|
|
@ -391,14 +400,20 @@ const EditNodeModal = forwardRef(
|
|||
myData.node.template[templateParam]
|
||||
.value ?? "Choose an option"
|
||||
}
|
||||
id={"dropdown-edit-" + index}
|
||||
id={
|
||||
"dropdown-edit-" +
|
||||
myData.node.template[templateParam].name
|
||||
}
|
||||
></Dropdown>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "int" ? (
|
||||
<div className="mx-auto">
|
||||
<IntComponent
|
||||
id={"edit-int-input-" + index}
|
||||
id={
|
||||
"edit-int-input-" +
|
||||
myData.node.template[templateParam].name
|
||||
}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
|
|
@ -493,7 +508,10 @@ const EditNodeModal = forwardRef(
|
|||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
id={"code-area-edit" + index}
|
||||
id={
|
||||
"code-area-edit" +
|
||||
myData.node.template[templateParam].name
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
|
|
@ -519,6 +537,7 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
disabled={disabled}
|
||||
size="small"
|
||||
editNode={true}
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ import {
|
|||
API_SUCCESS_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import {
|
||||
createApi,
|
||||
insertApi,
|
||||
invalidApi,
|
||||
noApi,
|
||||
CREATE_API_KEY,
|
||||
INSERT_API_KEY,
|
||||
INVALID_API_KEY,
|
||||
NO_API_KEY,
|
||||
} from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { addApiKeyStore } from "../../controllers/API";
|
||||
|
|
@ -68,8 +68,11 @@ export default function StoreApiKeyModal({
|
|||
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header
|
||||
description={
|
||||
(hasApiKey && !validApiKey ? invalidApi : !hasApiKey ? noApi : "") +
|
||||
insertApi
|
||||
(hasApiKey && !validApiKey
|
||||
? INVALID_API_KEY
|
||||
: !hasApiKey
|
||||
? NO_API_KEY
|
||||
: "") + INSERT_API_KEY
|
||||
}
|
||||
>
|
||||
<span className="pr-2">API Key</span>
|
||||
|
|
@ -104,7 +107,7 @@ export default function StoreApiKeyModal({
|
|||
</div>
|
||||
<div className="flex items-end justify-between">
|
||||
<span className="pr-1 text-xs text-muted-foreground">
|
||||
{createApi}{" "}
|
||||
{CREATE_API_KEY}{" "}
|
||||
<a
|
||||
className="text-high-indigo underline"
|
||||
href="https://langflow.store/"
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ function BaseModal({
|
|||
minWidth = "min-w-[60vw]";
|
||||
break;
|
||||
case "large":
|
||||
minWidth = "min-w-[80vw]";
|
||||
minWidth = "min-w-[85vw]";
|
||||
height = "h-[80vh]";
|
||||
break;
|
||||
case "large-thin":
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import {
|
|||
} from "../../constants/alerts_constants";
|
||||
import {
|
||||
CODE_PROMPT_DIALOG_SUBTITLE,
|
||||
editCodeTitle,
|
||||
EDIT_CODE_TITLE,
|
||||
} from "../../constants/constants";
|
||||
import { postCustomComponent, postValidateCode } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
|
|
@ -35,11 +35,14 @@ export default function CodeAreaModal({
|
|||
children,
|
||||
dynamic,
|
||||
readonly = false,
|
||||
openModal,
|
||||
selected,
|
||||
setOpenModal,
|
||||
open: myOpen,
|
||||
setOpen: mySetOpen,
|
||||
}: codeAreaModalPropsType): JSX.Element {
|
||||
const [code, setCode] = useState(value);
|
||||
const [open, setOpen] =
|
||||
mySetOpen !== undefined && myOpen !== undefined
|
||||
? [myOpen, mySetOpen]
|
||||
: useState(false);
|
||||
const dark = useDarkStore((state) => state.dark);
|
||||
const unselectAll = useFlowStore((state) => state.unselectAll);
|
||||
const [height, setHeight] = useState<string | null>(null);
|
||||
|
|
@ -48,7 +51,6 @@ export default function CodeAreaModal({
|
|||
const [error, setError] = useState<{
|
||||
detail: { error: string | undefined; traceback: string | undefined };
|
||||
} | null>(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -59,10 +61,6 @@ export default function CodeAreaModal({
|
|||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (openModal) setOpen(true);
|
||||
}, [openModal]);
|
||||
|
||||
function processNonDynamicField() {
|
||||
postValidateCode(code)
|
||||
.then((apiReturn) => {
|
||||
|
|
@ -154,7 +152,7 @@ export default function CodeAreaModal({
|
|||
<BaseModal open={open} setOpen={setOpen}>
|
||||
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header description={CODE_PROMPT_DIALOG_SUBTITLE}>
|
||||
<span className="pr-2"> {editCodeTitle} </span>
|
||||
<span className="pr-2"> {EDIT_CODE_TITLE} </span>
|
||||
<IconComponent
|
||||
name="prompts"
|
||||
className="h-6 w-6 pl-1 text-primary "
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import { Button } from "../../components/ui/button";
|
|||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import { API_WARNING_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||
import {
|
||||
ALERT_SAVE_WITH_API,
|
||||
EXPORT_DIALOG_SUBTITLE,
|
||||
alertSaveWApi,
|
||||
saveWApiCheckbox,
|
||||
SAVE_WITH_API_CHECKBOX,
|
||||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
|
|
@ -56,10 +56,12 @@ const ExportModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
<label htmlFor="terms" className="export-modal-save-api text-sm ">
|
||||
{saveWApiCheckbox}
|
||||
{SAVE_WITH_API_CHECKBOX}
|
||||
</label>
|
||||
</div>
|
||||
<span className=" text-xs text-destructive ">{alertSaveWApi}</span>
|
||||
<span className=" text-xs text-destructive ">
|
||||
{ALERT_SAVE_WITH_API}
|
||||
</span>
|
||||
</BaseModal.Content>
|
||||
|
||||
<BaseModal.Footer>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useEffect } from "react";
|
|||
import IconComponent from "../../../components/genericIconComponent";
|
||||
import { Textarea } from "../../../components/ui/textarea";
|
||||
import {
|
||||
chatInputPlaceholder,
|
||||
chatInputPlaceholderSend,
|
||||
CHAT_INPUT_PLACEHOLDER,
|
||||
CHAT_INPUT_PLACEHOLDER_SEND,
|
||||
} from "../../../constants/constants";
|
||||
import { chatInputType } from "../../../types/components";
|
||||
import { classNames } from "../../../utils/utils";
|
||||
|
|
@ -55,7 +55,7 @@ export default function ChatInput({
|
|||
? "Thinking..."
|
||||
: typeof chatValue === "object" &&
|
||||
Object.keys(chatValue)?.length === 0
|
||||
? chatInputPlaceholder
|
||||
? CHAT_INPUT_PLACEHOLDER
|
||||
: chatValue
|
||||
}
|
||||
onChange={(event): void => {
|
||||
|
|
@ -70,7 +70,9 @@ export default function ChatInput({
|
|||
|
||||
"form-modal-lockchat"
|
||||
)}
|
||||
placeholder={noInput ? chatInputPlaceholder : chatInputPlaceholderSend}
|
||||
placeholder={
|
||||
noInput ? CHAT_INPUT_PLACEHOLDER : CHAT_INPUT_PLACEHOLDER_SEND
|
||||
}
|
||||
/>
|
||||
<div className="form-modal-send-icon-position">
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export function CodeBlock({ language, value }: Props): JSX.Element {
|
|||
<div className="flex items-center">
|
||||
<button className="code-block-modal-button" onClick={copyToClipboard}>
|
||||
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
|
||||
{isCopied ? "Copied!" : "Copy code"}
|
||||
{isCopied ? "Copied!" : "Copy Code"}
|
||||
</button>
|
||||
<button className="code-block-modal-button" onClick={downloadAsFile}>
|
||||
<IconDownload size={18} />
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@ import {
|
|||
MSG_ERROR_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import {
|
||||
CHAT_FIRST_INITIAL_TEXT,
|
||||
CHAT_FORM_DIALOG_SUBTITLE,
|
||||
chatFirstInitialText,
|
||||
chatSecondInitialText,
|
||||
langflowChatTitle,
|
||||
CHAT_SECOND_INITIAL_TEXT,
|
||||
LANGFLOW_CHAT_TITLE,
|
||||
} from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { getBuildStatus } from "../../controllers/API";
|
||||
|
|
@ -594,20 +594,20 @@ export default function FormModal({
|
|||
<span>
|
||||
👋{" "}
|
||||
<span className="langflow-chat-span">
|
||||
{langflowChatTitle}
|
||||
{LANGFLOW_CHAT_TITLE}
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<div className="langflow-chat-desc">
|
||||
<span className="langflow-chat-desc-span">
|
||||
{chatFirstInitialText}{" "}
|
||||
{CHAT_FIRST_INITIAL_TEXT}{" "}
|
||||
<span>
|
||||
<IconComponent
|
||||
name="MessageSquare"
|
||||
className="mx-1 inline h-5 w-5 animate-bounce "
|
||||
/>
|
||||
</span>{" "}
|
||||
{chatSecondInitialText}
|
||||
{CHAT_SECOND_INITIAL_TEXT}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import {
|
|||
TEMP_NOTICE_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import {
|
||||
EDIT_TEXT_PLACEHOLDER,
|
||||
INVALID_CHARACTERS,
|
||||
MAX_WORDS_HIGHLIGHT,
|
||||
PROMPT_DIALOG_SUBTITLE,
|
||||
TEXT_DIALOG_SUBTITLE,
|
||||
editTextPlaceholder,
|
||||
regexHighlight,
|
||||
} from "../../constants/constants";
|
||||
import { TypeModal } from "../../constants/enums";
|
||||
|
|
@ -97,13 +97,23 @@ export default function GenericModal({
|
|||
useEffect(() => {
|
||||
setInputValue(value);
|
||||
}, [value, modalOpen]);
|
||||
|
||||
const coloredContent = (inputValue || "")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(regexHighlight, varHighlightHTML({ name: "$1" }))
|
||||
.replace(/\n/g, "<br />");
|
||||
.replace(regexHighlight, (match, p1, p2) => {
|
||||
// Decide which group was matched. If p1 is not undefined, do nothing
|
||||
// we don't want to change the text. If p2 is not undefined, then we
|
||||
// have a variable, so we should highlight it.
|
||||
// ! This will not work with multiline or indented json yet
|
||||
if (p1 !== undefined) {
|
||||
return match;
|
||||
} else if (p2 !== undefined) {
|
||||
return varHighlightHTML({ name: p2 });
|
||||
}
|
||||
|
||||
return match;
|
||||
})
|
||||
.replace(/\n/g, "<br />");
|
||||
function getClassByNumberLength(): string {
|
||||
let sumOfCaracteres: number = 0;
|
||||
wordsHighlight.forEach((element) => {
|
||||
|
|
@ -159,7 +169,7 @@ export default function GenericModal({
|
|||
setIsEdit(true);
|
||||
return setErrorData({
|
||||
title: PROMPT_ERROR_ALERT,
|
||||
list: [error.toString()],
|
||||
list: [error.response.data.detail ?? ""],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -217,7 +227,7 @@ export default function GenericModal({
|
|||
setInputValue(event.target.value);
|
||||
checkVariables(event.target.value);
|
||||
}}
|
||||
placeholder={editTextPlaceholder}
|
||||
placeholder={EDIT_TEXT_PLACEHOLDER}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, inputValue, "");
|
||||
}}
|
||||
|
|
@ -239,7 +249,7 @@ export default function GenericModal({
|
|||
onChange={(event) => {
|
||||
setInputValue(event.target.value);
|
||||
}}
|
||||
placeholder={editTextPlaceholder}
|
||||
placeholder={EDIT_TEXT_PLACEHOLDER}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, value, "");
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export default function ShareModal({
|
|||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const [internalOpen, internalSetOpen] = useState(children ? false : true);
|
||||
const [openConfirmationModal, setOpenConfirmationModal] = useState(false);
|
||||
const nameComponent = is_component ? "component" : "flow";
|
||||
const nameComponent = is_component ? "component" : "workflow";
|
||||
|
||||
const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
|
||||
const [loadingTags, setLoadingTags] = useState<boolean>(false);
|
||||
|
|
@ -179,7 +179,7 @@ export default function ShareModal({
|
|||
</span>
|
||||
<br></br>
|
||||
<span className=" text-xs text-destructive ">
|
||||
Warning: This action cannot be undone.
|
||||
Note: This action is irreversible.
|
||||
</span>
|
||||
</ConfirmationModal.Content>
|
||||
</ConfirmationModal>
|
||||
|
|
@ -204,7 +204,7 @@ export default function ShareModal({
|
|||
{children ? children : <></>}
|
||||
</BaseModal.Trigger>
|
||||
<BaseModal.Header
|
||||
description={`Share your ${nameComponent} to the Langflow Store.`}
|
||||
description={`Publish ${is_component ? "your component" : "workflow"} to the Langflow Store.`}
|
||||
>
|
||||
<span className="pr-2">Share</span>
|
||||
<IconComponent
|
||||
|
|
@ -235,12 +235,11 @@ export default function ShareModal({
|
|||
}}
|
||||
/>
|
||||
<label htmlFor="public" className="export-modal-save-api text-sm ">
|
||||
Make {nameComponent} public
|
||||
Set {nameComponent} status to public
|
||||
</label>
|
||||
</div>
|
||||
<span className=" text-xs text-destructive ">
|
||||
<b>Warning:</b> API keys in designated fields are removed when
|
||||
sharing.
|
||||
<b>Attention:</b> API keys in specified fields are automatically removed upon sharing.
|
||||
</span>
|
||||
</BaseModal.Content>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
getNodeId,
|
||||
isValidConnection,
|
||||
reconnectEdges,
|
||||
scapeJSONParse,
|
||||
validateSelection,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
|
||||
|
|
@ -320,6 +321,8 @@ export default function Page({
|
|||
(oldEdge: Edge, newConnection: Connection) => {
|
||||
if (isValidConnection(newConnection, nodes, edges)) {
|
||||
edgeUpdateSuccessful.current = true;
|
||||
oldEdge.data.targetHandle = scapeJSONParse(newConnection.targetHandle!);
|
||||
oldEdge.data.sourceHandle = scapeJSONParse(newConnection.sourceHandle!);
|
||||
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -315,25 +315,6 @@ export default function NodeToolbarComponent({
|
|||
}}
|
||||
data-testid="code-button-modal"
|
||||
>
|
||||
<div className="hidden">
|
||||
<CodeAreaComponent
|
||||
openModal={openModal}
|
||||
setOpenModal={setOpenModal}
|
||||
readonly={
|
||||
data.node?.flow && data.node.template[name].dynamic
|
||||
? true
|
||||
: false
|
||||
}
|
||||
dynamic={data.node?.template[name].dynamic ?? false}
|
||||
setNodeClass={handleNodeClass}
|
||||
nodeClass={data.node}
|
||||
disabled={false}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"code-input-node-toolbar-" + name}
|
||||
selected={selected}
|
||||
/>
|
||||
</div>
|
||||
<IconComponent name="TerminalSquare" className="h-4 w-4" />
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
|
|
@ -382,7 +363,7 @@ export default function NodeToolbarComponent({
|
|||
</button>
|
||||
</ShadTooltip>
|
||||
|
||||
<ShadTooltip content="Pin" side="top">
|
||||
<ShadTooltip content="Freeze" side="top">
|
||||
<button
|
||||
className={classNames(
|
||||
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
|
||||
|
|
@ -402,10 +383,11 @@ export default function NodeToolbarComponent({
|
|||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Pin"
|
||||
name="Snowflake"
|
||||
className={cn(
|
||||
"h-4 w-4 transition-all",
|
||||
pinned ? "animate-wiggle fill-current" : ""
|
||||
// TODO UPDATE THIS COLOR TO BE A VARIABLE
|
||||
pinned ? "animate-wiggle text-ice" : ""
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
|
|
@ -499,7 +481,7 @@ export default function NodeToolbarComponent({
|
|||
value={"Share"}
|
||||
disabled={!hasApiKey || !validApiKey}
|
||||
>
|
||||
<div className="flex" data-testid="save-button-modal">
|
||||
<div className="flex" data-testid="share-button-modal">
|
||||
<IconComponent
|
||||
name="Share3"
|
||||
className="relative top-0.5 -m-1 mr-1 h-6 w-6"
|
||||
|
|
@ -633,6 +615,26 @@ export default function NodeToolbarComponent({
|
|||
is_component={true}
|
||||
component={flowComponent!}
|
||||
/>
|
||||
{hasCode && (
|
||||
<div className="hidden">
|
||||
<CodeAreaComponent
|
||||
open={openModal}
|
||||
setOpen={setOpenModal}
|
||||
readonly={
|
||||
data.node?.flow && data.node.template[name].dynamic
|
||||
? true
|
||||
: false
|
||||
}
|
||||
dynamic={data.node?.template[name].dynamic ?? false}
|
||||
setNodeClass={handleNodeClass}
|
||||
nodeClass={data.node}
|
||||
disabled={false}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"code-input-node-toolbar-" + name}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default function ComponentsComponent({
|
|||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [pageSize, setPageSize] = useState(20);
|
||||
const [pageIndex, setPageIndex] = useState(1);
|
||||
const [loadingScreen, setLoadingScreen] = useState(true);
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ export default function ComponentsComponent({
|
|||
|
||||
function resetFilter() {
|
||||
setPageIndex(1);
|
||||
setPageSize(10);
|
||||
setPageSize(20);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import SidebarNav from "../../components/sidebarComponent";
|
|||
import { Button } from "../../components/ui/button";
|
||||
import { CONSOLE_ERROR_MSG } from "../../constants/alerts_constants";
|
||||
import {
|
||||
MY_COLLECTION_DESC,
|
||||
USER_PROJECTS_HEADER,
|
||||
myCollectionDesc,
|
||||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
|
|
@ -75,7 +75,7 @@ export default function HomePage(): JSX.Element {
|
|||
return (
|
||||
<PageLayout
|
||||
title={USER_PROJECTS_HEADER}
|
||||
description={myCollectionDesc}
|
||||
description={MY_COLLECTION_DESC}
|
||||
button={
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
INVALID_API_ERROR_ALERT,
|
||||
NOAPI_ERROR_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import { storeDesc, storeTitle } from "../../constants/constants";
|
||||
import { STORE_DESC, STORE_TITLE } from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { getStoreComponents, getStoreTags } from "../../controllers/API";
|
||||
import StoreApiKeyModal from "../../modals/StoreApiKeyModal";
|
||||
|
|
@ -174,8 +174,8 @@ export default function StorePage(): JSX.Element {
|
|||
return (
|
||||
<PageLayout
|
||||
betaIcon
|
||||
title={storeTitle}
|
||||
description={storeDesc}
|
||||
title={STORE_TITLE}
|
||||
description={STORE_DESC}
|
||||
button={
|
||||
<>
|
||||
{StoreApiKeyModal && (
|
||||
|
|
|
|||
|
|
@ -187,10 +187,12 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
typeof change === "function"
|
||||
? change(get().nodes.find((node) => node.id === id)!)
|
||||
: change;
|
||||
|
||||
get().setNodes((oldNodes) =>
|
||||
oldNodes.map((node) => {
|
||||
if (node.id === id) {
|
||||
if((node.data as NodeDataType).node?.pinned){
|
||||
(newChange.data as NodeDataType).node!.pinned = false;
|
||||
}
|
||||
return newChange;
|
||||
}
|
||||
return node;
|
||||
|
|
@ -223,12 +225,10 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
selection.nodes.some((node) => node.data.type === "ChatInput") &&
|
||||
checkChatInput(get().nodes)
|
||||
) {
|
||||
useAlertStore
|
||||
.getState()
|
||||
.setErrorData({
|
||||
title: "Error pasting components",
|
||||
list: ["You can only have one ChatInput component in the flow"],
|
||||
});
|
||||
useAlertStore.getState().setErrorData({
|
||||
title: "Error pasting components",
|
||||
list: ["You can only have one ChatInput component in the flow"],
|
||||
});
|
||||
return;
|
||||
}
|
||||
let minimumX = Infinity;
|
||||
|
|
@ -418,10 +418,12 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
});
|
||||
},
|
||||
buildFlow: async ({
|
||||
nodeId,
|
||||
startNodeId,
|
||||
stopNodeId,
|
||||
input_value,
|
||||
}: {
|
||||
nodeId?: string;
|
||||
startNodeId?: string;
|
||||
stopNodeId?: string;
|
||||
input_value?: string;
|
||||
}) => {
|
||||
get().setIsBuilding(true);
|
||||
|
|
@ -446,25 +448,52 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
function handleBuildUpdate(
|
||||
vertexBuildData: VertexBuildTypeAPI,
|
||||
status: BuildStatus,
|
||||
buildId: string
|
||||
runId: string
|
||||
) {
|
||||
if (vertexBuildData && vertexBuildData.inactive_vertices) {
|
||||
get().removeFromVerticesBuild(vertexBuildData.inactive_vertices);
|
||||
}
|
||||
if (vertexBuildData.next_vertices_ids) {
|
||||
// next_vertices_ids is a list of vertices that are going to be built next
|
||||
// verticesLayers is a list of list of vertices ids, where each list is a layer of vertices
|
||||
// we want to add a new layer (next_vertices_ids) to the list of layers (verticesLayers)
|
||||
// and the values of next_vertices_ids to the list of vertices ids (verticesIds)
|
||||
const newLayers = [
|
||||
...get().verticesBuild!.verticesLayers,
|
||||
vertexBuildData.next_vertices_ids,
|
||||
];
|
||||
const newIds = [
|
||||
...get().verticesBuild!.verticesIds,
|
||||
...vertexBuildData.next_vertices_ids,
|
||||
];
|
||||
get().updateVerticesBuild({
|
||||
verticesIds: newIds,
|
||||
verticesLayers: newLayers,
|
||||
runId: runId,
|
||||
});
|
||||
get().updateBuildStatus(
|
||||
vertexBuildData.next_vertices_ids,
|
||||
BuildStatus.TO_BUILD
|
||||
);
|
||||
}
|
||||
|
||||
get().addDataToFlowPool(
|
||||
{ ...vertexBuildData, buildId },
|
||||
{ ...vertexBuildData, buildId: runId },
|
||||
vertexBuildData.id
|
||||
);
|
||||
|
||||
useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status);
|
||||
}
|
||||
await buildVertices({
|
||||
input_value,
|
||||
flowId: currentFlow!.id,
|
||||
nodeId,
|
||||
startNodeId,
|
||||
stopNodeId,
|
||||
onGetOrderSuccess: () => {
|
||||
setNoticeData({ title: "Running components" });
|
||||
},
|
||||
onBuildComplete: () => {
|
||||
const nodeId = startNodeId || stopNodeId;
|
||||
if (nodeId) {
|
||||
setSuccessData({
|
||||
title: `${
|
||||
|
|
@ -481,12 +510,14 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
onBuildError: (title, list, idList) => {
|
||||
useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILT);
|
||||
setErrorData({ list, title });
|
||||
get().setIsBuilding(false);
|
||||
},
|
||||
onBuildStart: (idList) => {
|
||||
useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILDING);
|
||||
},
|
||||
validateNodes: validateSubgraph,
|
||||
});
|
||||
get().setIsBuilding(false);
|
||||
get().revertBuiltStatusFromBuilding();
|
||||
},
|
||||
getFlow: () => {
|
||||
|
|
@ -499,11 +530,11 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
updateVerticesBuild: (
|
||||
vertices: {
|
||||
verticesIds: string[];
|
||||
verticesOrder: string[][];
|
||||
verticesLayers: string[][];
|
||||
runId: string;
|
||||
} | null
|
||||
) => {
|
||||
console.log("updateVerticesBuild", vertices);
|
||||
set({ verticesBuild: vertices });
|
||||
},
|
||||
verticesBuild: null,
|
||||
|
|
@ -520,17 +551,25 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
});
|
||||
},
|
||||
updateBuildStatus: (nodeIdList: string[], status: BuildStatus) => {
|
||||
console.log("updateBuildStatus", nodeIdList, status);
|
||||
const newFlowBuildStatus = { ...get().flowBuildStatus };
|
||||
nodeIdList.forEach((id) => {
|
||||
newFlowBuildStatus[id] = status;
|
||||
newFlowBuildStatus[id] = {
|
||||
status,
|
||||
};
|
||||
if (status == BuildStatus.BUILT) {
|
||||
const timestamp_string = new Date(Date.now()).toLocaleString();
|
||||
newFlowBuildStatus[id].timestamp = timestamp_string;
|
||||
}
|
||||
console.log("updateBuildStatus", newFlowBuildStatus);
|
||||
});
|
||||
set({ flowBuildStatus: newFlowBuildStatus });
|
||||
},
|
||||
revertBuiltStatusFromBuilding: () => {
|
||||
const newFlowBuildStatus = { ...get().flowBuildStatus };
|
||||
Object.keys(newFlowBuildStatus).forEach((id) => {
|
||||
if (newFlowBuildStatus[id] === BuildStatus.BUILDING) {
|
||||
newFlowBuildStatus[id] = BuildStatus.BUILT;
|
||||
if (newFlowBuildStatus[id].status === BuildStatus.BUILDING) {
|
||||
newFlowBuildStatus[id].status = BuildStatus.BUILT;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -845,13 +845,13 @@
|
|||
}
|
||||
|
||||
.api-modal-tabs {
|
||||
@apply flex h-full max-w-full flex-col overflow-hidden rounded-md border bg-muted text-center sm:w-[75vw] md:w-[75vw] lg:w-[75vw] xl:w-[76vw] 2xl:w-full;
|
||||
@apply flex h-full flex-col overflow-hidden rounded-md border bg-muted text-center;
|
||||
}
|
||||
.api-modal-tablist-div {
|
||||
@apply flex items-center justify-between px-2 py-2;
|
||||
}
|
||||
.api-modal-tabs-content {
|
||||
@apply -mt-1 h-full w-full px-4 pb-4;
|
||||
@apply -mt-1 h-full w-full px-4 pb-4;
|
||||
}
|
||||
.api-modal-accordion-display {
|
||||
@apply mt-2 flex h-full w-full;
|
||||
|
|
@ -902,7 +902,7 @@
|
|||
@apply flex-max-width px-2 py-6 pl-4 pr-9;
|
||||
}
|
||||
.form-modal-chatbot-icon {
|
||||
@apply mb-3 ml-3 mr-6 mt-1;
|
||||
@apply flex flex-col mb-3 ml-3 mr-6 mt-1;
|
||||
}
|
||||
.form-modal-chat-image {
|
||||
@apply flex flex-col items-center gap-1;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
--radius: 0.5rem;
|
||||
--ring: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
|
||||
--round-btn-shadow: #00000063;
|
||||
--ice: #31a3cc;
|
||||
|
||||
--error-background: #fef2f2;
|
||||
--error-foreground: #991b1b;
|
||||
|
|
@ -67,6 +68,7 @@
|
|||
.dark {
|
||||
--background: 224 35% 7.5%; /* hsl(224 40% 10%) */
|
||||
--foreground: 213 31% 80%; /* hsl(213 31% 91%) */
|
||||
--ice: #60A5FA;
|
||||
|
||||
--muted: 223 27% 11%; /* hsl(223 27% 11%) */
|
||||
--muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ export type TemplateVariableType = {
|
|||
input_types?: Array<string>;
|
||||
display_name?: string;
|
||||
name?: string;
|
||||
refresh?: boolean;
|
||||
[key: string]: any;
|
||||
};
|
||||
export type sendAllProps = {
|
||||
|
|
@ -134,13 +135,15 @@ export type Component = {
|
|||
};
|
||||
|
||||
export type VerticesOrderTypeAPI = {
|
||||
ids: Array<Array<string>>;
|
||||
ids: Array<string>;
|
||||
run_id: string;
|
||||
};
|
||||
|
||||
export type VertexBuildTypeAPI = {
|
||||
id: string;
|
||||
next_vertices_ids: Array<string>;
|
||||
inactive_vertices: Array<string> | null;
|
||||
run_id: string;
|
||||
valid: boolean;
|
||||
params: string;
|
||||
data: VertexDataTypeAPI;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ export type ToggleComponentType = {
|
|||
disabled: boolean | undefined;
|
||||
size: "small" | "medium" | "large";
|
||||
id?: string;
|
||||
editNode?: boolean;
|
||||
};
|
||||
export type DropDownComponentType = {
|
||||
isLoading?: boolean;
|
||||
value: string;
|
||||
options: string[];
|
||||
onSelect: (value: string) => void;
|
||||
|
|
@ -113,8 +115,8 @@ export type CodeAreaComponentType = {
|
|||
dynamic?: boolean;
|
||||
id?: string;
|
||||
readonly?: boolean;
|
||||
openModal?: boolean;
|
||||
selected?: boolean;
|
||||
open?: boolean;
|
||||
setOpen?: (open: boolean) => void;
|
||||
};
|
||||
|
||||
export type FileComponentType = {
|
||||
|
|
@ -521,8 +523,8 @@ export type codeAreaModalPropsType = {
|
|||
children: ReactNode;
|
||||
dynamic?: boolean;
|
||||
readonly?: boolean;
|
||||
openModal?: boolean;
|
||||
selected?: boolean;
|
||||
open?: boolean;
|
||||
setOpen?: (open: boolean) => void;
|
||||
};
|
||||
|
||||
export type chatMessagePropsType = {
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ export type FlowPoolType = {
|
|||
|
||||
export type FlowStoreType = {
|
||||
flowPool: FlowPoolType;
|
||||
inputs: Array<{ type: string; id: string }>;
|
||||
outputs: Array<{ type: string; id: string }>;
|
||||
inputs: Array<{ type: string; id: string; displayName: string }>;
|
||||
outputs: Array<{ type: string; id: string; displayName: string }>;
|
||||
hasIO: boolean;
|
||||
setFlowPool: (flowPool: FlowPoolType) => void;
|
||||
addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => void;
|
||||
|
|
@ -90,10 +90,13 @@ export type FlowStoreType = {
|
|||
onConnect: (connection: Connection) => void;
|
||||
unselectAll: () => void;
|
||||
buildFlow: ({
|
||||
nodeId,
|
||||
startNodeId,
|
||||
stopNodeId,
|
||||
input_value,
|
||||
}: {
|
||||
nodeId?: string;
|
||||
startNodeId?: string;
|
||||
stopNodeId?: string;
|
||||
input_value?: string;
|
||||
}) => Promise<void>;
|
||||
getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport };
|
||||
|
|
@ -101,7 +104,6 @@ export type FlowStoreType = {
|
|||
vertices: {
|
||||
verticesIds: string[];
|
||||
verticesLayers: string[][];
|
||||
verticesOrder: string[][];
|
||||
runId: string;
|
||||
} | null
|
||||
) => void;
|
||||
|
|
@ -109,12 +111,13 @@ export type FlowStoreType = {
|
|||
verticesBuild: {
|
||||
verticesIds: string[];
|
||||
verticesLayers: string[][];
|
||||
verticesOrder: string[][];
|
||||
runId: string;
|
||||
} | null;
|
||||
updateBuildStatus: (nodeId: string[], status: BuildStatus) => void;
|
||||
revertBuiltStatusFromBuilding: () => void;
|
||||
flowBuildStatus: { [key: string]: BuildStatus };
|
||||
flowBuildStatus: {
|
||||
[key: string]: { status: BuildStatus; timestamp?: string };
|
||||
};
|
||||
updateFlowPool: (
|
||||
nodeId: string,
|
||||
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import { VertexBuildTypeAPI } from "../types/api";
|
|||
type BuildVerticesParams = {
|
||||
flowId: string; // Assuming FlowType is the type for your flow
|
||||
input_value?: any; // Replace any with the actual type if it's not any
|
||||
nodeId?: string | null; // Assuming nodeId is of type string, and it's optional
|
||||
startNodeId?: string | null; // Assuming nodeId is of type string, and it's optional
|
||||
stopNodeId?: string | null; // Assuming nodeId is of type string, and it's optional
|
||||
onGetOrderSuccess?: () => void;
|
||||
onBuildUpdate?: (
|
||||
data: VertexBuildTypeAPI,
|
||||
|
|
@ -31,6 +32,8 @@ function getInactiveVertexData(vertexId: string): VertexBuildTypeAPI {
|
|||
id: vertexId,
|
||||
data: inactiveData,
|
||||
params: "Inactive",
|
||||
run_id: "",
|
||||
next_vertices_ids: [],
|
||||
inactive_vertices: null,
|
||||
valid: false,
|
||||
timestamp: new Date().toISOString(),
|
||||
|
|
@ -41,18 +44,18 @@ function getInactiveVertexData(vertexId: string): VertexBuildTypeAPI {
|
|||
|
||||
export async function updateVerticesOrder(
|
||||
flowId: string,
|
||||
nodeId: string | null
|
||||
startNodeId?: string | null,
|
||||
stopNodeId?: string | null
|
||||
): Promise<{
|
||||
verticesLayers: string[][];
|
||||
verticesIds: string[];
|
||||
verticesOrder: string[][];
|
||||
runId: string;
|
||||
}> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const setErrorData = useAlertStore.getState().setErrorData;
|
||||
let orderResponse;
|
||||
try {
|
||||
orderResponse = await getVerticesOrder(flowId, nodeId);
|
||||
orderResponse = await getVerticesOrder(flowId, startNodeId, stopNodeId);
|
||||
} catch (error: any) {
|
||||
console.log(error);
|
||||
setErrorData({
|
||||
|
|
@ -62,43 +65,40 @@ export async function updateVerticesOrder(
|
|||
useFlowStore.getState().setIsBuilding(false);
|
||||
throw new Error("Invalid nodes");
|
||||
}
|
||||
let verticesOrder: Array<Array<string>> = orderResponse.data.ids;
|
||||
let verticesLayers: Array<Array<string>> = [orderResponse.data.ids];
|
||||
const runId = orderResponse.data.run_id;
|
||||
let verticesLayers: Array<Array<string>> = [];
|
||||
|
||||
if (nodeId) {
|
||||
for (let i = 0; i < verticesOrder.length; i += 1) {
|
||||
const innerArray = verticesOrder[i];
|
||||
const idIndex = innerArray.indexOf(nodeId);
|
||||
if (idIndex !== -1) {
|
||||
// If there's a nodeId, we want to run just that component and not the entire layer
|
||||
// because a layer contains dependencies for the next layer
|
||||
// and we are stopping at the layer that contains the nodeId
|
||||
verticesLayers.push([innerArray[idIndex]]);
|
||||
break; // Stop searching after finding the first occurrence
|
||||
}
|
||||
// If the targetId is not found, include the entire inner array
|
||||
verticesLayers.push(innerArray);
|
||||
}
|
||||
} else {
|
||||
verticesLayers = verticesOrder;
|
||||
}
|
||||
|
||||
const verticesIds = verticesLayers.flat();
|
||||
// if (nodeId) {
|
||||
// for (let i = 0; i < verticesOrder.length; i += 1) {
|
||||
// const innerArray = verticesOrder[i];
|
||||
// const idIndex = innerArray.indexOf(nodeId);
|
||||
// if (idIndex !== -1) {
|
||||
// // If there's a nodeId, we want to run just that component and not the entire layer
|
||||
// // because a layer contains dependencies for the next layer
|
||||
// // and we are stopping at the layer that contains the nodeId
|
||||
// verticesLayers.push([innerArray[idIndex]]);
|
||||
// break; // Stop searching after finding the first occurrence
|
||||
// }
|
||||
// // If the targetId is not found, include the entire inner array
|
||||
// verticesLayers.push(innerArray);
|
||||
// }
|
||||
// } else {
|
||||
// verticesLayers = verticesOrder;
|
||||
// }
|
||||
const verticesIds = orderResponse.data.ids;
|
||||
useFlowStore.getState().updateVerticesBuild({
|
||||
verticesLayers,
|
||||
verticesIds,
|
||||
verticesOrder,
|
||||
runId,
|
||||
});
|
||||
resolve({ verticesLayers, verticesIds, verticesOrder, runId });
|
||||
resolve({ verticesLayers, verticesIds, runId });
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildVertices({
|
||||
flowId,
|
||||
input_value,
|
||||
nodeId = null,
|
||||
startNodeId,
|
||||
stopNodeId,
|
||||
onGetOrderSuccess,
|
||||
onBuildUpdate,
|
||||
onBuildComplete,
|
||||
|
|
@ -107,12 +107,17 @@ export async function buildVertices({
|
|||
validateNodes,
|
||||
}: BuildVerticesParams) {
|
||||
let verticesBuild = useFlowStore.getState().verticesBuild;
|
||||
if (!verticesBuild || nodeId) {
|
||||
verticesBuild = await updateVerticesOrder(flowId, nodeId);
|
||||
// if startNodeId and stopNodeId are provided
|
||||
// something is wrong
|
||||
if (startNodeId && stopNodeId) {
|
||||
return;
|
||||
}
|
||||
if (!verticesBuild || startNodeId || stopNodeId) {
|
||||
verticesBuild = await updateVerticesOrder(flowId, startNodeId, stopNodeId);
|
||||
}
|
||||
|
||||
const verticesIds = verticesBuild?.verticesIds!;
|
||||
const verticesLayers = verticesBuild?.verticesLayers!;
|
||||
const verticesOrder = verticesBuild?.verticesOrder!;
|
||||
const runId = verticesBuild?.runId!;
|
||||
let stop = false;
|
||||
|
||||
|
|
@ -120,7 +125,8 @@ export async function buildVertices({
|
|||
|
||||
if (validateNodes) {
|
||||
try {
|
||||
validateNodes(verticesOrder.flatMap((id) => id));
|
||||
const nodes = useFlowStore.getState().nodes;
|
||||
validateNodes(nodes.map((node) => node.id));
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -128,49 +134,83 @@ export async function buildVertices({
|
|||
|
||||
useFlowStore.getState().updateBuildStatus(verticesIds, BuildStatus.TO_BUILD);
|
||||
useFlowStore.getState().setIsBuilding(true);
|
||||
|
||||
let currentLayerIndex = 0; // Start with the first layer
|
||||
// Set each vertex state to building
|
||||
const buildResults: Array<boolean> = [];
|
||||
for (const layer of verticesLayers) {
|
||||
if (onBuildStart) onBuildStart(layer);
|
||||
for (const id of layer) {
|
||||
// Check if id is in the list of inactive nodes
|
||||
if (!verticesIds.includes(id) && onBuildUpdate) {
|
||||
// If it is, skip building and set the state to inactive
|
||||
onBuildUpdate(getInactiveVertexData(id), BuildStatus.INACTIVE, runId);
|
||||
buildResults.push(false);
|
||||
continue;
|
||||
}
|
||||
await buildVertex({
|
||||
flowId,
|
||||
id,
|
||||
input_value,
|
||||
onBuildUpdate: (data: VertexBuildTypeAPI, status: BuildStatus) => {
|
||||
if (onBuildUpdate) onBuildUpdate(data, status, runId);
|
||||
},
|
||||
onBuildError,
|
||||
verticesIds,
|
||||
buildResults,
|
||||
stopBuild: () => {
|
||||
stop = true;
|
||||
},
|
||||
});
|
||||
if (stop) {
|
||||
break;
|
||||
|
||||
// Build each layer
|
||||
while (
|
||||
currentLayerIndex <
|
||||
(useFlowStore.getState().verticesBuild?.verticesLayers! || []).length
|
||||
) {
|
||||
// Get the current layer
|
||||
const currentLayer =
|
||||
useFlowStore.getState().verticesBuild?.verticesLayers![currentLayerIndex];
|
||||
// If there are no more layers, we are done
|
||||
if (!currentLayer) {
|
||||
if (onBuildComplete) {
|
||||
const allNodesValid = buildResults.every((result) => result);
|
||||
onBuildComplete(allNodesValid);
|
||||
useFlowStore.getState().setIsBuilding(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// If there is a callback for the start of the build, call it
|
||||
if (onBuildStart) onBuildStart(currentLayer);
|
||||
// Build each vertex in the current layer
|
||||
await Promise.all(
|
||||
currentLayer.map(async (vertexId) => {
|
||||
// Check if id is in the list of inactive nodes
|
||||
if (
|
||||
!useFlowStore
|
||||
.getState()
|
||||
.verticesBuild?.verticesIds.includes(vertexId) &&
|
||||
onBuildUpdate
|
||||
) {
|
||||
// If it is, skip building and set the state to inactive
|
||||
onBuildUpdate(
|
||||
getInactiveVertexData(vertexId),
|
||||
BuildStatus.INACTIVE,
|
||||
runId
|
||||
);
|
||||
buildResults.push(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the vertex
|
||||
await buildVertex({
|
||||
flowId,
|
||||
id: vertexId,
|
||||
input_value,
|
||||
onBuildUpdate: (data: VertexBuildTypeAPI, status: BuildStatus) => {
|
||||
if (onBuildUpdate) onBuildUpdate(data, status, runId);
|
||||
},
|
||||
onBuildError,
|
||||
verticesIds,
|
||||
buildResults,
|
||||
stopBuild: () => {
|
||||
stop = true;
|
||||
},
|
||||
});
|
||||
if (stop) {
|
||||
return;
|
||||
}
|
||||
})
|
||||
);
|
||||
// Once the current layer is built, move to the next layer
|
||||
currentLayerIndex += 1;
|
||||
|
||||
if (stop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (onBuildComplete) {
|
||||
const allNodesValid = buildResults.every((result) => result);
|
||||
onBuildComplete(allNodesValid);
|
||||
useFlowStore.getState().setIsBuilding(false);
|
||||
if (onBuildComplete) {
|
||||
const allNodesValid = buildResults.every((result) => result);
|
||||
onBuildComplete(allNodesValid);
|
||||
useFlowStore.getState().setIsBuilding(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function buildVertex({
|
||||
flowId,
|
||||
id,
|
||||
|
|
@ -192,6 +232,7 @@ async function buildVertex({
|
|||
}) {
|
||||
try {
|
||||
const buildRes = await postBuildVertex(flowId, id, input_value);
|
||||
|
||||
const buildData: VertexBuildTypeAPI = buildRes.data;
|
||||
if (onBuildUpdate) {
|
||||
if (!buildData.valid) {
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import {
|
|||
INPUT_TYPES,
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
OUTPUT_TYPES,
|
||||
SUCCESS_BUILD,
|
||||
specialCharsRegex,
|
||||
successBuild,
|
||||
} from "../constants/constants";
|
||||
import { downloadFlowsFromDatabase } from "../controllers/API";
|
||||
import {
|
||||
|
|
@ -1092,7 +1092,7 @@ export function getGroupStatus(
|
|||
flow: FlowType,
|
||||
ssData: { [key: string]: { valid: boolean; params: string } }
|
||||
) {
|
||||
let status = { valid: true, params: successBuild };
|
||||
let status = { valid: true, params: SUCCESS_BUILD };
|
||||
const { nodes } = flow.data!;
|
||||
const ids = nodes.map((n: NodeType) => n.data.id);
|
||||
ids.forEach((id) => {
|
||||
|
|
|
|||
|
|
@ -25,15 +25,23 @@ export function getTagsIds(
|
|||
}
|
||||
|
||||
export function getInputsAndOutputs(nodes: Node[]) {
|
||||
let inputs: { type: string; id: string }[] = [];
|
||||
let outputs: { type: string; id: string }[] = [];
|
||||
let inputs: { type: string; id: string; displayName: string }[] = [];
|
||||
let outputs: { type: string; id: string; displayName: string }[] = [];
|
||||
nodes.forEach((node) => {
|
||||
const nodeData: NodeDataType = node.data as NodeDataType;
|
||||
if (isOutputNode(nodeData)) {
|
||||
outputs.push({ type: nodeData.type, id: nodeData.id });
|
||||
outputs.push({
|
||||
type: nodeData.type,
|
||||
id: nodeData.id,
|
||||
displayName: nodeData.node?.display_name ?? nodeData.id,
|
||||
});
|
||||
}
|
||||
if (isInputNode(nodeData)) {
|
||||
inputs.push({ type: nodeData.type, id: nodeData.id });
|
||||
inputs.push({
|
||||
type: nodeData.type,
|
||||
id: nodeData.id,
|
||||
displayName: nodeData.node?.display_name ?? nodeData.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
return { inputs, outputs };
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
BookMarked,
|
||||
BookmarkPlus,
|
||||
Bot,
|
||||
Snowflake,
|
||||
Boxes,
|
||||
Braces,
|
||||
Cable,
|
||||
|
|
@ -82,6 +83,7 @@ import {
|
|||
Network,
|
||||
Paperclip,
|
||||
Pencil,
|
||||
PencilLine,
|
||||
Pin,
|
||||
Play,
|
||||
Plus,
|
||||
|
|
@ -383,6 +385,7 @@ export const nodeIconsLucide: iconsType = {
|
|||
Clipboard,
|
||||
Code2,
|
||||
Variable,
|
||||
Snowflake,
|
||||
Store,
|
||||
Download,
|
||||
Eraser,
|
||||
|
|
@ -419,6 +422,7 @@ export const nodeIconsLucide: iconsType = {
|
|||
Group,
|
||||
LogIn,
|
||||
ChevronUp,
|
||||
PencilLine,
|
||||
Ungroup,
|
||||
BookMarked,
|
||||
Minus,
|
||||
|
|
|
|||
|
|
@ -640,7 +640,5 @@ export function getFieldTitle(
|
|||
): string {
|
||||
return template[templateField].display_name
|
||||
? template[templateField].display_name!
|
||||
: template[templateField].name
|
||||
? toTitleCase(template[templateField].name!, true)
|
||||
: toTitleCase(templateField, true);
|
||||
: template[templateField].name ?? templateField;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ module.exports = {
|
|||
"beta-foreground": "var(--beta-foreground)",
|
||||
"chat-bot-icon": "var(--chat-bot-icon)",
|
||||
"chat-user-icon": "var(--chat-user-icon)",
|
||||
"ice": "var(--ice)",
|
||||
|
||||
white: "var(--white)",
|
||||
border: "hsl(var(--border))",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -2,19 +2,11 @@ import { test } from "@playwright/test";
|
|||
|
||||
test.describe("Auto_login tests", () => {
|
||||
test("auto_login sign in", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
});
|
||||
|
||||
test("auto_login block_admin", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.goto("http:localhost:3000/login");
|
||||
|
|
@ -117,7 +117,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showcode"]').click();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="code-area-edit0"]').click();
|
||||
await page.locator('//*[@id="code-area-editcode"]').click();
|
||||
|
||||
let value = await page.locator('//*[@id="codeValue"]').inputValue();
|
||||
|
||||
|
|
@ -132,6 +132,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
|
|||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
await page.locator('//*[@id="code-input-0"]').click();
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
await page.getByTestId("code-button-modal").click();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,21 +4,11 @@ import { readFileSync } from "fs";
|
|||
test.describe("drag and drop test", () => {
|
||||
/// <reference lib="dom"/>
|
||||
test("drop collection", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/onlyFront/assets/collection.json",
|
||||
"tests/end-to-end/assets/collection.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
|
|
@ -42,9 +32,7 @@ test.describe("drag and drop test", () => {
|
|||
}
|
||||
);
|
||||
|
||||
await page
|
||||
.getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0")
|
||||
.click();
|
||||
await page.getByText("Edit Flow").first().click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const genericNoda = page.getByTestId("div-generic-node");
|
||||
|
|
@ -1,17 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("dropDownComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/backend_12112023.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -24,24 +13,24 @@ test("dropDownComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(2000);
|
||||
|
||||
await page
|
||||
.getByTestId("llmsAmazon Bedrock")
|
||||
.getByTestId("model_specsAmazon Bedrock")
|
||||
.first()
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.getByTestId("dropdown-2-display").click();
|
||||
await page.getByTestId("dropdown-model_id-display").click();
|
||||
await page.getByTestId("ai21.j2-grande-instruct-0-option").click();
|
||||
|
||||
let value = await page.getByTestId("dropdown-2-display").innerText();
|
||||
let value = await page.getByTestId("dropdown-model_id-display").innerText();
|
||||
if (value !== "ai21.j2-grande-instruct") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("dropdown-2-display").click();
|
||||
await page.getByTestId("dropdown-model_id-display").click();
|
||||
await page.getByTestId("ai21.j2-jumbo-instruct-1-option").click();
|
||||
|
||||
value = await page.getByTestId("dropdown-2-display").innerText();
|
||||
value = await page.getByTestId("dropdown-model_id-display").innerText();
|
||||
if (value !== "ai21.j2-jumbo-instruct") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
|
@ -49,14 +38,14 @@ test("dropDownComponent", async ({ page }) => {
|
|||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
value = await page.getByTestId("dropdown-edit-1-display").innerText();
|
||||
value = await page.getByTestId("dropdown-edit-model_id-display").innerText();
|
||||
if (value !== "ai21.j2-jumbo-instruct") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
// showcode
|
||||
await page.locator('//*[@id="showcode"]').click();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
|
||||
|
||||
// showmodel_id
|
||||
await page.locator('//*[@id="showmodel_id"]').click();
|
||||
|
|
@ -64,7 +53,7 @@ test("dropDownComponent", async ({ page }) => {
|
|||
|
||||
// showcode
|
||||
await page.locator('//*[@id="showcode"]').click();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
|
||||
|
||||
// showmodel_id
|
||||
await page.locator('//*[@id="showmodel_id"]').click();
|
||||
|
|
@ -74,7 +63,7 @@ test("dropDownComponent", async ({ page }) => {
|
|||
|
||||
// showcode
|
||||
await page.locator('//*[@id="showcode"]').click();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
|
||||
|
||||
// showmodel_id
|
||||
await page.locator('//*[@id="showmodel_id"]').click();
|
||||
|
|
@ -82,7 +71,7 @@ test("dropDownComponent", async ({ page }) => {
|
|||
|
||||
// showcode
|
||||
await page.locator('//*[@id="showcode"]').click();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
|
||||
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
|
||||
|
||||
// showmodel_id
|
||||
await page.locator('//*[@id="showmodel_id"]').click();
|
||||
|
|
@ -90,17 +79,17 @@ test("dropDownComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showmodel_id"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.getByTestId("dropdown-edit-1-display").click();
|
||||
await page.getByTestId("dropdown-edit-model_id-display").click();
|
||||
await page.getByTestId("ai21.j2-ultra-v1-5-option").click();
|
||||
|
||||
value = await page.getByTestId("dropdown-edit-1-display").innerText();
|
||||
value = await page.getByTestId("dropdown-edit-model_id-display").innerText();
|
||||
if (value !== "ai21.j2-ultra-v1") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
value = await page.getByTestId("dropdown-2-display").innerText();
|
||||
value = await page.getByTestId("dropdown-model_id-display").innerText();
|
||||
if (value !== "ai21.j2-ultra-v1") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("FloatComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/backend_12112023.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -23,7 +13,7 @@ test("FloatComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(2000);
|
||||
|
||||
await page
|
||||
.locator('//*[@id="llmsLlamaCpp"]')
|
||||
.locator('//*[@id="model_specsLlamaCpp"]')
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
|
@ -102,18 +92,6 @@ test("FloatComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showmax_tokens"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showmetadata
|
||||
await page.locator('//*[@id="showmetadata"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showmetadata"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showmodel_kwargs
|
||||
await page.locator('//*[@id="showmodel_kwargs"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showmodel_path
|
||||
await page.locator('//*[@id="showmodel_path"]').click();
|
||||
expect(
|
||||
|
|
@ -271,16 +249,6 @@ test("FloatComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showmax_tokens"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showmetadata
|
||||
await page.locator('//*[@id="showmetadata"]').click();
|
||||
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
|
||||
|
||||
// showmodel_kwargs
|
||||
await page.locator('//*[@id="showmodel_kwargs"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showmodel_path
|
||||
await page.locator('//*[@id="showmodel_path"]').click();
|
||||
expect(
|
||||
|
|
@ -7,16 +7,6 @@ test.describe("Flow Page tests", () => {
|
|||
}
|
||||
|
||||
test("save", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/backend_12112023.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -4,21 +4,11 @@ import { readFileSync } from "fs";
|
|||
test.describe("group node test", () => {
|
||||
/// <reference lib="dom"/>
|
||||
test("group and ungroup updating values", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/onlyFront/assets/collection.json",
|
||||
"tests/end-to-end/assets/flow_group_test.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
|
|
@ -26,7 +16,7 @@ test.describe("group node test", () => {
|
|||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "flowtest.json", {
|
||||
const file = new File([data], "flow_group_test.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
|
|
@ -35,24 +25,27 @@ test.describe("group node test", () => {
|
|||
|
||||
page.waitForTimeout(2000);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent(
|
||||
'//*[@id="root"]/div/div[1]/div[2]/div[3]/div/div',
|
||||
"//*[@id='react-flow-id']/div[1]/div[1]/div",
|
||||
"drop",
|
||||
{
|
||||
dataTransfer,
|
||||
}
|
||||
);
|
||||
|
||||
await page
|
||||
.getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0")
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const genericNoda = page.getByTestId("div-generic-node");
|
||||
const elementCount = await genericNoda.count();
|
||||
if (elementCount > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[3]')
|
||||
.click();
|
||||
|
||||
await page.getByTestId("title-Agent Initializer").click({
|
||||
modifiers: ["Control"],
|
||||
});
|
||||
|
||||
await page.getByTestId("title-PythonFunctionTool").click({
|
||||
modifiers: ["Control"],
|
||||
|
|
@ -61,10 +54,6 @@ test.describe("group node test", () => {
|
|||
modifiers: ["Control"],
|
||||
});
|
||||
|
||||
await page.getByTestId("title-AgentInitializer").click({
|
||||
modifiers: ["Control"],
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Group" }).click();
|
||||
|
||||
const textArea = page.getByTestId("div-textarea-description");
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("InputComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -28,12 +18,12 @@ test("InputComponent", async ({ page }) => {
|
|||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.locator("#input-8").click();
|
||||
await page.getByTestId("input-collection_name").click();
|
||||
await page
|
||||
.locator("#input-8")
|
||||
.getByTestId("input-collection_name")
|
||||
.fill("collection_name_test_123123123!@#$&*(&%$@");
|
||||
|
||||
let value = await page.locator("#input-8").inputValue();
|
||||
let value = await page.getByTestId("input-collection_name").inputValue();
|
||||
|
||||
if (value != "collection_name_test_123123123!@#$&*(&%$@") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -61,9 +51,9 @@ test("InputComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showchroma_server_http_port"]').click();
|
||||
await page.locator('//*[@id="showchroma_server_port"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
|
||||
await page.locator('//*[@id="showchroma_server_port"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
|
||||
|
|
@ -76,19 +66,11 @@ test("InputComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showcollection_name"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showpersist"]').click();
|
||||
expect(await page.locator('//*[@id="showpersist"]').isChecked()).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showpersist_directory"]').click();
|
||||
await page.locator('//*[@id="showindex_directory"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showpersist_directory"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_directory"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click();
|
||||
expect(
|
||||
await page
|
||||
|
|
@ -106,9 +88,9 @@ test("InputComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showchroma_server_http_port"]').click();
|
||||
await page.locator('//*[@id="showchroma_server_port"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
|
||||
await page.locator('//*[@id="showchroma_server_port"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
|
||||
|
|
@ -116,33 +98,27 @@ test("InputComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showpersist"]').click();
|
||||
expect(await page.locator('//*[@id="showpersist"]').isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showpersist_directory"]').click();
|
||||
await page.locator('//*[@id="showindex_directory"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showpersist_directory"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_directory"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
let valueEditNode = await page.locator('//*[@id="input-5"]').inputValue();
|
||||
let valueEditNode = await page
|
||||
.getByTestId("input-collection_name-edit")
|
||||
.inputValue();
|
||||
|
||||
if (valueEditNode != "collection_name_test_123123123!@#$&*(&%$@") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="input-5"]').click();
|
||||
await page.getByTestId("input-collection_name-edit").click();
|
||||
await page
|
||||
.locator('//*[@id="input-5"]')
|
||||
.getByTestId("input-collection_name-edit")
|
||||
.fill("NEW_collection_name_test_123123123!@#$&*(&%$@");
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.locator("#input-8");
|
||||
const plusButtonLocator = page.getByTestId("input-collection_name");
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
|
@ -159,7 +135,7 @@ test("InputComponent", async ({ page }) => {
|
|||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
let value = await page.locator("#input-8").inputValue();
|
||||
let value = await page.getByTestId("input-collection_name").inputValue();
|
||||
|
||||
if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -1,17 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("IntComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/backend_12112023.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -30,21 +19,21 @@ test("IntComponent", async ({ page }) => {
|
|||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.locator('//*[@id="int-input-2"]').click();
|
||||
await page.getByTestId("int-input-timeout").click();
|
||||
await page
|
||||
.locator('//*[@id="int-input-2"]')
|
||||
.getByTestId("int-input-timeout")
|
||||
.fill("123456789123456789123456789");
|
||||
|
||||
let value = await page.locator('//*[@id="int-input-2"]').inputValue();
|
||||
let value = await page.getByTestId("int-input-timeout").inputValue();
|
||||
|
||||
if (value != "123456789123456789123456789") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="int-input-2"]').click();
|
||||
await page.locator('//*[@id="int-input-2"]').fill("0");
|
||||
await page.getByTestId("int-input-timeout").click();
|
||||
await page.getByTestId("int-input-timeout").fill("0");
|
||||
|
||||
value = await page.locator('//*[@id="int-input-2"]').inputValue();
|
||||
value = await page.getByTestId("int-input-timeout").inputValue();
|
||||
|
||||
if (value != "0") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -53,15 +42,15 @@ test("IntComponent", async ({ page }) => {
|
|||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
value = await page.locator('//*[@id="edit-int-input-2"]').inputValue();
|
||||
value = await page.getByTestId("edit-int-input-timeout").inputValue();
|
||||
|
||||
if (value != "0") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="edit-int-input-2"]').click();
|
||||
await page.getByTestId("edit-int-input-timeout").click();
|
||||
await page
|
||||
.locator('//*[@id="edit-int-input-2"]')
|
||||
.getByTestId("edit-int-input-timeout")
|
||||
.fill("123456789123456789123456789");
|
||||
|
||||
await page.locator('//*[@id="showheaders"]').click();
|
||||
|
|
@ -81,7 +70,7 @@ test("IntComponent", async ({ page }) => {
|
|||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.locator('//*[@id="int-input-2"]');
|
||||
const plusButtonLocator = page.getByTestId("int-input-timeout");
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
|
@ -95,7 +84,7 @@ test("IntComponent", async ({ page }) => {
|
|||
).toBeTruthy();
|
||||
|
||||
const valueEditNode = await page
|
||||
.locator('//*[@id="edit-int-input-2"]')
|
||||
.getByTestId("edit-int-input-timeout")
|
||||
.inputValue();
|
||||
|
||||
if (valueEditNode != "123456789123456789123456789") {
|
||||
|
|
@ -103,19 +92,19 @@ test("IntComponent", async ({ page }) => {
|
|||
}
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
await page.locator('//*[@id="int-input-2"]').click();
|
||||
await page.locator('//*[@id="int-input-2"]').fill("3");
|
||||
await page.getByTestId("int-input-timeout").click();
|
||||
await page.getByTestId("int-input-timeout").fill("3");
|
||||
|
||||
let value = await page.locator('//*[@id="int-input-2"]').inputValue();
|
||||
let value = await page.getByTestId("int-input-timeout").inputValue();
|
||||
|
||||
if (value != "3") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="int-input-2"]').click();
|
||||
await page.locator('//*[@id="int-input-2"]').fill("-3");
|
||||
await page.getByTestId("int-input-timeout").click();
|
||||
await page.getByTestId("int-input-timeout").fill("-3");
|
||||
|
||||
value = await page.locator('//*[@id="int-input-2"]').inputValue();
|
||||
value = await page.getByTestId("int-input-timeout").inputValue();
|
||||
|
||||
if (value != "0") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("KeypairListComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/backend_12112023.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("NestedComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/backend_12112023.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -31,75 +21,17 @@ test("NestedComponent", async ({ page }) => {
|
|||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
//showpool_threads
|
||||
await page.locator('//*[@id="showpool_threads"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpool_threads"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
//showtext_key
|
||||
await page.locator('//*[@id="showtext_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showsearch_kwargs
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showsearch_kwargs
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeFalsy();
|
||||
expect(await page.locator('//*[@id="showtext_key"]').isChecked()).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
|
@ -120,21 +52,14 @@ test("NestedComponent", async ({ page }) => {
|
|||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeTruthy();
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showsearch_kwargs
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeTruthy();
|
||||
).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
|
@ -155,21 +80,14 @@ test("NestedComponent", async ({ page }) => {
|
|||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeFalsy();
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showsearch_kwargs
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeFalsy();
|
||||
).toBeTruthy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
|
@ -190,21 +108,14 @@ test("NestedComponent", async ({ page }) => {
|
|||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeTruthy();
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showsearch_kwargs
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
|
||||
).toBeTruthy();
|
||||
).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
|
@ -223,6 +134,34 @@ test("NestedComponent", async ({ page }) => {
|
|||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
|
@ -234,7 +173,47 @@ test("NestedComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_env
|
||||
await page.locator('//*[@id="showpinecone_env"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_env"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
//showpool_threads
|
||||
await page.locator('//*[@id="showpool_threads"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpool_threads"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
//showtext_key
|
||||
await page.locator('//*[@id="showtext_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showtext_key"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
await page.getByTestId("div-dict-input").click();
|
||||
});
|
||||
|
|
@ -8,25 +8,27 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("promptTemplate");
|
||||
await page.getByPlaceholder("Search").fill("prompt");
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page
|
||||
.locator('//*[@id="promptsPromptTemplate"]')
|
||||
.locator('//*[@id="promptsPrompt"]')
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.getByTestId("prompt-input-0").click();
|
||||
await page.getByTestId("prompt-input-template").click();
|
||||
|
||||
// await page.getByTestId("edit-prompt-sanitized").click();
|
||||
// await page.getByTestId("modal-title").click();
|
||||
await page
|
||||
.getByTestId("modal-prompt-input-0")
|
||||
.getByTestId("modal-prompt-input-template")
|
||||
.fill("{prompt} example {prompt1}");
|
||||
|
||||
let value = await page.getByTestId("modal-prompt-input-0").inputValue();
|
||||
let value = await page
|
||||
.getByTestId("modal-prompt-input-template")
|
||||
.inputValue();
|
||||
|
||||
if (value != "{prompt} example {prompt1}") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -45,35 +47,39 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
await page.getByTestId("genericModalBtnSave").click();
|
||||
|
||||
await page.getByTestId("div-textarea-prompt").click();
|
||||
await page.getByTestId("text-area-modal").fill("prompt_value_!@#!@#");
|
||||
await page.getByTestId("textarea-prompt").fill("prompt_value_!@#!@#");
|
||||
|
||||
value = await page.getByTestId("text-area-modal").inputValue();
|
||||
value = await page.getByTestId("textarea-prompt").inputValue();
|
||||
|
||||
if (value != "prompt_value_!@#!@#") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("genericModalBtnSave").click();
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("save-button-modal").click();
|
||||
|
||||
const replace = await page.getByTestId("replace-button");
|
||||
if (replace) {
|
||||
await page.getByTestId("replace-button").click();
|
||||
}
|
||||
|
||||
await page.getByTestId("div-textarea-prompt1").click();
|
||||
await page
|
||||
.getByTestId("text-area-modal")
|
||||
.getByTestId("textarea-prompt1")
|
||||
.fill("prompt_name_test_123123!@#!@#");
|
||||
|
||||
value = await page.getByTestId("text-area-modal").inputValue();
|
||||
value = await page.getByTestId("textarea-prompt1").inputValue();
|
||||
|
||||
if (value != "prompt_name_test_123123!@#!@#") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
value = await page.getByTestId("text-area-modal").inputValue();
|
||||
value = await page.getByTestId("textarea-prompt1").inputValue();
|
||||
|
||||
if (value != "prompt_name_test_123123!@#!@#") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("genericModalBtnSave").click();
|
||||
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,22 +11,12 @@ test.describe("save component tests", () => {
|
|||
|
||||
/// <reference lib="dom"/>
|
||||
test("save group component tests", async ({ page }) => {
|
||||
//make front work withoput backend
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/onlyFront/assets/collection.json",
|
||||
"tests/end-to-end/assets/flow_group_test.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
|
|
@ -34,32 +24,32 @@ test.describe("save component tests", () => {
|
|||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "flowtest.json", {
|
||||
const file = new File([data], "flow_group_test.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
page.waitForTimeout(2000);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent(
|
||||
'//*[@id="root"]/div/div[1]/div[2]/div[3]/div/div',
|
||||
"//*[@id='react-flow-id']/div[1]/div[1]/div",
|
||||
"drop",
|
||||
{
|
||||
dataTransfer,
|
||||
}
|
||||
);
|
||||
|
||||
await page
|
||||
.getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0")
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const genericNoda = page.getByTestId("div-generic-node");
|
||||
const elementCount = await genericNoda.count();
|
||||
if (elementCount > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[3]')
|
||||
.click();
|
||||
|
||||
await page.getByTestId("title-PythonFunctionTool").click({
|
||||
modifiers: ["Control"],
|
||||
|
|
@ -68,7 +58,7 @@ test.describe("save component tests", () => {
|
|||
modifiers: ["Control"],
|
||||
});
|
||||
|
||||
await page.getByTestId("title-AgentInitializer").click({
|
||||
await page.getByTestId("title-Agent Initializer").click({
|
||||
modifiers: ["Control"],
|
||||
});
|
||||
|
||||
|
|
@ -87,9 +77,13 @@ test.describe("save component tests", () => {
|
|||
}
|
||||
|
||||
await page.getByTestId("title-Group").click();
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("save-button-modal").click();
|
||||
await page.getByTestId("delete-button-modal").click();
|
||||
await page.getByTestId("icon-SaveAll").click();
|
||||
|
||||
const replaceButton = page.getByTestId("replace-button");
|
||||
|
||||
if (replaceButton) {
|
||||
await replaceButton.click();
|
||||
}
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("group");
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("ToggleComponent", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
|
@ -38,29 +28,27 @@ test("ToggleComponent", async ({ page }) => {
|
|||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="toggle-edit-1"]').isChecked()
|
||||
).toBeFalsy();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showglob"]').click();
|
||||
expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeFalsy();
|
||||
|
|
@ -129,7 +117,7 @@ test("ToggleComponent", async ({ page }) => {
|
|||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.locator('//*[@id="toggle-1"]');
|
||||
const plusButtonLocator = page.getByTestId("toggle-load_hidden");
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
|
@ -145,24 +133,34 @@ test("ToggleComponent", async ({ page }) => {
|
|||
).toBeTruthy();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="toggle-edit-1"]').isChecked()
|
||||
await page.getByTestId("toggle-edit-load_hidden").isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="toggle-1"]').click();
|
||||
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
import { test } from "@playwright/test";
|
||||
|
||||
test.describe("Login Tests", () => {
|
||||
test("Login_Success", async ({ page }) => {
|
||||
// await page.route("**/api/v1/login", async (route) => {
|
||||
// const json = {
|
||||
// access_token:
|
||||
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWNlM2FkOS1iZTE2LTRiNjgtOGRhYi1hYjA4YTVjMmZjZTkiLCJleHAiOjE2OTUyNTIwNTh9.MBYFwMhTcZnsW_L7p4qavUhSDylCllJQWUCJdU1wX8o",
|
||||
// refresh_token:
|
||||
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWNlM2FkOS1iZTE2LTRiNjgtOGRhYi1hYjA4YTVjMmZjZTkiLCJ0eXBlIjoicmYiLCJleHAiOjE2OTUyNTI2NTh9.a4wL9-XK_zyTyrXduBFgCsODFXrqiByVr5HOeiCbiQA",
|
||||
// token_type: "bearer",
|
||||
// };
|
||||
// await route.fulfill({ json });
|
||||
// });
|
||||
// await page.goto("http://localhost:3000/");
|
||||
// await page.waitForURL("http://localhost:3000/login");
|
||||
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
|
||||
// await page.getByPlaceholder("Username").click();
|
||||
// await page.getByPlaceholder("Username").fill("test");
|
||||
// await page.getByPlaceholder("Password").click();
|
||||
// await page.getByPlaceholder("Password").fill("test");
|
||||
// await page.getByRole("button", { name: "Sign in" }).click();
|
||||
// await page.getByRole("button", { name: "Community Examples" }).click();
|
||||
// await page.waitForSelector(".community-pages-flows-panel");
|
||||
// expect(
|
||||
// await page
|
||||
// .locator(".community-pages-flows-panel")
|
||||
// .evaluate((el) => el.children)
|
||||
// ).toBeTruthy();
|
||||
// });
|
||||
// test("Login Error", async ({ page }) => {
|
||||
// await page.route("**/api/v1/login", async (route) => {
|
||||
// const json = { detail: "Incorrect username or password" };
|
||||
// await route.fulfill({ json, status: 401 });
|
||||
// });
|
||||
// await page.goto("http://localhost:3000/");
|
||||
// await page.waitForURL("http://localhost:3000/login");
|
||||
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
|
||||
// await page.getByPlaceholder("Username").click();
|
||||
// await page.getByPlaceholder("Username").fill("test");
|
||||
// await page.getByPlaceholder("Password").click();
|
||||
// await page.getByPlaceholder("Password").fill("test5");
|
||||
// await page.getByRole("button", { name: "Sign in" }).click();
|
||||
// await page.getByRole("heading", { name: "Error signing in" }).click();
|
||||
// });
|
||||
// test("Login create account wrong form", async ({ page }) => {
|
||||
// const fullfillForm = async (username, password, confirmPassword) => {
|
||||
// await page.getByPlaceholder("Username").click();
|
||||
// await page.getByPlaceholder("Username").fill(username);
|
||||
// await page.getByPlaceholder("Password", { exact: true }).click();
|
||||
// await page.getByPlaceholder("Password", { exact: true }).fill(password);
|
||||
// await page.getByPlaceholder("Confirm your password").click();
|
||||
// await page
|
||||
// .getByPlaceholder("Confirm your password")
|
||||
// .fill(confirmPassword);
|
||||
// };
|
||||
// await page.goto("http://localhost:3000/");
|
||||
// await page.waitForURL("http://localhost:3000/login");
|
||||
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
|
||||
// await page
|
||||
// .getByRole("button", { name: "Don't have an account? Sign Up" })
|
||||
// .click();
|
||||
// await page.getByText("Sign up to Langflow").click();
|
||||
// await page.goto("http://localhost:3000/signup");
|
||||
// await page.getByText("Sign up to Langflow").click();
|
||||
// await fullfillForm("name", "vazz", "vazz5");
|
||||
// expect(
|
||||
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
|
||||
// ).toBeTruthy();
|
||||
// await fullfillForm("", "vazz", "vazz");
|
||||
// expect(
|
||||
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
|
||||
// ).toBeTruthy();
|
||||
// await fullfillForm("name", "", "");
|
||||
// expect(
|
||||
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
|
||||
// ).toBeTruthy();
|
||||
// await fullfillForm("", "", "");
|
||||
// expect(
|
||||
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
|
||||
// ).toBeTruthy();
|
||||
// });
|
||||
// test("Login create account success", async ({ page }) => {
|
||||
// await page.route("**/api/v1/users/", async (route) => {
|
||||
// const json = {
|
||||
// id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
// username: "teste",
|
||||
// profile_image: null,
|
||||
// is_active: false,
|
||||
// is_superuser: false,
|
||||
// create_at: "2023-09-21T01:45:51.873303",
|
||||
// updated_at: "2023-09-21T01:45:51.873305",
|
||||
// last_login_at: null,
|
||||
// };
|
||||
// await route.fulfill({ json, status: 201 });
|
||||
// });
|
||||
// const submitForm = async (username, password, confirmPassword) => {
|
||||
// await page.getByPlaceholder("Username").click();
|
||||
// await page.getByPlaceholder("Username").fill(username);
|
||||
// await page.getByPlaceholder("Password", { exact: true }).click();
|
||||
// await page.getByPlaceholder("Password", { exact: true }).fill(password);
|
||||
// await page.getByPlaceholder("Confirm your password").click();
|
||||
// await page
|
||||
// .getByPlaceholder("Confirm your password")
|
||||
// .fill(confirmPassword);
|
||||
// };
|
||||
// await page.goto("http://localhost:3000/");
|
||||
// await page.waitForURL("http://localhost:3000/login");
|
||||
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
|
||||
// await page
|
||||
// .getByRole("button", { name: "Don't have an account? Sign Up" })
|
||||
// .click();
|
||||
// await page.getByText("Sign up to Langflow").click();
|
||||
// await page.goto("http://localhost:3000/signup");
|
||||
// await page.getByText("Sign up to Langflow").click();
|
||||
// await submitForm("teste", "pass", "pass");
|
||||
// await page.getByRole("button", { name: "Sign up" }).click();
|
||||
// await page.waitForURL("http://localhost:3000/login", { timeout: 1000 });
|
||||
// await page.getByText("Account created! Await admin activation.").click();
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue