diff --git a/src/components/CFPortSetter/CFPortSetter.tsx b/src/components/CFPortSetter/CFPortSetter.tsx index 537c7ce1..5735af2b 100644 --- a/src/components/CFPortSetter/CFPortSetter.tsx +++ b/src/components/CFPortSetter/CFPortSetter.tsx @@ -1,13 +1,10 @@ import { IEnvironmentStep1 } from "../../interfaces/environment/environment.step1.interface"; import CreateRobotFormAddButton from "../CreateRobotFormAddButton/CreateRobotFormAddButton"; -import { getPort as getFreePort } from "../../toolkit/PortSlice"; import CFPortInput from "../CFPortInput/CFPortInput"; -import { useAppDispatch } from "../../hooks/redux"; import CFInfoBar from "../CFInfoBar/CFInfoBar"; -import useMain from "../../hooks/useMain"; import { ReactElement } from "react"; -import { toast } from "sonner"; import { FormikProps } from "formik"; +import useFunctions from "../../hooks/useFunctions"; interface ICFPortSetter { formik: FormikProps; @@ -18,40 +15,7 @@ export default function CFPortSetter({ formik, type, }: ICFPortSetter): ReactElement { - const { selectedState } = useMain(); - - const dispatch = useAppDispatch(); - - async function getPort(): Promise { - try { - const result = await dispatch( - getFreePort({ - organizationId: selectedState?.organization?.id!, - instanceId: selectedState?.instance?.id!, - region: selectedState?.roboticsCloud?.region!, - roboticsCloudName: selectedState?.roboticsCloud?.name!, - }), - ); - - if ( - formik.values.services.ide.customPorts - ?.map((port: any) => port.backendPort) - .includes(result.payload) || - formik.values.services.vdi.customPorts - ?.map((port: any) => port.backendPort) - .includes(result.payload) || - formik.values.services.jupyterNotebook.customPorts - ?.map((port: any) => port.backendPort) - .includes(result.payload) - ) { - return getPort(); - } - - return result.payload; - } catch (error) { - toast.error("Error getting port. Please remove a port and try again."); - } - } + const { getFreePort } = useFunctions(); function handleGetNameFromType(): string { switch (type) { @@ -112,14 +76,18 @@ export default function CFPortSetter({ { - await formik.setFieldValue( - `services.${type}.customPorts`, - formik.values?.services?.[`${type}`]?.customPorts?.concat({ - name: "", - port: undefined, - backendPort: await getPort(), - }), - ); + const backendPort = await getFreePort(); + + if (typeof backendPort === "number") { + await formik.setFieldValue( + `services.${type}.customPorts`, + (formik.values?.services?.[`${type}`]?.customPorts || []).concat({ + name: "", + port: "", + backendPort: backendPort, + }), + ); + } }} className="!mt-1" /> diff --git a/src/components/CFWorkspaceItem/CFWorkspaceItem.tsx b/src/components/CFWorkspaceItem/CFWorkspaceItem.tsx index 4681083e..0fc9931f 100644 --- a/src/components/CFWorkspaceItem/CFWorkspaceItem.tsx +++ b/src/components/CFWorkspaceItem/CFWorkspaceItem.tsx @@ -1,15 +1,16 @@ import CFWorkspaceItemAccordionHeader from "../CFWorkspaceItemAccordionHeader/CFWorkspaceItemAccordionHeader"; import CFDeleteWorkspaceButton from "../CFDeleteWorkspaceButton/CFDeleteWorkspaceButton"; import CFWorkspaceNameDistro from "../CFWorkspaceNameDistro/CFWorkspaceNameDistro"; -import { IWorkspace, IWorkspaces } from "../../interfaces/robotInterfaces"; +import { IWorkspace } from "../../interfaces/robotInterfaces"; import CFRepositoryMapper from "../CFRepositoryMapper/CFRepositoryMapper"; import Accordion from "../Accordion/AccordionV2"; import { FormikProps } from "formik/dist/types"; import { ReactElement, useState } from "react"; import CFSection from "../CFSection/CFSection"; +import { IEnvironmentStep2 } from "../../interfaces/environment/environment.step2.interface"; interface ICFWorkspaceItem { - formik: FormikProps; + formik: FormikProps; workspace: IWorkspace; workspaceIndex: number; workspaceState: string[]; diff --git a/src/components/CFWorkspacesMapper/CFWorkspacesMapper.tsx b/src/components/CFWorkspacesMapper/CFWorkspacesMapper.tsx index fec33c4f..d4f3a3e7 100644 --- a/src/components/CFWorkspacesMapper/CFWorkspacesMapper.tsx +++ b/src/components/CFWorkspacesMapper/CFWorkspacesMapper.tsx @@ -2,10 +2,13 @@ import { ReactElement } from "react"; import { FormikProps } from "formik"; import useCreateRobot from "../../hooks/useCreateRobot"; import CFWorkspaceItem from "../CFWorkspaceItem/CFWorkspaceItem"; -import { IWorkspace, IWorkspaces } from "../../interfaces/robotInterfaces"; +import { + IEnvironmentStep2, + IEnvironmentStep2Workspace, +} from "../../interfaces/environment/environment.step2.interface"; interface ICFWorkspacesMapper { - formik: FormikProps; + formik: FormikProps; responseRobot: any; isImportRobot?: boolean; } @@ -23,7 +26,7 @@ export default function CFWorkspacesMapper({ className="flex flex-col gap-2" > {robotData?.step2?.workspaces?.map( - (workspace: IWorkspace, workspaceIndex: number) => { + (workspace: IEnvironmentStep2Workspace, workspaceIndex: number) => { return ( ({ + const formik = useFormik({ validationSchema: applicationMode ? CFAppStep2Validations : CFRobotStep2Validations, diff --git a/src/contexts/FunctionsContext.tsx b/src/contexts/FunctionsContext.tsx index e9a2ee7a..dbd54c48 100644 --- a/src/contexts/FunctionsContext.tsx +++ b/src/contexts/FunctionsContext.tsx @@ -74,6 +74,8 @@ import useMain from "../hooks/useMain"; import { createContext } from "react"; import { toast } from "sonner"; import { INamespace } from "../interfaces/namespace.interface"; +import { getPort as getFreePortDispatch } from "../toolkit/PortSlice"; + import { namespaceMapper, namespacesMapper, @@ -1380,6 +1382,44 @@ export default ({ children }: any) => { }); } + async function getFreePort(): Promise { + return new Promise(async (resolve, reject) => { + try { + const { payload: port } = await dispatch( + getFreePortDispatch({ + organizationId: selectedState?.organization?.id!, + roboticsCloudName: selectedState?.roboticsCloud?.name!, + region: selectedState?.roboticsCloud?.region!, + instanceId: selectedState?.instance?.id!, + }), + ); + + console.log("port", port, typeof port); + + if (typeof port !== "number") { + return reject(); + } else if ( + robotData.step1.services.ide.customPorts + ?.map((port: any) => port.backendPort) + .includes(port) || + robotData.step1.services.vdi.customPorts + ?.map((port: any) => port.backendPort) + .includes(port) || + robotData.step1.services.jupyterNotebook.customPorts + ?.map((port: any) => port.backendPort) + .includes(port) + ) { + getFreePort(); + } + + resolve(port); + } catch (error) { + toast.error("Error getting port. Please remove a port and try again."); + reject(error); + } + }); + } + function navigateTo404() { toast.error("The current page does not exist or is not available to you."); navigate("/404"); @@ -1864,6 +1904,8 @@ export default ({ children }: any) => { getTemplates, + getFreePort, + getOrganizationsFC, getRegionsFC, getCloudInstancesFC, diff --git a/src/handler/environment.handler.ts b/src/handler/environment.handler.ts index 6254509a..0f7262ed 100644 --- a/src/handler/environment.handler.ts +++ b/src/handler/environment.handler.ts @@ -53,7 +53,7 @@ function handleMapper(data: IEnvironmentBE[]): { return { name: item?.split("-")[0], port: item?.split("-")[1].split(":")[1], - backendPort: item?.split("-")[1].split(":")[0], + backendPort: Number(item?.split("-")[1].split(":")[0]), }; }) || [], gpuAllocation: env?.vdiGpuResource, @@ -70,7 +70,7 @@ function handleMapper(data: IEnvironmentBE[]): { return { name: item?.split("-")[0], port: item?.split("-")[1].split(":")[1], - backendPort: item?.split("-")[1].split(":")[0], + backendPort: Number(item?.split("-")[1].split(":")[0]), }; }) || [], gpuAllocation: env?.ideGpuResource, @@ -92,7 +92,7 @@ function handleMapper(data: IEnvironmentBE[]): { return { name: item?.split("-")[0], port: item?.split("-")[1].split(":")[1], - backendPort: item?.split("-")[1].split(":")[0], + backendPort: Number(item?.split("-")[1].split(":")[0]), }; }) || [], podName: env?.notebookPodName, diff --git a/src/interfaces/environment/environment.step1.interface.ts b/src/interfaces/environment/environment.step1.interface.ts index e9a1f432..83c28eb6 100644 --- a/src/interfaces/environment/environment.step1.interface.ts +++ b/src/interfaces/environment/environment.step1.interface.ts @@ -36,7 +36,7 @@ export interface IEnvironmentStep1 { customPorts: { name: string; port: string; - backendPort: string; + backendPort: number; }[]; gpuAllocation: number; podName: string; @@ -50,7 +50,7 @@ export interface IEnvironmentStep1 { customPorts: { name: string; port: string; - backendPort: string; + backendPort: number; }[]; gpuAllocation: number; gpuModelName: string; @@ -69,7 +69,7 @@ export interface IEnvironmentStep1 { customPorts: { name: string; port: string; - backendPort: string; + backendPort: number; }[]; podName: string; log: string; diff --git a/src/interfaces/useFunctionsInterfaces.ts b/src/interfaces/useFunctionsInterfaces.ts index acef3eff..20533894 100644 --- a/src/interfaces/useFunctionsInterfaces.ts +++ b/src/interfaces/useFunctionsInterfaces.ts @@ -285,6 +285,8 @@ export interface IuseFunctions { setResponseLaunchManagers?: any, ) => void; + getFreePort: () => Promise; + // // // // // // // getOrganizationsFC: ( fromPage: boolean,