mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
Fix 405 error (#516)
Co-authored-by: Christopher Oliphant <christopheroliphant@christophersmbp.home>
This commit is contained in:
1 parent
ff259446f6
commit
fecb909570
5 files changed
+179
-19
No files matched your search
@@ -107,4 +107,55 @@ export class UsersApi extends ApiManager {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async Signup({
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
passwordConfirmation,
|
||||
}: {
|
||||
username: string;
|
||||
email: string;
|
||||
password: string;
|
||||
passwordConfirmation: string;
|
||||
}): Promise<ApiResponse<{ signedSession?: string }>> {
|
||||
const endpoint = `${this.ApiTargets.BaseApi}/v1/create_account`;
|
||||
const body = {
|
||||
email_address: email,
|
||||
password,
|
||||
password_confirmation: passwordConfirmation,
|
||||
username,
|
||||
};
|
||||
return await this.post<
|
||||
{
|
||||
username: string;
|
||||
email_address: string;
|
||||
password: string;
|
||||
password_confirmation: string;
|
||||
},
|
||||
{
|
||||
success: boolean;
|
||||
signed_session?: string;
|
||||
error_fields?: Record<string, string>;
|
||||
error_message?: string;
|
||||
error_type?: string;
|
||||
}
|
||||
>({
|
||||
endpoint: endpoint,
|
||||
body: body,
|
||||
})
|
||||
.then((response) => {
|
||||
return {
|
||||
success: response.success,
|
||||
data: { signedSession: response.signed_session },
|
||||
errorMessage: Object.values(response.error_fields ?? {}).join(","),
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
error_message: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { LoadingDots, Toaster, TopBar } from "~/components";
|
||||
import { LoadingDots, TopBar } from "~/components";
|
||||
import { SidePanel } from "~/pages/PageEnigma/comps/SidePanel";
|
||||
import { Timeline } from "./comps/Timeline";
|
||||
import { Controls3D } from "./comps/Controls3D";
|
||||
@@ -108,7 +108,6 @@ export const PageEditor = () => {
|
||||
}}
|
||||
>
|
||||
<div className="relative w-full overflow-hidden bg-transparent">
|
||||
<Toaster />
|
||||
<SceneContainer>
|
||||
<EditorCanvas />
|
||||
<PreviewFrameImage />
|
||||
|
||||
@@ -22,6 +22,7 @@ import { config } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
import EnvironmentVariables from "~/Classes/EnvironmentVariables";
|
||||
import { environmentVariables, pageHeight, pageWidth } from "~/signals";
|
||||
import { Toaster } from "~/components";
|
||||
|
||||
config.autoAddCss = false; /* eslint-disable import/first */
|
||||
|
||||
@@ -95,6 +96,7 @@ export default function App() {
|
||||
<body className="overflow-hidden bg-ui-background">
|
||||
{data && <GlobalSettingsManager env={data.ENV} />}
|
||||
<div className="topbar-spacer" />
|
||||
<Toaster />
|
||||
<Outlet />
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
|
||||
+92
-17
@@ -1,31 +1,103 @@
|
||||
import { Form } from "@remix-run/react";
|
||||
import { faEnvelope, faKey, faUser } from "@fortawesome/pro-solid-svg-icons";
|
||||
import {
|
||||
Button,
|
||||
H1,
|
||||
Input,
|
||||
Link,
|
||||
P,
|
||||
} from '~/components';
|
||||
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 "@remix-run/react";
|
||||
|
||||
const regEx =
|
||||
/^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
|
||||
|
||||
export default function SignUpScreen() {
|
||||
useSignals();
|
||||
const navigate = useNavigate();
|
||||
const formRef = useRef<HTMLFormElement | null>(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<HTMLFormElement>) => {
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
export default function LoginScreen() {
|
||||
return (
|
||||
<div
|
||||
className="fixed w-full overflow-scroll"
|
||||
style={{height: "calc(100% - 72px)"}}
|
||||
style={{ height: "calc(100% - 72px)" }}
|
||||
>
|
||||
<div className="w-10/12 max-w-2xl mx-auto my-6">
|
||||
<div className="mx-auto my-6 w-10/12 max-w-2xl">
|
||||
<H1 className="text-center">Sign Up to Storyteller</H1>
|
||||
</div>
|
||||
<div
|
||||
className='bg-ui-panel w-10/12 max-w-2xl mx-auto my-6 rounded-lg p-6 border border-ui-panel-border'
|
||||
>
|
||||
<Form method="post" >
|
||||
<div className="mx-auto my-6 w-10/12 max-w-2xl rounded-lg border border-ui-panel-border bg-ui-panel p-6">
|
||||
<form ref={formRef} onSubmit={handleOnSubmit}>
|
||||
<Input
|
||||
label="Username"
|
||||
icon={faUser}
|
||||
placeholder="Username"
|
||||
name="username"
|
||||
errorMessage={usernameError}
|
||||
required
|
||||
/>
|
||||
<br />
|
||||
@@ -35,6 +107,7 @@ export default function LoginScreen() {
|
||||
icon={faEnvelope}
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
errorMessage={emailError}
|
||||
required
|
||||
/>
|
||||
<br />
|
||||
@@ -45,6 +118,7 @@ export default function LoginScreen() {
|
||||
name="password"
|
||||
placeholder="Password"
|
||||
autoComplete="current-password"
|
||||
errorMessage={passwordError}
|
||||
required
|
||||
/>
|
||||
<br />
|
||||
@@ -54,6 +128,7 @@ export default function LoginScreen() {
|
||||
icon={faKey}
|
||||
placeholder="Password COnfirmation"
|
||||
name="password-confirmation"
|
||||
errorMessage={passwordConfirmationError}
|
||||
required
|
||||
/>
|
||||
<br />
|
||||
@@ -62,9 +137,9 @@ export default function LoginScreen() {
|
||||
<br />
|
||||
<div className="flex gap-2">
|
||||
<P>Already have an account?</P>
|
||||
<Link to='/login'>Log in instead</Link>
|
||||
<Link to="/login">Log in instead</Link>
|
||||
</div>
|
||||
</Form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -48,6 +48,39 @@ export const login = async ({
|
||||
getUserInfoAndSubcriptions();
|
||||
};
|
||||
|
||||
export const signUp = async ({
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
passwordConfirmation,
|
||||
}: {
|
||||
username: string;
|
||||
email: string;
|
||||
password: string;
|
||||
passwordConfirmation: string;
|
||||
}) => {
|
||||
updateAuthStatus(AUTH_STATUS.LOGGING);
|
||||
|
||||
const usersApi = new UsersApi();
|
||||
const response = await usersApi.Signup({
|
||||
email,
|
||||
password,
|
||||
passwordConfirmation,
|
||||
username,
|
||||
});
|
||||
console.log(response);
|
||||
if (!response.success || !response.data) {
|
||||
setLogoutStates();
|
||||
return response.errorMessage ?? "Unknown error";
|
||||
}
|
||||
|
||||
// technically user is login with the system now, HOWEVER,
|
||||
// in storyteller studio, only having a sesison is not enough,
|
||||
// we need session info and active subscription info as well
|
||||
getUserInfoAndSubcriptions();
|
||||
return "";
|
||||
};
|
||||
|
||||
export const persistLogin = async () => {
|
||||
//Only run First Load, return if not
|
||||
if (authentication.status.value !== AUTH_STATUS.INIT) {
|
||||
|
||||
Reference in new issue
Block a user