83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
import { computed, observable } from "mobx";
|
|
import { observer } from "mobx-react";
|
|
import * as React from "react";
|
|
import { Container, Dimmer, Form, Header, InputOnChangeData, Loader, Message, Segment } from "semantic-ui-react";
|
|
|
|
import { AppState, injectState } from "@client/state";
|
|
import log from "@common/logger";
|
|
|
|
import "@client/styles/LoginPage";
|
|
|
|
class LoginPageState {
|
|
@observable username = "";
|
|
@observable password = "";
|
|
|
|
@observable loading: boolean = false;
|
|
@observable error: string | null = null;
|
|
|
|
@computed get canLogin() {
|
|
return this.username.length > 0 && this.password.length > 0;
|
|
}
|
|
|
|
onUsernameChange = (e: any, data: InputOnChangeData) => {
|
|
this.username = data.value;
|
|
}
|
|
|
|
onPasswordChange = (e: any, data: InputOnChangeData) => {
|
|
this.password = data.value;
|
|
}
|
|
|
|
login(appState: AppState) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
appState.tokenStore.grantPassword(this.username, this.password)
|
|
.then(() => {
|
|
this.loading = false;
|
|
log.info("logged in");
|
|
appState.history.push("/");
|
|
})
|
|
.catch((err) => {
|
|
this.loading = false;
|
|
this.error = err.message;
|
|
log.error({ err }, "login error");
|
|
});
|
|
}
|
|
}
|
|
|
|
class LoginPage extends React.Component<{ appState: AppState }> {
|
|
pageState = new LoginPageState();
|
|
|
|
render() {
|
|
const { username, password, canLogin, loading, error } = this.pageState;
|
|
return (
|
|
<Container className="loginPage">
|
|
<Segment>
|
|
<Dimmer inverted active={loading}>
|
|
<Loader/>
|
|
</Dimmer>
|
|
|
|
<Header as="h1">Login</Header>
|
|
<Form>
|
|
<Form.Input label="Username" value={username} onChange={this.pageState.onUsernameChange}/>
|
|
<Form.Input
|
|
label="Password"
|
|
value={password}
|
|
type="password"
|
|
onChange={this.pageState.onPasswordChange}
|
|
/>
|
|
<Message error visible={error != null}>{error}</Message>
|
|
<Form.Button disabled={!canLogin} onClick={this.login}>Login</Form.Button>
|
|
</Form>
|
|
</Segment>
|
|
</Container>
|
|
);
|
|
}
|
|
|
|
login = () => {
|
|
this.pageState.login(this.props.appState);
|
|
}
|
|
}
|
|
|
|
const DecoratedLoginPage = injectState(observer(LoginPage));
|
|
export { DecoratedLoginPage as LoginPage };
|