mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 01:18:34 +00:00
more nav-based routing
This commit is contained in:
1 parent
84006c85a7
commit
7da7fb75cb
10 files changed
+601
-87
No files matched your search
+3
-1
@@ -133,7 +133,9 @@ class App extends React.Component<Props, State> {
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<h1>New Vocodes</h1>
|
||||
<NewVocodesContainer
|
||||
sessionWrapper={this.state.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { MigrationMode } from '../App'
|
||||
import { SessionWrapper } from '../session/SessionWrapper';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
@@ -29,10 +30,11 @@ function MigrationTopNav_Session(props: Props) {
|
||||
onClick={() => props.setMigrationModeCallback(MigrationMode.OLD_VOCODES)}
|
||||
>{displayName}</button>
|
||||
} else {
|
||||
sessionLink = <button
|
||||
sessionLink = <Link
|
||||
to="/signup"
|
||||
className="button is-danger is-pulled-right"
|
||||
onClick={() => props.setMigrationModeCallback(MigrationMode.OLD_VOCODES)}
|
||||
>Sign Up / Login</button>
|
||||
>Sign Up / Login</Link>
|
||||
}
|
||||
|
||||
return sessionLink;
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { SessionStateResponse } from "./SessionState";
|
||||
|
||||
/**
|
||||
* SessionWrapper can wrap each of the following states:
|
||||
*
|
||||
* 1) non-existing session
|
||||
* 2) logged-out session
|
||||
* 3) logged-in session
|
||||
*/
|
||||
export class SessionWrapper {
|
||||
sessionStateResponse?: SessionStateResponse;
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ import { VideoJob, VideoJobStatus } from './modes/video/VideoJob';
|
||||
import { VideoJobPoller } from './modes/video/VideoJobPoller';
|
||||
import { VideoQueuePoller } from './modes/video/VideoQueuePoller';
|
||||
import { VideoQueueStats } from './modes/video/VideoQueueStats';
|
||||
import { SignupComponent } from './modes/signup/SignupComponent';
|
||||
import { SignupComponent } from '../v2/signup/SignupComponent';
|
||||
import { ApiConfig } from './api/ApiConfig';
|
||||
import { SessionStateResponse } from './api/SessionState';
|
||||
import { LoginComponent } from './modes/login/LoginComponent';
|
||||
import { LoginComponent } from '../v2/login/LoginComponent';
|
||||
import { UploadComponent } from './modes/upload/UploadComponent';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { ApiConfig } from '../../api/ApiConfig';
|
||||
import { Mode } from '../../../AppMode';
|
||||
import { ApiConfig } from '../../v1/api/ApiConfig';
|
||||
import { Mode } from '../../AppMode';
|
||||
|
||||
enum FieldTriState {
|
||||
EMPTY_FALSE,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { ApiConfig } from '../../api/ApiConfig';
|
||||
import { Mode } from '../../../AppMode';
|
||||
import { ApiConfig } from '../../v1/api/ApiConfig';
|
||||
import { Mode } from '../../AppMode';
|
||||
|
||||
enum FieldTriState {
|
||||
EMPTY_FALSE,
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import { NewMode } from '../../v2/NewVocodesContainer'
|
||||
import { SessionStateResponse } from '../api/SessionState';
|
||||
import { SessionWrapper } from '../../session/SessionWrapper';
|
||||
|
||||
interface Props {
|
||||
sessionState?: SessionStateResponse,
|
||||
mode: NewMode,
|
||||
sessionWrapper: SessionWrapper,
|
||||
///historyBadgeCount: number,
|
||||
//isHistoryCountBadgeVisible: boolean,
|
||||
switchModeCallback: (mode: NewMode ) => void,
|
||||
logoutHandler: () => void,
|
||||
}
|
||||
|
||||
@@ -46,30 +45,30 @@ function NewTopNav(props: Props) {
|
||||
if (loggedIn) {
|
||||
loginManagement = (
|
||||
<span>
|
||||
<a href="#profile" onClick={() => props.switchModeCallback(NewMode.MY_PROFILE_MODE)}>{displayName}</a>
|
||||
<a href="#logout" onClick={() => props.logoutHandler()}>Log Out</a>
|
||||
<a href="#profile" onClick={() => {}}>{displayName}</a>
|
||||
<a href="#logout" onClick={() => {}}>Log Out</a>
|
||||
</span>
|
||||
);
|
||||
column1 = (
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.MY_PROFILE_MODE)}
|
||||
onClick={() => {}}
|
||||
>Firehose</button>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
loginManagement = (
|
||||
<span>
|
||||
<a href="#login" onClick={() => props.switchModeCallback(NewMode.LOGIN_MODE)}>Login</a>
|
||||
<a href="#signup" onClick={() => props.switchModeCallback(NewMode.SIGNUP_MODE)} className="signup">Sign Up</a>
|
||||
<a href="#login" onClick={() => {}}>Login</a>
|
||||
<a href="#signup" onClick={() => {}} className="signup">Sign Up</a>
|
||||
</span>
|
||||
);
|
||||
column1 = (
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.SIGNUP_MODE)}
|
||||
onClick={() => {}}
|
||||
>Sign Up</button>
|
||||
</div>
|
||||
);
|
||||
@@ -77,7 +76,7 @@ function NewTopNav(props: Props) {
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.LOGIN_MODE)}
|
||||
onClick={() => {}}
|
||||
>Login</button>
|
||||
</div>
|
||||
);
|
||||
@@ -88,10 +87,10 @@ function NewTopNav(props: Props) {
|
||||
<strong>NEW Community Features let you use Your Own Voices and Video:</strong>
|
||||
<br />
|
||||
<br />
|
||||
<a href="#community_tts" onClick={() => props.switchModeCallback(NewMode.COMMUNITY_TTS_MODE)}>TTS</a>
|
||||
<a href="#community_video" onClick={() => props.switchModeCallback(NewMode.COMMUNITY_W2L_MODE)}>Video</a>
|
||||
<a href="#upload" onClick={() => props.switchModeCallback(NewMode.UPLOAD_MODE)}>Upload</a>
|
||||
<a href="#my_data" onClick={() => props.switchModeCallback(NewMode.MY_DATA_MODE)}>My Data</a>
|
||||
<a href="#community_tts" onClick={() => {}}>TTS</a>
|
||||
<a href="#community_video" onClick={() => {}}>Video</a>
|
||||
<a href="#upload" onClick={() => {}}>Upload</a>
|
||||
<a href="#my_data" onClick={() => {}}>My Data</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -105,13 +104,13 @@ function NewTopNav(props: Props) {
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.COMMUNITY_TTS_MODE)}
|
||||
onClick={() => {}}
|
||||
>Text to Speech 🗣️</button>
|
||||
</div>
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.COMMUNITY_TTS_MODE)}
|
||||
onClick={() => {}}
|
||||
>Video 🎥</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,19 +118,19 @@ function NewTopNav(props: Props) {
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.COMMUNITY_TTS_MODE)}
|
||||
onClick={() => {}}
|
||||
>Upload TTS ⬆️</button>
|
||||
</div>
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.COMMUNITY_TTS_MODE)}
|
||||
onClick={() => {}}
|
||||
>Upload Video ⬆️</button>
|
||||
</div>
|
||||
<div className="column">
|
||||
<button
|
||||
className="button is-link is-large is-inverted"
|
||||
onClick={() => props.switchModeCallback(NewMode.COMMUNITY_TTS_MODE)}
|
||||
onClick={() => {}}
|
||||
>My Data</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
import React from 'react';
|
||||
import { NewTopNav } from '../v1/navigation/NewTopNav';
|
||||
import { SessionStateResponse } from '../v1/api/SessionState';
|
||||
import { LoginComponent } from '../v1/modes/login/LoginComponent';
|
||||
import { SignupComponent } from '../v1/modes/signup/SignupComponent';
|
||||
import { LoginComponent } from './login/LoginComponent';
|
||||
import { SignupComponent } from './signup/SignupComponent';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { SessionWrapper } from '../session/SessionWrapper';
|
||||
|
||||
|
||||
enum NewMode {
|
||||
LOGIN_MODE,
|
||||
SIGNUP_MODE,
|
||||
COMMUNITY_TTS_MODE,
|
||||
COMMUNITY_W2L_MODE,
|
||||
UPLOAD_MODE,
|
||||
MY_DATA_MODE,
|
||||
MY_PROFILE_MODE,
|
||||
EDIT_MY_PROFILE_MODE,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sessionState?: SessionStateResponse,
|
||||
sessionWrapper: SessionWrapper,
|
||||
}
|
||||
|
||||
interface State {
|
||||
mode: NewMode,
|
||||
}
|
||||
|
||||
class NewVocodesContainer extends React.Component<Props, State> {
|
||||
@@ -30,64 +19,37 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
mode: NewMode.SIGNUP_MODE,
|
||||
}
|
||||
}
|
||||
|
||||
switchMode = (mode: NewMode) => {
|
||||
this.setState({mode: mode});
|
||||
}
|
||||
|
||||
logout = () => {
|
||||
}
|
||||
|
||||
public render() {
|
||||
let innerComponent = <div />;
|
||||
let loggedIn = false;
|
||||
let displayName = "My Account";
|
||||
|
||||
if (this.props.sessionState !== undefined) {
|
||||
console.log('sessionstate', this.props.sessionState);
|
||||
loggedIn = this.props.sessionState.logged_in;
|
||||
if (this.props.sessionState.user !== undefined &&
|
||||
this.props.sessionState.user !== null) {
|
||||
displayName = this.props.sessionState.user.display_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (this.state.mode) {
|
||||
case NewMode.SIGNUP_MODE:
|
||||
innerComponent = (
|
||||
<SignupComponent
|
||||
querySessionCallback={()=>{}}
|
||||
loggedIn={loggedIn}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case NewMode.LOGIN_MODE:
|
||||
innerComponent = (
|
||||
<LoginComponent
|
||||
querySessionCallback={()=>{}}
|
||||
loggedIn={loggedIn}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="main" className="mainwrap">
|
||||
<div id="viewable">
|
||||
|
||||
<NewTopNav
|
||||
mode={this.state.mode}
|
||||
switchModeCallback={this.switchMode}
|
||||
logoutHandler={this.logout}
|
||||
sessionState={this.props.sessionState}
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
|
||||
{innerComponent}
|
||||
<Switch>
|
||||
<Route path="/login">
|
||||
<LoginComponent
|
||||
querySessionCallback={()=>{}}
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/signup">
|
||||
<SignupComponent
|
||||
querySessionCallback={()=>{}}
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,4 +57,4 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
export { NewVocodesContainer, NewMode }
|
||||
export { NewVocodesContainer }
|
||||
@@ -0,0 +1,160 @@
|
||||
import React from 'react';
|
||||
import { ApiConfig } from '../../v1/api/ApiConfig';
|
||||
import { Mode } from '../../AppMode';
|
||||
import { SessionWrapper } from '../../session/SessionWrapper';
|
||||
|
||||
enum FieldTriState {
|
||||
EMPTY_FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
querySessionCallback : () => void,
|
||||
switchModeCallback?: (mode: Mode) => void,
|
||||
}
|
||||
|
||||
interface State {
|
||||
usernameOrEmail: string,
|
||||
usernameOrEmailValid: FieldTriState,
|
||||
usernameOrEmailInvalidReason: string,
|
||||
|
||||
password: string,
|
||||
passwordValid: FieldTriState,
|
||||
passwordInvalidReason: string,
|
||||
}
|
||||
|
||||
class LoginComponent extends React.Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
usernameOrEmail: "",
|
||||
usernameOrEmailValid: FieldTriState.EMPTY_FALSE,
|
||||
usernameOrEmailInvalidReason: "",
|
||||
|
||||
password: "",
|
||||
passwordValid: FieldTriState.EMPTY_FALSE,
|
||||
passwordInvalidReason: "",
|
||||
};
|
||||
}
|
||||
|
||||
handleUsernameOrEmailChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const usernameOrEmail = (ev.target as HTMLInputElement).value;
|
||||
|
||||
this.setState({
|
||||
usernameOrEmail: usernameOrEmail,
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handlePasswordChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const password = (ev.target as HTMLInputElement).value;
|
||||
|
||||
this.setState({
|
||||
password: password,
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handleFormSubmit = (ev: React.FormEvent<HTMLFormElement>) : boolean => {
|
||||
ev.preventDefault();
|
||||
|
||||
const api = new ApiConfig();
|
||||
const endpointUrl = api.login();
|
||||
|
||||
const request = {
|
||||
username_or_email: this.state.usernameOrEmail,
|
||||
password: this.state.password,
|
||||
}
|
||||
|
||||
fetch(endpointUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
console.log('login response', res)
|
||||
if (res.success) {
|
||||
console.log('querying new session');
|
||||
this.props.querySessionCallback();
|
||||
|
||||
if (this.props.switchModeCallback !== undefined) {
|
||||
this.props.switchModeCallback(Mode.SPEAK_MODE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
//this.props.onSpeakErrorCallback();
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.props.sessionWrapper.isLoggedIn()) {
|
||||
return <div>Invalid view for logged in users.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title is-1"> Login </h1>
|
||||
|
||||
<p></p>
|
||||
|
||||
<form onSubmit={this.handleFormSubmit}>
|
||||
<div className="field">
|
||||
<label className="label">Username or Email</label>
|
||||
<div className="control has-icons-left has-icons-right">
|
||||
<input className="input" type="text" placeholder="Username or Email" value={this.state.usernameOrEmail} onChange={this.handleUsernameOrEmailChange} />
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-user"></i>
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-check"></i>
|
||||
</span>
|
||||
</div>
|
||||
{/*<p className="help"></p>*/}
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="label">Password</label>
|
||||
<div className="control has-icons-left has-icons-right">
|
||||
<input className="input" type="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-envelope"></i>
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</div>
|
||||
{/*<p className="help"></p>*/}
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div className="field is-grouped">
|
||||
<div className="control">
|
||||
<button className="button is-link is-large">Login</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export { LoginComponent };
|
||||
@@ -0,0 +1,382 @@
|
||||
import React from 'react';
|
||||
import { ApiConfig } from '../../v1/api/ApiConfig';
|
||||
import { Mode } from '../../AppMode';
|
||||
import { SessionWrapper } from '../../session/SessionWrapper';
|
||||
|
||||
enum FieldTriState {
|
||||
EMPTY_FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
querySessionCallback : () => void,
|
||||
switchModeCallback?: (mode: Mode) => void,
|
||||
}
|
||||
|
||||
interface State {
|
||||
username: string,
|
||||
usernameValid: FieldTriState,
|
||||
usernameInvalidReason: string,
|
||||
|
||||
email: string,
|
||||
emailValid: FieldTriState,
|
||||
emailInvalidReason: string,
|
||||
|
||||
password: string,
|
||||
passwordValid: FieldTriState,
|
||||
passwordInvalidReason: string,
|
||||
|
||||
passwordConfirmation: string,
|
||||
passwordConfirmationValid: FieldTriState,
|
||||
passwordConfirmationInvalidReason: string,
|
||||
}
|
||||
|
||||
class SignupComponent extends React.Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
username: "",
|
||||
usernameValid: FieldTriState.EMPTY_FALSE,
|
||||
usernameInvalidReason: "",
|
||||
|
||||
email: "",
|
||||
emailValid: FieldTriState.EMPTY_FALSE,
|
||||
emailInvalidReason: "",
|
||||
|
||||
password: "",
|
||||
passwordValid: FieldTriState.EMPTY_FALSE,
|
||||
passwordInvalidReason: "",
|
||||
|
||||
passwordConfirmation: "",
|
||||
passwordConfirmationValid: FieldTriState.EMPTY_FALSE,
|
||||
passwordConfirmationInvalidReason: "",
|
||||
};
|
||||
}
|
||||
|
||||
handleUsernameChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const username = (ev.target as HTMLInputElement).value;
|
||||
|
||||
let usernameValid = FieldTriState.EMPTY_FALSE;
|
||||
let usernameInvalidReason = "";
|
||||
|
||||
if (username.length > 1) {
|
||||
if (username.length < 3) {
|
||||
usernameValid = FieldTriState.FALSE;
|
||||
usernameInvalidReason = "username is too short";
|
||||
} else if (username.length > 15) {
|
||||
usernameValid = FieldTriState.FALSE;
|
||||
usernameInvalidReason = "username is too long";
|
||||
} else {
|
||||
usernameValid = FieldTriState.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
username: username,
|
||||
usernameValid: usernameValid,
|
||||
usernameInvalidReason: usernameInvalidReason,
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handleEmailChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const email = (ev.target as HTMLInputElement).value;
|
||||
|
||||
let emailValid = FieldTriState.EMPTY_FALSE;
|
||||
let emailInvalidReason = "";
|
||||
|
||||
if (email.length > 1) {
|
||||
if (email.length < 3) {
|
||||
emailValid = FieldTriState.FALSE;
|
||||
emailInvalidReason = "email is too short";
|
||||
} else if (!email.includes("@")) {
|
||||
emailValid = FieldTriState.FALSE;
|
||||
emailInvalidReason = "email is invalid";
|
||||
} else {
|
||||
emailValid = FieldTriState.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
email: email,
|
||||
emailValid: emailValid,
|
||||
emailInvalidReason: emailInvalidReason,
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handlePasswordChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const password = (ev.target as HTMLInputElement).value;
|
||||
|
||||
let passwordValid = FieldTriState.EMPTY_FALSE;
|
||||
let passwordInvalidReason = "";
|
||||
let passwordConfirmationValid = FieldTriState.EMPTY_FALSE;
|
||||
let passwordConfirmationInvalidReason = "";
|
||||
|
||||
if (password.length > 1) {
|
||||
if (password.length < 5) {
|
||||
passwordValid = FieldTriState.FALSE;
|
||||
passwordInvalidReason = "password is too short";
|
||||
} else {
|
||||
passwordValid = FieldTriState.TRUE;
|
||||
}
|
||||
|
||||
if (password !== this.state.passwordConfirmation) {
|
||||
passwordConfirmationValid = FieldTriState.FALSE;
|
||||
passwordConfirmationInvalidReason = "passwords do not match";
|
||||
} else {
|
||||
passwordConfirmationValid = FieldTriState.TRUE;
|
||||
passwordConfirmationInvalidReason = "";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
password: password,
|
||||
passwordValid: passwordValid,
|
||||
passwordInvalidReason: passwordInvalidReason,
|
||||
passwordConfirmationValid: passwordConfirmationValid,
|
||||
passwordConfirmationInvalidReason: passwordConfirmationInvalidReason,
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
handlePasswordConfirmationChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const passwordConfirmation = (ev.target as HTMLInputElement).value;
|
||||
|
||||
let passwordConfirmationValid = FieldTriState.EMPTY_FALSE;
|
||||
let passwordConfirmationInvalidReason = "";
|
||||
|
||||
if (passwordConfirmation.length > 1) {
|
||||
|
||||
if (passwordConfirmation !== this.state.password) {
|
||||
passwordConfirmationValid = FieldTriState.FALSE;
|
||||
passwordConfirmationInvalidReason = "passwords do not match";
|
||||
} else {
|
||||
passwordConfirmationValid = FieldTriState.TRUE;
|
||||
passwordConfirmationInvalidReason = "";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
passwordConfirmation: passwordConfirmation,
|
||||
passwordConfirmationValid: passwordConfirmationValid,
|
||||
passwordConfirmationInvalidReason: passwordConfirmationInvalidReason,
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handleFormSubmit = (ev: React.FormEvent<HTMLFormElement>) : boolean => {
|
||||
ev.preventDefault();
|
||||
|
||||
if (!this.state.usernameValid ||
|
||||
!this.state.emailValid ||
|
||||
!this.state.passwordValid ||
|
||||
!this.state.passwordConfirmationValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const api = new ApiConfig();
|
||||
const endpointUrl = api.createAccount();
|
||||
|
||||
const request = {
|
||||
username: this.state.username,
|
||||
email_address: this.state.email,
|
||||
password: this.state.password,
|
||||
password_confirmation: this.state.passwordConfirmation,
|
||||
}
|
||||
|
||||
fetch(endpointUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
console.log('create account response', res)
|
||||
if (res.success) {
|
||||
console.log('querying new session');
|
||||
this.props.querySessionCallback();
|
||||
|
||||
if (this.props.switchModeCallback !== undefined) {
|
||||
this.props.switchModeCallback(Mode.SPEAK_MODE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
//this.props.onSpeakErrorCallback();
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.props.sessionWrapper.isLoggedIn()) {
|
||||
return <div>Invalid view for logged in users.</div>;
|
||||
}
|
||||
|
||||
let usernameInputClass = "input";
|
||||
let usernameHelpClass = "help";
|
||||
switch (this.state.usernameValid) {
|
||||
case FieldTriState.EMPTY_FALSE:
|
||||
break;
|
||||
case FieldTriState.FALSE:
|
||||
usernameInputClass += " is-danger";
|
||||
usernameHelpClass += " is-danger";
|
||||
break;
|
||||
case FieldTriState.TRUE:
|
||||
usernameInputClass += " is-success";
|
||||
usernameHelpClass += " is-success";
|
||||
break;
|
||||
}
|
||||
|
||||
let emailInputClass = "input";
|
||||
let emailHelpClass = "help";
|
||||
switch (this.state.emailValid) {
|
||||
case FieldTriState.EMPTY_FALSE:
|
||||
break;
|
||||
case FieldTriState.FALSE:
|
||||
emailInputClass += " is-danger";
|
||||
emailHelpClass += " is-danger";
|
||||
break;
|
||||
case FieldTriState.TRUE:
|
||||
emailInputClass += " is-success";
|
||||
emailHelpClass += " is-success";
|
||||
break;
|
||||
}
|
||||
|
||||
let passwordInputClass = "input";
|
||||
let passwordHelpClass = "help";
|
||||
switch (this.state.passwordValid) {
|
||||
case FieldTriState.EMPTY_FALSE:
|
||||
break;
|
||||
case FieldTriState.FALSE:
|
||||
passwordInputClass += " is-danger";
|
||||
passwordHelpClass += " is-danger";
|
||||
break;
|
||||
case FieldTriState.TRUE:
|
||||
passwordInputClass += " is-success";
|
||||
passwordHelpClass += " is-success";
|
||||
break;
|
||||
}
|
||||
|
||||
let passwordConfirmationInputClass = "input";
|
||||
let passwordConfirmationHelpClass = "help";
|
||||
switch (this.state.passwordConfirmationValid) {
|
||||
case FieldTriState.EMPTY_FALSE:
|
||||
break;
|
||||
case FieldTriState.FALSE:
|
||||
passwordConfirmationInputClass += " is-danger";
|
||||
passwordConfirmationHelpClass += " is-danger";
|
||||
break;
|
||||
case FieldTriState.TRUE:
|
||||
passwordConfirmationInputClass += " is-success";
|
||||
passwordConfirmationHelpClass += " is-success";
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title is-1"> Sign Up </h1>
|
||||
|
||||
<form onSubmit={this.handleFormSubmit}>
|
||||
<div className="field">
|
||||
<label className="label">Username</label>
|
||||
<div className="control has-icons-left has-icons-right">
|
||||
<input className={usernameInputClass} type="text" placeholder="Username" value={this.state.username} onChange={this.handleUsernameChange} />
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-user"></i>
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-check"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p className={usernameHelpClass}>{this.state.usernameInvalidReason}</p>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="label">Email</label>
|
||||
<div className="control has-icons-left has-icons-right">
|
||||
<input className={emailInputClass} type="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-envelope"></i>
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p className={emailHelpClass}>{this.state.emailInvalidReason}</p>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="label">Password</label>
|
||||
<div className="control has-icons-left has-icons-right">
|
||||
<input className={passwordInputClass} type="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-envelope"></i>
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p className={passwordHelpClass}>{this.state.passwordInvalidReason}</p>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="label">Password Confirmation</label>
|
||||
<div className="control has-icons-left has-icons-right">
|
||||
<input className={passwordConfirmationInputClass} type="password" placeholder="Password confirmation" value={this.state.passwordConfirmation} onChange={this.handlePasswordConfirmationChange} />
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-envelope"></i>
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p className={passwordConfirmationHelpClass}>{this.state.passwordConfirmationInvalidReason}</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div className="notification is-warning">
|
||||
<strong>Remember your password!</strong> We don't have password reset currently, and it'll be a
|
||||
few more weeks before it's added (there are more important features to work on). If you lose your
|
||||
password, please let us know in Discord.
|
||||
</div>
|
||||
|
||||
<div className="field is-grouped">
|
||||
<div className="control">
|
||||
<button className="button is-link is-large">Sign up</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export { SignupComponent };
|
||||
Reference in new issue
Block a user