People.Client: added Invite dialog component
This commit is contained in:
parent
67007af5d5
commit
84c2f3faed
@ -7,12 +7,20 @@ import {
|
||||
DropDownItem,
|
||||
toastr
|
||||
} from "asc-web-components";
|
||||
import InviteDialog from './../../dialogs/Invite';
|
||||
import { isAdmin } from '../../../store/auth/selectors';
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
import { typeUser, typeGuest, department } from './../../../helpers/customNames';
|
||||
|
||||
class PureArticleMainButtonContent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dialogVisible: false,
|
||||
}
|
||||
}
|
||||
|
||||
onDropDownItemClick = (link) => {
|
||||
this.props.history.push(link);
|
||||
};
|
||||
@ -21,48 +29,57 @@ class PureArticleMainButtonContent extends React.Component {
|
||||
toastr.success(text);
|
||||
};
|
||||
|
||||
toggleDialogVisible = () => this.setState({ dialogVisible: !this.state.dialogVisible });
|
||||
|
||||
render() {
|
||||
console.log("People ArticleMainButtonContent render");
|
||||
const { isAdmin, settings, t } = this.props;
|
||||
return (
|
||||
isAdmin ?
|
||||
<MainButton
|
||||
isDisabled={false}
|
||||
isDropdown={true}
|
||||
text={t('Actions')}
|
||||
>
|
||||
<DropDownItem
|
||||
icon="CatalogEmployeeIcon"
|
||||
label={t('CustomNewEmployee', { typeUser })}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/create/user`)}
|
||||
<>
|
||||
<MainButton
|
||||
isDisabled={false}
|
||||
isDropdown={true}
|
||||
text={t('Actions')}
|
||||
>
|
||||
<DropDownItem
|
||||
icon="CatalogEmployeeIcon"
|
||||
label={t('CustomNewEmployee', { typeUser })}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/create/user`)}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="CatalogGuestIcon"
|
||||
label={t('CustomNewGuest', { typeGuest })}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/create/guest`)}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="CatalogDepartmentsIcon"
|
||||
label={t('CustomNewDepartment', { department })}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/group/create`)}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
icon="InvitationLinkIcon"
|
||||
label={t('InviteLinkTitle')}
|
||||
onClick={this.toggleDialogVisible}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="PlaneIcon"
|
||||
label={t('LblInviteAgain')}
|
||||
onClick={this.onNotImplementedClick.bind(this, "Invite again action")}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="ImportIcon"
|
||||
label={t('ImportPeople')}
|
||||
onClick={this.onNotImplementedClick.bind(this, "Import people action")}
|
||||
/>
|
||||
</MainButton>
|
||||
<InviteDialog
|
||||
visible={this.state.dialogVisible}
|
||||
onClose={this.toggleDialogVisible}
|
||||
onCloseButton={this.toggleDialogVisible}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="CatalogGuestIcon"
|
||||
label={t('CustomNewGuest', { typeGuest })}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/create/guest`)}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="CatalogDepartmentsIcon"
|
||||
label={t('CustomNewDepartment', { department })}
|
||||
onClick={this.onDropDownItemClick.bind(this, `${settings.homepage}/group/create`)}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
icon="InvitationLinkIcon"
|
||||
label={t('InviteLinkTitle')}
|
||||
onClick={this.onNotImplementedClick.bind(this, "Invitation link action")}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="PlaneIcon"
|
||||
label={t('LblInviteAgain')}
|
||||
onClick={this.onNotImplementedClick.bind(this, "Invite again action")}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon="ImportIcon"
|
||||
label={t('ImportPeople')}
|
||||
onClick={this.onNotImplementedClick.bind(this, "Import people action")}
|
||||
/>
|
||||
</MainButton>
|
||||
</>
|
||||
:
|
||||
<></>
|
||||
);
|
||||
|
@ -0,0 +1,57 @@
|
||||
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/Invite/{{lng}}/{{ns}}.json`
|
||||
}
|
||||
});
|
||||
} else if (process.env.NODE_ENV === "development") {
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require("./locales/en/translation.json")
|
||||
}
|
||||
};
|
||||
|
||||
newInstance.init({
|
||||
resources: resources,
|
||||
lng: 'en',
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === 'lowercase') return value.toLowerCase();
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default newInstance;
|
@ -0,0 +1,224 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from 'react-router';
|
||||
import {
|
||||
toastr,
|
||||
ModalDialog,
|
||||
Link,
|
||||
Checkbox,
|
||||
Button,
|
||||
Textarea,
|
||||
Text
|
||||
} from "asc-web-components";
|
||||
import { getInvitationLink, getShortenedLink } from '../../../store/profile/actions';
|
||||
import { withTranslation, I18nextProvider } from 'react-i18next';
|
||||
import i18n from './i18n';
|
||||
import { typeGuests } from './../../../helpers/customNames';
|
||||
import styled from 'styled-components'
|
||||
|
||||
const ModalDialogContainer = styled.div`
|
||||
.margin-text {
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.margin-link {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.margin-textarea {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.flex{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
`;
|
||||
|
||||
const textAreaName = 'link-textarea';
|
||||
|
||||
class PureInviteDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isGuest: false,
|
||||
peopleInvitationLink: '',
|
||||
guestInvitationLink: '',
|
||||
isLoading: true,
|
||||
isLinkShort: false
|
||||
}
|
||||
}
|
||||
|
||||
onCopyLinkToClipboard = () => {
|
||||
const { t } = this.props;
|
||||
const link = document.getElementsByName(textAreaName)[0];
|
||||
link.select();
|
||||
document.execCommand('copy');
|
||||
toastr.success(t('LinkCopySuccess'));
|
||||
window.getSelection().removeAllRanges();
|
||||
link.blur();
|
||||
};
|
||||
|
||||
onCheckedGuest = () => this.setState({ isGuest: !this.state.isGuest });
|
||||
|
||||
onGetShortenedLink = () => {
|
||||
this.setState({ isLoading: true });
|
||||
const { getShortenedLink } = this.props;
|
||||
|
||||
getShortenedLink(this.state.peopleInvitationLink)
|
||||
.then((res) => {
|
||||
// console.log("getShortInvitationLinkPeople success", res.data.response);
|
||||
this.setState({ peopleInvitationLink: res.data.response });
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("getShortInvitationLink error", e);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
|
||||
getShortenedLink(this.state.guestInvitationLink)
|
||||
.then((res) => {
|
||||
// console.log("getShortInvitationLinkGuest success", res.data.response);
|
||||
this.setState({
|
||||
guestInvitationLink: res.data.response,
|
||||
isLoading: false,
|
||||
isLinkShort: true
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("getShortInvitationLink error", e);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (!prevProps.visible && !prevState.peopleInvitationLink && !prevState.guestInvitationLink) {
|
||||
// console.log('INVITE DIALOG DidUpdate');
|
||||
const { getInvitationLink } = this.props;
|
||||
const isGuest = true;
|
||||
|
||||
getInvitationLink()
|
||||
.then((res) => {
|
||||
// console.log("getInvitationLinkPeople success", res.data.response);
|
||||
this.setState({
|
||||
peopleInvitationLink: res.data.response,
|
||||
isLoading: false
|
||||
});
|
||||
this.onCopyLinkToClipboard();
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("getInvitationLinkPeople error", e);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
|
||||
getInvitationLink(isGuest)
|
||||
.then((res) => {
|
||||
// console.log("getInvitationLinkGuest success", res.data.response);
|
||||
this.setState({ guestInvitationLink: res.data.response });
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("getInvitationLinkGuest error", e);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
onClickToCloseButton = () => this.props.onCloseButton && this.props.onCloseButton();
|
||||
|
||||
render() {
|
||||
console.log("InviteDialog render");
|
||||
const { t, visible, onClose } = this.props;
|
||||
const fakeSettings = { hasShortenService: false };
|
||||
|
||||
return (
|
||||
<ModalDialogContainer>
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
onClose={() => onClose && onClose()}
|
||||
|
||||
headerContent={t('InviteLinkTitle')}
|
||||
|
||||
bodyContent={(
|
||||
<>
|
||||
<Text.Body
|
||||
className='margin-text'
|
||||
as='p'>
|
||||
{t('HelpAnswerLinkInviteSettings')}
|
||||
</Text.Body>
|
||||
<Text.Body
|
||||
className='margin-text'
|
||||
as='p'>
|
||||
{t('InviteLinkValidInterval', { count: 7 })}
|
||||
</Text.Body>
|
||||
<div className='flex'>
|
||||
<div>
|
||||
<Link
|
||||
className='margin-link'
|
||||
type='action'
|
||||
isHovered={true}
|
||||
onClick={this.onCopyLinkToClipboard}
|
||||
>
|
||||
{t('CopyToClipboard')}
|
||||
</Link>
|
||||
{
|
||||
fakeSettings.hasShortenService && !this.state.isLinkShort &&
|
||||
<Link type='action'
|
||||
isHovered={true}
|
||||
onClick={this.onGetShortenedLink}
|
||||
>
|
||||
{t('GetShortenLink')}
|
||||
</Link>
|
||||
}
|
||||
</div>
|
||||
<Checkbox
|
||||
label={t('InviteUsersAsCollaborators', { typeGuests })}
|
||||
isChecked={this.state.isGuest}
|
||||
onChange={this.onCheckedGuest}
|
||||
/>
|
||||
</div>
|
||||
<Textarea
|
||||
className='margin-textarea'
|
||||
isReadOnly={true}
|
||||
isDisabled={this.state.isLoading}
|
||||
name={textAreaName}
|
||||
value={this.state.isGuest ? this.state.guestInvitationLink : this.state.peopleInvitationLink}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
footerContent={(
|
||||
<>
|
||||
<Button
|
||||
key="CloseBtn"
|
||||
label={this.state.isLoading ? t('LoadingProcessing') : t('CloseButton')}
|
||||
size="medium"
|
||||
primary={true}
|
||||
onClick={this.onClickToCloseButton}
|
||||
isLoading={this.state.isLoading}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
settings: state.auth.settings
|
||||
}
|
||||
}
|
||||
|
||||
const InviteDialogContainer = withTranslation()(PureInviteDialog);
|
||||
|
||||
const InviteDialog = (props) => <I18nextProvider i18n={i18n}><InviteDialogContainer {...props} /></I18nextProvider>;
|
||||
|
||||
InviteDialog.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onCloseButton: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, { getInvitationLink, getShortenedLink })(withRouter(InviteDialog));
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"InviteLinkTitle": "Invitation link",
|
||||
"HelpAnswerLinkInviteSettings": "Share the link to invite your colleagues to your portal.",
|
||||
"InviteLinkValidInterval": "This link is valid for {{ count }} day only.",
|
||||
"CopyToClipboard": "Copy the link",
|
||||
"CloseButton": "Close",
|
||||
"LinkCopySuccess": "Link has been copied to the clipboard",
|
||||
"GetShortenLink": "Get shortened link",
|
||||
"InviteUsersAsCollaborators": "Add users as {{typeGuests, lowercase}}",
|
||||
"LoadingProcessing": "Loading...",
|
||||
|
||||
"InviteLinkValidInterval_plural": "This link is valid for {{ count }} days only."
|
||||
}
|
@ -3,5 +3,6 @@ export const department = 'Department';
|
||||
export const position = 'Position';
|
||||
export const employedSinceDate = 'Employed since';
|
||||
export const typeGuest = 'Guest';
|
||||
export const typeGuests = 'Guests';
|
||||
export const typeUser = 'Employee';
|
||||
export const headOfDepartment = 'Head of Department';
|
||||
|
@ -9,6 +9,22 @@
|
||||
"ImportPeople"
|
||||
]
|
||||
},
|
||||
"dialogs": {
|
||||
"Invite": {
|
||||
"Resource": [
|
||||
"HelpAnswerLinkInviteSettings",
|
||||
"CopyToClipboard",
|
||||
"CloseButton",
|
||||
"GetShortenLink",
|
||||
"LoadingProcessing",
|
||||
"InviteUsersAsCollaborators",
|
||||
"InviteLinkTitle"
|
||||
],
|
||||
"ResourceJS": [
|
||||
"LinkCopySuccess"
|
||||
]
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
"Profile": {
|
||||
"Resource": [
|
||||
|
@ -31,7 +31,7 @@ export function employeeWrapperToMemberModel(profile) {
|
||||
const department = profile.groups ? profile.groups.map(group => group.id) : [];
|
||||
const worksFrom = profile.workFrom;
|
||||
|
||||
return {...profile, comment, department, worksFrom};
|
||||
return { ...profile, comment, department, worksFrom };
|
||||
}
|
||||
|
||||
export function fetchProfile(userName) {
|
||||
@ -56,8 +56,8 @@ export function fetchProfile(userName) {
|
||||
|
||||
export function createProfile(profile) {
|
||||
return (dispatch, getState) => {
|
||||
const {people} = getState();
|
||||
const {filter} = people;
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
const member = employeeWrapperToMemberModel(profile);
|
||||
let result;
|
||||
|
||||
@ -75,8 +75,8 @@ export function createProfile(profile) {
|
||||
|
||||
export function updateProfile(profile) {
|
||||
return (dispatch, getState) => {
|
||||
const {people} = getState();
|
||||
const {filter} = people;
|
||||
const { people } = getState();
|
||||
const { filter } = people;
|
||||
const member = employeeWrapperToMemberModel(profile);
|
||||
let result;
|
||||
|
||||
@ -112,4 +112,24 @@ export function updateAvatar(profileId, images) {
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export function getInvitationLink(isGuest = false) {
|
||||
return dispatch => {
|
||||
return api.getInvitationLink(isGuest)
|
||||
.then(res => {
|
||||
checkResponseError(res);
|
||||
return Promise.resolve(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getShortenedLink(link) {
|
||||
return dispatch => {
|
||||
return api.getShortenedLink(link)
|
||||
.then(res => {
|
||||
checkResponseError(res);
|
||||
return Promise.resolve(res);
|
||||
});
|
||||
}
|
||||
}
|
@ -152,6 +152,20 @@ export function getGroup(groupId) {
|
||||
: axios.get(`${API_URL}/group/${groupId}.json`);
|
||||
}
|
||||
|
||||
export function getInvitationLink(isGuest) {
|
||||
return IS_FAKE
|
||||
? fakeApi.getInvitationLink(isGuest)
|
||||
: isGuest
|
||||
? axios.get(`${API_URL}/portal/users/invite/2.json`)
|
||||
: axios.get(`${API_URL}/portal/users/invite/1.json`);
|
||||
}
|
||||
|
||||
export function getShortenedLink(link) {
|
||||
return IS_FAKE
|
||||
? fakeApi.getShortenedLink(link)
|
||||
: axios.put(`${API_URL}/portal/getshortenlink.json`, link);
|
||||
}
|
||||
|
||||
function CheckError(res) {
|
||||
if (res.data && res.data.error) {
|
||||
const error = res.data.error.message || "Unknown error has happened";
|
||||
|
@ -558,3 +558,13 @@ export function getGroup(groupId) {
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
export function getInvitationLink(isGuest) {
|
||||
return fakeResponse(isGuest
|
||||
? "guest invitation link"
|
||||
: "user invitation link");
|
||||
}
|
||||
|
||||
export function getShortenedLink(link) {
|
||||
return fakeResponse("SHORT LINK: " + link);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user