Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: remove useEffects #707

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions app/(api)/api/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";

import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import { useState } from "react";

const DynamicReactSwagger = dynamic(() => import("./react-swagger"), {
ssr: false,
Expand All @@ -10,23 +9,33 @@ const DynamicReactSwagger = dynamic(() => import("./react-swagger"), {

export default function IndexPage() {
const [spec, setSpec] = useState(null);
const [error, setError] = useState(false);

useEffect(() => {
async function fetchSpecs() {
(async function fetchSpecs() {
if (spec || error) return;
try {
const response = await fetch("swagger/doc.json");

if (response.ok) {
if (!response.ok) throw new Error("Failed to fetch API docs");
const fetchedSpec = await response.json();
setSpec(fetchedSpec);
} else {
console.error("Failed to fetch API docs");
}
} catch (err) {
console.error("Error fetching Swagger specs:", err);
setError(true);
}

fetchSpecs();
}, []);

if (!spec) return <div>Loading...</div>;
})();

if (error) {
return <div>Error loading API documentation. Please try again later.</div>;
}

if (!spec) {
return (
<div className="loading">
<span>Loading API documentation...</span>
</div>
);
}

return (
<section className="container">
Expand Down
128 changes: 70 additions & 58 deletions components/NetworkSliceModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import {
Input,
Notification,
Expand Down Expand Up @@ -36,8 +36,8 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
const auth = useAuth()
const queryClient = useQueryClient();
const [apiError, setApiError] = useState<string | null>(null);
const [upfApiError, setUpfApiError] = useState<string | null>(null);
const [gnbApiError, setGnbApiError] = useState<string | null>(null);
const [upfApiError, setUpfApiError] = useState<string | null>(null);

const NetworkSliceSchema = Yup.object().shape({
name: Yup.string()
Expand All @@ -58,10 +58,16 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
.required("MNC is required."),
upf: Yup.object()
.shape({ hostname: Yup.string().required("Please select a UPF.") })
.shape({ port: Yup.string().required("Please select a UPF.") })
.required("Selecting a UPF is required."),
gnbList: Yup.array()
.min(1)
.required("Selecting at least 1 gNodeB is required."),
.of(
Yup.object().shape({
name: Yup.string().required("gNodeB name is required."),
tac: Yup.string().required("gNodeB TAC is required."),
})
)
.min(1, "Selecting at least 1 gNodeB is required."),
});

const modalTitle = () => {
Expand Down Expand Up @@ -94,6 +100,14 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
validationSchema: NetworkSliceSchema,
onSubmit: async (values) => {
try {
if (upfItems.length === 0) {
setUpfApiError("No available UPF. Please add at least one UPF.");
return;
}
if (gnbItems.length === 0) {
setGnbApiError("No available GNB. Please add at least one GNB.");
return;
}
if (networkSlice) {
await editNetworkSlice({
name: values.name,
Expand Down Expand Up @@ -128,55 +142,29 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
},
});

const { data: upfList = [], isLoading: isUpfLoading, isError: isUpfError } = useQuery({
const upfQuery = useQuery({
queryKey: [queryKeys.upfList, auth.user?.authToken],
queryFn: () => getUpfList(auth.user ? auth.user.authToken : ""),
enabled: auth.user ? true : false,
queryFn: () => getUpfList(auth.user!.authToken),
enabled: auth.user ? true : false
});

useEffect(() => {
const checkUpfList = async () => {
if (isUpfError) {
setUpfApiError("Failed to retrieve the list of UPFs from the server.")
} else if (!isUpfLoading && upfList.length === 0) {
setUpfApiError("No available UPF. Please add at least one UPF.");
}
};
checkUpfList();
}, [isUpfLoading, isUpfError, upfList]);

const { data: gnbList = [], isLoading: isGnbLoading, isError: isGnbError } = useQuery({
const gnbQuery = useQuery({
queryKey: [queryKeys.gnbList, auth.user?.authToken],
queryFn: () => getGnbList(auth.user ? auth.user.authToken : ""),
enabled: auth.user ? true : false,
queryFn: () => getGnbList(auth.user!.authToken),
enabled: auth.user ? true : false
});

useEffect(() => {
const checkGnbList = async () => {
if (isGnbError) {
setGnbApiError("Failed to retrieve the list of GNBs from the server.")
} else if (!isGnbLoading && gnbList.length === 0) {
setGnbApiError("No available GNB. Please add at least one GNB.");
}
};
checkGnbList();
}, [isGnbLoading, isGnbError, gnbList]);
const upfItems = (upfQuery.data as UpfItem[]) || [];
const gnbItems = (gnbQuery.data as GnbItem[]) || [];

const handleUpfChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const upf = upfList.find(
(item) => e.target.value === `${item.hostname}:${item.port}`,
);
const upf = upfItems.find((item: UpfItem) => e.target.value === `${item.hostname}:${item.port}`);
void formik.setFieldValue("upf", upf);
};

const handleGnbChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const selectedOptions = Array.from(e.target.selectedOptions);
const items = gnbList.filter((item) =>
selectedOptions.some(
(option) => option.value === `${item.name}:${item.tac}`,
),
);
void formik.setFieldValue("gnbList", items);
const gnb = gnbItems.find((item: GnbItem) => e.target.value === `${item.name}:${item.tac}`);
void formik.setFieldValue("gnbList", [...formik.values.gnbList, gnb]);
};

const getGnbListValueAsString = () => {
Expand All @@ -189,6 +177,42 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
return formik.values.upf.hostname ? `${formik.values.upf.hostname}:${formik.values.upf.port}` : "";
};

const ErrorNotification = ({
error,
}: {
error: string | null;
}) => {
return error ? (
<Notification severity="negative" title="Error">
{error}
</Notification>
) : null;
};

if (upfQuery.isLoading || gnbQuery.isLoading) {
return (
<Notification severity="information" title="Loading...">
Fetching data...
</Notification>
);
}

if (upfQuery.isError) {
return (
<Notification severity="negative" title="Error">
Failed to retrieve the list of UPFs from the server.
</Notification>
);
}

if (gnbQuery.isError) {
return (
<Notification severity="negative" title="Error">
Failed to retrieve the list of gNodeBs from the server.
</Notification>
);
}

return (
<Modal
title={modalTitle()}
Expand All @@ -205,21 +229,9 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
</ActionButton>
}
>
{apiError && (
<Notification severity="negative" title="Error">
{apiError}
</Notification>
)}
{upfApiError && (
<Notification severity="negative" title="Error">
{upfApiError}
</Notification>
)}
{gnbApiError && (
<Notification severity="negative" title="Error">
{gnbApiError}
</Notification>
)}
{apiError && <ErrorNotification error={apiError} />}
{upfApiError && <ErrorNotification error={upfApiError} />}
{gnbApiError && <ErrorNotification error={gnbApiError} />}
<Form>
<Input
type="text"
Expand Down Expand Up @@ -269,7 +281,7 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
label: "Select an option",
value: "",
},
...upfList.map((upf) => ({
...upfItems.map((upf) => ({
label: `${upf.hostname}:${upf.port}`,
value: `${upf.hostname}:${upf.port}`,
})),
Expand All @@ -286,7 +298,7 @@ const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceMo
disabled: true,
label: "Select...",
},
...gnbList.map((gnb) => ({
...gnbItems.map((gnb) => ({
label: `${gnb.name} (tac:${gnb.tac})`,
value: `${gnb.name}:${gnb.tac}`,
})),
Expand Down
Loading
Loading