mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-05-31 14:11:58 +05:30
Create app namespace for all absolute requires of app modules. Move all packages under packages yarn workspace
This commit is contained in:
91
packages/app/pages/dev/ApplicationsListPage.tsx
Normal file
91
packages/app/pages/dev/ApplicationsListPage.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import React from 'react';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
fetchAvailableApps,
|
||||
resetApp,
|
||||
deleteApp,
|
||||
} from 'app/components/dev/apps/actions';
|
||||
import ApplicationsIndex from 'app/components/dev/apps/ApplicationsIndex';
|
||||
import { User } from 'app/components/user';
|
||||
import { OauthAppResponse } from 'app/services/api/oauth';
|
||||
import { RootState } from 'app/reducers';
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
user: User;
|
||||
apps: OauthAppResponse[];
|
||||
fetchAvailableApps: () => Promise<void>;
|
||||
deleteApp: (clientId: string) => Promise<void>;
|
||||
resetApp: (clientId: string, resetClientSecret: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
type State = {
|
||||
isLoading: boolean;
|
||||
forceUpdate: boolean;
|
||||
};
|
||||
|
||||
class ApplicationsListPage extends React.Component<Props, State> {
|
||||
state = {
|
||||
isLoading: false,
|
||||
forceUpdate: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
!this.props.user.isGuest && this.loadApplicationsList();
|
||||
}
|
||||
|
||||
componentDidUpdate({ user }: Props) {
|
||||
if (this.props.user !== user) {
|
||||
// eslint-disable-next-line react/no-did-update-set-state
|
||||
this.setState({ forceUpdate: true });
|
||||
this.loadApplicationsList();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user, apps, resetApp, deleteApp, location } = this.props;
|
||||
const { isLoading, forceUpdate } = this.state;
|
||||
const clientId = location.hash.substr(1) || null;
|
||||
|
||||
return (
|
||||
<ApplicationsIndex
|
||||
displayForGuest={user.isGuest}
|
||||
applications={forceUpdate ? [] : apps}
|
||||
isLoading={isLoading}
|
||||
deleteApp={deleteApp}
|
||||
resetApp={resetApp}
|
||||
clientId={clientId}
|
||||
resetClientId={this.resetClientId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
loadApplicationsList = async () => {
|
||||
this.setState({ isLoading: true });
|
||||
await this.props.fetchAvailableApps();
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
forceUpdate: false,
|
||||
});
|
||||
};
|
||||
|
||||
resetClientId = () => {
|
||||
const { history, location } = this.props;
|
||||
|
||||
if (location.hash) {
|
||||
history.push({ ...location, hash: '' });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: RootState) => ({
|
||||
user: state.user,
|
||||
apps: state.apps.available,
|
||||
}),
|
||||
{
|
||||
fetchAvailableApps,
|
||||
resetApp,
|
||||
deleteApp,
|
||||
},
|
||||
)(ApplicationsListPage);
|
69
packages/app/pages/dev/CreateNewApplicationPage.tsx
Normal file
69
packages/app/pages/dev/CreateNewApplicationPage.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React, { Component } from 'react';
|
||||
import { FormModel } from 'app/components/ui/form';
|
||||
import ApplicationForm from 'app/components/dev/apps/applicationForm/ApplicationForm';
|
||||
import oauth from 'app/services/api/oauth';
|
||||
import { browserHistory } from 'app/services/history';
|
||||
import { OauthAppResponse } from 'app/services/api/oauth';
|
||||
import { ApplicationType } from 'app/components/dev/apps';
|
||||
|
||||
const app: OauthAppResponse = {
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
countUsers: 0,
|
||||
createdAt: 0,
|
||||
type: 'application',
|
||||
name: '',
|
||||
description: '',
|
||||
websiteUrl: '',
|
||||
redirectUri: '',
|
||||
minecraftServerIp: '',
|
||||
};
|
||||
|
||||
interface State {
|
||||
type: ApplicationType | null;
|
||||
}
|
||||
|
||||
export default class CreateNewApplicationPage extends Component<{}, State> {
|
||||
state: State = {
|
||||
type: null,
|
||||
};
|
||||
|
||||
form: FormModel = new FormModel();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ApplicationForm
|
||||
form={this.form}
|
||||
displayTypeSwitcher
|
||||
onSubmit={this.onSubmit}
|
||||
type={this.state.type}
|
||||
setType={this.setType}
|
||||
app={app}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
onSubmit = async () => {
|
||||
const { form } = this;
|
||||
const { type } = this.state;
|
||||
|
||||
if (!type) {
|
||||
throw new Error('Form was submitted without specified type');
|
||||
}
|
||||
|
||||
form.beginLoading();
|
||||
const result = await oauth.create(type, form.serialize());
|
||||
form.endLoading();
|
||||
|
||||
this.goToMainPage(result.data.clientId);
|
||||
};
|
||||
|
||||
setType = (type: ApplicationType) => {
|
||||
this.setState({
|
||||
type,
|
||||
});
|
||||
};
|
||||
|
||||
goToMainPage = (hash?: string) =>
|
||||
browserHistory.push(`/dev/applications${hash ? `#${hash}` : ''}`);
|
||||
}
|
39
packages/app/pages/dev/DevPage.tsx
Normal file
39
packages/app/pages/dev/DevPage.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
import { FooterMenu } from 'app/components/footerMenu';
|
||||
import PrivateRoute from 'app/containers/PrivateRoute';
|
||||
|
||||
import styles from './dev.scss';
|
||||
import ApplicationsListPage from './ApplicationsListPage';
|
||||
import CreateNewApplicationPage from './CreateNewApplicationPage';
|
||||
import UpdateApplicationPage from './UpdateApplicationPage';
|
||||
|
||||
export default function DevPage() {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div data-e2e-content>
|
||||
<Switch>
|
||||
<Route
|
||||
path="/dev/applications"
|
||||
exact
|
||||
component={ApplicationsListPage}
|
||||
/>
|
||||
<PrivateRoute
|
||||
path="/dev/applications/new"
|
||||
exact
|
||||
component={CreateNewApplicationPage}
|
||||
/>
|
||||
<PrivateRoute
|
||||
path="/dev/applications/:clientId"
|
||||
component={UpdateApplicationPage}
|
||||
/>
|
||||
<Redirect to="/dev/applications" />
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
<div className={styles.footer}>
|
||||
<FooterMenu />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
120
packages/app/pages/dev/UpdateApplicationPage.tsx
Normal file
120
packages/app/pages/dev/UpdateApplicationPage.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import logger from 'app/services/logger';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
import { FormModel } from 'app/components/ui/form';
|
||||
import { browserHistory } from 'app/services/history';
|
||||
import oauth from 'app/services/api/oauth';
|
||||
import loader from 'app/services/loader';
|
||||
import PageNotFound from 'app/pages/404/PageNotFound';
|
||||
import {
|
||||
getApp,
|
||||
fetchApp as fetchAppAction,
|
||||
} from 'app/components/dev/apps/actions';
|
||||
import ApplicationForm from 'app/components/dev/apps/applicationForm/ApplicationForm';
|
||||
import { OauthAppResponse } from 'app/services/api/oauth';
|
||||
import { RootState } from 'app/reducers';
|
||||
|
||||
type OwnProps = RouteComponentProps<{
|
||||
clientId: string;
|
||||
}>;
|
||||
|
||||
interface Props extends OwnProps {
|
||||
app: OauthAppResponse | null;
|
||||
fetchApp: (app: string) => Promise<void>;
|
||||
}
|
||||
|
||||
class UpdateApplicationPage extends React.Component<
|
||||
Props,
|
||||
{
|
||||
isNotFound: boolean;
|
||||
}
|
||||
> {
|
||||
form: FormModel = new FormModel();
|
||||
|
||||
state = {
|
||||
isNotFound: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.app === null && this.fetchApp();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { app } = this.props;
|
||||
|
||||
if (this.state.isNotFound) {
|
||||
return <PageNotFound />;
|
||||
}
|
||||
|
||||
if (!app) {
|
||||
// we are loading
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ApplicationForm
|
||||
form={this.form}
|
||||
onSubmit={this.onSubmit}
|
||||
app={app}
|
||||
type={app.type}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
async fetchApp() {
|
||||
const { fetchApp, match } = this.props;
|
||||
|
||||
try {
|
||||
loader.show();
|
||||
await fetchApp(match.params.clientId);
|
||||
} catch (resp) {
|
||||
const { status } = resp.originalResponse;
|
||||
|
||||
if (status === 403) {
|
||||
this.goToMainPage();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === 404) {
|
||||
this.setState({
|
||||
isNotFound: true,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
logger.unexpected('Error fetching app', resp);
|
||||
} finally {
|
||||
loader.hide();
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit = async () => {
|
||||
const { form } = this;
|
||||
const { app } = this.props;
|
||||
|
||||
if (!app || !app.clientId) {
|
||||
throw new Error('Form has an invalid state');
|
||||
}
|
||||
|
||||
form.beginLoading();
|
||||
const result = await oauth.update(app.clientId, form.serialize());
|
||||
form.endLoading();
|
||||
|
||||
this.goToMainPage(result.data.clientId);
|
||||
};
|
||||
|
||||
goToMainPage = (hash?: string) =>
|
||||
browserHistory.push(`/dev/applications${hash ? `#${hash}` : ''}`);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: RootState, props: OwnProps) => ({
|
||||
app: getApp(state, props.match.params.clientId),
|
||||
}),
|
||||
{
|
||||
fetchApp: fetchAppAction,
|
||||
},
|
||||
)(UpdateApplicationPage);
|
18
packages/app/pages/dev/dev.scss
Normal file
18
packages/app/pages/dev/dev.scss
Normal file
@@ -0,0 +1,18 @@
|
||||
.container {
|
||||
padding: 55px 0 65px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.container {
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user