Skip to content

Commit

Permalink
Make the server info page
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyberboss committed Oct 21, 2024
1 parent 4176674 commit 991e9e4
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 12 deletions.
5 changes: 3 additions & 2 deletions src/components/core/Router/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const NotFound = lazy(

const Router = () => {
const relayEnviroment = useRelayEnvironment();
const homeRoutes = HomeRoutes(relayEnviroment);
const router = createBrowserRouter([
{
path: "/",
Expand All @@ -41,14 +42,14 @@ const Router = () => {
path: "login",
element: <Login />
},
...HomeRoutes.filter(route => route.unprotected),
...homeRoutes.filter(route => route.unprotected),
{
element: <ProtectedRoute />,
children: [
HomeRouteLoader(relayEnviroment, {
path: ""
}),
...HomeRoutes.filter(route => !route.unprotected),
...homeRoutes.filter(route => !route.unprotected),
{
path: "*",
element: <NotFound />
Expand Down
5 changes: 3 additions & 2 deletions src/components/routed/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FormattedMessage } from "react-intl";
import { PreloadedQuery, usePreloadedQuery } from "react-relay";
import { PreloadedQuery, usePreloadedQuery, useRelayEnvironment } from "react-relay";

import { HomeCardPermissionsQuery } from "./graphql/__generated__/HomeCardPermissionsQuery.graphql";
import HomeCardPermissions from "./graphql/HomeCardPermissions";
Expand All @@ -15,6 +15,7 @@ interface IProps {

const Home = (props: IProps) => {
const session = useSession();
const relayEnvironment = useRelayEnvironment();
const usingDefaultCredentials =
!!session.currentSession?.originalCredentials.defaultCredentials;

Expand All @@ -34,7 +35,7 @@ const Home = (props: IProps) => {
</Alert>
) : null}
<div className="flex flex-row flex-wrap justify-center">
{HomeRoutes.map(route => (
{HomeRoutes(relayEnvironment).map(route => (
<div
key={route.localeNameId}
className="basis-full sm:basis-1/2 md:basis-1/3 lg:basis-1/4">
Expand Down
12 changes: 7 additions & 5 deletions src/components/routed/Home/HomeRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import {
faUser
} from "@fortawesome/free-solid-svg-icons";
import { lazy } from "react";
import { Environment } from "react-relay";
import { RouteObject } from "react-router-dom";

import ServerInfoRouteLoader from "../ServerInfo/ServerInfoRouteLoader";

import HomeCardProps from "./HomeCard/HomeCardProps";

import NotFound from "@/components/core/NotFound/NotFound";
Expand All @@ -28,7 +31,7 @@ interface IHomeRouteProtected {

type HomeRoute = RouteObject & IHomeRouteProtected & Omit<HomeCardProps, "queryData">;

const HomeRoutes: HomeRoute[] = [
const HomeRoutes = (relayEnviroment: Environment): HomeRoute[] => [
{
path: "instances",
icon: faHdd,
Expand Down Expand Up @@ -72,12 +75,11 @@ const HomeRoutes: HomeRoute[] = [
element: <Configuration />,
unprotected: true
},
{
ServerInfoRouteLoader(relayEnviroment, {
path: "/info",
icon: faInfoCircle,
localeNameId: "routes.info",
element: <NotFound />
}
localeNameId: "routes.info"
})
];

export default HomeRoutes;
188 changes: 188 additions & 0 deletions src/components/routed/ServerInfo/ServerInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { faLinux, faWindows } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FormattedMessage } from "react-intl";
import { PreloadedQuery, usePreloadedQuery } from "react-relay";

import { ServerInformationQuery } from "./graphql/__generated__/ServerInformationQuery.graphql";
import ServerInformation from "./graphql/ServerInformation";

import Pkg from "@/../package.json";
import capitalizeFirstLetter from "@/lib/capitalizeFirstLetter";

interface IProps {
queryRef: PreloadedQuery<ServerInformationQuery> | null;
}

const ServerInfo = (props: IProps) => {
if (!props.queryRef) {
throw new Error("ServerInformationQuery ref was null");
}

const data = usePreloadedQuery<ServerInformationQuery>(ServerInformation, props.queryRef);
const gatewayInfo = data.swarm.currentNode.gateway.information;
const activeOAuthProviders = Object.keys(gatewayInfo.oAuthProviderInfos ?? {}).filter(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
key => !!(gatewayInfo.oAuthProviderInfos as any)[key]
);

return (
<div className="text-center text-lg">
<h3>
<FormattedMessage id="view.info.client" />
</h3>
<div className="text-primary">
<h4>
<FormattedMessage id="view.info.version" />
{`${Pkg.version} (${import.meta.env.MODE.toLocaleUpperCase()})`}
</h4>
</div>

<hr />

<h3>
<FormattedMessage id="view.info.server" />
</h3>
<div className="text-primary">
<table className="mx-auto text-left">
<tbody>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.admin.hostos" />
</h4>
</td>
<td>
<h4>
<FontAwesomeIcon
fixedWidth
icon={gatewayInfo.windowsHost ? faWindows : faLinux}
/>
</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.version" />
</h4>
</td>
<td>
<h4>{gatewayInfo.version}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.gqlapiversion" />
</h4>
</td>
<td>
<h4>{gatewayInfo.apiVersion}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.dmapiversion" />
</h4>
</td>
<td>
<h4>{gatewayInfo.dmApiVersion}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.swarmversion" />
</h4>
</td>
<td>
<h4>{gatewayInfo.swarmProtocolVersion}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.minpassword" />
</h4>
</td>
<td>
<h4>{gatewayInfo.minimumPasswordLength}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.instancelimit" />
</h4>
</td>
<td>
<h4>{gatewayInfo.instanceLimit}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.userlimit" />
</h4>
</td>
<td>
<h4>{gatewayInfo.userLimit}</h4>
</td>
</tr>
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.grouplimit" />
</h4>
</td>
<td>
<h4>{gatewayInfo.userGroupLimit}</h4>
</td>
</tr>
{activeOAuthProviders.length > 0 ? (
<tr>
<td>
<h4 className="mr-3">
<FormattedMessage id="view.info.oauth" />
</h4>
</td>
<td>
<h4>
{activeOAuthProviders.map(capitalizeFirstLetter).join(", ")}
</h4>
</td>
</tr>
) : null}
</tbody>
</table>
</div>
{data.swarm.nodes?.length ? (
<>
<hr />

<FormattedMessage id="view.info.swarm" tagName="h3" />

{data.swarm.nodes.map(server => {
return (
<h4
key={server.identifier}
className={
server.controller
? "font-weight-bold text-primary"
: "text-primary"
}>
{server.identifier} ({server.address}){" "}
{server.controller ? (
<FormattedMessage id="view.info.controller" />
) : null}
</h4>
);
})}
</>
) : null}
</div>
);
};

export default ServerInfo;
27 changes: 27 additions & 0 deletions src/components/routed/ServerInfo/ServerInfoRouteLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { lazy } from "react";
import { Environment } from "react-relay";
import { RouteObject } from "react-router-dom";

import { ServerInformationQuery } from "./graphql/__generated__/ServerInformationQuery.graphql";
import ServerInformation from "./graphql/ServerInformation";

import devDelay from "@/lib/devDelay";
import RouteQueryLoader from "@/lib/RouteQueryLoader";

const ServerInfo = lazy(
async () => await devDelay(() => import("./ServerInfo"), "Component Load: ServerInfo")
);

const ServerInfoRouteLoader = <TRouteObject extends RouteObject>(
relayEnvironment: Environment,
partialRoute: TRouteObject
): TRouteObject =>
RouteQueryLoader<ServerInformationQuery, TRouteObject>(
relayEnvironment,
ServerInformation,
() => ({}),
partialRoute,
queryRef => <ServerInfo queryRef={queryRef} />
);

export default ServerInfoRouteLoader;
96 changes: 96 additions & 0 deletions src/components/routed/ServerInfo/ServerInformation.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { Meta, StoryObj } from "@storybook/react";
import { Suspense } from "react";
import { loadQuery, useRelayEnvironment } from "react-relay";

import { ServerInformationQuery } from "./graphql/__generated__/ServerInformationQuery.graphql";
import ServerInformation from "./graphql/ServerInformation";
import ServerInfo from "./ServerInfo";

import { WithRelayParameters } from "@/../.storybook/MockRelayEnvironment";

const variables = {};

const TestComponent = () => {
const queryRef = loadQuery<ServerInformationQuery>(
useRelayEnvironment(),
ServerInformation,
variables
);

return (
<Suspense>
<ServerInfo queryRef={queryRef} />
</Suspense>
);
};

const CreateRelay = (): WithRelayParameters<ServerInformationQuery> => ({
query: ServerInformation,
mockResolvers: {
Query: () => ({
swarm: {
currentNode: {
gateway: {
information: {
apiVersion: "10.10.0",
dmApiVersion: "5.10.0",
graphQLApiVersion: "0.3.0",
instanceLimit: 10,
minimumPasswordLength: 15,
swarmProtocolVersion: "7.0.0",
userGroupLimit: 25,
userLimit: 100,
version: "6.11.1",
windowsHost: true,
oAuthProviderInfos: {
discord: {
clientID: "asdf"
},
gitHub: {
clientID: "asdf"
},
invisionCommunity: {
clientID: "asdf"
},
keycloak: {
clientID: "asdf"
},
tgForums: {
clientID: "asdf"
}
}
}
}
},
nodes: [
{
address: "http://example1.org",
controller: true,
identifier: "Pro-Skub"
},
{
address: "http://example1.org",
controller: false,
identifier: "Anti-Skub"
}
]
}
})
},
variables
});

const config: Meta<typeof TestComponent> = {
component: TestComponent,
title: "Routed/ServerInfo"
};

export default config;

type Story = StoryObj<typeof config>;

export const Default: Story = {
parameters: {
relay: CreateRelay()
}
};
Loading

0 comments on commit 991e9e4

Please sign in to comment.