Merge branch 'feature/selectors-refactoring' of github.com:ONLYOFFICE/AppServer into feature/selectors-refactoring
This commit is contained in:
commit
0e4698b8f0
@ -1,7 +1,10 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { utils, TreeMenu, TreeNode, Icons, Link } from "asc-web-components";
|
||||
import { selectGroup } from "../../../store/people/actions";
|
||||
import {
|
||||
selectGroup,
|
||||
setIsVisibleDataLossDialog,
|
||||
} from "../../../store/people/actions";
|
||||
import { getSelectedGroup } from "../../../store/people/selectors";
|
||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||
import {
|
||||
@ -100,16 +103,25 @@ class ArticleBodyContent extends React.Component {
|
||||
|
||||
return false;
|
||||
}
|
||||
onSelectHandler = (data) => {
|
||||
const { editingForm, setIsVisibleDataLossDialog } = this.props;
|
||||
|
||||
onSelect = (data) => {
|
||||
const { selectGroup } = this.props;
|
||||
|
||||
this.changeTitleDocument(data);
|
||||
selectGroup(
|
||||
data && data.length === 1 && data[0] !== "root" ? data[0] : null
|
||||
);
|
||||
if (editingForm.isEdit) {
|
||||
setIsVisibleDataLossDialog(true, this.onSelect(data));
|
||||
} else {
|
||||
this.onSelect(data)();
|
||||
}
|
||||
};
|
||||
onSelect = (data) => {
|
||||
return () => {
|
||||
const { selectGroup } = this.props;
|
||||
|
||||
this.changeTitleDocument(data);
|
||||
selectGroup(
|
||||
data && data.length === 1 && data[0] !== "root" ? data[0] : null
|
||||
);
|
||||
};
|
||||
};
|
||||
switcherIcon = (obj) => {
|
||||
if (obj.isLeaf) {
|
||||
return null;
|
||||
@ -141,7 +153,7 @@ class ArticleBodyContent extends React.Component {
|
||||
showIcon={true}
|
||||
defaultExpandAll={true}
|
||||
switcherIcon={this.switcherIcon}
|
||||
onSelect={this.onSelect}
|
||||
onSelect={this.onSelectHandler}
|
||||
selectedKeys={selectedKeys}
|
||||
isFullFillSelection={false}
|
||||
gapBetweenNodes="22"
|
||||
@ -220,6 +232,7 @@ function mapStateToProps(state) {
|
||||
const { isLoaded, settings } = state.auth;
|
||||
const { customNames } = settings;
|
||||
const { groupsCaption } = customNames;
|
||||
const { editingForm } = state.people;
|
||||
|
||||
return {
|
||||
data: getTreeGroups(groups, groupsCaption),
|
||||
@ -229,7 +242,11 @@ function mapStateToProps(state) {
|
||||
groups,
|
||||
isAdmin: isAdmin(state),
|
||||
isLoaded,
|
||||
editingForm
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, { selectGroup })(BodyContent);
|
||||
export default connect(mapStateToProps, {
|
||||
selectGroup,
|
||||
setIsVisibleDataLossDialog,
|
||||
})(BodyContent);
|
||||
|
@ -0,0 +1,106 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { ModalDialog, Button, Text } from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { utils } from "asc-web-common";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
import {
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
} from "../../../store/people/actions";
|
||||
|
||||
const i18n = createI18N({
|
||||
page: "DataLossWarningDialog",
|
||||
localesPath: "dialogs/DataLossWarningDialog",
|
||||
});
|
||||
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
class DataLossWarningDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
changeLanguage(i18n);
|
||||
}
|
||||
|
||||
onClose = () => {
|
||||
const { setIsVisibleDataLossDialog } = this.props;
|
||||
setIsVisibleDataLossDialog(false);
|
||||
};
|
||||
|
||||
onSubmit = () => {
|
||||
const {
|
||||
onContinue,
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
editingForm,
|
||||
} = this.props;
|
||||
|
||||
setIsVisibleDataLossDialog(false, null);
|
||||
setIsEditingForm(false);
|
||||
|
||||
if (editingForm.callback) {
|
||||
editingForm.callback();
|
||||
} else {
|
||||
onContinue && onContinue();
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const { t, editingForm } = this.props;
|
||||
|
||||
return (
|
||||
<ModalDialogContainer>
|
||||
<ModalDialog
|
||||
visible={editingForm.isVisibleDataLossDialog}
|
||||
onClose={this.onClose}
|
||||
>
|
||||
<ModalDialog.Header>{t("DataLossWarningHeader")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text fontSize="13px">{t("DataLossWarningBody")}</Text>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
key="LeaveForm"
|
||||
label={t("DataLossWarningLeaveBtn")}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onSubmit}
|
||||
/>
|
||||
<Button
|
||||
className="button-dialog"
|
||||
key="StayOnPage"
|
||||
label={t("DataLossWarningCancelBtn")}
|
||||
size="medium"
|
||||
onClick={this.onClose}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const DataLossWarningDialogTranslated = withTranslation()(
|
||||
DataLossWarningDialogComponent
|
||||
);
|
||||
|
||||
const DataLossWarningDialog = (props) => (
|
||||
<DataLossWarningDialogTranslated i18n={i18n} {...props} />
|
||||
);
|
||||
|
||||
DataLossWarningDialog.propTypes = {
|
||||
editingForm: PropTypes.object.isRequired,
|
||||
onContinue: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
editingForm: state.people.editingForm,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
})(DataLossWarningDialog);
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"DataLossWarningHeader": "Leave the page?",
|
||||
"DataLossWarningBody": "Changes you made may not be saved.",
|
||||
"DataLossWarningLeaveBtn": "Leave",
|
||||
"DataLossWarningCancelBtn": "Cancel"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"DataLossWarningHeader": "Покинуть страницу?",
|
||||
"DataLossWarningBody": "Внесенные вами изменения могут быть не сохранены.",
|
||||
"DataLossWarningLeaveBtn": "Покинуть",
|
||||
"DataLossWarningCancelBtn": "Отмена"
|
||||
}
|
@ -8,6 +8,7 @@ import InviteDialog from "./InviteDialog";
|
||||
import SendInviteDialog from "./SendInviteDialog";
|
||||
import ChangeUserStatusDialog from "./ChangeUserStatusDialog";
|
||||
import ChangeUserTypeDialog from "./ChangeUserTypeDialog";
|
||||
import DataLossWarningDialog from "./DataLossWarningDialog";
|
||||
|
||||
export {
|
||||
ChangeEmailDialog,
|
||||
@ -19,5 +20,6 @@ export {
|
||||
InviteDialog,
|
||||
SendInviteDialog,
|
||||
ChangeUserStatusDialog,
|
||||
ChangeUserTypeDialog
|
||||
ChangeUserTypeDialog,
|
||||
DataLossWarningDialog,
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
resetGroup,
|
||||
updateGroup,
|
||||
} from "../../../../../store/group/actions";
|
||||
import { selectGroup } from "../../../../../store/people/actions";
|
||||
import { selectGroup, setFilter } from "../../../../../store/people/actions";
|
||||
|
||||
import { GUID_EMPTY } from "../../../../../helpers/constants";
|
||||
import PropTypes from "prop-types";
|
||||
@ -241,10 +241,10 @@ class SectionBodyContent extends React.Component {
|
||||
};
|
||||
|
||||
onCancel = () => {
|
||||
const { history, resetGroup, settings } = this.props;
|
||||
const { resetGroup, filter, setFilter } = this.props;
|
||||
|
||||
resetGroup();
|
||||
history.push(`${settings.homepage}/`);
|
||||
setFilter(filter);
|
||||
};
|
||||
|
||||
onSelectedItemClose = (member) => {
|
||||
@ -490,6 +490,7 @@ function mapStateToProps(state) {
|
||||
groupCaption,
|
||||
me: getCurrentUser(state),
|
||||
currentModuleName,
|
||||
filter: state.people.filter,
|
||||
};
|
||||
}
|
||||
|
||||
@ -498,4 +499,5 @@ export default connect(mapStateToProps, {
|
||||
createGroup,
|
||||
updateGroup,
|
||||
selectGroup,
|
||||
setFilter,
|
||||
})(withRouter(withTranslation()(SectionBodyContent)));
|
||||
|
@ -6,6 +6,7 @@ import { IconButton } from "asc-web-components";
|
||||
import { Headline } from "asc-web-common";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { resetGroup } from "../../../../../store/group/actions";
|
||||
import { setFilter } from "../../../../../store/people/actions";
|
||||
import styled from "styled-components";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
@ -23,7 +24,6 @@ const Wrapper = styled.div`
|
||||
`;
|
||||
|
||||
class SectionHeaderContent extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { group, t, groupCaption } = props;
|
||||
@ -32,14 +32,14 @@ class SectionHeaderContent extends React.Component {
|
||||
: t("CustomNewDepartment", { groupCaption });
|
||||
|
||||
this.state = {
|
||||
headerText
|
||||
}
|
||||
headerText,
|
||||
};
|
||||
}
|
||||
onClickBack = () => {
|
||||
const { history, settings, resetGroup } = this.props;
|
||||
const { filter, resetGroup, setFilter } = this.props;
|
||||
|
||||
resetGroup();
|
||||
history.push(settings.homepage);
|
||||
setFilter(filter);
|
||||
};
|
||||
|
||||
render() {
|
||||
@ -65,22 +65,22 @@ class SectionHeaderContent extends React.Component {
|
||||
|
||||
SectionHeaderContent.propTypes = {
|
||||
group: PropTypes.object,
|
||||
history: PropTypes.object.isRequired
|
||||
history: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
SectionHeaderContent.defaultProps = {
|
||||
group: null
|
||||
group: null,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
settings: state.auth.settings,
|
||||
group: state.group.targetGroup,
|
||||
groupCaption: state.auth.settings.customNames.groupCaption
|
||||
groupCaption: state.auth.settings.customNames.groupCaption,
|
||||
filter: state.people.filter,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ resetGroup }
|
||||
)(withTranslation()(withRouter(SectionHeaderContent)));
|
||||
export default connect(mapStateToProps, { resetGroup, setFilter })(
|
||||
withTranslation()(withRouter(SectionHeaderContent))
|
||||
);
|
||||
|
@ -12,7 +12,10 @@ import {
|
||||
toEmployeeWrapper,
|
||||
} from "../../../../../store/people/selectors";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import { updateUserStatus } from "../../../../../store/people/actions";
|
||||
import {
|
||||
updateUserStatus,
|
||||
setFilter,
|
||||
} from "../../../../../store/people/actions";
|
||||
import { updateProfile } from "../../../../../store/profile/actions";
|
||||
import {
|
||||
fetchProfile,
|
||||
@ -405,9 +408,9 @@ class SectionHeaderContent extends React.PureComponent {
|
||||
};
|
||||
|
||||
onClickBack = () => {
|
||||
const { history, settings } = this.props;
|
||||
|
||||
history.push(settings.homepage);
|
||||
const { filter, setFilter } = this.props;
|
||||
setFilter(filter);
|
||||
//history.push(settings.homepage);
|
||||
};
|
||||
|
||||
render() {
|
||||
@ -519,4 +522,5 @@ export default connect(mapStateToProps, {
|
||||
updateUserStatus,
|
||||
fetchProfile,
|
||||
updateProfile,
|
||||
setFilter,
|
||||
})(withRouter(withTranslation()(SectionHeaderContent)));
|
||||
|
@ -24,7 +24,7 @@ const { isAdmin, isVisitor, getLanguage } = store.auth.selectors;
|
||||
|
||||
class PureProfile extends React.Component {
|
||||
componentDidMount() {
|
||||
const { match, fetchProfile, t, location } = this.props;
|
||||
const { match, fetchProfile, profile, location, t } = this.props;
|
||||
const { userId } = match.params;
|
||||
|
||||
setDocumentTitle(t("Profile"));
|
||||
@ -39,8 +39,9 @@ class PureProfile extends React.Component {
|
||||
if (linkParams.email_change && linkParams.email_change === "success") {
|
||||
toastr.success(t("ChangeEmailSuccess"));
|
||||
}
|
||||
|
||||
fetchProfile(userId);
|
||||
if (!profile) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
Button,
|
||||
Textarea,
|
||||
AvatarEditor,
|
||||
Text
|
||||
Text,
|
||||
} from "asc-web-components";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import {
|
||||
@ -16,13 +16,22 @@ import {
|
||||
getUserContacts,
|
||||
mapGroupsToGroupSelectorOptions,
|
||||
mapGroupSelectorOptionsToGroups,
|
||||
filterGroupSelectorOptions
|
||||
filterGroupSelectorOptions,
|
||||
} from "../../../../../store/people/selectors";
|
||||
import { createProfile } from "../../../../../store/profile/actions";
|
||||
import {
|
||||
createProfile,
|
||||
updateCreatedAvatar,
|
||||
} from "../../../../../store/profile/actions";
|
||||
import {
|
||||
setFilter,
|
||||
updateProfileInUsers,
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
} from "../../../../../store/people/actions";
|
||||
import {
|
||||
MainContainer,
|
||||
AvatarContainer,
|
||||
MainFieldsContainer
|
||||
MainFieldsContainer,
|
||||
} from "./FormFields/Form";
|
||||
import TextField from "./FormFields/TextField";
|
||||
import PasswordField from "./FormFields/PasswordField";
|
||||
@ -32,6 +41,7 @@ import RadioField from "./FormFields/RadioField";
|
||||
import DepartmentField from "./FormFields/DepartmentField";
|
||||
import ContactsField from "./FormFields/ContactsField";
|
||||
import InfoFieldContainer from "./FormFields/InfoFieldContainer";
|
||||
import { DataLossWarningDialog } from "../../../../dialogs";
|
||||
import { api, toastr } from "asc-web-common";
|
||||
const { createThumbnailsAvatar, loadAvatar } = api.people;
|
||||
|
||||
@ -47,6 +57,7 @@ class CreateUserForm extends React.Component {
|
||||
this.onBirthdayDateChange = this.onBirthdayDateChange.bind(this);
|
||||
this.onWorkFromDateChange = this.onWorkFromDateChange.bind(this);
|
||||
this.onCancel = this.onCancel.bind(this);
|
||||
this.onCancelHandler = this.onCancelHandler.bind(this);
|
||||
|
||||
this.onContactsItemAdd = this.onContactsItemAdd.bind(this);
|
||||
this.onContactsItemTypeChange = this.onContactsItemTypeChange.bind(this);
|
||||
@ -74,15 +85,17 @@ class CreateUserForm extends React.Component {
|
||||
y: this.state.avatar.y,
|
||||
width: this.state.avatar.width,
|
||||
height: this.state.avatar.height,
|
||||
tmpFile: this.state.avatar.tmpFile
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
})
|
||||
.then(() => {
|
||||
.then((res) => {
|
||||
this.props.updateCreatedAvatar(res);
|
||||
this.props.updateProfileInUsers();
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.props.history.push(
|
||||
`${this.props.settings.homepage}/view/${userName}`
|
||||
);
|
||||
})
|
||||
.catch(error => toastr.error(error));
|
||||
.catch((error) => toastr.error(error));
|
||||
}
|
||||
|
||||
openAvatarEditor() {
|
||||
@ -100,37 +113,38 @@ class CreateUserForm extends React.Component {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
image: this.state.avatar.image,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2]
|
||||
}
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
},
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
visibleAvatarEditor: true
|
||||
visibleAvatarEditor: true,
|
||||
});
|
||||
}
|
||||
|
||||
onLoadFileAvatar(file) {
|
||||
onLoadFileAvatar(file, callback) {
|
||||
let data = new FormData();
|
||||
let _this = this;
|
||||
data.append("file", file);
|
||||
data.append("Autosave", false);
|
||||
|
||||
loadAvatar(0, data)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
img.onload = function () {
|
||||
var stateCopy = Object.assign({}, _this.state);
|
||||
stateCopy.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
_this.setState(stateCopy);
|
||||
if (typeof callback === "function") callback();
|
||||
};
|
||||
img.src = response.data;
|
||||
})
|
||||
.catch(error => toastr.error(error));
|
||||
.catch((error) => toastr.error(error));
|
||||
}
|
||||
|
||||
onSaveAvatar(isUpdate, result, file) {
|
||||
@ -149,6 +163,7 @@ class CreateUserForm extends React.Component {
|
||||
stateCopy.avatar.height = result.height;
|
||||
}
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onCloseAvatarEditor() {
|
||||
@ -156,8 +171,8 @@ class CreateUserForm extends React.Component {
|
||||
visibleAvatarEditor: false,
|
||||
croppedAvatarImage: "",
|
||||
avatar: {
|
||||
tmpFile: ""
|
||||
}
|
||||
tmpFile: "",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -167,10 +182,10 @@ class CreateUserForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
mapPropsToState = props => {
|
||||
mapPropsToState = (props) => {
|
||||
var profile = toEmployeeWrapper({
|
||||
isVisitor: props.match.params.type === "guest",
|
||||
passwordType: "link"
|
||||
passwordType: "link",
|
||||
});
|
||||
var allOptions = mapGroupsToGroupSelectorOptions(props.groups);
|
||||
var selected = mapGroupsToGroupSelectorOptions(profile.groups);
|
||||
@ -182,14 +197,14 @@ class CreateUserForm extends React.Component {
|
||||
firstName: false,
|
||||
lastName: false,
|
||||
email: false,
|
||||
password: false
|
||||
password: false,
|
||||
},
|
||||
profile: profile,
|
||||
selector: {
|
||||
visible: false,
|
||||
allOptions: allOptions,
|
||||
options: [...allOptions],
|
||||
selected: selected
|
||||
selected: selected,
|
||||
},
|
||||
avatar: {
|
||||
tmpFile: "",
|
||||
@ -199,27 +214,34 @@ class CreateUserForm extends React.Component {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
height: 0,
|
||||
},
|
||||
};
|
||||
};
|
||||
setIsEdit() {
|
||||
const { editingForm, setIsEditingForm } = this.props;
|
||||
if (!editingForm.isEdit) setIsEditingForm(true);
|
||||
}
|
||||
|
||||
onInputChange(event) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile[event.target.name] = event.target.value;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onBirthdayDateChange(value) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.birthday = value ? value.toJSON() : null;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onWorkFromDateChange(value) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.workFrom = value ? value.toJSON() : null;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
validate() {
|
||||
@ -228,7 +250,7 @@ class CreateUserForm extends React.Component {
|
||||
firstName: !profile.firstName.trim(),
|
||||
lastName: !profile.lastName.trim(),
|
||||
email: stateErrors.email || !profile.email.trim(),
|
||||
password: profile.passwordType === "temp" && !profile.password.trim()
|
||||
password: profile.passwordType === "temp" && !profile.password.trim(),
|
||||
};
|
||||
const hasError =
|
||||
errors.firstName || errors.lastName || errors.email || errors.password;
|
||||
@ -250,7 +272,7 @@ class CreateUserForm extends React.Component {
|
||||
|
||||
this.props
|
||||
.createProfile(this.state.profile)
|
||||
.then(profile => {
|
||||
.then((profile) => {
|
||||
if (this.state.avatar.tmpFile !== "") {
|
||||
this.createAvatar(profile.id, profile.userName);
|
||||
} else {
|
||||
@ -260,14 +282,25 @@ class CreateUserForm extends React.Component {
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
}
|
||||
|
||||
onCancelHandler() {
|
||||
const { editingForm, setIsVisibleDataLossDialog } = this.props;
|
||||
|
||||
if (editingForm.isEdit) {
|
||||
setIsVisibleDataLossDialog(true);
|
||||
} else {
|
||||
this.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
this.props.history.push(this.props.settings.homepage);
|
||||
const { filter, setFilter } = this.props;
|
||||
setFilter(filter);
|
||||
}
|
||||
|
||||
onContactsItemAdd(item) {
|
||||
@ -275,37 +308,41 @@ class CreateUserForm extends React.Component {
|
||||
stateCopy.profile.contacts.push({
|
||||
id: new Date().getTime().toString(),
|
||||
type: item.value,
|
||||
value: ""
|
||||
value: "",
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onContactsItemTypeChange(item) {
|
||||
const id = item.key.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.forEach(element => {
|
||||
stateCopy.profile.contacts.forEach((element) => {
|
||||
if (element.id === id) element.type = item.value;
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onContactsItemTextChange(event) {
|
||||
const id = event.target.name.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.forEach(element => {
|
||||
stateCopy.profile.contacts.forEach((element) => {
|
||||
if (element.id === id) element.value = event.target.value;
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onContactsItemRemove(event) {
|
||||
const id = event.target.closest(".remove_icon").dataset.for.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
const filteredArray = stateCopy.profile.contacts.filter(element => {
|
||||
const filteredArray = stateCopy.profile.contacts.filter((element) => {
|
||||
return element.id !== id;
|
||||
});
|
||||
stateCopy.profile.contacts = filteredArray;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onShowGroupSelector() {
|
||||
@ -335,20 +372,21 @@ class CreateUserForm extends React.Component {
|
||||
stateCopy.selector.selected = selected;
|
||||
stateCopy.selector.visible = false;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onRemoveGroup(id) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.groups = stateCopy.profile.groups.filter(
|
||||
group => group.id !== id
|
||||
(group) => group.id !== id
|
||||
);
|
||||
stateCopy.selector.selected = stateCopy.selector.selected.filter(
|
||||
option => option.key !== id
|
||||
(option) => option.key !== id
|
||||
);
|
||||
this.setState(stateCopy);
|
||||
}
|
||||
|
||||
onValidateEmailField = value =>
|
||||
onValidateEmailField = (value) =>
|
||||
this.setState({ errors: { ...this.state.errors, email: !value.isValid } });
|
||||
|
||||
render() {
|
||||
@ -357,7 +395,7 @@ class CreateUserForm extends React.Component {
|
||||
const {
|
||||
regDateCaption,
|
||||
userPostCaption,
|
||||
groupCaption
|
||||
groupCaption,
|
||||
} = settings.customNames;
|
||||
|
||||
const pattern = getUserContactsPattern();
|
||||
@ -366,6 +404,7 @@ class CreateUserForm extends React.Component {
|
||||
return (
|
||||
<>
|
||||
<MainContainer>
|
||||
<DataLossWarningDialog onContinue={this.onCancel} />
|
||||
<AvatarContainer>
|
||||
<Avatar
|
||||
size="max"
|
||||
@ -447,7 +486,7 @@ class CreateUserForm extends React.Component {
|
||||
radioValue={profile.passwordType}
|
||||
radioOptions={[
|
||||
{ value: "link", label: t("ActivationLink") },
|
||||
{ value: "temp", label: t("TemporaryPassword") }
|
||||
{ value: "temp", label: t("TemporaryPassword") },
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
@ -478,7 +517,7 @@ class CreateUserForm extends React.Component {
|
||||
radioValue={profile.sex}
|
||||
radioOptions={[
|
||||
{ value: "male", label: t("MaleSexStatus") },
|
||||
{ value: "female", label: t("FemaleSexStatus") }
|
||||
{ value: "female", label: t("FemaleSexStatus") },
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
@ -571,7 +610,7 @@ class CreateUserForm extends React.Component {
|
||||
/>
|
||||
<Button
|
||||
label={t("CancelButton")}
|
||||
onClick={this.onCancel}
|
||||
onClick={this.onCancelHandler}
|
||||
isDisabled={isLoading}
|
||||
size="big"
|
||||
style={{ marginLeft: "8px" }}
|
||||
@ -583,16 +622,22 @@ class CreateUserForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
const { settings } = state.auth;
|
||||
const { groups, filter, editingForm } = state.people;
|
||||
return {
|
||||
settings: state.auth.settings,
|
||||
groups: state.people.groups
|
||||
settings,
|
||||
groups,
|
||||
filter,
|
||||
editingForm,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
createProfile
|
||||
}
|
||||
)(withRouter(withTranslation()(CreateUserForm)));
|
||||
export default connect(mapStateToProps, {
|
||||
createProfile,
|
||||
updateCreatedAvatar,
|
||||
setFilter,
|
||||
updateProfileInUsers,
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
})(withRouter(withTranslation()(CreateUserForm)));
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
Textarea,
|
||||
Text,
|
||||
AvatarEditor,
|
||||
Link
|
||||
Link,
|
||||
} from "asc-web-components";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import {
|
||||
@ -17,17 +17,23 @@ import {
|
||||
getUserContacts,
|
||||
mapGroupsToGroupSelectorOptions,
|
||||
mapGroupSelectorOptionsToGroups,
|
||||
filterGroupSelectorOptions
|
||||
filterGroupSelectorOptions,
|
||||
} from "../../../../../store/people/selectors";
|
||||
import {
|
||||
updateProfile,
|
||||
getUserPhoto,
|
||||
fetchProfile
|
||||
fetchProfile,
|
||||
} from "../../../../../store/profile/actions";
|
||||
import {
|
||||
setFilter,
|
||||
updateProfileInUsers,
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
} from "../../../../../store/people/actions";
|
||||
import {
|
||||
MainContainer,
|
||||
AvatarContainer,
|
||||
MainFieldsContainer
|
||||
MainFieldsContainer,
|
||||
} from "./FormFields/Form";
|
||||
import TextField from "./FormFields/TextField";
|
||||
import TextChangeField from "./FormFields/TextChangeField";
|
||||
@ -37,18 +43,19 @@ import DepartmentField from "./FormFields/DepartmentField";
|
||||
import ContactsField from "./FormFields/ContactsField";
|
||||
import InfoFieldContainer from "./FormFields/InfoFieldContainer";
|
||||
import styled from "styled-components";
|
||||
import { DataLossWarningDialog } from "../../../../dialogs";
|
||||
import { api, toastr } from "asc-web-common";
|
||||
import {
|
||||
ChangeEmailDialog,
|
||||
ChangePasswordDialog,
|
||||
ChangePhoneDialog
|
||||
ChangePhoneDialog,
|
||||
} from "../../../../dialogs";
|
||||
const { createThumbnailsAvatar, loadAvatar, deleteAvatar } = api.people;
|
||||
|
||||
const dialogsDataset = {
|
||||
changeEmail: "changeEmail",
|
||||
changePassword: "changePassword",
|
||||
changePhone: "changePhone"
|
||||
changePhone: "changePhone",
|
||||
};
|
||||
|
||||
const Table = styled.table`
|
||||
@ -76,6 +83,7 @@ class UpdateUserForm extends React.Component {
|
||||
this.onBirthdayDateChange = this.onBirthdayDateChange.bind(this);
|
||||
this.onWorkFromDateChange = this.onWorkFromDateChange.bind(this);
|
||||
this.onCancel = this.onCancel.bind(this);
|
||||
this.onCancelHandler = this.onCancelHandler.bind(this);
|
||||
|
||||
this.onContactsItemAdd = this.onContactsItemAdd.bind(this);
|
||||
this.onContactsItemTypeChange = this.onContactsItemTypeChange.bind(this);
|
||||
@ -102,12 +110,12 @@ class UpdateUserForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
mapPropsToState = props => {
|
||||
mapPropsToState = (props) => {
|
||||
var profile = toEmployeeWrapper(props.profile);
|
||||
var allOptions = mapGroupsToGroupSelectorOptions(props.groups);
|
||||
var selected = mapGroupsToGroupSelectorOptions(profile.groups);
|
||||
|
||||
getUserPhoto(profile.id).then(userPhotoData => {
|
||||
getUserPhoto(profile.id).then((userPhotoData) => {
|
||||
if (userPhotoData.original) {
|
||||
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
|
||||
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
|
||||
@ -120,8 +128,8 @@ class UpdateUserForm extends React.Component {
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? null
|
||||
: userPhotoData.original
|
||||
: null
|
||||
}
|
||||
: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -131,7 +139,7 @@ class UpdateUserForm extends React.Component {
|
||||
isLoading: false,
|
||||
errors: {
|
||||
firstName: false,
|
||||
lastName: false
|
||||
lastName: false,
|
||||
},
|
||||
profile: profile,
|
||||
visibleAvatarEditor: false,
|
||||
@ -139,20 +147,20 @@ class UpdateUserForm extends React.Component {
|
||||
visible: false,
|
||||
allOptions: allOptions,
|
||||
options: [...allOptions],
|
||||
selected: selected
|
||||
selected: selected,
|
||||
},
|
||||
avatar: {
|
||||
tmpFile: "",
|
||||
image: null,
|
||||
defaultWidth: 0,
|
||||
defaultHeight: 0
|
||||
defaultHeight: 0,
|
||||
},
|
||||
dialogsVisible: {
|
||||
[dialogsDataset.changePassword]: false,
|
||||
[dialogsDataset.changePhone]: false,
|
||||
[dialogsDataset.changeEmail]: false,
|
||||
currentDialog: ""
|
||||
}
|
||||
currentDialog: "",
|
||||
},
|
||||
};
|
||||
|
||||
//Set unique contacts id
|
||||
@ -165,13 +173,19 @@ class UpdateUserForm extends React.Component {
|
||||
return newState;
|
||||
};
|
||||
|
||||
setIsEdit() {
|
||||
const { editingForm, setIsEditingForm } = this.props;
|
||||
if (!editingForm.isEdit) setIsEditingForm(true);
|
||||
}
|
||||
|
||||
onInputChange(event) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile[event.target.name] = event.target.value;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
toggleDialogsVisible = e => {
|
||||
toggleDialogsVisible = (e) => {
|
||||
const stateCopy = Object.assign({}, {}, this.state.dialogsVisible);
|
||||
const selectedDialog = e ? e.target.dataset.dialog : e;
|
||||
if (selectedDialog) {
|
||||
@ -188,25 +202,28 @@ class UpdateUserForm extends React.Component {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.isVisitor = event.target.value === "true";
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onBirthdayDateChange(value) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.birthday = value ? value.toJSON() : null;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onWorkFromDateChange(value) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.workFrom = value ? value.toJSON() : null;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
validate() {
|
||||
const { profile } = this.state;
|
||||
const errors = {
|
||||
firstName: !profile.firstName.trim(),
|
||||
lastName: !profile.lastName.trim()
|
||||
lastName: !profile.lastName.trim(),
|
||||
};
|
||||
const hasError = errors.firstName || errors.lastName;
|
||||
|
||||
@ -227,20 +244,36 @@ class UpdateUserForm extends React.Component {
|
||||
|
||||
this.props
|
||||
.updateProfile(this.state.profile)
|
||||
.then(profile => {
|
||||
.then((profile) => {
|
||||
this.props.updateProfileInUsers(profile);
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.props.history.push(
|
||||
`${this.props.settings.homepage}/view/${profile.userName}`
|
||||
);
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
}
|
||||
onCancelHandler() {
|
||||
const { editingForm, setIsVisibleDataLossDialog } = this.props;
|
||||
|
||||
if (editingForm.isEdit) {
|
||||
setIsVisibleDataLossDialog(true);
|
||||
} else {
|
||||
this.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
this.props.history.goBack();
|
||||
const { filter, setFilter } = this.props;
|
||||
|
||||
if (document.referrer) {
|
||||
this.props.history.goBack();
|
||||
} else {
|
||||
setFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
onContactsItemAdd(item) {
|
||||
@ -248,37 +281,41 @@ class UpdateUserForm extends React.Component {
|
||||
stateCopy.profile.contacts.push({
|
||||
id: new Date().getTime().toString(),
|
||||
type: item.value,
|
||||
value: ""
|
||||
value: "",
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onContactsItemTypeChange(item) {
|
||||
const id = item.key.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.forEach(element => {
|
||||
stateCopy.profile.contacts.forEach((element) => {
|
||||
if (element.id === id) element.type = item.value;
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onContactsItemTextChange(event) {
|
||||
const id = event.target.name.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.forEach(element => {
|
||||
stateCopy.profile.contacts.forEach((element) => {
|
||||
if (element.id === id) element.value = event.target.value;
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onContactsItemRemove(event) {
|
||||
const id = event.target.closest(".remove_icon").dataset.for.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
const filteredArray = stateCopy.profile.contacts.filter(element => {
|
||||
const filteredArray = stateCopy.profile.contacts.filter((element) => {
|
||||
return element.id !== id;
|
||||
});
|
||||
stateCopy.profile.contacts = filteredArray;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
openAvatarEditor() {
|
||||
@ -296,12 +333,12 @@ class UpdateUserForm extends React.Component {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
image: this.state.avatar.image,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2]
|
||||
}
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
},
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
visibleAvatarEditor: true
|
||||
visibleAvatarEditor: true,
|
||||
});
|
||||
}
|
||||
|
||||
@ -312,15 +349,15 @@ class UpdateUserForm extends React.Component {
|
||||
data.append("file", file);
|
||||
data.append("Autosave", false);
|
||||
loadAvatar(this.state.profile.id, data)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
img.onload = function () {
|
||||
var stateCopy = Object.assign({}, _this.state);
|
||||
stateCopy.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
_this.setState(stateCopy);
|
||||
_this.setState({ isLoading: false });
|
||||
@ -328,7 +365,7 @@ class UpdateUserForm extends React.Component {
|
||||
};
|
||||
img.src = response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
@ -346,9 +383,9 @@ class UpdateUserForm extends React.Component {
|
||||
),
|
||||
width: result.width,
|
||||
height: result.height,
|
||||
tmpFile: this.state.avatar.tmpFile
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
})
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
let stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.visibleAvatarEditor = false;
|
||||
stateCopy.avatar.tmpFile = "";
|
||||
@ -356,32 +393,37 @@ class UpdateUserForm extends React.Component {
|
||||
response.max +
|
||||
"?_=" +
|
||||
Math.floor(Math.random() * Math.floor(10000));
|
||||
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.setState({ isLoading: false });
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
})
|
||||
.then(() => this.props.updateProfile(this.props.profile))
|
||||
.then(() => this.props.fetchProfile(this.state.profile.id));
|
||||
.then(() => {
|
||||
this.props.updateProfile(this.props.profile);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
} else {
|
||||
deleteAvatar(this.state.profile.id)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
let stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.visibleAvatarEditor = false;
|
||||
stateCopy.profile.avatarMax = response.big;
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
})
|
||||
.catch(error => toastr.error(error));
|
||||
.catch((error) => toastr.error(error));
|
||||
}
|
||||
}
|
||||
|
||||
onCloseAvatarEditor() {
|
||||
this.setState({
|
||||
visibleAvatarEditor: false
|
||||
visibleAvatarEditor: false,
|
||||
});
|
||||
}
|
||||
|
||||
@ -412,17 +454,19 @@ class UpdateUserForm extends React.Component {
|
||||
stateCopy.selector.selected = selected;
|
||||
stateCopy.selector.visible = false;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
onRemoveGroup(id) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.groups = stateCopy.profile.groups.filter(
|
||||
group => group.id !== id
|
||||
(group) => group.id !== id
|
||||
);
|
||||
stateCopy.selector.selected = stateCopy.selector.selected.filter(
|
||||
option => option.key !== id
|
||||
(option) => option.key !== id
|
||||
);
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -433,7 +477,7 @@ class UpdateUserForm extends React.Component {
|
||||
userCaption,
|
||||
regDateCaption,
|
||||
userPostCaption,
|
||||
groupCaption
|
||||
groupCaption,
|
||||
} = settings.customNames;
|
||||
|
||||
const pattern = getUserContactsPattern();
|
||||
@ -517,6 +561,7 @@ class UpdateUserForm extends React.Component {
|
||||
return (
|
||||
<>
|
||||
<MainContainer>
|
||||
<DataLossWarningDialog onContinue={this.onCancel} />
|
||||
<AvatarContainer>
|
||||
<Avatar
|
||||
size="max"
|
||||
@ -562,7 +607,8 @@ class UpdateUserForm extends React.Component {
|
||||
case of loss of the password and send notifications.
|
||||
<p
|
||||
style={{
|
||||
margin: "1rem 0" /*, height: "0", visibility: "hidden"*/
|
||||
margin:
|
||||
"1rem 0" /*, height: "0", visibility: "hidden"*/,
|
||||
}}
|
||||
>
|
||||
You can create a new mail on the domain as the primary. In
|
||||
@ -636,7 +682,7 @@ class UpdateUserForm extends React.Component {
|
||||
radioValue={profile.sex}
|
||||
radioOptions={[
|
||||
{ value: "male", label: t("MaleSexStatus") },
|
||||
{ value: "female", label: t("FemaleSexStatus") }
|
||||
{ value: "female", label: t("FemaleSexStatus") },
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
@ -647,7 +693,7 @@ class UpdateUserForm extends React.Component {
|
||||
radioValue={profile.isVisitor.toString()}
|
||||
radioOptions={[
|
||||
{ value: "true", label: guestCaption },
|
||||
{ value: "false", label: userCaption }
|
||||
{ value: "false", label: userCaption },
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onUserTypeChange}
|
||||
@ -742,7 +788,7 @@ class UpdateUserForm extends React.Component {
|
||||
/>
|
||||
<Button
|
||||
label={t("CancelButton")}
|
||||
onClick={this.onCancel}
|
||||
onClick={this.onCancelHandler}
|
||||
isDisabled={isLoading}
|
||||
size="big"
|
||||
style={{ marginLeft: "8px" }}
|
||||
@ -778,18 +824,21 @@ class UpdateUserForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
profile: state.profile.targetUser,
|
||||
settings: state.auth.settings,
|
||||
groups: state.people.groups
|
||||
groups: state.people.groups,
|
||||
editingForm: state.people.editingForm,
|
||||
filter: state.people.filter,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
updateProfile,
|
||||
fetchProfile
|
||||
}
|
||||
)(withRouter(withTranslation()(UpdateUserForm)));
|
||||
export default connect(mapStateToProps, {
|
||||
updateProfile,
|
||||
fetchProfile,
|
||||
updateProfileInUsers,
|
||||
setIsVisibleDataLossDialog,
|
||||
setIsEditingForm,
|
||||
setFilter,
|
||||
})(withRouter(withTranslation()(UpdateUserForm)));
|
||||
|
@ -1,10 +1,14 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { connect } from 'react-redux';
|
||||
import React, { useCallback } from "react";
|
||||
import styled from "styled-components";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from "react-router";
|
||||
import { IconButton } from 'asc-web-components';
|
||||
import { Headline } from 'asc-web-common';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IconButton } from "asc-web-components";
|
||||
import { Headline } from "asc-web-common";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
setFilter,
|
||||
setIsVisibleDataLossDialog,
|
||||
} from "../../../../../store/people/actions";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
@ -18,45 +22,56 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.header-headline {
|
||||
margin-left: 16px;
|
||||
}
|
||||
margin-left: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const SectionHeaderContent = (props) => {
|
||||
const { profile, history, match, settings } = props;
|
||||
const {
|
||||
profile,
|
||||
history,
|
||||
match,
|
||||
settings,
|
||||
filter,
|
||||
editingForm,
|
||||
setFilter,
|
||||
setIsVisibleDataLossDialog,
|
||||
} = props;
|
||||
const { userCaption, guestCaption } = settings.customNames;
|
||||
const { type } = match.params;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const headerText = type
|
||||
? type === "guest"
|
||||
? t('CustomCreation', { user: guestCaption })
|
||||
: t('CustomCreation', { user: userCaption })
|
||||
? t("CustomCreation", { user: guestCaption })
|
||||
: t("CustomCreation", { user: userCaption })
|
||||
: profile
|
||||
? `${t('EditUserDialogTitle')} (${profile.displayName})`
|
||||
: "";
|
||||
? `${t("EditUserDialogTitle")} (${profile.displayName})`
|
||||
: "";
|
||||
|
||||
const onClickBackHandler = () => {
|
||||
if (editingForm.isEdit) {
|
||||
setIsVisibleDataLossDialog(true, onClickBack);
|
||||
} else {
|
||||
onClickBack();
|
||||
}
|
||||
};
|
||||
const onClickBack = useCallback(() => {
|
||||
//history.goBack();
|
||||
!profile ? history.push(settings.homepage) : history.push(`/products/people/view/${profile.userName}`);
|
||||
}, [history, profile, settings.homepage]);
|
||||
!profile || !document.referrer ? setFilter(filter) : history.goBack();
|
||||
}, [history, profile, setFilter, filter]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<IconButton
|
||||
iconName='ArrowPathIcon'
|
||||
iconName="ArrowPathIcon"
|
||||
color="#A3A9AE"
|
||||
size="17"
|
||||
hoverColor="#657077"
|
||||
isFill={true}
|
||||
onClick={onClickBack}
|
||||
onClick={onClickBackHandler}
|
||||
className="arrow-button"
|
||||
/>
|
||||
<Headline
|
||||
className='header-headline'
|
||||
type='content'
|
||||
truncate={true}
|
||||
>
|
||||
<Headline className="header-headline" type="content" truncate={true}>
|
||||
{headerText}
|
||||
</Headline>
|
||||
</Wrapper>
|
||||
@ -66,8 +81,13 @@ const SectionHeaderContent = (props) => {
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
profile: state.profile.targetUser,
|
||||
settings: state.auth.settings
|
||||
settings: state.auth.settings,
|
||||
filter: state.people.filter,
|
||||
editingForm: state.people.editingForm,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(SectionHeaderContent));
|
||||
export default connect(mapStateToProps, {
|
||||
setFilter,
|
||||
setIsVisibleDataLossDialog,
|
||||
})(withRouter(SectionHeaderContent));
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
UpdateUserForm,
|
||||
} from "./Section";
|
||||
import { fetchProfile } from "../../../store/profile/actions";
|
||||
import { setIsEditingForm } from "../../../store/people/actions";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
import { createI18N } from "../../../helpers/i18n";
|
||||
import { setDocumentTitle } from "../../../helpers/utils";
|
||||
@ -27,12 +28,14 @@ const { isAdmin } = store.auth.selectors;
|
||||
|
||||
class ProfileAction extends React.Component {
|
||||
componentDidMount() {
|
||||
const { match, fetchProfile, t } = this.props;
|
||||
const { match, fetchProfile, isEdit, setIsEditingForm, t } = this.props;
|
||||
const { userId } = match.params;
|
||||
|
||||
setDocumentTitle(t("ProfileAction"));
|
||||
changeLanguage(i18n);
|
||||
|
||||
if (isEdit) {
|
||||
setIsEditingForm(false);
|
||||
}
|
||||
if (userId) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
@ -129,9 +132,10 @@ function mapStateToProps(state) {
|
||||
isVisitor: state.auth.user.isVisitor,
|
||||
profile: state.profile.targetUser,
|
||||
isAdmin: isAdmin(state),
|
||||
isEdit: state.people.editingForm.isEdit,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, { fetchProfile })(
|
||||
export default connect(mapStateToProps, { fetchProfile, setIsEditingForm })(
|
||||
ProfileActionContainer
|
||||
);
|
||||
|
@ -9,8 +9,10 @@ import {
|
||||
SORT_BY,
|
||||
SORT_ORDER,
|
||||
PAGE,
|
||||
PAGE_COUNT
|
||||
PAGE_COUNT,
|
||||
} from "../../helpers/constants";
|
||||
import { getUserByUserName } from "../people/selectors";
|
||||
|
||||
const { EmployeeStatus } = constants;
|
||||
const { Filter } = api;
|
||||
|
||||
@ -24,39 +26,42 @@ export const SET_SELECTED = "SET_SELECTED";
|
||||
export const SET_FILTER = "SET_FILTER";
|
||||
export const SELECT_GROUP = "SELECT_GROUP";
|
||||
export const SET_SELECTOR_USERS = "SET_SELECTOR_USERS";
|
||||
export const SET_IS_VISIBLE_DATA_LOSS_DIALOG =
|
||||
"SET_IS_VISIBLE_DATA_LOSS_DIALOG";
|
||||
export const SET_IS_EDITING_FORM = "SET_IS_EDITING_FORM";
|
||||
|
||||
export function setUser(user) {
|
||||
return {
|
||||
type: SET_USER,
|
||||
user
|
||||
user,
|
||||
};
|
||||
}
|
||||
|
||||
export function setUsers(users) {
|
||||
return {
|
||||
type: SET_USERS,
|
||||
users
|
||||
users,
|
||||
};
|
||||
}
|
||||
|
||||
export function setGroups(groups) {
|
||||
return {
|
||||
type: SET_GROUPS,
|
||||
groups
|
||||
groups,
|
||||
};
|
||||
}
|
||||
|
||||
export function setSelection(selection) {
|
||||
return {
|
||||
type: SET_SELECTION,
|
||||
selection
|
||||
selection,
|
||||
};
|
||||
}
|
||||
|
||||
export function setSelected(selected) {
|
||||
return {
|
||||
type: SET_SELECTED,
|
||||
selected
|
||||
selected,
|
||||
};
|
||||
}
|
||||
|
||||
@ -75,14 +80,14 @@ export function selectGroup(groupId) {
|
||||
export function selectUser(user) {
|
||||
return {
|
||||
type: SELECT_USER,
|
||||
user
|
||||
user,
|
||||
};
|
||||
}
|
||||
|
||||
export function deselectUser(user) {
|
||||
return {
|
||||
type: DESELECT_USER,
|
||||
user
|
||||
user,
|
||||
};
|
||||
}
|
||||
|
||||
@ -120,7 +125,7 @@ export function setFilterUrl(filter) {
|
||||
|
||||
//const isProfileView = history.location.pathname.includes('/people/view') || history.location.pathname.includes('/people/edit');
|
||||
//if (params.length > 0 && !isProfileView) {
|
||||
history.push(`${config.homepage}/filter?${params.join("&")}`);
|
||||
history.push(`${config.homepage}/filter?${params.join("&")}`);
|
||||
//}
|
||||
}
|
||||
|
||||
@ -128,20 +133,35 @@ export function setFilter(filter) {
|
||||
setFilterUrl(filter);
|
||||
return {
|
||||
type: SET_FILTER,
|
||||
filter
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
export function setSelectorUsers(users) {
|
||||
return {
|
||||
type: SET_SELECTOR_USERS,
|
||||
users
|
||||
users,
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsVisibleDataLossDialog(isVisible, callback) {
|
||||
return {
|
||||
type: SET_IS_VISIBLE_DATA_LOSS_DIALOG,
|
||||
isVisible,
|
||||
callback,
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsEditingForm(isEdit) {
|
||||
return {
|
||||
type: SET_IS_EDITING_FORM,
|
||||
isEdit,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchSelectorUsers() {
|
||||
return dispatch => {
|
||||
api.people.getSelectorUserList().then(data => {
|
||||
return (dispatch) => {
|
||||
api.people.getSelectorUserList().then((data) => {
|
||||
const users = data.items;
|
||||
return dispatch(setSelectorUsers(users));
|
||||
});
|
||||
@ -149,10 +169,10 @@ export function fetchSelectorUsers() {
|
||||
}
|
||||
|
||||
export function fetchGroups(dispatchFunc = null) {
|
||||
return api.groups.getGroupList().then(groups => {
|
||||
return api.groups.getGroupList().then((groups) => {
|
||||
return dispatchFunc
|
||||
? dispatchFunc(setGroups(groups))
|
||||
: Promise.resolve(dispatch => dispatch(setGroups(groups)));
|
||||
: Promise.resolve((dispatch) => dispatch(setGroups(groups)));
|
||||
});
|
||||
}
|
||||
|
||||
@ -160,21 +180,33 @@ export function fetchPeople(filter, dispatchFunc = null) {
|
||||
return dispatchFunc
|
||||
? fetchPeopleByFilter(dispatchFunc, filter)
|
||||
: (dispatch, getState) => {
|
||||
if (filter) {
|
||||
return fetchPeopleByFilter(dispatch, filter);
|
||||
} else {
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
return fetchPeopleByFilter(dispatch, filter);
|
||||
}
|
||||
};
|
||||
if (filter) {
|
||||
return fetchPeopleByFilter(dispatch, filter);
|
||||
} else {
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
return fetchPeopleByFilter(dispatch, filter);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function removeUser(userId, filter) {
|
||||
return dispatch => {
|
||||
return api.people.deleteUsers(userId)
|
||||
.then(() => fetchPeople(filter, dispatch))
|
||||
return (dispatch) => {
|
||||
return api.people
|
||||
.deleteUsers(userId)
|
||||
.then(() => fetchPeople(filter, dispatch));
|
||||
};
|
||||
}
|
||||
|
||||
export function updateUserList(dispatch, filter) {
|
||||
let filterData = filter && filter.clone();
|
||||
if (!filterData) {
|
||||
filterData = Filter.getDefault();
|
||||
filterData.employeeStatus = EmployeeStatus.Active;
|
||||
}
|
||||
return api.people.getUserList(filterData).then((data) => {
|
||||
return dispatch(setUsers(data.items));
|
||||
});
|
||||
}
|
||||
|
||||
function fetchPeopleByFilter(dispatch, filter) {
|
||||
@ -185,12 +217,12 @@ function fetchPeopleByFilter(dispatch, filter) {
|
||||
filterData.employeeStatus = EmployeeStatus.Active;
|
||||
}
|
||||
|
||||
return api.people.getUserList(filterData).then(data => {
|
||||
return api.people.getUserList(filterData).then((data) => {
|
||||
filterData.total = data.total;
|
||||
dispatch(setFilter(filterData));
|
||||
dispatch({
|
||||
type: SELECT_GROUP,
|
||||
groupId: filterData.group
|
||||
groupId: filterData.group,
|
||||
});
|
||||
return dispatch(setUsers(data.items));
|
||||
});
|
||||
@ -198,21 +230,20 @@ function fetchPeopleByFilter(dispatch, filter) {
|
||||
|
||||
export function updateUserStatus(status, userIds, isRefetchPeople = false) {
|
||||
return (dispatch, getState) => {
|
||||
return api.people.updateUserStatus(status, userIds)
|
||||
.then(users => {
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
return isRefetchPeople
|
||||
? fetchPeople(filter, dispatch)
|
||||
: Promise.resolve();
|
||||
});
|
||||
return api.people.updateUserStatus(status, userIds).then((users) => {
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
return isRefetchPeople
|
||||
? fetchPeople(filter, dispatch)
|
||||
: Promise.resolve();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function updateUserType(type, userIds) {
|
||||
return dispatch => {
|
||||
return api.people.updateUserType(type, userIds).then(users => {
|
||||
users.forEach(user => {
|
||||
return (dispatch) => {
|
||||
return api.people.updateUserType(type, userIds).then((users) => {
|
||||
users.forEach((user) => {
|
||||
dispatch(setUser(user));
|
||||
});
|
||||
});
|
||||
@ -229,3 +260,43 @@ export function resetFilter() {
|
||||
return fetchPeople(newFilter, dispatch);
|
||||
};
|
||||
}
|
||||
|
||||
export function updateProfileInUsers(updatedProfile) {
|
||||
return (dispatch, getState) => {
|
||||
const { people } = getState();
|
||||
const { users } = people;
|
||||
|
||||
if (!users) {
|
||||
return updateUserList(dispatch);
|
||||
}
|
||||
|
||||
if (!updatedProfile) {
|
||||
const { profile } = getState();
|
||||
updatedProfile = profile.targetUser;
|
||||
}
|
||||
|
||||
const { userName } = updatedProfile;
|
||||
const oldProfile = getUserByUserName(users, userName);
|
||||
const newProfile = {};
|
||||
|
||||
for (let key in oldProfile) {
|
||||
if (
|
||||
updatedProfile.hasOwnProperty(key) &&
|
||||
updatedProfile[key] !== oldProfile[key]
|
||||
) {
|
||||
newProfile[key] = updatedProfile[key];
|
||||
} else {
|
||||
newProfile[key] = oldProfile[key];
|
||||
}
|
||||
}
|
||||
|
||||
const updatedUsers = users.map((user) => {
|
||||
if (user.id === newProfile.id) {
|
||||
return newProfile;
|
||||
} else {
|
||||
return user;
|
||||
}
|
||||
});
|
||||
return dispatch(setUsers(updatedUsers));
|
||||
};
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ import {
|
||||
SET_FILTER,
|
||||
SELECT_GROUP,
|
||||
SET_USER,
|
||||
SET_SELECTOR_USERS
|
||||
SET_SELECTOR_USERS,
|
||||
SET_IS_VISIBLE_DATA_LOSS_DIALOG,
|
||||
SET_IS_EDITING_FORM,
|
||||
} from "./actions";
|
||||
import { isUserSelected, skipUser, getUsersBySelected } from "./selectors";
|
||||
import { api } from "asc-web-common";
|
||||
@ -22,60 +24,79 @@ const initialState = {
|
||||
selectedGroup: null,
|
||||
filter: Filter.getDefault(),
|
||||
selector: {
|
||||
users: []
|
||||
}
|
||||
users: [],
|
||||
},
|
||||
editingForm: {
|
||||
isEdit: false,
|
||||
isVisibleDataLossDialog: false,
|
||||
},
|
||||
};
|
||||
|
||||
const peopleReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case SET_GROUPS:
|
||||
return Object.assign({}, state, {
|
||||
groups: action.groups
|
||||
groups: action.groups,
|
||||
});
|
||||
case SET_USERS:
|
||||
return Object.assign({}, state, {
|
||||
users: action.users
|
||||
users: action.users,
|
||||
});
|
||||
case SET_USER:
|
||||
return Object.assign({}, state, {
|
||||
users: state.users.map(user =>
|
||||
users: state.users.map((user) =>
|
||||
user.id === action.user.id ? action.user : user
|
||||
)
|
||||
),
|
||||
});
|
||||
case SET_SELECTION:
|
||||
return Object.assign({}, state, {
|
||||
selection: action.selection
|
||||
selection: action.selection,
|
||||
});
|
||||
case SELECT_USER:
|
||||
if (!isUserSelected(state.selection, action.user.id)) {
|
||||
return Object.assign({}, state, {
|
||||
selection: [...state.selection, action.user]
|
||||
selection: [...state.selection, action.user],
|
||||
});
|
||||
} else return state;
|
||||
case DESELECT_USER:
|
||||
if (isUserSelected(state.selection, action.user.id)) {
|
||||
return Object.assign({}, state, {
|
||||
selection: skipUser(state.selection, action.user.id)
|
||||
selection: skipUser(state.selection, action.user.id),
|
||||
});
|
||||
} else return state;
|
||||
case SET_SELECTED:
|
||||
return Object.assign({}, state, {
|
||||
selected: action.selected,
|
||||
selection: getUsersBySelected(state.users, action.selected)
|
||||
selection: getUsersBySelected(state.users, action.selected),
|
||||
});
|
||||
case SET_FILTER:
|
||||
return Object.assign({}, state, {
|
||||
filter: action.filter
|
||||
filter: action.filter,
|
||||
});
|
||||
case SELECT_GROUP:
|
||||
return Object.assign({}, state, {
|
||||
selectedGroup: action.groupId
|
||||
selectedGroup: action.groupId,
|
||||
});
|
||||
case SET_SELECTOR_USERS:
|
||||
return Object.assign({}, state, {
|
||||
selector: Object.assign({}, state.selector, {
|
||||
users: action.users
|
||||
})
|
||||
users: action.users,
|
||||
}),
|
||||
});
|
||||
case SET_IS_VISIBLE_DATA_LOSS_DIALOG:
|
||||
return Object.assign({}, state, {
|
||||
editingForm: {
|
||||
...state.editingForm,
|
||||
isVisibleDataLossDialog: action.isVisible,
|
||||
callback: action.callback,
|
||||
},
|
||||
});
|
||||
case SET_IS_EDITING_FORM:
|
||||
return Object.assign({}, state, {
|
||||
editingForm: {
|
||||
...state.editingForm,
|
||||
isEdit: action.isEdit,
|
||||
},
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { getUserByUserName } from "../people/selectors";
|
||||
import { fetchPeople } from "../people/actions";
|
||||
import { updateUserList } from "../people/actions";
|
||||
import { store, api } from "asc-web-common";
|
||||
const { setCurrentUser } = store.auth.actions;
|
||||
const { isMe } = store.auth.selectors;
|
||||
@ -43,7 +42,6 @@ export function fetchProfile(userName) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createProfile(profile) {
|
||||
return (dispatch, getState) => {
|
||||
const { people } = getState();
|
||||
@ -58,7 +56,7 @@ export function createProfile(profile) {
|
||||
return dispatch(setProfile(user));
|
||||
})
|
||||
.then(() => {
|
||||
return fetchPeople(filter, dispatch);
|
||||
return updateUserList(dispatch, filter);
|
||||
})
|
||||
.then(() => {
|
||||
return Promise.resolve(result);
|
||||
@ -67,9 +65,7 @@ export function createProfile(profile) {
|
||||
}
|
||||
|
||||
export function updateProfile(profile) {
|
||||
return (dispatch, getState) => {
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
return (dispatch) => {
|
||||
const member = employeeWrapperToMemberModel(profile);
|
||||
let result;
|
||||
|
||||
@ -79,15 +75,11 @@ export function updateProfile(profile) {
|
||||
result = user;
|
||||
return Promise.resolve(dispatch(setProfile(user)));
|
||||
})
|
||||
.then(() => {
|
||||
return fetchPeople(filter, dispatch);
|
||||
})
|
||||
.then(() => {
|
||||
return Promise.resolve(result);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function updateProfileCulture(id, culture) {
|
||||
return (dispatch) => {
|
||||
return api.people.updateUserCulture(id, culture).then((user) => {
|
||||
@ -100,3 +92,18 @@ export function updateProfileCulture(id, culture) {
|
||||
export function getUserPhoto(id) {
|
||||
return api.people.getUserPhoto(id);
|
||||
}
|
||||
|
||||
export function updateCreatedAvatar(avatar) {
|
||||
return (dispatch, getState) => {
|
||||
const { big, max, medium, small } = avatar;
|
||||
const { profile } = getState();
|
||||
const newProfile = {
|
||||
...profile.targetUser,
|
||||
avatarMax: max,
|
||||
avatarMedium: medium,
|
||||
avatar: big,
|
||||
avatarSmall: small,
|
||||
};
|
||||
return dispatch(setProfile(newProfile));
|
||||
};
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class Confirm extends React.PureComponent {
|
||||
|
||||
const loginData = {
|
||||
userName: this.state.email,
|
||||
password: hash,
|
||||
passwordHash: hash,
|
||||
};
|
||||
|
||||
const personalData = {
|
||||
|
@ -10,11 +10,16 @@ import {
|
||||
PasswordInput,
|
||||
Loader,
|
||||
toastr,
|
||||
Heading
|
||||
Heading,
|
||||
} from "asc-web-components";
|
||||
import { PageLayout } from "asc-web-common";
|
||||
import { store } from "asc-web-common";
|
||||
import { getConfirmationInfo, changePassword } from '../../../../store/confirm/actions';
|
||||
import { store, utils as commonUtils } from "asc-web-common";
|
||||
import {
|
||||
getConfirmationInfo,
|
||||
changePassword,
|
||||
} from "../../../../store/confirm/actions";
|
||||
|
||||
const { createPasswordHash } = commonUtils;
|
||||
const { logout } = store.auth.actions;
|
||||
|
||||
const BodyStyle = styled.form`
|
||||
@ -55,27 +60,27 @@ class Form extends React.PureComponent {
|
||||
isLoading: false,
|
||||
passwordEmpty: false,
|
||||
key: linkData.confirmHeader,
|
||||
userId: linkData.uid
|
||||
userId: linkData.uid,
|
||||
};
|
||||
}
|
||||
|
||||
onKeyPress = target => {
|
||||
onKeyPress = (target) => {
|
||||
if (target.key === "Enter") {
|
||||
this.onSubmit();
|
||||
}
|
||||
};
|
||||
|
||||
onChange = event => {
|
||||
onChange = (event) => {
|
||||
this.setState({ password: event.target.value });
|
||||
!this.state.passwordValid && this.setState({ passwordValid: true });
|
||||
event.target.value.trim() && this.setState({ passwordEmpty: false });
|
||||
this.onKeyPress(event);
|
||||
};
|
||||
|
||||
onSubmit = e => {
|
||||
onSubmit = (e) => {
|
||||
this.setState({ isLoading: true }, function () {
|
||||
const { userId, password, key } = this.state;
|
||||
const { history, changePassword } = this.props;
|
||||
const { history, changePassword, hashSettings } = this.props;
|
||||
let hasError = false;
|
||||
|
||||
if (!this.state.passwordValid) {
|
||||
@ -89,14 +94,15 @@ class Form extends React.PureComponent {
|
||||
this.setState({ isLoading: false });
|
||||
return false;
|
||||
}
|
||||
const hash = createPasswordHash(password, hashSettings);
|
||||
|
||||
changePassword(userId, password, key)
|
||||
changePassword(userId, hash, key)
|
||||
.then(() => this.props.logout())
|
||||
.then(() => {
|
||||
history.push("/");
|
||||
toastr.success(this.props.t("ChangePasswordSuccess"));
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
toastr.error(this.props.t(`${error}`));
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
@ -105,7 +111,7 @@ class Form extends React.PureComponent {
|
||||
|
||||
componentDidMount() {
|
||||
const { getConfirmationInfo, history } = this.props;
|
||||
getConfirmationInfo(this.state.key).catch(error => {
|
||||
getConfirmationInfo(this.state.key).catch((error) => {
|
||||
toastr.error(this.props.t(`${error}`));
|
||||
history.push("/");
|
||||
});
|
||||
@ -119,72 +125,72 @@ class Form extends React.PureComponent {
|
||||
window.removeEventListener("keyup", this.onKeyPress);
|
||||
}
|
||||
|
||||
validatePassword = value => this.setState({ passwordValid: value });
|
||||
validatePassword = (value) => this.setState({ passwordValid: value });
|
||||
|
||||
render() {
|
||||
const { settings, isConfirmLoaded, t, greetingTitle } = this.props;
|
||||
const { isLoading, password, passwordEmpty } = this.state;
|
||||
|
||||
return !isConfirmLoaded ? (
|
||||
<Loader className="pageLoader" type="rombs" size='40px' />
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
) : (
|
||||
<BodyStyle>
|
||||
<div className="password-header">
|
||||
<img
|
||||
className="password-logo"
|
||||
src="images/dark_general.png"
|
||||
alt="Logo"
|
||||
/>
|
||||
<Heading className="password-title" color="#116d9d">
|
||||
{greetingTitle}
|
||||
</Heading>
|
||||
</div>
|
||||
<Text className="password-text" fontSize='14px'>
|
||||
{t("PassworResetTitle")}
|
||||
</Text>
|
||||
<PasswordInput
|
||||
id="password"
|
||||
name="password"
|
||||
inputName="password"
|
||||
inputValue={password}
|
||||
size="huge"
|
||||
scale={true}
|
||||
type="password"
|
||||
isDisabled={isLoading}
|
||||
hasError={passwordEmpty}
|
||||
onValidateInput={this.validatePassword}
|
||||
generatorSpecial="!@#$%^&*"
|
||||
tabIndex={1}
|
||||
value={password}
|
||||
onChange={this.onChange}
|
||||
emailInputName="E-mail"
|
||||
passwordSettings={settings}
|
||||
tooltipPasswordTitle="Password must contain:"
|
||||
tooltipPasswordLength={`${t("ErrorPasswordLength", {
|
||||
fromNumber: settings.minLength,
|
||||
toNumber: 30
|
||||
})}:`}
|
||||
placeholder={t("PasswordCustomMode")}
|
||||
maxLength={30}
|
||||
onKeyDown={this.onKeyPress}
|
||||
isAutoFocussed={true}
|
||||
inputWidth="490px"
|
||||
<BodyStyle>
|
||||
<div className="password-header">
|
||||
<img
|
||||
className="password-logo"
|
||||
src="images/dark_general.png"
|
||||
alt="Logo"
|
||||
/>
|
||||
<Button
|
||||
id="button"
|
||||
className="password-button"
|
||||
primary
|
||||
size="big"
|
||||
tabIndex={2}
|
||||
label={
|
||||
isLoading ? t("LoadingProcessing") : t("ImportContactsOkButton")
|
||||
}
|
||||
isDisabled={isLoading}
|
||||
isLoading={isLoading}
|
||||
onClick={this.onSubmit}
|
||||
/>
|
||||
</BodyStyle>
|
||||
);
|
||||
<Heading className="password-title" color="#116d9d">
|
||||
{greetingTitle}
|
||||
</Heading>
|
||||
</div>
|
||||
<Text className="password-text" fontSize="14px">
|
||||
{t("PassworResetTitle")}
|
||||
</Text>
|
||||
<PasswordInput
|
||||
id="password"
|
||||
name="password"
|
||||
inputName="password"
|
||||
inputValue={password}
|
||||
size="huge"
|
||||
scale={true}
|
||||
type="password"
|
||||
isDisabled={isLoading}
|
||||
hasError={passwordEmpty}
|
||||
onValidateInput={this.validatePassword}
|
||||
generatorSpecial="!@#$%^&*"
|
||||
tabIndex={1}
|
||||
value={password}
|
||||
onChange={this.onChange}
|
||||
emailInputName="E-mail"
|
||||
passwordSettings={settings}
|
||||
tooltipPasswordTitle="Password must contain:"
|
||||
tooltipPasswordLength={`${t("ErrorPasswordLength", {
|
||||
fromNumber: settings.minLength,
|
||||
toNumber: 30,
|
||||
})}:`}
|
||||
placeholder={t("PasswordCustomMode")}
|
||||
maxLength={30}
|
||||
onKeyDown={this.onKeyPress}
|
||||
isAutoFocussed={true}
|
||||
inputWidth="490px"
|
||||
/>
|
||||
<Button
|
||||
id="button"
|
||||
className="password-button"
|
||||
primary
|
||||
size="big"
|
||||
tabIndex={2}
|
||||
label={
|
||||
isLoading ? t("LoadingProcessing") : t("ImportContactsOkButton")
|
||||
}
|
||||
isDisabled={isLoading}
|
||||
isLoading={isLoading}
|
||||
onClick={this.onSubmit}
|
||||
/>
|
||||
</BodyStyle>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,14 +198,14 @@ Form.propTypes = {
|
||||
history: PropTypes.object.isRequired,
|
||||
changePassword: PropTypes.func.isRequired,
|
||||
logout: PropTypes.func.isRequired,
|
||||
linkData: PropTypes.object.isRequired
|
||||
linkData: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
Form.defaultProps = {
|
||||
password: ""
|
||||
password: "",
|
||||
};
|
||||
|
||||
const ChangePasswordForm = props => (
|
||||
const ChangePasswordForm = (props) => (
|
||||
<PageLayout>
|
||||
<PageLayout.SectionBody>
|
||||
<Form {...props} />
|
||||
@ -213,12 +219,13 @@ function mapStateToProps(state) {
|
||||
isConfirmLoaded: state.confirm.isConfirmLoaded,
|
||||
settings: state.auth.settings.passwordSettings,
|
||||
isAuthenticated: state.auth.isAuthenticated,
|
||||
greetingTitle: state.auth.settings.greetingSettings
|
||||
greetingTitle: state.auth.settings.greetingSettings,
|
||||
hashSettings: state.auth.settings.hashSettings,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
changePassword,
|
||||
getConfirmationInfo,
|
||||
logout
|
||||
logout,
|
||||
})(withRouter(withTranslation()(ChangePasswordForm)));
|
||||
|
@ -127,7 +127,7 @@ class Confirm extends React.PureComponent {
|
||||
|
||||
const loginData = {
|
||||
userName: this.state.email,
|
||||
password: hash,
|
||||
passwordHash: hash,
|
||||
};
|
||||
|
||||
const personalData = {
|
||||
|
@ -31,7 +31,7 @@ export function createConfirmUser(registerData, loginData, key) {
|
||||
return api.people
|
||||
.createUser(data, key)
|
||||
.then((user) => dispatch(setCurrentUser(user)))
|
||||
.then(() => api.user.login(loginData.userName, loginData.password))
|
||||
.then(() => api.user.login(loginData.userName, loginData.passwordHash))
|
||||
.then(() => loadInitInfo(dispatch));
|
||||
};
|
||||
}
|
||||
@ -51,12 +51,12 @@ export function activateConfirmUser(
|
||||
|
||||
return (dispatch) => {
|
||||
return api.people
|
||||
.changePassword(userId, loginData.password, key)
|
||||
.changePassword(userId, loginData.passwordHash, key)
|
||||
.then((data) => {
|
||||
return api.people.updateActivationStatus(activationStatus, userId, key);
|
||||
})
|
||||
.then((data) => {
|
||||
return dispatch(login(loginData.userName, loginData.password));
|
||||
return dispatch(login(loginData.userName, loginData.passwordHash));
|
||||
})
|
||||
.then((data) => {
|
||||
return api.people.updateUser(changedData);
|
||||
@ -73,10 +73,10 @@ export function changeEmail(userId, email, key) {
|
||||
};
|
||||
}
|
||||
|
||||
export function changePassword(userId, password, key) {
|
||||
export function changePassword(userId, passwordHash, key) {
|
||||
return (dispatch) => {
|
||||
return api.people
|
||||
.changePassword(userId, password, key)
|
||||
.changePassword(userId, passwordHash, key)
|
||||
.then(() => logout(dispatch));
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "asc-web-common",
|
||||
"version": "1.0.248",
|
||||
"version": "1.0.249",
|
||||
"description": "Ascensio System SIA common components and solutions library",
|
||||
"license": "AGPL-3.0",
|
||||
"files": [
|
||||
|
@ -1,234 +1,232 @@
|
||||
|
||||
import { request } from "../client";
|
||||
//import axios from "axios";
|
||||
import Filter from "./filter";
|
||||
import * as fakePeople from "./fake";
|
||||
|
||||
export function getUserList(filter = Filter.getDefault(), fake = false) {
|
||||
if(fake) {
|
||||
return fakePeople.getUserList(filter);
|
||||
}
|
||||
|
||||
const params =
|
||||
filter && filter instanceof Filter
|
||||
? `/filter.json?${filter.toUrlParams()}`
|
||||
: "";
|
||||
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people${params}`
|
||||
});
|
||||
if (fake) {
|
||||
return fakePeople.getUserList(filter);
|
||||
}
|
||||
|
||||
export function getUser(userName = null) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/${userName || '@self'}.json`
|
||||
});
|
||||
}
|
||||
export function getUserPhoto(userId) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/${userId}/photo`
|
||||
});
|
||||
}
|
||||
const params =
|
||||
filter && filter instanceof Filter
|
||||
? `/filter.json?${filter.toUrlParams()}`
|
||||
: "";
|
||||
|
||||
export function createUser(data, confirmKey = null) {
|
||||
const options = {
|
||||
method: "post",
|
||||
url: "/people",
|
||||
data: data
|
||||
};
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people${params}`
|
||||
});
|
||||
}
|
||||
|
||||
if(confirmKey)
|
||||
options.headers = { confirm: confirmKey };
|
||||
export function getUser(userName = null) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/${userName || "@self"}.json`
|
||||
});
|
||||
}
|
||||
export function getUserPhoto(userId) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/${userId}/photo`
|
||||
});
|
||||
}
|
||||
|
||||
return request(options);
|
||||
}
|
||||
export function createUser(data, confirmKey = null) {
|
||||
const options = {
|
||||
method: "post",
|
||||
url: "/people",
|
||||
data: data
|
||||
};
|
||||
|
||||
export function changePassword(userId, password, key) {
|
||||
const data = { password };
|
||||
if (confirmKey) options.headers = { confirm: confirmKey };
|
||||
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${userId}/password`,
|
||||
data,
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
return request(options);
|
||||
}
|
||||
|
||||
export function changeEmail(userId, email, key) {
|
||||
const data = { email };
|
||||
export function changePassword(userId, passwordHash, key) {
|
||||
const data = { passwordHash };
|
||||
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${userId}/password`,
|
||||
data,
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
export function updateActivationStatus(activationStatus, userId, key) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/activationstatus/${activationStatus}.json`,
|
||||
data: { userIds: [userId] },
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${userId}/password`,
|
||||
data,
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
|
||||
export function updateUser(data) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${data.id}`,
|
||||
data
|
||||
});
|
||||
}
|
||||
export function changeEmail(userId, email, key) {
|
||||
const data = { email };
|
||||
|
||||
export function deleteSelf(key) {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: "/people/@self",
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${userId}/password`,
|
||||
data,
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
export function updateActivationStatus(activationStatus, userId, key) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/activationstatus/${activationStatus}.json`,
|
||||
data: { userIds: [userId] },
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
|
||||
export function sendInstructionsToChangePassword(email) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/people/password.json",
|
||||
data: { email }
|
||||
});
|
||||
}
|
||||
export function updateUser(data) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${data.id}`,
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function getListAdmins(filter = Filter.getDefault()) {
|
||||
const filterParams = filter.toUrlParams();
|
||||
const params =
|
||||
export function deleteSelf(key) {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: "/people/@self",
|
||||
headers: { confirm: key }
|
||||
});
|
||||
}
|
||||
|
||||
export function sendInstructionsToChangePassword(email) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/people/password.json",
|
||||
data: { email }
|
||||
});
|
||||
}
|
||||
|
||||
export function getListAdmins(filter = Filter.getDefault()) {
|
||||
const filterParams = filter.toUrlParams();
|
||||
const params =
|
||||
"fields=id,displayName,groups,name,avatar,avatarSmall,isOwner,isAdmin,profileUrl,listAdminModules";
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/filter.json?${filterParams}&${params}`
|
||||
});
|
||||
}
|
||||
|
||||
export function getAdmins(isParams) {
|
||||
let params = "&fields";
|
||||
if (isParams) {
|
||||
params =
|
||||
"fields=id,displayName,groups,name,avatar,avatarSmall,isOwner,isAdmin,profileUrl,listAdminModules";
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/filter.json?${filterParams}&${params}`
|
||||
});
|
||||
}
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/filter.json?isadministrator=true&${params}`
|
||||
});
|
||||
}
|
||||
|
||||
export function getAdmins(isParams) {
|
||||
let params = "&fields";
|
||||
if (isParams) {
|
||||
params =
|
||||
"fields=id,displayName,groups,name,avatar,avatarSmall,isOwner,isAdmin,profileUrl,listAdminModules";
|
||||
export function changeProductAdmin(userId, productId, administrator) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/settings/security/administrator",
|
||||
data: {
|
||||
productId,
|
||||
userId,
|
||||
administrator
|
||||
}
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/filter.json?isadministrator=true&${params}`
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function changeProductAdmin(userId, productId, administrator) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/settings/security/administrator",
|
||||
data: {
|
||||
productId,
|
||||
userId,
|
||||
administrator
|
||||
}
|
||||
});
|
||||
}
|
||||
export function getUserById(userId) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/${userId}`
|
||||
});
|
||||
}
|
||||
|
||||
export function getUserById(userId) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/people/${userId}`
|
||||
});
|
||||
}
|
||||
export function resendUserInvites(userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/people/invite",
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
|
||||
export function resendUserInvites(userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/people/invite",
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
export function updateUserCulture(id, cultureName) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${id}/culture`,
|
||||
data: { cultureName }
|
||||
});
|
||||
}
|
||||
|
||||
export function updateUserCulture(id, cultureName) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/${id}/culture`,
|
||||
data: { cultureName }
|
||||
});
|
||||
}
|
||||
export function loadAvatar(profileId, data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: `/people/${profileId}/photo`,
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function loadAvatar(profileId, data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: `/people/${profileId}/photo`,
|
||||
data
|
||||
});
|
||||
}
|
||||
export function createThumbnailsAvatar(profileId, data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: `/people/${profileId}/photo/thumbnails.json`,
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function createThumbnailsAvatar(profileId, data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: `/people/${profileId}/photo/thumbnails.json`,
|
||||
data
|
||||
});
|
||||
}
|
||||
export function deleteAvatar(profileId) {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: `/people/${profileId}/photo`
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteAvatar(profileId) {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: `/people/${profileId}/photo`
|
||||
});
|
||||
}
|
||||
export function updateUserStatus(status, userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/status/${status}`,
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
|
||||
export function updateUserStatus(status, userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/status/${status}`,
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
export function updateUserType(type, userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/type/${type}`,
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
|
||||
export function updateUserType(type, userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/people/type/${type}`,
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
export function sendInstructionsToDelete() {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/people/self/delete.json"
|
||||
});
|
||||
}
|
||||
|
||||
export function sendInstructionsToDelete() {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/people/self/delete.json"
|
||||
});
|
||||
}
|
||||
export function sendInstructionsToChangeEmail(userId, email) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/people/email.json",
|
||||
data: { userId, email }
|
||||
});
|
||||
}
|
||||
|
||||
export function sendInstructionsToChangeEmail(userId, email) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/people/email.json",
|
||||
data: { userId, email }
|
||||
});
|
||||
}
|
||||
export function deleteUser(userId) {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: `/people/${userId}.json`
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteUser(userId) {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: `/people/${userId}.json`
|
||||
});
|
||||
}
|
||||
export function deleteUsers(userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/people/delete.json",
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteUsers(userIds) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/people/delete.json",
|
||||
data: { userIds }
|
||||
});
|
||||
}
|
||||
|
||||
export function getSelectorUserList() {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/people/filter.json?fields=id,displayName,groups"
|
||||
});
|
||||
}
|
||||
export function getSelectorUserList() {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/people/filter.json?fields=id,displayName,groups"
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import styled from "styled-components";
|
||||
|
||||
const StyledMain = styled.main`
|
||||
height: calc(100vh - 56px);
|
||||
/*height: calc(var(--vh, 1vh) * 100 - 56px);*/
|
||||
height: calc(var(--vh, 1vh) * 100 - 56px);
|
||||
width: 100vw;
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
|
Loading…
Reference in New Issue
Block a user