2020-06-03 03:47:26 +08:00
|
|
|
import React, { PureComponent } from 'react';
|
2018-01-23 00:49:22 +08:00
|
|
|
import PropTypes from 'prop-types';
|
2017-12-15 03:03:34 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
2018-11-05 23:48:57 +08:00
|
|
|
import { Meteor } from 'meteor/meteor';
|
2018-05-09 00:30:00 +08:00
|
|
|
import Auth from '/imports/ui/services/auth';
|
2017-12-12 21:08:43 +08:00
|
|
|
import Button from '/imports/ui/components/button/component';
|
2020-10-08 17:15:05 +08:00
|
|
|
import allowRedirectToLogoutURL from './service';
|
2018-09-14 02:09:30 +08:00
|
|
|
import getFromUserSettings from '/imports/ui/services/users-settings';
|
2018-11-21 04:13:34 +08:00
|
|
|
import logoutRouteHandler from '/imports/utils/logoutRouteHandler';
|
2018-05-09 00:30:00 +08:00
|
|
|
import Rating from './rating/component';
|
2018-01-31 00:12:05 +08:00
|
|
|
import { styles } from './styles';
|
2019-03-01 05:55:38 +08:00
|
|
|
import logger from '/imports/startup/client/logger';
|
2019-11-06 05:16:34 +08:00
|
|
|
import Users from '/imports/api/users';
|
2020-06-03 03:47:26 +08:00
|
|
|
import AudioManager from '/imports/ui/services/audio-manager';
|
2020-09-14 23:21:11 +08:00
|
|
|
import { meetingIsBreakout } from '/imports/ui/components/app/service';
|
2018-11-05 23:48:57 +08:00
|
|
|
|
2017-12-15 03:03:34 +08:00
|
|
|
const intlMessage = defineMessages({
|
|
|
|
410: {
|
|
|
|
id: 'app.meeting.ended',
|
|
|
|
description: 'message when meeting is ended',
|
|
|
|
},
|
|
|
|
403: {
|
2018-01-16 04:59:09 +08:00
|
|
|
id: 'app.error.removed',
|
|
|
|
description: 'Message to display when user is removed from the conference',
|
2017-12-15 03:03:34 +08:00
|
|
|
},
|
2018-05-10 02:07:40 +08:00
|
|
|
430: {
|
|
|
|
id: 'app.error.meeting.ended',
|
|
|
|
description: 'user logged conference',
|
|
|
|
},
|
2018-11-05 23:48:57 +08:00
|
|
|
'acl-not-allowed': {
|
|
|
|
id: 'app.error.removed',
|
|
|
|
description: 'Message to display when user is removed from the conference',
|
|
|
|
},
|
2017-12-15 03:03:34 +08:00
|
|
|
messageEnded: {
|
|
|
|
id: 'app.meeting.endedMessage',
|
|
|
|
description: 'message saying to go back to home screen',
|
|
|
|
},
|
|
|
|
buttonOkay: {
|
2017-12-18 18:53:37 +08:00
|
|
|
id: 'app.meeting.endNotification.ok.label',
|
2017-12-15 03:03:34 +08:00
|
|
|
description: 'label okay for button',
|
|
|
|
},
|
2018-05-09 00:30:00 +08:00
|
|
|
title: {
|
|
|
|
id: 'app.feedback.title',
|
|
|
|
description: 'title for feedback screen',
|
|
|
|
},
|
|
|
|
subtitle: {
|
|
|
|
id: 'app.feedback.subtitle',
|
|
|
|
description: 'subtitle for feedback screen',
|
|
|
|
},
|
|
|
|
textarea: {
|
|
|
|
id: 'app.feedback.textarea',
|
|
|
|
description: 'placeholder for textarea',
|
|
|
|
},
|
|
|
|
confirmDesc: {
|
|
|
|
id: 'app.leaveConfirmation.confirmDesc',
|
|
|
|
description: 'adds context to confim option',
|
|
|
|
},
|
|
|
|
sendLabel: {
|
|
|
|
id: 'app.feedback.sendFeedback',
|
|
|
|
description: 'send feedback button label',
|
|
|
|
},
|
|
|
|
sendDesc: {
|
|
|
|
id: 'app.feedback.sendFeedbackDesc',
|
|
|
|
description: 'adds context to send feedback option',
|
|
|
|
},
|
2019-03-14 22:15:30 +08:00
|
|
|
duplicate_user_in_meeting_eject_reason: {
|
|
|
|
id: 'app.meeting.logout.duplicateUserEjectReason',
|
|
|
|
description: 'message for duplicate users',
|
|
|
|
},
|
2019-03-14 21:25:07 +08:00
|
|
|
not_enough_permission_eject_reason: {
|
2019-03-14 22:15:30 +08:00
|
|
|
id: 'app.meeting.logout.permissionEjectReason',
|
2019-03-14 21:25:07 +08:00
|
|
|
description: 'message for whom was kicked by doing something without permission',
|
|
|
|
},
|
2019-03-13 02:02:52 +08:00
|
|
|
user_requested_eject_reason: {
|
2019-03-14 22:15:30 +08:00
|
|
|
id: 'app.meeting.logout.ejectedFromMeeting',
|
2019-03-13 02:02:52 +08:00
|
|
|
description: 'message when the user is removed by someone',
|
|
|
|
},
|
2019-03-14 22:15:30 +08:00
|
|
|
validate_token_failed_eject_reason: {
|
|
|
|
id: 'app.meeting.logout.validateTokenFailedEjectReason',
|
|
|
|
description: 'invalid auth token',
|
|
|
|
},
|
|
|
|
user_inactivity_eject_reason: {
|
|
|
|
id: 'app.meeting.logout.userInactivityEjectReason',
|
|
|
|
description: 'message for whom was kicked by inactivity',
|
|
|
|
},
|
2017-12-15 03:03:34 +08:00
|
|
|
});
|
|
|
|
|
2018-01-23 00:49:22 +08:00
|
|
|
const propTypes = {
|
|
|
|
intl: PropTypes.shape({
|
|
|
|
formatMessage: PropTypes.func.isRequired,
|
|
|
|
}).isRequired,
|
|
|
|
code: PropTypes.string.isRequired,
|
2020-08-03 20:44:21 +08:00
|
|
|
reason: PropTypes.string.isRequired,
|
2018-01-23 00:49:22 +08:00
|
|
|
};
|
|
|
|
|
2020-06-03 03:47:26 +08:00
|
|
|
class MeetingEnded extends PureComponent {
|
2018-05-09 00:30:00 +08:00
|
|
|
static getComment() {
|
|
|
|
const textarea = document.getElementById('feedbackComment');
|
|
|
|
const comment = textarea.value;
|
|
|
|
return comment;
|
|
|
|
}
|
2019-01-15 05:39:03 +08:00
|
|
|
|
2018-05-09 00:30:00 +08:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
selected: 0,
|
2020-10-08 17:15:05 +08:00
|
|
|
dispatched: false,
|
2018-05-09 00:30:00 +08:00
|
|
|
};
|
2019-11-06 05:16:34 +08:00
|
|
|
|
|
|
|
const user = Users.findOne({ userId: Auth.userID });
|
|
|
|
if (user) {
|
|
|
|
this.localUserRole = user.role;
|
|
|
|
}
|
|
|
|
|
2018-05-09 00:30:00 +08:00
|
|
|
this.setSelectedStar = this.setSelectedStar.bind(this);
|
2020-10-08 17:15:05 +08:00
|
|
|
this.confirmRedirect = this.confirmRedirect.bind(this);
|
2018-05-09 00:30:00 +08:00
|
|
|
this.sendFeedback = this.sendFeedback.bind(this);
|
2020-10-08 17:15:05 +08:00
|
|
|
this.shouldShowFeedback = this.shouldShowFeedback.bind(this);
|
2018-11-05 23:48:57 +08:00
|
|
|
|
2020-06-03 03:47:26 +08:00
|
|
|
AudioManager.exitAudio();
|
2018-11-05 23:48:57 +08:00
|
|
|
Meteor.disconnect();
|
|
|
|
}
|
|
|
|
|
2018-05-09 00:30:00 +08:00
|
|
|
setSelectedStar(starNumber) {
|
|
|
|
this.setState({
|
|
|
|
selected: starNumber,
|
|
|
|
});
|
|
|
|
}
|
2018-05-11 04:23:17 +08:00
|
|
|
|
2020-10-08 17:15:05 +08:00
|
|
|
shouldShowFeedback() {
|
|
|
|
const { dispatched } = this.state;
|
|
|
|
return getFromUserSettings('bbb_ask_for_feedback_on_logout', Meteor.settings.public.app.askForFeedbackOnLogout) && !dispatched;
|
|
|
|
}
|
|
|
|
|
|
|
|
confirmRedirect() {
|
2018-05-09 00:30:00 +08:00
|
|
|
const {
|
|
|
|
selected,
|
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
if (selected <= 0) {
|
2020-09-14 23:21:11 +08:00
|
|
|
if (meetingIsBreakout()) window.close();
|
2020-10-08 17:15:05 +08:00
|
|
|
if (allowRedirectToLogoutURL()) logoutRouteHandler();
|
2018-05-09 00:30:00 +08:00
|
|
|
}
|
2020-10-08 17:15:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
sendFeedback() {
|
|
|
|
const {
|
|
|
|
selected,
|
|
|
|
} = this.state;
|
2018-05-09 00:30:00 +08:00
|
|
|
|
2019-07-12 04:51:09 +08:00
|
|
|
const { fullname } = Auth.credentials;
|
|
|
|
|
2018-05-09 00:30:00 +08:00
|
|
|
const message = {
|
|
|
|
rating: selected,
|
|
|
|
userId: Auth.userID,
|
2019-07-12 04:51:09 +08:00
|
|
|
userName: fullname,
|
2018-05-11 04:23:17 +08:00
|
|
|
authToken: Auth.token,
|
2018-05-09 00:30:00 +08:00
|
|
|
meetingId: Auth.meetingID,
|
|
|
|
comment: MeetingEnded.getComment(),
|
2019-11-06 05:16:34 +08:00
|
|
|
userRole: this.localUserRole,
|
2018-05-09 00:30:00 +08:00
|
|
|
};
|
2020-11-19 04:31:36 +08:00
|
|
|
const url = './feedback';
|
2018-05-10 02:07:40 +08:00
|
|
|
const options = {
|
|
|
|
method: 'POST',
|
|
|
|
body: JSON.stringify(message),
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2019-03-01 05:55:38 +08:00
|
|
|
// client logger
|
2019-06-29 05:45:50 +08:00
|
|
|
logger.info({ logCode: 'feedback_functionality', extraInfo: { feedback: message } }, 'Feedback component');
|
2019-03-01 05:55:38 +08:00
|
|
|
|
2020-10-08 17:15:05 +08:00
|
|
|
this.setState({
|
|
|
|
dispatched: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (allowRedirectToLogoutURL()) {
|
|
|
|
const FEEDBACK_WAIT_TIME = 500;
|
|
|
|
setTimeout(() => {
|
|
|
|
fetch(url, options)
|
|
|
|
.then(() => {
|
|
|
|
logoutRouteHandler();
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
logoutRouteHandler();
|
|
|
|
});
|
|
|
|
}, FEEDBACK_WAIT_TIME);
|
|
|
|
}
|
2018-05-09 00:30:00 +08:00
|
|
|
}
|
|
|
|
|
2020-10-08 17:15:05 +08:00
|
|
|
renderNoFeedback() {
|
2020-10-21 22:48:02 +08:00
|
|
|
const { intl, code, reason } = this.props;
|
2020-10-08 17:15:05 +08:00
|
|
|
|
2020-10-21 22:48:02 +08:00
|
|
|
logger.info({ logCode: 'meeting_ended_code', extraInfo: { endedCode: code, reason } }, 'Meeting ended component, no feedback configured');
|
2020-10-08 17:15:05 +08:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className={styles.parent}>
|
|
|
|
<div className={styles.modal}>
|
|
|
|
<div className={styles.content}>
|
|
|
|
<h1 className={styles.title} data-test="meetingEndedModalTitle">
|
|
|
|
{
|
|
|
|
intl.formatMessage(intlMessage[code] || intlMessage[430])
|
|
|
|
}
|
|
|
|
</h1>
|
|
|
|
{!allowRedirectToLogoutURL() ? null : (
|
|
|
|
<div>
|
|
|
|
<div className={styles.text}>
|
|
|
|
{intl.formatMessage(intlMessage.messageEnded)}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<Button
|
|
|
|
color="primary"
|
|
|
|
onClick={this.confirmRedirect}
|
|
|
|
className={styles.button}
|
|
|
|
label={intl.formatMessage(intlMessage.buttonOkay)}
|
|
|
|
description={intl.formatMessage(intlMessage.confirmDesc)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderFeedback() {
|
2020-10-21 22:48:02 +08:00
|
|
|
const { intl, code, reason } = this.props;
|
2019-01-15 05:39:03 +08:00
|
|
|
const {
|
|
|
|
selected,
|
2020-10-08 17:15:05 +08:00
|
|
|
dispatched,
|
2019-01-15 05:39:03 +08:00
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
const noRating = selected <= 0;
|
2019-03-20 03:55:12 +08:00
|
|
|
|
2020-10-21 22:48:02 +08:00
|
|
|
logger.info({ logCode: 'meeting_ended_code', extraInfo: { endedCode: code, reason } }, 'Meeting ended component, feedback allowed');
|
2019-03-20 03:55:12 +08:00
|
|
|
|
2018-01-23 00:49:22 +08:00
|
|
|
return (
|
|
|
|
<div className={styles.parent}>
|
2020-05-15 22:48:28 +08:00
|
|
|
<div className={styles.modal} data-test="meetingEndedModal">
|
2018-01-23 00:49:22 +08:00
|
|
|
<div className={styles.content}>
|
2020-05-15 22:48:28 +08:00
|
|
|
<h1 className={styles.title}>
|
2019-03-20 02:48:54 +08:00
|
|
|
{
|
2020-08-03 20:44:21 +08:00
|
|
|
intl.formatMessage(intlMessage[reason] || intlMessage[430])
|
2019-03-20 02:48:54 +08:00
|
|
|
}
|
|
|
|
</h1>
|
2018-01-23 00:49:22 +08:00
|
|
|
<div className={styles.text}>
|
2020-10-08 17:15:05 +08:00
|
|
|
{this.shouldShowFeedback()
|
2018-05-09 00:30:00 +08:00
|
|
|
? intl.formatMessage(intlMessage.subtitle)
|
|
|
|
: intl.formatMessage(intlMessage.messageEnded)}
|
2018-01-23 00:49:22 +08:00
|
|
|
</div>
|
2020-10-08 17:15:05 +08:00
|
|
|
|
|
|
|
{this.shouldShowFeedback() ? (
|
2020-05-15 22:48:28 +08:00
|
|
|
<div data-test="rating">
|
2018-05-09 00:30:00 +08:00
|
|
|
<Rating
|
|
|
|
total="5"
|
|
|
|
onRate={this.setSelectedStar}
|
|
|
|
/>
|
2019-01-15 05:39:03 +08:00
|
|
|
{!noRating ? (
|
|
|
|
<textarea
|
|
|
|
rows="5"
|
|
|
|
id="feedbackComment"
|
|
|
|
className={styles.textarea}
|
|
|
|
placeholder={intl.formatMessage(intlMessage.textarea)}
|
|
|
|
aria-describedby="textareaDesc"
|
|
|
|
/>
|
|
|
|
) : null}
|
2018-05-09 00:30:00 +08:00
|
|
|
</div>
|
|
|
|
) : null }
|
2020-10-08 17:15:05 +08:00
|
|
|
{noRating && allowRedirectToLogoutURL() ? (
|
|
|
|
<Button
|
|
|
|
color="primary"
|
|
|
|
onClick={this.confirmRedirect}
|
|
|
|
className={styles.button}
|
|
|
|
label={intl.formatMessage(intlMessage.buttonOkay)}
|
|
|
|
description={intl.formatMessage(intlMessage.confirmDesc)}
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
{!noRating && !dispatched ? (
|
|
|
|
<Button
|
|
|
|
color="primary"
|
|
|
|
onClick={this.sendFeedback}
|
|
|
|
className={styles.button}
|
|
|
|
label={intl.formatMessage(intlMessage.sendLabel)}
|
|
|
|
description={intl.formatMessage(intlMessage.sendDesc)}
|
|
|
|
/>
|
|
|
|
) : null}
|
2018-01-23 00:49:22 +08:00
|
|
|
</div>
|
2017-12-12 21:08:43 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
2018-01-23 00:49:22 +08:00
|
|
|
);
|
|
|
|
}
|
2020-10-08 17:15:05 +08:00
|
|
|
|
|
|
|
render() {
|
|
|
|
if (this.shouldShowFeedback()) return this.renderFeedback();
|
|
|
|
return this.renderNoFeedback();
|
|
|
|
}
|
2018-01-23 00:49:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
MeetingEnded.propTypes = propTypes;
|
2017-12-12 21:08:43 +08:00
|
|
|
|
2018-10-04 00:14:10 +08:00
|
|
|
export default injectIntl(MeetingEnded);
|