diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx index 275485f..fe1c4cf 100644 --- a/src/components/Footer/Footer.tsx +++ b/src/components/Footer/Footer.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { Wrapper, Left, Right, Earth, Flags, Love, Flag, Logo, Inner, ToolTip } from './styles'; import { goToVerdaccioWebsite } from '../../utils/windows'; -const renderTooltip = () => ( +const renderTooltip = (): JSX.Element => ( @@ -22,7 +22,7 @@ const ON_LABEL = 'on'; const HEARTH_EMOJI = '♥'; // @ts-ignore -const renderRight = (version = window.VERDACCIO_VERSION) => { +const renderRight = (version = window.VERDACCIO_VERSION): JSX.Element => { return ( {POWERED_LABEL} @@ -32,7 +32,7 @@ const renderRight = (version = window.VERDACCIO_VERSION) => { ); }; -const renderLeft = () => ( +const renderLeft = (): JSX.Element => ( {MADEWITH_LABEL} {HEARTH_EMOJI} diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index 830bd13..ba49923 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -67,7 +67,7 @@ const Icon: React.FC = ({ className, name, size = 'sm', img = false, poin // @ts-ignore const title = capitalize(name); return img ? ( - + {title} ) : ( diff --git a/src/components/Icon/styles.ts b/src/components/Icon/styles.ts index ebb44c9..01249cc 100644 --- a/src/components/Icon/styles.ts +++ b/src/components/Icon/styles.ts @@ -1,6 +1,6 @@ import styled, { css } from 'react-emotion'; -const getSize = (size?: 'md' | 'sm') => { +const getSize = (size: 'md' | 'sm' | string): string => { switch (size) { case 'md': return ` @@ -15,7 +15,7 @@ const getSize = (size?: 'md' | 'sm') => { } }; -const commonStyle = ({ size = 'sm', pointer, modifiers }: any) => css` +const commonStyle = ({ size = 'sm' as 'md' | 'sm' | string, pointer, modifiers = null }): string => css` && { display: inline-block; cursor: ${pointer ? 'pointer' : 'default'}; diff --git a/src/components/Install/Install.tsx b/src/components/Install/Install.tsx index 3b72c67..ee8ed59 100644 --- a/src/components/Install/Install.tsx +++ b/src/components/Install/Install.tsx @@ -3,7 +3,7 @@ import ListItemText from '@material-ui/core/ListItemText'; import React, { Component } from 'react'; // @ts-ignore -import { DetailContextConsumer } from '../../pages/version/Version'; +import { DetailContextConsumer, VersionPageConsumerProps } from '../../pages/version/Version'; import CopyToClipBoard from '../CopyToClipBoard'; // logos of package managers @@ -14,17 +14,17 @@ import yarn from './img/yarn.svg'; import { Heading, InstallItem, PackageMangerAvatar } from './styles'; class Install extends Component { - public render() { + public render(): JSX.Element { return ( - {(context: any) => { + {(context: Partial) => { return context && context.packageName && this.renderCopyCLI(context); }} ); } - public renderCopyCLI = ({ packageName }: { packageName: string }) => { + public renderCopyCLI = ({ packageName = '' }: Partial) => { return ( <> {'Installation'}}>{this.renderListItems(packageName)} diff --git a/src/components/Login/Login.test.tsx b/src/components/Login/Login.test.tsx index 03a9fce..aaf3e42 100644 --- a/src/components/Login/Login.test.tsx +++ b/src/components/Login/Login.test.tsx @@ -89,7 +89,7 @@ describe('', () => { const instance = wrapper.instance(); instance.submitCredentials = jest.fn(); - const { validateCredentials, setCredentials, submitCredentials } = instance; + const { handleValidateCredentials, setCredentials, submitCredentials } = instance; expect(setCredentials('username', eventUsername)).toBeUndefined(); expect(wrapper.state('form').username.value).toEqual('xyz'); @@ -97,7 +97,7 @@ describe('', () => { expect(setCredentials('password', eventPassword)).toBeUndefined(); expect(wrapper.state('form').password.value).toEqual('1234'); - validateCredentials(event); + handleValidateCredentials(event); expect(event.preventDefault).toHaveBeenCalled(); expect(wrapper.state('form').username.pristine).toEqual(false); expect(wrapper.state('form').password.pristine).toEqual(false); diff --git a/src/components/Login/Login.tsx b/src/components/Login/Login.tsx index d2806bf..d8c0d67 100644 --- a/src/components/Login/Login.tsx +++ b/src/components/Login/Login.tsx @@ -1,5 +1,4 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import Button from '@material-ui/core/Button'; import DialogTitle from '@material-ui/core/DialogTitle'; import Dialog from '@material-ui/core/Dialog'; @@ -15,21 +14,34 @@ import FormHelperText from '@material-ui/core/FormHelperText'; // @ts-ignore import classes from './login.scss'; -export default class LoginModal extends Component { - static propTypes = { - visibility: PropTypes.bool, - error: PropTypes.object, - onCancel: PropTypes.func, - onSubmit: PropTypes.func, - }; +interface FormFields { + required: boolean; + pristine: boolean; + helperText: string; + value: string; +} +interface FormError { + type: string; + title: string; + description: string; +} - static defaultProps = { - error: {}, - onCancel: () => {}, - onSubmit: () => {}, - visibility: true, - }; +interface LoginModalProps { + visibility: boolean; + error: Partial; + onCancel: () => void; + onSubmit: (username: string, password: string) => void; +} +interface LoginModalState { + form: { + username: Partial; + password: Partial; + }; + error: FormError; +} + +export default class LoginModal extends Component, LoginModalState> { constructor(props) { super(props); this.state = { @@ -51,11 +63,28 @@ export default class LoginModal extends Component { }; } + public render(): JSX.Element { + const { visibility, onCancel, error } = this.props as LoginModalProps; + return ( + +
+ {'Login'} + + {this.renderLoginError(error)} + {this.renderNameField()} + {this.renderPasswordField()} + + {this.renderActions()} +
+
+ ); + } + /** * set login modal's username and password to current state * Required to login */ - setCredentials = (name, e) => { + public setCredentials = (name, e) => { const { form } = this.state; this.setState({ form: { @@ -69,15 +98,15 @@ export default class LoginModal extends Component { }); }; - setUsername = event => { + public handleUsernameChange = event => { this.setCredentials('username', event); }; - setPassword = event => { + public handlePasswordChange = event => { this.setCredentials('password', event); }; - validateCredentials = event => { + public handleValidateCredentials = event => { const { form } = this.state; // prevents default submit behavior event.preventDefault(); @@ -89,7 +118,7 @@ export default class LoginModal extends Component { ...acc, ...{ [key]: { ...form[key], pristine: false } }, }), - {} + { username: {}, password: {} } ), }, () => { @@ -100,10 +129,14 @@ export default class LoginModal extends Component { ); }; - submitCredentials = async () => { + public submitCredentials = async () => { const { form } = this.state; + const username = (form.username && form.username.value) || ''; + const password = (form.password && form.password.value) || ''; const { onSubmit } = this.props; - await onSubmit(form.username.value, form.password.value); + if (onSubmit) { + await onSubmit(username, password); + } // let's wait for API response and then set // username and password filed to empty state this.setState({ @@ -112,12 +145,12 @@ export default class LoginModal extends Component { ...acc, ...{ [key]: { ...form[key], value: '', pristine: true } }, }), - {} + { username: {}, password: {} } ), }); }; - renderErrorMessage(title, description) { + private renderErrorMessage(title, description): JSX.Element { return (
@@ -128,7 +161,7 @@ export default class LoginModal extends Component { ); } - renderMessage(title, description) { + private renderMessage(title, description): JSX.Element { return (
@@ -137,37 +170,37 @@ export default class LoginModal extends Component { ); } - renderLoginError({ type, title, description }) { + private renderLoginError({ type, title, description }: Partial): JSX.Element | false { return type === 'error' && ; } - renderNameField = () => { + private renderNameField = () => { const { form: { username }, } = this.state; return ( {'Username'} - + {!username.value && !username.pristine && {username.helperText}} ); }; - renderPasswordField = () => { + private renderPasswordField = () => { const { form: { password }, } = this.state; return ( {'Password'} - + {!password.value && !password.pristine && {password.helperText}} ); }; - renderActions = () => { + private renderActions = () => { const { form: { username, password }, } = this.state; @@ -183,21 +216,4 @@ export default class LoginModal extends Component { ); }; - - render() { - const { visibility, onCancel, error } = this.props; - return ( - -
- {'Login'} - - {this.renderLoginError(error)} - {this.renderNameField()} - {this.renderPasswordField()} - - {this.renderActions()} -
-
- ); - } } diff --git a/src/components/Spinner/styles.ts b/src/components/Spinner/styles.ts index 95585e1..b86364a 100644 --- a/src/components/Spinner/styles.ts +++ b/src/components/Spinner/styles.ts @@ -1,5 +1,5 @@ import CircularProgress from '@material-ui/core/CircularProgress'; -import styled, { css, Themed } from 'react-emotion'; +import styled, { css } from 'react-emotion'; import colors from '../../utils/styles/colors'; @@ -8,7 +8,7 @@ export const Wrapper = styled('div')` display: flex; align-items: center; justify-content: center; - ${(props): Themed => + ${props => // @ts-ignore props.centered && css`