From 0f85376127ed9faafaabe13cdf3c81075e8c607a Mon Sep 17 00:00:00 2001 From: Muhamed <> Date: Wed, 26 Oct 2022 02:45:26 +0530 Subject: [PATCH 1/2] chore: apply read only prop in input component --- src/components/ui/input/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx index b19bb4bc99..3bafc93e7d 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 && ( From 9c9bd86ca7c99c9fb9a097fb759ab2d73243129a Mon Sep 17 00:00:00 2001 From: Muhamed <> Date: Fri, 28 Oct 2022 02:17:47 +0530 Subject: [PATCH 2/2] chore: transform welcome component tree to TS --- .../auth/{Welcome.jsx => Welcome.tsx} | 61 +++++++------ src/components/ui/Link.js | 86 ------------------- src/components/ui/Link.tsx | 73 ++++++++++++++++ src/components/ui/button/index.tsx | 76 +++++++--------- src/containers/auth/WelcomeScreen.tsx | 15 +++- src/helpers/array-helpers.ts | 4 +- 6 files changed, 151 insertions(+), 164 deletions(-) rename src/components/auth/{Welcome.jsx => Welcome.tsx} (66%) delete mode 100644 src/components/ui/Link.js create mode 100644 src/components/ui/Link.tsx diff --git a/src/components/auth/Welcome.jsx b/src/components/auth/Welcome.tsx similarity index 66% rename from src/components/auth/Welcome.jsx rename to src/components/auth/Welcome.tsx index 9e5d10126b..1aa8da4d66 100644 --- a/src/components/auth/Welcome.jsx +++ b/src/components/auth/Welcome.tsx @@ -1,14 +1,14 @@ -/* 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 { 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: { @@ -34,24 +34,28 @@ const messages = defineMessages({ }, }); -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, - }; +interface IProps extends Partial, WrappedComponentProps { + loginRoute: string; + signupRoute: string; + changeServerRoute: string; + recipes: RecipePreview[]; +} - useLocalServer() { +@inject('actions') +@observer +class Welcome extends Component { + constructor(props: IProps) { + super(props); + } + + useLocalServer(): void { serverlessLogin(this.props.actions); } - render() { - const { intl } = this.props; - const { loginRoute, signupRoute, changeServerRoute } = this.props; + render(): ReactElement { + const { loginRoute, signupRoute, changeServerRoute, intl } = this.props; let { recipes } = this.props; - recipes = shuffleArray(recipes); + recipes = shuffleArray(recipes); recipes.length = 8 * 2; let serverNameParse = serverName(); @@ -87,17 +91,22 @@ class Welcome extends Component { {intl.formatMessage(messages.changeServer)} -
-
-
- +
+
{recipes.map(recipe => (
- +
))}
@@ -106,4 +115,4 @@ class Welcome extends Component { } } -export default injectIntl(inject('actions')(observer(Welcome))); +export default injectIntl(Welcome); diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js deleted file mode 100644 index 714fc5a68d..0000000000 --- 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 0000000000..b5890ebd1b --- /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 a8bbfe7306..c1e647bc0d 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/containers/auth/WelcomeScreen.tsx b/src/containers/auth/WelcomeScreen.tsx index c033191799..561eef236d 100644 --- a/src/containers/auth/WelcomeScreen.tsx +++ b/src/containers/auth/WelcomeScreen.tsx @@ -1,12 +1,19 @@ import { Component, ReactElement } from 'react'; import { inject, observer } from 'mobx-react'; - import { StoresProps } from '../../@types/ferdium-components.types'; import Welcome from '../../components/auth/Welcome'; -class WelcomeScreen extends Component { +interface IProps extends Partial {} + +@inject('stores', 'actions') +@observer +class WelcomeScreen extends Component { + constructor(props: IProps) { + super(props); + } + render(): ReactElement { - const { user, recipePreviews } = this.props.stores; + const { user, recipePreviews } = this.props.stores!; return ( { } } -export default inject('stores', 'actions')(observer(WelcomeScreen)); +export default WelcomeScreen; diff --git a/src/helpers/array-helpers.ts b/src/helpers/array-helpers.ts index 33be12fa77..ffb584eab5 100644 --- a/src/helpers/array-helpers.ts +++ b/src/helpers/array-helpers.ts @@ -1,6 +1,6 @@ -export default function shuffleArray(arr: any[]): any[] { +export default function shuffleArray(arr: T[]): T[] { return arr - .map(a => [Math.random(), a]) + .map(a => [Math.random(), a] as [number, T]) .sort((a, b) => a[0] - b[0]) .map(a => a[1]); }