2019-06-20 19:37:28 +07:00
|
|
|
import React, { Component, ReactElement } from 'react';
|
2019-02-03 17:23:33 +07:00
|
|
|
import isNil from 'lodash/isNil';
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
import storage from '../utils/storage';
|
|
|
|
import { makeLogin, isTokenExpire } from '../utils/login';
|
|
|
|
|
|
|
|
import Loading from '../components/Loading';
|
|
|
|
import LoginModal from '../components/Login';
|
|
|
|
import Header from '../components/Header';
|
|
|
|
import { Container, Content } from '../components/Layout';
|
|
|
|
import RouterApp from '../router';
|
|
|
|
import API from '../utils/api';
|
|
|
|
import '../styles/typeface-roboto.scss';
|
|
|
|
import '../styles/main.scss';
|
2019-02-03 17:23:33 +07:00
|
|
|
import 'normalize.css';
|
2019-06-20 19:37:28 +07:00
|
|
|
import Footer from '../components/Footer';
|
2019-06-26 05:29:53 +07:00
|
|
|
import { FormError } from 'src/components/Login/Login';
|
2019-02-03 17:23:33 +07:00
|
|
|
|
2019-06-25 05:54:32 +07:00
|
|
|
export const AppContext = React.createContext<{}>({});
|
2019-02-03 17:23:33 +07:00
|
|
|
export const AppContextProvider = AppContext.Provider;
|
|
|
|
export const AppContextConsumer = AppContext.Consumer;
|
|
|
|
|
2019-06-26 05:29:53 +07:00
|
|
|
interface AppStateInterface {
|
|
|
|
error?: FormError;
|
|
|
|
logoUrl: string;
|
|
|
|
user: {};
|
|
|
|
scope: string;
|
|
|
|
showLoginModal: boolean;
|
|
|
|
isUserLoggedIn: boolean;
|
|
|
|
packages: [];
|
|
|
|
isLoading: boolean;
|
|
|
|
}
|
|
|
|
export default class App extends Component<{}, AppStateInterface> {
|
|
|
|
public state: AppStateInterface = {
|
2019-06-20 19:37:28 +07:00
|
|
|
// @ts-ignore
|
2019-02-03 17:23:33 +07:00
|
|
|
logoUrl: window.VERDACCIO_LOGO,
|
|
|
|
user: {},
|
2019-06-20 19:37:28 +07:00
|
|
|
// @ts-ignore
|
2019-02-03 17:23:33 +07:00
|
|
|
scope: window.VERDACCIO_SCOPE ? `${window.VERDACCIO_SCOPE}:` : '',
|
|
|
|
showLoginModal: false,
|
|
|
|
isUserLoggedIn: false,
|
|
|
|
packages: [],
|
|
|
|
isLoading: true,
|
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public componentDidMount(): void {
|
2019-02-03 17:23:33 +07:00
|
|
|
this.isUserAlreadyLoggedIn();
|
|
|
|
this.loadOnHandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
2019-06-20 19:37:28 +07:00
|
|
|
public componentDidUpdate(_, prevState): void {
|
2019-03-28 05:39:06 +07:00
|
|
|
const { isUserLoggedIn } = this.state;
|
2019-02-03 17:23:33 +07:00
|
|
|
if (prevState.isUserLoggedIn !== isUserLoggedIn) {
|
|
|
|
this.loadOnHandler();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public render(): React.ReactElement<HTMLDivElement> {
|
2019-03-28 05:39:06 +07:00
|
|
|
const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state;
|
|
|
|
|
2019-06-25 05:54:32 +07:00
|
|
|
const context = { isUserLoggedIn, packages, logoUrl, user, scope };
|
2019-06-20 19:37:28 +07:00
|
|
|
|
2019-03-28 05:39:06 +07:00
|
|
|
return (
|
2019-06-20 19:37:28 +07:00
|
|
|
// @ts-ignore
|
2019-03-28 05:39:06 +07:00
|
|
|
<Container isLoading={isLoading}>
|
|
|
|
{isLoading ? (
|
|
|
|
<Loading />
|
|
|
|
) : (
|
2019-06-20 19:37:28 +07:00
|
|
|
<>
|
|
|
|
<AppContextProvider value={context}>{this.renderContent()}</AppContextProvider>
|
|
|
|
</>
|
2019-03-28 05:39:06 +07:00
|
|
|
)}
|
|
|
|
{this.renderLoginModal()}
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public isUserAlreadyLoggedIn = () => {
|
2019-02-03 17:23:33 +07:00
|
|
|
// checks for token validity
|
|
|
|
const token = storage.getItem('token');
|
|
|
|
const username = storage.getItem('username');
|
|
|
|
if (isTokenExpire(token) || isNil(username)) {
|
|
|
|
this.handleLogout();
|
|
|
|
} else {
|
|
|
|
this.setState({
|
2019-03-28 05:39:06 +07:00
|
|
|
user: { username, token },
|
2019-02-03 17:23:33 +07:00
|
|
|
isUserLoggedIn: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public loadOnHandler = async () => {
|
2019-02-03 17:23:33 +07:00
|
|
|
try {
|
2019-06-20 19:37:28 +07:00
|
|
|
// @ts-ignore
|
2019-02-03 17:23:33 +07:00
|
|
|
this.req = await API.request('packages', 'GET');
|
|
|
|
this.setState({
|
2019-06-20 19:37:28 +07:00
|
|
|
// @ts-ignore
|
2019-02-03 17:23:33 +07:00
|
|
|
packages: this.req,
|
|
|
|
isLoading: false,
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
// FIXME: add dialog
|
|
|
|
console.error({
|
|
|
|
title: 'Warning',
|
|
|
|
message: `Unable to load package list: ${error.message}`,
|
|
|
|
});
|
|
|
|
this.setLoading(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public setLoading = isLoading =>
|
2019-02-03 17:23:33 +07:00
|
|
|
this.setState({
|
|
|
|
isLoading,
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggles the login modal
|
|
|
|
* Required by: <LoginModal /> <Header />
|
|
|
|
*/
|
2019-06-20 19:37:28 +07:00
|
|
|
public handleToggleLoginModal = () => {
|
2019-03-28 05:39:06 +07:00
|
|
|
this.setState(prevState => ({
|
2019-06-20 19:37:28 +07:00
|
|
|
// @ts-ignore
|
2019-02-03 17:23:33 +07:00
|
|
|
showLoginModal: !prevState.showLoginModal,
|
2019-06-26 05:29:53 +07:00
|
|
|
error: undefined,
|
2019-02-03 17:23:33 +07:00
|
|
|
}));
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* handles login
|
|
|
|
* Required by: <Header />
|
|
|
|
*/
|
2019-06-20 19:37:28 +07:00
|
|
|
public handleDoLogin = async (usernameValue, passwordValue) => {
|
|
|
|
// @ts-ignore
|
2019-03-28 05:39:06 +07:00
|
|
|
const { username, token, error } = await makeLogin(usernameValue, passwordValue);
|
2019-02-03 17:23:33 +07:00
|
|
|
|
|
|
|
if (username && token) {
|
|
|
|
storage.setItem('username', username);
|
|
|
|
storage.setItem('token', token);
|
2019-06-10 16:49:18 +07:00
|
|
|
this.setLoggedUser(username, token);
|
2019-02-03 17:23:33 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
this.setState({
|
|
|
|
user: {},
|
|
|
|
error,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public setLoggedUser = (username, token) => {
|
2019-02-03 17:23:33 +07:00
|
|
|
this.setState({
|
|
|
|
user: {
|
|
|
|
username,
|
|
|
|
token,
|
|
|
|
},
|
|
|
|
isUserLoggedIn: true, // close login modal after successful login
|
|
|
|
showLoginModal: false, // set isUserLoggedIn to true
|
|
|
|
});
|
|
|
|
};
|
2019-03-28 05:39:06 +07:00
|
|
|
|
2019-02-03 17:23:33 +07:00
|
|
|
/**
|
|
|
|
* Logouts user
|
|
|
|
* Required by: <Header />
|
|
|
|
*/
|
2019-06-20 19:37:28 +07:00
|
|
|
public handleLogout = () => {
|
2019-02-03 17:23:33 +07:00
|
|
|
storage.removeItem('username');
|
|
|
|
storage.removeItem('token');
|
|
|
|
this.setState({
|
|
|
|
user: {},
|
|
|
|
isUserLoggedIn: false,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public renderLoginModal = (): ReactElement<HTMLElement> => {
|
2019-03-28 05:39:06 +07:00
|
|
|
const { error, showLoginModal } = this.state;
|
2019-06-20 19:37:28 +07:00
|
|
|
return <LoginModal error={error} onCancel={this.handleToggleLoginModal} onSubmit={this.handleDoLogin} visibility={showLoginModal} />;
|
2019-02-03 17:23:33 +07:00
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public renderContent = (): ReactElement<HTMLElement> => {
|
2019-02-03 17:23:33 +07:00
|
|
|
return (
|
2019-06-20 19:37:28 +07:00
|
|
|
<>
|
2019-02-03 17:23:33 +07:00
|
|
|
<Content>
|
|
|
|
<RouterApp onLogout={this.handleLogout} onToggleLoginModal={this.handleToggleLoginModal}>
|
|
|
|
{this.renderHeader()}
|
|
|
|
</RouterApp>
|
|
|
|
</Content>
|
|
|
|
<Footer />
|
2019-06-20 19:37:28 +07:00
|
|
|
</>
|
2019-02-03 17:23:33 +07:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-06-20 19:37:28 +07:00
|
|
|
public renderHeader = (): ReactElement<HTMLElement> => {
|
|
|
|
const {
|
|
|
|
logoUrl,
|
|
|
|
// @ts-ignore
|
|
|
|
user: { username },
|
|
|
|
scope,
|
|
|
|
} = this.state;
|
2019-02-03 17:23:33 +07:00
|
|
|
|
2019-03-28 05:39:06 +07:00
|
|
|
return <Header logo={logoUrl} onLogout={this.handleLogout} onToggleLoginModal={this.handleToggleLoginModal} scope={scope} username={username} />;
|
2019-02-03 17:23:33 +07:00
|
|
|
};
|
|
|
|
}
|