mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 02:00:46 +00:00
redeem beta key and moderation page updates
init redeem beta key page redeem beta key page beta key redeem success page redeem beta key and moderation page updates redirects back to redeem page after login and signup removed unused
This commit is contained in:
1 parent
474934d2f0
commit
ef66b8ac3d
11 files changed
+413
-153
No files matched your search
@@ -18,5 +18,5 @@ export const CreateBetaKey = MakeRequest<
|
||||
{}
|
||||
>({
|
||||
method: "POST",
|
||||
routingFunction: () => "/v1/beta_keys/new",
|
||||
routingFunction: () => "/v1/beta_keys/create",
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import MakeRequest from "../MakeRequest";
|
||||
|
||||
export interface RedeemBetaKeyRequest {
|
||||
beta_key: string;
|
||||
}
|
||||
|
||||
export interface RedeemBetaKeyResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export const RedeemBetaKey = MakeRequest<
|
||||
string,
|
||||
RedeemBetaKeyRequest,
|
||||
RedeemBetaKeyResponse,
|
||||
{}
|
||||
>({
|
||||
method: "POST",
|
||||
routingFunction: () => "/v1/beta_keys/redeem",
|
||||
});
|
||||
@@ -31,7 +31,10 @@ import { useInferenceJobs, useLocalize } from "hooks";
|
||||
import { Logout } from "@storyteller/components/src/api/session/Logout";
|
||||
import { Button } from "components/common";
|
||||
import { WebUrl } from "common/WebUrl";
|
||||
import { WebsiteConfig, Website } from "@storyteller/components/src/env/GetWebsite";
|
||||
import {
|
||||
WebsiteConfig,
|
||||
Website,
|
||||
} from "@storyteller/components/src/env/GetWebsite";
|
||||
import { useDomainConfig } from "context/DomainConfigContext";
|
||||
|
||||
interface SideNavProps {
|
||||
@@ -59,6 +62,8 @@ export default function SideNav({
|
||||
const isOnLoginPage = window.location.pathname.includes("/login");
|
||||
const isOnSignUpPage = window.location.pathname.includes("/signup");
|
||||
const isOnStudioPage = window.location.pathname.includes("/studio");
|
||||
const isOnBetaKeyRedeemPage =
|
||||
window.location.pathname.includes("/beta-key/redeem");
|
||||
const domain: WebsiteConfig = useDomainConfig();
|
||||
|
||||
let history = useHistory();
|
||||
@@ -112,7 +117,8 @@ export default function SideNav({
|
||||
const shouldNotShowSidebar =
|
||||
(!isLoggedIn && (isOnLandingPage || isOnLoginPage || isOnSignUpPage)) ||
|
||||
isOnStudioPage ||
|
||||
(domain.website === Website.StorytellerAi && isOnLandingPage);
|
||||
(domain.website === Website.StorytellerAi && isOnLandingPage) ||
|
||||
isOnBetaKeyRedeemPage;
|
||||
const shouldShowSidebar = windowWidth >= 992 && !shouldNotShowSidebar;
|
||||
const sidebarClassName = `sidebar ${
|
||||
shouldShowSidebar ? "visible" : ""
|
||||
@@ -277,36 +283,35 @@ export default function SideNav({
|
||||
{t("videoWorkflow")}
|
||||
</NavLink>
|
||||
</li>
|
||||
{
|
||||
// <li>
|
||||
// <NavLink
|
||||
// to="/studio"
|
||||
// activeClassName="active-link"
|
||||
// onClick={handleNavLinkClick}
|
||||
// >
|
||||
// <FontAwesomeIcon
|
||||
// icon={faCameraMovie}
|
||||
// className="sidebar-heading-icon"
|
||||
// />
|
||||
// Storyteller Studio
|
||||
// {/* {t("videoStorytellerStudio")} */}
|
||||
// </NavLink>
|
||||
// </li>
|
||||
|
||||
// <li>
|
||||
// <NavLink
|
||||
// to="/engine-compositor"
|
||||
// activeClassName="active-link"
|
||||
// onClick={handleNavLinkClick}
|
||||
// >
|
||||
// <FontAwesomeIcon
|
||||
// icon={faTransporter}
|
||||
// className="sidebar-heading-icon"
|
||||
// />
|
||||
// Engine Compositor
|
||||
// {/* {t("videoStorytellerStudio")} */}
|
||||
// </NavLink>
|
||||
// </li>
|
||||
{
|
||||
// <li>
|
||||
// <NavLink
|
||||
// to="/studio"
|
||||
// activeClassName="active-link"
|
||||
// onClick={handleNavLinkClick}
|
||||
// >
|
||||
// <FontAwesomeIcon
|
||||
// icon={faCameraMovie}
|
||||
// className="sidebar-heading-icon"
|
||||
// />
|
||||
// Storyteller Studio
|
||||
// {/* {t("videoStorytellerStudio")} */}
|
||||
// </NavLink>
|
||||
// </li>
|
||||
// <li>
|
||||
// <NavLink
|
||||
// to="/engine-compositor"
|
||||
// activeClassName="active-link"
|
||||
// onClick={handleNavLinkClick}
|
||||
// >
|
||||
// <FontAwesomeIcon
|
||||
// icon={faTransporter}
|
||||
// className="sidebar-heading-icon"
|
||||
// />
|
||||
// Engine Compositor
|
||||
// {/* {t("videoStorytellerStudio")} */}
|
||||
// </NavLink>
|
||||
// </li>
|
||||
}
|
||||
</>
|
||||
);
|
||||
@@ -479,11 +484,7 @@ export default function SideNav({
|
||||
</NavLink>
|
||||
</li>
|
||||
<li className="mb-3">
|
||||
<a
|
||||
href={GetDiscordLink()}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<a href={GetDiscordLink()} target="_blank" rel="noreferrer">
|
||||
<FontAwesomeIcon
|
||||
icon={faDiscord}
|
||||
className="sidebar-heading-icon"
|
||||
|
||||
@@ -48,6 +48,8 @@ export default function TopNav({
|
||||
const isOnLoginPage = window.location.pathname.includes("/login");
|
||||
const isOnSignUpPage = window.location.pathname.includes("/signup");
|
||||
const isOnStudioPage = window.location.pathname.includes("/studio");
|
||||
const isOnBetaKeyRedeemPage =
|
||||
window.location.pathname.includes("/beta-key/redeem");
|
||||
|
||||
const { open } = useModal();
|
||||
const openModal = () => open({ component: InferenceJobsModal });
|
||||
@@ -192,15 +194,21 @@ export default function TopNav({
|
||||
const pageContentWrapper = document.getElementById("page-content-wrapper");
|
||||
|
||||
if (pageContentWrapper) {
|
||||
if (domain.titlePart === "Storyteller AI" && isOnLandingPage) {
|
||||
if (
|
||||
(domain.titlePart === "Storyteller AI" && isOnLandingPage) ||
|
||||
isOnBetaKeyRedeemPage
|
||||
) {
|
||||
pageContentWrapper.style.padding = "0px";
|
||||
} else {
|
||||
pageContentWrapper.style.padding = "";
|
||||
}
|
||||
}
|
||||
}, [domain.titlePart, isOnLandingPage]);
|
||||
}, [domain.titlePart, isOnLandingPage, isOnBetaKeyRedeemPage]);
|
||||
|
||||
if (domain.titlePart === "Storyteller AI" && isOnLandingPage) {
|
||||
if (
|
||||
(domain.titlePart === "Storyteller AI" && isOnLandingPage) ||
|
||||
isOnBetaKeyRedeemPage
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,8 @@ import DevUploadAlt from "./pages/dev_upload/DevUploadAlt";
|
||||
import { ModerationTokenInfoPage } from "./pages/moderation/ModerationTokenInfoPage";
|
||||
import StyleVideo from "./pages/style-video";
|
||||
import CreateBetaKeyPage from "./pages/beta_key/CreateBetaKeyPage";
|
||||
import RedeemBetaKeyPage from "./pages/beta_key/RedeemBetaKeyPage";
|
||||
import RedeemSuccessPage from "./pages/beta_key/RedeemSuccessPage";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -1129,6 +1131,14 @@ class PageContainer extends React.Component<
|
||||
<CreateBetaKeyPage />
|
||||
</Route>
|
||||
|
||||
<Route path="/beta-key/redeem/success">
|
||||
<RedeemSuccessPage />
|
||||
</Route>
|
||||
|
||||
<Route path="/beta-key/redeem">
|
||||
<RedeemBetaKeyPage />
|
||||
</Route>
|
||||
|
||||
{/*
|
||||
// <Route path="/engine-compositor">
|
||||
// <EngineCompositor
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
@import "scss/colours.scss";
|
||||
|
||||
.redeem-container {
|
||||
max-width: 600px !important;
|
||||
}
|
||||
|
||||
.redeem-button {
|
||||
font-size: 20px !important;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
background-color: $primary;
|
||||
border-radius: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
padding: 14px;
|
||||
width: 300px;
|
||||
border: 4px solid lighten($primary, 12%);
|
||||
|
||||
&:hover {
|
||||
background-color: lighten($primary, 5%);
|
||||
color: #fff;
|
||||
border: 4px solid lighten($primary, 12%);
|
||||
}
|
||||
&:active,
|
||||
&:focus {
|
||||
border: 4px solid lighten($primary, 12%);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import { Button, Container, Label, Panel, TempInput } from "components/common";
|
||||
import React, { useState } from "react";
|
||||
import "./BetaKey.scss";
|
||||
import { faKey } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { RedeemBetaKey } from "@storyteller/components/src/api/beta_key/RedeemBetaKey";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useSession } from "hooks";
|
||||
|
||||
export default function RedeemBetaKeyPage() {
|
||||
const [key, setKey] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const history = useHistory();
|
||||
const { loggedIn } = useSession();
|
||||
|
||||
const handleGoToSuccess = () => {
|
||||
history.push("/beta-key/redeem/success");
|
||||
};
|
||||
|
||||
const handleRedeemBetaKey = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const response = await RedeemBetaKey("", {
|
||||
beta_key: key,
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
handleGoToSuccess();
|
||||
} else {
|
||||
console.log("Failed to redeem beta key.");
|
||||
setShowAlert(true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to redeem beta key.", error);
|
||||
setShowAlert(true);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!loggedIn) {
|
||||
return (
|
||||
<Container type="panel" className="narrow-container">
|
||||
<div className="d-flex flex-column align-items-center justify-content-center vh-100 gap-4">
|
||||
<img
|
||||
src="/fakeyou/Storyteller-Logo-1.png"
|
||||
alt="Storyteller Logo"
|
||||
style={{ maxWidth: "280px" }}
|
||||
/>
|
||||
<Panel padding={true}>
|
||||
<div className="d-flex flex-column align-items-center py-4">
|
||||
<h4 className="fw-bold mb-1 text-center">
|
||||
You need an account to redeem a beta key.
|
||||
</h4>
|
||||
<p className="opacity-75 text-center">
|
||||
Please login or create an account to proceed with redeeming a
|
||||
beta key.
|
||||
</p>
|
||||
<div className="d-flex gap-2 mt-2">
|
||||
<Button
|
||||
label="Sign Up"
|
||||
className="mt-3"
|
||||
to="/signup?redirect=/beta-key/redeem/"
|
||||
variant="secondary"
|
||||
/>
|
||||
<Button
|
||||
label="Login"
|
||||
className="mt-3"
|
||||
to="/login?redirect=/beta-key/redeem/"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container type="panel" className="redeem-container">
|
||||
<div className="d-flex flex-column align-items-center justify-content-center vh-100 gap-4">
|
||||
<div className="px-4 d-flex flex-column align-items-center">
|
||||
<img
|
||||
src="/fakeyou/Storyteller-Logo-1.png"
|
||||
alt="Storyteller Logo"
|
||||
className="mb-5 pb-3 pb-lg-5"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
<h4 className="fw-bold mb-1 text-center">
|
||||
<FontAwesomeIcon icon={faKey} className="me-2 fs-5" />
|
||||
Redeem Studio Beta Key
|
||||
</h4>
|
||||
<p className="opacity-75 text-center">
|
||||
Enter your beta key to get access to Storyteller Studio Beta.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Panel padding={true}>
|
||||
<div className="w-100 d-flex justify-content-center fs-5">
|
||||
<Label label="Enter your key:" />
|
||||
</div>
|
||||
|
||||
<TempInput
|
||||
placeholder="Enter your beta key here..."
|
||||
value={key}
|
||||
onChange={e => {
|
||||
setKey(e.target.value);
|
||||
setShowAlert(false);
|
||||
}}
|
||||
required={true}
|
||||
className="text-center w-100 fs-5"
|
||||
/>
|
||||
|
||||
{showAlert && (
|
||||
<p className="text-center text-red">
|
||||
Invalid beta key! Please try again.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
<Button
|
||||
label="Redeem Beta Key"
|
||||
className="redeem-button mt-3"
|
||||
onClick={handleRedeemBetaKey}
|
||||
isLoading={loading}
|
||||
disabled={key.length === 0}
|
||||
/>
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Button, Container } from "components/common";
|
||||
import React from "react";
|
||||
import "./BetaKey.scss";
|
||||
|
||||
export default function RedeemSuccessPage() {
|
||||
const handleEnterStudio = () => {
|
||||
window.location.href = "https://studio.storyteller.ai";
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container type="panel" className="redeem-container">
|
||||
<div className="d-flex flex-column align-items-center justify-content-center vh-100">
|
||||
<div className="px-4 d-flex flex-column align-items-center">
|
||||
<img
|
||||
src="/mascot/kitsune_pose7.webp"
|
||||
alt="Success Mascot"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
<h2 className="fw-bold mb-1">Redemption Success</h2>
|
||||
<p className="opacity-75 text-center fs-5">
|
||||
You now have access to Storyteller Studio Beta!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
<Button
|
||||
label="Enter Studio"
|
||||
className="redeem-button mt-4"
|
||||
onClick={handleEnterStudio}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
import { Link, useHistory } from "react-router-dom";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import {
|
||||
CreateSession,
|
||||
CreateSessionIsError,
|
||||
@@ -29,6 +29,9 @@ function LoginPage(props: Props) {
|
||||
const [password, setPassword] = useState("");
|
||||
const [usernameOrEmail, setUsernameOrEmail] = useState("");
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
let location = useLocation();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const redirectUrl = queryParams.get("redirect") || "/";
|
||||
|
||||
if (props.sessionWrapper.isLoggedIn()) {
|
||||
history.push("/");
|
||||
@@ -72,7 +75,7 @@ function LoginPage(props: Props) {
|
||||
props.querySessionAction();
|
||||
props.querySessionSubscriptionsAction();
|
||||
Analytics.accountLoginSuccess();
|
||||
history.push("/");
|
||||
history.push(redirectUrl);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
+117
-108
@@ -11,7 +11,15 @@ import {
|
||||
faTags,
|
||||
faUsers,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faMagnifyingGlass, faUserAlt } from "@fortawesome/pro-solid-svg-icons";
|
||||
import {
|
||||
faGift,
|
||||
faKey,
|
||||
faList,
|
||||
faMagnifyingGlass,
|
||||
faUserAlt,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { Button, Container, Panel } from "components/common";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -23,124 +31,125 @@ function ModerationPage(props: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="container py-5">
|
||||
<h1 className=" fw-bold text-center text-lg-start">
|
||||
Moderation Controls
|
||||
</h1>
|
||||
</div>
|
||||
<Container type="panel" className="narrow-container">
|
||||
<PageHeader title="Moderation Controls" />
|
||||
|
||||
<div className="container-panel pt-3 pb-5">
|
||||
<div className="panel p-3 p-lg-4">
|
||||
<h2 className="panel-title fw-bold">Lookup, Stats, and Editing</h2>
|
||||
<div className="py-6">
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Link
|
||||
to="/moderation/token_info"
|
||||
className="btn btn-success w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faMagnifyingGlass} className="me-2" />
|
||||
Token Info Lookup
|
||||
</Link>
|
||||
</div>
|
||||
<div className="d-flex flex-column gap-4">
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-bold mb-3">Lookup, Stats, and Editing</h4>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Link to="/moderation/token_info" className="btn btn-success w-100">
|
||||
<FontAwesomeIcon icon={faMagnifyingGlass} className="me-2" />
|
||||
Token Info Lookup
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<div className="container-panel pt-3 pb-5">
|
||||
<div className="panel p-3 p-lg-4">
|
||||
<h2 className="panel-title fw-bold">Users</h2>
|
||||
<div className="py-6">
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Link to="/moderation/ip_bans" className="btn btn-secondary w-100">
|
||||
<FontAwesomeIcon icon={faBan} className="me-2" />
|
||||
IP Bans
|
||||
</Link>
|
||||
<Link to="/moderation/user_feature_flags" className="btn btn-secondary w-100">
|
||||
<FontAwesomeIcon icon={faUserAlt} className="me-2" />
|
||||
User Feature Flags
|
||||
</Link>
|
||||
</div>
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-bold mb-3">Studio Beta Keys</h4>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Button
|
||||
to="/beta-key/create"
|
||||
label="Create Beta Keys"
|
||||
icon={faKey}
|
||||
/>
|
||||
<Button
|
||||
icon={faGift}
|
||||
to="/beta-key/redeem"
|
||||
label="Redeem Beta Key Page"
|
||||
variant="secondary"
|
||||
/>
|
||||
<Button
|
||||
icon={faList}
|
||||
label="List of Beta Keys Page"
|
||||
disabled={true}
|
||||
variant="secondary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<div className="container-panel pt-3 pb-5">
|
||||
<div className="panel p-3 p-lg-4">
|
||||
<h2 className="panel-title fw-bold">Emergency</h2>
|
||||
<div className="py-6">
|
||||
<div className="d-flex flex-column gap-3">
|
||||
|
||||
<Link
|
||||
to="/moderation/job_control"
|
||||
className="btn btn-primary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faListCheck} className="me-2" />
|
||||
Job Control
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-bold mb-3">Users</h4>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Link to="/moderation/ip_bans" className="btn btn-secondary w-100">
|
||||
<FontAwesomeIcon icon={faBan} className="me-2" />
|
||||
IP Bans
|
||||
</Link>
|
||||
<Link
|
||||
to="/moderation/user_feature_flags"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faUserAlt} className="me-2" />
|
||||
User Feature Flags
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<div className="container-panel pt-3 pb-5">
|
||||
<div className="panel p-3 p-lg-4">
|
||||
<h2 className="panel-title fw-bold">Legacy and Deprecated Pages</h2>
|
||||
<div className="py-6">
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-bold mb-3">Emergency</h4>
|
||||
|
||||
<Link
|
||||
to="/moderation/job_stats"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faListCheck} className="me-2" />
|
||||
Job Stats (Old TTS + W2L)
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/moderation/user/list"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faUsers} className="me-2" />
|
||||
User List
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to={WebUrl.moderationTtsCategoryList()}
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTags} className="me-2" />
|
||||
Manage TTS Categories
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/moderation/approve/w2l_templates"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faClipboardCheck} className="me-2" />
|
||||
Unapproved W2L Templates
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/moderation/voice_stats"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faMicrophone} className="me-2" />
|
||||
Voice Stats
|
||||
</Link>
|
||||
</div>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Link
|
||||
to="/moderation/job_control"
|
||||
className="btn btn-primary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faListCheck} className="me-2" />
|
||||
Job Control
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-bold mb-3">Legacy and Deprecated Pages</h4>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Link
|
||||
to="/moderation/job_stats"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faListCheck} className="me-2" />
|
||||
Job Stats (Old TTS + W2L)
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/moderation/user/list"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faUsers} className="me-2" />
|
||||
User List
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to={WebUrl.moderationTtsCategoryList()}
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTags} className="me-2" />
|
||||
Manage TTS Categories
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/moderation/approve/w2l_templates"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faClipboardCheck} className="me-2" />
|
||||
Unapproved W2L Templates
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/moderation/voice_stats"
|
||||
className="btn btn-secondary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faMicrophone} className="me-2" />
|
||||
Voice Stats
|
||||
</Link>
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
|
||||
<div className="container pb-5">
|
||||
<p>
|
||||
More mod controls will be added in the future: user roles, activity
|
||||
tracking, timed bans, account bans, etc.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-5 opacity-75">
|
||||
More mod controls will be added in the future: user roles, activity
|
||||
tracking, timed bans, account bans, etc.
|
||||
</p>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "@storyteller/components/src/api/user/CreateAccount";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faUser, faEnvelope, faKey } from "@fortawesome/free-solid-svg-icons";
|
||||
import { Link, useHistory } from "react-router-dom";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
|
||||
import { Analytics } from "../../../../common/Analytics";
|
||||
@@ -35,6 +35,8 @@ interface Props {
|
||||
function SignupPage(props: Props) {
|
||||
let history = useHistory();
|
||||
const domain = useDomainConfig();
|
||||
let location = useLocation();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
|
||||
const parsedQueryString = queryString.parse(window.location.search);
|
||||
|
||||
@@ -264,7 +266,9 @@ function SignupPage(props: Props) {
|
||||
return await BeginStripeCheckoutFlow(maybeInternalPlanKey);
|
||||
}
|
||||
|
||||
let redirectUrl = WebUrl.pricingPageWithReferer("signup");
|
||||
const redirectLink = queryParams.get("redirect");
|
||||
|
||||
let redirectUrl = redirectLink || WebUrl.pricingPageWithReferer("signup");
|
||||
history.push(redirectUrl);
|
||||
|
||||
return true;
|
||||
|
||||
Reference in new issue
Block a user