diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartCustomPollReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartCustomPollReqMsgHdlr.scala
index 0cba314262..755bfdc01c 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartCustomPollReqMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartCustomPollReqMsgHdlr.scala
@@ -29,7 +29,7 @@ trait StartCustomPollReqMsgHdlr extends RightsManagementTrait {
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
for {
- pvo <- Polls.handleStartCustomPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, msg.body.isMultipleChoice, msg.body.answers, liveMeeting)
+ pvo <- Polls.handleStartCustomPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, msg.body.isMultipleResponse, msg.body.answers, liveMeeting)
} yield {
broadcastEvent(msg, pvo)
}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartPollReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartPollReqMsgHdlr.scala
index 6a9210317f..704782e41d 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartPollReqMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/polls/StartPollReqMsgHdlr.scala
@@ -30,7 +30,7 @@ trait StartPollReqMsgHdlr extends RightsManagementTrait {
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
for {
- pvo <- Polls.handleStartPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, msg.body.isMultipleChoice, liveMeeting)
+ pvo <- Polls.handleStartPollReqMsg(state, msg.header.userId, msg.body.pollId, msg.body.pollType, msg.body.isMultipleResponse, liveMeeting)
} yield {
broadcastEvent(msg, pvo)
}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala
index 44dac73641..391a79c479 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/domain/Meeting2x.scala
@@ -73,12 +73,12 @@ case class MeetingStatus(startEndTimeStatus: StartEndTimeStatus, recordingStatus
case class Meeting2x(defaultProps: DefaultProps, meetingStatus: MeetingStatus)
case class SimpleAnswerOutVO(id: Int, key: String)
-case class SimplePollOutVO(id: String, isMultipleChoice: Boolean, answers: Array[SimpleAnswerOutVO])
+case class SimplePollOutVO(id: String, isMultipleResponse: Boolean, answers: Array[SimpleAnswerOutVO])
case class SimpleVoteOutVO(id: Int, key: String, numVotes: Int)
case class SimplePollResultOutVO(id: String, answers: Array[SimpleVoteOutVO], numRespondents: Int, numResponders: Int)
case class Responder(userId: String, name: String)
case class AnswerVO(id: Int, key: String, text: Option[String], responders: Option[Array[Responder]])
-case class QuestionVO(id: Int, questionType: String, isMultipleChoice: Boolean, questionText: Option[String], answers: Option[Array[AnswerVO]])
+case class QuestionVO(id: Int, questionType: String, isMultipleResponse: Boolean, questionText: Option[String], answers: Option[Array[AnswerVO]])
case class PollVO(id: String, questions: Array[QuestionVO], title: Option[String], started: Boolean, stopped: Boolean, showResult: Boolean)
case class UserVO(id: String, externalId: String, name: String, role: String,
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PollsMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PollsMsgs.scala
index aa6bfcdbd7..d1f5d518cf 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PollsMsgs.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PollsMsgs.scala
@@ -44,11 +44,11 @@ case class ShowPollResultReqMsgBody(requesterId: String, pollId: String)
object StartCustomPollReqMsg { val NAME = "StartCustomPollReqMsg" }
case class StartCustomPollReqMsg(header: BbbClientMsgHeader, body: StartCustomPollReqMsgBody) extends StandardMsg
-case class StartCustomPollReqMsgBody(requesterId: String, pollId: String, pollType: String, isMultipleChoice: Boolean, answers: Seq[String])
+case class StartCustomPollReqMsgBody(requesterId: String, pollId: String, pollType: String, isMultipleResponse: Boolean, answers: Seq[String])
object StartPollReqMsg { val NAME = "StartPollReqMsg" }
case class StartPollReqMsg(header: BbbClientMsgHeader, body: StartPollReqMsgBody) extends StandardMsg
-case class StartPollReqMsgBody(requesterId: String, pollId: String, pollType: String, isMultipleChoice: Boolean)
+case class StartPollReqMsgBody(requesterId: String, pollId: String, pollType: String, isMultipleResponse: Boolean)
object StopPollReqMsg { val NAME = "StopPollReqMsg" }
case class StopPollReqMsg(header: BbbClientMsgHeader, body: StopPollReqMsgBody) extends StandardMsg
diff --git a/bigbluebutton-html5/imports/api/polls/server/methods/startPoll.js b/bigbluebutton-html5/imports/api/polls/server/methods/startPoll.js
index cbad087e70..e4761abeec 100644
--- a/bigbluebutton-html5/imports/api/polls/server/methods/startPoll.js
+++ b/bigbluebutton-html5/imports/api/polls/server/methods/startPoll.js
@@ -2,7 +2,7 @@ import RedisPubSub from '/imports/startup/server/redis';
import { check } from 'meteor/check';
import { extractCredentials } from '/imports/api/common/server/helpers';
-export default function startPoll(pollType, pollId, isMultipleChoice, answers) {
+export default function startPoll(pollType, pollId, isMultipleResponse, answers) {
const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
@@ -17,7 +17,7 @@ export default function startPoll(pollType, pollId, isMultipleChoice, answers) {
requesterId: requesterUserId,
pollId: `${pollId}/${new Date().getTime()}`,
pollType,
- isMultipleChoice,
+ isMultipleResponse,
};
if (pollType === 'custom') {
diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js
index 28e9f2db79..f57608f0b8 100644
--- a/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js
+++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js
@@ -15,7 +15,7 @@ export default function addPoll(meetingId, requesterId, poll) {
key: String,
},
],
- isMultipleChoice: Boolean
+ isMultipleResponse: Boolean,
});
const userSelector = {
diff --git a/bigbluebutton-html5/imports/ui/components/poll/component.jsx b/bigbluebutton-html5/imports/ui/components/poll/component.jsx
index dfb518258f..f7a4c2a34d 100644
--- a/bigbluebutton-html5/imports/ui/components/poll/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/poll/component.jsx
@@ -86,10 +86,10 @@ const intlMessages = defineMessages({
id: 'app.poll.a5',
description: 'label for A / B / C / D / E poll',
},
- enableMultipleChoiceLabel : {
- id: 'app.poll.enableMultipleChoiceLabel',
+ enableMultipleResponseLabel: {
+ id: 'app.poll.enableMultipleResponseLabel',
description: 'label for checkbox to enable multiple choice',
- }
+ },
});
const CHAT_ENABLED = Meteor.settings.public.chat.enabled;
@@ -104,13 +104,13 @@ class Poll extends Component {
customPollReq: false,
isPolling: false,
customPollValues: [],
- isMultipleChoice: false,
+ isMultipleResponse: false,
};
this.inputEditor = [];
this.toggleCustomFields = this.toggleCustomFields.bind(this);
- this.toggleIsMultipleChoice = this.toggleIsMultipleChoice.bind(this);
+ this.toggleIsMultipleResponse = this.toggleIsMultipleResponse.bind(this);
this.renderQuickPollBtns = this.renderQuickPollBtns.bind(this);
this.renderCustomView = this.renderCustomView.bind(this);
this.renderInputFields = this.renderInputFields.bind(this);
@@ -166,16 +166,16 @@ class Poll extends Component {
return this.setState({ customPollReq: !customPollReq });
}
- toggleIsMultipleChoice() {
- const { isMultipleChoice } = this.state;
- return this.setState({ isMultipleChoice: !isMultipleChoice });
+ toggleIsMultipleResponse() {
+ const { isMultipleResponse } = this.state;
+ return this.setState({ isMultipleResponse: !isMultipleResponse });
}
renderQuickPollBtns() {
const {
isMeteorConnected, pollTypes, startPoll, intl,
} = this.props;
- const { isMultipleChoice } = this.state;
+ const { isMultipleResponse } = this.state;
const btns = pollTypes.map((type) => {
if (type === 'custom') return false;
@@ -195,7 +195,7 @@ class Poll extends Component {
key={_.uniqueId('quick-poll-')}
onClick={() => {
Session.set('pollInitiated', true);
- this.setState({ isPolling: true }, () => startPoll(type, isMultipleChoice));
+ this.setState({ isPolling: true }, () => startPoll(type, isMultipleResponse));
}}
/>);
});
@@ -205,7 +205,7 @@ class Poll extends Component {
renderCustomView() {
const { intl, startCustomPoll } = this.props;
- const { isMultipleChoice } = this.state;
+ const { isMultipleResponse } = this.state;
const isDisabled = _.compact(this.inputEditor).length < 1;
return (
@@ -215,7 +215,7 @@ class Poll extends Component {
onClick={() => {
if (this.inputEditor.length > 0) {
Session.set('pollInitiated', true);
- this.setState({ isPolling: true }, () => startCustomPoll('custom', isMultipleChoice, _.compact(this.inputEditor)));
+ this.setState({ isPolling: true }, () => startCustomPoll('custom', isMultipleResponse, _.compact(this.inputEditor)));
}
}}
label={intl.formatMessage(intlMessages.startCustomLabel)}
@@ -285,19 +285,19 @@ class Poll extends Component {
renderPollOptions() {
const { isMeteorConnected, intl } = this.props;
- const { customPollReq, isMultipleChoice } = this.state;
+ const { customPollReq, isMultipleResponse } = this.state;
return (
-
diff --git a/bigbluebutton-html5/imports/ui/components/poll/container.jsx b/bigbluebutton-html5/imports/ui/components/poll/container.jsx
index ffdf2dcf30..685c4c76d0 100644
--- a/bigbluebutton-html5/imports/ui/components/poll/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/poll/container.jsx
@@ -22,9 +22,9 @@ export default withTracker(() => {
const pollId = currentSlide ? currentSlide.id : PUBLIC_CHAT_KEY;
- const startPoll = (type, isMultipleChoice) => makeCall('startPoll', type, pollId, isMultipleChoice);
+ const startPoll = (type, isMultipleResponse) => makeCall('startPoll', type, pollId, isMultipleResponse);
- const startCustomPoll = (type, isMultipleChoice, answers) => makeCall('startPoll', type, pollId, isMultipleChoice, answers);
+ const startCustomPoll = (type, isMultipleResponse, answers) => makeCall('startPoll', type, pollId, isMultipleResponse, answers);
const stopPoll = () => makeCall('stopPoll');
diff --git a/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx b/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx
index cd0b5cb020..6207e91d7c 100644
--- a/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/poll/live-result/component.jsx
@@ -65,10 +65,10 @@ class LiveResult extends PureComponent {
if (responses) {
const response = responses.find(r => r.userId === user.userId);
if (response) {
- let answerKeys = [];
+ const answerKeys = [];
response.answerIds.forEach((answerId) => {
answerKeys.push(answers[answerId].key);
- })
+ });
answer = answerKeys.join(', ');
}
}
@@ -198,14 +198,14 @@ class LiveResult extends PureComponent {
onClick={() => {
Session.set('pollInitiated', false);
Service.publishPoll();
- const { answers, numRespondents } = currentPoll;
+ const { answers, numResponders } = currentPoll;
let responded = 0;
let resultString = 'bbb-published-poll-\n';
answers.map((item) => {
responded += item.numVotes;
return item;
- }).map((item) => {
- const numResponded = responded === numRespondents ? numRespondents : responded;
+ }).forEach((item) => {
+ const numResponded = numResponders || responded;
const pct = Math.round(item.numVotes / numResponded * 100);
const pctFotmatted = `${Number.isNaN(pct) ? 0 : pct}%`;
resultString += `${item.key}: ${item.numVotes || 0} | ${pctFotmatted}\n`;
diff --git a/bigbluebutton-html5/imports/ui/components/polling/component.jsx b/bigbluebutton-html5/imports/ui/components/polling/component.jsx
index 1383cded3a..4a00b40e60 100644
--- a/bigbluebutton-html5/imports/ui/components/polling/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/polling/component.jsx
@@ -4,9 +4,9 @@ import Button from '/imports/ui/components/button/component';
import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
import { defineMessages, injectIntl } from 'react-intl';
import cx from 'classnames';
+import { Meteor } from 'meteor/meteor';
import { styles } from './styles.scss';
import AudioService from '/imports/ui/components/audio/service';
-import {Meteor} from "meteor/meteor";
const intlMessages = defineMessages({
pollingTitleLabel: {
@@ -18,8 +18,8 @@ const intlMessages = defineMessages({
pollAnswerDesc: {
id: 'app.polling.pollAnswerDesc',
},
- pollSendLabel: {
- id: 'app.polling.pollSendLabel',
+ pollSubmitLabel: {
+ id: 'app.polling.pollSubmitLabel',
},
});
@@ -28,8 +28,8 @@ class Polling extends Component {
super(props);
this.state = {
- checkedAnswers: []
- }
+ checkedAnswers: [],
+ };
this.play = this.play.bind(this);
this.renderButtonAnswers = this.renderButtonAnswers.bind(this);
@@ -66,52 +66,52 @@ class Polling extends Component {
}
return (
+
+
);
- })
+ });
}
handleCheckboxChange(pollId, answerId) {
- const {checkedAnswers} = this.state
+ const { checkedAnswers } = this.state;
if (checkedAnswers.includes(answerId)) {
- checkedAnswers.splice(checkedAnswers.indexOf(answerId), 1)
+ checkedAnswers.splice(checkedAnswers.indexOf(answerId), 1);
} else {
- checkedAnswers.push(answerId)
+ checkedAnswers.push(answerId);
}
checkedAnswers.sort();
}
handleSubmit(pollId) {
- const {handleVote} = this.props;
- const {checkedAnswers} = this.state
- handleVote(pollId, checkedAnswers)
+ const { handleVote } = this.props;
+ const { checkedAnswers } = this.state;
+ handleVote(pollId, checkedAnswers);
}
renderCheckboxAnswers() {
@@ -132,48 +132,48 @@ class Polling extends Component {
}
return (
+
+
this.handleCheckboxChange(poll.pollId, pollAnswer.id)}
+ aria-labelledby={`pollAnswerLabel${pollAnswer.key}`}
+ aria-describedby={`pollAnswerDesc${pollAnswer.key}`}
+ />
+
+ {label}
+
-
this.handleCheckboxChange(poll.pollId, pollAnswer.id)}
- aria-labelledby={`pollAnswerLabel${pollAnswer.key}`}
- aria-describedby={`pollAnswerDesc${pollAnswer.key}`}
- />
-
- {label}
-
-
- {intl.formatMessage(intlMessages.pollAnswerLabel, { 0: label })}
-
-
- {intl.formatMessage(intlMessages.pollAnswerDesc, { 0: label })}
-
+ {intl.formatMessage(intlMessages.pollAnswerLabel, { 0: label })}
+
+ {intl.formatMessage(intlMessages.pollAnswerDesc, { 0: label })}
+
+
);
})}
this.handleSubmit(poll.pollId)}
+ disabled={!isMeteorConnected}
+ className={styles.pollingButton}
+ color="primary"
+ size="md"
+ label={intl.formatMessage(intlMessages.pollSubmitLabel)}
+ onClick={() => this.handleSubmit(poll.pollId)}
/>
- )
+ );
}
render() {
@@ -207,7 +207,7 @@ class Polling extends Component {
{intl.formatMessage(intlMessages.pollingTitleLabel)}
- {poll.isMultipleChoice ? this.renderCheckboxAnswers() : this.renderButtonAnswers()}
+ {poll.isMultipleResponse ? this.renderCheckboxAnswers() : this.renderButtonAnswers()}
);
diff --git a/bigbluebutton-html5/imports/ui/components/polling/service.js b/bigbluebutton-html5/imports/ui/components/polling/service.js
index e45d8c62b7..109715db55 100644
--- a/bigbluebutton-html5/imports/ui/components/polling/service.js
+++ b/bigbluebutton-html5/imports/ui/components/polling/service.js
@@ -31,7 +31,7 @@ const mapPolls = () => {
poll: {
answers: poll.answers,
pollId: poll.id,
- isMultipleChoice: poll.isMultipleChoice,
+ isMultipleResponse: poll.isMultipleResponse,
stackOptions,
},
pollExists: true,
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/poll/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/poll/component.jsx
index ae58d937a4..4c19c6d545 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/poll/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/poll/component.jsx
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import PollService from '/imports/ui/components/poll/service';
import { injectIntl, defineMessages } from 'react-intl';
import styles from './styles';
-import { prototype } from 'clipboard';
const intlMessages = defineMessages({
pollResultAria: {
@@ -66,7 +65,7 @@ class PollDrawComponent extends Component {
// rendering / rerendering the text objects
const { annotation } = this.props;
- const { points, result } = annotation;
+ const { points, result, numResponders } = annotation;
const { slideWidth, slideHeight, intl } = this.props;
// x1 and y1 - coordinates of the top left corner of the annotation
@@ -84,18 +83,14 @@ class PollDrawComponent extends Component {
const width = ((initialWidth - 0.001) / 100) * slideWidth;
const height = ((initialHeight - 0.001) / 100) * slideHeight;
- let votesTotal = 0;
- let maxNumVotes = 0;
const textArray = [];
// counting the total number of votes, finding the biggest number of votes
- result.reduce((previousValue, currentValue) => {
- votesTotal = previousValue + currentValue.numVotes;
- if (maxNumVotes < currentValue.numVotes) {
- maxNumVotes = currentValue.numVotes;
+ const maxNumVotes = result.reduce((previousValue, currentValue) => {
+ if (previousValue < currentValue.numVotes) {
+ return currentValue.numVotes;
}
-
- return votesTotal;
+ return previousValue;
}, 0);
// filling the textArray with data to display
@@ -129,11 +124,11 @@ class PollDrawComponent extends Component {
}
_tempArray.push(_result.key, `${_result.numVotes}`);
- if (votesTotal === 0) {
+ if (numResponders === 0) {
_tempArray.push('0%');
_tempArray.push(i);
} else {
- const percResult = (_result.numVotes / votesTotal) * 100;
+ const percResult = (_result.numVotes / numResponders) * 100;
_tempArray.push(`${Math.round(percResult)}%`);
_tempArray.push(i);
}
@@ -604,7 +599,7 @@ class PollDrawComponent extends Component {
const { prepareToDisplay, textArray } = this.state;
let ariaResultLabel = `${intl.formatMessage(intlMessages.pollResultAria)}: `;
- textArray.map((t, idx) => {
+ textArray.forEach((t, idx) => {
const pollLine = t.slice(0, -1);
ariaResultLabel += `${idx > 0 ? ' |' : ''} ${pollLine.join(' | ')}`;
});
diff --git a/bigbluebutton-html5/private/locales/de.json b/bigbluebutton-html5/private/locales/de.json
index d46d031d53..72d661daac 100644
--- a/bigbluebutton-html5/private/locales/de.json
+++ b/bigbluebutton-html5/private/locales/de.json
@@ -213,7 +213,7 @@
"app.presentationUploder.clearErrors": "Fehler löschen",
"app.presentationUploder.clearErrorsDesc": "Löscht fehlgeschlagene Präsentationsuploads",
"app.poll.pollPaneTitle": "Umfrage",
- "app.poll.enableMultipleChoiceLabel": "Multiple-Choice?",
+ "app.poll.enableMultipleResponseLabel": "Mehrere Antworten pro Teilnehmer zulassen?",
"app.poll.quickPollTitle": "Schnellumfrage",
"app.poll.hidePollDesc": "Versteckt das Umfragemenü",
"app.poll.customPollInstruction": "Um eine benutzerdefinierte Umfrage zu erstellen, wählen Sie die Schaltfläche unten und geben Sie Ihre Optionen ein.",
@@ -253,6 +253,7 @@
"app.polling.pollingTitle": "Umfrageoptionen",
"app.polling.pollAnswerLabel": "Umfrageantwort {0}",
"app.polling.pollAnswerDesc": "Diese Option auswählen für Umfrage {0}",
+ "app.polling.pollSubmitLabel": "Abgeben",
"app.failedMessage": "Es gibt Verbindungsprobleme mit dem Server.",
"app.downloadPresentationButton.label": "Ursprüngliche Version der Präsentation herunterladen",
"app.connectingMessage": "Verbinde...",
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index ffe02d1880..7b5ed61ba3 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -213,7 +213,7 @@
"app.presentationUploder.clearErrors": "Clear errors",
"app.presentationUploder.clearErrorsDesc": "Clears failed presentation uploads",
"app.poll.pollPaneTitle": "Polling",
- "app.poll.enableMultipleChoiceLabel": "Multiple response?",
+ "app.poll.enableMultipleResponseLabel": "Allow multiple answers per respondent?",
"app.poll.quickPollTitle": "Quick Poll",
"app.poll.hidePollDesc": "Hides the poll menu pane",
"app.poll.customPollInstruction": "To create a custom poll, select the button below and input your options.",
@@ -256,6 +256,7 @@
"app.polling.pollingTitle": "Polling options",
"app.polling.pollAnswerLabel": "Poll answer {0}",
"app.polling.pollAnswerDesc": "Select this option to vote for {0}",
+ "app.polling.pollSubmitLabel": "Submit",
"app.failedMessage": "Apologies, trouble connecting to the server.",
"app.downloadPresentationButton.label": "Download the original presentation",
"app.connectingMessage": "Connecting ...",