mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-08-28 19:40:28 +00:00
Version 3 starter
This commit is contained in:
56
frontend/src/components/Footer.tsx
Normal file
56
frontend/src/components/Footer.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import React from "react";
|
||||
|
||||
import { useHealthState } from "context";
|
||||
import styled from "styled-components";
|
||||
import { Site } from "tabler-react";
|
||||
|
||||
const FixedFooterWrapper = styled.div`
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
fixed?: boolean;
|
||||
}
|
||||
function Footer({ fixed }: Props) {
|
||||
const { health } = useHealthState();
|
||||
|
||||
const footerNav = (
|
||||
<div>
|
||||
<a
|
||||
href="https://nginxproxymanager.com?utm_source=npm"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
User Guide
|
||||
</a>{" "}
|
||||
{String.fromCharCode(183)}{" "}
|
||||
<a
|
||||
href="https://github.com/jc21/nginx-proxy-manager/releases?utm_source=npm"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
Changelog
|
||||
</a>{" "}
|
||||
{String.fromCharCode(183)}{" "}
|
||||
<a
|
||||
href="https://github.com/jc21/nginx-proxy-manager?utm_source=npm"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
Github
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
const note =
|
||||
"v" + health.version + " " + String.fromCharCode(183) + " " + health.commit;
|
||||
|
||||
return fixed ? (
|
||||
<FixedFooterWrapper>
|
||||
<Site.Footer copyright={note} nav={footerNav} />
|
||||
</FixedFooterWrapper>
|
||||
) : (
|
||||
<Site.Footer copyright={note} nav={footerNav} />
|
||||
);
|
||||
}
|
||||
|
||||
export { Footer };
|
18
frontend/src/components/Loading.tsx
Normal file
18
frontend/src/components/Loading.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
import styled from "styled-components";
|
||||
import { Loader } from "tabler-react";
|
||||
|
||||
const Root = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
function Loading() {
|
||||
return (
|
||||
<Root>
|
||||
<Loader />
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
export { Loading };
|
57
frontend/src/components/Router.tsx
Normal file
57
frontend/src/components/Router.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import React, { lazy, Suspense } from "react";
|
||||
|
||||
import { Loading, SiteWrapper, SinglePage } from "components";
|
||||
import { useAuthState, useHealthState, UserProvider } from "context";
|
||||
import { BrowserRouter, Switch, Route } from "react-router-dom";
|
||||
|
||||
const Setup = lazy(() => import("pages/Setup"));
|
||||
const Dashboard = lazy(() => import("pages/Dashboard"));
|
||||
const Login = lazy(() => import("pages/Login"));
|
||||
|
||||
function Router() {
|
||||
const { health } = useHealthState();
|
||||
const { authenticated } = useAuthState();
|
||||
const Spinner = (
|
||||
<SinglePage>
|
||||
<Loading />
|
||||
</SinglePage>
|
||||
);
|
||||
|
||||
if (health.loading) {
|
||||
return Spinner;
|
||||
}
|
||||
|
||||
if (health.healthy && !health.setup) {
|
||||
return (
|
||||
<Suspense fallback={Spinner}>
|
||||
<Setup />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
if (!authenticated) {
|
||||
return (
|
||||
<Suspense fallback={Spinner}>
|
||||
<Login />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<UserProvider>
|
||||
<BrowserRouter>
|
||||
<SiteWrapper>
|
||||
<Suspense fallback={Spinner}>
|
||||
<Switch>
|
||||
<Route path="/">
|
||||
<Dashboard />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</SiteWrapper>
|
||||
</BrowserRouter>
|
||||
</UserProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default Router;
|
32
frontend/src/components/SinglePage.tsx
Normal file
32
frontend/src/components/SinglePage.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
import { Footer } from "components";
|
||||
import styled from "styled-components";
|
||||
|
||||
const Root = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: 100%;
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
}
|
||||
function SinglePage({ children }: Props) {
|
||||
return (
|
||||
<Root>
|
||||
<Wrapper>{children}</Wrapper>
|
||||
<Footer />
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
export { SinglePage };
|
193
frontend/src/components/SiteWrapper.tsx
Normal file
193
frontend/src/components/SiteWrapper.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
import { Footer } from "components";
|
||||
import { useAuthState, useUserState } from "context";
|
||||
import styled from "styled-components";
|
||||
import { Site, Container, Button, Grid, List } from "tabler-react";
|
||||
|
||||
const StyledContainer = styled(Container)`
|
||||
padding-bottom: 30px;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
}
|
||||
function SiteWrapper({ children }: Props) {
|
||||
const user = useUserState();
|
||||
const { logout } = useAuthState();
|
||||
|
||||
const accountDropdownProps = {
|
||||
avatarURL: user.gravatarUrl,
|
||||
name: user.nickname,
|
||||
description: user.roles.includes("admin")
|
||||
? "Administrator"
|
||||
: "Standard User",
|
||||
options: [
|
||||
{ icon: "user", value: "Profile" },
|
||||
{ icon: "settings", value: "Settings" },
|
||||
{ isDivider: true },
|
||||
{
|
||||
icon: "help-circle",
|
||||
value: "Need help?",
|
||||
href: "https://nginxproxymanager.com",
|
||||
target: "_blank",
|
||||
},
|
||||
{ icon: "log-out", value: "Log out", onClick: logout },
|
||||
],
|
||||
};
|
||||
|
||||
const navBarItems = [
|
||||
{
|
||||
value: "Home",
|
||||
to: "/",
|
||||
icon: "home",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
useExact: true,
|
||||
},
|
||||
{
|
||||
value: "Interface",
|
||||
icon: "box",
|
||||
subItems: [
|
||||
{
|
||||
value: "Cards Design",
|
||||
to: "/cards",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
//{ value: "Charts", to: "/charts", LinkComponent: withRouter(NavLink) },
|
||||
{
|
||||
value: "Pricing Cards",
|
||||
to: "/pricing-cards",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "Components",
|
||||
icon: "calendar",
|
||||
/*
|
||||
subItems: [
|
||||
{ value: "Maps", to: "/maps", LinkComponent: withRouter(NavLink) },
|
||||
{ value: "Icons", to: "/icons", LinkComponent: withRouter(NavLink) },
|
||||
{ value: "Store", to: "/store", LinkComponent: withRouter(NavLink) },
|
||||
{ value: "Blog", to: "/blog", LinkComponent: withRouter(NavLink) },
|
||||
],
|
||||
*/
|
||||
},
|
||||
{
|
||||
value: "Pages",
|
||||
icon: "file",
|
||||
subItems: [
|
||||
{
|
||||
value: "Profile",
|
||||
to: "/profile",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
//{ value: "Login", to: "/login", LinkComponent: withRouter(NavLink) },
|
||||
{
|
||||
value: "Register",
|
||||
to: "/register",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
value: "Forgot password",
|
||||
to: "/forgot-password",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
value: "Empty page",
|
||||
to: "/empty-page",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
//{ value: "RTL", to: "/rtl", LinkComponent: withRouter(NavLink) },
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "Forms",
|
||||
to: "/form-elements",
|
||||
icon: "check-square",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
value: "Gallery",
|
||||
to: "/gallery",
|
||||
icon: "image",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
icon: "file-text",
|
||||
value: "Documentation",
|
||||
to:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "https://tabler.github.io/tabler-react/documentation"
|
||||
: "/documentation",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Site.Wrapper
|
||||
headerProps={{
|
||||
href: "/",
|
||||
alt: "Nginx Proxy Manager",
|
||||
imageURL: "/images/logo-bold-horizontal-grey.svg",
|
||||
accountDropdown: accountDropdownProps,
|
||||
}}
|
||||
navProps={{ itemsObjects: navBarItems }}
|
||||
//routerContextComponentType={withRouter(RouterContextProvider)}
|
||||
footerProps={{
|
||||
links: [
|
||||
<a href="#asd">First Link</a>,
|
||||
<a href="#fg">Second Link</a>,
|
||||
<a href="#dsg">Third Link</a>,
|
||||
<a href="#egf">Fourth Link</a>,
|
||||
<a href="#dsf">Five Link</a>,
|
||||
<a href="#sdfg">Sixth Link</a>,
|
||||
<a href="#sdf">Seventh Link</a>,
|
||||
<a href="#sdf">Eigth Link</a>,
|
||||
],
|
||||
note: "Premium and Open Source dashboard template with responsive and high quality UI. For Free!",
|
||||
copyright: (
|
||||
<React.Fragment>
|
||||
Copyright © 2019
|
||||
<a href="."> Tabler-react</a>. Theme by
|
||||
<a
|
||||
href="https://codecalm.net"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
{" "}
|
||||
codecalm.net
|
||||
</a>{" "}
|
||||
All rights reserved.
|
||||
</React.Fragment>
|
||||
),
|
||||
nav: (
|
||||
<React.Fragment>
|
||||
<Grid.Col auto={true}>
|
||||
<List className="list-inline list-inline-dots mb-0">
|
||||
<List.Item className="list-inline-item">
|
||||
<a href="./docs/index.html">Documentation</a>
|
||||
</List.Item>
|
||||
<List.Item className="list-inline-item">
|
||||
<a href="./faq.html">FAQ</a>
|
||||
</List.Item>
|
||||
</List>
|
||||
</Grid.Col>
|
||||
<Grid.Col auto={true}>
|
||||
<Button
|
||||
href="https://github.com/tabler/tabler-react"
|
||||
size="sm"
|
||||
outline
|
||||
color="primary"
|
||||
RootComponent="a">
|
||||
Source code
|
||||
</Button>
|
||||
</Grid.Col>
|
||||
</React.Fragment>
|
||||
),
|
||||
}}>
|
||||
<StyledContainer>{children}</StyledContainer>
|
||||
<Footer fixed />
|
||||
</Site.Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export { SiteWrapper };
|
45
frontend/src/components/Unhealthy.tsx
Normal file
45
frontend/src/components/Unhealthy.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from "react";
|
||||
|
||||
import styled from "styled-components";
|
||||
import { Alert } from "tabler-react";
|
||||
|
||||
const Root = styled.div`
|
||||
padding: 20vh 10vw 0 10vw;
|
||||
|
||||
&& .ant-alert-warning {
|
||||
background-color: #2a2a2a;
|
||||
border: 2px solid #2ab1a4;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
&& .ant-alert-message {
|
||||
color: #fff;
|
||||
font-size: 6vh;
|
||||
}
|
||||
|
||||
&& .ant-alert-description {
|
||||
font-size: 4vh;
|
||||
line-height: 5vh;
|
||||
}
|
||||
|
||||
&& .ant-alert-with-description {
|
||||
padding-left: 23vh;
|
||||
}
|
||||
|
||||
&& .ant-alert-with-description .ant-alert-icon {
|
||||
font-size: 15vh;
|
||||
}
|
||||
`;
|
||||
|
||||
function Unhealthy() {
|
||||
return (
|
||||
<Root>
|
||||
<Alert type="warning" icon="alert-triangle">
|
||||
Nginx Proxy Manager is <strong>unhealthy</strong>. We'll continue to
|
||||
check the health and hope to be back up and running soon!
|
||||
</Alert>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
export { Unhealthy };
|
6
frontend/src/components/index.ts
Normal file
6
frontend/src/components/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from "./Footer";
|
||||
export * from "./Loading";
|
||||
export * from "./Router";
|
||||
export * from "./SinglePage";
|
||||
export * from "./SiteWrapper";
|
||||
export * from "./Unhealthy";
|
56
frontend/src/components/page/Footer.tsx
Normal file
56
frontend/src/components/page/Footer.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import React from "react";
|
||||
|
||||
import { useHealthState } from "context";
|
||||
import styled from "styled-components";
|
||||
import { Site } from "tabler-react";
|
||||
|
||||
const FixedFooterWrapper = styled.div`
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
fixed?: boolean;
|
||||
}
|
||||
function Footer({ fixed }: Props) {
|
||||
const { health } = useHealthState();
|
||||
|
||||
const footerNav = (
|
||||
<div>
|
||||
<a
|
||||
href="https://nginxproxymanager.com?utm_source=npm"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
User Guide
|
||||
</a>{" "}
|
||||
{String.fromCharCode(183)}{" "}
|
||||
<a
|
||||
href="https://github.com/jc21/nginx-proxy-manager/releases?utm_source=npm"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
Changelog
|
||||
</a>{" "}
|
||||
{String.fromCharCode(183)}{" "}
|
||||
<a
|
||||
href="https://github.com/jc21/nginx-proxy-manager?utm_source=npm"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
Github
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
const note =
|
||||
"v" + health.version + " " + String.fromCharCode(183) + " " + health.commit;
|
||||
|
||||
return fixed ? (
|
||||
<FixedFooterWrapper>
|
||||
<Site.Footer copyright={note} nav={footerNav} />
|
||||
</FixedFooterWrapper>
|
||||
) : (
|
||||
<Site.Footer copyright={note} nav={footerNav} />
|
||||
);
|
||||
}
|
||||
|
||||
export { Footer };
|
130
frontend/src/components/page/Header.tsx
Normal file
130
frontend/src/components/page/Header.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import React from "react";
|
||||
|
||||
import { useAuthState, useUserState } from "context";
|
||||
import { Site } from "tabler-react";
|
||||
|
||||
function Header() {
|
||||
const user = useUserState();
|
||||
const { logout } = useAuthState();
|
||||
|
||||
const accountDropdownProps = {
|
||||
avatarURL: user.gravatarUrl,
|
||||
name: user.nickname,
|
||||
description: user.roles.includes("admin")
|
||||
? "Administrator"
|
||||
: "Standard User",
|
||||
options: [
|
||||
{ icon: "user", value: "Profile" },
|
||||
{ icon: "settings", value: "Settings" },
|
||||
{ isDivider: true },
|
||||
{
|
||||
icon: "help-circle",
|
||||
value: "Need help?",
|
||||
href: "https://nginxproxymanager.com",
|
||||
target: "_blank",
|
||||
},
|
||||
{ icon: "log-out", value: "Log out", onClick: logout },
|
||||
],
|
||||
};
|
||||
|
||||
const navBarItems = [
|
||||
{
|
||||
value: "Home",
|
||||
to: "/",
|
||||
icon: "home",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
useExact: true,
|
||||
},
|
||||
{
|
||||
value: "Interface",
|
||||
icon: "box",
|
||||
subItems: [
|
||||
{
|
||||
value: "Cards Design",
|
||||
to: "/cards",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
//{ value: "Charts", to: "/charts", LinkComponent: withRouter(NavLink) },
|
||||
{
|
||||
value: "Pricing Cards",
|
||||
to: "/pricing-cards",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "Components",
|
||||
icon: "calendar",
|
||||
/*
|
||||
subItems: [
|
||||
{ value: "Maps", to: "/maps", LinkComponent: withRouter(NavLink) },
|
||||
{ value: "Icons", to: "/icons", LinkComponent: withRouter(NavLink) },
|
||||
{ value: "Store", to: "/store", LinkComponent: withRouter(NavLink) },
|
||||
{ value: "Blog", to: "/blog", LinkComponent: withRouter(NavLink) },
|
||||
],
|
||||
*/
|
||||
},
|
||||
{
|
||||
value: "Pages",
|
||||
icon: "file",
|
||||
subItems: [
|
||||
{
|
||||
value: "Profile",
|
||||
to: "/profile",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
//{ value: "Login", to: "/login", LinkComponent: withRouter(NavLink) },
|
||||
{
|
||||
value: "Register",
|
||||
to: "/register",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
value: "Forgot password",
|
||||
to: "/forgot-password",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
value: "Empty page",
|
||||
to: "/empty-page",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
//{ value: "RTL", to: "/rtl", LinkComponent: withRouter(NavLink) },
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "Forms",
|
||||
to: "/form-elements",
|
||||
icon: "check-square",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
value: "Gallery",
|
||||
to: "/gallery",
|
||||
icon: "image",
|
||||
//LinkComponent: withRouter(NavLink),
|
||||
},
|
||||
{
|
||||
icon: "file-text",
|
||||
value: "Documentation",
|
||||
to:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "https://tabler.github.io/tabler-react/documentation"
|
||||
: "/documentation",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Site.Header
|
||||
href="/"
|
||||
alt="Nginx Proxy Manager"
|
||||
imageURL="/images/logo-bold-horizontal-grey.svg"
|
||||
accountDropdown={accountDropdownProps}
|
||||
/>
|
||||
<Site.Nav itemsObjects={navBarItems} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export { Header };
|
2
frontend/src/components/page/index.ts
Normal file
2
frontend/src/components/page/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./Footer";
|
||||
export * from "./Header";
|
Reference in New Issue
Block a user