From 7f99096ff05d70965aa0b86aeeb3226d6861cd4d Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 18 Apr 2025 19:45:13 -0400 Subject: [PATCH] Remove remix client/server. Static page builds. Bugs: - no in-page navigation to login, signup, etc. - css bugs on login/logout --- .../reusable/ButtonLink/ButtonLink.tsx | 2 +- .../app/components/reusable/Typography.tsx | 2 +- .../signaled/TopBar/AuthButtons.tsx | 11 +- .../app/components/signaled/TopBar/TopBar.tsx | 2 +- .../editor3d/app/hoc/withProtectedRoute.tsx | 2 +- frontend/apps/editor3d/app/index.tsx | 121 +++ frontend/apps/editor3d/app/login.tsx | 185 ++++ .../apps/editor3d/app/pages/Page404/index.tsx | 2 +- .../PageEnigma/GlobalSettingsManager.tsx | 57 + .../ControlsTopButtons/ControlsTopButtons.tsx | 2 +- .../comps/Timeline/PremiumLockTimeline.tsx | 2 +- .../apps/editor3d/app/routes/$sceneToken.tsx | 2 +- frontend/apps/editor3d/app/routes/Login.tsx | 7 +- frontend/apps/editor3d/app/routes/Signup.tsx | 2 +- .../app/signals/authentication/fetchers.ts | 2 + frontend/apps/editor3d/app/signup.tsx | 185 ++++ frontend/apps/editor3d/app/utilities.ts | 2 +- frontend/apps/editor3d/index.html | 16 + frontend/apps/editor3d/login.html | 16 + frontend/apps/editor3d/package.json | 9 +- frontend/apps/editor3d/remix.config.ts | 7 - .../apps/editor3d/script/netlify_build.sh | 12 +- frontend/apps/editor3d/signup.html | 16 + frontend/apps/editor3d/tsconfig.json | 3 - frontend/apps/editor3d/vite.config.ts | 13 +- frontend/apps/my-app/index.html | 16 + frontend/apps/my-app/package.json | 5 + frontend/apps/my-app/public/favicon.ico | Bin 0 -> 15086 bytes frontend/apps/my-app/src/app/app.module.css | 1 + frontend/apps/my-app/src/app/app.spec.tsx | 16 + frontend/apps/my-app/src/app/app.tsx | 45 + frontend/apps/my-app/src/app/nx-welcome.tsx | 857 +++++++++++++++ frontend/apps/my-app/src/assets/.gitkeep | 0 frontend/apps/my-app/src/main.tsx | 16 + frontend/apps/my-app/src/styles.css | 1 + frontend/apps/my-app/tsconfig.app.json | 40 + frontend/apps/my-app/tsconfig.json | 13 + frontend/apps/my-app/tsconfig.spec.json | 36 + frontend/apps/my-app/vite.config.ts | 40 + frontend/package-lock.json | 994 +++++++++++++++++- frontend/package.json | 4 +- frontend/tsconfig.json | 3 + 42 files changed, 2681 insertions(+), 86 deletions(-) create mode 100644 frontend/apps/editor3d/app/index.tsx create mode 100644 frontend/apps/editor3d/app/login.tsx create mode 100644 frontend/apps/editor3d/app/pages/PageEnigma/GlobalSettingsManager.tsx create mode 100644 frontend/apps/editor3d/app/signup.tsx create mode 100644 frontend/apps/editor3d/index.html create mode 100644 frontend/apps/editor3d/login.html delete mode 100644 frontend/apps/editor3d/remix.config.ts create mode 100644 frontend/apps/editor3d/signup.html create mode 100644 frontend/apps/my-app/index.html create mode 100644 frontend/apps/my-app/package.json create mode 100644 frontend/apps/my-app/public/favicon.ico create mode 100644 frontend/apps/my-app/src/app/app.module.css create mode 100644 frontend/apps/my-app/src/app/app.spec.tsx create mode 100644 frontend/apps/my-app/src/app/app.tsx create mode 100644 frontend/apps/my-app/src/app/nx-welcome.tsx create mode 100644 frontend/apps/my-app/src/assets/.gitkeep create mode 100644 frontend/apps/my-app/src/main.tsx create mode 100644 frontend/apps/my-app/src/styles.css create mode 100644 frontend/apps/my-app/tsconfig.app.json create mode 100644 frontend/apps/my-app/tsconfig.json create mode 100644 frontend/apps/my-app/tsconfig.spec.json create mode 100644 frontend/apps/my-app/vite.config.ts diff --git a/frontend/apps/editor3d/app/components/reusable/ButtonLink/ButtonLink.tsx b/frontend/apps/editor3d/app/components/reusable/ButtonLink/ButtonLink.tsx index 5d96f64879..ad7ec70a1b 100644 --- a/frontend/apps/editor3d/app/components/reusable/ButtonLink/ButtonLink.tsx +++ b/frontend/apps/editor3d/app/components/reusable/ButtonLink/ButtonLink.tsx @@ -1,4 +1,4 @@ -import { Link, LinkProps } from "@remix-run/react"; +import { Link, LinkProps } from "react-router-dom"; import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { twMerge } from "tailwind-merge"; diff --git a/frontend/apps/editor3d/app/components/reusable/Typography.tsx b/frontend/apps/editor3d/app/components/reusable/Typography.tsx index b6a0df40ec..ed5d9a2cbd 100644 --- a/frontend/apps/editor3d/app/components/reusable/Typography.tsx +++ b/frontend/apps/editor3d/app/components/reusable/Typography.tsx @@ -1,4 +1,4 @@ -import { NavLink, NavLinkProps } from "@remix-run/react"; +import { NavLink, NavLinkProps } from "react-router-dom"; import { LabelHTMLAttributes, ReactNode } from "react"; import { twMerge } from "tailwind-merge"; diff --git a/frontend/apps/editor3d/app/components/signaled/TopBar/AuthButtons.tsx b/frontend/apps/editor3d/app/components/signaled/TopBar/AuthButtons.tsx index 3af31d4e03..473cb21fe9 100644 --- a/frontend/apps/editor3d/app/components/signaled/TopBar/AuthButtons.tsx +++ b/frontend/apps/editor3d/app/components/signaled/TopBar/AuthButtons.tsx @@ -16,10 +16,17 @@ export const AuthButtons = () => { } else { return ( <> - + Login - Sign Up + Sign Up ); } diff --git a/frontend/apps/editor3d/app/components/signaled/TopBar/TopBar.tsx b/frontend/apps/editor3d/app/components/signaled/TopBar/TopBar.tsx index 8ae1bdba41..c7b551c669 100644 --- a/frontend/apps/editor3d/app/components/signaled/TopBar/TopBar.tsx +++ b/frontend/apps/editor3d/app/components/signaled/TopBar/TopBar.tsx @@ -1,9 +1,9 @@ -import { useLocation, useParams } from "@remix-run/react"; import { faChevronLeft, faChevronRight, faImages, } from "@fortawesome/pro-solid-svg-icons"; +import { useLocation, useParams } from "react-router-dom"; import { Button, ButtonLink } from "~/components"; import { AuthButtons } from "./AuthButtons"; import { SceneTitleInput } from "./SceneTitleInput"; diff --git a/frontend/apps/editor3d/app/hoc/withProtectedRoute.tsx b/frontend/apps/editor3d/app/hoc/withProtectedRoute.tsx index 5e19b9bbcb..68db6e20bb 100644 --- a/frontend/apps/editor3d/app/hoc/withProtectedRoute.tsx +++ b/frontend/apps/editor3d/app/hoc/withProtectedRoute.tsx @@ -1,5 +1,5 @@ import { ComponentType, useEffect, useRef } from "react"; -import { useNavigate, useLocation } from "@remix-run/react"; +import { useNavigate, useLocation } from "react-router-dom"; import { useSignals, useSignalEffect } from "@preact/signals-react/runtime"; import { LoadingDots } from "~/components"; import { authentication, persistLogin } from "~/signals"; diff --git a/frontend/apps/editor3d/app/index.tsx b/frontend/apps/editor3d/app/index.tsx new file mode 100644 index 0000000000..9486c44927 --- /dev/null +++ b/frontend/apps/editor3d/app/index.tsx @@ -0,0 +1,121 @@ +import { StrictMode } from 'react'; +import { useSignals, useSignalEffect } from "@preact/signals-react/runtime"; +import { useEffect } from "react"; +import { BrowserRouter } from 'react-router-dom'; +import * as ReactDOM from 'react-dom/client'; +import { authentication, persistLogin } from "~/signals"; +import { PageEnigma } from './pages/PageEnigma/PageEnigma'; +import { createRoot } from "react-dom/client"; +//import App from './app/app'; +//import { App } from './root'; + +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, + useLoaderData, +} from "@remix-run/react"; + +import "./styles/normalize.css"; +import "./styles/tailwind.css"; +import "./styles/base.css"; +import "@fortawesome/fontawesome-svg-core/styles.css"; + +import { config } from "@fortawesome/fontawesome-svg-core"; + +import EnvironmentVariables from "~/Classes/EnvironmentVariables"; +import { pageHeight, pageWidth } from "~/signals"; + +import { showWizard } from "~/pages/PageEnigma/Wizard/signals/wizard"; +import { BuildEnvironmentType, GetBuildEnvironment } from "./BuildEnvironment"; + +config.autoAddCss = false; /* eslint-disable import/first */ + +//const root = ReactDOM.createRoot( +// document.getElementById('root') as HTMLElement +//); +// +//root.render( +// +// +// +// +// +//); + +//createRoot(document.getElementById("root")!).render(); + +// TODO(bt,2025-04-19): Make these configurable +const ENV = { + BASE_API: "https://api.storyteller.ai", + GOOGLE_API: "https://studio.storyteller.ai", + FUNNEL_API: "https://studio.storyteller.ai", + CDN_API: "https://cdn-2.fakeyou.com", + GRAVATAR_API: "https://studio.storyteller.ai", + DEPLOY_PRIME_URL: "https://studio.storyteller.ai", +}; + +const GlobalSettingsManager = ({ env }: { env: Record }) => { + useSignals(); + useSignalEffect(() => { + persistLogin(); + }); + + /// Initizations that depends on ENV vars /// + function PostHogInit() { + const data = EnvironmentVariables.values; + const apiKey = data.REACT_APP_PUBLIC_POSTHOG_KEY as string; + //posthog.init(apiKey, { + // //HACK: This is the default host from Netlify, but need to figure out why it isn't working on prod. + // // api_host: data.DEPLOY_PRIME_URL + "/ingest" as string, + // api_host: "https://studio.storyteller.ai/ingest" as string, + // ui_host: data.REACT_APP_PUBLIC_POSTHOG_UI as string, + //}); + } + useEffect(() => { + EnvironmentVariables.initialize(env); + PostHogInit(); + }, [env]); + + /// Initizations that run only once on 1ST mount /// + function setPage() { + // TODO address this issue with zooming + pageHeight.value = window.innerHeight; + pageWidth.value = window.innerWidth; + } + + function initWizard() { + if (showWizard.value) { + return; + } + const wizard = localStorage.getItem("storyteller-wizard"); + showWizard.value = wizard ? "" : "initial"; + localStorage.setItem("storyteller-wizard", "shown"); + } + + useEffect(() => { + initWizard(); + setPage(); + window.addEventListener("resize", setPage); + return () => { + window.removeEventListener("resize", setPage); + }; + }, []); + + return null; +}; + +// TODO: Replace environment variables from `root.tsx` +createRoot(document.getElementById("root")!).render( + <> + + + +
+ + + + +); diff --git a/frontend/apps/editor3d/app/login.tsx b/frontend/apps/editor3d/app/login.tsx new file mode 100644 index 0000000000..8bd06a595e --- /dev/null +++ b/frontend/apps/editor3d/app/login.tsx @@ -0,0 +1,185 @@ +import { useRef } from "react"; +import { BrowserRouter } from 'react-router-dom'; +import { StrictMode } from 'react'; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { useSignalEffect, useSignals } from "@preact/signals-react/runtime"; + +import { faKey, faUser } from "@fortawesome/pro-solid-svg-icons"; + +import { AUTH_STATUS } from "~/enums"; +import { authentication, login, logout } from "~/signals"; +import { createRoot } from "react-dom/client"; + +import { + Button, + H1, + Input, + Link, + P, + LoadingDots, + ConfirmationModal, +} from "~/components"; + +import "./styles/normalize.css"; +import "./styles/tailwind.css"; +import "./styles/base.css"; +import "@fortawesome/fontawesome-svg-core/styles.css"; + +import { config } from "@fortawesome/fontawesome-svg-core"; +import { GlobalSettingsManager } from "./pages/PageEnigma/GlobalSettingsManager"; + +config.autoAddCss = false; /* eslint-disable import/first */ + +// TODO(bt,2025-04-19): Make these configurable +const ENV = { + BASE_API: "https://api.storyteller.ai", + GOOGLE_API: "https://studio.storyteller.ai", + FUNNEL_API: "https://studio.storyteller.ai", + CDN_API: "https://cdn-2.fakeyou.com", + GRAVATAR_API: "https://studio.storyteller.ai", + DEPLOY_PRIME_URL: "https://studio.storyteller.ai", +}; + +export default function LoginScreen() { + useSignals(); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + + const formRef = useRef(null); + const { status: authStatus } = authentication; + const authLoaderMessage = getAuthLoaderMessage(); + const shouldShowLoader = checkShouldShowLoader(); + + const showNoAccessModal = authStatus.value === AUTH_STATUS.NO_ACCESS; + + const handleOnSumbit = (ev: React.FormEvent) => { + ev.preventDefault(); + if (formRef.current) { + const form = new FormData(formRef.current); + const usernameOrEmail = form.get("usernameOrEmail")?.toString(); + const password = form.get("password")?.toString(); + if (usernameOrEmail && password && login) { + login({ + usernameOrEmail, + password, + }); + } + } + }; // end handleOnSubmit + + useSignalEffect(() => { + const redirectPath = searchParams.get("redirect"); + if (authStatus.value === AUTH_STATUS.LOGGED_IN) { + navigate(redirectPath ? redirectPath : "/"); + } + }); + + return ( +
+
+

