This commit is contained in:
Nikita Gopienko 2019-10-02 13:20:24 +03:00
commit c0f4125f8d
10 changed files with 109 additions and 60 deletions

View File

@ -32,6 +32,9 @@ if (process.env.NODE_ENV === "production") {
const resources = { const resources = {
en: { en: {
translation: require("./locales/en/translation.json") translation: require("./locales/en/translation.json")
},
ru: {
translation: require("./locales/ru/translation.json")
} }
}; };

View File

@ -1802,14 +1802,15 @@ asap@~2.0.6:
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
"asc-web-components@file:../../../packages/asc-web-components": "asc-web-components@file:../../../packages/asc-web-components":
version "1.0.87" version "1.0.102"
dependencies: dependencies:
moment "^2.24.0" moment "^2.24.0"
prop-types "^15.7.2" prop-types "^15.7.2"
rc-tree "^2.1.2" rc-tree "^2.1.2"
react-autosize-textarea "^7.0.0" react-autosize-textarea "^7.0.0"
react-avatar-edit "^0.8.3" react-avatar-editor "^11.0.7"
react-custom-scrollbars "^4.2.1" react-custom-scrollbars "^4.2.1"
react-dropzone "^10.1.8"
react-text-mask "^5.4.3" react-text-mask "^5.4.3"
react-toastify "^5.3.2" react-toastify "^5.3.2"
react-virtualized-auto-sizer "^1.0.2" react-virtualized-auto-sizer "^1.0.2"
@ -1897,6 +1898,13 @@ atob@^2.1.1:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
attr-accept@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-1.1.3.tgz#48230c79f93790ef2775fcec4f0db0f5db41ca52"
integrity sha512-iT40nudw8zmCweivz6j58g+RT33I4KbaIvRUhjNmDwO2WmsQUxFEZZYZ5w3vXe5x5MX9D7mfvA/XaLOZYFR9EQ==
dependencies:
core-js "^2.5.0"
autoprefixer@^9.6.1: autoprefixer@^9.6.1:
version "9.6.1" version "9.6.1"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47"
@ -2968,7 +2976,7 @@ core-js@3.1.4:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07"
integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ== integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==
core-js@^2.4.0, core-js@^2.6.4: core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.4:
version "2.6.9" version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
@ -4320,6 +4328,13 @@ file-loader@3.0.1:
loader-utils "^1.0.2" loader-utils "^1.0.2"
schema-utils "^1.0.0" schema-utils "^1.0.0"
file-selector@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.1.12.tgz#fe726547be219a787a9dcc640575a04a032b1fd0"
integrity sha512-Kx7RTzxyQipHuiqyZGf+Nz4vY9R1XGxuQl/hLoJwq+J4avk/9wxxgZyHKtbyIPJmbD4A66DWGYfyykWNpcYutQ==
dependencies:
tslib "^1.9.0"
filesize@3.6.1: filesize@3.6.1:
version "3.6.1" version "3.6.1"
resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
@ -6298,11 +6313,6 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
konva@2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/konva/-/konva-2.5.1.tgz#cca611a9522e831e54cf57c508a1aed3f0ceac25"
integrity sha512-YdHEWqmbWPieqIZuLx7JFGm9Ui08hSUaSJ2k2Ml8o5giFgJ0WmxAS0DPXIM+Ty2ADRagOHZfXSJ/skwYqqlwgQ==
last-call-webpack-plugin@^3.0.0: last-call-webpack-plugin@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555"
@ -8736,12 +8746,12 @@ react-autosize-textarea@^7.0.0:
line-height "^0.3.1" line-height "^0.3.1"
prop-types "^15.5.6" prop-types "^15.5.6"
react-avatar-edit@^0.8.3: react-avatar-editor@^11.0.7:
version "0.8.3" version "11.0.7"
resolved "https://registry.yarnpkg.com/react-avatar-edit/-/react-avatar-edit-0.8.3.tgz#0ebf21391328fc255429bdfbc782f795827109bf" resolved "https://registry.yarnpkg.com/react-avatar-editor/-/react-avatar-editor-11.0.7.tgz#021053cfeaa138407b79279ee5a0384f273f0c54"
integrity sha512-QEedh6DjDCSI7AUsUHHtfhxApCWC5hJAoywxUA5PtUdw03iIjEurgVqPOIt1UBHhU/Zk/9amElRF3oepN9JZSg== integrity sha512-GbNYBd1/L1QyuU9VRvOW0hSkW1R0XSneOWZFgqI5phQf6dX+dF/G3/AjiJ0hv3JWh2irMQ7DL0oYDKzwtTnNBQ==
dependencies: dependencies:
konva "2.5.1" prop-types "^15.5.8"
react-custom-scrollbars@^4.2.1: react-custom-scrollbars@^4.2.1:
version "4.2.1" version "4.2.1"
@ -8798,6 +8808,15 @@ react-dom@^16.9.0:
prop-types "^15.6.2" prop-types "^15.6.2"
scheduler "^0.15.0" scheduler "^0.15.0"
react-dropzone@^10.1.8:
version "10.1.9"
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-10.1.9.tgz#8093ecd7d2dc4002280eb2dac1d5fa4216c800ee"
integrity sha512-7iqALZ0mzk+4g/AsYxEy3QyWPMTVQYKQVkYUe9zIbH18u+pi7EBDg010KEwfIX6jeTDH2qP0E6/eUnXvBYrovA==
dependencies:
attr-accept "^1.1.3"
file-selector "^0.1.11"
prop-types "^15.7.2"
react-error-overlay@^6.0.1: react-error-overlay@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.1.tgz#b8d3cf9bb991c02883225c48044cb3ee20413e0f" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.1.tgz#b8d3cf9bb991c02883225c48044cb3ee20413e0f"

View File

@ -21,7 +21,7 @@ const App = () => {
<Switch> <Switch>
<PublicRoute exact path={["/login","/login/error=:error", "/login/confirmed-email=:confirmedEmail"]} component={Login} /> <PublicRoute exact path={["/login","/login/error=:error", "/login/confirmed-email=:confirmedEmail"]} component={Login} />
<Route path="/confirm" component={Confirm} /> <Route path="/confirm" component={Confirm} />
<PrivateRoute exact path="/" component={Home} /> <PrivateRoute exact path={["/","/error=:error"]} component={Home} />
<PrivateRoute exact path="/about" component={About} /> <PrivateRoute exact path="/about" component={About} />
<PrivateRoute component={Error404} /> <PrivateRoute component={Error404} />
</Switch> </Switch>

View File

@ -2,18 +2,17 @@ import React, { Suspense, lazy } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Redirect, Route, Switch } from "react-router-dom"; import { Redirect, Route, Switch } from "react-router-dom";
import { Loader } from "asc-web-components"; import { Loader } from "asc-web-components";
import PublicRoute from "../../../helpers/publicRoute";
import ConfirmRoute from "../../../helpers/confirmRoute"; import ConfirmRoute from "../../../helpers/confirmRoute";
import i18n from "./i18n"; import i18n from "./i18n";
import { I18nextProvider } from "react-i18next"; import { I18nextProvider } from "react-i18next";
import ActivateEmailForm from "./sub-components/activateEmail";
const ActivateUserForm = lazy(() => import("./sub-components/activateUser")); const ActivateUserForm = lazy(() => import("./sub-components/activateUser"));
const CreateUserForm = lazy(() => import("./sub-components/createUser")); const CreateUserForm = lazy(() => import("./sub-components/createUser"));
const ChangePasswordForm = lazy(() => import("./sub-components/changePassword")); const ChangePasswordForm = lazy(() => import("./sub-components/changePassword"));
// const ActivateEmailForm = lazy(() => import("./sub-components/activateEmail")); const ActivateEmailForm = lazy(() => import("./sub-components/activateEmail"));
const ChangeEmailForm = lazy(() => import("./sub-components/changeEmail")); const ChangeEmailForm = lazy(() => import("./sub-components/changeEmail"));
const ChangePhoneForm = lazy(() => import("./sub-components/changePhone")); const ChangePhoneForm = lazy(() => import("./sub-components/changePhone"));
const Error404 = lazy(() => import("../Error"));
const Confirm = ({ match, language }) => { const Confirm = ({ match, language }) => {
@ -54,7 +53,7 @@ const Confirm = ({ match, language }) => {
path={`${match.path}/PhoneActivation`} path={`${match.path}/PhoneActivation`}
component={ChangePhoneForm} component={ChangePhoneForm}
/> />
<Redirect to={{ pathname: "/" }} /> <Route component={Error404} />
</Switch> </Switch>
</Suspense> </Suspense>
</I18nextProvider > </I18nextProvider >

View File

@ -74,7 +74,7 @@ class Confirm extends React.PureComponent {
onSubmit = (e) => { onSubmit = (e) => {
this.setState({ isLoading: true }, function () { this.setState({ isLoading: true }, function () {
const { history, activateConfirmUser } = this.props; const { activateConfirmUser } = this.props;
this.setState({ errorText: "" }); this.setState({ errorText: "" });
@ -113,7 +113,7 @@ class Confirm extends React.PureComponent {
}; };
activateConfirmUser(personalData, loginData, this.state.key, this.state.userId, EmployeeActivationStatus.Activated) activateConfirmUser(personalData, loginData, this.state.key, this.state.userId, EmployeeActivationStatus.Activated)
.then(() => history.push('/')) .then(() => window.location.href = '/')
.catch(e => { .catch(e => {
console.error("activate error", e); console.error("activate error", e);
this.setState({ errorText: e.message }); this.setState({ errorText: e.message });

View File

@ -6,7 +6,7 @@ import styled from 'styled-components';
import { Collapse } from 'reactstrap'; import { Collapse } from 'reactstrap';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { welcomePageTitle } from './../../../../helpers/customNames'; import { welcomePageTitle } from './../../../../helpers/customNames';
import { getConfirmationInfo, createConfirmUser } from '../../../../store/auth/actions'; import { getConfirmationInfo, createConfirmUser, logout } from '../../../../store/auth/actions';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const inputWidth = '400px'; const inputWidth = '400px';
@ -73,7 +73,7 @@ class Confirm extends React.PureComponent {
onSubmit = (e) => { onSubmit = (e) => {
this.setState({ isLoading: true }, function () { this.setState({ isLoading: true }, function () {
const { history, createConfirmUser, linkData } = this.props; const { history, createConfirmUser, logout, linkData } = this.props;
const isVisitor = parseInt(linkData.emplType) === 2; const isVisitor = parseInt(linkData.emplType) === 2;
this.setState({ errorText: "" }); this.setState({ errorText: "" });
@ -118,8 +118,9 @@ class Confirm extends React.PureComponent {
email: this.state.email email: this.state.email
}; };
const registerData = Object.assign(personalData, { isVisitor: isVisitor }) const registerData = Object.assign(personalData, { isVisitor: isVisitor })
logout();
createConfirmUser(registerData, loginData, this.state.key) createConfirmUser(registerData, loginData, this.state.key)
.then(() => history.push('/')) .then(() => window.location.href = '/')
.catch(e => { .catch(e => {
console.error("confirm error", e); console.error("confirm error", e);
this.setState({ this.setState({
@ -340,4 +341,4 @@ function mapStateToProps(state) {
}; };
} }
export default connect(mapStateToProps, { getConfirmationInfo, createConfirmUser })(withRouter(withTranslation()(CreateUserForm))); export default connect(mapStateToProps, { getConfirmationInfo, createConfirmUser, logout })(withRouter(withTranslation()(CreateUserForm)));

View File

@ -1,9 +1,9 @@
import React from 'react'; import React, { useEffect } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withRouter } from "react-router"; import { withRouter } from "react-router";
import { Container, Col, Row, Collapse } from 'reactstrap'; import { Container, Col, Row, Collapse } from 'reactstrap';
import { ModuleTile, Loader, PageLayout } from 'asc-web-components'; import { ModuleTile, Loader, PageLayout, toastr } from 'asc-web-components';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import i18n from './i18n'; import i18n from './i18n';
@ -30,8 +30,14 @@ Tiles.propTypes = {
history: PropTypes.object.isRequired history: PropTypes.object.isRequired
}; };
const Body = ({ modules, history, isLoaded }) => { const Body = ({ modules, match, history, isLoaded }) => {
const { t } = useTranslation('translation', { i18n }); const { t } = useTranslation('translation', { i18n });
const { params } = match;
useEffect(() => {
params.error && toastr.error(params.error);
}, [params.error]);
return ( return (
!isLoaded !isLoaded
? ( ? (

View File

@ -1,12 +1,11 @@
import React from 'react'; import React from 'react';
import { Redirect, Route } from 'react-router-dom'; import { Route } from 'react-router-dom';
import { AUTH_KEY } from './constants'; import { ValidationResult } from './../helpers/constants';
import Cookies from 'universal-cookie'; import { decomposeConfirmLink } from './../helpers/converters';
import { PageLayout, Loader } from "asc-web-components";
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { checkConfirmLink } from './../store/auth/actions'; import { checkConfirmLink } from './../store/auth/actions';
import { ValidationResult } from './../helpers/constants'; import { withRouter } from "react-router";
import decomposeConfirmLink from './../helpers/decomposeConfirmLink';
import { PageLayout, Loader } from "asc-web-components";
class ConfirmRoute extends React.Component { class ConfirmRoute extends React.Component {
constructor(props) { constructor(props) {
@ -20,16 +19,20 @@ class ConfirmRoute extends React.Component {
uid: '', uid: '',
firstname: '', firstname: '',
lastname: '', lastname: '',
isReady: false, isLoaded: false,
componentProps: {} componentProps: {}
} }
} }
componentDidMount() { componentDidMount() {
const { pathname, search } = this.props.location; const { location, checkConfirmLink, isAuthenticated, history } = this.props;
const { checkConfirmLink } = this.props; const { search } = location;
const decomposedLink = decomposeConfirmLink(pathname, search); const decomposedLink = decomposeConfirmLink(location);
let validationResult; let validationResult;
let path = '';
if (!isAuthenticated) {
path = '/login';
}
checkConfirmLink(decomposedLink) checkConfirmLink(decomposedLink)
.then((res) => { .then((res) => {
validationResult = res.data.response; validationResult = res.data.response;
@ -38,39 +41,38 @@ class ConfirmRoute extends React.Component {
const confirmHeader = `type=${decomposedLink.type}&${search.slice(1)}`; const confirmHeader = `type=${decomposedLink.type}&${search.slice(1)}`;
const componentProps = Object.assign({}, decomposedLink, { confirmHeader }); const componentProps = Object.assign({}, decomposedLink, { confirmHeader });
this.setState({ this.setState({
isReady: true, isLoaded: true,
componentProps componentProps
}); });
break; break;
case ValidationResult.Invalid: case ValidationResult.Invalid:
window.location.href = '/login/error=Invalid link' history.push(`${path}/error=Invalid link`);
break; break;
case ValidationResult.Expired: case ValidationResult.Expired:
window.location.href = '/login/error=Expired link' history.push(`${path}/error=Expired link`);
break; break;
default: default:
window.location.href = '/login/error=Unknown error' history.push(`${path}/error=Unknown error`);
break; break;
} }
}) })
.catch((e) => window.location.href = '/'); .catch((e) => history.push(`${path}/error=${e}`));
} }
render() { render() {
const { component: Component, location, path, computedMatch, ...rest } = this.props; const { component: Component, ...rest } = this.props;
const newProps = Object.assign({}, { location, path, computedMatch }, { linkData: this.state.componentProps });
return ( return (
<Route <Route
{...rest} {...rest}
render={props => render={props =>
!this.state.isReady ? ( !this.state.isLoaded ? (
<PageLayout <PageLayout
sectionBodyContent={ sectionBodyContent={
<Loader className="pageLoader" type="rombs" size={40} /> <Loader className="pageLoader" type="rombs" size={40} />
} }
/> />
) : ( ) : (
<Component {...newProps} /> <Component {...props = { ...props, linkData: this.state.componentProps }} />
) )
} }
/> />
@ -78,4 +80,10 @@ class ConfirmRoute extends React.Component {
} }
}; };
export default connect(null, { checkConfirmLink })(ConfirmRoute); function mapStateToProps(state) {
return {
isAuthenticated: state.auth.isAuthenticated
};
}
export default connect(mapStateToProps, { checkConfirmLink })(withRouter(ConfirmRoute));

View File

@ -0,0 +1,25 @@
export function getObjectByLocation(location) {
if (!location.search || !location.search.length) return null;
const searchUrl = location.search.substring(1);
const object = JSON.parse(
'{"' +
decodeURIComponent(searchUrl)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
'"}'
);
return object;
}
export function decomposeConfirmLink(location) {
const queryParams = getObjectByLocation(location);
const url = location.pathname;
const posSeparator = url.lastIndexOf('/');
const type = url.slice(posSeparator + 1);
const data = Object.assign({ type }, queryParams);
return data;
}

View File

@ -1,12 +0,0 @@
const decomposeConfirmLink = (url, querySearch) => {
const decodedString = decodeURIComponent(querySearch);
const queryString = decodedString.slice(1).split('&');
const arrayOfQueryString = queryString.map(queryParam => queryParam.split('='));
const queryParams = Object.fromEntries(arrayOfQueryString);
const posSeparator = url.lastIndexOf('/');
const type = url.slice(posSeparator + 1);
const data = Object.assign({ type }, queryParams);
return data;
}
export default decomposeConfirmLink;