diff --git a/packages/components/src/api/beta_key/CreateBetaKey.ts b/packages/components/src/api/beta_key/CreateBetaKey.ts index 6a7e8ff02f..7657058333 100644 --- a/packages/components/src/api/beta_key/CreateBetaKey.ts +++ b/packages/components/src/api/beta_key/CreateBetaKey.ts @@ -18,5 +18,5 @@ export const CreateBetaKey = MakeRequest< {} >({ method: "POST", - routingFunction: () => "/v1/beta_keys/new", + routingFunction: () => "/v1/beta_keys/create", }); diff --git a/packages/components/src/api/beta_key/RedeemBetaKey.ts b/packages/components/src/api/beta_key/RedeemBetaKey.ts new file mode 100644 index 0000000000..ba173993e4 --- /dev/null +++ b/packages/components/src/api/beta_key/RedeemBetaKey.ts @@ -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", +}); diff --git a/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx b/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx index ecd33c04d0..e4fbb727b9 100644 --- a/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx +++ b/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx @@ -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")} -{ - //
  • - // - // - // Storyteller Studio - // {/* {t("videoStorytellerStudio")} */} - // - //
  • - - //
  • - // - // - // Engine Compositor - // {/* {t("videoStorytellerStudio")} */} - // - //
  • + { + //
  • + // + // + // Storyteller Studio + // {/* {t("videoStorytellerStudio")} */} + // + //
  • + //
  • + // + // + // Engine Compositor + // {/* {t("videoStorytellerStudio")} */} + // + //
  • } ); @@ -479,11 +484,7 @@ export default function SideNav({
  • - + 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; } diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 04e89c44ab..e9429581d3 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -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< + + + + + + + + {/* // // { + 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 ( + +
    + Storyteller Logo + +
    +

    + You need an account to redeem a beta key. +

    +

    + Please login or create an account to proceed with redeeming a + beta key. +

    +
    +
    +
    +
    +
    +
    + ); + } + + return ( + <> + +
    +
    + Storyteller Logo +
    +

    + + Redeem Studio Beta Key +

    +

    + Enter your beta key to get access to Storyteller Studio Beta. +

    +
    +
    + + +
    +
    + + { + setKey(e.target.value); + setShowAlert(false); + }} + required={true} + className="text-center w-100 fs-5" + /> + + {showAlert && ( +

    + Invalid beta key! Please try again. +

    + )} + +
    +
    +
    +
    +
    + + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/beta_key/RedeemSuccessPage.tsx b/packages/fakeyou.com/src/v2/view/pages/beta_key/RedeemSuccessPage.tsx new file mode 100644 index 0000000000..e1507863e1 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/beta_key/RedeemSuccessPage.tsx @@ -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 ( + <> + +
    +
    + Success Mascot +
    +

    Redemption Success

    +

    + You now have access to Storyteller Studio Beta! +

    +
    +
    + +
    +
    +
    +
    + + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/login/LoginPage.tsx b/packages/fakeyou.com/src/v2/view/pages/login/LoginPage.tsx index 38d82d53ac..5e8ed0f0fa 100644 --- a/packages/fakeyou.com/src/v2/view/pages/login/LoginPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/login/LoginPage.tsx @@ -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; diff --git a/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationPage.tsx b/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationPage.tsx index 6b6a65d476..451e1e1b3d 100644 --- a/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationPage.tsx @@ -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 ( -
    -
    -

    - Moderation Controls -

    -
    + + -
    -
    -

    Lookup, Stats, and Editing

    -
    -
    - - - Token Info Lookup - -
    +
    + +

    Lookup, Stats, and Editing

    +
    + + + Token Info Lookup +
    -
    -
    + -
    -
    -

    Users

    -
    -
    - - - IP Bans - - - - User Feature Flags - -
    + +

    Studio Beta Keys

    +
    +
    -
    -
    + -
    -
    -

    Emergency

    -
    -
    - - - - Job Control - - -
    + +

    Users

    +
    + + + IP Bans + + + + User Feature Flags +
    -
    -
    + -
    -
    -

    Legacy and Deprecated Pages

    -
    -
    + +

    Emergency

    - - - Job Stats (Old TTS + W2L) - - - - - User List - - - - - Manage TTS Categories - - - - - Unapproved W2L Templates - - - - - Voice Stats - -
    +
    + + + Job Control +
    -
    + + + +

    Legacy and Deprecated Pages

    +
    + + + Job Stats (Old TTS + W2L) + + + + + User List + + + + + Manage TTS Categories + + + + + Unapproved W2L Templates + + + + + Voice Stats + +
    +
    -
    -

    - More mod controls will be added in the future: user roles, activity - tracking, timed bans, account bans, etc. -

    -
    -
    +

    + More mod controls will be added in the future: user roles, activity + tracking, timed bans, account bans, etc. +

    + ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/signup/SignupPage.tsx b/packages/fakeyou.com/src/v2/view/pages/signup/SignupPage.tsx index 25553f96e7..daba2b2aaa 100644 --- a/packages/fakeyou.com/src/v2/view/pages/signup/SignupPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/signup/SignupPage.tsx @@ -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;