diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml new file mode 100644 index 000000000..1b46e48b8 --- /dev/null +++ b/.github/workflows/pre-release.yml @@ -0,0 +1,49 @@ +name: pre-release + +on: + pull_request: + types: + - closed + branches: + - dev + paths: + - "pyproject.toml" + +env: + POETRY_VERSION: "1.5.1" + +jobs: + if_release: + if: | + ${{ github.event.pull_request.merged == true }} + && ${{ contains(github.event.pull_request.labels.*.name, 'pre-release') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install poetry + run: pipx install poetry==$POETRY_VERSION + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + cache: "poetry" + - name: Build project for distribution + run: make build + - name: Check Version + id: check-version + run: | + echo version=$(poetry version --short) >> $GITHUB_OUTPUT + - name: Create Release + uses: ncipollo/release-action@v1 + with: + artifacts: "dist/*" + token: ${{ secrets.GITHUB_TOKEN }} + draft: false + generateReleaseNotes: true + tag: v${{ steps.check-version.outputs.version }} + commit: main + - name: Publish to PyPI + env: + POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} + run: | + poetry publish diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d5284ad3..12f72f5f8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ on: - "pyproject.toml" env: - POETRY_VERSION: "1.4.0" + POETRY_VERSION: "1.5.1" jobs: if_release: diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 7af2a6e04..946c79864 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -29,6 +29,7 @@ "@tabler/icons-react": "^2.18.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.4", + "@types/axios": "^0.14.0", "accordion": "^3.0.2", "ace-builds": "^1.16.0", "add": "^2.0.6", @@ -142,6 +143,9 @@ } }, "node_modules/@babel/compat-data": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", + "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==", "version": "7.22.9", "license": "MIT", "engines": { @@ -9533,8 +9537,9 @@ "license": "MIT" }, "node_modules/word-wrap": { - "version": "1.2.3", - "license": "MIT", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "engines": { "node": ">=0.10.0" } diff --git a/src/frontend/package.json b/src/frontend/package.json index 323a9a7be..a5c4d61eb 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -24,6 +24,7 @@ "@tabler/icons-react": "^2.18.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.4", + "@types/axios": "^0.14.0", "accordion": "^3.0.2", "ace-builds": "^1.16.0", "add": "^2.0.6", diff --git a/src/frontend/src/components/codeTabsComponent/index.tsx b/src/frontend/src/components/codeTabsComponent/index.tsx index 9c9337920..1357e0c79 100644 --- a/src/frontend/src/components/codeTabsComponent/index.tsx +++ b/src/frontend/src/components/codeTabsComponent/index.tsx @@ -1,4 +1,5 @@ -import { useContext, useState } from "react"; +import { cloneDeep } from "lodash"; +import { useContext, useEffect, useState } from "react"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import AccordionComponent from "../../components/AccordionComponent"; @@ -54,9 +55,16 @@ export default function CodeTabsComponent({ }; }) { const [isCopied, setIsCopied] = useState(false); + const [data, setData] = useState(flow ? flow["data"]["nodes"] : null); const [openAccordion, setOpenAccordion] = useState([]); const { dark } = useContext(darkContext); + useEffect(() => { + if (flow && flow["data"]["nodes"]) { + setData(flow["data"]["nodes"]); + } + }, [flow]); + const copyToClipboard = () => { if (!navigator.clipboard || !navigator.clipboard.writeText) { return; @@ -185,7 +193,7 @@ export default function CodeTabsComponent({ : "overflow-hidden" )} > - {flow["data"]["nodes"].map((t: any, index) => ( + {data.map((t: any, index) => (
{tweaks.tweaksList.current.includes(t["data"]["id"]) && ( { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, @@ -274,16 +292,29 @@ export default function CodeTabsComponent({ { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, @@ -302,13 +333,27 @@ export default function CodeTabsComponent({ t.data.node.template[n] .password ?? false } - value={tweaks.getValue( + value={ + !t.data.node.template[n] + .value || t.data.node.template[n] - .value, - t.data, - t.data.node.template[n] - )} + .value === "" + ? "" + : t.data.node.template[ + n + ].value + } onChange={(k) => { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, @@ -328,9 +373,16 @@ export default function CodeTabsComponent({ .value } setEnabled={(e) => { - t.data.node.template[ - n - ].value = e; + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = e; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], e, @@ -345,12 +397,13 @@ export default function CodeTabsComponent({ "file" ? (
@@ -382,13 +435,26 @@ export default function CodeTabsComponent({ { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, @@ -410,18 +476,31 @@ export default function CodeTabsComponent({ .options } onSelect={(k) => { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, t.data.node.template[n] ); }} - value={tweaks.getValue( + value={ + !t.data.node.template[n] + .value || t.data.node.template[n] - .value, - t.data, - t.data.node.template[n] - )} + .value === "" + ? "" + : t.data.node.template[n] + .value + } >
) : t.data.node.template[n].type === @@ -430,13 +509,26 @@ export default function CodeTabsComponent({ { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, @@ -449,25 +541,40 @@ export default function CodeTabsComponent({ "prompt" ? (
{ + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, @@ -493,13 +600,27 @@ export default function CodeTabsComponent({ { + setData((old) => { + let newInputList = + cloneDeep(old); + newInputList[ + index + ].data.node.template[ + n + ].value = k; + return newInputList; + }); tweaks.buildTweakObject( t["data"]["id"], k, diff --git a/src/frontend/src/components/floatComponent/index.tsx b/src/frontend/src/components/floatComponent/index.tsx index cf79f3ccb..40d6fc3fe 100644 --- a/src/frontend/src/components/floatComponent/index.tsx +++ b/src/frontend/src/components/floatComponent/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { FloatComponentType } from "../../types/components"; import { Input } from "../ui/input"; @@ -12,12 +12,6 @@ export default function FloatComponent({ const min = 0; const max = 1; - const [myValue, setMyValue] = useState(value); - - useEffect(() => { - setMyValue(value); - }, [value]); - // Clear component state useEffect(() => { if (disabled) { @@ -48,7 +42,6 @@ export default function FloatComponent({ } onChange={(e) => { onChange(e.target.value); - setMyValue(e.target.value); }} />
diff --git a/src/frontend/src/components/inputComponent/index.tsx b/src/frontend/src/components/inputComponent/index.tsx index 6a050105a..78b06c411 100644 --- a/src/frontend/src/components/inputComponent/index.tsx +++ b/src/frontend/src/components/inputComponent/index.tsx @@ -11,11 +11,6 @@ export default function InputComponent({ editNode = false, }: InputComponentType) { const [pwdVisible, setPwdVisible] = useState(false); - const [myValue, setMyValue] = useState(value); - - useEffect(() => { - setMyValue(value); - }, [value]); // Clear component state useEffect(() => { @@ -38,7 +33,6 @@ export default function InputComponent({ placeholder={password && editNode ? "Key" : "Type something..."} onChange={(e) => { onChange(e.target.value); - setMyValue(e.target.value); }} /> {password && ( diff --git a/src/frontend/src/components/inputListComponent/index.tsx b/src/frontend/src/components/inputListComponent/index.tsx index 2ccda91a1..1bda41333 100644 --- a/src/frontend/src/components/inputListComponent/index.tsx +++ b/src/frontend/src/components/inputListComponent/index.tsx @@ -1,10 +1,9 @@ -import { useContext, useEffect, useState } from "react"; +import { useEffect } from "react"; import { InputListComponentType } from "../../types/components"; import { Input } from "../ui/input"; import { classNames } from "../../utils/utils"; import _ from "lodash"; -import { PopUpContext } from "../../contexts/popUpContext"; import IconComponent from "../genericIconComponent"; export default function InputListComponent({ @@ -13,31 +12,21 @@ export default function InputListComponent({ disabled, editNode = false, }: InputListComponentType) { - const [inputList, setInputList] = useState(value ?? [""]); - const { closeEdit } = useContext(PopUpContext); - - useEffect(() => { - if (value) { - setInputList(value); - } - }, [closeEdit]); - useEffect(() => { if (disabled) { - setInputList([""]); onChange([""]); } - }, [disabled, onChange]); + }, [disabled]); return (
1 && editNode ? "my-1" : "", + value.length > 1 && editNode ? "my-1" : "", "flex flex-col gap-3" ) }> - {inputList.map((i, idx) => { + {value.map((i, idx) => { return (
{ - setInputList((old) => { - let newInputList = _.cloneDeep(inputList); - newInputList[idx] = e.target.value; - return newInputList; - }); - onChange(inputList); + let newInputList = _.cloneDeep(value); + newInputList[idx] = e.target.value; + onChange(newInputList); }} /> - {idx === inputList.length - 1 ? ( + {idx === value.length - 1 ? (
diff --git a/src/frontend/src/components/toggleShadComponent/index.tsx b/src/frontend/src/components/toggleShadComponent/index.tsx index aa11a22bb..95ef6d062 100644 --- a/src/frontend/src/components/toggleShadComponent/index.tsx +++ b/src/frontend/src/components/toggleShadComponent/index.tsx @@ -1,4 +1,3 @@ -import { useEffect, useState } from "react"; import { ToggleComponentType } from "../../types/components"; import { Switch } from "../ui/switch"; @@ -27,12 +26,6 @@ export default function ToggleShadComponent({ scaleY = 1; } - const [myValue, setMyValue] = useState(enabled); - - useEffect(() => { - setMyValue(enabled); - }, [enabled]); - return (
{ setEnabled(x); - setMyValue(x); }} >
diff --git a/src/frontend/src/components/ui/accordion.tsx b/src/frontend/src/components/ui/accordion.tsx index 4add6c8ac..27dbba93b 100644 --- a/src/frontend/src/components/ui/accordion.tsx +++ b/src/frontend/src/components/ui/accordion.tsx @@ -56,4 +56,4 @@ const AccordionContent = React.forwardRef< )); AccordionContent.displayName = AccordionPrimitive.Content.displayName; -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; +export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }; diff --git a/src/frontend/src/components/ui/card.tsx b/src/frontend/src/components/ui/card.tsx index 585a81a76..c904310cd 100644 --- a/src/frontend/src/components/ui/card.tsx +++ b/src/frontend/src/components/ui/card.tsx @@ -77,9 +77,9 @@ CardFooter.displayName = "CardFooter"; export { Card, - CardHeader, - CardFooter, - CardTitle, - CardDescription, CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, }; diff --git a/src/frontend/src/components/ui/dialog.tsx b/src/frontend/src/components/ui/dialog.tsx index 82641c063..57dda0fef 100644 --- a/src/frontend/src/components/ui/dialog.tsx +++ b/src/frontend/src/components/ui/dialog.tsx @@ -116,10 +116,10 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName; export { Dialog, - DialogTrigger, DialogContent, - DialogHeader, - DialogFooter, - DialogTitle, DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, }; diff --git a/src/frontend/src/components/ui/dropdown-menu.tsx b/src/frontend/src/components/ui/dropdown-menu.tsx index c61e09fc1..f9a0d87d3 100644 --- a/src/frontend/src/components/ui/dropdown-menu.tsx +++ b/src/frontend/src/components/ui/dropdown-menu.tsx @@ -182,18 +182,18 @@ DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; export { DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, DropdownMenuCheckboxItem, - DropdownMenuRadioItem, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, DropdownMenuLabel, + DropdownMenuPortal, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, - DropdownMenuRadioGroup, + DropdownMenuTrigger, }; diff --git a/src/frontend/src/components/ui/menubar.tsx b/src/frontend/src/components/ui/menubar.tsx index 276f5fc5b..512bb6e63 100644 --- a/src/frontend/src/components/ui/menubar.tsx +++ b/src/frontend/src/components/ui/menubar.tsx @@ -218,19 +218,19 @@ MenubarShortcut.displayname = "MenubarShortcut"; export { Menubar, - MenubarMenu, - MenubarTrigger, - MenubarContent, - MenubarItem, - MenubarSeparator, - MenubarLabel, MenubarCheckboxItem, + MenubarContent, + MenubarGroup, + MenubarItem, + MenubarLabel, + MenubarMenu, + MenubarPortal, MenubarRadioGroup, MenubarRadioItem, - MenubarPortal, + MenubarSeparator, + MenubarShortcut, + MenubarSub, MenubarSubContent, MenubarSubTrigger, - MenubarGroup, - MenubarSub, - MenubarShortcut, + MenubarTrigger, }; diff --git a/src/frontend/src/components/ui/table.tsx b/src/frontend/src/components/ui/table.tsx index 80a74f378..eb1e3bda6 100644 --- a/src/frontend/src/components/ui/table.tsx +++ b/src/frontend/src/components/ui/table.tsx @@ -103,11 +103,11 @@ TableCaption.displayName = "TableCaption"; export { Table, - TableHeader, TableBody, + TableCaption, + TableCell, TableFooter, TableHead, + TableHeader, TableRow, - TableCell, - TableCaption, }; diff --git a/src/frontend/src/components/ui/tabs.tsx b/src/frontend/src/components/ui/tabs.tsx index 317de722c..a1f365ba6 100644 --- a/src/frontend/src/components/ui/tabs.tsx +++ b/src/frontend/src/components/ui/tabs.tsx @@ -51,4 +51,4 @@ const TabsContent = React.forwardRef< )); TabsContent.displayName = TabsPrimitive.Content.displayName; -export { Tabs, TabsList, TabsTrigger, TabsContent }; +export { Tabs, TabsContent, TabsList, TabsTrigger }; diff --git a/src/frontend/src/components/ui/tooltip.tsx b/src/frontend/src/components/ui/tooltip.tsx index c54245a53..3d31ab66d 100644 --- a/src/frontend/src/components/ui/tooltip.tsx +++ b/src/frontend/src/components/ui/tooltip.tsx @@ -28,4 +28,4 @@ const TooltipContent = React.forwardRef< )); TooltipContent.displayName = TooltipPrimitive.Content.displayName; -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; +export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }; diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index ff4cc1c29..d4523bf60 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -71,18 +71,7 @@ export function TypesProvider({ children }: { children: ReactNode }) { // Clear the interval if successful. clearInterval(intervalId); } catch (error) { - retryCount++; - // On error, double the delay for the next attempt up to a maximum. - delay = Math.min(30000, delay * 2); - // Log errors but don't do anything else - the function will try again on the next interval. - console.error(error); - // Clear the old interval and start a new one with the new delay. - if (retryCount <= maxRetryCount) { - clearInterval(intervalId); - intervalId = setInterval(getTypes, delay); - } else { - console.error("Max retry attempts reached. Stopping retries."); - } + console.error("An error has occurred while fetching types."); } } diff --git a/src/frontend/src/controllers/API/api.tsx b/src/frontend/src/controllers/API/api.tsx new file mode 100644 index 000000000..8dd9eac9f --- /dev/null +++ b/src/frontend/src/controllers/API/api.tsx @@ -0,0 +1,58 @@ +import axios, { AxiosError, AxiosInstance } from "axios"; +import { useContext, useEffect, useRef } from "react"; +import { alertContext } from "../../contexts/alertContext"; + +// Create a new Axios instance +const api: AxiosInstance = axios.create({ + baseURL: "", +}); + +function ApiInterceptor() { + const retryCounts = useRef([]); + const { setErrorData } = useContext(alertContext); + + useEffect(() => { + const interceptor = api.interceptors.response.use( + (response) => response, + async (error: AxiosError) => { + let retryCount = 0; + + while (retryCount < 4) { + await sleep(5000); // Sleep for 5 seconds + retryCount++; + try { + const response = await axios.request(error.config); + return response; + } catch (error) { + if (retryCount === 3) { + setErrorData({ + title: "There was an error on web connection, please: ", + list: [ + "Refresh the page", + "Use a new flow tab", + "Check if the backend is up", + "Endpoint: " + error.config.url, + ], + }); + return Promise.reject(error); + } + } + } + } + ); + + return () => { + // Clean up the interceptor when the component unmounts + api.interceptors.response.eject(interceptor); + }; + }, [retryCounts]); + + return null; +} + +// Function to sleep for a given duration in milliseconds +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export { ApiInterceptor, api }; diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 7668fea0a..6d24e7d09 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -1,5 +1,6 @@ -import axios, { AxiosResponse } from "axios"; +import { AxiosResponse } from "axios"; import { ReactFlowJsonObject } from "reactflow"; +import { api } from "../../controllers/API/api"; import { APIObjectType, sendAllProps } from "../../types/api/index"; import { FlowStyleType, FlowType } from "../../types/flow"; import { @@ -17,16 +18,14 @@ import { * @returns {Promise>} A promise that resolves to an AxiosResponse containing all the objects. */ export async function getAll(): Promise> { - return await axios.get(`/api/v1/all`); + return await api.get(`/api/v1/all`); } const GITHUB_API_URL = "https://api.github.com"; export async function getRepoStars(owner, repo) { try { - const response = await axios.get( - `${GITHUB_API_URL}/repos/${owner}/${repo}` - ); + const response = await api.get(`${GITHUB_API_URL}/repos/${owner}/${repo}`); return response.data.stargazers_count; } catch (error) { console.error("Error fetching repository data:", error); @@ -41,13 +40,13 @@ export async function getRepoStars(owner, repo) { * @returns {AxiosResponse} The API response. */ export async function sendAll(data: sendAllProps) { - return await axios.post(`/api/v1/predict`, data); + return await api.post(`/api/v1/predict`, data); } export async function postValidateCode( code: string ): Promise> { - return await axios.post("/api/v1/validate/code", { code }); + return await api.post("/api/v1/validate/code", { code }); } /** @@ -62,7 +61,7 @@ export async function postValidatePrompt( template: string, frontend_node: APIClassType ): Promise> { - return await axios.post("/api/v1/validate/prompt", { + return await api.post("/api/v1/validate/prompt", { name: name, template: template, frontend_node: frontend_node, @@ -77,14 +76,14 @@ export async function postValidatePrompt( export async function getExamples(): Promise { const url = "https://api.github.com/repos/logspace-ai/langflow_examples/contents/examples?ref=main"; - const response = await axios.get(url); + const response = await api.get(url); const jsonFiles = response.data.filter((file: any) => { return file.name.endsWith(".json"); }); const contentsPromises = jsonFiles.map(async (file: any) => { - const contentResponse = await axios.get(file.download_url); + const contentResponse = await api.get(file.download_url); return contentResponse.data; }); @@ -106,11 +105,12 @@ export async function saveFlowToDatabase(newFlow: { style?: FlowStyleType; }): Promise { try { - const response = await axios.post("/api/v1/flows/", { + const response = await api.post("/api/v1/flows/", { name: newFlow.name, data: newFlow.data, description: newFlow.description, }); + if (response.status !== 201) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -131,7 +131,7 @@ export async function updateFlowInDatabase( updatedFlow: FlowType ): Promise { try { - const response = await axios.patch(`/api/v1/flows/${updatedFlow.id}`, { + const response = await api.patch(`/api/v1/flows/${updatedFlow.id}`, { name: updatedFlow.name, data: updatedFlow.data, description: updatedFlow.description, @@ -155,7 +155,7 @@ export async function updateFlowInDatabase( */ export async function readFlowsFromDatabase() { try { - const response = await axios.get("/api/v1/flows/"); + const response = await api.get("/api/v1/flows/"); if (response.status !== 200) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -168,7 +168,7 @@ export async function readFlowsFromDatabase() { export async function downloadFlowsFromDatabase() { try { - const response = await axios.get("/api/v1/flows/download/"); + const response = await api.get("/api/v1/flows/download/"); if (response.status !== 200) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -181,7 +181,7 @@ export async function downloadFlowsFromDatabase() { export async function uploadFlowsToDatabase(flows) { try { - const response = await axios.post(`/api/v1/flows/upload/`, flows); + const response = await api.post(`/api/v1/flows/upload/`, flows); if (response.status !== 201) { throw new Error(`HTTP error! status: ${response.status}`); @@ -202,7 +202,7 @@ export async function uploadFlowsToDatabase(flows) { */ export async function deleteFlowFromDatabase(flowId: string) { try { - const response = await axios.delete(`/api/v1/flows/${flowId}`); + const response = await api.delete(`/api/v1/flows/${flowId}`); if (response.status !== 200) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -222,7 +222,7 @@ export async function deleteFlowFromDatabase(flowId: string) { */ export async function getFlowFromDatabase(flowId: number) { try { - const response = await axios.get(`/api/v1/flows/${flowId}`); + const response = await api.get(`/api/v1/flows/${flowId}`); if (response.status !== 200) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -241,7 +241,7 @@ export async function getFlowFromDatabase(flowId: number) { */ export async function getFlowStylesFromDatabase() { try { - const response = await axios.get("/api/v1/flow_styles/"); + const response = await api.get("/api/v1/flow_styles/"); if (response.status !== 200) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -261,7 +261,7 @@ export async function getFlowStylesFromDatabase() { */ export async function saveFlowStyleToDatabase(flowStyle: FlowStyleType) { try { - const response = await axios.post("/api/v1/flow_styles/", flowStyle, { + const response = await api.post("/api/v1/flow_styles/", flowStyle, { headers: { accept: "application/json", "Content-Type": "application/json", @@ -284,7 +284,7 @@ export async function saveFlowStyleToDatabase(flowStyle: FlowStyleType) { * @returns {Promise>} A promise that resolves to an AxiosResponse containing the version information. */ export async function getVersion() { - const respnose = await axios.get("/api/v1/version"); + const respnose = await api.get("/api/v1/version"); return respnose.data; } @@ -294,7 +294,7 @@ export async function getVersion() { * @returns {Promise>} A promise that resolves to an AxiosResponse containing the health status. */ export async function getHealth() { - return await axios.get("/health"); // Health is the only endpoint that doesn't require /api/v1 + return await api.get("/health"); // Health is the only endpoint that doesn't require /api/v1 } /** @@ -306,7 +306,7 @@ export async function getHealth() { export async function getBuildStatus( flowId: string ): Promise { - return await axios.get(`/api/v1/build/${flowId}/status`); + return await api.get(`/api/v1/build/${flowId}/status`); } //docs for postbuildinit @@ -319,7 +319,7 @@ export async function getBuildStatus( export async function postBuildInit( flow: FlowType ): Promise> { - return await axios.post(`/api/v1/build/init/${flow.id}`, flow); + return await api.post(`/api/v1/build/init/${flow.id}`, flow); } // fetch(`/upload/${id}`, { @@ -337,5 +337,5 @@ export async function uploadFile( ): Promise> { const formData = new FormData(); formData.append("file", file); - return await axios.post(`/api/v1/upload/${id}`, formData); + return await api.post(`/api/v1/upload/${id}`, formData); } diff --git a/src/frontend/src/index.css b/src/frontend/src/index.css index 7aedc908c..3e25dbb4b 100644 --- a/src/frontend/src/index.css +++ b/src/frontend/src/index.css @@ -38,9 +38,10 @@ --info-background: #f0f4fd; --info-foreground: #141653; - + --high-indigo: #4338ca; --medium-indigo: #6366f1; + --low-indigo: #e0e7ff; --chat-bot-icon: #afe6ef; --chat-user-icon: #aface9; @@ -52,6 +53,7 @@ --chat-trigger-disabled: #b4c3da; --status-red: #ef4444; --status-yellow: #eab308; + --chat-send: #059669; --status-green: #4ade80; --status-blue:#2563eb; --connection: #555; @@ -104,6 +106,7 @@ --high-indigo: #4338ca; --medium-indigo: #6366f1; + --low-indigo: #e0e7ff; /* Colors that are shared in dark and light mode */ --blur-shared: #151923d2; @@ -112,6 +115,7 @@ --chat-trigger-disabled: #2d3b54; --status-red: #ef4444; --status-yellow: #eab308; + --chat-send: #059669; --status-green: #4ade80; --status-blue: #2563eb; --connection: #555; diff --git a/src/frontend/src/index.tsx b/src/frontend/src/index.tsx index 794fcbf32..f78c9da94 100644 --- a/src/frontend/src/index.tsx +++ b/src/frontend/src/index.tsx @@ -4,6 +4,7 @@ import App from "./App"; import ContextWrapper from "./contexts"; import reportWebVitals from "./reportWebVitals"; +import { ApiInterceptor } from "./controllers/API/api"; import "./index.css"; const root = ReactDOM.createRoot( @@ -13,6 +14,7 @@ root.render( + ); diff --git a/src/frontend/src/modals/EditNodeModal/index.tsx b/src/frontend/src/modals/EditNodeModal/index.tsx index 141cb8dfb..3e1cd32a3 100644 --- a/src/frontend/src/modals/EditNodeModal/index.tsx +++ b/src/frontend/src/modals/EditNodeModal/index.tsx @@ -22,11 +22,10 @@ import { TableRow, } from "../../components/ui/table"; import { limitScrollFieldsModal } from "../../constants/constants"; -import { PopUpContext } from "../../contexts/popUpContext"; import { TabsContext } from "../../contexts/tabsContext"; import { typesContext } from "../../contexts/typesContext"; import { NodeDataType } from "../../types/flow"; -import { classNames, getRandomKeyByssmm } from "../../utils/utils"; +import { classNames } from "../../utils/utils"; import BaseModal from "../baseModal"; const EditNodeModal = forwardRef( @@ -48,7 +47,6 @@ const EditNodeModal = forwardRef( const [myData, setMyData] = useState(data); const { setTabsState, tabId } = useContext(TabsContext); const { reactFlowInstance } = useContext(typesContext); - const { setCloseEdit } = useContext(PopUpContext); let disabled = reactFlowInstance?.getEdges().some((e) => e.targetHandle === data.id) ?? @@ -72,7 +70,6 @@ const EditNodeModal = forwardRef( useEffect(() => { setMyData(data); // reset data to what it is on node when opening modal - setCloseEdit(getRandomKeyByssmm().toString()); }, [modalOpen]); return ( diff --git a/src/frontend/src/modals/formModal/chatInput/index.tsx b/src/frontend/src/modals/formModal/chatInput/index.tsx index 30dfdcd6d..e8be2f292 100644 --- a/src/frontend/src/modals/formModal/chatInput/index.tsx +++ b/src/frontend/src/modals/formModal/chatInput/index.tsx @@ -69,10 +69,10 @@ export default function ChatInput({ className={classNames( "form-modal-send-button", noInput - ? "bg-indigo-600 text-background" + ? "bg-high-indigo text-background" : chatValue === "" ? "text-primary" - : "bg-emerald-600 text-background" + : "bg-chat-send text-background" )} disabled={lockChat} onClick={() => sendMessage()} diff --git a/src/frontend/src/modals/formModal/chatMessage/index.tsx b/src/frontend/src/modals/formModal/chatMessage/index.tsx index 44e57accb..08cc2d22b 100644 --- a/src/frontend/src/modals/formModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/formModal/chatMessage/index.tsx @@ -78,69 +78,75 @@ export default function ChatMessage({
{useMemo( - () => ( - + ) : ( + {props.children}; - }, - code: ({ - node, - inline, - className, - children, - ...props - }) => { - if (children.length) { - if (children[0] === "▍") { - return ( - - ▍ - + components={{ + pre({ node, ...props }) { + return <>{props.children}; + }, + code: ({ + node, + inline, + className, + children, + ...props + }) => { + if (children.length) { + if (children[0] === "▍") { + return ( + + ▍ + + ); + } + + children[0] = (children[0] as string).replace( + "`▍`", + "▍" ); } - children[0] = (children[0] as string).replace( - "`▍`", - "▍" + const match = /language-(\w+)/.exec( + className || "" ); - } - const match = /language-(\w+)/.exec( - className || "" - ); - - return !inline ? ( - {}} - /> - ) : ( - - {children} - - ); - }, - }} - > - {chat.message.toString()} - - ), + return !inline ? ( + {}} + /> + ) : ( + + {children} + + ); + }, + }} + > + {chat.message.toString()} + + ), [chat.message, chat.message.toString()] )}
diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 0ce772a3f..f0e18a118 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -395,7 +395,7 @@ export default function FormModal({ Chat