Skip to content

Commit

Permalink
Merge pull request #400 from sinamics/unlinked-networks
Browse files Browse the repository at this point in the history
Added notification if there is unlinked networks
  • Loading branch information
sinamics authored May 9, 2024
2 parents 0d24323 + ab4a3a8 commit f34aec8
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 1 deletion.
29 changes: 29 additions & 0 deletions src/__tests__/pages/network/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

jest.mock("../../../utils/api", () => ({
api: {
admin: {
unlinkedNetwork: {
useQuery: jest.fn(),
},
},
network: {
getUserNetworks: {
useQuery: jest.fn(),
Expand Down Expand Up @@ -44,6 +49,11 @@ describe("Networks page", () => {
id: "test-id",
},
}));
(api.admin.unlinkedNetwork.useQuery as jest.Mock).mockReturnValue({
data: [1, 2],
isLoading: true,
refetch: jest.fn(),
});
});

it("displays loading when fetching networks", () => {
Expand All @@ -52,6 +62,7 @@ describe("Networks page", () => {
isLoading: true,
refetch: jest.fn(),
});

render(
<QueryClientProvider client={queryClient}>
<NextIntlClientProvider locale="en" messages={enTranslation}>
Expand All @@ -61,7 +72,25 @@ describe("Networks page", () => {
);
expect(screen.getByRole("skeleton")).toBeInTheDocument();
});
it("displays notification if there is unlinked networks on the controller", async () => {
(api.network.getUserNetworks.useQuery as jest.Mock).mockReturnValue({
data: [],
isLoading: false,
refetch: jest.fn(),
});

render(
<QueryClientProvider client={queryClient}>
<NextIntlClientProvider locale="en" messages={enTranslation}>
<Networks />
</NextIntlClientProvider>
</QueryClientProvider>,
);

expect(
screen.getByText("There is 2 unassigned network registered with the controller."),
).toBeInTheDocument();
});
it("displays networks and handles add network button", async () => {
const mockRefetch = jest.fn();
// const mockCreateNetwork = jest.fn().mockResolvedValue({});
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "Loading",
"title": "Networks",
"description": "VPN Networks",
"unlinkedNetworks": {
"title": "There is {amount} unassigned network registered with the controller.",
"navigate": "Goto Controller"
},
"noNetworksMessage": "No networks have been created yet. Start by creating one and it will appear here.",
"networkActionModal": {
"modalTitle": "Options for Network <span>{networkName}</span>",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/es/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "Cargando",
"title": "Redes",
"description": "Redes VPN",
"unlinkedNetworks": {
"title": "Hay {amount} red no asignada registrada con el controlador.",
"navigate": "Ir al Controlador"
},
"noNetworksMessage": "No se han creado redes todavía. Comienza creando una y aparecerá aquí.",
"networkActionModal": {
"modalTitle": "Acciones de red <span>{networkName}</span>",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "Chargement",
"title": "Réseaux",
"description": "Réseaux VPN",
"unlinkedNetworks": {
"title": "Il y a {amount} réseau non assigné enregistré avec le contrôleur.",
"navigate": "Aller au Contrôleur"
},
"noNetworksMessage": "Aucun réseau n'a encore été créé. Commencez par en créer un et il apparaîtra ici.",
"networkActionModal": {
"modalTitle": "Options pour le réseau <span>{networkName}</span>",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/no/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "Laster",
"title": "Nettverk",
"description": "VPN-nettverk",
"unlinkedNetworks": {
"title": "Det er {amount} ufordelt nettverk registrert med kontrolleren.",
"navigate": "Gå til Kontroller"
},
"noNetworksMessage": "Ingen nettverk er opprettet ennå. Start ved å opprette en, og den vil dukke opp her.",
"networkActionModal": {
"modalTitle": "Aksjon for Nettverk <span>{networkName}</span>",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/pl/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "Ładowanie",
"title": "Sieci",
"description": "Sieci VPN",
"unlinkedNetworks": {
"title": "Jest {amount} nieprzypisana sieć zarejestrowana z kontrolerem.",
"navigate": "Przejdź do Kontrolera"
},
"noNetworksMessage": "Nie utworzono jeszcze żadnych sieci. Utwórz nową sieć, a pojawi się ona właśnie tutaj...",
"networkActionModal": {
"modalTitle": "Opcje dla sieci <span>{networkName}</span>",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/zh-tw/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "載入中",
"title": "網路",
"description": "VPN網路",
"unlinkedNetworks": {
"title": "有{amount}個未分配的網絡註冊在控制器上。",
"navigate": "前往控制器"
},
"noNetworksMessage": "尚未建立任何網路。首先建立一個,它將出現在這裡。",
"networkActionModal": {
"modalTitle": "網路操作 <span>{networkName}</span>",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"loading": "加载中",
"title": "网络",
"description": "VPN网络",
"unlinkedNetworks": {
"title": "有{amount}个未分配的网络注册在控制器上。",
"navigate": "前往控制器"
},
"noNetworksMessage": "尚未创建任何网络。首先创建一个,它将出现在这里。",
"networkActionModal": {
"modalTitle": "网络操作 <span>{networkName}</span>",
Expand Down
39 changes: 38 additions & 1 deletion src/pages/network/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ import {
useTrpcApiErrorHandler,
useTrpcApiSuccessHandler,
} from "~/hooks/useTrpcApiHandler";
import Link from "next/link";
import { User } from "@prisma/client";

type OrganizationId = {
id: string;
};
interface IProps {
orgIds: OrganizationId[];
user: User;
}

const title = `${globalSiteTitle} - Local Controller`;

const Networks: NextPageWithLayout = ({ orgIds }: IProps) => {
const Networks: NextPageWithLayout = ({ orgIds, user }: IProps) => {
const b = useTranslations("commonButtons");
const t = useTranslations("networks");

Expand All @@ -40,6 +43,10 @@ const Networks: NextPageWithLayout = ({ orgIds }: IProps) => {
central: false,
});

const { data: unlinkedNetworks } = api.admin.unlinkedNetwork.useQuery(undefined, {
enabled: user?.role === "ADMIN",
});

const { mutate: createNetwork } = api.network.createNetwork.useMutation({
onError: handleApiError,
onSuccess: handleApiSuccess({ actions: [refetch] }),
Expand All @@ -65,7 +72,37 @@ const Networks: NextPageWithLayout = ({ orgIds }: IProps) => {
<div className="mb-3 mt-3 flex w-full justify-center ">
<h5 className="w-full text-center text-2xl">{t("title")}</h5>
</div>

<div className="grid grid-cols-1 space-y-3 px-3 pt-5 md:grid-cols-[1fr,1fr,1fr] md:space-y-0 md:px-11">
{unlinkedNetworks?.length > 0 && (
<div className="col-span-3 flex justify-center pb-5">
<div role="alert" className="alert w-3/6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
className="stroke-info shrink-0 w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
</svg>
<span>
{t.rich("unlinkedNetworks.title", {
amount: unlinkedNetworks?.length,
})}
</span>
<div>
<Link href="/admin/?tab=controller" className="btn btn-sm">
{t("unlinkedNetworks.navigate")}
</Link>
</div>
</div>
</div>
)}
<div className="flex justify-center">
<button className={"btn btn-primary btn-outline"} onClick={addNewNetwork}>
<svg
Expand Down

0 comments on commit f34aec8

Please sign in to comment.