From d95573393206bc3931202d363bfb6c54974e0203 Mon Sep 17 00:00:00 2001 From: muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com> Date: Fri, 28 Oct 2022 07:37:55 +0530 Subject: Transform welcome component tree to TS (#715) --- src/components/auth/Welcome.jsx | 109 ---------------------------------- src/components/auth/Welcome.tsx | 118 +++++++++++++++++++++++++++++++++++++ src/components/ui/Link.js | 86 --------------------------- src/components/ui/Link.tsx | 73 +++++++++++++++++++++++ src/components/ui/button/index.tsx | 76 ++++++++++-------------- src/components/ui/input/index.tsx | 2 + 6 files changed, 223 insertions(+), 241 deletions(-) delete mode 100644 src/components/auth/Welcome.jsx create mode 100644 src/components/auth/Welcome.tsx delete mode 100644 src/components/ui/Link.js create mode 100644 src/components/ui/Link.tsx (limited to 'src/components') diff --git a/src/components/auth/Welcome.jsx b/src/components/auth/Welcome.jsx deleted file mode 100644 index 9e5d10126..000000000 --- a/src/components/auth/Welcome.jsx +++ /dev/null @@ -1,109 +0,0 @@ -/* eslint jsx-a11y/anchor-is-valid: 0 */ -import { Component } from 'react'; -import PropTypes from 'prop-types'; -import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; -import { defineMessages, injectIntl } from 'react-intl'; -import serverlessLogin from '../../helpers/serverless-helpers'; -import shuffleArray from '../../helpers/array-helpers'; -import { serverName } from '../../api/apiBase'; - -import Link from '../ui/Link'; -import { H1 } from '../ui/headline'; - -const messages = defineMessages({ - signupButton: { - id: 'welcome.signupButton', - defaultMessage: 'Create a free account', - }, - loginButton: { - id: 'welcome.loginButton', - defaultMessage: 'Login to your account', - }, - changeServerMessage: { - id: 'login.changeServerMessage', - defaultMessage: - 'You are using {serverNameParse} Server, do you want to switch?', - }, - changeServer: { - id: 'login.changeServer', - defaultMessage: 'Change here!', - }, - serverless: { - id: 'services.serverless', - defaultMessage: 'Use Ferdium without an Account', - }, -}); - -class Welcome extends Component { - static propTypes = { - loginRoute: PropTypes.string.isRequired, - signupRoute: PropTypes.string.isRequired, - changeServerRoute: PropTypes.string.isRequired, - recipes: MobxPropTypes.arrayOrObservableArray.isRequired, - actions: PropTypes.object.isRequired, - }; - - useLocalServer() { - serverlessLogin(this.props.actions); - } - - render() { - const { intl } = this.props; - const { loginRoute, signupRoute, changeServerRoute } = this.props; - let { recipes } = this.props; - recipes = shuffleArray(recipes); - recipes.length = 8 * 2; - - let serverNameParse = serverName(); - serverNameParse = - serverNameParse === 'Custom' ? 'a Custom' : serverNameParse; - - return ( -
-
- -
-
-

Ferdium

-
-
- - {intl.formatMessage(messages.signupButton)} - - - {intl.formatMessage(messages.loginButton)} - -
- - {intl.formatMessage(messages.changeServerMessage, { - serverNameParse, - })} - - - {intl.formatMessage(messages.changeServer)} - -
-
-
-
- - {intl.formatMessage(messages.serverless)} - -
-
- {recipes.map(recipe => ( -
- -
- ))} -
-
- ); - } -} - -export default injectIntl(inject('actions')(observer(Welcome))); diff --git a/src/components/auth/Welcome.tsx b/src/components/auth/Welcome.tsx new file mode 100644 index 000000000..1aa8da4d6 --- /dev/null +++ b/src/components/auth/Welcome.tsx @@ -0,0 +1,118 @@ +import { Component, ReactElement } from 'react'; +import { observer, inject } from 'mobx-react'; +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { noop } from 'lodash'; +import serverlessLogin from '../../helpers/serverless-helpers'; +import shuffleArray from '../../helpers/array-helpers'; +import { serverName } from '../../api/apiBase'; +import Link from '../ui/Link'; +import { H1 } from '../ui/headline'; +import { StoresProps } from '../../@types/ferdium-components.types'; +import RecipePreview from '../../models/RecipePreview'; + +const messages = defineMessages({ + signupButton: { + id: 'welcome.signupButton', + defaultMessage: 'Create a free account', + }, + loginButton: { + id: 'welcome.loginButton', + defaultMessage: 'Login to your account', + }, + changeServerMessage: { + id: 'login.changeServerMessage', + defaultMessage: + 'You are using {serverNameParse} Server, do you want to switch?', + }, + changeServer: { + id: 'login.changeServer', + defaultMessage: 'Change here!', + }, + serverless: { + id: 'services.serverless', + defaultMessage: 'Use Ferdium without an Account', + }, +}); + +interface IProps extends Partial, WrappedComponentProps { + loginRoute: string; + signupRoute: string; + changeServerRoute: string; + recipes: RecipePreview[]; +} + +@inject('actions') +@observer +class Welcome extends Component { + constructor(props: IProps) { + super(props); + } + + useLocalServer(): void { + serverlessLogin(this.props.actions); + } + + render(): ReactElement { + const { loginRoute, signupRoute, changeServerRoute, intl } = this.props; + let { recipes } = this.props; + recipes = shuffleArray(recipes); + recipes.length = 8 * 2; + + let serverNameParse = serverName(); + serverNameParse = + serverNameParse === 'Custom' ? 'a Custom' : serverNameParse; + + return ( +
+
+ +
+
+

Ferdium

+
+
+ + {intl.formatMessage(messages.signupButton)} + + + {intl.formatMessage(messages.loginButton)} + +
+ + {intl.formatMessage(messages.changeServerMessage, { + serverNameParse, + })} + + + {intl.formatMessage(messages.changeServer)} + +
+
+ +
+
+ {recipes.map(recipe => ( +
+ +
+ ))} +
+
+ ); + } +} + +export default injectIntl(Welcome); diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js deleted file mode 100644 index 714fc5a68..000000000 --- a/src/components/ui/Link.js +++ /dev/null @@ -1,86 +0,0 @@ -import { Component } from 'react'; -import PropTypes from 'prop-types'; -import { inject, observer } from 'mobx-react'; -import { RouterStore } from '@superwf/mobx-react-router'; -import classnames from 'classnames'; - -import { oneOrManyChildElements } from '../../prop-types'; -import matchRoute from '../../helpers/routing-helpers'; -import { openExternalUrl } from '../../helpers/url-helpers'; - -// Should this file be converted into the coding style similar to './toggle/index.tsx'? -// TODO: create container component for this component -class Link extends Component { - onClick(e) { - if (this.props.disabled) { - e.preventDefault(); - } else if (this.props.target === '_blank') { - e.preventDefault(); - openExternalUrl(this.props.to, true); - } - // Note: if neither of the above, then let the other onClick handlers process it - } - - render() { - const { - children, - stores, - to, - className, - activeClassName, - strictFilter, - style, - } = this.props; - const { router } = stores; - - let filter = `${to}(*action)`; - if (strictFilter) { - filter = `${to}`; - } - - const match = matchRoute(filter, router.location.pathname); - - const linkClasses = classnames({ - [`${className}`]: true, - [`${activeClassName}`]: match, - 'is-disabled': this.props.disabled, - }); - - return ( - this.onClick(e)} - > - {children} - - ); - } -} - -Link.propTypes = { - stores: PropTypes.shape({ - router: PropTypes.instanceOf(RouterStore).isRequired, - }).isRequired, - children: PropTypes.oneOfType([oneOrManyChildElements, PropTypes.string]) - .isRequired, - to: PropTypes.string.isRequired, - className: PropTypes.string, - activeClassName: PropTypes.string, - strictFilter: PropTypes.bool, - target: PropTypes.string, - style: PropTypes.object, - disabled: PropTypes.bool, -}; - -Link.defaultProps = { - className: '', - activeClassName: '', - strictFilter: false, - disabled: false, - target: '', - style: {}, -}; - -export default inject('stores')(observer(Link)); diff --git a/src/components/ui/Link.tsx b/src/components/ui/Link.tsx new file mode 100644 index 000000000..b5890ebd1 --- /dev/null +++ b/src/components/ui/Link.tsx @@ -0,0 +1,73 @@ +import { Component, CSSProperties, ReactNode, MouseEvent } from 'react'; +import { inject, observer } from 'mobx-react'; +import classnames from 'classnames'; +import matchRoute from '../../helpers/routing-helpers'; +import { openExternalUrl } from '../../helpers/url-helpers'; +import { StoresProps } from '../../@types/ferdium-components.types'; + +interface IProps extends Partial { + children: ReactNode; + to: string; + className?: string; + activeClassName?: string; + strictFilter?: boolean; + target?: string; + style?: CSSProperties; + disabled?: boolean; +} + +// TODO: create container component for this component +@inject('stores') +@observer +class Link extends Component { + constructor(props: IProps) { + super(props); + } + + onClick(e: MouseEvent): void { + const { disabled = false, target = '', to } = this.props; + if (disabled) { + e.preventDefault(); + } else if (target === '_blank') { + e.preventDefault(); + openExternalUrl(to, true); + } + // Note: if neither of the above, then let the other onClick handlers process it + } + + render() { + const { + children, + stores, + to, + className = '', + activeClassName = '', + strictFilter = false, + disabled = false, + style = {}, + } = this.props; + const { router } = stores!; + + const filter = strictFilter ? `${to}` : `${to}(*action)`; + const match = matchRoute(filter, router.location.pathname); + + const linkClasses = classnames({ + [`${className}`]: true, + [`${activeClassName}`]: match, + 'is-disabled': disabled, + }); + + return ( + this.onClick(e)} + > + {children} + + ); + } +} + +export default Link; diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx index a8bbfe730..c1e647bc0 100644 --- a/src/components/ui/button/index.tsx +++ b/src/components/ui/button/index.tsx @@ -1,10 +1,10 @@ import Icon from '@mdi/react'; import classnames from 'classnames'; import { Property } from 'csstype'; +import { noop } from 'lodash'; import { Component, MouseEvent } from 'react'; import withStyles, { WithStylesProps } from 'react-jss'; import Loader from 'react-loader'; - import { Theme } from '../../../themes'; import { IFormField } from '../typings/generic'; @@ -16,24 +16,6 @@ type ButtonType = | 'warning' | 'inverted'; -interface IProps extends IFormField, WithStylesProps { - className?: string; - label?: string; - disabled?: boolean; - id?: string; - type?: 'button' | 'reset' | 'submit' | undefined; - onClick: ( - event: MouseEvent | MouseEvent, - ) => void; - buttonType?: ButtonType; - loaded?: boolean; - busy?: boolean; - icon?: string; - href?: string; - target?: string; - htmlForm?: string; -} - let buttonTransition: string = 'none'; let loaderContainerTransition: string = 'none'; @@ -148,38 +130,38 @@ const styles = (theme: Theme) => ({ }, }); -class ButtonComponent extends Component { - customDefaultProps: { - disabled: boolean; - type: 'button' | 'reset' | 'submit' | undefined; - onClick: ( - event: MouseEvent | MouseEvent, - ) => void; - buttonType: ButtonType; - busy: boolean; - } = { - type: 'button', - disabled: false, - onClick: () => null, - buttonType: 'primary' as ButtonType, - busy: false, - }; +interface IProps extends IFormField, WithStylesProps { + className?: string; + label?: string; + disabled?: boolean; + id?: string; + type?: 'button' | 'reset' | 'submit' | undefined; + onClick: (event: MouseEvent) => void; + buttonType?: ButtonType; + loaded?: boolean; + busy?: boolean; + icon?: string; + href?: string; + target?: string; + htmlForm?: string; +} - state = { - busy: false, - }; +interface IState { + busy: boolean; +} +class ButtonComponent extends Component { constructor(props: IProps) { super(props); this.state = { - busy: props.busy || false, + busy: this.props.busy || false, }; } - static getDerivedStateFromProps(nextProps: IProps) { + static getDerivedStateFromProps(nextProps: IProps): IState { return { - busy: nextProps.busy, + busy: nextProps.busy || false, }; } @@ -188,27 +170,29 @@ class ButtonComponent extends Component { classes, className, // theme, - disabled, id, label, - type, - onClick, - buttonType, loaded, icon, href, target, htmlForm, - } = { ...this.customDefaultProps, ...this.props }; + type = 'button', + disabled = false, + onClick = noop, + buttonType = 'primary' as ButtonType, + } = this.props; const { busy } = this.state; let showLoader = false; + if (loaded) { showLoader = !loaded; console.warn( 'Ferdium Button prop `loaded` will be deprecated in the future. Please use `busy` instead', ); } + if (busy) { showLoader = busy; } diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx index b19bb4bc9..3bafc93e7 100644 --- a/src/components/ui/input/index.tsx +++ b/src/components/ui/input/index.tsx @@ -106,6 +106,7 @@ class InputComponent extends Component { showPasswordToggle = false, type = 'text', disabled = false, + readOnly, } = this.props; const { showPassword, passwordScore } = this.state; @@ -152,6 +153,7 @@ class InputComponent extends Component { min={min} max={max} step={step} + readOnly={readOnly} /> {suffix && {suffix}} {showPasswordToggle && ( -- cgit v1.2.3-54-g00ecf