People.Client: Dialogs: added DeleteSelfProfileDialog component, applied to Home and Profile component

This commit is contained in:
Daniil Senkiv 2019-12-14 12:45:31 +03:00
parent 62d87d2625
commit 49da1505b3
7 changed files with 252 additions and 112 deletions

View File

@ -0,0 +1,56 @@
import i18n from "i18next";
import Backend from "i18next-xhr-backend";
import config from "../../../../package.json";
const newInstance = i18n.createInstance();
if (process.env.NODE_ENV === "production") {
newInstance
.use(Backend)
.init({
lng: 'en',
fallbackLng: "en",
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === 'lowercase') return value.toLowerCase();
return value;
}
},
react: {
useSuspense: true
},
backend: {
loadPath: `${config.homepage}/locales/DeleteSelfProfileDialog/{{lng}}/{{ns}}.json`
}
});
} else if (process.env.NODE_ENV === "development") {
const resources = {
en: {
translation: require("./locales/en/translation.json")
},
ru: {
translation: require("./locales/ru/translation.json")
},
};
newInstance.init({
resources: resources,
lng: 'en',
fallbackLng: "en",
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
react: {
useSuspense: true
}
});
}
export default newInstance;

View File

@ -0,0 +1,122 @@
import React from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
import {
toastr,
ModalDialog,
Button,
Link,
Text
} from "asc-web-components";
import { withTranslation, I18nextProvider } from "react-i18next";
import i18n from "./i18n";
import styled from "styled-components";
import { api } from "asc-web-common";
const { sendInstructionsToDelete } = api.people;
const ModalDialogContainer = styled.div`
.margin-top {
margin-top: 16px;
}
.margin-left {
margin-left: 8px;
}
`;
class PureDeleteSelfProfileDialog extends React.Component {
constructor(props) {
super(props);
const { language } = props;
this.state = {
isRequestRunning: false
};
i18n.changeLanguage(language);
}
onDeleteSelfProfileInstructions = () => {
const { onClose } = this.props;
this.setState({ isRequestRunning: true }, function () {
sendInstructionsToDelete()
.then((res) => {
toastr.success(res);
})
.catch((error) => toastr.error(error))
.finally(() => {
onClose();
this.setState({ isRequestRunning: false });
});
})
}
render() {
console.log("DeleteSelfProfileDialog render");
const { t, visible, email, onClose } = this.props;
const { isRequestRunning } = this.state;
return (
<ModalDialogContainer>
<ModalDialog
visible={visible}
onClose={onClose}
headerContent={t('DeleteProfileTitle')}
bodyContent={
<Text fontSize='13px'>
{t('DeleteProfileInfo')} <Link type="page" href={`mailto:${email}`} isHovered title={email}>
{email}
</Link>
</Text>
}
footerContent={
<>
<Button
key="SendBtn"
label={t('SendButton')}
size="medium"
primary={true}
onClick={this.onDeleteSelfProfileInstructions}
isLoading={isRequestRunning}
/>
<Button
className='margin-left'
key="CloseBtn"
label={t('CloseButton')}
size="medium"
onClick={onClose}
isDisabled={isRequestRunning}
/>
</>
}
/>
</ModalDialogContainer>
);
}
}
const DeleteSelfProfileDialogContainer = withTranslation()(PureDeleteSelfProfileDialog);
const DeleteSelfProfileDialog = props => (
<I18nextProvider i18n={i18n}>
<DeleteSelfProfileDialogContainer {...props} />
</I18nextProvider>
);
DeleteSelfProfileDialog.propTypes = {
visible: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
email: PropTypes.string.isRequired,
};
function mapStateToProps(state) {
return {
language: state.auth.user.cultureName,
};
}
export default connect(mapStateToProps, {})(withRouter(DeleteSelfProfileDialog));

View File

@ -0,0 +1,6 @@
{
"DeleteProfileTitle": "Delete profile dialog",
"DeleteProfileInfo": "Send the profile deletion instructions to the email address",
"SendButton": "Send",
"CloseButton": "Close"
}

View File

@ -0,0 +1,6 @@
{
"DeleteProfileTitle": "Диалог удаления профиля",
"DeleteProfileInfo": "Отправить инструкции по удалению профиля на адрес электронной почты",
"SendButton": "Отправить",
"CloseButton": "Закрыть"
}

