mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-12-25 06:30:00 +05:30
#22: refactor application forms
This commit is contained in:
parent
f6b925122f
commit
c454c58d5c
@ -1,26 +1,25 @@
|
||||
// @flow
|
||||
import type { ComponentType } from 'react';
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import type { OauthAppResponse } from 'services/api/oauth';
|
||||
import type { ApplicationType } from 'components/dev/apps';
|
||||
import React, { Component } from 'react';
|
||||
import { FormattedMessage as Message } from 'react-intl';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import { Form, FormModel, Button } from 'components/ui/form';
|
||||
import { BackButton } from 'components/profile/ProfileForm';
|
||||
import { COLOR_GREEN } from 'components/ui';
|
||||
|
||||
import { TYPE_APPLICATION, TYPE_MINECRAFT_SERVER } from 'components/dev/apps';
|
||||
import styles from 'components/profile/profileForm.scss';
|
||||
import logger from 'services/logger';
|
||||
import messages from './ApplicationForm.intl.json';
|
||||
|
||||
import ApplicationTypeSwitcher from './ApplicationTypeSwitcher';
|
||||
import WebsiteType from './WebsiteType';
|
||||
import MinecraftServerType from './MinecraftServerType';
|
||||
|
||||
import type { ComponentType } from 'react';
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import type { OauthAppResponse } from 'services/api/oauth';
|
||||
|
||||
const typeToForm: {
|
||||
[key: string]: {
|
||||
[key: ApplicationType]: {
|
||||
label: MessageDescriptor,
|
||||
component: ComponentType<any>,
|
||||
},
|
||||
@ -36,9 +35,10 @@ const typeToForm: {
|
||||
};
|
||||
|
||||
const typeToLabel: {
|
||||
[key: string]: MessageDescriptor,
|
||||
} = Object.keys(typeToForm).reduce((result, key: string) => {
|
||||
[key: ApplicationType]: MessageDescriptor,
|
||||
} = Object.keys(typeToForm).reduce((result, key: ApplicationType) => {
|
||||
result[key] = typeToForm[key].label;
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
@ -46,12 +46,10 @@ export default class ApplicationForm extends Component<{
|
||||
app: OauthAppResponse,
|
||||
form: FormModel,
|
||||
displayTypeSwitcher?: bool,
|
||||
type: ?string,
|
||||
setType: (string) => void,
|
||||
onSubmit: (FormModel) => Promise<*>,
|
||||
type: ?ApplicationType,
|
||||
setType: (ApplicationType) => void,
|
||||
onSubmit: (FormModel) => Promise<void>,
|
||||
}> {
|
||||
static displayName = 'ApplicationForm';
|
||||
|
||||
static defaultProps = {
|
||||
setType: () => {},
|
||||
};
|
||||
@ -87,15 +85,15 @@ export default class ApplicationForm extends Component<{
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!FormComponent && (
|
||||
{FormComponent ? (
|
||||
<FormComponent form={form} app={app} />
|
||||
) : (
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.toDisplayRegistrationFormChooseType} />
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{FormComponent && <FormComponent form={form} app={app} />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -123,7 +121,7 @@ export default class ApplicationForm extends Component<{
|
||||
return;
|
||||
}
|
||||
|
||||
throw resp;
|
||||
logger.unexpected(new Error('Error submitting application form'), resp);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,40 +1,32 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import type { ApplicationType } from 'components/dev/apps';
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import React from 'react';
|
||||
import { SKIN_LIGHT } from 'components/ui';
|
||||
import { Radio } from 'components/ui/form';
|
||||
|
||||
import styles from './applicationTypeSwitcher.scss';
|
||||
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
|
||||
export default class ApplicationTypeSwitcher extends Component<{
|
||||
export default function ApplicationTypeSwitcher({ setType, appTypes, selectedType }: {
|
||||
appTypes: {
|
||||
[key: string]: MessageDescriptor,
|
||||
[key: ApplicationType]: MessageDescriptor,
|
||||
},
|
||||
selectedType: ?string,
|
||||
setType: (type: string) => void,
|
||||
}> {
|
||||
render() {
|
||||
const { appTypes, selectedType } = this.props;
|
||||
|
||||
return (
|
||||
<div onChange={this.onChange}>
|
||||
{Object.keys(appTypes).map((type: string) => (
|
||||
<div className={styles.radioContainer} key={type}>
|
||||
<Radio
|
||||
skin={SKIN_LIGHT}
|
||||
label={appTypes[type]}
|
||||
value={type}
|
||||
checked={selectedType === type}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (event: {target: {value: string}}) => {
|
||||
this.props.setType(event.target.value);
|
||||
}
|
||||
selectedType: ?ApplicationType,
|
||||
setType: (type: ApplicationType) => void,
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
{Object.keys(appTypes).map((type: ApplicationType) => (
|
||||
<div className={styles.radioContainer} key={type}>
|
||||
<Radio
|
||||
onChange={() => setType(type)}
|
||||
skin={SKIN_LIGHT}
|
||||
label={appTypes[type]}
|
||||
value={type}
|
||||
checked={selectedType === type}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,59 +1,53 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import type {OauthAppResponse} from 'services/api/oauth';
|
||||
import React from 'react';
|
||||
import { FormattedMessage as Message } from 'react-intl';
|
||||
|
||||
import styles from 'components/profile/profileForm.scss';
|
||||
import messages from './ApplicationForm.intl.json';
|
||||
|
||||
import { Input, FormModel } from 'components/ui/form';
|
||||
import { SKIN_LIGHT } from 'components/ui';
|
||||
|
||||
import type {OauthAppResponse} from 'services/api/oauth';
|
||||
import messages from './ApplicationForm.intl.json';
|
||||
|
||||
export default class MinecraftServerType extends Component<{
|
||||
export default function MinecraftServerType({ form, app }: {
|
||||
form: FormModel,
|
||||
app: OauthAppResponse,
|
||||
}> {
|
||||
render() {
|
||||
const { form, app } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('name')}
|
||||
label={messages.serverName}
|
||||
defaultValue={app.name}
|
||||
required
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.ipAddressIsOptionButPreferable} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('minecraftServerIp')}
|
||||
label={messages.serverIp}
|
||||
defaultValue={app.minecraftServerIp}
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.youCanAlsoSpecifyServerSite} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('websiteUrl')}
|
||||
label={messages.websiteLink}
|
||||
defaultValue={app.websiteUrl}
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('name')}
|
||||
label={messages.serverName}
|
||||
defaultValue={app.name}
|
||||
required
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.ipAddressIsOptionButPreferable} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('minecraftServerIp')}
|
||||
label={messages.serverIp}
|
||||
defaultValue={app.minecraftServerIp}
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.youCanAlsoSpecifyServerSite} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('websiteUrl')}
|
||||
label={messages.websiteLink}
|
||||
defaultValue={app.websiteUrl}
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,74 +1,68 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import type { OauthAppResponse } from 'services/api/oauth';
|
||||
import React from 'react';
|
||||
import { FormattedMessage as Message } from 'react-intl';
|
||||
|
||||
import styles from 'components/profile/profileForm.scss';
|
||||
import messages from './ApplicationForm.intl.json';
|
||||
|
||||
import { Input, TextArea, FormModel } from 'components/ui/form';
|
||||
import { SKIN_LIGHT } from 'components/ui';
|
||||
import styles from 'components/profile/profileForm.scss';
|
||||
|
||||
import type { OauthAppResponse } from 'services/api/oauth';
|
||||
import messages from './ApplicationForm.intl.json';
|
||||
|
||||
export default class WebsiteType extends Component<{
|
||||
export default function WebsiteType({ form, app }: {
|
||||
form: FormModel,
|
||||
app: OauthAppResponse,
|
||||
}> {
|
||||
render() {
|
||||
const { form, app } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('name')}
|
||||
label={messages.applicationName}
|
||||
defaultValue={app.name}
|
||||
required
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.appDescriptionWillBeAlsoVisibleOnOauthPage} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<TextArea {...form.bindField('description')}
|
||||
label={messages.description}
|
||||
defaultValue={app.description}
|
||||
skin={SKIN_LIGHT}
|
||||
minRows={3}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.websiteLinkWillBeUsedAsAdditionalId} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('websiteUrl')}
|
||||
label={messages.websiteLink}
|
||||
defaultValue={app.websiteUrl}
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.redirectUriLimitsAllowableBaseAddress} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('redirectUri')}
|
||||
label={messages.redirectUri}
|
||||
defaultValue={app.redirectUri}
|
||||
required
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('name')}
|
||||
label={messages.applicationName}
|
||||
defaultValue={app.name}
|
||||
required
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.appDescriptionWillBeAlsoVisibleOnOauthPage} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<TextArea {...form.bindField('description')}
|
||||
label={messages.description}
|
||||
defaultValue={app.description}
|
||||
skin={SKIN_LIGHT}
|
||||
minRows={3}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.websiteLinkWillBeUsedAsAdditionalId} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('websiteUrl')}
|
||||
label={messages.websiteLink}
|
||||
defaultValue={app.websiteUrl}
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.redirectUriLimitsAllowableBaseAddress} />
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('redirectUri')}
|
||||
label={messages.redirectUri}
|
||||
defaultValue={app.redirectUri}
|
||||
required
|
||||
skin={SKIN_LIGHT}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// @flow
|
||||
|
||||
export const TYPE_APPLICATION = 'application';
|
||||
export const TYPE_MINECRAFT_SERVER = 'minecraft-server';
|
||||
export type ApplicationType = 'application' | 'minecraft-server';
|
||||
export const TYPE_APPLICATION: 'application' = 'application';
|
||||
export const TYPE_MINECRAFT_SERVER: 'minecraft-server' = 'minecraft-server';
|
||||
|
@ -1,13 +1,11 @@
|
||||
// @flow
|
||||
import type { Node } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { Motion, spring } from 'react-motion';
|
||||
|
||||
import MeasureHeight from 'components/MeasureHeight';
|
||||
|
||||
import styles from './collapse.scss';
|
||||
|
||||
import type { Node } from 'react';
|
||||
|
||||
type Props = {
|
||||
isOpened?: bool,
|
||||
children: Node,
|
||||
|
@ -44,10 +44,14 @@ export default class Checkbox extends FormInputComponent<{
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.el.checked ? 1 : 0;
|
||||
const { el } = this;
|
||||
|
||||
return el && el.checked ? 1 : 0;
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.el.focus();
|
||||
const { el } = this;
|
||||
|
||||
el && el.focus();
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,16 @@ export default class FormComponent<P, S = void> extends Component<P, S> {
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
formatMessage(message: string | MessageDescriptor) {
|
||||
if (message && message.id && this.context && this.context.intl) {
|
||||
message = this.context.intl.formatMessage(message);
|
||||
formatMessage(message: string | MessageDescriptor): string {
|
||||
if (message && message.id) {
|
||||
if (this.context && this.context.intl) {
|
||||
message = this.context.intl.formatMessage(message);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
return ((message: any): string);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,22 +112,26 @@ export default class Input extends FormInputComponent<{
|
||||
}
|
||||
|
||||
focus() {
|
||||
if (!this.el) {
|
||||
const el = this.el;
|
||||
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.el.focus();
|
||||
setTimeout(this.el.focus.bind(this.el), 10);
|
||||
el.focus();
|
||||
setTimeout(el.focus.bind(el), 10);
|
||||
}
|
||||
|
||||
onCopy = async () => {
|
||||
if (!this.getValue()) {
|
||||
const value = this.getValue();
|
||||
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
clearTimeout(copiedStateTimeout);
|
||||
await copy(this.getValue());
|
||||
await copy(value);
|
||||
this.setState({wasCopied: true});
|
||||
copiedStateTimeout = setTimeout(() => this.setState({wasCopied: false}), 2000);
|
||||
} catch (err) {
|
||||
|
@ -44,10 +44,14 @@ export default class Radio extends FormInputComponent<{
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.el.checked ? 1 : 0;
|
||||
const { el } = this;
|
||||
|
||||
return el && el.checked ? 1 : 0;
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.el.focus();
|
||||
const { el } = this;
|
||||
|
||||
el && el.focus();
|
||||
}
|
||||
}
|
||||
|
@ -74,11 +74,17 @@ export default class TextArea extends FormInputComponent<{
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.el.value;
|
||||
return this.el && this.el.value;
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.el.focus();
|
||||
setTimeout(this.el.focus.bind(this.el), 10);
|
||||
const { el } = this;
|
||||
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
el.focus();
|
||||
setTimeout(el.focus.bind(el), 10);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,18 @@
|
||||
// @flow
|
||||
import type {OauthAppResponse} from 'services/api/oauth';
|
||||
import type { ApplicationType } from 'components/dev/apps';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { FormModel } from 'components/ui/form';
|
||||
|
||||
import ApplicationForm from 'components/dev/apps/applicationForm/ApplicationForm';
|
||||
|
||||
import oauth from 'services/api/oauth';
|
||||
import { browserHistory } from 'services/history';
|
||||
|
||||
import type {OauthAppResponse} from 'services/api/oauth';
|
||||
|
||||
const app: OauthAppResponse = {
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
countUsers: 0,
|
||||
createdAt: 0,
|
||||
type: '',
|
||||
type: 'application',
|
||||
name: '',
|
||||
description: '',
|
||||
websiteUrl: '',
|
||||
@ -24,15 +21,13 @@ const app: OauthAppResponse = {
|
||||
};
|
||||
|
||||
export default class CreateNewApplicationPage extends Component<{}, {
|
||||
type: ?string,
|
||||
type: ?ApplicationType,
|
||||
}> {
|
||||
static displayName = 'CreateNewApplicationPage';
|
||||
|
||||
state = {
|
||||
type: null,
|
||||
};
|
||||
|
||||
form = new FormModel();
|
||||
form: FormModel = new FormModel();
|
||||
|
||||
render() {
|
||||
return (
|
||||
@ -50,6 +45,7 @@ export default class CreateNewApplicationPage extends Component<{}, {
|
||||
onSubmit = async () => {
|
||||
const { form } = this;
|
||||
const { type } = this.state;
|
||||
|
||||
if (!type) {
|
||||
throw new Error('Form was submitted without specified type');
|
||||
}
|
||||
@ -61,7 +57,7 @@ export default class CreateNewApplicationPage extends Component<{}, {
|
||||
this.goToMainPage(result.data.clientId);
|
||||
};
|
||||
|
||||
setType = (type: string) => {
|
||||
setType = (type: ApplicationType) => {
|
||||
this.setState({
|
||||
type,
|
||||
});
|
||||
|
@ -1,17 +1,15 @@
|
||||
// @flow
|
||||
import type { OauthAppResponse } from 'services/api/oauth';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import logger from 'services/logger';
|
||||
import { FormModel } from 'components/ui/form';
|
||||
|
||||
import ApplicationForm from 'components/dev/apps/applicationForm/ApplicationForm';
|
||||
|
||||
import { browserHistory } from 'services/history';
|
||||
import oauth from 'services/api/oauth';
|
||||
import loader from 'services/loader';
|
||||
|
||||
import PageNotFound from 'pages/404/PageNotFound';
|
||||
|
||||
import type { OauthAppResponse } from 'services/api/oauth';
|
||||
import { getApp, fetchApp } from 'components/dev/apps/actions';
|
||||
import ApplicationForm from 'components/dev/apps/applicationForm/ApplicationForm';
|
||||
|
||||
type MatchType = {
|
||||
match: {
|
||||
@ -23,24 +21,23 @@ type MatchType = {
|
||||
|
||||
class UpdateApplicationPage extends Component<{
|
||||
app: ?OauthAppResponse,
|
||||
fetchApp: (string) => Promise<*>,
|
||||
fetchApp: (string) => Promise<void>,
|
||||
} & MatchType, {
|
||||
isNotFound: bool,
|
||||
}> {
|
||||
static displayName = 'UpdateApplicationPage';
|
||||
|
||||
form = new FormModel();
|
||||
form: FormModel = new FormModel();
|
||||
|
||||
state = {
|
||||
isNotFound: false,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.props.app === null && this.fetchApp();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { app } = this.props;
|
||||
|
||||
if (this.state.isNotFound) {
|
||||
return (
|
||||
<PageNotFound />
|
||||
@ -48,7 +45,8 @@ class UpdateApplicationPage extends Component<{
|
||||
}
|
||||
|
||||
if (!app) {
|
||||
return (<div/>);
|
||||
// we are loading
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -63,11 +61,13 @@ class UpdateApplicationPage extends Component<{
|
||||
|
||||
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;
|
||||
@ -80,7 +80,7 @@ class UpdateApplicationPage extends Component<{
|
||||
return;
|
||||
}
|
||||
|
||||
throw resp;
|
||||
logger.unexpected('Error fetching app', resp);
|
||||
} finally {
|
||||
loader.hide();
|
||||
}
|
||||
@ -89,6 +89,7 @@ class UpdateApplicationPage extends Component<{
|
||||
onSubmit = async () => {
|
||||
const { form } = this;
|
||||
const { app } = this.props;
|
||||
|
||||
if (!app || !app.clientId) {
|
||||
throw new Error('Form has an invalid state');
|
||||
}
|
||||
@ -103,9 +104,6 @@ class UpdateApplicationPage extends Component<{
|
||||
goToMainPage = (hash?: string) => browserHistory.push(`/dev/applications${hash ? `#${hash}` : ''}`);
|
||||
}
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { getApp, fetchApp } from 'components/dev/apps/actions';
|
||||
|
||||
export default connect((state, props: MatchType) => ({
|
||||
app: getApp(state, props.match.params.clientId),
|
||||
}), {
|
||||
|
@ -1,12 +1,13 @@
|
||||
// @flow
|
||||
/* eslint camelcase: off */
|
||||
import type { Resp } from 'services/request';
|
||||
import type { ApplicationType } from 'components/dev/apps';
|
||||
import request from 'services/request';
|
||||
|
||||
export type OauthAppResponse = {
|
||||
clientId: string,
|
||||
clientSecret: string,
|
||||
type: string,
|
||||
type: ApplicationType,
|
||||
name: string,
|
||||
websiteUrl: string,
|
||||
createdAt: number,
|
||||
|
@ -55,6 +55,13 @@ class Logger {
|
||||
});
|
||||
}
|
||||
|
||||
unexpected(message: string | Error, previous: mixed) {
|
||||
// TODO: check whether previous was already handled. Cover with tests
|
||||
this.error(message, {
|
||||
error: previous
|
||||
});
|
||||
}
|
||||
|
||||
error(message: string | Error, context: Object) {
|
||||
log('error', message, context);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user