bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/poll/component.jsx

292 lines
8.0 KiB
React
Raw Normal View History

2018-09-15 01:50:18 +08:00
import React, { Component } from 'react';
import { Link } from 'react-router';
import Button from '/imports/ui/components/button/component';
import Icon from '/imports/ui/components/icon/component';
2018-09-24 06:20:20 +08:00
import { findDOMNode } from 'react-dom';
import { defineMessages, injectIntl } from 'react-intl';
import _ from 'lodash';
2018-09-15 01:50:18 +08:00
import { styles } from './styles.scss';
const intlMessages = defineMessages({
pollPaneTitle: {
id: 'app.poll.pollPaneTitle',
description: 'heading label for the poll menu',
},
hidePollDesc: {
id: 'app.poll.hidePollDesc',
description: 'aria label description for hide poll button',
},
customPollLabel: {
id: 'app.poll.customPollLabel',
description: 'label for custom poll button',
},
startCustomLabel: {
id: 'app.poll.startCustomLabel',
description: 'label for button to start custom poll',
},
customPollInstruction: {
id: 'app.poll.customPollInstruction',
description: 'instructions for using custom poll',
},
quickPollInstruction: {
id: 'app.poll.quickPollInstruction',
description: 'instructions for using pre configured polls',
},
2018-09-25 06:43:54 +08:00
activePollInstruction: {
id: 'app.poll.activePollInstruction',
description: 'instructions displayed when a poll is active',
},
publishLabel: {
id: 'app.poll.publishLabel',
description: 'label for the publish button',
},
backLabel: {
id: 'app.poll.backLabel',
description: 'label for the return to poll options button',
},
customPlaceholder: {
id: 'app.poll.customPlaceholder',
description: 'custom poll input field placeholder text',
},
truefalse: {
id: 'app.poll.truefalse',
description: 'label for true / false poll',
},
yesno: {
id: 'app.poll.yesno',
description: 'label for Yes / No poll',
},
ab: {
id: 'app.poll.ab',
description: 'label for A / B poll',
},
abc: {
id: 'app.poll.abc',
description: 'label for A / B / C poll',
},
abcd: {
id: 'app.poll.abcd',
description: 'label for A / B / C / D poll',
},
abcde: {
id: 'app.poll.abcde',
description: 'label for A / B / C / D / E poll',
},
});
2018-10-03 07:59:45 +08:00
const MAX_CUSTOM_FIELDS = Meteor.settings.public.poll.max_custom;
2018-09-15 01:50:18 +08:00
class Poll extends Component {
constructor(props) {
super(props);
this.state = {
customPollReq: false,
2018-09-25 06:43:54 +08:00
isPolling: false,
2018-09-15 01:50:18 +08:00
};
this.pollOptions = [];
2018-09-15 01:50:18 +08:00
this.toggleCustomFields = this.toggleCustomFields.bind(this);
this.renderQuickPollBtns = this.renderQuickPollBtns.bind(this);
2018-09-24 06:20:20 +08:00
this.renderInputFields = this.renderInputFields.bind(this);
this.validateInputField = this.validateInputField.bind(this);
this.nonPresenterRedirect = this.nonPresenterRedirect.bind(this);
2018-09-24 06:20:20 +08:00
this.getInputFields = this.getInputFields.bind(this);
}
componentWillMount() {
this.nonPresenterRedirect();
}
2018-09-24 06:20:20 +08:00
componentDidUpdate(prevProps, prevState) {
this.nonPresenterRedirect();
}
2018-09-24 06:20:20 +08:00
nonPresenterRedirect() {
const { currentUser, router } = this.props;
if (!currentUser.presenter) return router.push('/users');
}
2018-09-24 06:20:20 +08:00
getInputFields() {
const { intl } = this.props;
2018-09-24 06:20:20 +08:00
const items = [];
2018-10-03 07:59:45 +08:00
for (let i = 0; i < MAX_CUSTOM_FIELDS; i++) {
2018-09-24 06:20:20 +08:00
items.push(<input
key={_.uniqueId('custom-poll-')}
placeholder={intl.formatMessage(intlMessages.customPlaceholder)}
2018-09-24 06:20:20 +08:00
className={styles.input}
ref={(node) => { this[`pollInput${i}`] = node; }}
onChange={() => this.validateInputField(this[`pollInput${i}`])}
data-index={i}
/>);
}
return items;
}
2018-09-24 06:20:20 +08:00
validateInputField(ref) {
2018-10-03 04:45:41 +08:00
// This regex will replace any instance of 2 or more consecutive white spaces
// with a single white space character.
2018-09-24 06:20:20 +08:00
const option = ref.value.replace(/\s{2,}/g, ' ').trim();
const index = ref.getAttribute('data-index');
2018-09-24 06:20:20 +08:00
this.pollOptions[index] = option === '' ? '' : option;
2018-09-24 06:20:20 +08:00
return _.compact(this.pollOptions).length > 1
? findDOMNode(this.startPollBtn).setAttribute('aria-disabled', 'false')
: findDOMNode(this.startPollBtn).setAttribute('aria-disabled', 'true');
2018-09-15 01:50:18 +08:00
}
toggleCustomFields() {
const { customPollReq } = this.state;
2018-09-24 06:20:20 +08:00
this.pollOptions = [];
return customPollReq
? this.setState({ customPollReq: false })
: this.setState({ customPollReq: true });
}
renderQuickPollBtns() {
const { pollTypes, startPoll, intl } = this.props;
2018-09-24 06:20:20 +08:00
const btns = pollTypes.reduce((arr, type) => {
if (type === 'custom') return arr;
let label = '';
2018-09-24 06:20:20 +08:00
if (type === 'YN') label = intl.formatMessage(intlMessages.yesno);
if (type === 'TF') label = intl.formatMessage(intlMessages.truefalse);
if (type === 'A-2') label = intl.formatMessage(intlMessages.ab);
if (type === 'A-3') label = intl.formatMessage(intlMessages.abc);
if (type === 'A-4') label = intl.formatMessage(intlMessages.abcd);
if (type === 'A-5') label = intl.formatMessage(intlMessages.abcde);
arr.push(<Button
label={label}
color="default"
className={styles.pollBtn}
key={_.uniqueId('quick-poll-')}
2018-09-25 06:43:54 +08:00
onClick={() => {
this.setState({ isPolling: true }, () => startPoll(type));
}}
/>);
2018-09-24 06:20:20 +08:00
return arr;
}, []);
return btns;
2018-09-15 01:50:18 +08:00
}
2018-09-24 06:20:20 +08:00
renderInputFields() {
const { intl, startCustomPoll } = this.props;
return (
2018-09-24 06:20:20 +08:00
<div className={styles.customInputWrapper}>
{this.getInputFields()}
<Button
2018-09-24 06:20:20 +08:00
onClick={() => {
if (_.compact(this.pollOptions).length > 1) {
2018-09-25 06:43:54 +08:00
this.setState({ isPolling: true }, () => startCustomPoll('custom', _.compact(this.pollOptions)));
2018-09-24 06:20:20 +08:00
}
}}
label={intl.formatMessage(intlMessages.startCustomLabel)}
2018-09-24 06:20:20 +08:00
color="primary"
ref={node => this.startPollBtn = node}
aria-disabled
className={styles.btn}
/>
</div>
);
2018-09-15 01:50:18 +08:00
}
2018-09-25 06:43:54 +08:00
renderActivePollOptions() {
const {
intl, router, publishPoll, stopPoll,
} = this.props;
return (
<div>
<div className={styles.instructions}>{intl.formatMessage(intlMessages.activePollInstruction)}</div>
<Button
onClick={() => {
publishPoll();
router.push('/users');
2018-09-25 06:43:54 +08:00
}}
label={intl.formatMessage(intlMessages.publishLabel)}
color="primary"
className={styles.btn}
/>
<Button
onClick={() => {
stopPoll();
this.setState({ isPolling: false });
}}
label={intl.formatMessage(intlMessages.backLabel)}
color="default"
className={styles.btn}
/>
</div>
);
}
renderPollOptions() {
const { intl } = this.props;
const { customPollReq } = this.state;
2018-09-15 01:50:18 +08:00
return (
2018-09-24 06:20:20 +08:00
<div>
<div className={styles.instructions}>
{intl.formatMessage(intlMessages.quickPollInstruction)}
2018-09-15 01:50:18 +08:00
</div>
<div className={styles.grid}>
{this.renderQuickPollBtns()}
</div>
<div className={styles.instructions}>
{intl.formatMessage(intlMessages.customPollInstruction)}
</div>
<Button
className={styles.customBtn}
color="default"
onClick={this.toggleCustomFields}
label={intl.formatMessage(intlMessages.customPollLabel)}
/>
2018-09-24 06:20:20 +08:00
{!customPollReq ? null : this.renderInputFields()}
2018-09-15 01:50:18 +08:00
</div>
);
}
2018-09-25 06:43:54 +08:00
render() {
const {
intl, stopPoll,
} = this.props;
return (
<div>
<header className={styles.header}>
<Link
to="/users"
role="button"
aria-label={intl.formatMessage(intlMessages.hidePollDesc)}
onClick={() => {
if (this.state.isPolling) {
stopPoll();
this.setState({ isPolling: false });
}
}}
>
<Icon iconName="left_arrow" />{intl.formatMessage(intlMessages.pollPaneTitle)}
</Link>
</header>
{
this.state.isPolling ? this.renderActivePollOptions() : this.renderPollOptions()
}
</div>
);
}
2018-09-15 01:50:18 +08:00
}
export default injectIntl(Poll);