+ Login to Storyteller +

+
+
+
+ + +
+ + Forgot your password? + +
+

Don't have an account?

+ Sign Up +
+
+ + +
+ + { + handleClose(); + if (window) { + window.open("https://storyteller.ai/beta-key/redeem", "_blank"); + } + }} + /> +
+
+ ); +} + +const handleClose = () => { + if (authentication.status.value !== AUTH_STATUS.LOGGED_OUT) { + logout(); + } +}; + +const checkShouldShowLoader = () => { + return ( + authentication.status.value === AUTH_STATUS.LOGGING || + authentication.status.value === AUTH_STATUS.LOGGED_IN + ); +}; + +const getAuthLoaderMessage = () => { + if (authentication.status.value === AUTH_STATUS.LOGGED_IN) { + return "Authenticated, Redirecting..."; + } + if (authentication.status.value === AUTH_STATUS.GET_USER_INFO) { + return "Getting User Info..."; + } + return "Getting Session..."; +}; + + +// TODO: Replace environment variables from `root.tsx` +createRoot(document.getElementById("root")!).render( + <> + + + + + + + +); diff --git a/frontend/apps/editor3d/app/pages/Page404/index.tsx b/frontend/apps/editor3d/app/pages/Page404/index.tsx index c9d910023d..69ae9ebcb6 100644 --- a/frontend/apps/editor3d/app/pages/Page404/index.tsx +++ b/frontend/apps/editor3d/app/pages/Page404/index.tsx @@ -1,6 +1,6 @@ import { faChevronLeft } from "@fortawesome/pro-solid-svg-icons"; import { P, H1, ButtonLink } from "~/components"; -import { json } from "@remix-run/router"; +import { json } from "react-router-dom"; export const loader = () => { return json(null, { status: 404 }); diff --git a/frontend/apps/editor3d/app/pages/PageEnigma/GlobalSettingsManager.tsx b/frontend/apps/editor3d/app/pages/PageEnigma/GlobalSettingsManager.tsx new file mode 100644 index 0000000000..b228e5cd21 --- /dev/null +++ b/frontend/apps/editor3d/app/pages/PageEnigma/GlobalSettingsManager.tsx @@ -0,0 +1,57 @@ +import { useSignals, useSignalEffect } from "@preact/signals-react/runtime"; +import EnvironmentVariables from "~/Classes/EnvironmentVariables"; +import { persistLogin } from "~/signals"; +import { pageHeight, pageWidth } from "~/signals"; +import { useEffect } from "react"; +import { showWizard } from "~/pages/PageEnigma/Wizard/signals/wizard"; + + +export const GlobalSettingsManager = ({ env }: { env: Record }) => { + useSignals(); + useSignalEffect(() => { + persistLogin(); + }); + + /// Initizations that depends on ENV vars /// + function PostHogInit() { + const data = EnvironmentVariables.values; + const apiKey = data.REACT_APP_PUBLIC_POSTHOG_KEY as string; + //posthog.init(apiKey, { + // //HACK: This is the default host from Netlify, but need to figure out why it isn't working on prod. + // // api_host: data.DEPLOY_PRIME_URL + "/ingest" as string, + // api_host: "https://studio.storyteller.ai/ingest" as string, + // ui_host: data.REACT_APP_PUBLIC_POSTHOG_UI as string, + //}); + } + useEffect(() => { + EnvironmentVariables.initialize(env); + PostHogInit(); + }, [env]); + + /// Initizations that run only once on 1ST mount /// + function setPage() { + // TODO address this issue with zooming + pageHeight.value = window.innerHeight; + pageWidth.value = window.innerWidth; + } + + function initWizard() { + if (showWizard.value) { + return; + } + const wizard = localStorage.getItem("storyteller-wizard"); + showWizard.value = wizard ? "" : "initial"; + localStorage.setItem("storyteller-wizard", "shown"); + } + + useEffect(() => { + initWizard(); + setPage(); + window.addEventListener("resize", setPage); + return () => { + window.removeEventListener("resize", setPage); + }; + }, []); + + return null; +}; diff --git a/frontend/apps/editor3d/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx b/frontend/apps/editor3d/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx index f181948b3e..1ded1d16a1 100644 --- a/frontend/apps/editor3d/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx +++ b/frontend/apps/editor3d/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx @@ -1,5 +1,5 @@ import { useContext, useState, useCallback } from "react"; -import { useParams, useLocation, useNavigate } from "@remix-run/react"; +import { useParams, useLocation, useNavigate } from "react-router-dom"; import { useSignals, useSignalEffect } from "@preact/signals-react/runtime"; import { faCheckSquare, diff --git a/frontend/apps/editor3d/app/pages/PageEnigma/comps/Timeline/PremiumLockTimeline.tsx b/frontend/apps/editor3d/app/pages/PageEnigma/comps/Timeline/PremiumLockTimeline.tsx index 23ffee1736..af2616e4e1 100644 --- a/frontend/apps/editor3d/app/pages/PageEnigma/comps/Timeline/PremiumLockTimeline.tsx +++ b/frontend/apps/editor3d/app/pages/PageEnigma/comps/Timeline/PremiumLockTimeline.tsx @@ -1,4 +1,4 @@ -import { Link } from "@remix-run/react"; +import { Link } from "react-router-dom"; import { fullWidth, timelineHeight } from "../../signals"; interface PremiumLockTimelineProps { diff --git a/frontend/apps/editor3d/app/routes/$sceneToken.tsx b/frontend/apps/editor3d/app/routes/$sceneToken.tsx index da212591e2..db0b4754ab 100644 --- a/frontend/apps/editor3d/app/routes/$sceneToken.tsx +++ b/frontend/apps/editor3d/app/routes/$sceneToken.tsx @@ -1,5 +1,5 @@ import type { HeadersFunction } from "@remix-run/deno"; -import { useParams } from "@remix-run/react"; +import { useParams } from "react-router-dom"; import { withProtectionRoute } from "~/hoc/withProtectedRoute"; import { PageEnigma } from "~/pages/PageEnigma"; diff --git a/frontend/apps/editor3d/app/routes/Login.tsx b/frontend/apps/editor3d/app/routes/Login.tsx index 4a952cd6d1..a53d27aa9c 100644 --- a/frontend/apps/editor3d/app/routes/Login.tsx +++ b/frontend/apps/editor3d/app/routes/Login.tsx @@ -1,5 +1,5 @@ import { useRef } from "react"; -import { useNavigate, useSearchParams } from "@remix-run/react"; +import { useNavigate, useSearchParams } from "react-router-dom"; import { useSignalEffect, useSignals } from "@preact/signals-react/runtime"; import { faKey, faUser } from "@fortawesome/pro-solid-svg-icons"; @@ -90,7 +90,10 @@ export default function LoginScreen() {

