Merge pull request #930 from ONLYOFFICE/feature/change-user-status-dialog

Feature/change user status dialog
This commit is contained in:
Nikita Gopienko 2022-10-19 15:48:42 +03:00 committed by GitHub
commit 1cb9c4450e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 212 additions and 213 deletions

View File

@ -5,12 +5,7 @@ import PropTypes from "prop-types";
import ModalDialog from "@docspace/components/modal-dialog";
import Button from "@docspace/components/button";
import Text from "@docspace/components/text";
import ToggleContent from "@docspace/components/toggle-content";
import Checkbox from "@docspace/components/checkbox";
import CustomScrollbarsVirtualList from "@docspace/components/scrollbar/custom-scrollbars-virtual-list";
import { FixedSizeList as List, areEqual } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
import { withTranslation } from "react-i18next";
import toastr from "@docspace/components/toast/toastr";
import { EmployeeStatus } from "@docspace/common/constants";
@ -21,45 +16,64 @@ class ChangeUserStatusDialogComponent extends React.Component {
constructor(props) {
super(props);
const { userIds } = props;
this.state = { isRequestRunning: false, userIds };
this.state = { isRequestRunning: false };
}
onChangeUserStatus = () => {
const {
updateUserStatus,
userStatus,
status,
t,
setSelected,
onClose,
userIDs,
getPeopleListItem,
setSelection,
infoPanelVisible,
} = this.props;
const { userIds } = this.state;
let usersCount = 0;
this.setState({ isRequestRunning: true }, () => {
updateUserStatus(userStatus, userIds)
.then(() =>
toastr.success(t("PeopleTranslations:SuccessChangeUserStatus"))
)
updateUserStatus(status, userIDs)
.then((users) => {
if (users.length === 1 && infoPanelVisible) {
const user = getPeopleListItem(users[0]);
setSelection(user);
}
usersCount = users.length;
})
.catch((error) => toastr.error(error))
.finally(() => {
this.setState({ isRequestRunning: false }, () => {
setSelected("close");
toastr.success(t("PeopleTranslations:SuccessChangeUserStatus"));
(!infoPanelVisible || usersCount !== 1) && setSelected("close");
onClose();
});
});
});
};
onCloseAction = () => {
const { onClose } = this.props;
const { isRequestRunning } = this.state;
!isRequestRunning && onClose();
};
render() {
const { t, tReady, onClose, visible, userStatus } = this.props;
const { isRequestRunning, userIds } = this.state;
const { t, tReady, visible, status, userIDs } = this.props;
const { isRequestRunning } = this.state;
const statusTranslation =
userStatus === EmployeeStatus.Active
status === EmployeeStatus.Active
? t("ChangeUsersActiveStatus")
: t("ChangeUsersDisableStatus");
const userStatusTranslation =
userStatus === EmployeeStatus.Active
status === EmployeeStatus.Active
? t("PeopleTranslations:DisabledEmployeeStatus")
: t("Common:Active");
@ -67,7 +81,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
<ModalDialogContainer
isLoading={!tReady}
visible={visible}
onClose={onClose}
onClose={this.onCloseAction}
autoMaxHeight
>
<ModalDialog.Header>
@ -90,13 +104,13 @@ class ChangeUserStatusDialogComponent extends React.Component {
scale
onClick={this.onChangeUserStatus}
isLoading={isRequestRunning}
isDisabled={userIds.length === 0}
isDisabled={userIDs.length === 0}
/>
<Button
label={t("Common:CancelButton")}
size="normal"
scale
onClick={onClose}
onClick={this.onCloseAction}
isDisabled={isRequestRunning}
/>
</ModalDialog.Footer>
@ -115,26 +129,26 @@ ChangeUserStatusDialog.propTypes = {
visible: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
setSelected: PropTypes.func.isRequired,
userIds: PropTypes.arrayOf(PropTypes.string).isRequired,
selectedUsers: PropTypes.arrayOf(PropTypes.object).isRequired,
userIDs: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default withRouter(
inject(({ peopleStore }, ownProps) => {
const updateUserStatus = peopleStore.usersStore.updateUserStatus;
const selectedUsers = peopleStore.selectionStore.selection;
inject(({ peopleStore, auth }) => {
const setSelected = peopleStore.selectionStore.setSelected;
const userIds =
ownProps.userStatus === EmployeeStatus.Active
? peopleStore.selectionStore.getUsersToActivateIds
: peopleStore.selectionStore.getUsersToDisableIds;
const { getPeopleListItem, updateUserStatus } = peopleStore.usersStore;
const { setSelection, isVisible: infoPanelVisible } = auth.infoPanelStore;
return {
updateUserStatus,
selectedUsers,
setSelected,
userIds,
getPeopleListItem,
setSelection,
infoPanelVisible,
};
})(observer(ChangeUserStatusDialog))
);

View File

@ -47,10 +47,13 @@ class ChangeUserTypeDialogComponent extends React.Component {
};
onCloseAction = async () => {
const { isRequestRunning } = this.state;
const { onClose, getUsersList, filter } = this.props;
await getUsersList(filter);
if (!isRequestRunning) {
await getUsersList(filter);
onClose();
onClose();
}
};
getType = (type) => {
@ -70,7 +73,7 @@ class ChangeUserTypeDialogComponent extends React.Component {
};
render() {
const { visible, onClose, t, tReady, toType, fromType } = this.props;
const { visible, t, tReady, toType, fromType } = this.props;
const { isRequestRunning, userIDs } = this.state;
const firstType = fromType.length === 1 ? this.getType(fromType[0]) : null;

View File

@ -25,9 +25,9 @@ const Dialogs = ({
deleteProfileEver,
data,
closeDialogs,
employeeDialogVisible,
changeUserTypeDialogVisible,
guestDialogVisible,
activeDialogVisible,
changeUserStatusDialogVisible,
disableDialogVisible,
sendInviteDialogVisible,
deleteDialogVisible,
@ -70,34 +70,22 @@ const Dialogs = ({
user={data}
/>
)}
{employeeDialogVisible && (
{changeUserTypeDialogVisible && (
<ChangeUserTypeDialog
visible={employeeDialogVisible}
visible={changeUserTypeDialogVisible}
onClose={closeDialogs}
{...data}
/>
)}
{guestDialogVisible && (
<ChangeUserTypeDialog
visible={guestDialogVisible}
onClose={closeDialogs}
userType={EmployeeType.Guest}
/>
)}
{activeDialogVisible && (
{changeUserStatusDialogVisible && (
<ChangeUserStatusDialog
visible={activeDialogVisible}
visible={changeUserStatusDialogVisible}
onClose={closeDialogs}
userStatus={EmployeeStatus.Active}
/>
)}
{disableDialogVisible && (
<ChangeUserStatusDialog
visible={disableDialogVisible}
onClose={closeDialogs}
userStatus={EmployeeStatus.Disabled}
{...data}
/>
)}
{sendInviteDialogVisible && (
<SendInviteDialog
visible={sendInviteDialogVisible}
@ -140,9 +128,9 @@ export default inject(({ auth, peopleStore }) => {
data,
closeDialogs,
employeeDialogVisible,
changeUserTypeDialogVisible,
guestDialogVisible,
activeDialogVisible,
changeUserStatusDialogVisible,
disableDialogVisible,
sendInviteDialogVisible,
deleteDialogVisible,
@ -165,9 +153,9 @@ export default inject(({ auth, peopleStore }) => {
data,
closeDialogs,
employeeDialogVisible,
changeUserTypeDialogVisible,
guestDialogVisible,
activeDialogVisible,
changeUserStatusDialogVisible,
disableDialogVisible,
sendInviteDialogVisible,
deleteDialogVisible,

View File

@ -74,7 +74,11 @@ const UserContent = ({
isTextOverflow={true}
noHover
>
{statusType === "pending" ? email : displayName ? displayName : email}
{statusType === "pending"
? email
: displayName?.trim()
? displayName
: email}
</Link>
<Badges statusType={statusType} isPaid={!isVisitor} />

View File

@ -343,7 +343,7 @@ const PeopleTableRow = (props) => {
>
{statusType === "pending"
? email
: displayName
: displayName?.trim()
? displayName
: email}
</Link>

View File

@ -16,7 +16,8 @@ const AccountsItemTitle = ({
getUserContextOptions,
severalItemsLength,
}) => {
const isPending = selection.statusType === "pending";
const isPending =
selection.statusType === "pending" || selection.statusType === "disabled";
const getData = () => {
const newOptions = selection.options.filter(
@ -51,7 +52,11 @@ const AccountsItemTitle = ({
title={selection.displayName}
truncate
>
{isPending ? selection.email : selection.displayName}
{isPending
? selection.email
: selection.displayName?.trim()
? selection.displayName
: selection.email}
</Text>
{!isPending && (
<Text className={"info-text__email"} noSelect title={selection.email}>

View File

@ -144,7 +144,7 @@ class AccountsContextOptionsStore {
};
getUserGroupContextOptions = (t) => {
const { onChangeType } = this.peopleStore;
const { onChangeType, onChangeStatus } = this.peopleStore;
const {
hasUsersToMakeEmployees,
@ -155,13 +155,11 @@ class AccountsContextOptionsStore {
hasFreeUsers,
} = this.peopleStore.selectionStore;
const {
setActiveDialogVisible,
setDisableDialogVisible,
setSendInviteDialogVisible,
setDeleteDialogVisible,
} = this.peopleStore.dialogStore;
const { isAdmin, isOwner } = this.authStore.userStore.user;
const { isOwner } = this.authStore.userStore.user;
const { setIsVisible, isVisible } = this.peopleStore.infoPanelStore;
@ -227,14 +225,14 @@ class AccountsContextOptionsStore {
key: "cm-enable",
label: t("Common:Enable"),
disabled: !hasUsersToActivate,
onClick: () => setActiveDialogVisible(true),
onClick: () => onChangeStatus(EmployeeStatus.Active),
icon: "images/enable.react.svg",
},
{
key: "cm-disable",
label: t("PeopleTranslations:DisableUserButton"),
disabled: !hasUsersToDisable,
onClick: () => setDisableDialogVisible(true),
onClick: () => onChangeStatus(EmployeeStatus.Disabled),
icon: "images/disable.react.svg",
},
{
@ -310,58 +308,18 @@ class AccountsContextOptionsStore {
onEnableClick = (t, item) => {
const { id } = item;
const {
updateUserStatus,
getUserContextOptions,
getStatusType,
} = this.peopleStore.usersStore;
const { setSelection } = this.authStore.infoPanelStore;
updateUserStatus(EmployeeStatus.Active, [id])
.then(() => {
const updatedUser = { ...item };
updatedUser.status = EmployeeStatus.Active;
updatedUser.statusType = getStatusType(updatedUser);
updatedUser.options = getUserContextOptions(
false,
false,
updatedUser.statusType,
EmployeeStatus.Active
);
setSelection(updatedUser);
})
.then(() =>
toastr.success(t("PeopleTranslations:SuccessChangeUserStatus"))
)
.catch((error) => toastr.error(error));
const { changeStatus } = this.peopleStore;
changeStatus(EmployeeStatus.Active, [id]);
};
onDisableClick = (t, item) => {
const { id } = item;
const {
updateUserStatus,
getUserContextOptions,
getStatusType,
} = this.peopleStore.usersStore;
const { setSelection } = this.authStore.infoPanelStore;
updateUserStatus(EmployeeStatus.Disabled, [id])
.then(() => {
const updatedUser = { ...item };
updatedUser.status = EmployeeStatus.Disabled;
updatedUser.statusType = getStatusType(updatedUser);
updatedUser.options = getUserContextOptions(
false,
false,
updatedUser.statusType,
EmployeeStatus.Disabled
);
setSelection(updatedUser);
})
.then(() =>
toastr.success(t("PeopleTranslations:SuccessChangeUserStatus"))
)
.catch((error) => toastr.error(error));
const { changeStatus } = this.peopleStore;
changeStatus(EmployeeStatus.Disabled, [id]);
};
onReassignDataClick = (item) => {

View File

@ -9,9 +9,9 @@ class DialogStore {
deleteProfileEver = false;
data = {};
employeeDialogVisible = false;
guestDialogVisible = false;
activeDialogVisible = false;
changeUserTypeDialogVisible = false;
changeUserStatusDialogVisible = false;
disableDialogVisible = false;
sendInviteDialogVisible = false;
invitationDialogVisible = false;
@ -49,20 +49,12 @@ class DialogStore {
this.data = data;
};
setEmployeeDialogVisible = (visible) => {
this.employeeDialogVisible = visible;
setChangeUserTypeDialogVisible = (visible) => {
this.changeUserTypeDialogVisible = visible;
};
setGuestDialogVisible = (visible) => {
this.guestDialogVisible = visible;
};
setActiveDialogVisible = (visible) => {
this.activeDialogVisible = visible;
};
setDisableDialogVisible = (visible) => {
this.disableDialogVisible = visible;
setChangeUserStatusDialogVisible = (visible) => {
this.changeUserStatusDialogVisible = visible;
};
setSendInviteDialogVisible = (visible) => {
@ -85,10 +77,9 @@ class DialogStore {
this.setDeleteProfileDialogVisible(false);
this.setDialogData({});
this.setEmployeeDialogVisible(false);
this.setGuestDialogVisible(false);
this.setActiveDialogVisible(false);
this.setDisableDialogVisible(false);
this.setChangeUserTypeDialogVisible(false);
this.setChangeUserStatusDialogVisible(false);
this.setSendInviteDialogVisible(false);
this.setDeleteDialogVisible(false);
this.setInvitationDialogVisible(false);

View File

@ -20,6 +20,7 @@ import {
import { isMobileRDD } from "react-device-detect";
import toastr from "@docspace/components/toast/toastr";
import { EmployeeStatus } from "@docspace/common/constants";
class PeopleStore {
contextOptionsStore = null;
@ -98,7 +99,7 @@ class PeopleStore {
return getUsersList(newFilter);
};
onChangeType = (e, t) => {
onChangeType = (e) => {
const action = e?.action ? e.action : e?.target?.dataset?.action;
const { getUsersToMakeEmployees } = this.selectionStore;
@ -107,7 +108,7 @@ class PeopleStore {
};
changeType = (type, users) => {
const { setEmployeeDialogVisible, setDialogData } = this.dialogStore;
const { setChangeUserTypeDialogVisible, setDialogData } = this.dialogStore;
let fromType =
users.length === 1 ? [users[0].role] : users.map((u) => u.role);
@ -130,7 +131,38 @@ class PeopleStore {
setDialogData({ toType: type, fromType, userIDs });
setEmployeeDialogVisible(true);
setChangeUserTypeDialogVisible(true);
};
onChangeStatus = (status) => {
const users = [];
if (status === EmployeeStatus.Active) {
const { getUsersToActivate } = this.selectionStore;
users.push(...getUsersToActivate);
} else {
const { getUsersToDisable } = this.selectionStore;
users.push(...getUsersToDisable);
}
this.changeStatus(status, users);
};
changeStatus = (status, users) => {
const {
setChangeUserStatusDialogVisible,
setDialogData,
} = this.dialogStore;
const userIDs = users.map((user) => {
return user?.id ? user.id : user;
});
setDialogData({ status, userIDs });
setChangeUserStatusDialogVisible(true);
};
onOpenInfoPanel = () => {
@ -148,8 +180,6 @@ class PeopleStore {
hasFreeUsers,
} = this.selectionStore;
const {
setActiveDialogVisible,
setDisableDialogVisible,
setSendInviteDialogVisible,
setDeleteDialogVisible,
} = this.dialogStore;
@ -165,7 +195,7 @@ class PeopleStore {
className: "group-menu_drop-down",
label: t("Common:DocSpaceAdmin"),
title: t("Common:DocSpaceAdmin"),
onClick: (e) => this.onChangeType(e, t),
onClick: (e) => this.onChangeType(e),
"data-action": "admin",
key: "administrator",
};
@ -174,7 +204,7 @@ class PeopleStore {
className: "group-menu_drop-down",
label: t("Common:RoomAdmin"),
title: t("Common:RoomAdmin"),
onClick: (e) => this.onChangeType(e, t),
onClick: (e) => this.onChangeType(e),
"data-action": "manager",
key: "manager",
};
@ -183,7 +213,7 @@ class PeopleStore {
className: "group-menu_drop-down",
label: t("Common:User"),
title: t("Common:User"),
onClick: (e) => this.onChangeType(e, t),
onClick: (e) => this.onChangeType(e),
"data-action": "user",
key: "user",
};
@ -223,14 +253,14 @@ class PeopleStore {
key: "enable",
label: t("Common:Enable"),
disabled: !hasUsersToActivate,
onClick: () => setActiveDialogVisible(true),
onClick: () => this.onChangeStatus(EmployeeStatus.Active),
iconUrl: "images/enable.react.svg",
},
{
key: "disable",
label: t("PeopleTranslations:DisableUserButton"),
disabled: !hasUsersToDisable,
onClick: () => setDisableDialogVisible(true),
onClick: () => this.onChangeStatus(EmployeeStatus.Disabled),
iconUrl: "images/disable.react.svg",
},
{

View File

@ -181,7 +181,7 @@ class SelectionStore {
return false;
}
get getUsersToActivateIds() {
get getUsersToActivate() {
const { id, isOwner, isAdmin } = this.peopleStore.authStore.userStore.user;
if (isOwner) {
@ -189,7 +189,7 @@ class SelectionStore {
(x) => x.status !== EmployeeStatus.Active && x.id !== id
);
return users.map((u) => u.id);
return users.map((u) => u);
}
if (isAdmin && !isOwner) {
@ -201,7 +201,7 @@ class SelectionStore {
!x.isOwner
);
return users.map((u) => u.id);
return users.map((u) => u);
}
return [];
@ -233,7 +233,7 @@ class SelectionStore {
return false;
}
get getUsersToDisableIds() {
get getUsersToDisable() {
const { id, isOwner, isAdmin } = this.peopleStore.authStore.userStore.user;
if (isOwner) {
@ -241,7 +241,7 @@ class SelectionStore {
(x) => x.status !== EmployeeStatus.Disabled && x.id !== id
);
return users.map((u) => u.id);
return users.map((u) => u);
}
if (isAdmin && !isOwner) {
@ -253,7 +253,7 @@ class SelectionStore {
!x.isOwner
);
return users.map((u) => u.id);
return users.map((u) => u);
}
return [];

View File

@ -87,12 +87,16 @@ class UsersStore {
};
updateUserStatus = async (status, userIds) => {
const user = await api.people.updateUserStatus(status, userIds);
return api.people.updateUserStatus(status, userIds).then((users) => {
if (users) {
users.forEach((user) => {
const userIndex = this.users.findIndex((x) => x.id === user.id);
if (userIndex !== -1) this.users[userIndex] = user;
});
}
if (user) {
const userIndex = this.users.findIndex((x) => x.id === user[0].id);
if (userIndex !== -1) this.users[userIndex] = user[0];
}
return users;
});
};
updateUserType = async (type, userIds, filter, fromType) => {
@ -333,62 +337,64 @@ class UsersStore {
return res.items;
};
getPeopleListItem = (user) => {
const {
id,
displayName,
avatar,
email,
isOwner,
isAdmin: isAdministrator,
isVisitor,
mobilePhone,
userName,
activationStatus,
status,
groups,
title,
firstName,
lastName,
} = user;
const statusType = this.getStatusType(user);
const role = this.getUserRole(user);
const isMySelf =
this.peopleStore.authStore.userStore.user &&
user.userName === this.peopleStore.authStore.userStore.user.userName;
//const isViewerAdmin = this.peopleStore.authStore.isAdmin;
const options = this.getUserContextOptions(
isMySelf,
isOwner,
isAdministrator,
statusType,
role,
status
);
return {
id,
status,
activationStatus,
statusType,
role,
isOwner,
isAdmin: isAdministrator,
isVisitor,
displayName,
avatar,
email,
userName,
mobilePhone,
options,
groups,
position: title,
firstName,
lastName,
};
};
get peopleList() {
const list = this.users.map((user) => {
const {
id,
displayName,
avatar,
email,
isOwner,
isAdmin: isAdministrator,
isVisitor,
mobilePhone,
userName,
activationStatus,
status,
groups,
title,
firstName,
lastName,
} = user;
const statusType = this.getStatusType(user);
const role = this.getUserRole(user);
const isMySelf =
this.peopleStore.authStore.userStore.user &&
user.userName === this.peopleStore.authStore.userStore.user.userName;
//const isViewerAdmin = this.peopleStore.authStore.isAdmin;
const options = this.getUserContextOptions(
isMySelf,
isOwner,
isAdministrator,
statusType,
role,
status
);
return {
id,
status,
activationStatus,
statusType,
role,
isOwner,
isAdmin: isAdministrator,
isVisitor,
displayName,
avatar,
email,
userName,
mobilePhone,
options,
groups,
position: title,
firstName,
lastName,
};
});
const list = this.users.map((user) => this.getPeopleListItem(user));
return list;
}