Skip to content

Commit

Permalink
Merge pull request #335 from tgstation/MoreWorkCauseWhyNot
Browse files Browse the repository at this point in the history
Setup Home Page
  • Loading branch information
Cyberboss authored Oct 20, 2024
2 parents c0e1d32 + 5f06e82 commit 8ca18cf
Show file tree
Hide file tree
Showing 21 changed files with 314 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .storybook/AddConfigDark.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC } from "react";

import ConfigProvider from "../src/context/config/Provider";
import ConfigProvider from "../src/context/config/ConfigProvider";

const AddConfigDark = (Story: FC) => {
return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { lazy, StrictMode, Suspense, useEffect, useState } from "react";
import { IntlProvider } from "react-intl";

import ConfigProvider from "../context/config/Provider";
import ConfigProvider from "../context/config/ConfigProvider";
import devDelay from "../lib/devDelay";
import ITranslation from "../lib/translations/ITranslation";
import ITranslationFactory from "../lib/translations/ITranslationFactory";
Expand Down
4 changes: 2 additions & 2 deletions src/components/core/Environment/Environment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import Router from "../Router/Router";

import Pkg from "@/../package.json";
import useConfig from "@/context/config/useConfig";
import ErrorsProvider from "@/context/errors/Provider";
import SessionProvider from "@/context/session/Provider";
import ErrorsProvider from "@/context/errors/ErrorsProvider";
import SessionProvider from "@/context/session/SessionProvider";
import CreateRelayEnvironment from "@/lib/CreateRelayEnvironment";

const Environment = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/core/ErrorViewer/ErrorViewer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useEffect } from "react";
import ErrorViewer from "./ErrorViewer";

import { ErrorMessageSingleFragment$data } from "@/components/graphql/__generated__/ErrorMessageSingleFragment.graphql";
import ErrorsProvider from "@/context/errors/Provider";
import ErrorsProvider from "@/context/errors/ErrorsProvider";
import useErrors from "@/context/errors/useErrors";
import sleep from "@/lib/sleep";

Expand Down
20 changes: 6 additions & 14 deletions src/components/core/Router/Router.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { lazy, Suspense } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

import HomeRoutes from "../../routed/Home/HomeRoutes";

import ProtectedRoute from "./ProtectedRoute/ProtectedRoute";
import RethrowRouteError from "./RethrowRouteError/RethrowRouteError";

import devDelay from "@/lib/devDelay";
import { ICredentials } from "@/lib/Credentials";
import Loading from "@/components/utils/Loading/Loading";

const Configuration = lazy(
async () =>
await devDelay(
() => import("@/components/routed/Configuration/Configuration"),
"Component Load: Configuration"
)
);
import { ICredentials } from "@/lib/Credentials";
import devDelay from "@/lib/devDelay";

