Skip to content

Commit

Permalink
feat: refresh pages automatically when a new slices or subsribers added
Browse files Browse the repository at this point in the history
Signed-off-by: gatici <[email protected]>
  • Loading branch information
gatici committed Jan 8, 2025
1 parent 386a2de commit 96f0d3b
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 36 deletions.
54 changes: 45 additions & 9 deletions app/(nms)/network-configuration/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import {
Button,
Card,
Expand All @@ -11,37 +11,65 @@ import NetworkSliceModal from "@/components/NetworkSliceModal";
import NetworkSliceEmptyState from "@/components/NetworkSliceEmptyState";
import { NetworkSliceTable } from "@/components/NetworkSliceTable";
import Loader from "@/components/Loader";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { queryKeys } from "@/utils/queryKeys";
import PageHeader from "@/components/PageHeader";
import PageContent from "@/components/PageContent";
import { NetworkSlice } from "@/components/types";
import { useAuth } from "@/utils/auth";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiPostNetworkSlice } from "@/utils/callNetworkSliceApi";

const NetworkConfiguration = () => {
const queryClient = useQueryClient();
const [isCreateModalVisible, setCreateModalVisible] = useState(false);
const [isEditModalVisible, setEditModalVisible] = useState(false);
const [networkSlice, setNetworkSlice] = useState<NetworkSlice | undefined>(undefined);
const [refresh, setRefresh] = useState(false); // State to track refresh (optional if using mutation directly)
const auth = useAuth()

// Fetching Network Slices using useQuery
const { data: networkSlices = [], isLoading: loading, status: networkSlicesQueryStatus, error: networkSlicesQueryError } = useQuery({
queryKey: [queryKeys.networkSlices, auth.user?.authToken],
queryFn: () => getNetworkSlices(auth.user ? auth.user.authToken : ""),
enabled: auth.user ? true : false,
enabled: !!auth.user, // Only enable if the user is authenticated
retry: (failureCount, error): boolean => {
if (error.message.includes("401")) {
return false
}
return true
}
});
if (networkSlicesQueryStatus == "error") {
if (networkSlicesQueryError.message.includes("401")) {
auth.logout()
}
return <p>{networkSlicesQueryError.message}</p>
}

// Mutation hook to add a new Network Slice
const addNetworkSlice = async (newSlice: NetworkSlice): Promise<Response> => {
return await apiPostNetworkSlice(newSlice["slice-name"], newSlice, auth.user?.authToken || "");
};

const addNetworkSliceMutation = useMutation<unknown, Error, NetworkSlice>({
mutationFn: addNetworkSlice,
onSuccess: () => {
// Invalidate and refetch the network slices query
queryClient.invalidateQueries({ queryKey: [queryKeys.networkSlices] });

// Optionally trigger refresh via state (if more actions depend on it)
setRefresh(true);
},
onError: (error) => {
console.error("Error adding network slice:", error);
},
});

// Trigger UI refresh when refresh flag is set
useEffect(() => {
if (refresh) {
setRefresh(false); // Reset refresh state
setCreateModalVisible(false); // Close modal after adding network slice
}
}, [refresh]);

const handleAddNetworkSlice = (newSlice: NetworkSlice) => {
addNetworkSliceMutation.mutate(newSlice);
};

const toggleCreateNetworkSliceModal = () =>
setCreateModalVisible((prev) => !prev);
Expand Down Expand Up @@ -115,6 +143,13 @@ const NetworkConfiguration = () => {
return <Loader text="Loading..." />;
}

if (networkSlicesQueryStatus == "error") {
if (networkSlicesQueryError.message.includes("401")) {
auth.logout()
}
return <p>{networkSlicesQueryError.message}</p>
}

return (
<>
{networkSlices.length > 0 && (
Expand Down Expand Up @@ -145,6 +180,7 @@ const NetworkConfiguration = () => {
{isCreateModalVisible && (
<NetworkSliceModal
toggleModal={toggleCreateNetworkSliceModal}
onSave={handleAddNetworkSlice} // Pass the mutation handler to modal for saving new slice
/>
)}
{isEditModalVisible && (
Expand Down
61 changes: 57 additions & 4 deletions app/(nms)/subscribers/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import {
Button,
MainTable,
Expand All @@ -13,7 +13,7 @@ import { getNetworkSlices } from "@/utils/getNetworkSlices";
import SyncOutlinedIcon from "@mui/icons-material/SyncOutlined";
import { deleteSubscriber } from "@/utils/deleteSubscriber";
import Loader from "@/components/Loader";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { queryKeys } from "@/utils/queryKeys";
import PageHeader from "@/components/PageHeader";
import PageContent from "@/components/PageContent";
Expand All @@ -24,10 +24,29 @@ export type Subscriber = {
ueId: string;
};

const addSubscriber = async (newSubscriber: void, token: string | undefined) => {
const response = await fetch("/api/subscribers", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(newSubscriber),
});
if (!response.ok) {
const errorBody = await response.json().catch(() => ({}));
throw new Error(
errorBody.message || "Failed to add subscriber"
);
}
return response.json();
};

const Subscribers = () => {
const queryClient = useQueryClient();
const [isCreateModalVisible, setCreateModalVisible] = useState(false);
const [isEditModalVisible, setEditModalVisible] = useState(false);
const [newSubscriberAdded, setNewSubscriberAdded] = useState(false); // Tracks if updates are needed
const [subscriber, setSubscriber] = useState<any | undefined>(undefined);
const auth = useAuth()

Expand All @@ -43,6 +62,33 @@ const Subscribers = () => {
}
});

// Mutation to add a subscriber
const mutation = useMutation({
mutationFn: (newSubscriber) => addSubscriber(newSubscriber, auth.user?.authToken),
onSuccess: () => {
// On successful addition, invalidate the query to refresh
queryClient.invalidateQueries({ queryKey: [queryKeys.subscribers] });
setNewSubscriberAdded(true); // Indicate that new data is added
},
});

// Effect to handle state changes
useEffect(() => {
if (newSubscriberAdded) {
queryClient.invalidateQueries({ queryKey: [queryKeys.subscribers] });
setNewSubscriberAdded(false);
}
}, [newSubscriberAdded, queryClient]); // `queryClient` is now included in the dependency array.

const handleCreateSubscriber = async (newSubscriber: void) => {
try {
await mutation.mutateAsync(newSubscriber); // Trigger mutation
setCreateModalVisible(false); // Close the modal
} catch (error) {
console.error("Error adding subscriber:", error); // Handle error
}
};

const { data: deviceGroups = [], isLoading: isDeviceGroupsLoading } = useQuery({
queryKey: [queryKeys.deviceGroups, auth.user?.authToken],
queryFn: () => getDeviceGroups(auth.user ? auth.user.authToken : ""),
Expand Down Expand Up @@ -165,10 +211,17 @@ const Subscribers = () => {
rows={tableContent}
/>
</PageContent>
{isCreateModalVisible && <SubscriberModal toggleModal={toggleCreateModal} slices={slices} deviceGroups={deviceGroups} />}
{isCreateModalVisible && (
<SubscriberModal
toggleModal={toggleCreateModal}
onSubmit={(newSubscriber: any) => handleCreateSubscriber(newSubscriber)}
slices={slices}
deviceGroups={deviceGroups}
/>)
}
{isEditModalVisible &&
<SubscriberModal toggleModal={toggleEditModal} subscriber={subscriber} slices={slices} deviceGroups={deviceGroups} />}
</>
);
};
export default Subscribers;
export default Subscribers;
7 changes: 4 additions & 3 deletions components/NetworkSliceModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ interface NetworkSliceValues {
}

interface NetworkSliceModalProps {
networkSlice?: NetworkSlice;
toggleModal: () => void;
networkSlice?: NetworkSlice,
toggleModal: () => void,
onSave?: (newSlice: NetworkSlice) => void
}

const NetworkSliceModal = ({ networkSlice, toggleModal }: NetworkSliceModalProps) => {
const NetworkSliceModal = ({ networkSlice, toggleModal, onSave }: NetworkSliceModalProps) => {
const auth = useAuth()
const queryClient = useQueryClient();
const [apiError, setApiError] = useState<string | null>(null);
Expand Down
11 changes: 6 additions & 5 deletions components/SubscriberModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ interface SubscriberValues {
}

type Props = {
toggleModal: () => void;
subscriber?: any;
slices: NetworkSlice[];
deviceGroups: any[]
toggleModal: () => void,
subscriber?: any,
slices: NetworkSlice[],
deviceGroups: any[],
onSubmit?: (newSubscriber: any) => Promise<void>
};

const SubscriberModal = ({ toggleModal, subscriber, slices, deviceGroups }: Props) => {
const SubscriberModal = ({ toggleModal, subscriber, slices, deviceGroups, onSubmit }: Props) => {
const queryClient = useQueryClient();
const auth = useAuth()
const [apiError, setApiError] = useState<string | null>(null);
Expand Down
19 changes: 4 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
},
"devDependencies": {
"@types/swagger-ui-react": "^4.18.2",
"immutable": "^5.0.3",
"prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9"
}
Expand Down

0 comments on commit 96f0d3b

Please sign in to comment.