Merge pull request #24 from ONLYOFFICE/feature/translations
Feature/translations
This commit is contained in:
commit
dde3cdd895
@ -7,7 +7,6 @@ import {
|
||||
Icons
|
||||
} from "asc-web-components";
|
||||
import { selectGroup } from '../../../store/people/actions';
|
||||
import { departments } from './../../../helpers/customNames';
|
||||
|
||||
const getItems = data => {
|
||||
return data.map(item => {
|
||||
@ -109,7 +108,7 @@ class ArticleBodyContent extends React.Component {
|
||||
};
|
||||
};
|
||||
|
||||
const getTreeGroups = (groups) => {
|
||||
const getTreeGroups = (groups, departments) => {
|
||||
const treeData = [
|
||||
{
|
||||
key: "root",
|
||||
@ -128,7 +127,7 @@ const getTreeGroups = (groups) => {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
data: getTreeGroups(state.people.groups),
|
||||
data: getTreeGroups(state.people.groups, state.auth.settings.customNames.groupsCaption),
|
||||
selectedKeys: state.people.selectedGroup ? [state.people.selectedGroup] : ["root"]
|
||||
};
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import {
|
||||
import { InviteDialog } from './../../dialogs';
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
import { typeUser, typeGuest, department } from './../../../helpers/customNames';
|
||||
import { store } from 'asc-web-common';
|
||||
import { store, utils } from 'asc-web-common';
|
||||
const { changeLanguage } = utils;
|
||||
const { isAdmin } = store.auth.selectors;
|
||||
|
||||
class PureArticleMainButtonContent extends React.Component {
|
||||
@ -50,6 +50,7 @@ class PureArticleMainButtonContent extends React.Component {
|
||||
render() {
|
||||
console.log("People ArticleMainButtonContent render");
|
||||
const { isAdmin, settings, t } = this.props;
|
||||
const { userCaption, guestCaption, groupCaption } = settings.customNames;
|
||||
const { dialogVisible } = this.state;
|
||||
return (
|
||||
isAdmin ?
|
||||
@ -60,18 +61,18 @@ class PureArticleMainButtonContent extends React.Component {
|
||||
text={t('Actions')}
|
||||
>
|
||||
<DropDownItem
|
||||
icon="CatalogEmployeeIcon"
|
||||
label={t('CustomNewEmployee', { typeUser })}
|
||||
icon="AddEmployeeIcon"
|
||||
label={userCaption}
|
||||
onClick={this.goToEmployeeCreate}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="CatalogGuestIcon"
|
||||
label={t('CustomNewGuest', { typeGuest })}
|
||||
icon="AddGuestIcon"
|
||||
label={guestCaption}
|
||||
onClick={this.goToGuestCreate}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="CatalogDepartmentsIcon"
|
||||
label={t('CustomNewDepartment', { department })}
|
||||
icon="AddDepartmentIcon"
|
||||
label={groupCaption}
|
||||
onClick={this.goToGroupCreate}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
@ -110,8 +111,7 @@ class PureArticleMainButtonContent extends React.Component {
|
||||
const ArticleMainButtonContentContainer = withTranslation()(PureArticleMainButtonContent);
|
||||
|
||||
const ArticleMainButtonContent = (props) => {
|
||||
const { language } = props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
return (<I18nextProvider i18n={i18n}><ArticleMainButtonContentContainer {...props} /></I18nextProvider>);
|
||||
};
|
||||
|
||||
@ -123,7 +123,6 @@ ArticleMainButtonContent.propTypes = {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
isAdmin: isAdmin(state.auth.user),
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture,
|
||||
settings: state.auth.settings
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,15 +10,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,16 +37,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -2,8 +2,5 @@
|
||||
"InviteLinkTitle": "Invitation link",
|
||||
"ImportPeople": "Import people",
|
||||
"Actions": "Actions",
|
||||
"LblInviteAgain": "Invite again",
|
||||
"CustomNewEmployee": "New {{typeUser, lowercase}}",
|
||||
"CustomNewGuest": "New {{typeGuest, lowercase}}",
|
||||
"CustomNewDepartment": "New {{department, lowercase}}"
|
||||
"LblInviteAgain": "Invite again"
|
||||
}
|
@ -2,8 +2,5 @@
|
||||
"InviteLinkTitle": "Пригласительная ссылка",
|
||||
"ImportPeople": "Импортировать людей",
|
||||
"Actions": "Действия",
|
||||
"LblInviteAgain": "Отправить приглашение ещё раз",
|
||||
"CustomNewEmployee": "Новый {{typeUser, lowercase}}",
|
||||
"CustomNewGuest": "Новый {{typeGuest, lowercase}}",
|
||||
"CustomNewDepartment": "Новый {{department, lowercase}}"
|
||||
"LblInviteAgain": "Отправить приглашение ещё раз"
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,15 +10,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,7 +37,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
@ -13,14 +11,15 @@ import {
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import { api } from "asc-web-common";
|
||||
import { api, utils } from "asc-web-common";
|
||||
const { sendInstructionsToChangeEmail } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ChangeEmailDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { user, language } = props;
|
||||
const { user } = props;
|
||||
const { email } = user;
|
||||
|
||||
this.state = {
|
||||
@ -32,7 +31,7 @@ class ChangeEmailDialogComponent extends React.Component {
|
||||
emailErrors: []
|
||||
};
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -169,10 +168,5 @@ ChangeEmailDialog.propTypes = {
|
||||
user: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {})(withRouter(ChangeEmailDialog));
|
||||
export default ChangeEmailDialog;
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,15 +10,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,7 +37,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
@ -11,20 +9,19 @@ import {
|
||||
} from "asc-web-components";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api } from "asc-web-common";
|
||||
import { api, utils } from "asc-web-common";
|
||||
const { sendInstructionsToChangePassword } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ChangePasswordDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { language } = props;
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
isRequestRunning: false
|
||||
};
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
}
|
||||
onSendPasswordChangeInstructions = () => {
|
||||
const { email, onClose } = this.props;
|
||||
@ -91,10 +88,4 @@ ChangePasswordDialog.propTypes = {
|
||||
email: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {})(withRouter(ChangePasswordDialog));
|
||||
export default ChangePasswordDialog;
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,15 +10,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,7 +37,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
@ -10,19 +8,18 @@ import {
|
||||
} from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api } from "asc-web-common";
|
||||
import { api, utils } from "asc-web-common";
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ChangePhoneDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { language } = props;
|
||||
|
||||
this.state = {
|
||||
isRequestRunning: false
|
||||
};
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
}
|
||||
|
||||
// TODO: add real api request for executing change phone
|
||||
@ -48,7 +45,7 @@ class ChangePhoneDialogComponent extends React.Component {
|
||||
headerContent={t('MobilePhoneChangeTitle')}
|
||||
bodyContent={
|
||||
<Text>
|
||||
{t('MessageChangePhone')}
|
||||
{t('MobilePhoneEraseDescription')}
|
||||
</Text>
|
||||
}
|
||||
footerContent={
|
||||
@ -78,10 +75,4 @@ ChangePhoneDialog.propTypes = {
|
||||
user: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {})(withRouter(ChangePhoneDialog));
|
||||
export default ChangePhoneDialog;
|
||||
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"SendButton": "Send",
|
||||
"MobilePhoneChangeTitle": "Change mobile phone",
|
||||
|
||||
"MessageChangePhone": "The instructions on how to change the user mobile number will be sent to the user email address"
|
||||
"MobilePhoneEraseDescription": "The instructions on how to change the user mobile number will be sent to the user email address"
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"SendButton": "Отправить",
|
||||
"MobilePhoneChangeTitle": "Изменение номера телефона",
|
||||
|
||||
"MessageChangePhone": "Инструкция по смене номера мобильного телефона будет отправлена на Вашу почту"
|
||||
"MobilePhoneEraseDescription": "Инструкция по смене номера мобильного телефона будет отправлена на Вашу почту"
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,15 +10,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,7 +37,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
@ -10,24 +10,22 @@ import {
|
||||
} from "asc-web-components";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api } from "asc-web-common";
|
||||
import { typeUser } from "../../../helpers/customNames";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import { fetchPeople } from '../../../store/people/actions';
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
const { deleteUser } = api.people;
|
||||
const { Filter } = api;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class DeleteProfileEverDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { language } = props;
|
||||
|
||||
this.state = {
|
||||
isRequestRunning: false
|
||||
};
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
}
|
||||
onDeleteProfileEver = () => {
|
||||
const { onClose, filter, fetchPeople, user, t } = this.props;
|
||||
@ -51,7 +49,7 @@ class DeleteProfileEverDialogComponent extends React.Component {
|
||||
|
||||
render() {
|
||||
console.log("DeleteProfileEverDialog render");
|
||||
const { t, visible, user, onClose } = this.props;
|
||||
const { t, visible, user, onClose, userCaption } = this.props;
|
||||
const { isRequestRunning } = this.state;
|
||||
|
||||
return (
|
||||
@ -64,7 +62,7 @@ class DeleteProfileEverDialogComponent extends React.Component {
|
||||
<>
|
||||
<Text>
|
||||
<Trans i18nKey='DeleteUserConfirmation' i18n={i18n}>
|
||||
{{ typeUser }} <strong>{{ user: user.displayName }}</strong> will be deleted.
|
||||
{{ userCaption }} <strong>{{ user: user.displayName }}</strong> will be deleted.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text>{t('NotBeUndone')}</Text>
|
||||
@ -120,7 +118,7 @@ DeleteProfileEverDialog.propTypes = {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName,
|
||||
userCaption: state.auth.settings.customNames.userCaption
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"Confirmation": "Confirmation",
|
||||
"DeleteUserConfirmation": "{{typeUser}} <strong>{{user}}</strong> will be deleted.",
|
||||
"DeleteUserConfirmation": "{{userCaption}} <strong>{{user}}</strong> will be deleted.",
|
||||
"NotBeUndone": "Note: this action cannot be undone.",
|
||||
"DeleteUserDataConfirmation": "User's personal documents that are available to others will be deleted. To avoid this, you must start the data reassign process before deleting.",
|
||||
"OKButton": "OK",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"Confirmation": "Подтверждение",
|
||||
"DeleteUserConfirmation": "{{typeUser}} <strong>{{user}}</strong> будет удален.",
|
||||
"DeleteUserConfirmation": "{{userCaption}} <strong>{{user}}</strong> будет удален.",
|
||||
"NotBeUndone": "Внимание: это действие необратимо.",
|
||||
"DeleteUserDataConfirmation": "Будут удалены личные документы пользователя, доступные для других. Чтобы избежать этого, нужно перед удалением запустить процесс передачи данных.",
|
||||
"OKButton": "OK",
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,15 +10,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,7 +37,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
@ -12,20 +10,19 @@ import {
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import { api } from "asc-web-common";
|
||||
import { api, utils } from "asc-web-common";
|
||||
const { sendInstructionsToDelete } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class DeleteSelfProfileDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { language } = props;
|
||||
|
||||
this.state = {
|
||||
isRequestRunning: false
|
||||
};
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
}
|
||||
onDeleteSelfProfileInstructions = () => {
|
||||
const { onClose } = this.props;
|
||||
@ -98,10 +95,4 @@ DeleteSelfProfileDialog.propTypes = {
|
||||
email: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {})(withRouter(DeleteSelfProfileDialog));
|
||||
export default DeleteSelfProfileDialog;
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,7 +10,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
@ -39,7 +41,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
@ -13,39 +12,37 @@ import {
|
||||
} from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { typeGuests } from "./../../../helpers/customNames";
|
||||
import ModalDialogContainer from '../ModalDialogContainer';
|
||||
import copy from "copy-to-clipboard";
|
||||
import { api } from "asc-web-common";
|
||||
import { api, utils } from "asc-web-common";
|
||||
const { getShortenedLink } = api.portal;
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
const textAreaName = "link-textarea";
|
||||
|
||||
class InviteDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { language, userInvitationLink, guestInvitationLink } = this.props;
|
||||
const { userInvitationLink, guestInvitationLink } = props;
|
||||
this.state = {
|
||||
isGuest: false,
|
||||
userInvitationLink,
|
||||
guestInvitationLink,
|
||||
isLoading: false,
|
||||
isLinkShort: false,
|
||||
visible: false
|
||||
visible: false,
|
||||
};
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
}
|
||||
|
||||
onCopyLinkToClipboard = () => {
|
||||
// console.log("COPY");
|
||||
// console.log("COPY", this.props);
|
||||
const { t } = this.props;
|
||||
copy(
|
||||
this.state.isGuest
|
||||
? this.state.guestInvitationLink
|
||||
: this.state.userInvitationLink
|
||||
);
|
||||
|
||||
toastr.success(t("LinkCopySuccess"));
|
||||
};
|
||||
|
||||
@ -79,7 +76,12 @@ class InviteDialogComponent extends React.Component {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.onCopyLinkToClipboard();
|
||||
const { t } = this.props;
|
||||
copy(this.state.userInvitationLink);
|
||||
|
||||
changeLanguage(i18n)
|
||||
.then(()=> this.setState({visible: true}))
|
||||
.then(()=> toastr.success(t("LinkCopySuccess")));
|
||||
}
|
||||
|
||||
onClickToCloseButton = () =>
|
||||
@ -88,9 +90,10 @@ class InviteDialogComponent extends React.Component {
|
||||
|
||||
render() {
|
||||
console.log("InviteDialog render");
|
||||
const { t, visible, settings } = this.props;
|
||||
const { t, visible, settings, guestsCaption } = this.props;
|
||||
|
||||
return (
|
||||
this.state.visible &&
|
||||
<ModalDialogContainer>
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
@ -125,7 +128,7 @@ class InviteDialogComponent extends React.Component {
|
||||
)}
|
||||
</div>
|
||||
<Checkbox
|
||||
label={t("InviteUsersAsCollaborators", { typeGuests })}
|
||||
label={t("InviteUsersAsCollaborators", { guestsCaption })}
|
||||
isChecked={this.state.isGuest}
|
||||
onChange={this.onCheckedGuest}
|
||||
isDisabled={this.state.isLoading}
|
||||
@ -171,7 +174,7 @@ const mapStateToProps = state => {
|
||||
settings: state.auth.settings.hasShortenService,
|
||||
userInvitationLink: state.portal.inviteLinks.userLink,
|
||||
guestInvitationLink: state.portal.inviteLinks.guestLink,
|
||||
language: state.auth.user.cultureName,
|
||||
guestsCaption: state.auth.settings.customNames.guestsCaption
|
||||
};
|
||||
};
|
||||
|
||||
@ -187,4 +190,4 @@ InviteDialog.propTypes = {
|
||||
onCloseButton: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(InviteDialog));
|
||||
export default connect(mapStateToProps)(InviteDialog);
|
||||
|
@ -6,6 +6,6 @@
|
||||
"CloseButton": "Close",
|
||||
"LinkCopySuccess": "Link has been copied to the clipboard",
|
||||
"GetShortenLink": "Get shortened link",
|
||||
"InviteUsersAsCollaborators": "Add users as {{typeGuests, lowercase}}",
|
||||
"InviteUsersAsCollaborators": "Add users as {{guestsCaption, lowercase}}",
|
||||
"LoadingProcessing": "Loading..."
|
||||
}
|
@ -6,6 +6,6 @@
|
||||
"CloseButton": "Закрыть",
|
||||
"LinkCopySuccess": "Ссылка скопирована в буфер обмена",
|
||||
"GetShortenLink": "Получить сокращенную ссылку",
|
||||
"InviteUsersAsCollaborators": "Добавить со статусом {{typeGuests, lowercase}}",
|
||||
"InviteUsersAsCollaborators": "Добавить со статусом {{guestsCaption, lowercase}}",
|
||||
"LoadingProcessing": "Загрузка..."
|
||||
}
|
@ -15,11 +15,6 @@ import {
|
||||
resetGroup,
|
||||
updateGroup
|
||||
} from "../../../../../store/group/actions";
|
||||
import {
|
||||
department,
|
||||
headOfDepartment,
|
||||
typeUser
|
||||
} from "../../../../../helpers/customNames";
|
||||
|
||||
import { GUID_EMPTY } from "../../../../../helpers/constants";
|
||||
import PropTypes from "prop-types";
|
||||
@ -87,12 +82,16 @@ class SectionBodyContent extends React.Component {
|
||||
|
||||
mapPropsToState = () => {
|
||||
const { group, users, groups, t } = this.props;
|
||||
const buttonLabel = group
|
||||
? t('SaveButton')
|
||||
: t("AddButton");
|
||||
|
||||
const newState = {
|
||||
id: group ? group.id : "",
|
||||
groupName: group ? group.name : "",
|
||||
searchValue: "",
|
||||
error: null,
|
||||
buttonLabel,
|
||||
inLoading: false,
|
||||
isHeadSelectorOpen: false,
|
||||
isUsersSelectorOpen: false,
|
||||
@ -105,7 +104,7 @@ class SectionBodyContent extends React.Component {
|
||||
}
|
||||
: {
|
||||
key: 0,
|
||||
label: t("CustomAddEmployee", { typeUser })
|
||||
label: t("LblSelect")
|
||||
},
|
||||
groupMembers:
|
||||
group && group.members
|
||||
@ -124,7 +123,7 @@ class SectionBodyContent extends React.Component {
|
||||
}
|
||||
: {
|
||||
key: GUID_EMPTY,
|
||||
label: t("CustomAddEmployee", { typeUser }),
|
||||
label: t("LblSelect"),
|
||||
default: true
|
||||
}
|
||||
};
|
||||
@ -191,7 +190,7 @@ class SectionBodyContent extends React.Component {
|
||||
};
|
||||
|
||||
onSave = () => {
|
||||
const { group } = this.props;
|
||||
const { group, t, groupCaption } = this.props;
|
||||
const { groupName, groupManager, groupMembers } = this.state;
|
||||
|
||||
if (!groupName || !groupName.trim().length) return false;
|
||||
@ -208,7 +207,7 @@ class SectionBodyContent extends React.Component {
|
||||
|
||||
this.save(newGroup)
|
||||
.then(group => {
|
||||
toastr.success(`Group '${group.name}' has been saved successfully`);
|
||||
toastr.success(t('SuccessSaveGroup', {groupCaption, groupName: group.name }));
|
||||
})
|
||||
.catch(error => {
|
||||
toastr.error(error);
|
||||
@ -255,7 +254,7 @@ class SectionBodyContent extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
const { t, groupHeadCaption, groupsCaption } = this.props;
|
||||
const {
|
||||
groupName,
|
||||
groupMembers,
|
||||
@ -264,7 +263,8 @@ class SectionBodyContent extends React.Component {
|
||||
inLoading,
|
||||
error,
|
||||
searchValue,
|
||||
groupManager
|
||||
groupManager,
|
||||
buttonLabel
|
||||
} = this.state;
|
||||
return (
|
||||
<MainContainer>
|
||||
@ -273,7 +273,7 @@ class SectionBodyContent extends React.Component {
|
||||
isRequired={true}
|
||||
hasError={false}
|
||||
isVertical={true}
|
||||
labelText={t("CustomDepartmentName", { department })}
|
||||
labelText={t("Name")}
|
||||
>
|
||||
<TextInput
|
||||
id="group-name"
|
||||
@ -293,7 +293,7 @@ class SectionBodyContent extends React.Component {
|
||||
isRequired={false}
|
||||
hasError={false}
|
||||
isVertical={true}
|
||||
labelText={t("CustomHeadOfDepartment", { headOfDepartment })}
|
||||
labelText={groupHeadCaption}
|
||||
>
|
||||
<ComboBox
|
||||
id="head-selector_button"
|
||||
@ -313,6 +313,7 @@ class SectionBodyContent extends React.Component {
|
||||
isOpen={isHeadSelectorOpen}
|
||||
onSelect={this.onHeadSelectorSelect}
|
||||
onCancel={this.onCancelSelector}
|
||||
groupsCaption={groupsCaption}
|
||||
/>
|
||||
</FieldContainer>
|
||||
<FieldContainer
|
||||
@ -345,6 +346,8 @@ class SectionBodyContent extends React.Component {
|
||||
isMultiSelect={true}
|
||||
onSelect={this.onUsersSelectorSelect}
|
||||
onCancel={this.onCancelSelector}
|
||||
searchPlaceHolderLabel={t('SearchAddedMembers')}
|
||||
groupsCaption={groupsCaption}
|
||||
/>
|
||||
</FieldContainer>
|
||||
{groupMembers && groupMembers.length > 0 && (
|
||||
@ -376,7 +379,7 @@ class SectionBodyContent extends React.Component {
|
||||
{error && <div><strong>{error}</strong></div>}
|
||||
<div className="buttons_container">
|
||||
<Button
|
||||
label={t("SaveButton")}
|
||||
label={buttonLabel}
|
||||
primary
|
||||
type="submit"
|
||||
isLoading={inLoading}
|
||||
@ -435,7 +438,10 @@ function mapStateToProps(state) {
|
||||
settings: state.auth.settings,
|
||||
group: state.group.targetGroup,
|
||||
groups: convertGroups(state.people.groups),
|
||||
users: convertUsers(state.people.selector.users) //TODO: replace to api requests with search
|
||||
users: convertUsers(state.people.selector.users), //TODO: replace to api requests with search
|
||||
groupHeadCaption: state.auth.settings.customNames.groupHeadCaption,
|
||||
groupsCaption: state.auth.settings.customNames.groupsCaption,
|
||||
groupCaption: state.auth.settings.customNames.groupCaption
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import PropTypes from "prop-types";
|
||||
import { IconButton } from "asc-web-components";
|
||||
import { Headline } from "asc-web-common";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { department } from "./../../../../../helpers/customNames";
|
||||
import { resetGroup } from "../../../../../store/group/actions";
|
||||
import styled from "styled-components";
|
||||
|
||||
@ -24,6 +23,18 @@ const Wrapper = styled.div`
|
||||
`;
|
||||
|
||||
class SectionHeaderContent extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { group, t, groupCaption } = props;
|
||||
const headerText = group
|
||||
? group.name
|
||||
: t("CustomNewDepartment", { groupCaption });
|
||||
|
||||
this.state = {
|
||||
headerText
|
||||
}
|
||||
}
|
||||
onClickBack = () => {
|
||||
const { history, settings, resetGroup } = this.props;
|
||||
|
||||
@ -32,10 +43,7 @@ class SectionHeaderContent extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { group, t } = this.props;
|
||||
const headerText = group
|
||||
? t("CustomEditDepartment", { department })
|
||||
: t("CustomNewDepartment", { department });
|
||||
const { headerText } = this.state;
|
||||
return (
|
||||
<Wrapper>
|
||||
<IconButton
|
||||
@ -67,7 +75,8 @@ SectionHeaderContent.defaultProps = {
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
settings: state.auth.settings,
|
||||
group: state.group.targetGroup
|
||||
group: state.group.targetGroup,
|
||||
groupCaption: state.auth.settings.customNames.groupCaption
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,7 +10,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
@ -40,7 +42,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Loader } from "asc-web-components";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import { PageLayout, utils } from "asc-web-common";
|
||||
import { ArticleHeaderContent, ArticleMainButtonContent, ArticleBodyContent } from '../../Article';
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import { fetchGroup, resetGroup } from "../../../store/group/actions";
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class GroupAction extends React.Component {
|
||||
|
||||
@ -32,9 +33,9 @@ class GroupAction extends React.Component {
|
||||
render() {
|
||||
console.log("GroupAction render")
|
||||
|
||||
const { group, match, language } = this.props;
|
||||
const { group, match } = this.props;
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
@ -62,7 +63,6 @@ class GroupAction extends React.Component {
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
settings: state.auth.settings,
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture,
|
||||
group: state.group.targetGroup
|
||||
};
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
{
|
||||
"SaveButton": "Save",
|
||||
"CancelButton": "Cancel",
|
||||
|
||||
|
||||
|
||||
"CustomHeadOfDepartment": "{{headOfDepartment}}",
|
||||
"CustomAddEmployee": "Add {{typeUser, lowercase}}",
|
||||
"CustomNewDepartment": "New {{department, lowercase}}",
|
||||
"CustomEditDepartment": "Edit {{department, lowercase}}",
|
||||
"CustomDepartmentName": "{{department}} name",
|
||||
"Members": "Members",
|
||||
"AddMembers": "Add members",
|
||||
"LblSelect": "Select",
|
||||
"Name": "Name",
|
||||
"AddButton": "Add",
|
||||
|
||||
"SuccessSaveGroup": "{{groupCaption}} '{{ groupName }}' has been saved successfully",
|
||||
|
||||
"CustomNewDepartment": "{{groupCaption}} (creation)",
|
||||
"SearchAddedMembers": "Search added members"
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
{
|
||||
"SaveButton": "Сохранить",
|
||||
"CancelButton": "Отмена",
|
||||
|
||||
|
||||
|
||||
"CustomHeadOfDepartment": "{{headOfDepartment}}",
|
||||
"CustomAddEmployee": "Добавить {{typeUser, lowercase}}",
|
||||
"CustomNewDepartment": "Новый {{department, lowercase}}",
|
||||
"CustomEditDepartment": "Редактирование {{department, lowercase}}",
|
||||
"CustomDepartmentName": "Имя {{department}}",
|
||||
"Members": "Участники",
|
||||
"AddMembers": "Добавить участников",
|
||||
"LblSelect": "Выбрать",
|
||||
"Name": "Название",
|
||||
"AddButton": "Добавить",
|
||||
|
||||
"SuccessSaveGroup": "Успешное сохранение: {{groupCaption, lowercase}} '{{ groupName }}'",
|
||||
|
||||
"CustomNewDepartment": "{{groupCaption}} (создание)",
|
||||
"SearchAddedMembers": "Поиск добавленных участников"
|
||||
}
|
@ -11,6 +11,7 @@ import {
|
||||
Link,
|
||||
RowContainer,
|
||||
Text,
|
||||
utils
|
||||
} from "asc-web-components";
|
||||
import UserContent from "./userContent";
|
||||
import {
|
||||
@ -32,6 +33,7 @@ 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';
|
||||
const { isArrayEqual } = utils.array;
|
||||
const { isAdmin, isMe } = store.auth.selectors;
|
||||
const { resendUserInvites } = api.people;
|
||||
const { EmployeeStatus } = constants;
|
||||
@ -303,6 +305,9 @@ class SectionBodyContent extends React.PureComponent {
|
||||
if (!isEqual(currentProps.data, nextProps.data)) {
|
||||
return true;
|
||||
}
|
||||
if (!isArrayEqual(currentProps.contextOptions, nextProps.contextOptions)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -5,11 +5,6 @@ import { fetchPeople } from "../../../../../store/people/actions";
|
||||
import find from "lodash/find";
|
||||
import result from "lodash/result";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import {
|
||||
typeGuest,
|
||||
typeUser,
|
||||
department
|
||||
} from "./../../../../../helpers/customNames";
|
||||
import { withRouter } from "react-router";
|
||||
import { getFilterByLocation } from "../../../../../helpers/converters";
|
||||
import { store } from 'asc-web-common';
|
||||
@ -65,7 +60,7 @@ class SectionFilterContent extends React.Component {
|
||||
|
||||
const newFilter = getFilterByLocation(location);
|
||||
|
||||
if(!newFilter || newFilter.equals(filter)) return;
|
||||
if (!newFilter || newFilter.equals(filter)) return;
|
||||
|
||||
onLoading(true);
|
||||
fetchPeople(newFilter).finally(() => onLoading(false));
|
||||
@ -98,28 +93,29 @@ class SectionFilterContent extends React.Component {
|
||||
};
|
||||
|
||||
getData = () => {
|
||||
const { user, groups, t } = this.props;
|
||||
const { user, groups, t, settings } = this.props;
|
||||
const { guestCaption, userCaption, groupCaption } = settings.customNames;
|
||||
|
||||
const options = !isAdmin(user)
|
||||
? []
|
||||
: [
|
||||
{
|
||||
key: "filter-status",
|
||||
group: "filter-status",
|
||||
label: t("UserStatus"),
|
||||
isHeader: true
|
||||
},
|
||||
{
|
||||
key: "1",
|
||||
group: "filter-status",
|
||||
label: t("LblActive")
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
group: "filter-status",
|
||||
label: t("LblTerminated")
|
||||
}
|
||||
];
|
||||
{
|
||||
key: "filter-status",
|
||||
group: "filter-status",
|
||||
label: t("UserStatus"),
|
||||
isHeader: true
|
||||
},
|
||||
{
|
||||
key: "1",
|
||||
group: "filter-status",
|
||||
label: t("LblActive")
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
group: "filter-status",
|
||||
label: t("LblTerminated")
|
||||
}
|
||||
];
|
||||
|
||||
const groupOptions = groups.map(group => {
|
||||
return {
|
||||
@ -158,12 +154,12 @@ class SectionFilterContent extends React.Component {
|
||||
{
|
||||
key: "user",
|
||||
group: "filter-type",
|
||||
label: t("CustomTypeUser", { typeUser })
|
||||
label: userCaption
|
||||
},
|
||||
{
|
||||
key: "guest",
|
||||
group: "filter-type",
|
||||
label: t("CustomTypeGuest", { typeGuest })
|
||||
label: guestCaption
|
||||
},
|
||||
{
|
||||
key: "filter-other",
|
||||
@ -175,8 +171,8 @@ class SectionFilterContent extends React.Component {
|
||||
key: "filter-type-group",
|
||||
group: "filter-other",
|
||||
subgroup: "filter-group",
|
||||
label: t("CustomDepartment", { department }),
|
||||
defaultSelectLabel: t("DefaultSelectLabel")
|
||||
label: groupCaption,
|
||||
defaultSelectLabel: t("LblSelect")
|
||||
},
|
||||
...groupOptions
|
||||
];
|
||||
@ -236,9 +232,17 @@ class SectionFilterContent extends React.Component {
|
||||
return selectedFilterData;
|
||||
};
|
||||
|
||||
needForUpdate = (currentProps, nextProps) => {
|
||||
if (currentProps.language !== nextProps.language) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
render() {
|
||||
const selectedFilterData = this.getSelectedFilterData();
|
||||
const { t } = this.props;
|
||||
const { t, i18n } = this.props;
|
||||
return (
|
||||
<FilterInput
|
||||
getFilterData={this.getData}
|
||||
@ -247,7 +251,9 @@ class SectionFilterContent extends React.Component {
|
||||
onFilter={this.onFilter}
|
||||
directionAscLabel={t("DirectionAscLabel")}
|
||||
directionDescLabel={t("DirectionDescLabel")}
|
||||
placeholder={t("FilterPlaceholder")}
|
||||
placeholder={t("Search")}
|
||||
needForUpdate={this.needForUpdate}
|
||||
language={i18n.language}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -19,11 +19,6 @@ import {
|
||||
updateUserType,
|
||||
fetchPeople
|
||||
} from "../../../../../store/people/actions";
|
||||
import {
|
||||
typeUser,
|
||||
typeGuest,
|
||||
department
|
||||
} from "../../../../../helpers/../helpers/customNames";
|
||||
import { deleteGroup } from "../../../../../store/group/actions";
|
||||
import { store, api, constants } from 'asc-web-common';
|
||||
import { InviteDialog } from '../../../../dialogs';
|
||||
@ -112,20 +107,20 @@ const SectionHeaderContent = props => {
|
||||
|
||||
const onSentInviteAgain = useCallback(() => {
|
||||
resendUserInvites(selectedUserIds)
|
||||
.then(() => toastr.success("The invitation was successfully sent"))
|
||||
.then(() => toastr.success(t('SuccessSendInvitation')))
|
||||
.catch(error => toastr.error(error));
|
||||
}, [selectedUserIds]);
|
||||
}, [selectedUserIds, t]);
|
||||
|
||||
const onDelete = useCallback(() => {
|
||||
onLoading(true);
|
||||
deleteUsers(selectedUserIds)
|
||||
.then(() => {
|
||||
toastr.success("Users have been removed successfully");
|
||||
toastr.success(t('SuccessfullyRemovedUsers'));
|
||||
return fetchPeople(filter);
|
||||
})
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => onLoading(false));
|
||||
}, [selectedUserIds, onLoading, filter]);
|
||||
}, [selectedUserIds, onLoading, filter, t]);
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
@ -142,12 +137,12 @@ const SectionHeaderContent = props => {
|
||||
onSelect: item => onSelect(item.key)
|
||||
},
|
||||
{
|
||||
label: t("CustomMakeUser", { typeUser }),
|
||||
label: t('ChangeToUser', { userCaption: settings.customNames.userCaption }),
|
||||
disabled: !selection.length,
|
||||
onClick: onSetEmployee
|
||||
},
|
||||
{
|
||||
label: t("CustomMakeGuest", { typeGuest }),
|
||||
label: t('ChangeToGuest', { guestCaption: settings.customNames.guestCaption }),
|
||||
disabled: !selection.length,
|
||||
onClick: onSetGuest
|
||||
},
|
||||
@ -169,7 +164,7 @@ const SectionHeaderContent = props => {
|
||||
{
|
||||
label: t("LblSendEmail"),
|
||||
disabled: !selection.length,
|
||||
onClick: toastr.success.bind(this, "Send e-mail action")
|
||||
onClick: toastr.success.bind(this, t("SendEmailAction"))
|
||||
},
|
||||
{
|
||||
label: t("DeleteButton"),
|
||||
@ -185,9 +180,9 @@ const SectionHeaderContent = props => {
|
||||
|
||||
const onDeleteGroup = useCallback(() => {
|
||||
deleteGroup(group.id).then(() =>
|
||||
toastr.success("Group has been removed successfully")
|
||||
toastr.success(t("SuccessfullyRemovedGroup"))
|
||||
);
|
||||
}, [deleteGroup, group]);
|
||||
}, [deleteGroup, group, t]);
|
||||
|
||||
const getContextOptionsGroup = useCallback(() => {
|
||||
return [
|
||||
@ -221,20 +216,21 @@ const SectionHeaderContent = props => {
|
||||
);
|
||||
|
||||
const getContextOptionsPlus = useCallback(() => {
|
||||
const { guestCaption, userCaption, groupCaption } = settings.customNames;
|
||||
return [
|
||||
{
|
||||
key: "new-employee",
|
||||
label: t("CustomNewEmployee", { typeUser }),
|
||||
label: userCaption,
|
||||
onClick: goToEmployeeCreate
|
||||
},
|
||||
{
|
||||
key: "new-guest",
|
||||
label: t("CustomNewGuest", { typeGuest }),
|
||||
label: guestCaption,
|
||||
onClick: goToGuestCreate
|
||||
},
|
||||
{
|
||||
key: "new-group",
|
||||
label: t("CustomNewDepartment", { department }),
|
||||
label: groupCaption,
|
||||
onClick: goToGroupCreate
|
||||
},
|
||||
{ key: 'separator', isSeparator: true },
|
||||
@ -245,11 +241,11 @@ const SectionHeaderContent = props => {
|
||||
}/* ,
|
||||
{
|
||||
key: "send-invitation",
|
||||
label: t("SendInvitationAgain"),
|
||||
label: t("SendInviteAgain"),
|
||||
onClick: onSentInviteAgain
|
||||
} */
|
||||
];
|
||||
}, [t, goToEmployeeCreate, goToGuestCreate, goToGroupCreate, onInvitationDialogClick/* , onSentInviteAgain */]);
|
||||
}, [settings, t, goToEmployeeCreate, goToGuestCreate, goToGroupCreate, onInvitationDialogClick/* , onSentInviteAgain */]);
|
||||
|
||||
return (
|
||||
<StyledContainer isHeaderVisible={isHeaderVisible}>
|
||||
@ -287,7 +283,7 @@ const SectionHeaderContent = props => {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Headline className='headline-header' truncate={true} type="content">Departments</Headline>
|
||||
<Headline className='headline-header' truncate={true} type="content">{settings.customNames.groupsCaption}</Headline>
|
||||
{isAdmin && (
|
||||
<>
|
||||
<ContextMenuButton
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,16 +10,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -40,16 +38,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -3,7 +3,7 @@ import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import { RequestLoader } from "asc-web-components";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import { PageLayout, utils } from "asc-web-common";
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from "./i18n";
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
SectionPagingContent
|
||||
} from "./Section";
|
||||
import { setSelected } from "../../../store/people/actions";
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class PureHome extends React.Component {
|
||||
constructor(props) {
|
||||
@ -148,8 +149,7 @@ class PureHome extends React.Component {
|
||||
const HomeContainer = withTranslation()(PureHome);
|
||||
|
||||
const Home = (props) => {
|
||||
const {language} = props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
return (<I18nextProvider i18n={i18n}><HomeContainer {...props}/></I18nextProvider>);
|
||||
}
|
||||
|
||||
@ -164,8 +164,7 @@ function mapStateToProps(state) {
|
||||
users: state.people.users,
|
||||
selection: state.people.selection,
|
||||
selected: state.people.selected,
|
||||
isLoaded: state.auth.isLoaded,
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture,
|
||||
isLoaded: state.auth.isLoaded
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,15 @@
|
||||
"People": "People",
|
||||
"PreviousPage": "Previous",
|
||||
"NextPage": "Next",
|
||||
"MessageEmailActivationInstuctionsSentOnEmail": "The email activation instructions have been sent to the <1>{{email}}</1> email address",
|
||||
"Search": "Search",
|
||||
"SendInviteAgain": "Send invitation once again",
|
||||
"SuccessSendInvitation": "The invitation was successfully sent",
|
||||
|
||||
"CountPerPage": "{{count}} per page",
|
||||
"PageOfTotalPage": "{{page}} of {{totalPage}}",
|
||||
"ChangeToUser": "Change to {{userCaption}}",
|
||||
"ChangeToGuest": "Change to {{guestCaption}}",
|
||||
|
||||
"LblInviteAgain": "Invite again",
|
||||
"ByFirstNameSorting": "By first name",
|
||||
@ -39,27 +48,10 @@
|
||||
"LblInvited": "Invited",
|
||||
"LblSetActive": "Set active",
|
||||
"LblSetDisabled": "Set disabled",
|
||||
"MessageEmailActivationInstuctionsSentOnEmail": "The email activation instructions have been sent to the <1>{{email}}</1> email address",
|
||||
|
||||
"CustomHeadOfDepartment": " {{headOfDepartment}}",
|
||||
"CustomTypeGuest": "{{typeGuest}}",
|
||||
"CustomTypeUser": "{{typeUser}}",
|
||||
"CustomMakeUser": "Make {{typeUser, lowercase}}",
|
||||
"CustomMakeGuest": "Make {{typeGuest, lowercase}}",
|
||||
"CustomDepartment": "{{department}}",
|
||||
"CountPerPage": "{{count}} per page",
|
||||
"PageOfTotalPage": "{{page}} of {{totalPage}}",
|
||||
|
||||
"DirectionAscLabel":"A-Z",
|
||||
"DirectionDescLabel":"Z-A",
|
||||
|
||||
"DefaultSelectLabel": "Select",
|
||||
|
||||
"FilterPlaceholder": "Search",
|
||||
|
||||
"CustomNewEmployee": "New {{typeUser, lowercase}}",
|
||||
"CustomNewGuest": "New {{typeGuest, lowercase}}",
|
||||
"CustomNewDepartment": "New {{department, lowercase}}",
|
||||
"MakeInvitationLink": "Make invitation link",
|
||||
"SendInvitationAgain": "Send invitation once"
|
||||
"SuccessfullyRemovedUsers": "Users have been removed successfully",
|
||||
"SendEmailAction": "Send e-mail action",
|
||||
"SuccessfullyRemovedGroup": "Group has been removed successfully"
|
||||
}
|
@ -32,34 +32,26 @@
|
||||
"People": "Люди",
|
||||
"PreviousPage": "Предыдущая",
|
||||
"NextPage": "Следующая",
|
||||
"MessageEmailActivationInstuctionsSentOnEmail": "Инструкции по активации электронной почты были отправлены на адрес <1>{{email}}</1>",
|
||||
"Search": "Поиск",
|
||||
"SendInviteAgain": "Отправить приглашение ещё раз",
|
||||
"SuccessSendInvitation": "Приглашение успешно отправлено",
|
||||
|
||||
"PageOfTotalPage": "{{page}} из {{totalPage}}",
|
||||
"CountPerPage": "{{count}} на странице",
|
||||
"ChangeToUser": "Изменить на {{userCaption}}",
|
||||
"ChangeToGuest": "Изменить на {{guestCaption}}",
|
||||
|
||||
"LblInviteAgain": "Выслать прилашение ещё раз",
|
||||
"ByFirstNameSorting": "По имени",
|
||||
"ByLastNameSorting": "По фамилии",
|
||||
"LblInvited": "Invited",
|
||||
"LblInvited": "Приглашен",
|
||||
"LblSetActive": "Разблокировать",
|
||||
"LblSetDisabled": "Заблокировать",
|
||||
"MessageEmailActivationInstuctionsSentOnEmail": "Инструкции по активации электронной почты были отправлены на адрес <1>{{email}}</1>",
|
||||
|
||||
"CustomHeadOfDepartment": " {{headOfDepartment}}",
|
||||
"CustomTypeGuest": "{{typeGuest}}",
|
||||
"CustomTypeUser": "{{typeUser}}",
|
||||
"CustomMakeUser": "Сделать {{typeUser, lowercase}}",
|
||||
"CustomMakeGuest": "Сделать {{typeGuest, lowercase}}",
|
||||
"CustomDepartment": "{{department}}",
|
||||
"CountPerPage": "{{count}} на странице",
|
||||
"PageOfTotalPage": "{{page}} из {{totalPage}}",
|
||||
|
||||
"DirectionAscLabel":"А-Я",
|
||||
"DirectionDescLabel":"Я-А",
|
||||
|
||||
"DefaultSelectLabel": "Выберите",
|
||||
|
||||
"FilterPlaceholder": "Поиск",
|
||||
|
||||
"CustomNewEmployee": "Новый {{typeUser, lowercase}}",
|
||||
"CustomNewGuest": "Новый {{typeGuest, lowercase}}",
|
||||
"CustomNewDepartment": "Новый {{department, lowercase}}",
|
||||
"MakeInvitationLink": "Создать пригласительную ссылку",
|
||||
"SendInvitationAgain": "Отправить приглашение ещё раз"
|
||||
"SuccessfullyRemovedUsers": "Пользователи были успешно удалены",
|
||||
"SendEmailAction": "Действие отправки e-mail",
|
||||
"SuccessfullyRemovedGroup": "Группа была успешно удалена"
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import React from "react";
|
||||
import { Trans } from 'react-i18next';
|
||||
import { department as departmentName, position, employedSinceDate } from '../../../../../../helpers/customNames';
|
||||
import {
|
||||
Text,
|
||||
IconButton,
|
||||
@ -10,8 +9,11 @@ import {
|
||||
HelpButton
|
||||
} from "asc-web-components";
|
||||
import styled from 'styled-components';
|
||||
import { history, api } from "asc-web-common";
|
||||
import { history, api, store as commonStore } from "asc-web-common";
|
||||
import { connect } from "react-redux";
|
||||
import store from "../../../../../../store/store";
|
||||
const { resendUserInvites } = api.people;
|
||||
const { getCurrentCustomSchema, getModules } = commonStore.auth.actions;
|
||||
|
||||
const InfoContainer = styled.div`
|
||||
margin-bottom: 24px;
|
||||
@ -123,11 +125,13 @@ class ProfileInfo extends React.PureComponent {
|
||||
|
||||
onLanguageSelect = (language) => {
|
||||
console.log("onLanguageSelect", language);
|
||||
const { profile, updateProfileCulture } = this.props;
|
||||
const { profile, updateProfileCulture, nameSchemaId } = this.props;
|
||||
|
||||
if (profile.cultureName === language.key) return;
|
||||
|
||||
updateProfileCulture(profile.id, language.key);
|
||||
updateProfileCulture(profile.id, language.key)
|
||||
.then(() => getModules(store.dispatch))
|
||||
.then(() => getCurrentCustomSchema(store.dispatch, nameSchemaId));
|
||||
}
|
||||
|
||||
getLanguages = () => {
|
||||
@ -142,8 +146,8 @@ class ProfileInfo extends React.PureComponent {
|
||||
const { isVisitor, email, activationStatus, department, groups, title, mobilePhone, sex, workFrom, birthday, location, cultureName, currentCulture } = this.props.profile;
|
||||
const isAdmin = this.props.isAdmin;
|
||||
const isSelf = this.props.isSelf;
|
||||
const { t, i18n } = this.props;
|
||||
const type = isVisitor ? "Guest" : "Employee";
|
||||
const { t, i18n, userPostCaption, regDateCaption, groupCaption, userCaption, guestCaption } = this.props;
|
||||
const type = isVisitor ? guestCaption : userCaption;
|
||||
const language = cultureName || currentCulture || this.props.culture;
|
||||
const languages = this.getLanguages();
|
||||
const selectedLanguage = languages.find(item => item.key === language);
|
||||
@ -238,7 +242,7 @@ class ProfileInfo extends React.PureComponent {
|
||||
{title &&
|
||||
<InfoItem>
|
||||
<InfoItemLabel>
|
||||
{t("CustomPosition", { position })}:
|
||||
{userPostCaption}:
|
||||
</InfoItemLabel>
|
||||
<InfoItemValue>
|
||||
{title}
|
||||
@ -248,7 +252,7 @@ class ProfileInfo extends React.PureComponent {
|
||||
{department &&
|
||||
<InfoItem>
|
||||
<InfoItemLabel>
|
||||
{t("CustomDepartment", { department: departmentName })}:
|
||||
{groupCaption}:
|
||||
</InfoItemLabel>
|
||||
<InfoItemValue>
|
||||
{formatedDepartments}
|
||||
@ -268,7 +272,7 @@ class ProfileInfo extends React.PureComponent {
|
||||
{workFrom &&
|
||||
<InfoItem>
|
||||
<InfoItemLabel>
|
||||
{t("CustomEmployedSinceDate", { employedSinceDate })}:
|
||||
{regDateCaption}:
|
||||
</InfoItemLabel>
|
||||
<InfoItemValue>
|
||||
{workFromDate}
|
||||
@ -293,13 +297,13 @@ class ProfileInfo extends React.PureComponent {
|
||||
className='language-combo'
|
||||
/>
|
||||
<HelpButton
|
||||
place="bottom"
|
||||
offsetLeft={50}
|
||||
offsetRight={0}
|
||||
tooltipContent={tooltipLanguage}
|
||||
helpButtonHeaderContent={t('Language')}
|
||||
className="help-icon"
|
||||
/>
|
||||
place="bottom"
|
||||
offsetLeft={50}
|
||||
offsetRight={0}
|
||||
tooltipContent={tooltipLanguage}
|
||||
helpButtonHeaderContent={t('Language')}
|
||||
className="help-icon"
|
||||
/>
|
||||
</InfoItemValue>
|
||||
|
||||
</InfoItem>
|
||||
@ -309,4 +313,15 @@ class ProfileInfo extends React.PureComponent {
|
||||
}
|
||||
};
|
||||
|
||||
export default ProfileInfo;
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
groupCaption: state.auth.settings.customNames.groupCaption,
|
||||
regDateCaption: state.auth.settings.customNames.regDateCaption,
|
||||
userPostCaption: state.auth.settings.customNames.userPostCaption,
|
||||
userCaption: state.auth.settings.customNames.userCaption,
|
||||
guestCaption: state.auth.settings.customNames.guestCaption,
|
||||
nameSchemaId: state.auth.settings.nameSchemaId
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(ProfileInfo);
|
@ -406,9 +406,9 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
headerLabel={t("editAvatar")}
|
||||
chooseFileLabel={t("chooseFileLabel")}
|
||||
chooseMobileFileLabel={t("chooseMobileFileLabel")}
|
||||
unknownTypeError={t("unknownTypeError")}
|
||||
unknownTypeError={t("ErrorUnknownFileImageType")}
|
||||
maxSizeFileError={t("maxSizeFileError")}
|
||||
unknownError={t("unknownError")}
|
||||
unknownError={t("Error")}
|
||||
/>
|
||||
|
||||
{dialogsVisible.deleteSelfProfile &&
|
||||
|
@ -1,12 +1,14 @@
|
||||
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: "en",
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
@ -33,7 +35,7 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: "en",
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -2,12 +2,13 @@ import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { Loader, toastr } from "asc-web-components";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import { PageLayout, utils } from "asc-web-common";
|
||||
import { ArticleHeaderContent, ArticleMainButtonContent, ArticleBodyContent } from '../../Article';
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
import { fetchProfile } from '../../../store/profile/actions';
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class PureProfile extends React.Component {
|
||||
|
||||
@ -68,9 +69,8 @@ class PureProfile extends React.Component {
|
||||
const ProfileContainer = withTranslation()(PureProfile);
|
||||
|
||||
const Profile = (props) => {
|
||||
const { language } = props;
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return <I18nextProvider i18n={i18n}><ProfileContainer {...props} /></I18nextProvider>
|
||||
};
|
||||
@ -86,7 +86,6 @@ Profile.propTypes = {
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
profile: state.profile.targetUser,
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture,
|
||||
isVisitor: state.auth.user.isVisitor,
|
||||
};
|
||||
}
|
||||
|
@ -23,26 +23,21 @@
|
||||
"Actions": "Actions",
|
||||
"ChangeEmailSuccess": "Mail has been successfully changed",
|
||||
"NotFoundLanguage": "In case you cannot find your language in the list of the available ones, feel free to write to us at <1>{{supportEmail}}</1> to take part in the translation and get up to 1 year free of charge.",
|
||||
"LearnMore": "Learn more...",
|
||||
"ErrorUnknownFileImageType": "Unknown image file type",
|
||||
"Error": "Error",
|
||||
"SocialProfiles": "Social profiles",
|
||||
|
||||
"PhoneChange": "Change phone",
|
||||
"PhoneLbl": "Phone",
|
||||
"EditSubscriptionsBtn": "Edit subscriptions",
|
||||
"InviteAgainLbl": "Invite again",
|
||||
"LDAPLbl": "LDAP",
|
||||
"SocialProfiles": "Social profiles",
|
||||
|
||||
"CustomEmployedSinceDate": "{{employedSinceDate}}",
|
||||
"CustomPosition": "{{position}}",
|
||||
"CustomDepartment": "{{department}}",
|
||||
"Culture_en": "English (United Kingdom)",
|
||||
"Culture_en-US": "English (United States)",
|
||||
"Culture_ru-RU": "Russian (Russia)",
|
||||
"LearnMore": "Learn more...",
|
||||
|
||||
"chooseFileLabel": "Drop file here, or click to select file",
|
||||
"chooseMobileFileLabel": "Click to select files",
|
||||
"unknownTypeError": "Unknown image file type",
|
||||
"maxSizeFileError": "Maximum file size exceeded",
|
||||
"unknownError": "Error",
|
||||
"editAvatar": "Edit photo"
|
||||
"editAvatar": "Edit"
|
||||
}
|
@ -23,26 +23,21 @@
|
||||
"Actions": "Действия",
|
||||
"ChangeEmailSuccess": "Email успешно изменен",
|
||||
"NotFoundLanguage": "Если Вы не можете найти свой язык в списке доступных, Вы всегда можете написать нам по адресу <1>{{supportEmail}}</1>, чтобы принять участие в переводе и получить до 1 года бесплатного использования.",
|
||||
"LearnMore": "Подробнее...",
|
||||
"ErrorUnknownFileImageType": "Неизвестный тип файла изображения",
|
||||
"Error": "Ошибка",
|
||||
"SocialProfiles": "Социальные профили",
|
||||
|
||||
"PhoneChange": "Измененить номер телефона",
|
||||
"PhoneChange": "Изменить номер телефона",
|
||||
"PhoneLbl": "Основной телефон",
|
||||
"EditSubscriptionsBtn": "Изменить подписки",
|
||||
"InviteAgainLbl": "Активировать адрес email ещё раз",
|
||||
"LDAPLbl": "LDAP",
|
||||
"SocialProfiles": "Социальные профили",
|
||||
|
||||
"CustomEmployedSinceDate": "{{employedSinceDate}}",
|
||||
"CustomPosition": "{{position}}",
|
||||
"CustomDepartment": "{{department}}",
|
||||
"Culture_en": "Английский (Великобритания)",
|
||||
"Culture_en-US": "Английский (США)",
|
||||
"Culture_ru-RU": "Русский (Россия)",
|
||||
"LearnMore": "Подробнее...",
|
||||
|
||||
"chooseFileLabel": "Перетащите файл сюда или нажмите, чтобы выбрать файл",
|
||||
"chooseMobileFileLabel": "Нажмите сюда, чтобы выбрать файл",
|
||||
"unknownTypeError": "Неизвестный тип файла изображения",
|
||||
"maxSizeFileError": "Превышен максимальный размер файла",
|
||||
"unknownError": "Ошибка",
|
||||
"editAvatar": "Изменить фотографию"
|
||||
"editAvatar": "Изменить"
|
||||
}
|
@ -29,8 +29,7 @@ class DepartmentField extends React.Component {
|
||||
|
||||
selectorIsVisible,
|
||||
selectorSelectedOptions,
|
||||
selectorOnSelectGroups,
|
||||
searchPlaceHolderLabel
|
||||
selectorOnSelectGroups
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -51,7 +50,6 @@ class DepartmentField extends React.Component {
|
||||
isMultiSelect={true}
|
||||
onSelect={selectorOnSelectGroups}
|
||||
onCancel={onCloseGroupSelector}
|
||||
searchPlaceHolderLabel={searchPlaceHolderLabel}
|
||||
/>
|
||||
{selectorSelectedOptions.map(option => (
|
||||
<SelectedItem
|
||||
|
@ -14,7 +14,6 @@ import RadioField from './FormFields/RadioField'
|
||||
import DepartmentField from './FormFields/DepartmentField'
|
||||
import ContactsField from './FormFields/ContactsField'
|
||||
import InfoFieldContainer from './FormFields/InfoFieldContainer'
|
||||
import { departments, department, position, employedSinceDate } from '../../../../../helpers/customNames';
|
||||
import { api } from "asc-web-common";
|
||||
const {
|
||||
createThumbnailsAvatar,
|
||||
@ -320,6 +319,7 @@ class CreateUserForm extends React.Component {
|
||||
render() {
|
||||
const { isLoading, errors, profile, selector } = this.state;
|
||||
const { t, settings, i18n } = this.props;
|
||||
const { regDateCaption, userPostCaption, groupCaption } = settings.customNames;
|
||||
|
||||
const pattern = getUserContactsPattern();
|
||||
const contacts = getUserContacts(profile.contacts);
|
||||
@ -333,7 +333,7 @@ class CreateUserForm extends React.Component {
|
||||
role={getUserRole(profile)}
|
||||
editing={true}
|
||||
source={this.state.croppedAvatarImage}
|
||||
editLabel={t("AddPhoto")}
|
||||
editLabel={t("AddButton")}
|
||||
editAction={this.openAvatarEditor}
|
||||
/>
|
||||
<AvatarEditor
|
||||
@ -342,12 +342,12 @@ class CreateUserForm extends React.Component {
|
||||
onClose={this.onCloseAvatarEditor}
|
||||
onSave={this.onSaveAvatar}
|
||||
onLoadFile={this.onLoadFileAvatar}
|
||||
headerLabel={t("editAvatar")}
|
||||
headerLabel={t("AddPhoto")}
|
||||
chooseFileLabel ={t("chooseFileLabel")}
|
||||
chooseMobileFileLabel={t("chooseMobileFileLabel")}
|
||||
unknownTypeError={t("unknownTypeError")}
|
||||
unknownTypeError={t("ErrorUnknownFileImageType")}
|
||||
maxSizeFileError={t("maxSizeFileError")}
|
||||
unknownError ={t("unknownError")}
|
||||
unknownError ={t("Error")}
|
||||
/>
|
||||
</AvatarContainer>
|
||||
<MainFieldsContainer ref={this.mainFieldsContainerRef}>
|
||||
@ -419,7 +419,7 @@ class CreateUserForm extends React.Component {
|
||||
passwordSettings={settings.passwordSettings}
|
||||
/>
|
||||
<DateField
|
||||
calendarHeaderContent={t("CalendarSelectDate")}
|
||||
calendarHeaderContent={`${t("CalendarSelectDate")}:`}
|
||||
labelText={`${t("Birthdate")}:`}
|
||||
inputName="birthday"
|
||||
inputValue={profile.birthday ? new Date(profile.birthday) : undefined}
|
||||
@ -432,15 +432,15 @@ class CreateUserForm extends React.Component {
|
||||
radioName="sex"
|
||||
radioValue={profile.sex}
|
||||
radioOptions={[
|
||||
{ value: 'male', label: t("SexMale") },
|
||||
{ value: 'female', label: t("SexFemale") }
|
||||
{ value: 'male', label: t("MaleSexStatus") },
|
||||
{ value: 'female', label: t("FemaleSexStatus") }
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
/>
|
||||
<DateField
|
||||
calendarHeaderContent={t("CalendarSelectDate")}
|
||||
labelText={`${t("CustomEmployedSinceDate", { employedSinceDate })}:`}
|
||||
calendarHeaderContent={`${t("CalendarSelectDate")}:`}
|
||||
labelText={`${regDateCaption}:`}
|
||||
inputName="workFrom"
|
||||
inputValue={profile.workFrom ? new Date(profile.workFrom) : undefined}
|
||||
inputIsDisabled={isLoading}
|
||||
@ -456,7 +456,7 @@ class CreateUserForm extends React.Component {
|
||||
inputTabIndex={7}
|
||||
/>
|
||||
<TextField
|
||||
labelText={`${t("CustomPosition", { position })}:`}
|
||||
labelText={`${userPostCaption}:`}
|
||||
inputName="title"
|
||||
inputValue={profile.title}
|
||||
inputIsDisabled={isLoading}
|
||||
@ -464,17 +464,15 @@ class CreateUserForm extends React.Component {
|
||||
inputTabIndex={8}
|
||||
/>
|
||||
<DepartmentField
|
||||
labelText={`${t("CustomDepartment", { department })}:`}
|
||||
labelText={`${groupCaption}:`}
|
||||
isDisabled={isLoading}
|
||||
showGroupSelectorButtonTitle={t("AddButton")}
|
||||
onShowGroupSelector={this.onShowGroupSelector}
|
||||
onCloseGroupSelector={this.onCloseGroupSelector}
|
||||
onRemoveGroup={this.onRemoveGroup}
|
||||
selectorIsVisible={selector.visible}
|
||||
searchPlaceHolderLabel={t("SearchDepartments")}
|
||||
selectorOptions={selector.options}
|
||||
selectorSelectedOptions={selector.selected}
|
||||
selectorAddButtonText={t("CustomAddDepartments", { departments })}
|
||||
selectorSelectAllText={t("SelectAll")}
|
||||
selectorOnSearchGroups={this.onSearchGroups}
|
||||
selectorOnSelectGroups={this.onSelectGroups}
|
||||
@ -482,7 +480,7 @@ class CreateUserForm extends React.Component {
|
||||
</MainFieldsContainer>
|
||||
</MainContainer>
|
||||
<InfoFieldContainer headerText={t("Comments")}>
|
||||
<Textarea placeholder={t("AddСomment")} name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={9}/>
|
||||
<Textarea placeholder={t("WriteComment")} name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={9}/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer headerText={t("ContactInformation")}>
|
||||
<ContactsField
|
||||
|
@ -13,7 +13,6 @@ import RadioField from './FormFields/RadioField'
|
||||
import DepartmentField from './FormFields/DepartmentField'
|
||||
import ContactsField from './FormFields/ContactsField'
|
||||
import InfoFieldContainer from './FormFields/InfoFieldContainer'
|
||||
import { departments, department, position, employedSinceDate, typeGuest, typeUser } from '../../../../../helpers/customNames';
|
||||
import styled from "styled-components";
|
||||
import { api } from "asc-web-common";
|
||||
import { ChangeEmailDialog, ChangePasswordDialog, ChangePhoneDialog } from '../../../../dialogs';
|
||||
@ -366,7 +365,8 @@ class UpdateUserForm extends React.Component {
|
||||
|
||||
render() {
|
||||
const { isLoading, errors, profile, selector, dialogsVisible } = this.state;
|
||||
const { t, i18n } = this.props;
|
||||
const { t, i18n, settings } = this.props;
|
||||
const { guestCaption, userCaption, regDateCaption, userPostCaption, groupCaption } = settings.customNames;
|
||||
|
||||
const pattern = getUserContactsPattern();
|
||||
const contacts = getUserContacts(profile.contacts);
|
||||
@ -389,12 +389,12 @@ class UpdateUserForm extends React.Component {
|
||||
</Th>
|
||||
<Th>
|
||||
<Text isBold fontSize='13px'>
|
||||
{t("Employee")}
|
||||
{userCaption}
|
||||
</Text>
|
||||
</Th>
|
||||
<Th>
|
||||
<Text isBold fontSize='13px'>
|
||||
{t("GuestCaption")}
|
||||
{guestCaption}
|
||||
</Text>
|
||||
</Th>
|
||||
</tr>
|
||||
@ -455,7 +455,7 @@ class UpdateUserForm extends React.Component {
|
||||
source={profile.avatarMax}
|
||||
userName={profile.displayName}
|
||||
editing={true}
|
||||
editLabel={t("EditPhoto")}
|
||||
editLabel={t("editAvatar")}
|
||||
editAction={this.openAvatarEditor}
|
||||
/>
|
||||
<AvatarEditor
|
||||
@ -464,12 +464,12 @@ class UpdateUserForm extends React.Component {
|
||||
onClose={this.onCloseAvatarEditor}
|
||||
onSave={this.onSaveAvatar}
|
||||
onLoadFile={this.onLoadFileAvatar}
|
||||
headerLabel={t("editAvatar")}
|
||||
headerLabel={t("EditPhoto")}
|
||||
chooseFileLabel={t("chooseFileLabel")}
|
||||
chooseMobileFileLabel={t("chooseMobileFileLabel")}
|
||||
unknownTypeError={t("unknownTypeError")}
|
||||
unknownTypeError={t("ErrorUnknownFileImageType")}
|
||||
maxSizeFileError={t("maxSizeFileError")}
|
||||
unknownError={t("unknownError")}
|
||||
unknownError={t("Error")}
|
||||
/>
|
||||
</AvatarContainer>
|
||||
<MainFieldsContainer ref={this.mainFieldsContainerRef}>
|
||||
@ -541,7 +541,7 @@ class UpdateUserForm extends React.Component {
|
||||
maxLength={50}
|
||||
/>
|
||||
<DateField
|
||||
calendarHeaderContent={t("CalendarSelectDate")}
|
||||
calendarHeaderContent={`${t("CalendarSelectDate")}:`}
|
||||
labelText={`${t("Birthdate")}:`}
|
||||
inputName="birthday"
|
||||
inputValue={profile.birthday ? new Date(profile.birthday) : undefined}
|
||||
@ -554,8 +554,8 @@ class UpdateUserForm extends React.Component {
|
||||
radioName="sex"
|
||||
radioValue={profile.sex}
|
||||
radioOptions={[
|
||||
{ value: 'male', label: t("SexMale") },
|
||||
{ value: 'female', label: t("SexFemale") }
|
||||
{ value: 'male', label: t("MaleSexStatus") },
|
||||
{ value: 'female', label: t("FemaleSexStatus") }
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
@ -565,8 +565,8 @@ class UpdateUserForm extends React.Component {
|
||||
radioName="isVisitor"
|
||||
radioValue={profile.isVisitor.toString()}
|
||||
radioOptions={[
|
||||
{ value: "true", label: t("CustomTypeGuest", { typeGuest }) },
|
||||
{ value: "false", label: t("CustomTypeUser", { typeUser }) }
|
||||
{ value: "true", label: guestCaption },
|
||||
{ value: "false", label: userCaption }
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onUserTypeChange}
|
||||
@ -575,8 +575,8 @@ class UpdateUserForm extends React.Component {
|
||||
helpButtonHeaderContent={t('UserType')}
|
||||
/>
|
||||
<DateField
|
||||
calendarHeaderContent={t("CalendarSelectDate")}
|
||||
labelText={`${t("CustomEmployedSinceDate", { employedSinceDate })}:`}
|
||||
calendarHeaderContent={`${t("CalendarSelectDate")}:`}
|
||||
labelText={`${regDateCaption}:`}
|
||||
inputName="workFrom"
|
||||
inputValue={profile.workFrom ? new Date(profile.workFrom) : undefined}
|
||||
inputIsDisabled={isLoading}
|
||||
@ -592,7 +592,7 @@ class UpdateUserForm extends React.Component {
|
||||
inputTabIndex={8}
|
||||
/>
|
||||
<TextField
|
||||
labelText={`${t("CustomPosition", { position })}:`}
|
||||
labelText={`${userPostCaption}:`}
|
||||
inputName="title"
|
||||
inputValue={profile.title}
|
||||
inputIsDisabled={isLoading}
|
||||
@ -600,17 +600,15 @@ class UpdateUserForm extends React.Component {
|
||||
inputTabIndex={9}
|
||||
/>
|
||||
<DepartmentField
|
||||
labelText={`${t("CustomDepartment", { department })}:`}
|
||||
labelText={`${groupCaption}:`}
|
||||
isDisabled={isLoading}
|
||||
showGroupSelectorButtonTitle={t("AddButton")}
|
||||
onShowGroupSelector={this.onShowGroupSelector}
|
||||
onCloseGroupSelector={this.onCloseGroupSelector}
|
||||
onRemoveGroup={this.onRemoveGroup}
|
||||
selectorIsVisible={selector.visible}
|
||||
searchPlaceHolderLabel={t("SearchDepartments")}
|
||||
selectorOptions={selector.options}
|
||||
selectorSelectedOptions={selector.selected}
|
||||
selectorAddButtonText={t("CustomAddDepartments", { departments })}
|
||||
selectorSelectAllText={t("SelectAll")}
|
||||
selectorOnSearchGroups={this.onSearchGroups}
|
||||
selectorOnSelectGroups={this.onSelectGroups}
|
||||
@ -618,7 +616,7 @@ class UpdateUserForm extends React.Component {
|
||||
</MainFieldsContainer>
|
||||
</MainContainer>
|
||||
<InfoFieldContainer headerText={t("Comments")}>
|
||||
<Textarea placeholder={t("AddСomment")} name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={10}/>
|
||||
<Textarea placeholder={t("WriteComment")} name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={10}/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer headerText={t("ContactInformation")}>
|
||||
<ContactsField
|
||||
|
@ -5,7 +5,6 @@ import { withRouter } from "react-router";
|
||||
import { IconButton } from 'asc-web-components';
|
||||
import { Headline } from 'asc-web-common';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { typeUser, typeGuest } from './../../../../../helpers/customNames';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
@ -24,16 +23,17 @@ const Wrapper = styled.div`
|
||||
`;
|
||||
|
||||
const SectionHeaderContent = (props) => {
|
||||
const { profile, history, match } = props;
|
||||
const { profile, history, match, settings } = props;
|
||||
const { userCaption, guestCaption } = settings.customNames;
|
||||
const { type } = match.params;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const headerText = type
|
||||
? type === "guest"
|
||||
? t('CustomNewGuest', { typeGuest })
|
||||
: t('CustomNewEmployee', { typeUser })
|
||||
? t('CustomCreation', { user: guestCaption })
|
||||
: t('CustomCreation', { user: userCaption })
|
||||
: profile
|
||||
? `${t('EditProfile')} (${profile.displayName})`
|
||||
? `${t('EditUserDialogTitle')} (${profile.displayName})`
|
||||
: "";
|
||||
|
||||
const onClickBack = useCallback(() => {
|
||||
|
@ -1,6 +1,8 @@
|
||||
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();
|
||||
|
||||
@ -8,12 +10,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
@ -36,12 +38,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { Loader } from "asc-web-components";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import { PageLayout, utils } from "asc-web-common";
|
||||
import {
|
||||
ArticleHeaderContent,
|
||||
ArticleMainButtonContent,
|
||||
@ -16,6 +16,7 @@ import {
|
||||
import { fetchProfile } from "../../../store/profile/actions";
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class ProfileAction extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -41,10 +42,10 @@ class ProfileAction extends React.Component {
|
||||
console.log("ProfileAction render");
|
||||
|
||||
let loaded = false;
|
||||
const { profile, isVisitor, match, language } = this.props;
|
||||
const { profile, isVisitor, match } = this.props;
|
||||
const { userId, type } = match.params;
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
if (type) {
|
||||
loaded = true;
|
||||
@ -88,7 +89,6 @@ ProfileAction.propTypes = {
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
profile: state.profile.targetUser,
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture,
|
||||
isVisitor: state.auth.user.isVisitor,
|
||||
};
|
||||
}
|
||||
|
@ -28,36 +28,27 @@
|
||||
"CommunityProduct": "Community",
|
||||
"People": "People",
|
||||
"Message": "Talk",
|
||||
"WriteComment": "Add comment",
|
||||
"MaleSexStatus": "Male",
|
||||
"FemaleSexStatus": "Female",
|
||||
"EditUserDialogTitle": "Edit profile",
|
||||
"ErrorUnknownFileImageType": "Unknown image file type",
|
||||
"Error": "Error",
|
||||
|
||||
"CustomCreation": "{{user}} (creation)",
|
||||
|
||||
"ActivationLink": "Activation link",
|
||||
"AddPhoto": "Add photo",
|
||||
"AddСomment": "Add comment",
|
||||
"TemporaryPassword": "Temporary password",
|
||||
"SexMale": "Male",
|
||||
"SexFemale": "Female",
|
||||
"RequiredField": "Required field",
|
||||
"ChangeButton": "Change",
|
||||
"Phone": "Phone",
|
||||
"ChangesSavedSuccessfully": "Changes saved successfully",
|
||||
"EditProfile": "Edit profile",
|
||||
"SearchDepartments": "Search departments",
|
||||
|
||||
"CustomEmployedSinceDate": "{{employedSinceDate}}",
|
||||
"CustomPosition": "{{position}}",
|
||||
"CustomDepartment": "{{department}}",
|
||||
"CustomTypeGuest": "{{typeGuest}}",
|
||||
"CustomTypeUser": "{{typeUser}}",
|
||||
"CustomNewEmployee": "New {{typeUser, lowercase}}",
|
||||
"CustomNewGuest": "New {{typeGuest, lowercase}}",
|
||||
"CustomAddDepartments": "Add {{departments, lowercase}}",
|
||||
|
||||
"chooseFileLabel": "Drop file here, or click to select file",
|
||||
"chooseMobileFileLabel": "Click to select files",
|
||||
"unknownTypeError": "Unknown image file type",
|
||||
"maxSizeFileError": "Maximum file size exceeded",
|
||||
"unknownError": "Error",
|
||||
"editAvatar": "Edit photo",
|
||||
"CalendarSelectDate": "Select date:",
|
||||
"Employee": "Employee",
|
||||
"editAvatar": "Edit",
|
||||
"CalendarSelectDate": "Select date",
|
||||
"Calendar": "Calendar"
|
||||
}
|
@ -20,7 +20,6 @@
|
||||
"EmailPopupHelper": "Основной email нужен для восстановления доступа к порталу в случае потери пароля, а также для отправки оповещений. <1>Вы можете создать новый email на домене в качестве основного. В этом случае потребуется задать одноразовый пароль, чтобы пользователь смог войти на портал в первый раз.</1> Основной email можно использовать как логин при входе на портал.",
|
||||
"ProfileTypePopupHelper": "Гости имеют ограниченный доступ к некоторым функциям и модулям портала",
|
||||
"ProductsAndInstruments_Products": "Модули",
|
||||
"GuestCaption": "Гость",
|
||||
"TermsOfUsePopupHelperLink": "Подробнее об условиях использования",
|
||||
"Mail": "Почта",
|
||||
"DocumentsProduct": "Документы",
|
||||
@ -28,36 +27,27 @@
|
||||
"CommunityProduct": "Сообщество",
|
||||
"People": "Люди",
|
||||
"Message": "Чат",
|
||||
"WriteComment": "Добавить комментарий",
|
||||
"MaleSexStatus": "Мужской",
|
||||
"FemaleSexStatus": "Женский",
|
||||
"EditUserDialogTitle": "Редактирование профиля",
|
||||
"ErrorUnknownFileImageType": "Неизвестный тип файла изображения",
|
||||
"Error": "Ошибка",
|
||||
|
||||
"CustomCreation": "{{user}} (создание)",
|
||||
|
||||
"ActivationLink": "Activation link",
|
||||
"ActivationLink": "Ссылка для активации",
|
||||
"AddPhoto": "Добавить фотографию",
|
||||
"AddСomment": "Добавить комментарий",
|
||||
"TemporaryPassword": "Temporary password",
|
||||
"SexMale": "Мужской",
|
||||
"SexFemale": "Женский",
|
||||
"TemporaryPassword": "Временный пароль",
|
||||
"RequiredField": "Обязательное поле",
|
||||
"ChangeButton": "Изменить",
|
||||
"Phone": "Телефон",
|
||||
"ChangesSavedSuccessfully": "Изменения успешно сохранены",
|
||||
"EditProfile": "Редактирование профиля",
|
||||
"SearchDepartments": "Поиск группы",
|
||||
|
||||
"CustomEmployedSinceDate": "{{employedSinceDate}}",
|
||||
"CustomPosition": "{{position}}",
|
||||
"CustomDepartment": "{{department}}",
|
||||
"CustomTypeGuest": "{{typeGuest}}",
|
||||
"CustomTypeUser": "{{typeUser}}",
|
||||
"CustomNewEmployee": "Новый {{typeUser, lowercase}}",
|
||||
"CustomNewGuest": "Новый {{typeGuest, lowercase}}",
|
||||
"CustomAddDepartments": "Добавить {{departments, lowercase}}",
|
||||
|
||||
"chooseFileLabel": "Перетащите файл сюда или нажмите, чтобы выбрать файл",
|
||||
"chooseMobileFileLabel": "Нажмите сюда, чтобы выбрать файл",
|
||||
"unknownTypeError": "Неизвестный тип файла изображения",
|
||||
"maxSizeFileError": "Превышен максимальный размер файла",
|
||||
"unknownError": "Ошибка",
|
||||
"editAvatar": "Изменить фотографию",
|
||||
"CalendarSelectDate": "Выберите дату:",
|
||||
"Employee": "Гость",
|
||||
"editAvatar": "Изменить",
|
||||
"CalendarSelectDate": "Выберите дату",
|
||||
"Calendar": "Календарь"
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
export const departments = 'Departments';
|
||||
export const department = 'Department';
|
||||
export const position = 'Position';
|
||||
export const employedSinceDate = 'Employed since';
|
||||
export const typeGuest = 'Guest';
|
||||
export const typeGuests = 'Guests';
|
||||
export const typeUser = 'Employee';
|
||||
export const headOfDepartment = 'Head of department';
|
@ -43,7 +43,8 @@
|
||||
"ChangePhoneDialog":{
|
||||
"Resource": [
|
||||
"SendButton",
|
||||
"MobilePhoneChangeTitle"
|
||||
"MobilePhoneChangeTitle",
|
||||
"MobilePhoneEraseDescription"
|
||||
]
|
||||
},
|
||||
"DeleteProfileEverDialog":{
|
||||
@ -95,7 +96,10 @@
|
||||
"EditButton",
|
||||
"ChangeEmailSuccess",
|
||||
"Actions",
|
||||
"NotFoundLanguage"
|
||||
"NotFoundLanguage",
|
||||
"LearnMore",
|
||||
"ErrorUnknownFileImageType",
|
||||
"Error"
|
||||
]
|
||||
},
|
||||
"ProfileAction": {
|
||||
@ -113,20 +117,25 @@
|
||||
"CopyEmailAndPassword",
|
||||
"UserType",
|
||||
"CancelButton",
|
||||
|
||||
"EmailPopupHelper",
|
||||
"ProfileTypePopupHelper",
|
||||
"ProductsAndInstruments_Products",
|
||||
"GuestCaption",
|
||||
"TermsOfUsePopupHelperLink",
|
||||
"Mail",
|
||||
"People"
|
||||
"People",
|
||||
"MaleSexStatus",
|
||||
"FemaleSexStatus",
|
||||
"EditUserDialogTitle",
|
||||
"ErrorUnknownFileImageType",
|
||||
"Error"
|
||||
],
|
||||
"FeedResource": [
|
||||
"DocumentsProduct",
|
||||
"ProjectsProduct",
|
||||
"CommunityProduct",
|
||||
"Message"
|
||||
"Message",
|
||||
"WriteComment"
|
||||
]
|
||||
},
|
||||
"Home": {
|
||||
@ -150,7 +159,9 @@
|
||||
"Actions",
|
||||
"People",
|
||||
"MessageEmailActivationInstuctionsSentOnEmail",
|
||||
"EnableUserButton"
|
||||
"EnableUserButton",
|
||||
"Search",
|
||||
"SendInviteAgain"
|
||||
],
|
||||
"PeopleResource": [
|
||||
"LblSendEmail",
|
||||
@ -166,7 +177,8 @@
|
||||
],
|
||||
"PeopleJSResource": [
|
||||
"SuccessChangeUserStatus",
|
||||
"SuccessChangeUserType"
|
||||
"SuccessChangeUserType",
|
||||
"SuccessSendInvitation"
|
||||
],
|
||||
"UserControlsCommonResource": [
|
||||
"NextPage",
|
||||
@ -186,7 +198,18 @@
|
||||
"GroupAction": {
|
||||
"Resource": [
|
||||
"SaveButton",
|
||||
"CancelButton"
|
||||
"CancelButton",
|
||||
"Name"
|
||||
],
|
||||
"PeopleResource": [
|
||||
"Members",
|
||||
"AddMembers",
|
||||
"AddButton"
|
||||
],
|
||||
"UserControlsCommonResource": [
|
||||
"Members",
|
||||
"AddMembers",
|
||||
"LblSelect"
|
||||
]
|
||||
},
|
||||
"Reassign":{
|
||||
@ -202,7 +225,7 @@
|
||||
"ReassignButton",
|
||||
"ReassignsToUser"
|
||||
],
|
||||
"UserControlsCommonResource.resx":[
|
||||
"UserControlsCommonResource":[
|
||||
"NotBeUndone"
|
||||
],
|
||||
"PeopleJSResource":[
|
||||
|
@ -283,6 +283,26 @@ namespace ASC.Api.Settings
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[Read("customschemas/{id}")]
|
||||
public SchemaItemModel PeopleSchema(string id)
|
||||
{
|
||||
var names = CustomNamingPeople.GetPeopleNames(id);
|
||||
var schemaItem = new SchemaItemModel
|
||||
{
|
||||
Id = names.Id,
|
||||
UserCaption = names.UserCaption,
|
||||
UsersCaption = names.UsersCaption,
|
||||
GroupCaption = names.GroupCaption,
|
||||
GroupsCaption = names.GroupsCaption,
|
||||
UserPostCaption = names.UserPostCaption,
|
||||
RegDateCaption = names.RegDateCaption,
|
||||
GroupHeadCaption = names.GroupHeadCaption,
|
||||
GuestCaption = names.GuestCaption,
|
||||
GuestsCaption = names.GuestsCaption,
|
||||
};
|
||||
return schemaItem;
|
||||
}
|
||||
|
||||
[Read("quota")]
|
||||
public QuotaWrapper GetQuotaUsed()
|
||||
{
|
||||
|
@ -1,5 +1,8 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -7,16 +10,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,16 +38,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Text, Link } from "asc-web-components";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import { PageLayout, utils } from "asc-web-common";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import version from "../../../../package.json";
|
||||
import styled from "styled-components";
|
||||
import { Trans } from "react-i18next";
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
const BodyStyle = styled.div`
|
||||
margin-top: 24px;
|
||||
@ -73,12 +73,12 @@ const VersionStyle = styled.div`
|
||||
padding: 8px 0px 20px 0px;
|
||||
`;
|
||||
|
||||
const Body = ({ language }) => {
|
||||
const Body = () => {
|
||||
const { t } = useTranslation("translation", { i18n });
|
||||
|
||||
useEffect(() => {
|
||||
i18n.changeLanguage(language);
|
||||
}, [language]);
|
||||
changeLanguage(i18n);
|
||||
}, []);
|
||||
|
||||
const gitHub = "GitHub";
|
||||
const license = "AGPL-3.0";
|
||||
@ -191,10 +191,5 @@ const About = ({ language }) => (
|
||||
<PageLayout sectionBodyContent={<Body language={language} />} />
|
||||
);
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(About);
|
||||
export default About;
|
||||
|
@ -1,5 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -7,16 +9,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,16 +37,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { Suspense, lazy } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { Loader } from "asc-web-components";
|
||||
import ConfirmRoute from "../../../helpers/confirmRoute";
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import { Error404 } from "asc-web-common";
|
||||
import { Error404, utils } from "asc-web-common";
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
const ActivateUserForm = lazy(() => import("./sub-components/activateUser"));
|
||||
const CreateUserForm = lazy(() => import("./sub-components/createUser"));
|
||||
@ -16,9 +17,9 @@ const ChangePhoneForm = lazy(() => import("./sub-components/changePhone"));
|
||||
const ProfileRemoveForm = lazy(() => import("./sub-components/profileRemove"));
|
||||
const ChangeOwnerForm = lazy(() => import("./sub-components/changeOwner"));
|
||||
|
||||
const Confirm = ({ match, language }) => {
|
||||
const Confirm = ({ match }) => {
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
//console.log("Confirm render");
|
||||
return (
|
||||
@ -74,10 +75,4 @@ const Confirm = ({ match, language }) => {
|
||||
);
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Confirm);
|
||||
export default Confirm;
|
||||
|
@ -26,5 +26,5 @@
|
||||
"ConfirmOwnerPortalTitle": "Please confirm that you want to change portal owner to {{newOwner}}",
|
||||
"SaveButton": "Save",
|
||||
"CancelButton": "Cancel",
|
||||
"ConfirmOwnerPortalSuccessMessage": "Владелец портала был успешно изменен. {0} Через 10 секунд вы будете перенаправлены {1} сюда {2}"
|
||||
"ConfirmOwnerPortalSuccessMessage": "Portal owner has been successfully changed. {0}In 10 seconds you will be redirected {1}here{2}"
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -7,16 +9,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: false,
|
||||
|
||||
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: {
|
||||
@ -36,16 +34,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -3,11 +3,13 @@ import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from "react-router";
|
||||
import { Loader, toastr, Text } from 'asc-web-components';
|
||||
import { ModuleTile, PageLayout } from "asc-web-common";
|
||||
import { ModuleTile, PageLayout, utils } from "asc-web-common";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import i18n from './i18n';
|
||||
import styled from "styled-components";
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
const HomeContainer = styled.div`
|
||||
padding: 62px 15px 0 15px;
|
||||
margin: 0 auto;
|
||||
@ -74,6 +76,8 @@ const Body = ({ modules, match, isLoaded }) => {
|
||||
params.error && toastr.error(params.error);
|
||||
}, [params.error]);
|
||||
|
||||
useEffect(() => changeLanguage(i18n), []);
|
||||
|
||||
return (
|
||||
!isLoaded
|
||||
? (
|
||||
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"NoOneModulesAvailable": "Ни один модуль не доступен"
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
import React from 'react';
|
||||
import { utils } from 'asc-web-components';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
TreeMenu,
|
||||
TreeNode,
|
||||
Icons,
|
||||
Link
|
||||
Link,
|
||||
utils
|
||||
} from "asc-web-components";
|
||||
import { withRouter } from "react-router";
|
||||
import styled from 'styled-components';
|
||||
@ -58,10 +57,9 @@ class ArticleBodyContent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { match, history, i18n, language } = props;
|
||||
const { match, history } = props;
|
||||
const fullSettingsUrl = props.match.url;
|
||||
const locationPathname = props.location.pathname;
|
||||
i18n.changeLanguage(language);
|
||||
|
||||
if (locationPathname === fullSettingsUrl) {
|
||||
const defaultKey = ['0'];
|
||||
@ -101,20 +99,14 @@ class ArticleBodyContent extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (!utils.array.isArrayEqual(prevState.selectedKeys, this.state.selectedKeys)){
|
||||
const { selectedKeys } = this.state;
|
||||
const { match, history } = this.props;
|
||||
const settingsPath = getSelectedLinkByKey(selectedKeys[0], settingsTree);
|
||||
const newPath = match.path + settingsPath;
|
||||
history.push(newPath);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
if (!utils.array.isArrayEqual(nextState.selectedKeys, this.state.selectedKeys)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
onSelect = value => {
|
||||
@ -168,10 +160,4 @@ class ArticleBodyContent extends React.Component {
|
||||
};
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(withTranslation()(ArticleBodyContent)));
|
||||
export default withRouter(withTranslation()(ArticleBodyContent));
|
||||
|
@ -33,7 +33,7 @@ const Layout = ({ currentProductId, setCurrentProductId, language, children }) =
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language: state.auth.user.cultureName
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,12 @@ import { withTranslation } from 'react-i18next';
|
||||
import { FieldContainer, Text, ComboBox, Loader, Button, toastr, Link, TextInput } from "asc-web-components";
|
||||
import styled from 'styled-components';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { store } from 'asc-web-common';
|
||||
import { store, utils } from 'asc-web-common';
|
||||
import { setLanguageAndTime, getPortalTimezones, setGreetingTitle, restoreGreetingTitle } from '../../../../../store/settings/actions';
|
||||
const { getPortalCultures } = store.auth.actions;
|
||||
import { default as clientStore } from '../../../../../store/store';
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
const { getPortalCultures, getModules } = store.auth.actions;
|
||||
|
||||
const mapCulturesToArray = (cultures, t) => {
|
||||
return cultures.map((culture) => {
|
||||
@ -94,6 +97,19 @@ class Customization extends React.Component {
|
||||
if (timezones.length && languages.length && !prevState.isLoadedData) {
|
||||
this.setState({ isLoadedData: true });
|
||||
}
|
||||
if (this.props.language !== prevProps.language) {
|
||||
changeLanguage(this.props.i18n)
|
||||
.then(() => getModules(clientStore.dispatch))
|
||||
.then(() => {
|
||||
const newLocaleLanguages = mapCulturesToArray(this.props.rawCultures, this.props.t);
|
||||
const newLocaleSelectedLanguage = findSelectedItemByKey(newLocaleLanguages, this.state.language.key) || newLocaleLanguages[0];
|
||||
|
||||
this.setState({
|
||||
languages: newLocaleLanguages,
|
||||
language: newLocaleSelectedLanguage
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onLanguageSelect = (language) => {
|
||||
@ -109,9 +125,12 @@ class Customization extends React.Component {
|
||||
this.setState({ isLoading: true }, function () {
|
||||
setLanguageAndTime(this.state.language.key, this.state.timezone.key)
|
||||
.then(() => {
|
||||
this.setState({ isLoading: false })
|
||||
toastr.success(t('SuccessfullySaveSettingsMessage'));
|
||||
});
|
||||
const { i18n } = this.props;
|
||||
changeLanguage(i18n)
|
||||
.then(() => toastr.success(i18n.t("SuccessfullySaveSettingsMessage")));
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.finally(() => this.setState({ isLoading: false }));
|
||||
})
|
||||
}
|
||||
|
||||
@ -123,10 +142,9 @@ class Customization extends React.Component {
|
||||
const { setGreetingTitle, t } = this.props;
|
||||
this.setState({ isLoadingGreetingSave: true }, function () {
|
||||
setGreetingTitle(this.state.greetingTitle)
|
||||
.then(() => {
|
||||
this.setState({ isLoadingGreetingSave: false })
|
||||
toastr.success(t('SuccessfullySaveGreetingSettingsMessage'));
|
||||
});
|
||||
.then(() => toastr.success(t('SuccessfullySaveGreetingSettingsMessage')))
|
||||
.catch((error) => toastr.error(error))
|
||||
.finally(() => this.setState({ isLoadingGreetingSave: false }));
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,17 @@
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from "react-router";
|
||||
import i18n from "../../i18n";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import { TabContainer } from "asc-web-components";
|
||||
import { utils } from 'asc-web-common';
|
||||
|
||||
import OwnerSettings from "./sub-components/owner";
|
||||
import AdminsSettings from "./sub-components/admins";
|
||||
// import ModulesSettings from "./sub-components/modules";
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
const MainContainer = styled.div`
|
||||
padding-bottom: 16px;
|
||||
width: 100%;
|
||||
@ -43,8 +45,6 @@ class PureAccessRights extends Component {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {}
|
||||
|
||||
onSelectPage = page => {
|
||||
const { history } = this.props;
|
||||
|
||||
@ -76,6 +76,7 @@ class PureAccessRights extends Component {
|
||||
|
||||
render() {
|
||||
const { isLoading, selectedTab } = this.state;
|
||||
const { t } = this.props;
|
||||
|
||||
console.log("accessRight render_");
|
||||
|
||||
@ -89,12 +90,12 @@ class PureAccessRights extends Component {
|
||||
{[
|
||||
{
|
||||
key: "0",
|
||||
title: "Owner settings",
|
||||
title: t('OwnerSettings'),
|
||||
content: <OwnerSettings />
|
||||
},
|
||||
{
|
||||
key: "1",
|
||||
title: "Admins settings",
|
||||
title: t('AdminsSettings'),
|
||||
content: <AdminsSettings />
|
||||
},
|
||||
// {
|
||||
@ -112,9 +113,8 @@ class PureAccessRights extends Component {
|
||||
const AccessRightsContainer = withTranslation()(PureAccessRights);
|
||||
|
||||
const AccessRights = props => {
|
||||
const { language } = props;
|
||||
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
@ -123,4 +123,4 @@ const AccessRights = props => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(null, {})(withRouter(AccessRights));
|
||||
export default withRouter(AccessRights);
|
||||
|
@ -366,7 +366,7 @@ class PureAdminsSettings extends Component {
|
||||
id="people-admin-selector_button"
|
||||
size="medium"
|
||||
primary={true}
|
||||
label="Set people admin"
|
||||
label={t('SetPeopleAdmin')}
|
||||
isDisabled={isLoading}
|
||||
onClick={this.onShowGroupSelector}
|
||||
/>
|
||||
@ -384,7 +384,7 @@ class PureAdminsSettings extends Component {
|
||||
id="full-admin-selector_button"
|
||||
size="medium"
|
||||
primary={true}
|
||||
label="Set portal admin"
|
||||
label={t('SetPortalAdmin')}
|
||||
isDisabled={isLoading}
|
||||
onClick={this.onShowFullAdminGroupSelector}
|
||||
/>
|
||||
@ -404,6 +404,8 @@ class PureAdminsSettings extends Component {
|
||||
getFilterData={() => []}
|
||||
getSortData={this.getSortData}
|
||||
onFilter={this.onFilter}
|
||||
directionAscLabel={t("DirectionAscLabel")}
|
||||
directionDescLabel={t("DirectionDescLabel")}
|
||||
/>
|
||||
|
||||
{admins.length > 0 ? (
|
||||
@ -445,8 +447,8 @@ class PureAdminsSettings extends Component {
|
||||
|
||||
<Text>
|
||||
{user.isAdmin
|
||||
? "Full access"
|
||||
: "People module admin"}
|
||||
? t('AccessRightsFullAccess')
|
||||
: t('PeopleAdmin')}
|
||||
</Text>
|
||||
|
||||
{!user.isOwner ? (
|
||||
|
@ -107,7 +107,7 @@ class PureModulesSettings extends Component {
|
||||
})}
|
||||
</Text>
|
||||
<Text fontSize='12px'>
|
||||
<li>{t("ViewProfilesAndGroups")}</li>
|
||||
<li>{t("ProductUserOpportunities")}</li>
|
||||
</Text>
|
||||
</ProjectsBody>
|
||||
</ProjectsContainer>
|
||||
|
@ -216,7 +216,7 @@ class PureOwnerSettings extends Component {
|
||||
className="button_offset"
|
||||
size="medium"
|
||||
primary={true}
|
||||
label="Change portal owner"
|
||||
label={t('AccessRightsChangeOwnerButtonText')}
|
||||
isDisabled={!isLoading ? selectedOwner === null : false}
|
||||
onClick={this.onChangeOwner}
|
||||
/>
|
||||
|
@ -1,5 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -7,16 +9,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: 'en',
|
||||
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: {
|
||||
@ -39,16 +37,12 @@ if (process.env.NODE_ENV === "production") {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -65,9 +65,11 @@
|
||||
"NotFoundTitle": "No results matching your search could be found",
|
||||
"NotFoundDescription": "No people matching your filter can be displayed in this section. Please select other filter options or clear filter to view all the people in this section.",
|
||||
"ClearButton": "Reset filter",
|
||||
"ProductUserOpportunities": "View profiles and groups",
|
||||
"LearnMore": "Learn more...",
|
||||
"AccessRightsChangeOwnerButtonText": "Change portal owner",
|
||||
|
||||
|
||||
"ViewProfilesAndGroups": "View profiles and groups",
|
||||
"ProjectsUserCapabilityView": "View projects and take part in discussions",
|
||||
"ProjectsUserCapabilityCreate": "Create and edit milestones, tasks, discussions, documents",
|
||||
"ProjectsUserCapabilityTrack": "Track time for tasks, generate reports",
|
||||
@ -82,9 +84,15 @@
|
||||
"Culture_en": "English (United Kingdom)",
|
||||
"Culture_en-US": "English (United States)",
|
||||
"Culture_ru-RU": "Russian (Russia)",
|
||||
"LearnMore": "Learn more...",
|
||||
"CountPerPage": "{{count}} per page",
|
||||
"PageOfTotalPage": "{{page}} of {{totalPage}}",
|
||||
"ByFirstNameSorting": "By first name",
|
||||
"ByLastNameSorting": "By last name"
|
||||
"ByLastNameSorting": "By last name",
|
||||
"OwnerSettings": "Owner settings",
|
||||
"AdminsSettings": "Admins settings",
|
||||
"SetPeopleAdmin": "Set people admin",
|
||||
"SetPortalAdmin": "Set portal admin",
|
||||
"PeopleAdmin": "People module admin",
|
||||
"DirectionAscLabel":"A-Z",
|
||||
"DirectionDescLabel":"Z-A"
|
||||
}
|
@ -64,9 +64,11 @@
|
||||
"NotFoundTitle": "Результатов, соответствующих заданным критериям, не найдено",
|
||||
"NotFoundDescription": "В данном разделе нет людей, соответствующих фильтру. Пожалуйста, выберите другие параметры или очистите фильтр, чтобы просмотреть всех людей в этом разделе.",
|
||||
"ClearButton": "Сбросить фильтр",
|
||||
"LearnMore": "Подробнее...",
|
||||
"AccessRightsChangeOwnerButtonText": "Сменить владельца портала",
|
||||
|
||||
|
||||
"ViewProfilesAndGroups": "Просматривать профили и группы",
|
||||
"ProductUserOpportunities": "Просматривать профили и группы",
|
||||
"AccessRightsAccessToProduct": "Доступ к модулю {{product}} предоставлен для",
|
||||
"ProjectsUserCapabilityView": "Просматривать проекты и участвовать в обсуждениях",
|
||||
"ProjectsUserCapabilityCreate": "Создавать и редактировать вехи, задачи, обсуждения, документы",
|
||||
@ -82,9 +84,15 @@
|
||||
"Culture_en": "Английский (Великобритания)",
|
||||
"Culture_en-US": "Английский (США)",
|
||||
"Culture_ru-RU": "Русский (Россия)",
|
||||
"LearnMore": "Подробнее...",
|
||||
"CountPerPage": "{{count}} на странице",
|
||||
"PageOfTotalPage": "{{page}} из {{totalPage}}",
|
||||
"ByFirstNameSorting": "По имени",
|
||||
"ByLastNameSorting": "По фамилии"
|
||||
"ByLastNameSorting": "По фамилии",
|
||||
"OwnerSettings": "Настройки владельца портата",
|
||||
"AdminsSettings": "Настройки администраторов",
|
||||
"SetPeopleAdmin": "Установить администратора модуля Люди",
|
||||
"SetPortalAdmin": "Установить администратора портала",
|
||||
"PeopleAdmin": "Администратор модуля Люди",
|
||||
"DirectionAscLabel":"А-Я",
|
||||
"DirectionDescLabel":"Я-А"
|
||||
}
|
@ -101,7 +101,9 @@
|
||||
"Employees",
|
||||
"AccessRightsChangeOwnerText",
|
||||
"DnsChangeMsg",
|
||||
"AccessRightsChangeOwnerConfirmText"
|
||||
"AccessRightsChangeOwnerConfirmText",
|
||||
"LearnMore",
|
||||
"AccessRightsChangeOwnerButtonText"
|
||||
],
|
||||
"FeedResource": [
|
||||
"ProjectsProduct",
|
||||
@ -110,7 +112,8 @@
|
||||
"DocumentsProduct"
|
||||
],
|
||||
"PeopleResource": [
|
||||
"Settings"
|
||||
"Settings",
|
||||
"ProductUserOpportunities"
|
||||
],
|
||||
"AuditResource": [
|
||||
"LoginHistoryNav",
|
||||
|
@ -9,5 +9,6 @@ module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
jest: true
|
||||
},
|
||||
};
|
||||
|
@ -74,4 +74,11 @@ export function getSettings() {
|
||||
method: "get",
|
||||
url: `/settings/whitelabel/logos.json`
|
||||
});
|
||||
}
|
||||
|
||||
export function getCurrentCustomSchema(id) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `settings/customschemas/${id}.json`
|
||||
});
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { connect } from "react-redux";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import AdvancedSelector from "../AdvancedSelector";
|
||||
import { getGroupList } from "../../api/groups";
|
||||
import { changeLanguage } from '../../utils';
|
||||
|
||||
class GroupSelector extends React.Component {
|
||||
constructor(props) {
|
||||
@ -15,8 +15,7 @@ class GroupSelector extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { language } = this.props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
getGroupList(this.props.useFake)
|
||||
.then(groups => this.setState({ groups: this.convertGroups(groups) }))
|
||||
@ -147,23 +146,9 @@ GroupSelector.defaultProps = {
|
||||
const ExtendedGroupSelector = withTranslation()(GroupSelector);
|
||||
|
||||
const GroupSelectorWithI18n = props => {
|
||||
const { language } = props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return <ExtendedGroupSelector i18n={i18n} {...props} />;
|
||||
};
|
||||
|
||||
GroupSelectorWithI18n.propTypes = {
|
||||
language: PropTypes.string
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language:
|
||||
state.auth &&
|
||||
((state.auth.user && state.auth.user.cultureName) ||
|
||||
(state.auth.settings && state.auth.settings.culture))
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(GroupSelectorWithI18n);
|
||||
export default GroupSelectorWithI18n;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import en from "./locales/en/translation.json";
|
||||
import ru from "./locales/ru/translation.json";
|
||||
import { LANGUAGE } from '../../constants';
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -15,16 +16,12 @@ const resources = {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Backdrop, Aside } from "asc-web-components";
|
||||
import { Backdrop, Aside, utils } from "asc-web-components";
|
||||
import HeaderComponent from "./sub-components/header";
|
||||
import Nav from "./sub-components/nav";
|
||||
import Main from "./sub-components/main";
|
||||
@ -35,8 +35,8 @@ class Layout extends React.Component {
|
||||
hash += props.currentModuleId;
|
||||
}
|
||||
if (props.currentUser) {
|
||||
const { id, displayName, email, avatarSmall } = props.currentUser;
|
||||
hash += id + displayName + email + avatarSmall;
|
||||
const { id, displayName, email, avatarSmall, cultureName } = props.currentUser;
|
||||
hash += id + displayName + email + avatarSmall + cultureName;
|
||||
}
|
||||
if (props.availableModules) {
|
||||
for (let i = 0, l = props.availableModules.length; i < l; i++) {
|
||||
@ -44,6 +44,9 @@ class Layout extends React.Component {
|
||||
hash += item.id + item.notifications;
|
||||
}
|
||||
}
|
||||
if (props.availableModules && this.state.availableModules) {
|
||||
hash += utils.array.isArrayEqual(this.state.availableModules, props.availableModules);
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
|
||||
|
@ -12,8 +12,7 @@ class ProfileActions extends React.PureComponent {
|
||||
|
||||
this.state = {
|
||||
opened: props.opened,
|
||||
user: props.user,
|
||||
userActions: props.userActions
|
||||
user: props.user
|
||||
};
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
@ -95,7 +94,7 @@ class ProfileActions extends React.PureComponent {
|
||||
displayName={this.state.user.displayName}
|
||||
email={this.state.user.email}
|
||||
/>
|
||||
{this.state.userActions.map(action => (
|
||||
{this.props.userActions.map(action => (
|
||||
<Link
|
||||
noHover={true}
|
||||
key={action.key}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import en from "./locales/en/translation.json";
|
||||
import ru from "./locales/ru/translation.json";
|
||||
import { LANGUAGE } from '../../constants';
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -15,7 +16,7 @@ const resources = {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
|
@ -3,7 +3,6 @@ import PropTypes from "prop-types";
|
||||
import { Backdrop } from "asc-web-components";
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import i18n from './i18n';
|
||||
import { connect } from "react-redux";
|
||||
import { ARTICLE_PINNED_KEY } from "../../constants";
|
||||
|
||||
import Article from "./sub-components/article";
|
||||
@ -17,6 +16,7 @@ import SectionFilter from "./sub-components/section-filter";
|
||||
import SectionBody from "./sub-components/section-body";
|
||||
import SectionPaging from "./sub-components/section-paging";
|
||||
import SectionToggler from "./sub-components/section-toggler";
|
||||
import { changeLanguage } from '../../utils';
|
||||
|
||||
class PageLayoutComponent extends React.PureComponent {
|
||||
constructor(props) {
|
||||
@ -191,8 +191,7 @@ class PageLayoutComponent extends React.PureComponent {
|
||||
|
||||
const PageLayoutTranslated = withTranslation()(PageLayoutComponent);
|
||||
const PageLayout = props => {
|
||||
const { language } = props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return <PageLayoutTranslated i18n={i18n} {...props} />
|
||||
}
|
||||
@ -241,13 +240,5 @@ PageLayoutComponent.defaultProps = {
|
||||
withBodyAutoFocus: false
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language:
|
||||
state.auth &&
|
||||
((state.auth.user && state.auth.user.cultureName) ||
|
||||
(state.auth.settings && state.auth.settings.culture))
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(PageLayout);
|
||||
export default PageLayout;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
@ -8,6 +7,7 @@ import { getUserList } from "../../api/people";
|
||||
import { getGroupList } from "../../api/groups";
|
||||
import Filter from "../../api/people/filter";
|
||||
import UserTooltip from "./sub-components/UserTooltip";
|
||||
import { changeLanguage } from '../../utils';
|
||||
|
||||
class PeopleSelector extends React.Component {
|
||||
constructor(props) {
|
||||
@ -23,8 +23,8 @@ class PeopleSelector extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { language } = this.props;
|
||||
i18n.changeLanguage(language);
|
||||
const { groupsCaption, t } = this.props;
|
||||
changeLanguage(i18n);
|
||||
|
||||
getGroupList(this.props.useFake)
|
||||
.then(groups =>
|
||||
@ -32,7 +32,7 @@ class PeopleSelector extends React.Component {
|
||||
groups: [
|
||||
{
|
||||
key: "all",
|
||||
label: "All groups",
|
||||
label: t('CustomAllGroups', { groupsCaption }),
|
||||
total: 0
|
||||
}
|
||||
].concat(this.convertGroups(groups))
|
||||
@ -160,7 +160,9 @@ class PeopleSelector extends React.Component {
|
||||
onSelect,
|
||||
size,
|
||||
onCancel,
|
||||
t
|
||||
t,
|
||||
searchPlaceHolderLabel,
|
||||
groupsCaption
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -180,10 +182,10 @@ class PeopleSelector extends React.Component {
|
||||
isOpen={isOpen}
|
||||
isMultiSelect={isMultiSelect}
|
||||
isDisabled={isDisabled}
|
||||
searchPlaceHolderLabel={t("SearchUsersPlaceholder")}
|
||||
searchPlaceHolderLabel={searchPlaceHolderLabel || t("SearchUsersPlaceholder")}
|
||||
selectButtonLabel={t("AddMembersButtonLabel")}
|
||||
selectAllLabel={t("SelectAllLabel")}
|
||||
groupsHeaderLabel={t("CustomDepartments", { departments: "Groups" })} //TODO: Replace to variable from settings
|
||||
groupsHeaderLabel={groupsCaption}
|
||||
emptySearchOptionsLabel={t("EmptySearchUsersResult")}
|
||||
emptyOptionsLabel={t("EmptyUsers")}
|
||||
loadingLabel={t("LoadingLabel")}
|
||||
@ -210,6 +212,8 @@ PeopleSelector.propTypes = {
|
||||
size: PropTypes.oneOf(["full", "compact"]),
|
||||
language: PropTypes.string,
|
||||
t: PropTypes.func,
|
||||
groupsCaption: PropTypes.string,
|
||||
searchPlaceHolderLabel: PropTypes.string,
|
||||
role: PropTypes.oneOf(["admin", "user", "guest"])
|
||||
};
|
||||
|
||||
@ -223,8 +227,7 @@ PeopleSelector.defaultProps = {
|
||||
const ExtendedPeopleSelector = withTranslation()(PeopleSelector);
|
||||
|
||||
const PeopleSelectorWithI18n = props => {
|
||||
const { language } = props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return <ExtendedPeopleSelector i18n={i18n} {...props} />;
|
||||
};
|
||||
@ -233,13 +236,4 @@ PeopleSelectorWithI18n.propTypes = {
|
||||
language: PropTypes.string
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
language:
|
||||
state.auth &&
|
||||
((state.auth.user && state.auth.user.cultureName) ||
|
||||
(state.auth.settings && state.auth.settings.culture))
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(PeopleSelectorWithI18n);
|
||||
export default PeopleSelectorWithI18n;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import en from "./locales/en/translation.json";
|
||||
import ru from "./locales/ru/translation.json";
|
||||
import { LANGUAGE } from '../../constants';
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -15,7 +16,7 @@ const resources = {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
@ -27,6 +28,7 @@ newInstance.init({
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
react: {
|
||||
useSuspense: false
|
||||
}
|
||||
|
@ -5,5 +5,5 @@
|
||||
"EmptySearchUsersResult": "There are no users with such name",
|
||||
"EmptyUsers": "There are no users",
|
||||
"LoadingLabel": "Loading... Please wait...",
|
||||
"CustomDepartments": "{{departments}}"
|
||||
"CustomAllGroups":"All {{ groupsCaption, lowercase }}"
|
||||
}
|
@ -5,5 +5,5 @@
|
||||
"EmptySearchUsersResult": "Нет такого пользователя",
|
||||
"EmptyUsers": "Нет пользователей",
|
||||
"LoadingLabel": "Загрузка... Пожалуйста подождите...",
|
||||
"CustomDepartments": "{{departments}}"
|
||||
"CustomAllGroups":"Все {{ groupsCaption, lowercase }}"
|
||||
}
|
@ -1,12 +1,17 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Toast } from "asc-web-components";
|
||||
import { Toast, utils } from "asc-web-components";
|
||||
import Layout from "../Layout";
|
||||
|
||||
class PureStudioLayout extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (this.props.availableModules && nextProps.availableModules &&
|
||||
!utils.array.isArrayEqual(nextProps.availableModules, this.props.availableModules)) {
|
||||
return true;
|
||||
}
|
||||
return this.props.hasChanges !== nextProps.hasChanges ||
|
||||
this.props.currentModuleId !== nextProps.currentModuleId;
|
||||
this.props.currentModuleId !== nextProps.currentModuleId ||
|
||||
this.props.language !== nextProps.language;
|
||||
}
|
||||
|
||||
onProfileClick = () => {
|
||||
@ -75,6 +80,7 @@ class PureStudioLayout extends React.Component {
|
||||
}
|
||||
|
||||
PureStudioLayout.propTypes = {
|
||||
availableModules: PropTypes.array,
|
||||
logout: PropTypes.func.isRequired,
|
||||
language: PropTypes.string,
|
||||
hasChanges: PropTypes.bool,
|
||||
|
@ -6,6 +6,7 @@ import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { logout } from "../../store/auth/actions";
|
||||
import PureStudioLayout from "./PureStudioLayout";
|
||||
import { changeLanguage } from '../../utils';
|
||||
|
||||
const getSeparator = id => {
|
||||
return {
|
||||
@ -65,8 +66,7 @@ const getAvailableModules = (modules, currentUser) => {
|
||||
const StudioLayoutContainer = withTranslation()(PureStudioLayout);
|
||||
|
||||
const StudioLayout = props => {
|
||||
const { language } = props;
|
||||
i18n.changeLanguage(language);
|
||||
changeLanguage(i18n);
|
||||
|
||||
return <StudioLayoutContainer i18n={i18n} {...props} />;
|
||||
};
|
||||
@ -82,8 +82,7 @@ function mapStateToProps(state) {
|
||||
availableModules: getAvailableModules(state.auth.modules, state.auth.user),
|
||||
currentUser: state.auth.user,
|
||||
currentModuleId: state.auth.settings.currentProductId,
|
||||
settings: state.auth.settings,
|
||||
language: state.auth.user.cultureName || state.auth.settings.culture
|
||||
settings: state.auth.settings
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import en from "./locales/en/translation.json";
|
||||
import ru from "./locales/ru/translation.json";
|
||||
import { LANGUAGE } from '../../constants';
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
@ -15,16 +16,12 @@ const resources = {
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
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: {
|
||||
|
@ -1,4 +1,5 @@
|
||||
export const AUTH_KEY = 'asc_auth_key';
|
||||
export const LANGUAGE = 'language';
|
||||
export const ARTICLE_PINNED_KEY = 'asc_article_pinned_key';
|
||||
|
||||
/**
|
||||
|
@ -8,12 +8,13 @@ export const SET_IS_LOADED = "SET_IS_LOADED";
|
||||
export const LOGOUT = "LOGOUT";
|
||||
export const SET_PASSWORD_SETTINGS = "SET_PASSWORD_SETTINGS";
|
||||
export const SET_NEW_EMAIL = "SET_NEW_EMAIL";
|
||||
export const GET_PORTAL_CULTURES = "GET_PORTAL_CULTURES";
|
||||
export const SET_PORTAL_CULTURES = "SET_PORTAL_CULTURES";
|
||||
export const SET_PORTAL_LANGUAGE_AND_TIME = "SET_PORTAL_LANGUAGE_AND_TIME";
|
||||
export const GET_TIMEZONES = "GET_TIMEZONES";
|
||||
export const SET_TIMEZONES = "SET_TIMEZONES";
|
||||
export const SET_CURRENT_PRODUCT_ID = "SET_CURRENT_PRODUCT_ID";
|
||||
export const SET_CURRENT_PRODUCT_HOME_PAGE = "SET_CURRENT_PRODUCT_HOME_PAGE";
|
||||
export const SET_GREETING_SETTINGS = "SET_GREETING_SETTINGS";
|
||||
export const SET_CUSTOM_NAMES = "SET_CUSTOM_NAMES";
|
||||
|
||||
export function setCurrentUser(user) {
|
||||
return {
|
||||
@ -66,7 +67,7 @@ export function setNewEmail(email) {
|
||||
|
||||
export function setPortalCultures(cultures) {
|
||||
return {
|
||||
type: GET_PORTAL_CULTURES,
|
||||
type: SET_PORTAL_CULTURES,
|
||||
cultures
|
||||
};
|
||||
}
|
||||
@ -80,7 +81,7 @@ export function setPortalLanguageAndTime(newSettings) {
|
||||
|
||||
export function setTimezones(timezones) {
|
||||
return {
|
||||
type: GET_TIMEZONES,
|
||||
type: SET_TIMEZONES,
|
||||
timezones
|
||||
};
|
||||
}
|
||||
@ -106,6 +107,13 @@ export function setGreetingSettings(title) {
|
||||
};
|
||||
}
|
||||
|
||||
export function setCustomNames(customNames) {
|
||||
return {
|
||||
type: SET_CUSTOM_NAMES,
|
||||
customNames
|
||||
};
|
||||
}
|
||||
|
||||
export function getUser(dispatch) {
|
||||
return api.people.getUser().then(user => dispatch(setCurrentUser(user)));
|
||||
}
|
||||
@ -113,7 +121,16 @@ export function getUser(dispatch) {
|
||||
export function getPortalSettings(dispatch) {
|
||||
return api.settings
|
||||
.getSettings()
|
||||
.then(settings => dispatch(setSettings(settings)));
|
||||
.then(settings => {
|
||||
dispatch(setSettings(settings));
|
||||
settings.nameSchemaId && getCurrentCustomSchema(dispatch, settings.nameSchemaId);
|
||||
});
|
||||
}
|
||||
export function getCurrentCustomSchema(dispatch, id) {
|
||||
|
||||
return api.settings
|
||||
.getCurrentCustomSchema(id)
|
||||
.then(customNames => dispatch(setCustomNames(customNames)));
|
||||
}
|
||||
|
||||
export function getModules(dispatch) {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import {
|
||||
SET_CURRENT_USER, SET_MODULES, SET_SETTINGS, SET_IS_LOADED, LOGOUT, SET_PASSWORD_SETTINGS, SET_NEW_EMAIL,
|
||||
GET_PORTAL_CULTURES, SET_PORTAL_LANGUAGE_AND_TIME, GET_TIMEZONES, SET_CURRENT_PRODUCT_ID, SET_CURRENT_PRODUCT_HOME_PAGE, SET_GREETING_SETTINGS,
|
||||
} from './actions';
|
||||
SET_PORTAL_CULTURES, SET_PORTAL_LANGUAGE_AND_TIME, SET_TIMEZONES, SET_CURRENT_PRODUCT_ID, SET_CURRENT_PRODUCT_HOME_PAGE, SET_GREETING_SETTINGS,
|
||||
SET_CUSTOM_NAMES } from './actions';
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import { LANGUAGE } from '../../constants';
|
||||
|
||||
const initialState = {
|
||||
isAuthenticated: false,
|
||||
@ -35,6 +36,9 @@ const initialState = {
|
||||
const authReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case SET_CURRENT_USER:
|
||||
action.user.cultureName
|
||||
&& localStorage.getItem(LANGUAGE) !== action.user.cultureName
|
||||
&& localStorage.setItem(LANGUAGE, action.user.cultureName);
|
||||
return Object.assign({}, state, {
|
||||
isAuthenticated: !isEmpty(action.user),
|
||||
user: action.user
|
||||
@ -44,10 +48,13 @@ const authReducer = (state = initialState, action) => {
|
||||
modules: action.modules
|
||||
});
|
||||
case SET_SETTINGS:
|
||||
if (!localStorage.getItem(LANGUAGE)) {
|
||||
localStorage.setItem(LANGUAGE, action.settings.culture);
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
settings: { ...state.settings, ...action.settings }
|
||||
});
|
||||
case GET_PORTAL_CULTURES:
|
||||
case SET_PORTAL_CULTURES:
|
||||
return Object.assign({}, state, {
|
||||
settings: { ...state.settings, cultures: action.cultures }
|
||||
});
|
||||
@ -64,10 +71,13 @@ const authReducer = (state = initialState, action) => {
|
||||
user: { ...state.user, email: action.email }
|
||||
});
|
||||
case SET_PORTAL_LANGUAGE_AND_TIME:
|
||||
if (!state.user.cultureName) {
|
||||
localStorage.setItem(LANGUAGE, action.newSettings.lng);
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
settings: { ...state.settings, culture: action.newSettings.lng, timezone: action.newSettings.timeZoneID }
|
||||
});
|
||||
case GET_TIMEZONES:
|
||||
case SET_TIMEZONES:
|
||||
return Object.assign({}, state, {
|
||||
settings: { ...state.settings, timezones: action.timezones }
|
||||
});
|
||||
@ -83,6 +93,10 @@ const authReducer = (state = initialState, action) => {
|
||||
return Object.assign({}, state, {
|
||||
settings: { ...state.settings, greetingSettings: action.title }
|
||||
});
|
||||
case SET_CUSTOM_NAMES:
|
||||
return Object.assign({}, state, {
|
||||
settings: { ...state.settings, customNames: action.customNames }
|
||||
});
|
||||
case LOGOUT:
|
||||
return Object.assign({}, initialState, {
|
||||
settings: state.settings
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { LANGUAGE } from '../constants';
|
||||
|
||||
export const toUrlParams = (obj, skipNull) => {
|
||||
let str = "";
|
||||
for (var key in obj) {
|
||||
@ -28,3 +30,11 @@ export function getObjectByLocation(location) {
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
export function changeLanguage(i18nInstance) {
|
||||
return localStorage.getItem(LANGUAGE)
|
||||
? (i18nInstance.language !== localStorage.getItem(LANGUAGE)
|
||||
? i18nInstance.changeLanguage(localStorage.getItem(LANGUAGE))
|
||||
: Promise.resolve())
|
||||
: i18nInstance.changeLanguage('en');
|
||||
}
|
||||
|
@ -411,8 +411,8 @@ class FilterInput extends React.Component {
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.throttledResize);
|
||||
}
|
||||
componentDidUpdate(){
|
||||
if(this.props.needForUpdate){
|
||||
componentDidUpdate(prevProps){
|
||||
if(this.props.needForUpdate && this.props.needForUpdate(prevProps, this.props)){
|
||||
let internalFilterData = convertToInternalData(this.props.getFilterData(), cloneObjectsArray(this.props.selectedFilterData.filterValues));
|
||||
this.updateFilter(internalFilterData);
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.3502 0C12.5262 0 12.6786 0.053566 12.8074 0.160787C12.9357 0.267978 13 0.394823 13 0.541618V7.04151C13 7.36733 12.949 7.69119 12.8467 8.01316C12.7323 8.00444 12.6167 8 12.5 8C11.7907 8 11.1196 8.16413 10.5229 8.45648C10.8743 7.97985 11.05 7.5082 11.05 7.04151V1.62486H8.125L6.5 3.25L6.49995 11.2478C7.30564 10.8924 8.02677 10.5058 8.66324 10.0883C8.6847 10.0743 8.70601 10.0603 8.72717 10.0463C8.28239 10.7288 8.0178 11.5395 8.00087 12.4109C7.62856 12.5895 7.35999 12.7127 7.19557 12.7799C7.01625 12.8533 6.87236 12.9097 6.76415 12.9491C6.68276 12.983 6.59493 13 6.49991 13C6.405 13 6.31707 12.983 6.23575 12.9491C6.12746 12.9097 5.98357 12.8533 5.80418 12.7799C5.62482 12.7066 5.32174 12.5667 4.89518 12.3609C4.46863 12.1552 4.05897 11.9364 3.66632 11.7051C3.27367 11.4736 2.84544 11.1833 2.38157 10.8333C1.91777 10.4836 1.51836 10.1238 1.18315 9.75417C0.847951 9.38461 0.566925 8.96138 0.340183 8.4846C0.113335 8.00778 0 7.52681 0 7.04151V0.541618C0 0.394912 0.0643513 0.267949 0.192947 0.160787C0.321614 0.053566 0.473973 0 0.65013 0H5.28125L6.50014 1.21875L7.71875 0H12.3502Z" fill="#333333"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 16C14.433 16 16 14.433 16 12.5C16 10.567 14.433 9 12.5 9C10.567 9 9 10.567 9 12.5C9 14.433 10.567 16 12.5 16ZM13 10V12.0001H15V13.0001H13V15L12 15V13.0001H9.99999V12.0001H12V10H13Z" fill="#333333"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.125 0C7.9701 0 9.46591 1.44649 9.46591 3.23076C9.46591 5.01517 7.9701 6.46153 6.125 6.46153C4.2799 6.46153 2.78409 5.01503 2.78409 3.23076C2.78409 1.44649 4.2799 0 6.125 0ZM8.25606 14H1.57202C0.703828 14 0 13.3432 0 12.543C0 8.97743 1.68911 7.52238 3.53122 7.48433L6.12501 11.375L8.7426 7.44861C9.53875 7.50503 10.264 7.77829 10.8457 8.3138C9.179 8.97299 8 10.5988 8 12.5C8 13.026 8.09023 13.5308 8.25606 14Z" fill="#333333"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 16C14.433 16 16 14.433 16 12.5C16 10.567 14.433 9 12.5 9C10.567 9 9 10.567 9 12.5C9 14.433 10.567 16 12.5 16ZM13 10V12H15V13H13V15H12V13H9.99999V12H12V10H13Z" fill="#333333"/>
|
||||
</svg>
|
After Width: | Height: | Size: 813 B |
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.54817 3.23076C9.54817 1.44649 8.03936 0 6.17823 0C4.31709 0 2.80828 1.44649 2.80828 3.23076C2.80828 5.01503 4.31709 6.46153 6.17823 6.46153C8.03936 6.46153 9.54817 5.01517 9.54817 3.23076ZM10.9117 8.28831C9.2102 8.93029 7.99998 10.5738 7.99998 12.5C7.99998 13.026 8.09022 13.5308 8.25604 14H1.58569C0.709944 14 0 13.3432 0 12.543C0 8.87114 1.80689 7.4375 3.72846 7.48469C4.3947 7.90803 5.20365 8.15679 6.07659 8.15679C6.98151 8.15679 7.81769 7.88951 8.49723 7.4375C9.41301 7.4375 10.2518 7.70008 10.9117 8.28831Z" fill="#333333"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 16C14.433 16 16 14.433 16 12.5C16 10.567 14.433 9 12.5 9C10.567 9 9 10.567 9 12.5C9 14.433 10.567 16 12.5 16ZM13 10V12H15V13H13V15H12V13H9.99999V12H12V10H13Z" fill="#333333"/>
|
||||
</svg>
|
After Width: | Height: | Size: 917 B |
@ -145,6 +145,10 @@ import OrigShareFacebookIcon from './share.facebook.react.svg';
|
||||
import OrigShareTwitterIcon from './share.twitter.react.svg';
|
||||
import OrigShareLinkedInIcon from './share.linkedin.react.svg';
|
||||
|
||||
import OrigAddDepartmentIcon from './add.department.react.svg';
|
||||
import OrigAddEmployeeIcon from './add.employee.react.svg';
|
||||
import OrigAddGuestIcon from './add.guest.react.svg';
|
||||
|
||||
export const AZSortingIcon = createStyledIcon(
|
||||
OrigAZSortingIcon,
|
||||
'AZSortingIcon'
|
||||
@ -189,6 +193,18 @@ export const ActionsUploadIcon = createStyledIcon(
|
||||
OrigActionsUploadIcon,
|
||||
'ActionsUploadIcon'
|
||||
);
|
||||
export const AddDepartmentIcon = createStyledIcon(
|
||||
OrigAddDepartmentIcon,
|
||||
'AddDepartmentIcon'
|
||||
);
|
||||
export const AddEmployeeIcon = createStyledIcon(
|
||||
OrigAddEmployeeIcon,
|
||||
'AddEmployeeIcon'
|
||||
);
|
||||
export const AddGuestIcon = createStyledIcon(
|
||||
OrigAddGuestIcon,
|
||||
'AddGuestIcon'
|
||||
);
|
||||
export const AdministratorIcon = createStyledIcon(
|
||||
OrigAdministratorIcon,
|
||||
'AdministratorIcon'
|
||||
|
Loading…
Reference in New Issue
Block a user