diff --git a/packages/app/components/accounts/actions.ts b/packages/app/components/accounts/actions.ts index 28b1466..7b1b6f8 100644 --- a/packages/app/components/accounts/actions.ts +++ b/packages/app/components/accounts/actions.ts @@ -41,11 +41,11 @@ export function authenticate( } try { - const { token: newToken, refreshToken: newRefreshToken, user } = await validateToken( - accountId, - token, - refreshToken, - ); + const { + token: newToken, + refreshToken: newRefreshToken, + user, + } = await validateToken(accountId, token, refreshToken); const newAccount: Account = { id: user.id, username: user.username, diff --git a/packages/app/components/auth/PanelTransition.tsx b/packages/app/components/auth/PanelTransition.tsx index 29beac9..911d9b7 100644 --- a/packages/app/components/auth/PanelTransition.tsx +++ b/packages/app/components/auth/PanelTransition.tsx @@ -405,7 +405,7 @@ class PanelTransition extends React.PureComponent { getHeader({ key, style, data }: TransitionPlainStyle): ReactElement { const { Title } = data as AnimationData; - const { transformSpring } = (style as unknown) as AnimationStyle; + const { transformSpring } = style as unknown as AnimationStyle; let { hasBackButton } = data; @@ -414,7 +414,7 @@ class PanelTransition extends React.PureComponent { } const transitionStyle = { - ...this.getDefaultTransitionStyles(key, (style as unknown) as AnimationStyle), + ...this.getDefaultTransitionStyles(key, style as unknown as AnimationStyle), opacity: 1, // reset default }; @@ -448,7 +448,7 @@ class PanelTransition extends React.PureComponent { getBody({ key, style, data }: TransitionPlainStyle): ReactElement { const { Body } = data as AnimationData; - const { transformSpring } = (style as unknown) as AnimationStyle; + const { transformSpring } = style as unknown as AnimationStyle; const { direction } = this.state; let transform = this.translate(transformSpring, direction); @@ -460,7 +460,7 @@ class PanelTransition extends React.PureComponent { } const transitionStyle: CSSProperties = { - ...this.getDefaultTransitionStyles(key, (style as unknown) as AnimationStyle), + ...this.getDefaultTransitionStyles(key, style as unknown as AnimationStyle), top: 'auto', // reset default [verticalOrigin]: 0, ...transform, @@ -486,7 +486,7 @@ class PanelTransition extends React.PureComponent { getFooter({ key, style, data }: TransitionPlainStyle): ReactElement { const { Footer } = data as AnimationData; - const transitionStyle = this.getDefaultTransitionStyles(key, (style as unknown) as AnimationStyle); + const transitionStyle = this.getDefaultTransitionStyles(key, style as unknown as AnimationStyle); return (
@@ -498,7 +498,7 @@ class PanelTransition extends React.PureComponent { getLinks({ key, style, data }: TransitionPlainStyle): ReactElement { const { Links } = data as AnimationData; - const transitionStyle = this.getDefaultTransitionStyles(key, (style as unknown) as AnimationStyle); + const transitionStyle = this.getDefaultTransitionStyles(key, style as unknown as AnimationStyle); return (
diff --git a/packages/app/components/auth/chooseAccount/AccountSwitcher.tsx b/packages/app/components/auth/chooseAccount/AccountSwitcher.tsx index 39e6c4c..2c46ea8 100644 --- a/packages/app/components/auth/chooseAccount/AccountSwitcher.tsx +++ b/packages/app/components/auth/chooseAccount/AccountSwitcher.tsx @@ -15,18 +15,19 @@ interface Props { const AccountSwitcher: ComponentType = ({ accounts, onAccountClick }) => { const [selectedAccount, setSelectedAccount] = useState(); const onAccountClickCallback = useCallback( - (account: Account): MouseEventHandler => async (event) => { - event.stopPropagation(); + (account: Account): MouseEventHandler => + async (event) => { + event.stopPropagation(); - setSelectedAccount(account.id); - try { - if (onAccountClick) { - await onAccountClick(account); + setSelectedAccount(account.id); + try { + if (onAccountClick) { + await onAccountClick(account); + } + } finally { + setSelectedAccount(undefined); } - } finally { - setSelectedAccount(undefined); - } - }, + }, [onAccountClick], ); diff --git a/packages/app/components/dev/apps/applicationForm/ApplicationForm.tsx b/packages/app/components/dev/apps/applicationForm/ApplicationForm.tsx index 918698d..f1457e5 100644 --- a/packages/app/components/dev/apps/applicationForm/ApplicationForm.tsx +++ b/packages/app/components/dev/apps/applicationForm/ApplicationForm.tsx @@ -44,7 +44,7 @@ const typeToForm: TypeToForm = { type TypeToLabel = Record; -const typeToLabel: TypeToLabel = ((Object.keys(typeToForm) as unknown) as Array).reduce( +const typeToLabel: TypeToLabel = (Object.keys(typeToForm) as unknown as Array).reduce( (result, key) => { result[key] = typeToForm[key].label; diff --git a/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx b/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx index 997ad2d..9520521 100644 --- a/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx +++ b/packages/app/components/dev/apps/applicationForm/ApplicationTypeSwitcher.tsx @@ -14,7 +14,7 @@ interface Props { const ApplicationTypeSwitcher: ComponentType = ({ appTypes, selectedType, setType }) => (
- {((Object.keys(appTypes) as unknown) as Array).map((type) => ( + {(Object.keys(appTypes) as unknown as Array).map((type) => (
setType(type)} diff --git a/packages/app/components/footerMenu/FooterMenu.tsx b/packages/app/components/footerMenu/FooterMenu.tsx index ce4a44c..a914094 100644 --- a/packages/app/components/footerMenu/FooterMenu.tsx +++ b/packages/app/components/footerMenu/FooterMenu.tsx @@ -14,10 +14,11 @@ const FooterMenu: ComponentType = () => { const dispatch = useReduxDispatch(); const createPopupHandler = useCallback( - (popup: ComponentType): MouseEventHandler => (event) => { - event.preventDefault(); - dispatch(createPopup({ Popup: popup })); - }, + (popup: ComponentType): MouseEventHandler => + (event) => { + event.preventDefault(); + dispatch(createPopup({ Popup: popup })); + }, [dispatch], ); diff --git a/packages/app/components/ui/form/Dropdown.tsx b/packages/app/components/ui/form/Dropdown.tsx index 630a5e9..37628de 100644 --- a/packages/app/components/ui/form/Dropdown.tsx +++ b/packages/app/components/ui/form/Dropdown.tsx @@ -11,7 +11,7 @@ import FormInputComponent from './FormInputComponent'; type I18nString = string | MessageDescriptor; type ItemLabel = I18nString | React.ReactElement; -interface Props extends InputHTMLAttributes { +interface Props extends InputHTMLAttributes { label: I18nString; items: Record; block?: boolean; diff --git a/packages/app/components/ui/form/FormModel.ts b/packages/app/components/ui/form/FormModel.ts index 746c12f..acbc29d 100644 --- a/packages/app/components/ui/form/FormModel.ts +++ b/packages/app/components/ui/form/FormModel.ts @@ -39,9 +39,7 @@ export default class FormModel { * * @returns {object} - ref and name props for component */ - bindField( - name: string, - ): { + bindField(name: string): { name: string; ref: (el: any) => void; error?: ValidationError; diff --git a/packages/app/components/userbar/AccountSwitcher.tsx b/packages/app/components/userbar/AccountSwitcher.tsx index 1fa07c8..317794f 100644 --- a/packages/app/components/userbar/AccountSwitcher.tsx +++ b/packages/app/components/userbar/AccountSwitcher.tsx @@ -27,19 +27,21 @@ const AccountSwitcher: ComponentType = ({ }) => { const available = accounts.filter((account) => account.id !== activeAccount.id); const onAccountClickCallback = useCallback( - (account: Account): MouseEventHandler => (event) => { - event.preventDefault(); - onAccountClick(account); - }, + (account: Account): MouseEventHandler => + (event) => { + event.preventDefault(); + onAccountClick(account); + }, [onAccountClick], ); const onAccountRemoveCallback = useCallback( - (account: Account): MouseEventHandler => (event) => { - event.preventDefault(); - event.stopPropagation(); + (account: Account): MouseEventHandler => + (event) => { + event.preventDefault(); + event.stopPropagation(); - onRemoveClick(account); - }, + onRemoveClick(account); + }, [onRemoveClick], ); diff --git a/packages/app/functions.ts b/packages/app/functions.ts index 8b331c3..72fb2da 100644 --- a/packages/app/functions.ts +++ b/packages/app/functions.ts @@ -88,9 +88,7 @@ export { default as debounce } from 'debounce'; * * @returns {object} - decoded jwt payload */ -export function getJwtPayloads( - jwt: string, -): { +export function getJwtPayloads(jwt: string): { sub: string; jti: number; exp: number; diff --git a/packages/app/pages/profile/ProfileController.tsx b/packages/app/pages/profile/ProfileController.tsx index a0d859d..623e82d 100644 --- a/packages/app/pages/profile/ProfileController.tsx +++ b/packages/app/pages/profile/ProfileController.tsx @@ -78,94 +78,96 @@ export default connect( }), { refreshUserData, - onSubmit: ({ form, sendData }: { form: FormModel; sendData: () => Promise }) => (dispatch: Dispatch) => { - form.beginLoading(); + onSubmit: + ({ form, sendData }: { form: FormModel; sendData: () => Promise }) => + (dispatch: Dispatch) => { + form.beginLoading(); - return sendData() - .catch((resp) => { - const requirePassword = resp.errors && !!resp.errors.password; + return sendData() + .catch((resp) => { + const requirePassword = resp.errors && !!resp.errors.password; - // prevalidate user input, because requestPassword popup will block the - // entire form from input, so it must be valid - if (resp.errors) { - delete resp.errors.password; + // prevalidate user input, because requestPassword popup will block the + // entire form from input, so it must be valid + if (resp.errors) { + delete resp.errors.password; - if (resp.errors.email && resp.data && resp.data.canRepeatIn) { - resp.errors.email = { - type: resp.errors.email, - payload: { - msLeft: resp.data.canRepeatIn * 1000, - }, - }; + if (resp.errors.email && resp.data && resp.data.canRepeatIn) { + resp.errors.email = { + type: resp.errors.email, + payload: { + msLeft: resp.data.canRepeatIn * 1000, + }, + }; + } + + if (Object.keys(resp.errors).length) { + form.setErrors(resp.errors); + + return Promise.reject(resp); + } + + if (requirePassword) { + return requestPassword(form); + } } - if (Object.keys(resp.errors).length) { - form.setErrors(resp.errors); - + return Promise.reject(resp); + }) + .catch((resp) => { + if (!resp || !resp.errors) { + logger.warn('Unexpected profile editing error', { + resp, + }); + } else { return Promise.reject(resp); } + }) + .finally(() => form.endLoading()); - if (requirePassword) { - return requestPassword(form); - } - } + function requestPassword(form: FormModel) { + return new Promise((resolve, reject) => { + dispatch( + createPopup({ + Popup(props: { onClose: () => Promise }) { + const onSubmit = () => { + form.beginLoading(); - return Promise.reject(resp); - }) - .catch((resp) => { - if (!resp || !resp.errors) { - logger.warn('Unexpected profile editing error', { - resp, - }); - } else { - return Promise.reject(resp); - } - }) - .finally(() => form.endLoading()); + sendData() + .then(resolve) + .then(props.onClose) + .catch((resp) => { + if (resp.errors) { + form.setErrors(resp.errors); - function requestPassword(form: FormModel) { - return new Promise((resolve, reject) => { - dispatch( - createPopup({ - Popup(props: { onClose: () => Promise }) { - const onSubmit = () => { - form.beginLoading(); + const parentFormHasErrors = + Object.keys(resp.errors).filter((name) => name !== 'password') + .length > 0; - sendData() - .then(resolve) - .then(props.onClose) - .catch((resp) => { - if (resp.errors) { - form.setErrors(resp.errors); - - const parentFormHasErrors = - Object.keys(resp.errors).filter((name) => name !== 'password') - .length > 0; - - if (parentFormHasErrors) { - // something wrong with parent form, hiding popup and show that form - props.onClose(); - reject(resp); - logger.warn( - 'Profile: can not submit password popup due to errors in source form', - { resp }, - ); + if (parentFormHasErrors) { + // something wrong with parent form, hiding popup and show that form + props.onClose(); + reject(resp); + logger.warn( + 'Profile: can not submit password popup due to errors in source form', + { resp }, + ); + } + } else { + return Promise.reject(resp); } - } else { - return Promise.reject(resp); - } - }) - .finally(() => form.endLoading()); - }; + }) + .finally(() => form.endLoading()); + }; - return ; - }, - // TODO: this property should be automatically extracted from the popup's isClosable prop - disableOverlayClose: true, - }), - ); - }); - } - }, + return ; + }, + // TODO: this property should be automatically extracted from the popup's isClosable prop + disableOverlayClose: true, + }), + ); + }); + } + }, }, )(ProfileController); diff --git a/packages/app/services/api/mfa.ts b/packages/app/services/api/mfa.ts index 5e442fb..c5c5ef0 100644 --- a/packages/app/services/api/mfa.ts +++ b/packages/app/services/api/mfa.ts @@ -1,8 +1,6 @@ import request, { Resp } from 'app/services/request'; -export function getSecret( - id: number, -): Promise< +export function getSecret(id: number): Promise< Resp<{ qr: string; secret: string; diff --git a/packages/app/services/i18n/i18n.ts b/packages/app/services/i18n/i18n.ts index 2901d3f..a46c1d2 100644 --- a/packages/app/services/i18n/i18n.ts +++ b/packages/app/services/i18n/i18n.ts @@ -66,9 +66,7 @@ class I18N { await intlPolyfill('en'); } - async require( - locale: string, - ): Promise<{ + async require(locale: string): Promise<{ locale: string; messages: Record; }> { diff --git a/packages/scripts/i18n-crowdin.ts b/packages/scripts/i18n-crowdin.ts index 1b97edc..e75e4a6 100644 --- a/packages/scripts/i18n-crowdin.ts +++ b/packages/scripts/i18n-crowdin.ts @@ -267,25 +267,23 @@ async function pull(): Promise { }); let downloadingReady = 0; - const promises = localesToPull.map( - async (languageId): Promise => { - const { - data: { url }, - } = await crowdin.translationsApi.buildProjectFileTranslation(PROJECT_ID, fileId, { - targetLanguageId: languageId, - }); + const promises = localesToPull.map(async (languageId): Promise => { + const { + data: { url }, + } = await crowdin.translationsApi.buildProjectFileTranslation(PROJECT_ID, fileId, { + targetLanguageId: languageId, + }); - const { data: fileContents } = await axios.get(url, { - // Disable response parsing - transformResponse: [], - }); - fs.writeFileSync(getLocaleFilePath(languageId), fileContents); + const { data: fileContents } = await axios.get(url, { + // Disable response parsing + transformResponse: [], + }); + fs.writeFileSync(getLocaleFilePath(languageId), fileContents); - downloadingProgressBar.update(++downloadingReady / localesToPull.length, { - cCurrent: downloadingReady, - }); - }, - ); + downloadingProgressBar.update(++downloadingReady / localesToPull.length, { + cCurrent: downloadingReady, + }); + }); await Promise.all(promises); diff --git a/postcss.config.js b/postcss.config.js index 37676b2..49e977d 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -12,13 +12,15 @@ module.exports = ({ webpackLoaderContext: loader }) => ({ 'postcss-import': { addModulesDirectories: ['./src'], - resolve: ((defaultResolve) => (url, basedir, importOptions) => - defaultResolve( - // mainly to remove '~' from request - loaderUtils.urlToRequest(url), - basedir, - importOptions, - ))(require('postcss-import/lib/resolve-id')), + resolve: ( + (defaultResolve) => (url, basedir, importOptions) => + defaultResolve( + // mainly to remove '~' from request + loaderUtils.urlToRequest(url), + basedir, + importOptions, + ) + )(require('postcss-import/lib/resolve-id')), load: ((defaultLoad) => (filename, importOptions) => { if (/\.font.(js|json)$/.test(filename)) { diff --git a/tests-e2e/cypress/integration/auth/invalid-refreshToken.test.ts b/tests-e2e/cypress/integration/auth/invalid-refreshToken.test.ts index ced87a0..28c9eda 100644 --- a/tests-e2e/cypress/integration/auth/invalid-refreshToken.test.ts +++ b/tests-e2e/cypress/integration/auth/invalid-refreshToken.test.ts @@ -240,8 +240,7 @@ function createState() { id: 7, username: 'SleepWalker', email: 'danilenkos@auroraglobal.com', - token: - 'eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4MDksImV4cCI6MTUxODM3NzQwOSwic3ViIjoiZWx5fDciLCJqdGkiOjM1NDh9.Fv4AbJ0iDbrH3bhbgF0ViJLfYYiwH78deR4fMlMhKrQ', + token: 'eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4MDksImV4cCI6MTUxODM3NzQwOSwic3ViIjoiZWx5fDciLCJqdGkiOjM1NDh9.Fv4AbJ0iDbrH3bhbgF0ViJLfYYiwH78deR4fMlMhKrQ', refreshToken: '3gh6ZZ3R9jGeFdp0TmlY7sd0zBxH6Zfq48M86eUAv952RcAKx32RAnjlKkgd6i-MV-RKbjtADIdoRwMUWOYQjEYtwwXPjcQJ', }, @@ -249,8 +248,7 @@ function createState() { id: 102, username: 'test', email: 'admin@udf.su', - token: - 'eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4NjUsImV4cCI6MTUxODM3NzQ2NSwic3ViIjoiZWx5fDEwMiIsImp0aSI6MzU0OX0.eJEgvXT3leGqBe3tYNGZb0E4WEvWfrLPjcD7eNjyQYO', + token: 'eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4NjUsImV4cCI6MTUxODM3NzQ2NSwic3ViIjoiZWx5fDEwMiIsImp0aSI6MzU0OX0.eJEgvXT3leGqBe3tYNGZb0E4WEvWfrLPjcD7eNjyQYO', refreshToken: 'Al75SIx-LFOCP7kaqZBVqMVmSljJw9_bdFQGyuM64c6ShP7YsXbkCD8vPOundAwUDfRZqsIbOHUROmAHPB0VBfjLfw96yqxx', }, diff --git a/tests-e2e/cypress/integration/dev/applications.test.ts b/tests-e2e/cypress/integration/dev/applications.test.ts index ef9353b..ffb498d 100644 --- a/tests-e2e/cypress/integration/dev/applications.test.ts +++ b/tests-e2e/cypress/integration/dev/applications.test.ts @@ -6,7 +6,7 @@ describe('Applications', () => { // remove all previously added apps cy.window().then(async (win) => { - const { oauthApi } = (win as any) as { + const { oauthApi } = win as any as { oauthApi: typeof import('app/services/api/oauth').default; }; const apps = await oauthApi.getAppsByUser(user.id); diff --git a/tests-e2e/cypress/support/index.d.ts b/tests-e2e/cypress/support/index.d.ts index b82d25c..edbfee7 100644 --- a/tests-e2e/cypress/support/index.d.ts +++ b/tests-e2e/cypress/support/index.d.ts @@ -32,11 +32,7 @@ declare namespace Cypress { */ rawApiResp?: false; }): Promise<{ accounts: TAccount[] }>; - login(options: { - accounts: AccountAlias[]; - updateState?: boolean; - rawApiResp: true; - }): Promise<{ + login(options: { accounts: AccountAlias[]; updateState?: boolean; rawApiResp: true }): Promise<{ accounts: { success: true; access_token: string;