View File

@ -33,8 +33,9 @@ import isEqual from "lodash/isEqual";
import { store, api, constants } from 'asc-web-common';
import ChangeEmailDialog from '../../../../dialogs/ChangeEmailDialog';
import ChangePasswordDialog from '../../../../dialogs/ChangePasswordDialog';
import DeleteSelfProfileDialog from '../../../../dialogs/DeleteSelfProfileDialog';
const { isAdmin, isMe } = store.auth.selectors;
const { resendUserInvites, sendInstructionsToDelete, sendInstructionsToChangePassword, deleteUser } = api.people;
const { resendUserInvites, deleteUser } = api.people;
const { EmployeeStatus } = constants;
@ -51,6 +52,7 @@ class SectionBodyContent extends React.PureComponent {
},
changeEmailDialogVisible: false,
changePasswordDialogVisible: false,
deleteSelfProfileDialogVisible: false,
isEmailValid: false
};
}
@ -173,50 +175,8 @@ class SectionBodyContent extends React.PureComponent {
onDeleteSelfProfileClick = email => {
this.setState({
dialog: {
visible: true,
header: "Delete profile dialog",
body: (
<Text>
Send the profile deletion instructions to the email address{" "}
<Link type="page" href={`mailto:${email}`} isHovered title={email}>
{email}
</Link>
</Text>
),
buttons: [
<Button
key="OkBtn"
label="Send"
size="medium"
primary={true}
onClick={() => {
const { onLoading } = this.props;
onLoading(true);
sendInstructionsToDelete()
.then(() =>
toastr.success(
<Text>
Instructions to delete your profile has been sent to{" "}
<b>{email}</b> email address
</Text>
)
)
.catch(error => toastr.error(error))
.finally(() => onLoading(false));
this.onDialogClose();
}}
/>,
<Button
key="CancelBtn"
label="Cancel"
size="medium"
primary={false}
onClick={this.onDialogClose}
style={{ marginLeft: "8px" }}
/>
]
}
deleteSelfProfileDialogVisible: true,
userEmail: email
});
};
@ -378,6 +338,8 @@ class SectionBodyContent extends React.PureComponent {
onChangePasswordDialogClose = () => this.setState({ changePasswordDialogVisible: false });
onDeleteSelfProfileDialogClose = () => this.setState({ deleteSelfProfileDialogVisible: false });
needForUpdate = (currentProps, nextProps) => {
if (currentProps.checked !== nextProps.checked) {
return true;
@ -394,7 +356,7 @@ class SectionBodyContent extends React.PureComponent {
render() {
console.log("Home SectionBodyContent render()");
const { users, viewer, selection, history, settings, t } = this.props;
const { dialog, changeEmailDialogVisible, changePasswordDialogVisible } = this.state;
const { dialog, changeEmailDialogVisible, changePasswordDialogVisible, deleteSelfProfileDialogVisible } = this.state;
return users.length > 0 ? (
<>
@ -458,6 +420,14 @@ class SectionBodyContent extends React.PureComponent {
email={this.state.userEmail}
/>
}
{deleteSelfProfileDialogVisible &&
<DeleteSelfProfileDialog
visible={deleteSelfProfileDialogVisible}
onClose={this.onDeleteSelfProfileDialogClose}
email={this.state.userEmail}
/>
}
</>
) : (
<EmptyScreenContainer

View File

@ -26,10 +26,10 @@ import {
import { fetchProfile, getUserPhoto } from "../../../../../store/profile/actions";
import styled from "styled-components";
import { store, api, constants } from "asc-web-common";
import DeleteSelfProfileDialog from '../../../../dialogs/DeleteSelfProfileDialog';
const { isAdmin, isMe } = store.auth.selectors;
const {
resendUserInvites,
sendInstructionsToDelete,
sendInstructionsToChangePassword,
sendInstructionsToChangeEmail,
createThumbnailsAvatar,
@ -85,7 +85,8 @@ class SectionHeaderContent extends React.PureComponent {
image: null,
defaultWidth: 0,
defaultHeight: 0
}
},
deleteSelfProfileDialogVisible: false
};
return newState;
@ -93,7 +94,7 @@ class SectionHeaderContent extends React.PureComponent {
openAvatarEditor = () => {
getUserPhoto(this.state.profile.id).then(userPhotoData => {
if(userPhotoData.original){
if (userPhotoData.original) {
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
this.setState({
@ -105,7 +106,7 @@ class SectionHeaderContent extends React.PureComponent {
},
visibleAvatarEditor: true
});
}else{
} else {
this.setState({
avatar: {
tmpFile: this.state.avatar.tmpFile,
@ -128,7 +129,7 @@ class SectionHeaderContent extends React.PureComponent {
loadAvatar(this.state.profile.id, data)
.then(response => {
var img = new Image();
img.onload = function() {
img.onload = function () {
var stateCopy = Object.assign({}, _this.state);
stateCopy.avatar = {
tmpFile: response.data,
@ -371,50 +372,13 @@ class SectionHeaderContent extends React.PureComponent {
onDeleteSelfProfileClick = email => {
this.setState({
dialog: {
visible: true,
header: "Delete profile dialog",
body: (
<Text>
Send the profile deletion instructions to the email address{" "}
<Link type="page" href={`mailto:${email}`} isHovered title={email}>
{email}
</Link>
</Text>
),
buttons: [
<Button
key="OkBtn"
label="Send"
size="medium"
primary={true}
onClick={() => {
sendInstructionsToDelete()
.then(() =>
toastr.success(
<Text>
Instructions to delete your profile has been sent to{" "}
<b>{email}</b> email address
</Text>
)
)
.catch(error => toastr.error(error));
this.onDialogClose();
}}
/>,
<Button
key="CancelBtn"
label="Cancel"
size="medium"
primary={false}
onClick={this.onDialogClose}
style={{ marginLeft: "8px" }}
/>
]
}
deleteSelfProfileDialogVisible: true,
email
});
};
onDeleteSelfProfileDialogClose = () => this.setState({ deleteSelfProfileDialogVisible: false });
onInviteAgainClick = () => {
resendUserInvites(new Array(this.state.profile.id))
.then(() =>
@ -464,15 +428,15 @@ class SectionHeaderContent extends React.PureComponent {
? viewer.isOwner
? {}
: {
key: "delete-profile",
label: t("DeleteSelfProfile"),
onClick: this.onDeleteSelfProfileClick.bind(this, user.email)
}
: {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick
key: "delete-profile",
label: t("DeleteSelfProfile"),
onClick: this.onDeleteSelfProfileClick.bind(this, user.email)
}
: {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick
}
];
case "disabled":
return [
@ -520,17 +484,17 @@ class SectionHeaderContent extends React.PureComponent {
onClick: this.openAvatarEditor
},
!isMe(user, viewer.userName) &&
(user.status === EmployeeStatus.Active
? {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick
}
: {
key: "enable",
label: t("EnableUserButton"),
onClick: this.onEnableClick
}),
(user.status === EmployeeStatus.Active
? {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick
}
: {
key: "enable",
label: t("EnableUserButton"),
onClick: this.onEnableClick
}),
isMe(user, viewer.userName) && {
key: "delete-profile",
label: t("DeleteSelfProfile"),
@ -548,7 +512,7 @@ class SectionHeaderContent extends React.PureComponent {
render() {
const { profile, isAdmin, viewer, t } = this.props;
const { dialog, avatar, visibleAvatarEditor } = this.state;
const { dialog, avatar, visibleAvatarEditor, deleteSelfProfileDialogVisible } = this.state;
const contextOptions = () => this.getUserContextOptions(profile, viewer);
@ -596,6 +560,14 @@ class SectionHeaderContent extends React.PureComponent {
maxSizeFileError={t("maxSizeFileError")}
unknownError={t("unknownError")}
/>
{deleteSelfProfileDialogVisible &&
<DeleteSelfProfileDialog
visible={deleteSelfProfileDialogVisible}
onClose={this.onDeleteSelfProfileDialogClose}
email={this.state.email}
/>
}
</div>
);
}

View File

@ -32,6 +32,14 @@
"SendButton"
]
},
"DeleteProfileDialog":{
"Resource": [
"DeleteProfileTitle",
"DeleteProfileInfo",
"CloseButton",
"SendButton"
]
},
"ChangePasswordDialog":{
"Resource": [
"PasswordChangeTitle",