Don't have an account?

- Sign Up + Sign Up
diff --git a/frontend/apps/editor3d/app/routes/Signup.tsx b/frontend/apps/editor3d/app/routes/Signup.tsx index 765b3b502c..d91c42132f 100644 --- a/frontend/apps/editor3d/app/routes/Signup.tsx +++ b/frontend/apps/editor3d/app/routes/Signup.tsx @@ -4,7 +4,7 @@ import { addToast, authentication, signUp } from "~/signals"; import { FormEvent, useRef, useState } from "react"; import { AUTH_STATUS, ToastTypes } from "~/enums"; import { useSignalEffect, useSignals } from "@preact/signals-react/runtime"; -import { useNavigate, useSearchParams } from "@remix-run/react"; +import { useNavigate, useSearchParams } from "react-router-dom"; const regEx = /^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i; diff --git a/frontend/apps/editor3d/app/signals/authentication/fetchers.ts b/frontend/apps/editor3d/app/signals/authentication/fetchers.ts index a46f2c4372..1c4bf29d27 100644 --- a/frontend/apps/editor3d/app/signals/authentication/fetchers.ts +++ b/frontend/apps/editor3d/app/signals/authentication/fetchers.ts @@ -46,6 +46,8 @@ export const login = async ({ // in storyteller studio, only having a sesison is not enough, // we need session info and active subscription info as well getUserInfoAndSubcriptions(); + + window.location.href = "/"; // TODO(bt,2025-04-19): Once we have in-page routing, get rid of this. }; export const signUp = async ({ diff --git a/frontend/apps/editor3d/app/signup.tsx b/frontend/apps/editor3d/app/signup.tsx new file mode 100644 index 0000000000..0b762e7fe2 --- /dev/null +++ b/frontend/apps/editor3d/app/signup.tsx @@ -0,0 +1,185 @@ +import { faEnvelope, faKey, faUser } from "@fortawesome/pro-solid-svg-icons"; +import { GlobalSettingsManager } from "./pages/PageEnigma/GlobalSettingsManager"; +import { StrictMode } from 'react'; +import { Button, H1, Input, Link, P } from "~/components"; +import { addToast, authentication, signUp } from "~/signals"; +import { FormEvent, useRef, useState } from "react"; +import { AUTH_STATUS, ToastTypes } from "~/enums"; +import { useSignalEffect, useSignals } from "@preact/signals-react/runtime"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { createRoot } from "react-dom/client"; +import { BrowserRouter } from 'react-router-dom'; + +import "./styles/normalize.css"; +import "./styles/tailwind.css"; +import "./styles/base.css"; +import "@fortawesome/fontawesome-svg-core/styles.css"; + +import { config } from "@fortawesome/fontawesome-svg-core"; + +config.autoAddCss = false; /* eslint-disable import/first */ + +const regEx = + /^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i; + +// TODO(bt,2025-04-19): Make these configurable +const ENV = { + BASE_API: "https://api.storyteller.ai", + GOOGLE_API: "https://studio.storyteller.ai", + FUNNEL_API: "https://studio.storyteller.ai", + CDN_API: "https://cdn-2.fakeyou.com", + GRAVATAR_API: "https://studio.storyteller.ai", + DEPLOY_PRIME_URL: "https://studio.storyteller.ai", +}; + +export default function SignUpScreen() { + useSignals(); + const navigate = useNavigate(); + const formRef = useRef(null); + const [usernameError, setUsernameError] = useState(""); + const [emailError, setEmailError] = useState(""); + const [passwordError, setPasswordError] = useState(""); + const [passwordConfirmationError, setPasswordConfirmationError] = + useState(""); + const [searchParams] = useSearchParams(); + const { status: authStatus } = authentication; + + const handleOnSubmit = (ev: FormEvent) => { + ev.preventDefault(); + if (formRef.current) { + const form = new FormData(formRef.current); + const email = form.get("email")?.toString(); + const password = form.get("password")?.toString(); + const passwordConfirmation = form + .get("password-confirmation") + ?.toString(); + const username = form.get("username")?.toString(); + setUsernameError(""); + if (!username || username.length < 6) { + setUsernameError("Username must be at least 6 characters long"); + } + setEmailError(""); + if (!email || !email.match(regEx)) { + setEmailError("Email must be a valid email address"); + } + setPasswordError(""); + if (!password || password.length < 8) { + setPasswordError("Password must be at least 8 characters long"); + } + setPasswordConfirmationError(""); + if (!passwordError && passwordConfirmation !== password) { + setPasswordConfirmationError("Passwords do not match"); + } + + if ( + !usernameError && + !passwordError && + !emailError && + !passwordConfirmationError && + signUp + ) { + signUp({ + username: username!, + email: email!, + password: password!, + passwordConfirmation: passwordConfirmation!, + }).then((error) => { + console.log("Error occured", error); + if (error) { + addToast(ToastTypes.ERROR, error); + } + }); + } + } + }; // end handleOnSubmit + + useSignalEffect(() => { + const redirectPath = searchParams.get("redirect"); + if (authStatus.value === AUTH_STATUS.LOGGED_IN) { + navigate(redirectPath ? redirectPath : "/"); + return; + } + if (authStatus.value === AUTH_STATUS.NO_ACCESS) { + window.open("https://storyteller.ai/", "_self"); + return; + } + }); + + return ( +
+
+

Sign Up to Storyteller

+
+
+
+ +
+ +
+ +
+ +
+
+ +
+
+

Already have an account?

+ Log in instead +
+
+
+
+ ); +} + + +// TODO: Replace environment variables from `root.tsx` +createRoot(document.getElementById("root")!).render( + <> + + + + + + + +); diff --git a/frontend/apps/editor3d/app/utilities.ts b/frontend/apps/editor3d/app/utilities.ts index c78e7fa1b8..0193c4c4e9 100644 --- a/frontend/apps/editor3d/app/utilities.ts +++ b/frontend/apps/editor3d/app/utilities.ts @@ -1,4 +1,4 @@ -import { Params } from "@remix-run/react"; +import { Params } from "react-router-dom"; import { JobStatus } from "./enums"; import deepEqual from "deep-equal"; diff --git a/frontend/apps/editor3d/index.html b/frontend/apps/editor3d/index.html new file mode 100644 index 0000000000..81c86cd95e --- /dev/null +++ b/frontend/apps/editor3d/index.html @@ -0,0 +1,16 @@ + + + + + MyApp + + + + + + + +
+ + + diff --git a/frontend/apps/editor3d/login.html b/frontend/apps/editor3d/login.html new file mode 100644 index 0000000000..dea0fea239 --- /dev/null +++ b/frontend/apps/editor3d/login.html @@ -0,0 +1,16 @@ + + + + + Login + + + + + + + +
+ + + diff --git a/frontend/apps/editor3d/package.json b/frontend/apps/editor3d/package.json index 23184eba48..610c9b1eae 100644 --- a/frontend/apps/editor3d/package.json +++ b/frontend/apps/editor3d/package.json @@ -14,9 +14,10 @@ } }, "scripts": { - "build": "remix vite:build", - "dev": "echo 'editor3d' && remix vite:dev", - "staging-build": "remix vite:build", + "build": "vite build", + "preview": "vite preview --port 8080", + "dev": "echo 'editor3d' && vite dev", + "staging-build": "vite build", "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint playground/* .", "start": "netlify serve", "typecheck": "tsc", @@ -65,6 +66,8 @@ "react-drag-drop-files": "^2.3.10", "react-helmet": "^6.1.0", "react-image-crop": "^11.0.5", + "react-router": "^6.26.1", + "react-router-dom": "^6.26.1", "react-virtualized": "^9.22.6", "tailwind-merge": "^2.2.2", "terser": "^5.30.3", diff --git a/frontend/apps/editor3d/remix.config.ts b/frontend/apps/editor3d/remix.config.ts deleted file mode 100644 index 1069800ddf..0000000000 --- a/frontend/apps/editor3d/remix.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { AppConfig } from '@remix-run/dev'; - -module.exports = { - ignoredRouteFiles: ["**/.*"], - tailwind: true, - serverModuleFormat: "cjs", -} satisfies AppConfig; \ No newline at end of file diff --git a/frontend/apps/editor3d/script/netlify_build.sh b/frontend/apps/editor3d/script/netlify_build.sh index 33d8afb80a..81085ae0a5 100755 --- a/frontend/apps/editor3d/script/netlify_build.sh +++ b/frontend/apps/editor3d/script/netlify_build.sh @@ -11,15 +11,15 @@ nx build editor3d --verbose echo "Change to project dir" pushd apps/editor3d/ -echo "List build directory files" -ls -lA build/ +#echo "List build directory files" +#ls -lA build/ -echo "Make output directory" -mkdir dist/ +#echo "Make output directory" +#mkdir dist/ echo "Copy files to putput directory" -cp -r build/server/* dist/ -cp -r build/client/* dist/ +#cp -r build/server/* dist/ +#cp -r build/client/* dist/ cp _headers dist/ #cp _redirects dist/ #cp "404.html" dist/ diff --git a/frontend/apps/editor3d/signup.html b/frontend/apps/editor3d/signup.html new file mode 100644 index 0000000000..b668ef3a6c --- /dev/null +++ b/frontend/apps/editor3d/signup.html @@ -0,0 +1,16 @@ + + + + + Signup + + + + + + + +
+ + + diff --git a/frontend/apps/editor3d/tsconfig.json b/frontend/apps/editor3d/tsconfig.json index 5c348b8c23..490787456a 100644 --- a/frontend/apps/editor3d/tsconfig.json +++ b/frontend/apps/editor3d/tsconfig.json @@ -21,9 +21,6 @@ "noEmit": true }, "references": [ - { - "path": "../../libs/api" - }, { "path": "../../libs/login" } diff --git a/frontend/apps/editor3d/vite.config.ts b/frontend/apps/editor3d/vite.config.ts index bc8d6ac52e..e3fe396f3f 100644 --- a/frontend/apps/editor3d/vite.config.ts +++ b/frontend/apps/editor3d/vite.config.ts @@ -1,9 +1,9 @@ -import { vitePlugin as remix } from "@remix-run/dev"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; import { netlifyPlugin } from "@netlify/remix-edge-adapter/plugin"; import { viteCommonjs, esbuildCommonjs } from '@originjs/vite-plugin-commonjs' import path from 'path' +import { dirname, resolve } from 'node:path' export default defineConfig({ root: __dirname, @@ -34,8 +34,17 @@ export default defineConfig({ // globals: {}, // }, //}, + build: { + rollupOptions: { + input: { + index: resolve(__dirname, 'index.html'), + login: resolve(__dirname, 'login.html'), + signup: resolve(__dirname, 'signup.html'), + //nested: resolve(__dirname, 'nested/index.html'), + }, + }, + }, plugins: [ - remix(), netlifyPlugin(), tsconfigPaths(), //viteCommonjs({ diff --git a/frontend/apps/my-app/index.html b/frontend/apps/my-app/index.html new file mode 100644 index 0000000000..dd8b10918b --- /dev/null +++ b/frontend/apps/my-app/index.html @@ -0,0 +1,16 @@ + + + + + MyApp + + + + + + + +
+ + + diff --git a/frontend/apps/my-app/package.json b/frontend/apps/my-app/package.json new file mode 100644 index 0000000000..646cb266d6 --- /dev/null +++ b/frontend/apps/my-app/package.json @@ -0,0 +1,5 @@ +{ + "name": "@frontend/my-app", + "version": "0.0.1", + "private": true +} diff --git a/frontend/apps/my-app/public/favicon.ico b/frontend/apps/my-app/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..317ebcb2336e0833a22dddf0ab287849f26fda57 GIT binary patch literal 15086 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 { + it('should render successfully', () => { + const { baseElement } = render(); + expect(baseElement).toBeTruthy(); + }); + + it('should have a greeting as the title', () => { + const { getAllByText } = render(); + expect(getAllByText(new RegExp('Welcome @frontend/my-app', 'gi')).length > 0).toBeTruthy(); + }); +}); diff --git a/frontend/apps/my-app/src/app/app.tsx b/frontend/apps/my-app/src/app/app.tsx new file mode 100644 index 0000000000..4d497d8aba --- /dev/null +++ b/frontend/apps/my-app/src/app/app.tsx @@ -0,0 +1,45 @@ +// Uncomment this line to use CSS modules +// import styles from './app.module.css'; +import NxWelcome from "./nx-welcome"; + +import { Route, Routes, Link } from 'react-router-dom'; + +export function App() { + return ( +
+ + + {/* START: routes */} + {/* These routes and navigation have been generated for you */} + {/* Feel free to move and update them to fit your needs */} +
+
+
+
+
    +
  • Home
  • +
  • Page 2
  • +
+
+ + This is the generated root route. Click here for page 2.
+ } + /> + Click here to go back to root page. + } + /> + + {/* END: routes */} + + ); +} + +export default App; + + diff --git a/frontend/apps/my-app/src/app/nx-welcome.tsx b/frontend/apps/my-app/src/app/nx-welcome.tsx new file mode 100644 index 0000000000..63cc7d12c2 --- /dev/null +++ b/frontend/apps/my-app/src/app/nx-welcome.tsx @@ -0,0 +1,857 @@ +/* + * * * * * * * * * * * * * * * * * * * * * * * * * * * * + This is a starter component and can be deleted. + * * * * * * * * * * * * * * * * * * * * * * * * * * * * + Delete this file and get started with your project! + * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ +export function NxWelcome({ title }: { title: string }) { + return ( + <> +