Web People Client: simplified configuration of i18n (+ removed useless requests + removed useless Import page)
This commit is contained in:
parent
5542e211df
commit
ac6dfbaebc
@ -3,12 +3,19 @@ import { connect } from "react-redux";
|
||||
import { Router, Switch, Redirect } from "react-router-dom";
|
||||
import { Loader } from "asc-web-components";
|
||||
import Home from "./components/pages/Home";
|
||||
import Profile from './components/pages/Profile';
|
||||
import ProfileAction from './components/pages/ProfileAction';
|
||||
import GroupAction from './components/pages/GroupAction';
|
||||
import Reassign from './components/pages/Reassign';
|
||||
import Import from './components/pages/Import';
|
||||
import { history, PrivateRoute, PublicRoute, Login, Error404, StudioLayout, Offline } from "asc-web-common";
|
||||
import Profile from "./components/pages/Profile";
|
||||
import ProfileAction from "./components/pages/ProfileAction";
|
||||
import GroupAction from "./components/pages/GroupAction";
|
||||
import Reassign from "./components/pages/Reassign";
|
||||
import {
|
||||
history,
|
||||
PrivateRoute,
|
||||
PublicRoute,
|
||||
Login,
|
||||
Error404,
|
||||
StudioLayout,
|
||||
Offline
|
||||
} from "asc-web-common";
|
||||
|
||||
/*const Profile = lazy(() => import("./components/pages/Profile"));
|
||||
const ProfileAction = lazy(() => import("./components/pages/ProfileAction"));
|
||||
@ -16,16 +23,19 @@ const GroupAction = lazy(() => import("./components/pages/GroupAction"));*/
|
||||
|
||||
const App = ({ settings }) => {
|
||||
const { homepage } = settings;
|
||||
return (
|
||||
navigator.onLine ?
|
||||
return navigator.onLine ? (
|
||||
<Router history={history}>
|
||||
<StudioLayout>
|
||||
<Suspense
|
||||
fallback={<Loader className="pageLoader" type="rombs" size='40px' />}
|
||||
fallback={<Loader className="pageLoader" type="rombs" size="40px" />}
|
||||
>
|
||||
<Switch>
|
||||
<Redirect exact from="/" to={`${homepage}`} />
|
||||
<PrivateRoute exact path={[homepage, `${homepage}/filter`]} component={Home} />
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={[homepage, `${homepage}/filter`]}
|
||||
component={Home}
|
||||
/>
|
||||
<PrivateRoute
|
||||
path={`${homepage}/view/:userId`}
|
||||
component={Profile}
|
||||
@ -56,18 +66,22 @@ const App = ({ settings }) => {
|
||||
component={Reassign}
|
||||
restricted
|
||||
/>
|
||||
<PrivateRoute
|
||||
path={`${homepage}/import`}
|
||||
component={Import}
|
||||
restricted
|
||||
<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} />
|
||||
<PrivateRoute component={Error404} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</StudioLayout>
|
||||
</Router>
|
||||
: <Offline/>
|
||||
) : (
|
||||
<Offline />
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,18 +1,17 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
utils,
|
||||
TreeMenu,
|
||||
TreeNode,
|
||||
Icons,
|
||||
Link
|
||||
} from "asc-web-components";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { utils, TreeMenu, TreeNode, Icons, Link } from "asc-web-components";
|
||||
import { history } from "asc-web-common";
|
||||
import { selectGroup } from '../../../store/people/actions';
|
||||
import { selectGroup } from "../../../store/people/actions";
|
||||
import { getSelectedGroup } from "../../../store/people/selectors";
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
import { utils as commonUtils } from 'asc-web-common';
|
||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||
import { utils as commonUtils } from "asc-web-common";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "Article",
|
||||
localesPath: "Article"
|
||||
});
|
||||
|
||||
const { changeLanguage } = commonUtils;
|
||||
|
||||
@ -31,28 +30,27 @@ const getItems = data => {
|
||||
color="#657077"
|
||||
/>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
""
|
||||
)
|
||||
}
|
||||
>
|
||||
{getItems(item.children)}
|
||||
</TreeNode>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<TreeNode key={item.key} title={item.title} />
|
||||
);
|
||||
return <TreeNode key={item.key} title={item.title} />;
|
||||
});
|
||||
};
|
||||
|
||||
class ArticleBodyContent extends React.Component {
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if(!utils.array.isArrayEqual(nextProps.selectedKeys, this.props.selectedKeys)) {
|
||||
if (
|
||||
!utils.array.isArrayEqual(nextProps.selectedKeys, this.props.selectedKeys)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!utils.array.isArrayEqual(nextProps.data, this.props.data)) {
|
||||
if (!utils.array.isArrayEqual(nextProps.data, this.props.data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -66,7 +64,9 @@ class ArticleBodyContent extends React.Component {
|
||||
document.title = currentGroup
|
||||
? `${currentGroup.name} – ${t("People")}`
|
||||
: `${t("People")} – ${t("OrganizationName")}`;
|
||||
selectGroup(data && data.length === 1 && data[0] !== "root" ? data[0] : null);
|
||||
selectGroup(
|
||||
data && data.length === 1 && data[0] !== "root" ? data[0] : null
|
||||
);
|
||||
};
|
||||
|
||||
switcherIcon = obj => {
|
||||
@ -104,8 +104,8 @@ class ArticleBodyContent extends React.Component {
|
||||
{getItems(data)}
|
||||
</TreeMenu>
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const getTreeGroups = (groups, departments) => {
|
||||
const linkProps = { fontSize: "14px", fontWeight: 600, noHover: true };
|
||||
@ -113,32 +113,41 @@ const getTreeGroups = (groups, departments) => {
|
||||
let newLink = link.split("&");
|
||||
const index = newLink.findIndex(x => x.includes("group"));
|
||||
index && newLink.splice(1, 1);
|
||||
newLink = newLink.join('&');
|
||||
newLink = newLink.join("&");
|
||||
|
||||
const onTitleClick = () => {
|
||||
history.push("/products/people/");
|
||||
}
|
||||
};
|
||||
|
||||
const treeData = [
|
||||
{
|
||||
key: "root",
|
||||
title: <Link {...linkProps} onClick={onTitleClick} href={`${history.location.pathname}`}>{departments}</Link>,
|
||||
root: true,
|
||||
children: groups.map(g => {
|
||||
return {
|
||||
key: g.id,
|
||||
title: (
|
||||
<Link
|
||||
{...linkProps}
|
||||
href={`${history.location.pathname}?group=${g.id}&${newLink}`}
|
||||
>
|
||||
{g.name}
|
||||
</Link>
|
||||
),
|
||||
root: false
|
||||
};
|
||||
}) || []
|
||||
}
|
||||
{
|
||||
key: "root",
|
||||
title: (
|
||||
<Link
|
||||
{...linkProps}
|
||||
onClick={onTitleClick}
|
||||
href={`${history.location.pathname}`}
|
||||
>
|
||||
{departments}
|
||||
</Link>
|
||||
),
|
||||
root: true,
|
||||
children:
|
||||
groups.map(g => {
|
||||
return {
|
||||
key: g.id,
|
||||
title: (
|
||||
<Link
|
||||
{...linkProps}
|
||||
href={`${history.location.pathname}?group=${g.id}&${newLink}`}
|
||||
>
|
||||
{g.name}
|
||||
</Link>
|
||||
),
|
||||
root: false
|
||||
};
|
||||
}) || []
|
||||
}
|
||||
];
|
||||
|
||||
return treeData;
|
||||
@ -146,9 +155,13 @@ const getTreeGroups = (groups, departments) => {
|
||||
|
||||
const ArticleBodyContentWrapper = withTranslation()(ArticleBodyContent);
|
||||
|
||||
const BodyContent = (props) => {
|
||||
const BodyContent = props => {
|
||||
changeLanguage(i18n);
|
||||
return (<I18nextProvider i18n={i18n}><ArticleBodyContentWrapper {...props} /></I18nextProvider>);
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ArticleBodyContentWrapper {...props} />
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
@ -156,9 +169,14 @@ function mapStateToProps(state) {
|
||||
|
||||
return {
|
||||
data: getTreeGroups(groups, state.auth.settings.customNames.groupsCaption),
|
||||
selectedKeys: state.people.selectedGroup ? [state.people.selectedGroup] : ["root"],
|
||||
selectedKeys: state.people.selectedGroup
|
||||
? [state.people.selectedGroup]
|
||||
: ["root"],
|
||||
groups
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, { selectGroup })(BodyContent);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ selectGroup }
|
||||
)(BodyContent);
|
||||
|
@ -1,16 +1,18 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from 'react-router';
|
||||
import {
|
||||
MainButton,
|
||||
DropDownItem,
|
||||
toastr
|
||||
} from "asc-web-components";
|
||||
import { InviteDialog } from './../../dialogs';
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
import { store, utils } from 'asc-web-common';
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import { MainButton, DropDownItem, toastr } from "asc-web-components";
|
||||
import { InviteDialog } from "./../../dialogs";
|
||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||
import { store, utils } from "asc-web-common";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
|
||||
const i18n = createI18N({
|
||||
page: "Article",
|
||||
localesPath: "Article"
|
||||
});
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
const { isAdmin } = store.auth.selectors;
|
||||
|
||||
@ -19,10 +21,10 @@ class PureArticleMainButtonContent extends React.Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
dialogVisible: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onDropDownItemClick = (link) => {
|
||||
onDropDownItemClick = link => {
|
||||
this.props.history.push(link);
|
||||
};
|
||||
|
||||
@ -34,85 +36,90 @@ class PureArticleMainButtonContent extends React.Component {
|
||||
goToGuestCreate = () => {
|
||||
const { history, settings } = this.props;
|
||||
history.push(`${settings.homepage}/create/guest`);
|
||||
}
|
||||
};
|
||||
|
||||
goToGroupCreate = () => {
|
||||
const { history, settings } = this.props;
|
||||
history.push(`${settings.homepage}/group/create`);
|
||||
}
|
||||
};
|
||||
|
||||
onNotImplementedClick = (text) => {
|
||||
onNotImplementedClick = text => {
|
||||
toastr.success(text);
|
||||
};
|
||||
|
||||
onInvitationDialogClick = () => this.setState({ dialogVisible: !this.state.dialogVisible });
|
||||
onInvitationDialogClick = () =>
|
||||
this.setState({ dialogVisible: !this.state.dialogVisible });
|
||||
|
||||
render() {
|
||||
console.log("People ArticleMainButtonContent render");
|
||||
const { isAdmin, settings, t } = this.props;
|
||||
const { userCaption, guestCaption, groupCaption } = settings.customNames;
|
||||
const { dialogVisible } = this.state;
|
||||
return (
|
||||
isAdmin ?
|
||||
<>
|
||||
<MainButton
|
||||
isDisabled={false}
|
||||
isDropdown={true}
|
||||
text={t('Actions')}
|
||||
>
|
||||
<DropDownItem
|
||||
icon="AddEmployeeIcon"
|
||||
label={userCaption}
|
||||
onClick={this.goToEmployeeCreate}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="AddGuestIcon"
|
||||
label={guestCaption}
|
||||
onClick={this.goToGuestCreate}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="AddDepartmentIcon"
|
||||
label={groupCaption}
|
||||
onClick={this.goToGroupCreate}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
icon="InvitationLinkIcon"
|
||||
label={t('InviteLinkTitle')}
|
||||
onClick={this.onInvitationDialogClick}
|
||||
/>
|
||||
{/* <DropDownItem
|
||||
return isAdmin ? (
|
||||
<>
|
||||
<MainButton isDisabled={false} isDropdown={true} text={t("Actions")}>
|
||||
<DropDownItem
|
||||
icon="AddEmployeeIcon"
|
||||
label={userCaption}
|
||||
onClick={this.goToEmployeeCreate}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="AddGuestIcon"
|
||||
label={guestCaption}
|
||||
onClick={this.goToGuestCreate}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="AddDepartmentIcon"
|
||||
label={groupCaption}
|
||||
onClick={this.goToGroupCreate}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
icon="InvitationLinkIcon"
|
||||
label={t("InviteLinkTitle")}
|
||||
onClick={this.onInvitationDialogClick}
|
||||
/>
|
||||
{/* <DropDownItem
|
||||
icon="PlaneIcon"
|
||||
label={t('LblInviteAgain')}
|
||||
onClick={this.onNotImplementedClick.bind(this, "Invite again action")}
|
||||
/> */}
|
||||
{false &&
|
||||
<DropDownItem
|
||||
icon="ImportIcon"
|
||||
label={t('ImportPeople')}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/import`)}
|
||||
/>
|
||||
}
|
||||
</MainButton>
|
||||
{dialogVisible &&
|
||||
<InviteDialog
|
||||
visible={dialogVisible}
|
||||
onClose={this.onInvitationDialogClick}
|
||||
onCloseButton={this.onInvitationDialogClick}
|
||||
{false && (
|
||||
<DropDownItem
|
||||
icon="ImportIcon"
|
||||
label={t("ImportPeople")}
|
||||
onClick={this.onDropDownItemClick.bind(
|
||||
this,
|
||||
`${settings.homepage}/import`
|
||||
)}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
:
|
||||
<></>
|
||||
)}
|
||||
</MainButton>
|
||||
{dialogVisible && (
|
||||
<InviteDialog
|
||||
visible={dialogVisible}
|
||||
onClose={this.onInvitationDialogClick}
|
||||
onCloseButton={this.onInvitationDialogClick}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const ArticleMainButtonContentContainer = withTranslation()(PureArticleMainButtonContent);
|
||||
const ArticleMainButtonContentContainer = withTranslation()(
|
||||
PureArticleMainButtonContent
|
||||
);
|
||||
|
||||
const ArticleMainButtonContent = (props) => {
|
||||
const ArticleMainButtonContent = props => {
|
||||
changeLanguage(i18n);
|
||||
return (<I18nextProvider i18n={i18n}><ArticleMainButtonContentContainer {...props} /></I18nextProvider>);
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ArticleMainButtonContentContainer {...props} />
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
ArticleMainButtonContent.propTypes = {
|
||||
@ -120,11 +127,11 @@ ArticleMainButtonContent.propTypes = {
|
||||
history: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
isAdmin: isAdmin(state.auth.user),
|
||||
settings: state.auth.settings
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(ArticleMainButtonContent));
|
||||
export default connect(mapStateToProps)(withRouter(ArticleMainButtonContent));
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/Article/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/ChangeEmailDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -9,9 +9,15 @@ import {
|
||||
FieldContainer
|
||||
} from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { api, utils } from "asc-web-common";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "ChangeEmailDialog",
|
||||
localesPath: "dialogs/ChangeEmailDialog"
|
||||
});
|
||||
|
||||
const { sendInstructionsToChangeEmail } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
@ -27,7 +33,7 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
isRequestRunning: false,
|
||||
email,
|
||||
hasError: false,
|
||||
errorMessage: '',
|
||||
errorMessage: "",
|
||||
emailErrors: []
|
||||
};
|
||||
|
||||
@ -50,7 +56,8 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
window.removeEventListener("keyup", this.onKeyPress);
|
||||
}
|
||||
|
||||
onValidateEmailInput = result => this.setState({ isEmailValid: result.isValid, emailErrors: result.errors });
|
||||
onValidateEmailInput = result =>
|
||||
this.setState({ isEmailValid: result.isValid, emailErrors: result.errors });
|
||||
|
||||
onChangeEmailInput = e => {
|
||||
const { hasError } = this.state;
|
||||
@ -65,14 +72,16 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
const { id } = user;
|
||||
this.setState({ isRequestRunning: true }, () => {
|
||||
sendInstructionsToChangeEmail(id, email)
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
toastr.success(res);
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => {
|
||||
this.setState({ isRequestRunning: false }, () => this.props.onClose());
|
||||
this.setState({ isRequestRunning: false }, () =>
|
||||
this.props.onClose()
|
||||
);
|
||||
});
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
onValidateEmail = () => {
|
||||
@ -81,15 +90,13 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
if (isEmailValid) {
|
||||
const sameEmailError = email.toLowerCase() === user.email.toLowerCase();
|
||||
if (sameEmailError) {
|
||||
this.setState({ errorMessage: t('SameEmail'), hasError: true });
|
||||
}
|
||||
else {
|
||||
this.setState({ errorMessage: '', hasError: false });
|
||||
this.setState({ errorMessage: t("SameEmail"), hasError: true });
|
||||
} else {
|
||||
this.setState({ errorMessage: "", hasError: false });
|
||||
this.onSendEmailChangeInstructions();
|
||||
}
|
||||
}
|
||||
else {
|
||||
const translatedErrors = emailErrors.map((errorKey => t(errorKey)));
|
||||
} else {
|
||||
const translatedErrors = emailErrors.map(errorKey => t(errorKey));
|
||||
const errorMessage = translatedErrors[0];
|
||||
this.setState({ errorMessage, hasError: true });
|
||||
}
|
||||
@ -102,7 +109,6 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
render() {
|
||||
console.log("ChangeEmailDialog render");
|
||||
const { t, visible, onClose } = this.props;
|
||||
@ -113,12 +119,12 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
headerContent={t('EmailChangeTitle')}
|
||||
headerContent={t("EmailChangeTitle")}
|
||||
bodyContent={
|
||||
<>
|
||||
<FieldContainer
|
||||
isVertical
|
||||
labelText={t('EnterEmail')}
|
||||
labelText={t("EnterEmail")}
|
||||
errorMessage={errorMessage}
|
||||
hasError={hasError}
|
||||
>
|
||||
@ -133,17 +139,15 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
hasError={hasError}
|
||||
/>
|
||||
</FieldContainer>
|
||||
<Text
|
||||
className='text-dialog'
|
||||
>
|
||||
{t('EmailActivationDescription')}
|
||||
<Text className="text-dialog">
|
||||
{t("EmailActivationDescription")}
|
||||
</Text>
|
||||
</>
|
||||
}
|
||||
footerContent={
|
||||
<Button
|
||||
key="SendBtn"
|
||||
label={t('SendButton')}
|
||||
label={t("SendButton")}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onValidateEmail}
|
||||
@ -156,7 +160,9 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const ChangeEmailDialogTranslated = withTranslation()(ChangeEmailDialogComponent);
|
||||
const ChangeEmailDialogTranslated = withTranslation()(
|
||||
ChangeEmailDialogComponent
|
||||
);
|
||||
|
||||
const ChangeEmailDialog = props => (
|
||||
<ChangeEmailDialogTranslated i18n={i18n} {...props} />
|
||||
@ -168,5 +174,4 @@ ChangeEmailDialog.propTypes = {
|
||||
user: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
|
||||
export default ChangeEmailDialog;
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/ChangePasswordDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -1,15 +1,15 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
Button,
|
||||
Link,
|
||||
Text
|
||||
} from "asc-web-components";
|
||||
import { toastr, ModalDialog, Button, Link, Text } from "asc-web-components";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api, utils } from "asc-web-common";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "ChangePasswordDialog",
|
||||
localesPath: "dialogs/ChangePasswordDialog"
|
||||
});
|
||||
|
||||
const { sendInstructionsToChangePassword } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
@ -27,17 +27,15 @@ class ChangePasswordDialogComponent extends React.Component {
|
||||
const { email, onClose } = this.props;
|
||||
this.setState({ isRequestRunning: true }, () => {
|
||||
sendInstructionsToChangePassword(email)
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
toastr.success(res);
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => {
|
||||
this.setState({ isRequestRunning: false }, () => onClose());
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
console.log("ChangePasswordDialog render");
|
||||
@ -48,23 +46,31 @@ class ChangePasswordDialogComponent extends React.Component {
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
headerContent={t('PasswordChangeTitle')}
|
||||
headerContent={t("PasswordChangeTitle")}
|
||||
bodyContent={
|
||||
<Text fontSize='13px'>
|
||||
<Trans i18nKey="MessageSendPasswordChangeInstructionsOnEmail" i18n={i18n}>
|
||||
<Text fontSize="13px">
|
||||
<Trans
|
||||
i18nKey="MessageSendPasswordChangeInstructionsOnEmail"
|
||||
i18n={i18n}
|
||||
>
|
||||
Send the password change instructions to the
|
||||
<Link type="page" href={`mailto:${email}`} noHover color='#316DAA' title={email}>
|
||||
<Link
|
||||
type="page"
|
||||
href={`mailto:${email}`}
|
||||
noHover
|
||||
color="#316DAA"
|
||||
title={email}
|
||||
>
|
||||
{{ email }}
|
||||
</Link>
|
||||
email address
|
||||
</Trans>
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
}
|
||||
footerContent={
|
||||
<Button
|
||||
key="SendBtn"
|
||||
label={t('SendButton')}
|
||||
label={t("SendButton")}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onSendPasswordChangeInstructions}
|
||||
@ -76,7 +82,9 @@ class ChangePasswordDialogComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const ChangePasswordDialogTranslated = withTranslation()(ChangePasswordDialogComponent);
|
||||
const ChangePasswordDialogTranslated = withTranslation()(
|
||||
ChangePasswordDialogComponent
|
||||
);
|
||||
|
||||
const ChangePasswordDialog = props => (
|
||||
<ChangePasswordDialogTranslated i18n={i18n} {...props} />
|
||||
@ -85,7 +93,7 @@ const ChangePasswordDialog = props => (
|
||||
ChangePasswordDialog.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
email: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default ChangePasswordDialog;
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/ChangePhoneDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -1,14 +1,15 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
Button,
|
||||
Text
|
||||
} from "asc-web-components";
|
||||
import { toastr, ModalDialog, Button, Text } from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import { utils } from "asc-web-common";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "ChangePhoneDialog",
|
||||
localesPath: "dialogs/ChangePhoneDialog"
|
||||
});
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ChangePhoneDialogComponent extends React.Component {
|
||||
@ -31,8 +32,6 @@ class ChangePhoneDialogComponent extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
console.log("ChangePhoneDialog render");
|
||||
const { t, visible, onClose } = this.props;
|
||||
@ -42,16 +41,12 @@ class ChangePhoneDialogComponent extends React.Component {
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
headerContent={t('MobilePhoneChangeTitle')}
|
||||
bodyContent={
|
||||
<Text>
|
||||
{t('MobilePhoneEraseDescription')}
|
||||
</Text>
|
||||
}
|
||||
headerContent={t("MobilePhoneChangeTitle")}
|
||||
bodyContent={<Text>{t("MobilePhoneEraseDescription")}</Text>}
|
||||
footerContent={
|
||||
<Button
|
||||
key="SendBtn"
|
||||
label={t('SendButton')}
|
||||
label={t("SendButton")}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onChangePhone}
|
||||
@ -63,7 +58,9 @@ class ChangePhoneDialogComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const ChangePhoneDialogTranslated = withTranslation()(ChangePhoneDialogComponent);
|
||||
const ChangePhoneDialogTranslated = withTranslation()(
|
||||
ChangePhoneDialogComponent
|
||||
);
|
||||
|
||||
const ChangePhoneDialog = props => (
|
||||
<ChangePhoneDialogTranslated i18n={i18n} {...props} />
|
||||
@ -72,7 +69,7 @@ const ChangePhoneDialog = props => (
|
||||
ChangePhoneDialog.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default ChangePhoneDialog;
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/ChangeUserStatusDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -14,11 +14,16 @@ import {
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { utils } from "asc-web-common";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { updateUserStatus } from "../../../store/people/actions";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "ChangeUserStatusDialog",
|
||||
localesPath: "dialogs/ChangeUserStatusDialog"
|
||||
});
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ChangeUserStatusDialogComponent extends React.Component {
|
||||
@ -189,6 +194,7 @@ ChangeUserStatusDialog.propTypes = {
|
||||
selectedUsers: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default connect(null, { updateUserStatus })(
|
||||
withRouter(ChangeUserStatusDialog)
|
||||
);
|
||||
export default connect(
|
||||
null,
|
||||
{ updateUserStatus }
|
||||
)(withRouter(ChangeUserStatusDialog));
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/ChangeUserTypeDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -14,11 +14,16 @@ import {
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import i18n from "./i18n";
|
||||
import { utils } from "asc-web-common";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { updateUserType } from "../../../store/people/actions";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "ChangeUserTypeDialog",
|
||||
localesPath: "dialogs/ChangeUserTypeDialog"
|
||||
});
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ChangeUserTypeDialogComponent extends React.Component {
|
||||
@ -178,6 +183,7 @@ ChangeUserTypeDialog.propTypes = {
|
||||
selectedUsers: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default connect(null, { updateUserType })(
|
||||
withRouter(ChangeUserTypeDialog)
|
||||
);
|
||||
export default connect(
|
||||
null,
|
||||
{ updateUserType }
|
||||
)(withRouter(ChangeUserTypeDialog));
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/DeleteProfileEverDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -2,17 +2,17 @@ import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from "react-router";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
Button,
|
||||
Text
|
||||
} from "asc-web-components";
|
||||
import { toastr, ModalDialog, Button, Text } from "asc-web-components";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import { fetchPeople } from '../../../store/people/actions';
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import { fetchPeople } from "../../../store/people/actions";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "DeleteProfileEverDialog",
|
||||
localesPath: "dialogs/DeleteProfileEverDialog"
|
||||
});
|
||||
|
||||
const { deleteUser } = api.people;
|
||||
const { Filter } = api;
|
||||
const { changeLanguage } = utils;
|
||||
@ -31,20 +31,20 @@ class DeleteProfileEverDialogComponent extends React.Component {
|
||||
const { onClose, filter, fetchPeople, user, t } = this.props;
|
||||
this.setState({ isRequestRunning: true }, () => {
|
||||
deleteUser(user.id)
|
||||
.then((res) => {
|
||||
toastr.success(t('SuccessfullyDeleteUserInfoMessage'));
|
||||
.then(res => {
|
||||
toastr.success(t("SuccessfullyDeleteUserInfoMessage"));
|
||||
return fetchPeople(filter);
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => {
|
||||
this.setState({ isRequestRunning: false }, () => onClose());
|
||||
});
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
onReassignDataClick = () => {
|
||||
const { history, settings, user } = this.props;
|
||||
history.push(`${settings.homepage}/reassign/${user.userName}`)
|
||||
history.push(`${settings.homepage}/reassign/${user.userName}`);
|
||||
};
|
||||
|
||||
render() {
|
||||
@ -57,37 +57,36 @@ class DeleteProfileEverDialogComponent extends React.Component {
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
headerContent={t('Confirmation')}
|
||||
headerContent={t("Confirmation")}
|
||||
bodyContent={
|
||||
<>
|
||||
<Text>
|
||||
<Trans i18nKey='DeleteUserConfirmation' i18n={i18n}>
|
||||
{{ userCaption }} <strong>{{ user: user.displayName }}</strong> will be deleted.
|
||||
</Trans>
|
||||
<Trans i18nKey="DeleteUserConfirmation" i18n={i18n}>
|
||||
{{ userCaption }}{" "}
|
||||
<strong>{{ user: user.displayName }}</strong> will be deleted.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text>{t('NotBeUndone')}</Text>
|
||||
<Text color="#c30" fontSize="18px" className='warning-text'>
|
||||
{t('Warning')}
|
||||
</Text>
|
||||
<Text>
|
||||
{t('DeleteUserDataConfirmation')}
|
||||
<Text>{t("NotBeUndone")}</Text>
|
||||
<Text color="#c30" fontSize="18px" className="warning-text">
|
||||
{t("Warning")}
|
||||
</Text>
|
||||
<Text>{t("DeleteUserDataConfirmation")}</Text>
|
||||
</>
|
||||
}
|
||||
footerContent={
|
||||
<>
|
||||
<Button
|
||||
key="OKBtn"
|
||||
label={t('OKButton')}
|
||||
label={t("OKButton")}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onDeleteProfileEver}
|
||||
isLoading={isRequestRunning}
|
||||
/>
|
||||
<Button
|
||||
className='button-dialog'
|
||||
className="button-dialog"
|
||||
key="ReassignBtn"
|
||||
label={t('ReassignData')}
|
||||
label={t("ReassignData")}
|
||||
size="medium"
|
||||
onClick={this.onReassignDataClick}
|
||||
isDisabled={isRequestRunning}
|
||||
@ -100,7 +99,9 @@ class DeleteProfileEverDialogComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const DeleteProfileEverDialogTranslated = withTranslation()(DeleteProfileEverDialogComponent);
|
||||
const DeleteProfileEverDialogTranslated = withTranslation()(
|
||||
DeleteProfileEverDialogComponent
|
||||
);
|
||||
|
||||
const DeleteProfileEverDialog = props => (
|
||||
<DeleteProfileEverDialogTranslated i18n={i18n} {...props} />
|
||||
@ -122,4 +123,7 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, { fetchPeople })(withRouter(DeleteProfileEverDialog));
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ fetchPeople }
|
||||
)(withRouter(DeleteProfileEverDialog));
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/DeleteSelfProfileDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -1,16 +1,14 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
Button,
|
||||
Link,
|
||||
Text
|
||||
} from "asc-web-components";
|
||||
import { toastr, ModalDialog, Button, Link, Text } from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "DeleteSelfProfileDialog",
|
||||
localesPath: "dialogs/DeleteSelfProfileDialog"
|
||||
});
|
||||
const { sendInstructionsToDelete } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
@ -28,15 +26,15 @@ class DeleteSelfProfileDialogComponent extends React.Component {
|
||||
const { onClose } = this.props;
|
||||
this.setState({ isRequestRunning: true }, () => {
|
||||
sendInstructionsToDelete()
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
toastr.success(res);
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => {
|
||||
this.setState({ isRequestRunning: false }, () => onClose());
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
console.log("DeleteSelfProfileDialog render");
|
||||
@ -48,10 +46,17 @@ class DeleteSelfProfileDialogComponent extends React.Component {
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
headerContent={t('DeleteProfileTitle')}
|
||||
headerContent={t("DeleteProfileTitle")}
|
||||
bodyContent={
|
||||
<Text fontSize='13px'>
|
||||
{t('DeleteProfileInfo')} <Link type="page" href={`mailto:${email}`} noHover color='#316DAA' title={email}>
|
||||
<Text fontSize="13px">
|
||||
{t("DeleteProfileInfo")}{" "}
|
||||
<Link
|
||||
type="page"
|
||||
href={`mailto:${email}`}
|
||||
noHover
|
||||
color="#316DAA"
|
||||
title={email}
|
||||
>
|
||||
{email}
|
||||
</Link>
|
||||
</Text>
|
||||
@ -60,16 +65,16 @@ class DeleteSelfProfileDialogComponent extends React.Component {
|
||||
<>
|
||||
<Button
|
||||
key="SendBtn"
|
||||
label={t('SendButton')}
|
||||
label={t("SendButton")}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onDeleteSelfProfileInstructions}
|
||||
isLoading={isRequestRunning}
|
||||
/>
|
||||
<Button
|
||||
className='button-dialog'
|
||||
className="button-dialog"
|
||||
key="CloseBtn"
|
||||
label={t('CloseButton')}
|
||||
label={t("CloseButton")}
|
||||
size="medium"
|
||||
onClick={onClose}
|
||||
isDisabled={isRequestRunning}
|
||||
@ -82,8 +87,9 @@ class DeleteSelfProfileDialogComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const DeleteSelfProfileDialogTranslated = withTranslation()(DeleteSelfProfileDialogComponent);
|
||||
const DeleteSelfProfileDialogTranslated = withTranslation()(
|
||||
DeleteSelfProfileDialogComponent
|
||||
);
|
||||
|
||||
const DeleteSelfProfileDialog = props => (
|
||||
<DeleteSelfProfileDialogTranslated i18n={i18n} {...props} />
|
||||
@ -92,7 +98,7 @@ const DeleteSelfProfileDialog = props => (
|
||||
DeleteSelfProfileDialog.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
email: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default DeleteSelfProfileDialog;
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/DeleteUsersDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -14,10 +14,14 @@ import {
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import { removeUser } from "../../../store/people/actions";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "DeleteUsersDialog",
|
||||
localesPath: "dialogs/DeleteUsersDialog"
|
||||
});
|
||||
|
||||
const { Filter } = api;
|
||||
const { changeLanguage } = utils;
|
||||
@ -185,4 +189,7 @@ DeleteUsersDialog.propTypes = {
|
||||
removeUser: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(null, { removeUser })(withRouter(DeleteUsersDialog));
|
||||
export default connect(
|
||||
null,
|
||||
{ removeUser }
|
||||
)(withRouter(DeleteUsersDialog));
|
||||
|
@ -1,62 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === 'lowercase') return value.toLowerCase();
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/InviteDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === 'lowercase') return value.toLowerCase();
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -11,12 +11,17 @@ import {
|
||||
Text
|
||||
} from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "InviteDialog",
|
||||
localesPath: "dialogs/InviteDialog"
|
||||
});
|
||||
const { getShortenedLink } = api.portal;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
const textAreaName = "link-textarea";
|
||||
|
||||
class InviteDialogComponent extends React.Component {
|
||||
@ -30,7 +35,7 @@ class InviteDialogComponent extends React.Component {
|
||||
guestInvitationLink,
|
||||
isLoading: false,
|
||||
isLinkShort: false,
|
||||
visible: false,
|
||||
visible: false
|
||||
};
|
||||
}
|
||||
|
||||
@ -50,10 +55,7 @@ class InviteDialogComponent extends React.Component {
|
||||
|
||||
onGetShortenedLink = () => {
|
||||
this.setState({ isLoading: true });
|
||||
const {
|
||||
userInvitationLink,
|
||||
guestInvitationLink
|
||||
} = this.props;
|
||||
const { userInvitationLink, guestInvitationLink } = this.props;
|
||||
|
||||
getShortenedLink(userInvitationLink)
|
||||
.then(link => this.setState({ userInvitationLink: link }))
|
||||
@ -80,8 +82,8 @@ class InviteDialogComponent extends React.Component {
|
||||
copy(this.state.userInvitationLink);
|
||||
|
||||
changeLanguage(i18n)
|
||||
.then(()=> this.setState({visible: true}))
|
||||
.then(()=> toastr.success(t("LinkCopySuccess")));
|
||||
.then(() => this.setState({ visible: true }))
|
||||
.then(() => toastr.success(t("LinkCopySuccess")));
|
||||
}
|
||||
|
||||
onClickToCloseButton = () =>
|
||||
@ -93,78 +95,77 @@ class InviteDialogComponent extends React.Component {
|
||||
const { t, visible, settings, guestsCaption } = this.props;
|
||||
|
||||
return (
|
||||
this.state.visible &&
|
||||
<ModalDialogContainer>
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={this.onClose}
|
||||
headerContent={t("InviteLinkTitle")}
|
||||
bodyContent={
|
||||
<>
|
||||
<Text as="p">
|
||||
{t("HelpAnswerLinkInviteSettings")}
|
||||
</Text>
|
||||
<Text className="text-dialog" as="p">
|
||||
{t("InviteLinkValidInterval", { count: 7 })}
|
||||
</Text>
|
||||
<div className="flex">
|
||||
<div>
|
||||
<Link
|
||||
className="link-dialog"
|
||||
type="action"
|
||||
isHovered={true}
|
||||
onClick={this.onCopyLinkToClipboard}
|
||||
>
|
||||
{t("CopyToClipboard")}
|
||||
</Link>
|
||||
{settings && !this.state.isLinkShort && (
|
||||
this.state.visible && (
|
||||
<ModalDialogContainer>
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={this.onClose}
|
||||
headerContent={t("InviteLinkTitle")}
|
||||
bodyContent={
|
||||
<>
|
||||
<Text as="p">{t("HelpAnswerLinkInviteSettings")}</Text>
|
||||
<Text className="text-dialog" as="p">
|
||||
{t("InviteLinkValidInterval", { count: 7 })}
|
||||
</Text>
|
||||
<div className="flex">
|
||||
<div>
|
||||
<Link
|
||||
className="link-dialog"
|
||||
type="action"
|
||||
isHovered={true}
|
||||
onClick={this.onGetShortenedLink}
|
||||
onClick={this.onCopyLinkToClipboard}
|
||||
>
|
||||
{t("GetShortenLink")}
|
||||
{t("CopyToClipboard")}
|
||||
</Link>
|
||||
)}
|
||||
{settings && !this.state.isLinkShort && (
|
||||
<Link
|
||||
type="action"
|
||||
isHovered={true}
|
||||
onClick={this.onGetShortenedLink}
|
||||
>
|
||||
{t("GetShortenLink")}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<Checkbox
|
||||
label={t("InviteUsersAsCollaborators", { guestsCaption })}
|
||||
isChecked={this.state.isGuest}
|
||||
onChange={this.onCheckedGuest}
|
||||
isDisabled={this.state.isLoading}
|
||||
/>
|
||||
</div>
|
||||
<Checkbox
|
||||
label={t("InviteUsersAsCollaborators", { guestsCaption })}
|
||||
isChecked={this.state.isGuest}
|
||||
onChange={this.onCheckedGuest}
|
||||
<Textarea
|
||||
className="textarea-dialog"
|
||||
isReadOnly={true}
|
||||
isDisabled={this.state.isLoading}
|
||||
name={textAreaName}
|
||||
value={
|
||||
this.state.isGuest
|
||||
? this.state.guestInvitationLink
|
||||
: this.state.userInvitationLink
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Textarea
|
||||
className="textarea-dialog"
|
||||
isReadOnly={true}
|
||||
isDisabled={this.state.isLoading}
|
||||
name={textAreaName}
|
||||
value={
|
||||
this.state.isGuest
|
||||
? this.state.guestInvitationLink
|
||||
: this.state.userInvitationLink
|
||||
}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
footerContent={
|
||||
<>
|
||||
<Button
|
||||
key="CloseBtn"
|
||||
label={
|
||||
this.state.isLoading
|
||||
? t("LoadingProcessing")
|
||||
: t("CloseButton")
|
||||
}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onClickToCloseButton}
|
||||
isLoading={this.state.isLoading}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ModalDialogContainer>
|
||||
</>
|
||||
}
|
||||
footerContent={
|
||||
<>
|
||||
<Button
|
||||
key="CloseBtn"
|
||||
label={
|
||||
this.state.isLoading
|
||||
? t("LoadingProcessing")
|
||||
: t("CloseButton")
|
||||
}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onClickToCloseButton}
|
||||
isLoading={this.state.isLoading}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ModalDialogContainer>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -180,9 +181,7 @@ const mapStateToProps = state => {
|
||||
|
||||
const InviteDialogTranslated = withTranslation()(InviteDialogComponent);
|
||||
|
||||
const InviteDialog = props => (
|
||||
<InviteDialogTranslated i18n={i18n} {...props} />
|
||||
);
|
||||
const InviteDialog = props => <InviteDialogTranslated i18n={i18n} {...props} />;
|
||||
|
||||
InviteDialog.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/SendInviteDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -13,10 +13,13 @@ import {
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "SendInviteDialog",
|
||||
localesPath: "dialogs/SendInviteDialog"
|
||||
});
|
||||
const { resendUserInvites } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === 'lowercase') return value.toLowerCase();
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/GroupAction/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === 'lowercase') return value.toLowerCase();
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -6,15 +6,18 @@ import {
|
||||
ArticleHeaderContent,
|
||||
ArticleMainButtonContent,
|
||||
ArticleBodyContent
|
||||
} from '../../Article';
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
import i18n from "./i18n";
|
||||
} from "../../Article";
|
||||
import { SectionHeaderContent, SectionBodyContent } from "./Section";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
import { fetchGroup, resetGroup } from "../../../store/group/actions";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "GroupAction",
|
||||
localesPath: "pages/GroupAction"
|
||||
});
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class GroupAction extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
const { match, fetchGroup, t } = this.props;
|
||||
const { groupId } = match.params;
|
||||
@ -37,7 +40,7 @@ class GroupAction extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("GroupAction render")
|
||||
console.log("GroupAction render");
|
||||
|
||||
const { group, match } = this.props;
|
||||
|
||||
@ -68,24 +71,24 @@ class GroupAction extends React.Component {
|
||||
</PageLayout.SectionBody>
|
||||
</PageLayout>
|
||||
) : (
|
||||
<PageLayout>
|
||||
<PageLayout.ArticleHeader>
|
||||
<ArticleHeaderContent />
|
||||
</PageLayout.ArticleHeader>
|
||||
<PageLayout>
|
||||
<PageLayout.ArticleHeader>
|
||||
<ArticleHeaderContent />
|
||||
</PageLayout.ArticleHeader>
|
||||
|
||||
<PageLayout.ArticleMainButton>
|
||||
<ArticleMainButtonContent />
|
||||
</PageLayout.ArticleMainButton>
|
||||
<PageLayout.ArticleMainButton>
|
||||
<ArticleMainButtonContent />
|
||||
</PageLayout.ArticleMainButton>
|
||||
|
||||
<PageLayout.ArticleBody>
|
||||
<ArticleBodyContent />
|
||||
</PageLayout.ArticleBody>
|
||||
<PageLayout.ArticleBody>
|
||||
<ArticleBodyContent />
|
||||
</PageLayout.ArticleBody>
|
||||
|
||||
<PageLayout.SectionBody>
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
</PageLayout.SectionBody>
|
||||
</PageLayout>
|
||||
)}
|
||||
<PageLayout.SectionBody>
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
</PageLayout.SectionBody>
|
||||
</PageLayout>
|
||||
)}
|
||||
</I18nextProvider>
|
||||
);
|
||||
}
|
||||
@ -109,8 +112,10 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps,
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchGroup,
|
||||
resetGroup
|
||||
})(GroupActionContainer);
|
||||
}
|
||||
)(GroupActionContainer);
|
||||
|
@ -31,9 +31,18 @@ import {
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { Loader } from "asc-web-components";
|
||||
import { store, api, constants } from 'asc-web-common';
|
||||
import i18n from '../../i18n';
|
||||
import { ChangeEmailDialog, ChangePasswordDialog, DeleteSelfProfileDialog, DeleteProfileEverDialog } from '../../../../dialogs';
|
||||
import { store, api, constants } from "asc-web-common";
|
||||
import {
|
||||
ChangeEmailDialog,
|
||||
ChangePasswordDialog,
|
||||
DeleteSelfProfileDialog,
|
||||
DeleteProfileEverDialog
|
||||
} from "../../../../dialogs";
|
||||
import { createI18N } from "../../../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "Home",
|
||||
localesPath: "pages/Home"
|
||||
});
|
||||
const { isArrayEqual } = utils.array;
|
||||
const { isAdmin, isMe } = store.auth.selectors;
|
||||
const { resendUserInvites } = api.people;
|
||||
@ -50,7 +59,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
changeEmail: false,
|
||||
changePassword: false,
|
||||
deleteSelfProfile: false,
|
||||
deleteProfileEver: false,
|
||||
deleteProfileEver: false
|
||||
},
|
||||
isEmailValid: false
|
||||
};
|
||||
@ -80,18 +89,24 @@ class SectionBodyContent extends React.PureComponent {
|
||||
history.push(`${settings.homepage}/edit/${user.userName}`);
|
||||
};
|
||||
|
||||
toggleChangePasswordDialog = (email) => {
|
||||
const checkedEmail = typeof (email) === 'string' ? email : undefined;
|
||||
toggleChangePasswordDialog = email => {
|
||||
const checkedEmail = typeof email === "string" ? email : undefined;
|
||||
this.setState({
|
||||
dialogsVisible: { ...this.state.dialogsVisible, changePassword: !this.state.dialogsVisible.changePassword },
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
changePassword: !this.state.dialogsVisible.changePassword
|
||||
},
|
||||
user: { email: checkedEmail }
|
||||
});
|
||||
};
|
||||
|
||||
toggleChangeEmailDialog = (user) => {
|
||||
toggleChangeEmailDialog = user => {
|
||||
const checkedUser = user ? user : {};
|
||||
this.setState({
|
||||
dialogsVisible: { ...this.state.dialogsVisible, changeEmail: !this.state.dialogsVisible.changeEmail },
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
changeEmail: !this.state.dialogsVisible.changeEmail
|
||||
},
|
||||
user: {
|
||||
email: checkedUser.email,
|
||||
id: checkedUser.id
|
||||
@ -104,7 +119,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
|
||||
onLoading(true);
|
||||
updateUserStatus(EmployeeStatus.Disabled, [user.id], isRefetchPeople)
|
||||
.then(() => toastr.success(t('SuccessChangeUserStatus')))
|
||||
.then(() => toastr.success(t("SuccessChangeUserStatus")))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => onLoading(false));
|
||||
};
|
||||
@ -114,7 +129,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
|
||||
onLoading(true);
|
||||
updateUserStatus(EmployeeStatus.Active, [user.id], isRefetchPeople)
|
||||
.then(() => toastr.success(t('SuccessChangeUserStatus')))
|
||||
.then(() => toastr.success(t("SuccessChangeUserStatus")))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => onLoading(false));
|
||||
};
|
||||
@ -131,19 +146,25 @@ class SectionBodyContent extends React.PureComponent {
|
||||
toggleDeleteProfileEverDialog = user => {
|
||||
const checkedUser = user ? user : {};
|
||||
this.setState({
|
||||
dialogsVisible: { ...this.state.dialogsVisible, deleteProfileEver: !this.state.dialogsVisible.deleteProfileEver },
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
deleteProfileEver: !this.state.dialogsVisible.deleteProfileEver
|
||||
},
|
||||
user: {
|
||||
id: checkedUser.id,
|
||||
displayName: checkedUser.displayName,
|
||||
userName: checkedUser.userName,
|
||||
userName: checkedUser.userName
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
toggleDeleteSelfProfileDialog = email => {
|
||||
const checkedEmail = typeof (email) === 'string' ? email : undefined;
|
||||
const checkedEmail = typeof email === "string" ? email : undefined;
|
||||
this.setState({
|
||||
dialogsVisible: { ...this.state.dialogsVisible, deleteSelfProfile: !this.state.dialogsVisible.deleteSelfProfile },
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
deleteSelfProfile: !this.state.dialogsVisible.deleteSelfProfile
|
||||
},
|
||||
user: { email: checkedEmail }
|
||||
});
|
||||
};
|
||||
@ -154,10 +175,13 @@ class SectionBodyContent extends React.PureComponent {
|
||||
resendUserInvites([user.id])
|
||||
.then(() =>
|
||||
toastr.success(
|
||||
<Trans i18nKey='MessageEmailActivationInstuctionsSentOnEmail' i18n={i18n}>
|
||||
<Trans
|
||||
i18nKey="MessageEmailActivationInstuctionsSentOnEmail"
|
||||
i18n={i18n}
|
||||
>
|
||||
The email activation instructions have been sent to the
|
||||
<strong>{{ email: user.email }}</strong> email address
|
||||
</Trans>
|
||||
<strong>{{ email: user.email }}</strong> email address
|
||||
</Trans>
|
||||
)
|
||||
)
|
||||
.catch(error => toastr.error(error))
|
||||
@ -186,11 +210,11 @@ class SectionBodyContent extends React.PureComponent {
|
||||
onClick: this.onEmailSentClick.bind(this, user.email)
|
||||
},
|
||||
user.mobilePhone &&
|
||||
isMobileOnly && {
|
||||
key: "send-message",
|
||||
label: t("LblSendMessage"),
|
||||
onClick: this.onSendMessageClick.bind(this, user.mobilePhone)
|
||||
},
|
||||
isMobileOnly && {
|
||||
key: "send-message",
|
||||
label: t("LblSendMessage"),
|
||||
onClick: this.onSendMessageClick.bind(this, user.mobilePhone)
|
||||
},
|
||||
{ key: "separator", isSeparator: true },
|
||||
{
|
||||
key: "edit",
|
||||
@ -211,15 +235,18 @@ class SectionBodyContent extends React.PureComponent {
|
||||
? viewer.isOwner
|
||||
? null
|
||||
: {
|
||||
key: "delete-profile",
|
||||
label: t("DeleteSelfProfile"),
|
||||
onClick: this.toggleDeleteSelfProfileDialog.bind(this, user.email)
|
||||
}
|
||||
key: "delete-profile",
|
||||
label: t("DeleteSelfProfile"),
|
||||
onClick: this.toggleDeleteSelfProfileDialog.bind(
|
||||
this,
|
||||
user.email
|
||||
)
|
||||
}
|
||||
: {
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick.bind(this, user)
|
||||
}
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick.bind(this, user)
|
||||
}
|
||||
];
|
||||
case "disabled":
|
||||
return [
|
||||
@ -257,17 +284,17 @@ class SectionBodyContent extends React.PureComponent {
|
||||
onClick: this.onInviteAgainClick.bind(this, user)
|
||||
},
|
||||
!isSelf &&
|
||||
(user.status === EmployeeStatus.Active
|
||||
? {
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick.bind(this, user)
|
||||
}
|
||||
: {
|
||||
key: "enable",
|
||||
label: t("EnableUserButton"),
|
||||
onClick: this.onEnableClick.bind(this, user)
|
||||
}),
|
||||
(user.status === EmployeeStatus.Active
|
||||
? {
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick.bind(this, user)
|
||||
}
|
||||
: {
|
||||
key: "enable",
|
||||
label: t("EnableUserButton"),
|
||||
onClick: this.onEnableClick.bind(this, user)
|
||||
}),
|
||||
isSelf && {
|
||||
key: "delete-profile",
|
||||
label: t("DeleteSelfProfile"),
|
||||
@ -312,102 +339,113 @@ class SectionBodyContent extends React.PureComponent {
|
||||
|
||||
render() {
|
||||
//console.log("Home SectionBodyContent render()");
|
||||
const { users, viewer, selection, history, settings, t, filter } = this.props;
|
||||
const {
|
||||
users,
|
||||
viewer,
|
||||
selection,
|
||||
history,
|
||||
settings,
|
||||
t,
|
||||
filter
|
||||
} = this.props;
|
||||
const { dialogsVisible, user } = this.state;
|
||||
|
||||
return users == null
|
||||
? (<Loader className="pageLoader" type="rombs" size='40px' />)
|
||||
: users.length > 0 ? (
|
||||
<>
|
||||
<RowContainer useReactWindow={false}>
|
||||
{users.map(user => {
|
||||
const contextOptions = this.getUserContextOptions(user, viewer).filter(o => o);
|
||||
const contextOptionsProps = !contextOptions.length
|
||||
? {}
|
||||
: { contextOptions };
|
||||
const checked = isUserSelected(selection, user.id);
|
||||
const checkedProps = isAdmin(viewer) ? { checked } : {};
|
||||
const element = (
|
||||
<Avatar
|
||||
size="small"
|
||||
role={getUserRole(user)}
|
||||
userName={user.displayName}
|
||||
source={user.avatar}
|
||||
return users == null ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
) : users.length > 0 ? (
|
||||
<>
|
||||
<RowContainer useReactWindow={false}>
|
||||
{users.map(user => {
|
||||
const contextOptions = this.getUserContextOptions(
|
||||
user,
|
||||
viewer
|
||||
).filter(o => o);
|
||||
const contextOptionsProps = !contextOptions.length
|
||||
? {}
|
||||
: { contextOptions };
|
||||
const checked = isUserSelected(selection, user.id);
|
||||
const checkedProps = isAdmin(viewer) ? { checked } : {};
|
||||
const element = (
|
||||
<Avatar
|
||||
size="small"
|
||||
role={getUserRole(user)}
|
||||
userName={user.displayName}
|
||||
source={user.avatar}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Row
|
||||
key={user.id}
|
||||
status={getUserStatus(user)}
|
||||
data={user}
|
||||
element={element}
|
||||
onSelect={this.onContentRowSelect}
|
||||
{...checkedProps}
|
||||
{...contextOptionsProps}
|
||||
needForUpdate={this.needForUpdate}
|
||||
>
|
||||
<UserContent
|
||||
user={user}
|
||||
history={history}
|
||||
settings={settings}
|
||||
selectGroup={this.props.selectGroup}
|
||||
/>
|
||||
);
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</RowContainer>
|
||||
|
||||
return (
|
||||
<Row
|
||||
key={user.id}
|
||||
status={getUserStatus(user)}
|
||||
data={user}
|
||||
element={element}
|
||||
onSelect={this.onContentRowSelect}
|
||||
{...checkedProps}
|
||||
{...contextOptionsProps}
|
||||
needForUpdate={this.needForUpdate}
|
||||
>
|
||||
<UserContent
|
||||
user={user}
|
||||
history={history}
|
||||
settings={settings}
|
||||
selectGroup={this.props.selectGroup}
|
||||
/>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</RowContainer>
|
||||
|
||||
{dialogsVisible.changeEmail &&
|
||||
<ChangeEmailDialog
|
||||
visible={dialogsVisible.changeEmail}
|
||||
onClose={this.toggleChangeEmailDialog}
|
||||
user={user}
|
||||
/>
|
||||
}
|
||||
{dialogsVisible.changePassword &&
|
||||
<ChangePasswordDialog
|
||||
visible={dialogsVisible.changePassword}
|
||||
onClose={this.toggleChangePasswordDialog}
|
||||
email={user.email}
|
||||
/>
|
||||
}
|
||||
|
||||
{dialogsVisible.deleteSelfProfile &&
|
||||
<DeleteSelfProfileDialog
|
||||
visible={dialogsVisible.deleteSelfProfile}
|
||||
onClose={this.toggleDeleteSelfProfileDialog}
|
||||
email={user.email}
|
||||
/>
|
||||
}
|
||||
|
||||
{dialogsVisible.deleteProfileEver &&
|
||||
<DeleteProfileEverDialog
|
||||
visible={dialogsVisible.deleteProfileEver}
|
||||
onClose={this.toggleDeleteProfileEverDialog}
|
||||
user={user}
|
||||
filter={filter}
|
||||
settings={settings}
|
||||
history={history}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
) : (
|
||||
<EmptyScreenContainer
|
||||
imageSrc="images/empty_screen_filter.png"
|
||||
imageAlt="Empty Screen Filter image"
|
||||
headerText={t("NotFoundTitle")}
|
||||
descriptionText={t("NotFoundDescription")}
|
||||
buttons={
|
||||
<>
|
||||
<Icons.CrossIcon size="small" style={{ marginRight: "4px" }} />
|
||||
<Link type="action" isHovered={true} onClick={this.onResetFilter}>
|
||||
{t("ClearButton")}
|
||||
</Link>
|
||||
</>
|
||||
}
|
||||
{dialogsVisible.changeEmail && (
|
||||
<ChangeEmailDialog
|
||||
visible={dialogsVisible.changeEmail}
|
||||
onClose={this.toggleChangeEmailDialog}
|
||||
user={user}
|
||||
/>
|
||||
);
|
||||
)}
|
||||
{dialogsVisible.changePassword && (
|
||||
<ChangePasswordDialog
|
||||
visible={dialogsVisible.changePassword}
|
||||
onClose={this.toggleChangePasswordDialog}
|
||||
email={user.email}
|
||||
/>
|
||||
)}
|
||||
|
||||
{dialogsVisible.deleteSelfProfile && (
|
||||
<DeleteSelfProfileDialog
|
||||
visible={dialogsVisible.deleteSelfProfile}
|
||||
onClose={this.toggleDeleteSelfProfileDialog}
|
||||
email={user.email}
|
||||
/>
|
||||
)}
|
||||
|
||||
{dialogsVisible.deleteProfileEver && (
|
||||
<DeleteProfileEverDialog
|
||||
visible={dialogsVisible.deleteProfileEver}
|
||||
onClose={this.toggleDeleteProfileEverDialog}
|
||||
user={user}
|
||||
filter={filter}
|
||||
settings={settings}
|
||||
history={history}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<EmptyScreenContainer
|
||||
imageSrc="images/empty_screen_filter.png"
|
||||
imageAlt="Empty Screen Filter image"
|
||||
headerText={t("NotFoundTitle")}
|
||||
descriptionText={t("NotFoundDescription")}
|
||||
buttons={
|
||||
<>
|
||||
<Icons.CrossIcon size="small" style={{ marginRight: "4px" }} />
|
||||
<Link type="action" isHovered={true} onClick={this.onResetFilter}>
|
||||
{t("ClearButton")}
|
||||
</Link>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,5 +466,13 @@ const mapStateToProps = state => {
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ selectUser, deselectUser, setSelection, updateUserStatus, resetFilter, fetchPeople, selectGroup }
|
||||
{
|
||||
selectUser,
|
||||
deselectUser,
|
||||
setSelection,
|
||||
updateUserStatus,
|
||||
resetFilter,
|
||||
fetchPeople,
|
||||
selectGroup
|
||||
}
|
||||
)(withRouter(withTranslation()(SectionBodyContent)));
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/Home/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -4,8 +4,7 @@ import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import { RequestLoader } from "asc-web-components";
|
||||
import { PageLayout, utils } from "asc-web-common";
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from "./i18n";
|
||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||
import {
|
||||
ArticleHeaderContent,
|
||||
ArticleBodyContent,
|
||||
@ -19,6 +18,11 @@ import {
|
||||
} from "./Section";
|
||||
import { setSelected } from "../../../store/people/actions";
|
||||
import { getSelectedGroup } from "../../../store/people/selectors";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "Home",
|
||||
localesPath: "pages/Home"
|
||||
});
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class PureHome extends React.Component {
|
||||
@ -98,16 +102,13 @@ class PureHome extends React.Component {
|
||||
<RequestLoader
|
||||
visible={this.state.isLoading}
|
||||
zIndex={256}
|
||||
loaderSize='16px'
|
||||
loaderSize="16px"
|
||||
loaderColor={"#999"}
|
||||
label={`${t('LoadingProcessing')} ${t('LoadingDescription')}`}
|
||||
fontSize='12px'
|
||||
label={`${t("LoadingProcessing")} ${t("LoadingDescription")}`}
|
||||
fontSize="12px"
|
||||
fontColor={"#999"}
|
||||
/>
|
||||
<PageLayout
|
||||
withBodyScroll={true}
|
||||
withBodyAutoFocus={true}
|
||||
>
|
||||
<PageLayout withBodyScroll={true} withBodyAutoFocus={true}>
|
||||
<PageLayout.ArticleHeader>
|
||||
<ArticleHeaderContent />
|
||||
</PageLayout.ArticleHeader>
|
||||
@ -143,7 +144,7 @@ class PureHome extends React.Component {
|
||||
onChange={this.onRowChange}
|
||||
/>
|
||||
</PageLayout.SectionBody>
|
||||
|
||||
|
||||
<PageLayout.SectionPaging>
|
||||
<SectionPagingContent onLoading={this.onLoading} />
|
||||
</PageLayout.SectionPaging>
|
||||
@ -157,8 +158,12 @@ const HomeContainer = withTranslation()(PureHome);
|
||||
|
||||
const Home = props => {
|
||||
changeLanguage(i18n);
|
||||
return (<I18nextProvider i18n={i18n}><HomeContainer {...props} /></I18nextProvider>);
|
||||
}
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<HomeContainer {...props} />
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Home.propTypes = {
|
||||
users: PropTypes.array,
|
||||
|
@ -1,277 +0,0 @@
|
||||
import React, { memo } from "react";
|
||||
import { withRouter } from "react-router";
|
||||
// import { useTranslation } from 'react-i18next';
|
||||
import { connect } from "react-redux";
|
||||
import styled from 'styled-components';
|
||||
import { Text, Button, Avatar, toastr } from 'asc-web-components';
|
||||
import { api } from 'asc-web-common';
|
||||
import { toEmployeeWrapper } from "../../../../../store/people/selectors";
|
||||
import { importUsers } from "../../../../../store/people/actions";
|
||||
import { FixedSizeList as List, areEqual } from 'react-window';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
const LoadCsvWrapper = styled.div`
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
max-width: 1024px;
|
||||
`;
|
||||
|
||||
const SelectSourceWrapper = styled.div`
|
||||
margin-top: 24px;
|
||||
`;
|
||||
|
||||
const StyledFileInput = styled.div`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
height: 36px;
|
||||
|
||||
input[type="file"] {
|
||||
height: 100%;
|
||||
font-size: 200px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledFieldContainer = styled.div`
|
||||
position: relative;
|
||||
|
||||
@media (min-width:768px) {
|
||||
margin-top: 14px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledAvatar = styled.div`
|
||||
float: left;
|
||||
|
||||
@media (max-width:768px) {
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledField = styled.div`
|
||||
line-height: 14px;
|
||||
min-width: 100px;
|
||||
padding: 4px 16px;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
@media (min-width:768px) {
|
||||
margin-top: 4px;
|
||||
display: inline-block !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledProgress = styled.div`
|
||||
position: absolute;
|
||||
max-width: 100%;
|
||||
width: ${props => props.completed && `${props.completed}%`};
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
background-color: #7ACE9B;
|
||||
opacity: 0.3;
|
||||
border-radius: 3px;
|
||||
z-index: -1;
|
||||
transition-property: width;
|
||||
transition-duration: 1s;
|
||||
`;
|
||||
|
||||
class ImportRow extends React.PureComponent {
|
||||
render() {
|
||||
const { items, completed } = this.props;
|
||||
|
||||
const fullName = items[0] + ' ' + items[1];
|
||||
const firstName = items[0];
|
||||
const lastName = items[1];
|
||||
const email = items[2];
|
||||
|
||||
return (
|
||||
<StyledFieldContainer key={email}>
|
||||
<StyledAvatar>
|
||||
<Avatar size='small' role='user' userName={fullName} />
|
||||
</StyledAvatar>
|
||||
<StyledField style={{ display: 'inline-block' }}>{firstName}</StyledField>
|
||||
<StyledField style={{ display: 'inline-block' }}>{lastName}</StyledField>
|
||||
<StyledField style={{ display: 'block' }}>{email}</StyledField>
|
||||
<StyledProgress completed={completed} />
|
||||
</StyledFieldContainer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class SectionBodyContent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
splittedLines: [],
|
||||
importing: false
|
||||
}
|
||||
}
|
||||
|
||||
getAsText = (fileToRead) => {
|
||||
if (!fileToRead) return;
|
||||
|
||||
let reader = new FileReader();
|
||||
reader.readAsText(fileToRead);
|
||||
reader.onload = this.loadHandler;
|
||||
reader.onerror = this.errorHandler;
|
||||
}
|
||||
|
||||
loadHandler = (event) => {
|
||||
const csv = event.target.result;
|
||||
this.processData(csv);
|
||||
}
|
||||
|
||||
errorHandler = (event) => {
|
||||
if (event.target.error.name === 'NotReadableError') {
|
||||
alert(event.target.error.name);
|
||||
}
|
||||
}
|
||||
|
||||
processData = (csv) => {
|
||||
const allTextLines = csv.split(/\r\n|\n/);
|
||||
const splittedLines = allTextLines.map(line => line.split(','));
|
||||
const filteredLines = splittedLines.filter(line => (line[0].length > 0) && line);
|
||||
|
||||
this.setState({
|
||||
splittedLines: filteredLines
|
||||
});
|
||||
}
|
||||
|
||||
createRows = rows => rows.map(data => {
|
||||
return (
|
||||
<ImportRow items={data} />
|
||||
);
|
||||
});
|
||||
|
||||
renderRow = memo(({ data, index, style }) => {
|
||||
return (
|
||||
<div style={style}>
|
||||
{data[index]}
|
||||
</div>
|
||||
)
|
||||
}, areEqual);
|
||||
|
||||
prepareUsersData = data => {
|
||||
const { splittedLines } = this.state;
|
||||
const rawUsers = splittedLines || data;
|
||||
|
||||
const preparedUsers = rawUsers.map(user => {
|
||||
const userObj = {};
|
||||
|
||||
userObj.firstName = user[0];
|
||||
userObj.lastName = user[1];
|
||||
userObj.email = user[2];
|
||||
|
||||
return toEmployeeWrapper(userObj);
|
||||
});
|
||||
|
||||
return preparedUsers;
|
||||
}
|
||||
|
||||
makeChunks = (data, size = 50) => {
|
||||
let temp = [];
|
||||
|
||||
for (let i = 0; i < data.length; i += size) {
|
||||
temp.push(data.slice(i, i + size));
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
runImport = users => {
|
||||
const chunks = this.makeChunks(users);
|
||||
|
||||
chunks.map(async chunk => { //TODO: do something better than an asynchronous carnival
|
||||
for (const user of chunk) {
|
||||
await api.people.createUser(user);
|
||||
}
|
||||
});
|
||||
|
||||
this.setState({
|
||||
importing: false
|
||||
});
|
||||
}
|
||||
|
||||
onImportClick = () => {
|
||||
const users = this.prepareUsersData();
|
||||
|
||||
this.setState({
|
||||
importing: true
|
||||
});
|
||||
|
||||
this.runImport(users);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { splittedLines, importing } = this.state;
|
||||
// const { t } = useTranslation();
|
||||
const rows = this.createRows(splittedLines);
|
||||
const isImportEnabled = true;
|
||||
|
||||
const renderList = ({ height, width }) => {
|
||||
const itemHeight = (width < 768) ? 56 : 36;
|
||||
return (
|
||||
<List
|
||||
className="List"
|
||||
height={height}
|
||||
width={width}
|
||||
itemSize={itemHeight}
|
||||
itemCount={rows.length}
|
||||
itemData={rows}
|
||||
>
|
||||
{this.renderRow}
|
||||
</List>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text fontSize='18px' >
|
||||
Functionality at development stage.
|
||||
</Text>
|
||||
<br />
|
||||
<Text fontSize='14px' >
|
||||
Files are formatted according to <b>CSV RFC 4180</b> rules. <br />
|
||||
<b>Column Order:</b> FirstName, LastName, Email. <br />
|
||||
Comma delimiter, strings in unix format. <br />
|
||||
</Text>
|
||||
<SelectSourceWrapper>
|
||||
<StyledFileInput>
|
||||
<Button size='big' primary={true} scale={true} label="Upload CSV" isDisabled={!isImportEnabled} />
|
||||
{isImportEnabled &&
|
||||
<input type="file" name="file" onChange={(e) => this.getAsText(e.target.files[0])} accept='.csv' />
|
||||
}
|
||||
</StyledFileInput>
|
||||
</SelectSourceWrapper>
|
||||
<br />
|
||||
<Text fontSize='14px' >
|
||||
Ready for import: {splittedLines.length} of {splittedLines.length}
|
||||
</Text>
|
||||
<LoadCsvWrapper>
|
||||
<AutoSizer>
|
||||
{renderList}
|
||||
</AutoSizer>
|
||||
</LoadCsvWrapper>
|
||||
<StyledFileInput>
|
||||
<Button size='big' primary={true} scale={true} onClick={this.onImportClick} isDisabled={importing || !splittedLines.length} label="Start import" />
|
||||
</StyledFileInput>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {})(withRouter(SectionBodyContent));
|
@ -1,61 +0,0 @@
|
||||
import React, { useCallback } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { IconButton } from "asc-web-components";
|
||||
import { Headline } from 'asc-web-common';
|
||||
import { withRouter } from "react-router";
|
||||
// import { useTranslation } from 'react-i18next';
|
||||
import styled from "styled-components";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.arrow-button {
|
||||
@media (max-width: 1024px) {
|
||||
padding: 8px 0 8px 8px;
|
||||
margin-left: -8px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const textStyle = {
|
||||
marginLeft: "16px",
|
||||
marginRight: "16px"
|
||||
};
|
||||
|
||||
const SectionHeaderContent = props => {
|
||||
const { history, settings } = props;
|
||||
//const { t } = useTranslation();
|
||||
|
||||
const onClickBack = useCallback(() => {
|
||||
history.push(settings.homepage);
|
||||
}, [history, settings]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<div style={{ width: "16px" }}>
|
||||
<IconButton
|
||||
iconName="ArrowPathIcon"
|
||||
color="#A3A9AE"
|
||||
size="17"
|
||||
hoverColor="#657077"
|
||||
isFill={true}
|
||||
onClick={onClickBack}
|
||||
className="arrow-button"
|
||||
/>
|
||||
</div>
|
||||
<Headline type="content" truncate={true} style={textStyle}>
|
||||
Add users to the portal (Development)
|
||||
</Headline>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
profile: state.profile.targetUser,
|
||||
settings: state.auth.settings
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(SectionHeaderContent));
|
@ -1,2 +0,0 @@
|
||||
export { default as SectionHeaderContent } from './Header';
|
||||
export { default as SectionBodyContent } from './Body';
|
@ -1,51 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/Reassign/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -1,93 +0,0 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
// import PropTypes from "prop-types";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import {
|
||||
ArticleHeaderContent,
|
||||
ArticleMainButtonContent,
|
||||
ArticleBodyContent
|
||||
} from '../../Article';
|
||||
// import { SectionHeaderContent } from './Section';
|
||||
// import { fetchProfile } from '../../../store/profile/actions';
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
|
||||
class Import extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
// const { match, fetchProfile } = this.props;
|
||||
// const { userId } = match.params;
|
||||
|
||||
// if (userId) {
|
||||
// fetchProfile(userId);
|
||||
// }
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
// const { match, fetchProfile } = this.props;
|
||||
// const { userId } = match.params;
|
||||
// const prevUserId = prevProps.match.params.userId;
|
||||
|
||||
// if (userId !== undefined && userId !== prevUserId) {
|
||||
// fetchProfile(userId);
|
||||
// }
|
||||
}
|
||||
|
||||
render() {
|
||||
//console.log("Import render")
|
||||
|
||||
// let loaded = false;
|
||||
// const { profile, match } = this.props;
|
||||
// const { userId, type } = match.params;
|
||||
|
||||
// if (type) {
|
||||
// loaded = true;
|
||||
// } else if (profile) {
|
||||
// loaded = profile.userName === userId || profile.id === userId;
|
||||
// }
|
||||
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<PageLayout>
|
||||
<PageLayout.ArticleHeader>
|
||||
<ArticleHeaderContent />
|
||||
</PageLayout.ArticleHeader>
|
||||
|
||||
<PageLayout.ArticleMainButton>
|
||||
<ArticleMainButtonContent />
|
||||
</PageLayout.ArticleMainButton>
|
||||
|
||||
<PageLayout.ArticleBody>
|
||||
<ArticleBodyContent />
|
||||
</PageLayout.ArticleBody>
|
||||
|
||||
<PageLayout.SectionHeader>
|
||||
<SectionHeaderContent />
|
||||
</PageLayout.SectionHeader>
|
||||
|
||||
<PageLayout.SectionBody>
|
||||
<SectionBodyContent />
|
||||
</PageLayout.SectionBody>
|
||||
</PageLayout>
|
||||
</I18nextProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Import.propTypes = {
|
||||
// match: PropTypes.object.isRequired,
|
||||
// profile: PropTypes.object,
|
||||
// fetchProfile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
// profile: state.profile.targetUser
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
})(Import);
|
@ -1,16 +0,0 @@
|
||||
{
|
||||
"ReassignmentData": "Reassignment of data",
|
||||
"ReassignsToUser": "Employee to whom the data will be transferred —",
|
||||
"ChooseUser": "Choose user",
|
||||
"ReassignsTransferedListHdr": "Will be transferred:",
|
||||
"ReassignsTransferedListItem1": "General documents and personal documents that are available to other portal users;",
|
||||
"ReassignsTransferedListItem2": "Open projects, milestones and tasks;",
|
||||
"ReassignsTransferedListItem3": "Contacts, open tasks, unclosed opportunities and CRM cases;",
|
||||
"NotBeUndone": "Note: this action cannot be undone.",
|
||||
"ReassignsReadMore": "More about data transfer",
|
||||
"DeleteProfileAfterReassignment": "Delete profile when reassignment will be finished",
|
||||
"CancelButton": "Cancel",
|
||||
"ReassignButton": "Reassign",
|
||||
|
||||
"LDAPLbl": "LDAP"
|
||||
}
|
@ -4,26 +4,34 @@ import {
|
||||
IconButton,
|
||||
ContextMenuButton,
|
||||
toastr,
|
||||
AvatarEditor,
|
||||
AvatarEditor
|
||||
} from "asc-web-components";
|
||||
import { Headline } from 'asc-web-common';
|
||||
import { Headline } from "asc-web-common";
|
||||
import { withRouter } from "react-router";
|
||||
import {
|
||||
getUserStatus,
|
||||
toEmployeeWrapper
|
||||
} from "../../../../../store/people/selectors";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import { updateUserStatus } from "../../../../../store/people/actions";
|
||||
import { updateProfile } from "../../../../../store/profile/actions";
|
||||
import {
|
||||
updateUserStatus
|
||||
} from "../../../../../store/people/actions";
|
||||
import {
|
||||
updateProfile
|
||||
fetchProfile,
|
||||
getUserPhoto
|
||||
} from "../../../../../store/profile/actions";
|
||||
import { fetchProfile, getUserPhoto } from "../../../../../store/profile/actions";
|
||||
import styled from "styled-components";
|
||||
import { store, api, constants } from "asc-web-common";
|
||||
import { DeleteSelfProfileDialog, ChangePasswordDialog, ChangeEmailDialog, DeleteProfileEverDialog } from '../../../../dialogs';
|
||||
import i18n from '../../i18n';
|
||||
import {
|
||||
DeleteSelfProfileDialog,
|
||||
ChangePasswordDialog,
|
||||
ChangeEmailDialog,
|
||||
DeleteProfileEverDialog
|
||||
} from "../../../../dialogs";
|
||||
import { createI18N } from "../../../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "Profile",
|
||||
localesPath: "pages/Profile"
|
||||
});
|
||||
const { isAdmin, isMe } = store.auth.selectors;
|
||||
const {
|
||||
resendUserInvites,
|
||||
@ -39,29 +47,29 @@ const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.action-button {
|
||||
margin-left: 16px;
|
||||
.action-button {
|
||||
margin-left: 16px;
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
margin-left: auto;
|
||||
@media (max-width: 1024px) {
|
||||
margin-left: auto;
|
||||
|
||||
& > div:first-child {
|
||||
padding: 8px 16px 8px 0px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.arrow-button {
|
||||
@media (max-width: 1024px) {
|
||||
padding: 8px 16px 8px 16px;
|
||||
margin-left: -16px;
|
||||
& > div:first-child {
|
||||
padding: 8px 16px 8px 0px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-headline {
|
||||
margin-left: 16px;
|
||||
}
|
||||
.arrow-button {
|
||||
@media (max-width: 1024px) {
|
||||
padding: 8px 16px 8px 16px;
|
||||
margin-left: -16px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-headline {
|
||||
margin-left: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
class SectionHeaderContent extends React.PureComponent {
|
||||
@ -95,7 +103,7 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
changePassword: false,
|
||||
changeEmail: false,
|
||||
deleteProfileEver: false
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
return newState;
|
||||
@ -111,7 +119,11 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
image: userPhotoData.original ? userPhotoData.original.indexOf('default_user_photo') !== -1 ? null : userPhotoData.original : null
|
||||
image: userPhotoData.original
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? null
|
||||
: userPhotoData.original
|
||||
: null
|
||||
},
|
||||
visibleAvatarEditor: true
|
||||
});
|
||||
@ -138,7 +150,7 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
loadAvatar(this.state.profile.id, data)
|
||||
.then(response => {
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
img.onload = function() {
|
||||
var stateCopy = Object.assign({}, _this.state);
|
||||
stateCopy.avatar = {
|
||||
tmpFile: response.data,
|
||||
@ -180,7 +192,7 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
.then(() => this.props.updateProfile(this.props.profile))
|
||||
.then(() => this.props.fetchProfile(this.state.profile.id))
|
||||
.then(() => toastr.success(this.props.t("ChangesApplied")))
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
toastr.error(error);
|
||||
});
|
||||
} else {
|
||||
@ -189,7 +201,7 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
let stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.visibleAvatarEditor = false;
|
||||
stateCopy.profile.avatarMax = response.big;
|
||||
toastr.success(this.props.t('ChangesApplied'));
|
||||
toastr.success(this.props.t("ChangesApplied"));
|
||||
this.setState(stateCopy);
|
||||
})
|
||||
.catch(error => toastr.error(error));
|
||||
@ -202,9 +214,21 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
});
|
||||
};
|
||||
|
||||
toggleChangePasswordDialog = () => this.setState({ dialogsVisible: { ...this.state.dialogsVisible, changePassword: !this.state.dialogsVisible.changePassword } });
|
||||
toggleChangePasswordDialog = () =>
|
||||
this.setState({
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
changePassword: !this.state.dialogsVisible.changePassword
|
||||
}
|
||||
});
|
||||
|
||||
toggleChangeEmailDialog = () => this.setState({ dialogsVisible: { ...this.state.dialogsVisible, changeEmail: !this.state.dialogsVisible.changeEmail } });
|
||||
toggleChangeEmailDialog = () =>
|
||||
this.setState({
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
changeEmail: !this.state.dialogsVisible.changeEmail
|
||||
}
|
||||
});
|
||||
|
||||
onEditClick = () => {
|
||||
const { history, settings } = this.props;
|
||||
@ -217,8 +241,8 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
updateUserStatus(status, new Array(userId))
|
||||
.then(() => this.props.updateProfile(this.props.profile))
|
||||
.then(() => fetchProfile(userId))
|
||||
.then(() => toastr.success(t('SuccessChangeUserStatus')))
|
||||
.catch(error => toastr.error(error))
|
||||
.then(() => toastr.success(t("SuccessChangeUserStatus")))
|
||||
.catch(error => toastr.error(error));
|
||||
};
|
||||
|
||||
onDisableClick = () =>
|
||||
@ -236,23 +260,33 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
toastr.success("Context action: Delete personal data");
|
||||
};
|
||||
|
||||
toggleDeleteProfileEverDialog = () => this.setState({ dialogsVisible: { ...this.state.dialogsVisible, deleteProfileEver: !this.state.dialogsVisible.deleteProfileEver } });
|
||||
|
||||
toggleDeleteProfileEverDialog = () =>
|
||||
this.setState({
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
deleteProfileEver: !this.state.dialogsVisible.deleteProfileEver
|
||||
}
|
||||
});
|
||||
|
||||
toggleDeleteSelfProfileDialog = () => {
|
||||
this.setState(
|
||||
{
|
||||
dialogsVisible: { ...this.state.dialogsVisible, deleteSelfProfile: !this.state.dialogsVisible.deleteSelfProfile }
|
||||
});
|
||||
this.setState({
|
||||
dialogsVisible: {
|
||||
...this.state.dialogsVisible,
|
||||
deleteSelfProfile: !this.state.dialogsVisible.deleteSelfProfile
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onInviteAgainClick = () => {
|
||||
resendUserInvites(new Array(this.state.profile.id))
|
||||
.then(() =>
|
||||
toastr.success(
|
||||
<Trans i18nKey='MessageEmailActivationInstuctionsSentOnEmail' i18n={i18n}>
|
||||
<Trans
|
||||
i18nKey="MessageEmailActivationInstuctionsSentOnEmail"
|
||||
i18n={i18n}
|
||||
>
|
||||
The email activation instructions have been sent to the
|
||||
<strong>{{ email: this.state.profile.email }}</strong> email address
|
||||
<strong>{{ email: this.state.profile.email }}</strong> email address
|
||||
</Trans>
|
||||
)
|
||||
)
|
||||
@ -295,15 +329,15 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
? viewer.isOwner
|
||||
? {}
|
||||
: {
|
||||
key: "delete-profile",
|
||||
label: t("DeleteSelfProfile"),
|
||||
onClick: this.toggleDeleteSelfProfileDialog
|
||||
}
|
||||
key: "delete-profile",
|
||||
label: t("DeleteSelfProfile"),
|
||||
onClick: this.toggleDeleteSelfProfileDialog
|
||||
}
|
||||
: {
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick
|
||||
}
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick
|
||||
}
|
||||
];
|
||||
case "disabled":
|
||||
return [
|
||||
@ -351,17 +385,17 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
onClick: this.openAvatarEditor
|
||||
},
|
||||
!isMe(user, viewer.userName) &&
|
||||
(user.status === EmployeeStatus.Active
|
||||
? {
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick
|
||||
}
|
||||
: {
|
||||
key: "enable",
|
||||
label: t("EnableUserButton"),
|
||||
onClick: this.onEnableClick
|
||||
}),
|
||||
(user.status === EmployeeStatus.Active
|
||||
? {
|
||||
key: "disable",
|
||||
label: t("DisableUserButton"),
|
||||
onClick: this.onDisableClick
|
||||
}
|
||||
: {
|
||||
key: "enable",
|
||||
label: t("EnableUserButton"),
|
||||
onClick: this.onEnableClick
|
||||
}),
|
||||
isMe(user, viewer.userName) && {
|
||||
key: "delete-profile",
|
||||
label: t("DeleteSelfProfile"),
|
||||
@ -380,7 +414,15 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { profile, isAdmin, viewer, t, filter, settings, history } = this.props;
|
||||
const {
|
||||
profile,
|
||||
isAdmin,
|
||||
viewer,
|
||||
t,
|
||||
filter,
|
||||
settings,
|
||||
history
|
||||
} = this.props;
|
||||
const { avatar, visibleAvatarEditor, dialogsVisible } = this.state;
|
||||
const contextOptions = () => this.getUserContextOptions(profile, viewer);
|
||||
|
||||
@ -395,7 +437,7 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
onClick={this.onClickBack}
|
||||
className="arrow-button"
|
||||
/>
|
||||
<Headline className='header-headline' type='content' truncate={true}>
|
||||
<Headline className="header-headline" type="content" truncate={true}>
|
||||
{profile.displayName}
|
||||
{profile.isLDAP && ` (${t("LDAPLbl")})`}
|
||||
</Headline>
|
||||
@ -424,34 +466,34 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
unknownTypeError={t("ErrorUnknownFileImageType")}
|
||||
maxSizeFileError={t("maxSizeFileError")}
|
||||
unknownError={t("Error")}
|
||||
saveButtonLabel={t('SaveButton')}
|
||||
saveButtonLabel={t("SaveButton")}
|
||||
/>
|
||||
|
||||
{dialogsVisible.deleteSelfProfile &&
|
||||
{dialogsVisible.deleteSelfProfile && (
|
||||
<DeleteSelfProfileDialog
|
||||
visible={dialogsVisible.deleteSelfProfile}
|
||||
onClose={this.toggleDeleteSelfProfileDialog}
|
||||
email={this.state.profile.email}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
|
||||
{dialogsVisible.changePassword &&
|
||||
{dialogsVisible.changePassword && (
|
||||
<ChangePasswordDialog
|
||||
visible={dialogsVisible.changePassword}
|
||||
onClose={this.toggleChangePasswordDialog}
|
||||
email={this.state.profile.email}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
|
||||
{dialogsVisible.changeEmail &&
|
||||
{dialogsVisible.changeEmail && (
|
||||
<ChangeEmailDialog
|
||||
visible={dialogsVisible.changeEmail}
|
||||
onClose={this.toggleChangeEmailDialog}
|
||||
user={this.state.profile}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
|
||||
{dialogsVisible.deleteProfileEver &&
|
||||
{dialogsVisible.deleteProfileEver && (
|
||||
<DeleteProfileEverDialog
|
||||
visible={dialogsVisible.deleteProfileEver}
|
||||
onClose={this.toggleDeleteProfileEverDialog}
|
||||
@ -460,7 +502,7 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
settings={settings}
|
||||
history={history}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance.use(Backend).init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/Profile/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -7,15 +7,18 @@ import {
|
||||
ArticleHeaderContent,
|
||||
ArticleMainButtonContent,
|
||||
ArticleBodyContent
|
||||
} from '../../Article';
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
import { fetchProfile, resetProfile } from '../../../store/profile/actions';
|
||||
import i18n from "./i18n";
|
||||
} from "../../Article";
|
||||
import { SectionHeaderContent, SectionBodyContent } from "./Section";
|
||||
import { fetchProfile, resetProfile } from "../../../store/profile/actions";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "Profile",
|
||||
localesPath: "pages/Profile"
|
||||
});
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class PureProfile extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -30,12 +33,14 @@ class PureProfile extends React.Component {
|
||||
const { match, fetchProfile, t } = this.props;
|
||||
const { userId } = match.params;
|
||||
|
||||
const queryParams = this.state.queryString.split('&');
|
||||
const arrayOfQueryParams = queryParams.map(queryParam => queryParam.split('='));
|
||||
const queryParams = this.state.queryString.split("&");
|
||||
const arrayOfQueryParams = queryParams.map(queryParam =>
|
||||
queryParam.split("=")
|
||||
);
|
||||
const linkParams = Object.fromEntries(arrayOfQueryParams);
|
||||
|
||||
if (linkParams.email_change && linkParams.email_change === "success") {
|
||||
toastr.success(t('ChangeEmailSuccess'));
|
||||
toastr.success(t("ChangeEmailSuccess"));
|
||||
}
|
||||
|
||||
fetchProfile(userId);
|
||||
@ -87,21 +92,24 @@ class PureProfile extends React.Component {
|
||||
{profile ? (
|
||||
<SectionBodyContent />
|
||||
) : (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
)}
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
)}
|
||||
</PageLayout.SectionBody>
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const ProfileContainer = withTranslation()(PureProfile);
|
||||
|
||||
const Profile = (props) => {
|
||||
|
||||
const Profile = props => {
|
||||
changeLanguage(i18n);
|
||||
|
||||
return <I18nextProvider i18n={i18n}><ProfileContainer {...props} /></I18nextProvider>
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ProfileContainer {...props} />
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Profile.propTypes = {
|
||||
@ -119,8 +127,10 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps,
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchProfile,
|
||||
resetProfile
|
||||
})(Profile);
|
||||
}
|
||||
)(Profile);
|
||||
|
@ -1,54 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/ProfileAction/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -14,8 +14,12 @@ import {
|
||||
UpdateUserForm
|
||||
} from "./Section";
|
||||
import { fetchProfile } from "../../../store/profile/actions";
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "ProfileAction",
|
||||
localesPath: "pages/ProfileAction"
|
||||
});
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ProfileAction extends React.Component {
|
||||
@ -55,7 +59,6 @@ class ProfileAction extends React.Component {
|
||||
loaded = profile.userName === userId || profile.id === userId;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<PageLayout>
|
||||
@ -86,11 +89,11 @@ class ProfileAction extends React.Component {
|
||||
type ? (
|
||||
<CreateUserForm />
|
||||
) : (
|
||||
<UpdateUserForm />
|
||||
)
|
||||
<UpdateUserForm />
|
||||
)
|
||||
) : (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
)}
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
)}
|
||||
</PageLayout.SectionBody>
|
||||
</PageLayout>
|
||||
</I18nextProvider>
|
||||
@ -123,4 +126,7 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, { fetchProfile })(ProfileActionContainer);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ fetchProfile }
|
||||
)(ProfileActionContainer);
|
||||
|
@ -1,51 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/Reassign/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -6,19 +6,21 @@ import {
|
||||
ArticleHeaderContent,
|
||||
ArticleMainButtonContent,
|
||||
ArticleBodyContent
|
||||
} from '../../Article';
|
||||
} from "../../Article";
|
||||
// import { SectionHeaderContent } from './Section';
|
||||
// import { fetchProfile } from '../../../store/profile/actions';
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
import { SectionHeaderContent, SectionBodyContent } from "./Section";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
const i18n = createI18N({
|
||||
page: "Reassign",
|
||||
localesPath: "pages/Reassign"
|
||||
});
|
||||
|
||||
class Reassign extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
// const { match, fetchProfile } = this.props;
|
||||
// const { userId } = match.params;
|
||||
|
||||
// if (userId) {
|
||||
// fetchProfile(userId);
|
||||
// }
|
||||
@ -28,14 +30,13 @@ class Reassign extends React.Component {
|
||||
// const { match, fetchProfile } = this.props;
|
||||
// const { userId } = match.params;
|
||||
// const prevUserId = prevProps.match.params.userId;
|
||||
|
||||
// if (userId !== undefined && userId !== prevUserId) {
|
||||
// fetchProfile(userId);
|
||||
// }
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("Reassign render")
|
||||
console.log("Reassign render");
|
||||
|
||||
// let loaded = false;
|
||||
// const { profile, match } = this.props;
|
||||
@ -65,7 +66,7 @@ class Reassign extends React.Component {
|
||||
<PageLayout.SectionHeader>
|
||||
<SectionHeaderContent />
|
||||
</PageLayout.SectionHeader>
|
||||
|
||||
|
||||
<PageLayout.SectionBody>
|
||||
<SectionBodyContent />
|
||||
</PageLayout.SectionBody>
|
||||
@ -75,7 +76,6 @@ class Reassign extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reassign.propTypes = {
|
||||
// match: PropTypes.object.isRequired,
|
||||
// profile: PropTypes.object,
|
||||
@ -88,6 +88,7 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
})(Reassign);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{}
|
||||
)(Reassign);
|
||||
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"ReassignmentData": "Переназначение данных",
|
||||
"ReassignsToUser": "Сотрудник, которому будут переданы данные —",
|
||||
"ChooseUser": "Выберите пользователя",
|
||||
"ReassignsTransferedListHdr": "Будет передан:",
|
||||
"ReassignsTransferedListItem1": "Общие документы и личные документы, доступные другим пользователям портала;",
|
||||
"ReassignsTransferedListItem2": "Открытые проекты, вехи и задачи;",
|
||||
"ReassignsTransferedListItem3": "Контакты, открытые задачи, незакрытые возможности и кейсы CRM;",
|
||||
"NotBeUndone": "Примечание: это действие нельзя отменить.",
|
||||
"ReassignsReadMore": "Подробнее о передаче данных",
|
||||
"DeleteProfileAfterReassignment": "Удалить профиль, когда переназначение будет завершено",
|
||||
"CancelButton": "Отмена",
|
||||
"ReassignButton": "Переназначить",
|
||||
|
||||
"LDAPLbl": "LDAP"
|
||||
}
|
35
products/ASC.People/Client/src/helpers/i18n.js
Normal file
35
products/ASC.People/Client/src/helpers/i18n.js
Normal file
@ -0,0 +1,35 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import { constants } from "asc-web-common";
|
||||
const { i18nBaseSettings } = constants;
|
||||
|
||||
/**
|
||||
* @description create i18n instance
|
||||
* @param {object} object with method,url,data etc.
|
||||
*/
|
||||
export const createI18N = function(options) {
|
||||
const { page, localesPath } = options;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance.use(Backend).init({
|
||||
...i18nBaseSettings,
|
||||
backend: {
|
||||
loadPath: `/locales/${page}/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
const resources = {};
|
||||
|
||||
i18nBaseSettings.supportedLngs.forEach(name => {
|
||||
resources[name] = {
|
||||
translation: require(`../components/${localesPath}/locales/${name}/translation.json`)
|
||||
};
|
||||
});
|
||||
|
||||
newInstance.init({ ...i18nBaseSettings, resources });
|
||||
}
|
||||
|
||||
return newInstance;
|
||||
};
|
Loading…
Reference in New Issue
Block a user