Web: People: added send invite dialog to group users
This commit is contained in:
parent
05954f21e0
commit
7ada48f0bc
@ -40,8 +40,8 @@ const ModalDialogContainer = styled.div`
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.delete-group-users_dialog {
|
||||
.heading-toggle-content {
|
||||
.toggle-content-dialog {
|
||||
.heading-toggle-content {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
import i18n from "i18next";
|
||||
import Backend from "i18next-xhr-backend";
|
||||
import config from "../../../../package.json";
|
||||
import { constants } from 'asc-web-common';
|
||||
const { LANGUAGE } = constants;
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
},
|
||||
backend: {
|
||||
loadPath: `${config.homepage}/locales/DeleteProfileEverDialog/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
},
|
||||
ru: {
|
||||
translation: require("./locales/ru/translation.json")
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: localStorage.getItem(LANGUAGE) || 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -0,0 +1,92 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { withRouter } from "react-router";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
Button,
|
||||
Text,
|
||||
ToggleContent
|
||||
} from "asc-web-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { api, utils } from "asc-web-common";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
const { resendUserInvites } = api.people;
|
||||
const { changeLanguage } = utils;
|
||||
|
||||
const SendInviteDialogComponent = props => {
|
||||
const { t, onClose, visible } = props;
|
||||
const users = props.users.filter(x => x.status === 2);
|
||||
const usersId = [];
|
||||
users.map(item => usersId.push(item.id));
|
||||
|
||||
const [isRequestRunning, setIsRequestRunning] = useState(false);
|
||||
|
||||
changeLanguage(i18n);
|
||||
|
||||
const onSendInvite = useCallback(() => {
|
||||
setIsRequestRunning(true);
|
||||
resendUserInvites(usersId)
|
||||
.then(() => toastr.success(t("SuccessSendInvitation")))
|
||||
.catch(error => toastr.error(error))
|
||||
.finally(() => setIsRequestRunning(false));
|
||||
}, [t, usersId]);
|
||||
|
||||
//console.log("SendInviteDialog render");
|
||||
return (
|
||||
<ModalDialogContainer>
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
headerContent={t("SendInviteAgain")}
|
||||
bodyContent={
|
||||
<>
|
||||
<Text>{t("SendInviteAgainDialog")}</Text>
|
||||
<ToggleContent
|
||||
className="toggle-content-dialog"
|
||||
label={t("DeleteGroupUsersShowUsers")}
|
||||
>
|
||||
{users.map((item, index) => (
|
||||
<Text key={index}>{item.displayName}</Text>
|
||||
))}
|
||||
</ToggleContent>
|
||||
</>
|
||||
}
|
||||
footerContent={
|
||||
<>
|
||||
<Button
|
||||
label={t("OKButton")}
|
||||
size="medium"
|
||||
primary
|
||||
onClick={onSendInvite}
|
||||
isLoading={isRequestRunning}
|
||||
/>
|
||||
<Button
|
||||
className="button-dialog"
|
||||
label={t("CancelButton")}
|
||||
size="medium"
|
||||
onClick={onClose}
|
||||
isDisabled={isRequestRunning}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const SendInviteDialogTranslated = withTranslation()(SendInviteDialogComponent);
|
||||
|
||||
const SendInviteDialog = props => (
|
||||
<SendInviteDialogTranslated i18n={i18n} {...props} />
|
||||
);
|
||||
|
||||
SendInviteDialog.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
users: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default withRouter(SendInviteDialog);
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"OKButton": "OK",
|
||||
"CancelButton": "Cancel",
|
||||
"SendInviteAgain": "Send invitation once again",
|
||||
|
||||
"DeleteGroupUsersShowUsers": "View users list",
|
||||
"SendInviteAgainDialog": "The invitation to the portal will be sent once again to the selected users with the 'Pending' status who are not disabled. After the users confirm the invitation to the portal their status will change to 'Active'"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"OKButton": "ОК",
|
||||
"CancelButton": "Отмена",
|
||||
"SendInviteAgain": "Отправить приглашение еще раз",
|
||||
|
||||
"DeleteGroupUsersShowUsers": "Показать список пользователей",
|
||||
"SendInviteAgainDialog": "Приглашение на портал будет отправлено еще раз выбранным пользователям со статусом 'Ожидание', которые не заблокированы. После того, как пользователи подтвердят приглашение на портал, их статус изменится на 'Активный'"
|
||||
}
|
@ -4,7 +4,8 @@ import ChangePhoneDialog from "./ChangePhoneDialog";
|
||||
import DeleteProfileEverDialog from "./DeleteProfileEverDialog";
|
||||
import DeleteSelfProfileDialog from "./DeleteSelfProfileDialog";
|
||||
import DeleteGroupUsersDialog from "./DeleteGroupUsersDialog";
|
||||
import InviteDialog from './InviteDialog';
|
||||
import InviteDialog from "./InviteDialog";
|
||||
import SendInviteDialog from "./SendInviteDialog";
|
||||
|
||||
export {
|
||||
ChangeEmailDialog,
|
||||
@ -13,5 +14,6 @@ export {
|
||||
DeleteProfileEverDialog,
|
||||
DeleteSelfProfileDialog,
|
||||
DeleteGroupUsersDialog,
|
||||
InviteDialog
|
||||
};
|
||||
InviteDialog,
|
||||
SendInviteDialog
|
||||
};
|
||||
|
@ -7,13 +7,13 @@ import {
|
||||
toastr,
|
||||
ContextMenuButton
|
||||
} from "asc-web-components";
|
||||
import { Headline } from 'asc-web-common';
|
||||
import { Headline } from "asc-web-common";
|
||||
import { connect } from "react-redux";
|
||||
import {
|
||||
getSelectedGroup,
|
||||
getSelectionIds,
|
||||
getSelectionIds,
|
||||
getUserType,
|
||||
getGuestType,
|
||||
getGuestType,
|
||||
getUsersStatus,
|
||||
getInactiveUsers,
|
||||
getDeleteUsers
|
||||
@ -26,29 +26,39 @@ import {
|
||||
removeUser
|
||||
} from "../../../../../store/people/actions";
|
||||
import { deleteGroup } from "../../../../../store/group/actions";
|
||||
import { store, api, constants } from 'asc-web-common';
|
||||
import { InviteDialog, DeleteGroupUsersDialog } from '../../../../dialogs';
|
||||
import { store, constants } from "asc-web-common";
|
||||
import {
|
||||
InviteDialog,
|
||||
DeleteGroupUsersDialog,
|
||||
SendInviteDialog
|
||||
} from "../../../../dialogs";
|
||||
|
||||
const { isAdmin } = store.auth.selectors;
|
||||
const { resendUserInvites } = api.people;
|
||||
const { EmployeeStatus, EmployeeType } = constants;
|
||||
|
||||
const isRefetchPeople = true;
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
${props => props.isHeaderVisible && css`width: calc(100% + 76px);`}
|
||||
${props =>
|
||||
props.isHeaderVisible &&
|
||||
css`
|
||||
width: calc(100% + 76px);
|
||||
`}
|
||||
}
|
||||
|
||||
.group-button-menu-container {
|
||||
margin: 0 -16px;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
padding-bottom: 56px;
|
||||
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
& > div:first-child {
|
||||
${props => props.isArticlePinned && css`width: calc(100% - 240px);`}
|
||||
${props =>
|
||||
props.isArticlePinned &&
|
||||
css`
|
||||
width: calc(100% - 240px);
|
||||
`}
|
||||
position: absolute;
|
||||
top: 56px;
|
||||
z-index: 180;
|
||||
@ -85,6 +95,7 @@ const StyledContainer = styled.div`
|
||||
const SectionHeaderContent = props => {
|
||||
const [dialogVisible, setDialogVisible] = useState(false);
|
||||
const [deleteDialog, setDeleteDialog] = useState(false);
|
||||
const [sendInviteDialog, setSendInviteDialog] = useState(false);
|
||||
|
||||
const {
|
||||
isHeaderVisible,
|
||||
@ -142,16 +153,14 @@ const SectionHeaderContent = props => {
|
||||
toastr.success(t("SuccessChangeUserType"));
|
||||
}, [selectedUserIds, updateUserType, t]);
|
||||
|
||||
const onSentInviteAgain = useCallback(() => {
|
||||
resendUserInvites(selectedUserIds)
|
||||
.then(() => toastr.success(t('SuccessSendInvitation')))
|
||||
.catch(error => toastr.error(error));
|
||||
}, [selectedUserIds, t]);
|
||||
|
||||
const onDelete = useCallback(() =>
|
||||
setDeleteDialog(!deleteDialog), [deleteDialog]
|
||||
const onSentInviteAgain = useCallback(
|
||||
() => setSendInviteDialog(!sendInviteDialog),
|
||||
[sendInviteDialog]
|
||||
);
|
||||
|
||||
const onDelete = useCallback(() => setDeleteDialog(!deleteDialog), [
|
||||
deleteDialog
|
||||
]);
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
@ -168,12 +177,16 @@ const SectionHeaderContent = props => {
|
||||
onSelect: item => onSelect(item.key)
|
||||
},
|
||||
{
|
||||
label: t('ChangeToUser', { userCaption: settings.customNames.userCaption }),
|
||||
label: t("ChangeToUser", {
|
||||
userCaption: settings.customNames.userCaption
|
||||
}),
|
||||
disabled: userType,
|
||||
onClick: onSetEmployee
|
||||
},
|
||||
{
|
||||
label: t('ChangeToGuest', { guestCaption: settings.customNames.guestCaption }),
|
||||
label: t("ChangeToGuest", {
|
||||
guestCaption: settings.customNames.guestCaption
|
||||
}),
|
||||
disabled: guestType,
|
||||
onClick: onSetGuest
|
||||
},
|
||||
@ -242,8 +255,9 @@ const SectionHeaderContent = props => {
|
||||
history.push(`${settings.homepage}/group/create`);
|
||||
}, [history, settings]);
|
||||
|
||||
const onInvitationDialogClick = useCallback(() =>
|
||||
setDialogVisible(!dialogVisible), [dialogVisible]
|
||||
const onInvitationDialogClick = useCallback(
|
||||
() => setDialogVisible(!dialogVisible),
|
||||
[dialogVisible]
|
||||
);
|
||||
|
||||
const getContextOptionsPlus = useCallback(() => {
|
||||
@ -264,34 +278,49 @@ const SectionHeaderContent = props => {
|
||||
label: groupCaption,
|
||||
onClick: goToGroupCreate
|
||||
},
|
||||
{ key: 'separator', isSeparator: true },
|
||||
{ key: "separator", isSeparator: true },
|
||||
{
|
||||
key: "make-invitation-link",
|
||||
label: t("MakeInvitationLink"),
|
||||
onClick: onInvitationDialogClick
|
||||
}/* ,
|
||||
} /* ,
|
||||
{
|
||||
key: "send-invitation",
|
||||
label: t("SendInviteAgain"),
|
||||
onClick: onSentInviteAgain
|
||||
} */
|
||||
];
|
||||
}, [settings, t, goToEmployeeCreate, goToGuestCreate, goToGroupCreate, onInvitationDialogClick/* , onSentInviteAgain */]);
|
||||
}, [
|
||||
settings,
|
||||
t,
|
||||
goToEmployeeCreate,
|
||||
goToGuestCreate,
|
||||
goToGroupCreate,
|
||||
onInvitationDialogClick /* , onSentInviteAgain */
|
||||
]);
|
||||
|
||||
const isArticlePinned = window.localStorage.getItem('asc_article_pinned_key');
|
||||
const isArticlePinned = window.localStorage.getItem("asc_article_pinned_key");
|
||||
|
||||
return (
|
||||
<StyledContainer isHeaderVisible={isHeaderVisible} isArticlePinned={isArticlePinned}>
|
||||
{deleteDialog &&
|
||||
<StyledContainer
|
||||
isHeaderVisible={isHeaderVisible}
|
||||
isArticlePinned={isArticlePinned}
|
||||
>
|
||||
{deleteDialog && (
|
||||
<DeleteGroupUsersDialog
|
||||
visible={deleteDialog}
|
||||
onClose={onDelete}
|
||||
users={selection}
|
||||
filter={filter}
|
||||
settings={settings}
|
||||
history={history}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
{sendInviteDialog && (
|
||||
<SendInviteDialog
|
||||
visible={sendInviteDialog}
|
||||
onClose={onSentInviteAgain}
|
||||
users={selection}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isHeaderVisible ? (
|
||||
<div className="group-button-menu-container">
|
||||
@ -308,51 +337,63 @@ const SectionHeaderContent = props => {
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="header-container">
|
||||
{group ? (
|
||||
<>
|
||||
<Headline className='headline-header' type="content" truncate={true}>{group.name}</Headline>
|
||||
{isAdmin && (
|
||||
<div className="header-container">
|
||||
{group ? (
|
||||
<>
|
||||
<Headline
|
||||
className="headline-header"
|
||||
type="content"
|
||||
truncate={true}
|
||||
>
|
||||
{group.name}
|
||||
</Headline>
|
||||
{isAdmin && (
|
||||
<ContextMenuButton
|
||||
className="action-button"
|
||||
directionX="right"
|
||||
title={t("Actions")}
|
||||
iconName="VerticalDotsIcon"
|
||||
size={16}
|
||||
color="#A3A9AE"
|
||||
getData={getContextOptionsGroup}
|
||||
isDisabled={false}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Headline
|
||||
className="headline-header"
|
||||
truncate={true}
|
||||
type="content"
|
||||
>
|
||||
{settings.customNames.groupsCaption}
|
||||
</Headline>
|
||||
{isAdmin && (
|
||||
<>
|
||||
<ContextMenuButton
|
||||
className="action-button"
|
||||
directionX="right"
|
||||
title={t("Actions")}
|
||||
iconName="VerticalDotsIcon"
|
||||
iconName="PlusIcon"
|
||||
size={16}
|
||||
color="#A3A9AE"
|
||||
getData={getContextOptionsGroup}
|
||||
color="#657077"
|
||||
getData={getContextOptionsPlus}
|
||||
isDisabled={false}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Headline className='headline-header' truncate={true} type="content">{settings.customNames.groupsCaption}</Headline>
|
||||
{isAdmin && (
|
||||
<>
|
||||
<ContextMenuButton
|
||||
className="action-button"
|
||||
directionX="right"
|
||||
title={t("Actions")}
|
||||
iconName="PlusIcon"
|
||||
size={16}
|
||||
color="#657077"
|
||||
getData={getContextOptionsPlus}
|
||||
isDisabled={false}
|
||||
/>
|
||||
{dialogVisible &&
|
||||
<InviteDialog
|
||||
visible={dialogVisible}
|
||||
onClose={onInvitationDialogClick}
|
||||
onCloseButton={onInvitationDialogClick}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
{dialogVisible && (
|
||||
<InviteDialog
|
||||
visible={dialogVisible}
|
||||
onClose={onInvitationDialogClick}
|
||||
onCloseButton={onInvitationDialogClick}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -379,7 +420,10 @@ const mapStateToProps = state => {
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ updateUserStatus, updateUserType, fetchPeople, deleteGroup, removeUser }
|
||||
)(withTranslation()(withRouter(SectionHeaderContent)));
|
||||
export default connect(mapStateToProps, {
|
||||
updateUserStatus,
|
||||
updateUserType,
|
||||
fetchPeople,
|
||||
deleteGroup,
|
||||
removeUser
|
||||
})(withTranslation()(withRouter(SectionHeaderContent)));
|
||||
|
@ -78,6 +78,13 @@
|
||||
"UserControlsCommonResource":[
|
||||
"NotBeUndone"
|
||||
]
|
||||
},
|
||||
"SendInviteDialog":{
|
||||
"Resource": [
|
||||
"OKButton",
|
||||
"CancelButton",
|
||||
"SendInviteAgain"
|
||||
]
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
|
@ -195,7 +195,7 @@ export function getUserType(users) {
|
||||
}
|
||||
|
||||
export function getInactiveUsers(users) {
|
||||
const disabledStatus = users.filter(x => x.activationStatus === 2);
|
||||
const disabledStatus = users.filter(x => x.activationStatus === 2 && x.status === 1);
|
||||
return !disabledStatus.length;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user