add basic socket toast and invalidate

This commit is contained in:
karamvir
2023-07-31 21:50:04 -07:00
parent d1be56923f
commit f15540e860
5 changed files with 82 additions and 12 deletions

View File

@@ -10,6 +10,7 @@ import { DeploymentName } from "@resources/deployment/util";
import { DesktopUpdates } from "@components/updates/desktop";
import { BuildName } from "@resources/build/util";
import { Omnibar } from "./omnibar";
import { WsStatusIndicator } from "@util/socket";
export const Paths = () => {
const path = useLocation().pathname.split("/")[1];
@@ -73,9 +74,7 @@ export const Header = () => {
<div className="flex">
{user && (
<>
<Button disabled variant="ghost">
<Circle className="w-4 h-4 fill-green-500 stroke-none" />
</Button>
<WsStatusIndicator />
<Omnibar />
<DesktopUpdates />
</>

View File

@@ -5,6 +5,7 @@ import {
useMutation,
UseQueryOptions,
UseMutationOptions,
useQueryClient,
} from "@tanstack/react-query";
import { useAtomValue, useSetAtom } from "jotai";
import { atomWithStorage } from "jotai/utils";
@@ -15,6 +16,7 @@ import {
WriteResponses,
} from "@monitor/client/dist/responses";
import { useEffect, useState } from "react";
import { ReadRequest } from "@monitor/client/dist/types";
export const useRead = <
T extends Types.ReadRequest["type"],
@@ -61,6 +63,17 @@ export const useExecute = <
config
);
export const useInvalidate = () => {
const qc = useQueryClient();
return <
T extends ReadRequest["type"],
P = Extract<Types.ReadRequest, { type: T }>["params"]
>(
...keys: Array<[T] | [T, P]>
) => keys.forEach((k) => qc.invalidateQueries([...k]));
};
export const useUser = () => useRead("GetUser", {});
export const useLogin = () => {

View File

@@ -1,6 +1,7 @@
import { Header } from "@components/header";
import { useUser } from "@hooks";
import { Toaster } from "@ui/toast";
import { WebsocketProvider } from "@util/socket";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
export const Layout = () => {
@@ -10,7 +11,7 @@ export const Layout = () => {
if (isError && !path.includes("login")) nav("/login");
return (
<>
<WebsocketProvider>
<div className="relative flex min-h-screen flex-col">
<Header />
<div className="container pt-12 pb-16">
@@ -18,6 +19,6 @@ export const Layout = () => {
</div>
</div>
<Toaster />
</>
</WebsocketProvider>
);
};

View File

@@ -13,7 +13,7 @@ const ToastViewport = React.forwardRef<
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 sm:right-0 z-[100] gap-2 flex max-h-screen w-full flex-col-reverse p-4 sm:flex-col md:max-w-[420px]",
"fixed bottom-0 sm:right-0 z-[100] gap-2 flex max-h-screen w-full flex-col-reverse p-4 sm:flex-col md:max-w-[420px]",
className
)}
{...props}

View File

@@ -1,24 +1,81 @@
import { useInvalidate } from "@hooks";
import { Types } from "@monitor/client";
import { Button } from "@ui/button";
import { toast } from "@ui/toast/use-toast";
import { useState } from "react";
import { atom, useAtom } from "jotai";
import { Circle } from "lucide-react";
import { ReactNode } from "react";
import rws from "reconnecting-websocket";
import { cn } from "./helpers";
import { UPDATE_WS_URL } from "@main";
export const WebsocketProvider = () => {
const ws = new rws("ws-url");
const [_, set] = useState(false);
const rws_atom = atom(new rws(UPDATE_WS_URL));
const useWebsocket = () => useAtom(rws_atom);
export const WsStatusIndicator = () => {
const [ws] = useWebsocket();
const onclick = () =>
toast({ title: "surprise", description: "motherfucker" });
return (
<Button variant="ghost" onClick={onclick}>
<Circle
className={cn(
"w-4 h-4 stroke-none",
!!ws ? "fill-green-500" : "fill-red-500"
)}
/>
</Button>
);
};
export const WebsocketProvider = ({ children }: { children: ReactNode }) => {
const invalidate = useInvalidate();
const [ws] = useWebsocket();
ws.addEventListener("open", () => {
const token = localStorage.getItem("token");
const token = localStorage.getItem("monitor-auth-token");
if (token) ws.send(token);
set(true);
});
ws.addEventListener("message", ({ data }) => {
if (data == "LOGGED_IN") return console.log("logged in to ws");
const update = JSON.parse(data) as Types.Update;
toast({
title: `${update.target} ${update.operation}`,
description: update.operator,
});
invalidate(["ListUpdates"]);
if (update.target.type === "Deployment") {
invalidate(
["ListDeployments"],
["GetDeployment", { id: update.target.id }],
["GetLog", { id: update.target.id }],
["GetDeploymentActionState", { id: update.target.id }],
["GetDeploymentStatus", { id: update.target.id }]
);
}
if (update.target.type === "Server") {
invalidate(
["ListServers"],
["GetServer", { id: update.target.id }],
["GetServerActionState", { id: update.target.id }],
["GetServerStatus", { id: update.target.id }],
["GetHistoricalServerStats", { id: update.target.id }]
);
}
if (update.target.type === "Build") {
invalidate(
["ListBuilds"],
["GetBuild", { id: update.target.id }],
["GetBuildActionState", { id: update.target.id }]
);
}
});
return <>{children}</>;
};