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