mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-24 20:16:41 -05:00
Rework flag
This commit is contained in:
@@ -48,6 +48,9 @@ SQL_LOG=none
|
||||
|
||||
VITE_SHOW_LUTI_NAV_ITEM=false
|
||||
|
||||
// If false the scanner page and its ingest endpoint are admin only
|
||||
VITE_SCANNER_ENABLED=false
|
||||
|
||||
// Push notification. Generate values here https://vapidkeys.com/
|
||||
VITE_VAPID_PUBLIC_KEY=
|
||||
VAPID_PRIVATE_KEY=
|
||||
|
||||
@@ -42,6 +42,7 @@ const values = {
|
||||
VITE_PROD_MODE: stringBool("VITE_PROD_MODE"),
|
||||
VITE_SHOW_LUTI_NAV_ITEM: stringBool("VITE_SHOW_LUTI_NAV_ITEM"),
|
||||
VITE_FUSE_ENABLED: stringBool("VITE_FUSE_ENABLED"),
|
||||
VITE_SCANNER_ENABLED: stringBool("VITE_SCANNER_ENABLED"),
|
||||
VITE_LEAGUE_GOOGLE_FORM_URL: env.VITE_LEAGUE_GOOGLE_FORM_URL,
|
||||
VITE_SHOW_BANNER_FOR_SEASON: env.VITE_SHOW_BANNER_FOR_SEASON,
|
||||
VITE_SENTRY_DSN: env.VITE_SENTRY_DSN,
|
||||
@@ -66,6 +67,8 @@ export const Config = {
|
||||
/** Whether to show the LUTI navigation item. */
|
||||
showLutiNavItem: values.VITE_SHOW_LUTI_NAV_ITEM,
|
||||
fuseEnabled: values.VITE_FUSE_ENABLED,
|
||||
/** Whether the scanner is available to everyone. While false only the admin can use the scanner page and its ingest endpoint. */
|
||||
scannerEnabled: values.VITE_SCANNER_ENABLED,
|
||||
/** Google Form URL for league registration, if configured. */
|
||||
leagueGoogleFormUrl: values.VITE_LEAGUE_GOOGLE_FORM_URL,
|
||||
/** Season identifier to show the registration banner for, if any. */
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { ActionFunction } from "react-router";
|
||||
import { Config } from "~/config";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import type { ScannerMatch } from "~/features/scanner/core/scanner-match";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { isAdmin } from "~/modules/permissions/utils";
|
||||
import { logger } from "~/utils/logger";
|
||||
import { badRequestIfFalsy, parseBody } from "~/utils/remix.server";
|
||||
import { badRequestIfFalsy, forbidden, parseBody } from "~/utils/remix.server";
|
||||
import * as Scoreboards from "../core/Scoreboards";
|
||||
import * as ScannerIngestRepository from "../ScannerIngestRepository.server";
|
||||
import { ingestBodySchema } from "../scanner-ingest-schemas";
|
||||
@@ -15,6 +17,10 @@ import { ingestBodySchema } from "../scanner-ingest-schemas";
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
const user = requireUser();
|
||||
|
||||
if (!Config.scannerEnabled && !isAdmin(user)) {
|
||||
forbidden();
|
||||
}
|
||||
|
||||
const data = await parseBody({ request, schema: ingestBodySchema });
|
||||
|
||||
const povUserId = data.povUserId ?? user?.id ?? null;
|
||||
|
||||
@@ -42,7 +42,6 @@ import { EventCard } from "./EventCard";
|
||||
import { EventsSummary } from "./EventsSummary";
|
||||
import { downloadEventsCsv } from "./events-csv";
|
||||
import { type FixtureData, saveFixture } from "./fixture-export";
|
||||
import { SENDOU_UPLOAD_ENABLED } from "./flags";
|
||||
import { MatchCard } from "./MatchCard";
|
||||
import { MatchLobbyTabs } from "./MatchLobbyTabs";
|
||||
import {
|
||||
@@ -293,25 +292,21 @@ export function LivePage({
|
||||
<div className="controls">
|
||||
{!running ? (
|
||||
<>
|
||||
{SENDOU_UPLOAD_ENABLED ? (
|
||||
<button
|
||||
type="button"
|
||||
disabled={!sendouUser}
|
||||
title={sendouUser ? undefined : "log in on sendou.ink first"}
|
||||
onClick={() => void start(true)}
|
||||
>
|
||||
<Send aria-hidden />
|
||||
Start capture
|
||||
</button>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
className={SENDOU_UPLOAD_ENABLED ? "outlined" : undefined}
|
||||
disabled={!sendouUser}
|
||||
title={sendouUser ? undefined : "log in on sendou.ink first"}
|
||||
onClick={() => void start(true)}
|
||||
>
|
||||
<Send aria-hidden />
|
||||
Start capture
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="outlined"
|
||||
onClick={() => void start(false)}
|
||||
>
|
||||
{SENDOU_UPLOAD_ENABLED
|
||||
? "Start capture (no sending)"
|
||||
: "Start capture"}
|
||||
Start capture (no sending)
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
@@ -319,21 +314,19 @@ export function LivePage({
|
||||
<button type="button" onClick={stop}>
|
||||
Stop
|
||||
</button>
|
||||
{SENDOU_UPLOAD_ENABLED ? (
|
||||
<button
|
||||
type="button"
|
||||
className="outlined"
|
||||
disabled={!sendouUser}
|
||||
title={sendouUser ? undefined : "log in on sendou.ink first"}
|
||||
onClick={() => {
|
||||
liveSendRef.current = !liveSend;
|
||||
setLiveSend(!liveSend);
|
||||
}}
|
||||
>
|
||||
<Send aria-hidden />
|
||||
{liveSend ? "Stop sending" : "Start sending"}
|
||||
</button>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
className="outlined"
|
||||
disabled={!sendouUser}
|
||||
title={sendouUser ? undefined : "log in on sendou.ink first"}
|
||||
onClick={() => {
|
||||
liveSendRef.current = !liveSend;
|
||||
setLiveSend(!liveSend);
|
||||
}}
|
||||
>
|
||||
<Send aria-hidden />
|
||||
{liveSend ? "Stop sending" : "Start sending"}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<select value={deviceId} onChange={(e) => setDeviceId(e.target.value)}>
|
||||
@@ -411,7 +404,7 @@ export function LivePage({
|
||||
justFormed={justFormed}
|
||||
send={aggregateSendStatus(built.sources)}
|
||||
onSend={
|
||||
SENDOU_UPLOAD_ENABLED && sendouUser && !skipReason
|
||||
sendouUser && !skipReason
|
||||
? () => void send(matchContaining(id), { manual: true })
|
||||
: undefined
|
||||
}
|
||||
@@ -466,7 +459,6 @@ export function LivePage({
|
||||
}
|
||||
send={e.send}
|
||||
onSend={
|
||||
SENDOU_UPLOAD_ENABLED &&
|
||||
sendouUser &&
|
||||
e.id !== undefined &&
|
||||
INGESTABLE_TYPES.includes(e.type)
|
||||
@@ -525,15 +517,13 @@ function LiveMenu({
|
||||
>
|
||||
CSV
|
||||
</SendouMenuItem>
|
||||
{SENDOU_UPLOAD_ENABLED ? (
|
||||
<SendouMenuItem
|
||||
icon={<Send />}
|
||||
isDisabled={!canSend}
|
||||
onAction={onSendUnsent}
|
||||
>
|
||||
Send unsent to sendou.ink
|
||||
</SendouMenuItem>
|
||||
) : null}
|
||||
<SendouMenuItem
|
||||
icon={<Send />}
|
||||
isDisabled={!canSend}
|
||||
onAction={onSendUnsent}
|
||||
>
|
||||
Send unsent to sendou.ink
|
||||
</SendouMenuItem>
|
||||
<SendouMenuItem
|
||||
icon={<Trash2 />}
|
||||
isDestructive
|
||||
|
||||
@@ -56,7 +56,6 @@ import { EventCard, type GetFrame } from "./EventCard";
|
||||
import { EventsSummary } from "./EventsSummary";
|
||||
import { downloadEventsCsv } from "./events-csv";
|
||||
import type { FixtureData } from "./fixture-export";
|
||||
import { SENDOU_UPLOAD_ENABLED } from "./flags";
|
||||
import { formatTime } from "./format";
|
||||
import { MatchCard } from "./MatchCard";
|
||||
import { MatchLobbyTabs } from "./MatchLobbyTabs";
|
||||
@@ -602,18 +601,18 @@ export function VodPage({
|
||||
` · ${progress.rate.toFixed(0)}× realtime`}
|
||||
</span>
|
||||
)}
|
||||
{SENDOU_UPLOAD_ENABLED && upload?.url && (
|
||||
{upload?.url && (
|
||||
<Link to={upload.url} className="link-button">
|
||||
<Video aria-hidden />
|
||||
Add VoD
|
||||
</Link>
|
||||
)}
|
||||
{SENDOU_UPLOAD_ENABLED && upload?.problem && (
|
||||
{upload?.problem && (
|
||||
<span className="score">
|
||||
upload unavailable: {upload.problem}
|
||||
</span>
|
||||
)}
|
||||
{SENDOU_UPLOAD_ENABLED && resultsMatchCount > 0 && (
|
||||
{resultsMatchCount > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
disabled={!sendouUser || resultsSend?.state === "sending"}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/**
|
||||
* WIP: sendou.ink uploading is not live yet — this hides every button that
|
||||
* sends data to sendou.ink (Live tab live send / send unsent / per-card Send,
|
||||
* VoD tab "Add VoD" and "Send results"). Flip to true to bring
|
||||
* them back.
|
||||
*/
|
||||
export const SENDOU_UPLOAD_ENABLED = true;
|
||||
@@ -2,7 +2,10 @@ import { lazy } from "react";
|
||||
import type { MetaFunction } from "react-router";
|
||||
import { Main } from "~/components/Main";
|
||||
import { Placeholder } from "~/components/Placeholder";
|
||||
import { Redirect } from "~/components/Redirect";
|
||||
import { Config } from "~/config";
|
||||
import { useHydrated } from "~/hooks/useHydrated";
|
||||
import { useHasRole } from "~/modules/permissions/hooks";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
|
||||
@@ -31,6 +34,11 @@ const ScannerApp = lazy(() =>
|
||||
|
||||
export default function ScannerPage() {
|
||||
const isHydrated = useHydrated();
|
||||
const isAdmin = useHasRole("ADMIN");
|
||||
|
||||
if (!Config.scannerEnabled && !isAdmin) {
|
||||
return <Redirect to="/" />;
|
||||
}
|
||||
|
||||
return <Main bigger>{isHydrated ? <ScannerApp /> : <Placeholder />}</Main>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user