rapid patch: add event info banner (related #69)
This commit is contained in:
parent
4e8ac29cb0
commit
924815e629
|
@ -51,6 +51,7 @@ RUN sed -i -e 's/"main": ".*"/"main": ".\/dist\/index.js"/' packages/lib/package
|
|||
|
||||
# --- build main client ---
|
||||
|
||||
ARG VITE_INCLUDE_EVENT_INFO
|
||||
RUN npm -w packages/client run build
|
||||
|
||||
# --- build admin ---
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import React, { useEffect, useRef } from "react";
|
||||
import { useAppContext } from "../contexts/AppContext";
|
||||
import { Button } from "@nextui-org/react";
|
||||
|
||||
const EVENT_START = 1720756800000; // midnight 7/12/2024 eastern
|
||||
|
||||
/**
|
||||
* *oh god the terrible code*
|
||||
*
|
||||
* not sure of another clean way to do this
|
||||
*
|
||||
* This is used to show details about the event, immediately on page load
|
||||
*
|
||||
* used by the canvas preview page to get people hyped up for the event (<7 days before)
|
||||
*/
|
||||
export const EventInfoOverlay = ({ children }: React.PropsWithChildren) => {
|
||||
const { setInfoSidebar, setSettingsSidebar } = useAppContext();
|
||||
const $countdown = useRef<HTMLElement | null>(null);
|
||||
|
||||
const getCountdown = () => {
|
||||
// date math always confuses me...
|
||||
// https://stackoverflow.com/a/7709819
|
||||
|
||||
const now = Date.now();
|
||||
const ms = EVENT_START - now;
|
||||
const days = Math.floor(ms / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor((ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
const minutes = Math.floor(
|
||||
((ms % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) / (1000 * 60)
|
||||
);
|
||||
const seconds = Math.round(
|
||||
(((ms % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) % (1000 * 60)) / 1000
|
||||
);
|
||||
|
||||
return [days, hours, minutes, seconds];
|
||||
};
|
||||
|
||||
const updateTime = () => {
|
||||
if (!$countdown.current) return;
|
||||
|
||||
const [days, hours, minutes, seconds] = getCountdown();
|
||||
|
||||
$countdown.current.innerText = [
|
||||
days && days + "d",
|
||||
hours && hours + "h",
|
||||
minutes && minutes + "m",
|
||||
seconds && seconds + "s",
|
||||
]
|
||||
.filter((a) => a)
|
||||
.join(" ");
|
||||
|
||||
$countdown.current.title = `${days} days ${hours} hours ${minutes} minutes ${seconds} seconds`;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
var interval = setInterval(updateTime, 1000);
|
||||
updateTime();
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="bg-black text-white p-4 fixed top-0 left-0 w-full z-[9999] flex flex-row"
|
||||
style={{
|
||||
pointerEvents: "initial",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold">Canvas 2024</h1>
|
||||
<h2 ref={(r) => ($countdown.current = r)} className="text-3xl"></h2>
|
||||
</div>
|
||||
|
||||
<div className="flex-grow" />
|
||||
|
||||
<div>
|
||||
<Button onPress={() => setInfoSidebar(true)}>Info</Button>
|
||||
<Button onPress={() => setSettingsSidebar(true)}>Settings</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -4,6 +4,7 @@ import { User } from "./User";
|
|||
import { Debug } from "@sc07-canvas/lib/src/debug";
|
||||
import React, { lazy } from "react";
|
||||
import { AccountStanding } from "./AccountStanding";
|
||||
import { EventInfoOverlay } from "../EventInfoOverlay";
|
||||
|
||||
const OpenChatButton = lazy(() => import("../Chat/OpenChatButton"));
|
||||
|
||||
|
@ -18,6 +19,7 @@ export const Header = () => {
|
|||
|
||||
return (
|
||||
<header id="main-header">
|
||||
{import.meta.env.VITE_INCLUDE_EVENT_INFO && <EventInfoOverlay />}
|
||||
<HeaderLeft />
|
||||
<div className="spacer"></div>
|
||||
{!connected && (
|
||||
|
|
|
@ -45,12 +45,23 @@ export const InfoSidebar = () => {
|
|||
Discord
|
||||
</Button>
|
||||
</div>
|
||||
<Button as={Link} href="https://toast.ooo/c/canvas">
|
||||
<Button as={Link} href="https://toast.ooo/c/canvas" target="_blank">
|
||||
<div className="flex flex-col text-center">
|
||||
<span>Lemmy</span>
|
||||
<span className="text-xs">!canvas@toast.ooo</span>
|
||||
</div>
|
||||
</Button>
|
||||
<Button
|
||||
as={Link}
|
||||
href="https://social.fediverse.events/@canvas"
|
||||
target="_blank"
|
||||
>
|
||||
<div className="flex flex-col text-center">
|
||||
<span>Mastodon</span>
|
||||
<span className="text-xs">@canvas@fediverse.events</span>
|
||||
</div>
|
||||
</Button>
|
||||
<b>Build {__COMMIT_HASH__}</b>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -67,10 +67,16 @@ export const Palette = () => {
|
|||
|
||||
{!user && (
|
||||
<div className="pallete-user-overlay">
|
||||
You are not logged in
|
||||
<a href="/api/login" className="user-login">
|
||||
Login
|
||||
</a>
|
||||
{import.meta.env.VITE_INCLUDE_EVENT_INFO ? (
|
||||
<>The event hasn't started yet</>
|
||||
) : (
|
||||
<>
|
||||
You are not logged in
|
||||
<a href="/api/login" className="user-login">
|
||||
Login
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -4,12 +4,15 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>canvas</title>
|
||||
<title>Canvas</title>
|
||||
|
||||
<link rel="stylesheet" href="./style.scss" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Mastodon verification -->
|
||||
<a href="https://social.fediverse.events/@canvas" rel="me"></a>
|
||||
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="module" src="./index.tsx"></script>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_API_HOST: string;
|
||||
readonly VITE_MATRIX_HOST: string;
|
||||
readonly VITE_INCLUDE_EVENT_INFO: boolean;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
|
|
@ -31,6 +31,14 @@ const app = Router();
|
|||
* Redirect to actual authorization page
|
||||
*/
|
||||
app.get("/login", (req, res) => {
|
||||
if (process.env.INHIBIT_LOGINS) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: "Login is not permitted.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
res.redirect(
|
||||
OpenID.client.authorizationUrl({
|
||||
prompt: "consent",
|
||||
|
@ -57,6 +65,14 @@ app.post("/logout", (req, res) => {
|
|||
* This executes multiple database queries and should be ratelimited
|
||||
*/
|
||||
app.get("/callback", RateLimiter.HIGH, async (req, res) => {
|
||||
if (process.env.INHIBIT_LOGINS) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: "Login is not permitted.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let exchange: TokenSet;
|
||||
|
||||
try {
|
||||
|
|
|
@ -58,24 +58,26 @@ if (!process.env.REDIS_RATELIMIT_PREFIX) {
|
|||
);
|
||||
}
|
||||
|
||||
if (!process.env.AUTH_ENDPOINT) {
|
||||
Logger.error("AUTH_ENDPOINT is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.INHIBIT_LOGIN) {
|
||||
if (!process.env.AUTH_ENDPOINT) {
|
||||
Logger.error("AUTH_ENDPOINT is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.AUTH_CLIENT) {
|
||||
Logger.error("AUTH_CLIENT is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.AUTH_CLIENT) {
|
||||
Logger.error("AUTH_CLIENT is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.AUTH_SECRET) {
|
||||
Logger.error("AUTH_SECRET is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.AUTH_SECRET) {
|
||||
Logger.error("AUTH_SECRET is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.OIDC_CALLBACK_HOST) {
|
||||
Logger.error("OIDC_CALLBACK_HOST is not defined");
|
||||
process.exit(1);
|
||||
if (!process.env.OIDC_CALLBACK_HOST) {
|
||||
Logger.error("OIDC_CALLBACK_HOST is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// run startup tasks, all of these need to be completed to serve
|
||||
|
|
|
@ -5,6 +5,13 @@ class OpenID_ {
|
|||
client: BaseClient = {} as any;
|
||||
|
||||
async setup() {
|
||||
if (process.env.INHIBIT_LOGIN) {
|
||||
console.warn(
|
||||
"OpenID is not setup; INHIBIT_LOGIN environment variable set! Proceed with caution!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const { AUTH_ENDPOINT, AUTH_CLIENT, AUTH_SECRET } = process.env;
|
||||
|
||||
this.issuer = await Issuer.discover(AUTH_ENDPOINT);
|
||||
|
|
Loading…
Reference in New Issue