const Home = lazy(
async () =>
Expand Down Expand Up @@ -50,21 +44,19 @@ const Router = (props: IProps) => {
element: <Layout />,
errorElement: <RethrowRouteError />,
children: [
{
path: "config",
element: <Configuration />
},
{
path: "login",
element: <Login setTemporaryCredentials={props.setTemporaryCredentials} />
},
...HomeRoutes.filter(route => route.unprotected),
{
element: <ProtectedRoute />,
children: [
{
path: "",
element: <Home />
},
...HomeRoutes.filter(route => !route.unprotected),
{
path: "*",
element: <NotFound />
Expand Down
82 changes: 82 additions & 0 deletions src/components/routed/Home/Home.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Meta, StoryObj } from "@storybook/react";

import { HomeCardPermissionsQuery } from "./graphql/__generated__/HomeCardPermissionsQuery.graphql";
import HomeCardPermissions from "./graphql/HomeCardPermissions";
import Home from "./Home";

import { WithRelayParameters } from "@/../.storybook/MockRelayEnvironment";
import SessionContext from "@/context/session/SessionContext";
import { DefaultUserPasswordCredentials, UserPasswordCredentials } from "@/lib/Credentials";

interface IArgs {
defaultCredentials: boolean;
}

const TestComponent = (props: IArgs) => {
const session = {
currentSession: {
bearer: "asdf",
userId: "fdsa",
originalCredentials: props.defaultCredentials
? new DefaultUserPasswordCredentials()
: new UserPasswordCredentials("asdf", "asdf")
},
setSession: () => {}
};

return (
<SessionContext.Provider value={session}>
<Home />
</SessionContext.Provider>
);
};

const CreateRelay = (fieldsEnabled: boolean): WithRelayParameters<HomeCardPermissionsQuery> => ({
query: HomeCardPermissions,
mockResolvers: {
PermissionSet: () => ({
administrationRights: {
canChangeVersion: fieldsEnabled,
canDownloadLogs: fieldsEnabled,
canEditOwnPassword: fieldsEnabled,
canReadUsers: fieldsEnabled,
canUploadVersion: fieldsEnabled,
canWriteUsers: fieldsEnabled
},
instanceManagerRights: {
canList: fieldsEnabled,
canRead: fieldsEnabled
}
})
}
});

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

export default config;

type Story = StoryObj<typeof config>;

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

export const DisabledPerms: Story = {
parameters: {
relay: CreateRelay(false)
}
};

export const WithDefaultAdminPassword: Story = {
args: {
defaultCredentials: true
},
parameters: {
relay: CreateRelay(true)
}
};
38 changes: 37 additions & 1 deletion src/components/routed/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
import { FormattedMessage } from "react-intl";
import { useLazyLoadQuery } from "react-relay";

import { HomeCardPermissionsQuery } from "./graphql/__generated__/HomeCardPermissionsQuery.graphql";
import HomeCardPermissions from "./graphql/HomeCardPermissions";
import HomeCard from "./HomeCard/HomeCard";
import HomeRoutes from "./HomeRoutes";

import { Alert, AlertDescription } from "@/components/ui/alert";
import useSession from "@/context/session/useSession";

const Home = () => {
return <></>;
const session = useSession();
const usingDefaultCredentials =
!!session.currentSession?.originalCredentials.defaultCredentials;

const data = useLazyLoadQuery<HomeCardPermissionsQuery>(HomeCardPermissions, {
userID: session.currentSession!.userId
});

return (
<>
{usingDefaultCredentials ? (
<Alert className="clearfix bg-warning mb-4">
<AlertDescription className="font-bold text-warning-foreground text-lg text-center">
<FormattedMessage id="error.app.default_creds" />
</AlertDescription>
</Alert>
) : null}
<div className="flex flex-row flex-wrap justify-center">
{HomeRoutes.map(route => (
<div className="basis-full sm:basis-1/2 md:basis-1/3 lg:basis-1/4">
<HomeCard key={route.localeNameId} {...route} queryData={data} />
</div>
))}
</div>
</>
);
};

export default Home;
29 changes: 29 additions & 0 deletions src/components/routed/Home/HomeCard/HomeCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FormattedMessage } from "react-intl";
import { Link } from "react-router-dom";

import IHomeCardProps from "./HomeCardProps";

import { Card, CardContent, CardFooter } from "@/components/ui/card";

const HomeCard = (props: IHomeCardProps) => {
const enabled = props.calculateEnabled ? props.calculateEnabled(props.queryData) : true;
const RenderCard = () => (
<Card
className={enabled ? "text-primary hover:text-primary-foreground" : "text-destructive"}>
<CardContent style={{ height: "245px" }} className="text-center border-0">
<FontAwesomeIcon className="w-4/5 h-4/5 mt-4 mb-4" icon={props.icon} />
<hr />
</CardContent>
<CardFooter className={"justify-center font-bold text-lg" + (enabled ? "" : "italic")}>
<FormattedMessage id={props.localeNameId} />
</CardFooter>
</Card>
);
return (
<div className="m-4">
{enabled ? <Link to={props.path}>{RenderCard()}</Link> : RenderCard()}
</div>
);
};
export default HomeCard;
11 changes: 11 additions & 0 deletions src/components/routed/Home/HomeCard/HomeCardProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IconProp } from "@fortawesome/fontawesome-svg-core";

import { HomeCardPermissionsQuery$data } from "../graphql/__generated__/HomeCardPermissionsQuery.graphql";

export default interface IHomeCardProps {
icon: IconProp;
localeNameId: string;
path: string;
calculateEnabled?: (data: HomeCardPermissionsQuery$data) => boolean | undefined;
queryData: HomeCardPermissionsQuery$data;
}
83 changes: 83 additions & 0 deletions src/components/routed/Home/HomeRoutes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
faCogs,
faHdd,
faInfoCircle,
faKey,
faTools,
faUser
} from "@fortawesome/free-solid-svg-icons";
import { lazy } from "react";
import { RouteObject } from "react-router-dom";

import HomeCardProps from "./HomeCard/HomeCardProps";

import NotFound from "@/components/core/NotFound/NotFound";
import devDelay from "@/lib/devDelay";

const Configuration = lazy(
async () =>
await devDelay(
() => import("@/components/routed/Configuration/Configuration"),
"Component Load: Configuration"
)
);

interface IHomeRouteProtected {
unprotected?: boolean;
}

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

const HomeRoutes: HomeRoute[] = [
{
path: "instances",
icon: faHdd,
localeNameId: "routes.instancelist",
calculateEnabled: data =>
data.node?.effectivePermissionSet?.instanceManagerRights.canList ||
data.node?.effectivePermissionSet?.instanceManagerRights.canRead,
element: <NotFound />
},
{
path: "users",
icon: faUser,
localeNameId: "routes.usermanager",
calculateEnabled: data =>
data.node?.effectivePermissionSet?.administrationRights.canReadUsers ||
data.node?.effectivePermissionSet?.administrationRights.canWriteUsers,
element: <NotFound />
},
{
path: "admin",
icon: faTools,
localeNameId: "routes.admin",
calculateEnabled: data =>
data.node?.effectivePermissionSet?.administrationRights.canChangeVersion ||
data.node?.effectivePermissionSet?.administrationRights.canDownloadLogs ||
data.node?.effectivePermissionSet?.administrationRights.canUploadVersion,
element: <NotFound />
},
{
path: "/users/passwd",
icon: faKey,
localeNameId: "routes.passwd",
calculateEnabled: data =>
data.node?.effectivePermissionSet?.administrationRights.canEditOwnPassword,
element: <NotFound />
},
{
path: "/config",
icon: faCogs,
localeNameId: "routes.config",
element: <Configuration />,
unprotected: true
},
{
path: "/info",
icon: faInfoCircle,
localeNameId: "routes.info",
element: <NotFound />
}
];

export default HomeRoutes;
26 changes: 26 additions & 0 deletions src/components/routed/Home/graphql/HomeCardPermissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { graphql } from "react-relay";

const HomeCardPermissions = graphql`
query HomeCardPermissionsQuery($userID: ID!) {
node(id: $userID) {
... on User {
effectivePermissionSet {
administrationRights {
canChangeVersion
canDownloadLogs
canUploadVersion
canEditOwnPassword
canReadUsers
canWriteUsers
}
instanceManagerRights {
canList
canRead
}
}
}
}
}
`;

export default HomeCardPermissions;
5 changes: 2 additions & 3 deletions src/components/routed/Login/Login.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import {
} from "./OAuthOptions/graphql/__generated__/GetOAuthProvidersQuery.graphql";

import { MockRelayEnvironment, WithRelayParameters } from "@/../.storybook/MockRelayEnvironment";
import ErrorsProvider from "@/context/errors/Provider";
import ErrorsProvider from "@/context/errors/ErrorsProvider";
import useErrors from "@/context/errors/useErrors";
import SessionProvider from "@/context/session/Provider";
import SessionProvider from "@/context/session/SessionProvider";
import useSession from "@/context/session/useSession";
import { ICredentials } from "@/lib/Credentials";
import sleep from "@/lib/sleep";
Expand Down Expand Up @@ -134,7 +134,6 @@ const config: Meta<typeof TestComponent> = {
}
},
parameters: {
query: GetOAuthProviders,
relay
}
};
Expand Down
Loading

0 comments on commit 8ca18cf

Please sign in to comment.