diff --git a/.eslintrc.js b/.eslintrc.js index ac30525..a8e623e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -69,7 +69,6 @@ module.exports = { 'error', { min: 2, exceptions: ['x', 'y', 'i', 'k', 'l', 'm', 'n', '$', '_'] }, ], - 'require-atomic-updates': 'warn', 'guard-for-in': ['error'], 'no-var': ['error'], 'prefer-const': ['error'], diff --git a/.prettierignore b/.prettierignore index 4c2ad32..d8be4ed 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,5 @@ cache *.png *.gif *.svg +*.hbs +.gitlab-ci.yml diff --git a/.storybook/config.tsx b/.storybook/config.tsx index e9eea65..85daf2f 100644 --- a/.storybook/config.tsx +++ b/.storybook/config.tsx @@ -5,7 +5,7 @@ import storyDecorator from './storyDecorator'; const req = require.context('../packages/app', true, /\.story\.[tj]sx?$/); function loadStories() { - req.keys().forEach(filename => req(filename)); + req.keys().forEach((filename) => req(filename)); } addDecorator(storyDecorator); diff --git a/.storybook/storyDecorator.tsx b/.storybook/storyDecorator.tsx index 5158493..5431c6a 100644 --- a/.storybook/storyDecorator.tsx +++ b/.storybook/storyDecorator.tsx @@ -9,7 +9,7 @@ import { IntlDecorator } from './decorators'; const store = storeFactory(); -export default (story => { +export default ((story) => { const channel = addons.getChannel(); return ( diff --git a/package.json b/package.json index f2eb1c2..33b5403 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ "test:watch": "yarn test --watch", "lint": "eslint --ext js,ts,tsx --fix .", "lint:check": "eslint --ext js,ts,tsx --quiet .", - "prettier": "prettier --write \"{packages/**/*,tests-e2e/**/*,jest/**/*,config/**/*,*}.{js,ts,tsx,json,md,scss,css}\"", - "prettier:check": "prettier --check \"{packages/**/*,tests-e2e/**/*,jest/**/*,config/**/*,*}.{js,ts,tsx,json,md,scss,css}\"", + "prettier": "prettier --write .", + "prettier:check": "prettier --check .", "ts:check": "tsc", "ci:check": "yarn lint:check && yarn ts:check && yarn test", "analyze": "yarn run clean && yarn run build:webpack --analyze", @@ -154,7 +154,7 @@ "postcss-import": "^12.0.1", "postcss-loader": "^3.0.0", "postcss-scss": "^2.1.1", - "prettier": "^1.19.1", + "prettier": "^2.0.5", "raw-loader": "^4.0.1", "react-test-renderer": "^16.13.1", "sass-loader": "^8.0.2", diff --git a/packages/app/components/accounts/AccountSwitcher.tsx b/packages/app/components/accounts/AccountSwitcher.tsx index a5405ce..09675a0 100644 --- a/packages/app/components/accounts/AccountSwitcher.tsx +++ b/packages/app/components/accounts/AccountSwitcher.tsx @@ -57,7 +57,9 @@ export class AccountSwitcher extends React.Component { let { available } = accounts; if (highlightActiveAccount) { - available = available.filter(account => account.id !== activeAccount.id); + available = available.filter( + (account) => account.id !== activeAccount.id, + ); } return ( @@ -152,7 +154,7 @@ export class AccountSwitcher extends React.Component { className={styles.addAccount} label={ - {message => ( + {(message) => (
{message} @@ -178,7 +180,7 @@ export class AccountSwitcher extends React.Component { .then(() => this.props.onSwitch(account)) // we won't sent any logs to sentry, because an error should be already // handled by external logic - .catch(error => console.warn('Error switching account', { error })) + .catch((error) => console.warn('Error switching account', { error })) .finally(() => loader.hide()); }; diff --git a/packages/app/components/accounts/actions.test.ts b/packages/app/components/accounts/actions.test.ts index 185f62a..63a9891 100644 --- a/packages/app/components/accounts/actions.test.ts +++ b/packages/app/components/accounts/actions.test.ts @@ -48,7 +48,7 @@ describe('components/accounts/actions', () => { beforeEach(() => { dispatch = sinon - .spy(arg => (typeof arg === 'function' ? arg(dispatch, getState) : arg)) + .spy((arg) => (typeof arg === 'function' ? arg(dispatch, getState) : arg)) .named('store.dispatch'); getState = sinon.stub().named('store.getState'); @@ -146,7 +146,7 @@ describe('components/accounts/actions', () => { )); it('resolves with account', () => - authenticate(account)(dispatch, getState, undefined).then(resp => + authenticate(account)(dispatch, getState, undefined).then((resp) => expect(resp, 'to equal', account), )); diff --git a/packages/app/components/accounts/actions.ts b/packages/app/components/accounts/actions.ts index 5962d58..17d7b43 100644 --- a/packages/app/components/accounts/actions.ts +++ b/packages/app/components/accounts/actions.ts @@ -53,7 +53,7 @@ export function authenticate( } const knownAccount = getState().accounts.available.find( - item => item.id === accountId, + (item) => item.id === accountId, ); if (knownAccount) { @@ -246,10 +246,10 @@ export function requestNewToken(): ThunkAction> { } return requestToken(refreshToken) - .then(token => { + .then((token) => { dispatch(updateToken(token)); }) - .catch(resp => { + .catch((resp) => { // all the logic to get the valid token was failed, // looks like we have some problems with token // lets redirect to login page @@ -313,7 +313,7 @@ export function logoutAll(): ThunkAction> { accounts: { available }, } = getState(); - available.forEach(account => + available.forEach((account) => logout(account.token).catch(() => { // we don't care }), @@ -345,10 +345,12 @@ export function logoutStrangers(): ThunkAction> { !refreshToken && !sessionStorage.getItem(`stranger${id}`); if (available.some(isStranger)) { - const accountToReplace = available.find(account => !isStranger(account)); + const accountToReplace = available.find( + (account) => !isStranger(account), + ); if (accountToReplace) { - available.filter(isStranger).forEach(account => { + available.filter(isStranger).forEach((account) => { dispatch(remove(account)); logout(account.token); }); diff --git a/packages/app/components/accounts/reducer.ts b/packages/app/components/accounts/reducer.ts index 389f79e..f34799a 100644 --- a/packages/app/components/accounts/reducer.ts +++ b/packages/app/components/accounts/reducer.ts @@ -17,7 +17,7 @@ export function getActiveAccount(state: { accounts: State }): Account | null { const accountId = state.accounts.active; return ( - state.accounts.available.find(account => account.id === accountId) || null + state.accounts.available.find((account) => account.id === accountId) || null ); } @@ -43,7 +43,7 @@ export default function accounts( const { payload } = action; state.available = state.available - .filter(account => account.id !== payload.id) + .filter((account) => account.id !== payload.id) .concat(payload); state.available.sort((account1, account2) => { @@ -65,7 +65,7 @@ export default function accounts( const { payload } = action; return { - available: state.available.map(account => { + available: state.available.map((account) => { if (account.id === payload.id) { return { ...payload }; } @@ -91,7 +91,9 @@ export default function accounts( return { ...state, - available: state.available.filter(account => account.id !== payload.id), + available: state.available.filter( + (account) => account.id !== payload.id, + ), }; } @@ -104,7 +106,7 @@ export default function accounts( return { ...state, - available: state.available.map(account => { + available: state.available.map((account) => { if (account.id === state.active) { return { ...account, diff --git a/packages/app/components/auth/AuthTitle.tsx b/packages/app/components/auth/AuthTitle.tsx index c51028d..2557e2c 100644 --- a/packages/app/components/auth/AuthTitle.tsx +++ b/packages/app/components/auth/AuthTitle.tsx @@ -5,7 +5,7 @@ import { FormattedMessage as Message, MessageDescriptor } from 'react-intl'; export default function AuthTitle({ title }: { title: MessageDescriptor }) { return ( - {msg => ( + {(msg) => ( {msg} diff --git a/packages/app/components/auth/PanelTransition.tsx b/packages/app/components/auth/PanelTransition.tsx index bd2fddb..1dbef95 100644 --- a/packages/app/components/auth/PanelTransition.tsx +++ b/packages/app/components/auth/PanelTransition.tsx @@ -1,4 +1,9 @@ -import React, { CSSProperties, MouseEventHandler, ReactElement, ReactNode } from 'react'; +import React, { + CSSProperties, + MouseEventHandler, + ReactElement, + ReactNode, +} from 'react'; import { AccountsState } from 'app/components/accounts'; import { User } from 'app/components/user'; import { connect } from 'react-redux'; @@ -64,7 +69,7 @@ if (process.env.NODE_ENV !== 'production') { // TODO: it may be moved to tests in future contexts.reduce((acc, context) => { - context.forEach(panel => { + context.forEach((panel) => { if (acc[panel]) { throw new Error( `Panel ${panel} is already exists in context ${JSON.stringify( @@ -186,7 +191,7 @@ class PanelTransition extends React.PureComponent { } componentWillUnmount() { - this.timerIds.forEach(id => clearTimeout(id)); + this.timerIds.forEach((id) => clearTimeout(id)); this.timerIds = []; } @@ -262,7 +267,7 @@ class PanelTransition extends React.PureComponent { willEnter={this.willEnter} willLeave={this.willLeave} > - {items => { + {(items) => { const panels = items.filter(({ key }) => key !== 'common'); const [common] = items.filter(({ key }) => key === 'common'); @@ -289,7 +294,7 @@ class PanelTransition extends React.PureComponent { > - {panels.map(config => this.getHeader(config))} + {panels.map((config) => this.getHeader(config))}
{ >
- {panels.map(config => this.getBody(config))} + {panels.map((config) => this.getBody(config))}
- {panels.map(config => this.getFooter(config))} + {panels.map((config) => this.getFooter(config))}
@@ -311,7 +316,7 @@ class PanelTransition extends React.PureComponent { className={helpLinksStyles} data-testid="auth-controls-secondary" > - {panels.map(config => this.getLinks(config))} + {panels.map((config) => this.getLinks(config))}
); @@ -356,7 +361,7 @@ class PanelTransition extends React.PureComponent { const fromLeft = -1; const fromRight = 1; - const currentContext = contexts.find(context => context.includes(key)); + const currentContext = contexts.find((context) => context.includes(key)); if (!currentContext) { throw new Error(`Can not find settings for ${key} panel`); @@ -377,7 +382,7 @@ class PanelTransition extends React.PureComponent { } getDirection(next: PanelId, prev: PanelId): 'X' | 'Y' { - const context = contexts.find(item => item.includes(prev)); + const context = contexts.find((item) => item.includes(prev)); if (!context) { throw new Error(`Can not find context for transition ${prev} -> ${next}`); @@ -521,11 +526,11 @@ class PanelTransition extends React.PureComponent { key={`body/${key}`} style={transitionStyle} state={this.shouldMeasureHeight()} - onMeasure={height => this.onUpdateHeight(height, key)} + onMeasure={(height) => this.onUpdateHeight(height, key)} > {React.cloneElement(Body, { // @ts-ignore - ref: body => { + ref: (body) => { this.body = body; }, })} @@ -596,7 +601,7 @@ class PanelTransition extends React.PureComponent { } requestRedraw = (): Promise => - new Promise(resolve => + new Promise((resolve) => this.setState({ isHeightDirty: true }, () => { this.setState({ isHeightDirty: false }); diff --git a/packages/app/components/auth/RejectionLink.tsx b/packages/app/components/auth/RejectionLink.tsx index f63382d..e767f9c 100644 --- a/packages/app/components/auth/RejectionLink.tsx +++ b/packages/app/components/auth/RejectionLink.tsx @@ -25,7 +25,7 @@ const RejectionLink: ComponentType = ({ return ( { + onClick={(event) => { event.preventDefault(); context.reject(payload); diff --git a/packages/app/components/auth/actions.test.ts b/packages/app/components/auth/actions.test.ts index 2374da5..cf168d7 100644 --- a/packages/app/components/auth/actions.test.ts +++ b/packages/app/components/auth/actions.test.ts @@ -176,7 +176,7 @@ describe('components/auth/actions', () => { (request.post as any).returns(Promise.reject(resp)); - return callThunk(oAuthComplete).catch(error => { + return callThunk(oAuthComplete).catch((error) => { expect(error.acceptRequired, 'to be true'); expectDispatchCalls([[requirePermissionsAccept()]]); }); diff --git a/packages/app/components/auth/actions.ts b/packages/app/components/auth/actions.ts index 23fde96..99ef213 100644 --- a/packages/app/components/auth/actions.ts +++ b/packages/app/components/auth/actions.ts @@ -87,10 +87,10 @@ export function login({ totp?: string; rememberMe?: boolean; }) { - return wrapInLoader(dispatch => + return wrapInLoader((dispatch) => loginEndpoint({ login, password, totp, rememberMe }) .then(authHandler(dispatch)) - .catch(resp => { + .catch((resp) => { if (resp.errors) { if (resp.errors.password === PASSWORD_REQUIRED) { return dispatch(setLogin(login)); @@ -118,7 +118,7 @@ export function login({ } export function acceptRules() { - return wrapInLoader(dispatch => + return wrapInLoader((dispatch) => dispatch(userAcceptRules()).catch(validationErrorsHandler(dispatch)), ); } @@ -152,7 +152,7 @@ export function recoverPassword({ newPassword: string; newRePassword: string; }) { - return wrapInLoader(dispatch => + return wrapInLoader((dispatch) => recoverPasswordEndpoint(key, newPassword, newRePassword) .then(authHandler(dispatch)) .catch(validationErrorsHandler(dispatch, '/forgot-password')), @@ -205,7 +205,7 @@ export function activate({ }: { key: string; }): ThunkAction> { - return wrapInLoader(dispatch => + return wrapInLoader((dispatch) => activateEndpoint(key) .then(authHandler(dispatch)) .catch(validationErrorsHandler(dispatch, '/resend-activation')), @@ -219,9 +219,9 @@ export function resendActivation({ email: string; captcha: string; }) { - return wrapInLoader(dispatch => + return wrapInLoader((dispatch) => resendActivationEndpoint(email, captcha) - .then(resp => { + .then((resp) => { dispatch( updateUser({ email, @@ -368,17 +368,17 @@ const KNOWN_SCOPES: ReadonlyArray = [ export function oAuthValidate(oauthData: OauthData) { // TODO: move to oAuth actions? // test request: /oauth?client_id=ely&redirect_uri=http%3A%2F%2Fely.by&response_type=code&scope=minecraft_server_session&description=foo - return wrapInLoader(dispatch => + return wrapInLoader((dispatch) => oauth .validate(oauthData) - .then(resp => { + .then((resp) => { const { scopes } = resp.session; const invalidScopes = scopes.filter( - scope => !KNOWN_SCOPES.includes(scope), + (scope) => !KNOWN_SCOPES.includes(scope), ); let prompt = (oauthData.prompt || 'none') .split(',') - .map(item => item.trim()); + .map((item) => item.trim()); if (prompt.includes('none')) { prompt = ['none']; @@ -415,7 +415,7 @@ export function oAuthValidate(oauthData: OauthData) { /** * @param {object} params * @param {bool} params.accept=false - * + * @param params.accept * @returns {Promise} */ export function oAuthComplete(params: { accept?: boolean } = {}) { @@ -638,12 +638,12 @@ function wrapInLoader(fn: ThunkAction>): ThunkAction> { const endLoading = () => dispatch(setLoadingState(false)); return fn(dispatch, getState, undefined).then( - resp => { + (resp) => { endLoading(); return resp; }, - resp => { + (resp) => { endLoading(); return Promise.reject(resp); @@ -668,7 +668,7 @@ function authHandler(dispatch: Dispatch) { token: oAuthResp.access_token, refreshToken: oAuthResp.refresh_token || null, }), - ).then(resp => { + ).then((resp) => { dispatch(setLogin(null)); return resp; @@ -684,7 +684,7 @@ function validationErrorsHandler( data?: Record; }>, ) => Promise { - return resp => { + return (resp) => { if (resp.errors) { const [firstError] = Object.keys(resp.errors); const firstErrorObj: ValidationError = { @@ -711,7 +711,7 @@ function validationErrorsHandler( } // TODO: can I clone the object or its necessary to catch modified errors list on corresponding catches? - const errors: Record = resp.errors; + const { errors } = resp; errors[firstError] = firstErrorObj; dispatch(setErrors(errors)); diff --git a/packages/app/components/auth/factory.tsx b/packages/app/components/auth/factory.tsx index 0cf6e13..9cbef7f 100644 --- a/packages/app/components/auth/factory.tsx +++ b/packages/app/components/auth/factory.tsx @@ -25,7 +25,7 @@ interface FactoryParams { links?: RejectionLinkProps | Array; } -export default function({ +export default function ({ title, body, footer, diff --git a/packages/app/components/auth/finish/Finish.tsx b/packages/app/components/auth/finish/Finish.tsx index c5ddeff..5e8b844 100644 --- a/packages/app/components/auth/finish/Finish.tsx +++ b/packages/app/components/auth/finish/Finish.tsx @@ -84,7 +84,7 @@ class Finish extends React.Component { ); } - onCopyClick: MouseEventHandler = event => { + onCopyClick: MouseEventHandler = (event) => { event.preventDefault(); const { code } = this.props; diff --git a/packages/app/components/auth/login/Login.ts b/packages/app/components/auth/login/Login.ts index 193529c..cb28913 100644 --- a/packages/app/components/auth/login/Login.ts +++ b/packages/app/components/auth/login/Login.ts @@ -10,7 +10,7 @@ export default factory({ label: messages.next, }, links: { - isAvailable: context => !context.user.isGuest, + isAvailable: (context) => !context.user.isGuest, label: messages.createNewAccount, }, }); diff --git a/packages/app/components/auth/permissions/PermissionsBody.tsx b/packages/app/components/auth/permissions/PermissionsBody.tsx index be17509..7c4cd06 100644 --- a/packages/app/components/auth/permissions/PermissionsBody.tsx +++ b/packages/app/components/auth/permissions/PermissionsBody.tsx @@ -41,7 +41,7 @@ export default class PermissionsBody extends BaseAuthBody {