diff --git a/packages/app/components/dev/apps/ApplicationsIndex.story.tsx b/packages/app/components/dev/apps/ApplicationsIndex.story.tsx index 096f9cb..48afc0a 100644 --- a/packages/app/components/dev/apps/ApplicationsIndex.story.tsx +++ b/packages/app/components/dev/apps/ApplicationsIndex.story.tsx @@ -3,7 +3,7 @@ import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import ApplicationsIndex from './ApplicationsIndex'; -import { TYPE_APPLICATION } from 'app/components/dev/apps'; +import { TYPE_WEB_APPLICATION } from 'app/components/dev/apps'; import { OauthAppResponse } from 'app/services/api/oauth'; import rootStyles from 'app/pages/root/root.scss'; @@ -18,8 +18,10 @@ export const DevLayout: ComponentType = ({ children }) => ( export const sampleApp: OauthAppResponse = { clientId: 'my-application', clientSecret: 'cL1eNtS3cRE7xNJqfWQdqrMRKURfW1ssP4kiX6JDW0_szM-n-q', - type: TYPE_APPLICATION, + type: TYPE_WEB_APPLICATION, name: 'My Application', + description: '', + redirectUri: '', websiteUrl: '', createdAt: 0, countUsers: 0, diff --git a/packages/app/components/dev/apps/ApplicationsIndex.tsx b/packages/app/components/dev/apps/ApplicationsIndex.tsx index b9444f9..8d8eb62 100644 --- a/packages/app/components/dev/apps/ApplicationsIndex.tsx +++ b/packages/app/components/dev/apps/ApplicationsIndex.tsx @@ -1,7 +1,8 @@ -import React from 'react'; -import clsx from 'clsx'; +import React, { FC, ReactElement } from 'react'; import { defineMessages, FormattedMessage as Message } from 'react-intl'; import { Helmet } from 'react-helmet-async'; +import clsx from 'clsx'; + import { LinkButton } from 'app/components/ui/form'; import { COLOR_GREEN, COLOR_BLUE } from 'app/components/ui'; import { ContactLink } from 'app/components/contact'; @@ -27,77 +28,83 @@ type Props = { resetApp: (clientId: string, resetClientSecret: boolean) => Promise; }; -export default class ApplicationsIndex extends React.Component { - render() { - return ( -
-
- - {(pageTitle: string) => ( -

- - {pageTitle} -

- )} -
-
-
- - - - ), - }} - /> -
-
- - - - ), - }} - /> -
-
+const ApplicationsIndex: FC = ({ + displayForGuest, + applications, + isLoading, + resetApp, + deleteApp, + clientId, + resetClientId, +}) => { + let content: ReactElement; - {this.getContent()} -
+ if (applications.length > 0) { + content = ( + ); + } else if (displayForGuest) { + content = ; + } else { + content = ; } - getContent() { - const { displayForGuest, applications, isLoading, resetApp, deleteApp, clientId, resetClientId } = this.props; + return ( +
+
+ + {(pageTitle: string) => ( +

+ + {pageTitle} +

+ )} +
+
+
+ + + + ), + }} + /> +
+
+ + + + ), + }} + /> +
+
- if (applications.length > 0) { - return ( - - ); - } + {content} +
+ ); +}; - if (displayForGuest) { - return ; - } - - return ; - } +interface LoaderProps { + noApps: boolean; } -function Loader({ noApps }: { noApps: boolean }) { +const Loader: FC = ({ noApps }) => { return (
@@ -130,9 +137,9 @@ function Loader({ noApps }: { noApps: boolean }) {
); -} +}; -function Guest() { +const Guest: FC = () => { return (
@@ -150,4 +157,6 @@ function Guest() {
); -} +}; + +export default ApplicationsIndex; diff --git a/packages/app/components/dev/apps/applicationForm/ApplicationForm.story.tsx b/packages/app/components/dev/apps/applicationForm/ApplicationForm.story.tsx index fb0065c..d9b4226 100644 --- a/packages/app/components/dev/apps/applicationForm/ApplicationForm.story.tsx +++ b/packages/app/components/dev/apps/applicationForm/ApplicationForm.story.tsx @@ -4,14 +4,19 @@ import { action } from '@storybook/addon-actions'; import { OauthAppResponse } from 'app/services/api/oauth'; import { FormModel } from 'app/components/ui/form'; -import { ApplicationType, TYPE_APPLICATION, TYPE_MINECRAFT_SERVER } from 'app/components/dev/apps'; +import { + ApplicationType, + TYPE_WEB_APPLICATION, + TYPE_DESKTOP_APPLICATION, + TYPE_MINECRAFT_SERVER, +} from 'app/components/dev/apps'; import ApplicationForm from './ApplicationForm'; import { DevLayout } from '../ApplicationsIndex.story'; const blankApp: OauthAppResponse = { clientId: '', clientSecret: '', - type: TYPE_APPLICATION, + type: TYPE_WEB_APPLICATION, name: '', websiteUrl: '', createdAt: 0, @@ -47,7 +52,17 @@ storiesOf('Components/Dev/Apps/ApplicationForm', module) form={new FormModel()} onSubmit={onSubmit} displayTypeSwitcher - type={TYPE_APPLICATION} + type={TYPE_WEB_APPLICATION} + setType={action('setType')} + app={blankApp} + /> + )) + .add('Create desktop application', () => ( + @@ -69,7 +84,7 @@ storiesOf('Components/Dev/Apps/ApplicationForm', module) ; const typeToForm: TypeToForm = { - [TYPE_APPLICATION]: { + [TYPE_WEB_APPLICATION]: { label: messages.website, component: WebsiteType, }, + [TYPE_DESKTOP_APPLICATION]: { + label: messages.desktopApplication, + component: DesktopApplicationType, + }, [TYPE_MINECRAFT_SERVER]: { label: messages.minecraftServer, component: MinecraftServerType, @@ -53,83 +63,22 @@ const typeToLabel: TypeToLabel = (Object.keys(typeToForm) as unknown as Array void; - onSubmit: (form: FormModel) => Promise; -}> { - static defaultProps = { - setType: () => {}, - }; + setType?: (type: ApplicationType) => void; + onSubmit?: (form: FormModel) => Promise; +} - render() { - const { type, setType, form, displayTypeSwitcher, app } = this.props; - const { component: FormComponent } = (type && typeToForm[type]) || {}; - const isUpdate = app.clientId !== ''; - - return ( -
-
- - -
-
- - {(pageTitle: string) => ( -

- - {pageTitle} -

- )} -
- - {displayTypeSwitcher && ( -
- -
- )} - - {FormComponent ? ( - - ) : ( -
-

- -

-
- )} -
-
- - {!!FormComponent && ( - - )} -
-
- ); - } - - onFormSubmit = async () => { - const { form } = this.props; +const ApplicationForm: FC = ({ app, form, displayTypeSwitcher, type, setType, onSubmit }) => { + const isUpdate = app.clientId !== ''; + const { component: FormComponent } = (type && typeToForm[type]) || {}; + const onFormSubmit = useCallback(async () => { try { - await this.props.onSubmit(form); + await onSubmit?.(form); } catch (resp) { if (resp.errors) { form.setErrors(resp.errors); @@ -139,5 +88,57 @@ export default class ApplicationForm extends React.Component<{ logger.unexpected(new Error('Error submitting application form'), resp); } - }; -} + }, [form, onSubmit]); + + return ( +
+
+ + +
+
+ + {(pageTitle: string) => ( +

+ + {pageTitle} +

+ )} +
+ + {displayTypeSwitcher && ( +
+ +
+ )} + + {FormComponent ? ( + + ) : ( +
+

+ +

+
+ )} +
+
+ + {!!FormComponent && ( + + )} +
+
+ ); +}; + +export default ApplicationForm; diff --git a/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx b/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx index 9520521..a817515 100644 --- a/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx +++ b/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx @@ -9,7 +9,7 @@ import styles from './applicationTypeSwitcher.scss'; interface Props { appTypes: Record; selectedType: ApplicationType | null; - setType: (type: ApplicationType) => void; + setType?: (type: ApplicationType) => void; } const ApplicationTypeSwitcher: ComponentType = ({ appTypes, selectedType, setType }) => ( @@ -17,7 +17,7 @@ const ApplicationTypeSwitcher: ComponentType = ({ appTypes, selectedType, {(Object.keys(appTypes) as unknown as Array).map((type) => (
setType(type)} + onChange={() => setType?.(type)} skin={SKIN_LIGHT} label={appTypes[type]} value={type} diff --git a/packages/app/components/dev/apps/applicationForm/DesktopApplicationType.tsx b/packages/app/components/dev/apps/applicationForm/DesktopApplicationType.tsx new file mode 100644 index 0000000..397b379 --- /dev/null +++ b/packages/app/components/dev/apps/applicationForm/DesktopApplicationType.tsx @@ -0,0 +1,59 @@ +import React, { FC } from 'react'; +import { FormattedMessage as Message } from 'react-intl'; + +import { Input, TextArea, FormModel } from 'app/components/ui/form'; +import { OauthDesktopAppResponse } from 'app/services/api/oauth'; +import { SKIN_LIGHT } from 'app/components/ui'; +import styles from 'app/components/profile/profileForm.scss'; + +import commonMessages from './commonMessages'; + +interface Props { + form: FormModel; + app: OauthDesktopAppResponse; +} + +const DesktopApplicationType: FC = ({ form, app }) => ( +
+
+ +
+ +
+

+ +

+
+
+