From 70ab1f099aec8b4fda74e016a68a4288c396f5f6 Mon Sep 17 00:00:00 2001
From: Ramon Souza <contato@ramonsouza.com>
Date: Thu, 18 Mar 2021 13:13:57 -0300
Subject: [PATCH] show poll question in chat

---
 .../polls/server/handlers/pollPublished.js    |  3 --
 .../polls/server/handlers/sendPollChatMsg.js  | 14 +++++++-
 .../time-window-chat-item/component.jsx       |  2 ++
 .../time-window-chat-item/container.jsx       | 14 +++++++-
 .../message-chat-item/component.jsx           | 35 +++++++++++++++----
 5 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/bigbluebutton-html5/imports/api/polls/server/handlers/pollPublished.js b/bigbluebutton-html5/imports/api/polls/server/handlers/pollPublished.js
index e2f754c76c..22bc358a79 100644
--- a/bigbluebutton-html5/imports/api/polls/server/handlers/pollPublished.js
+++ b/bigbluebutton-html5/imports/api/polls/server/handlers/pollPublished.js
@@ -1,5 +1,4 @@
 import { check } from 'meteor/check';
-import removePoll from '../modifiers/removePoll';
 import setPublishedPoll from '../../../meetings/server/modifiers/setPublishedPoll';
 
 export default function pollPublished({ body }, meetingId) {
@@ -9,6 +8,4 @@ export default function pollPublished({ body }, meetingId) {
   check(pollId, String);
 
   setPublishedPoll(meetingId, true);
-
-  return removePoll(meetingId, pollId);
 }
diff --git a/bigbluebutton-html5/imports/api/polls/server/handlers/sendPollChatMsg.js b/bigbluebutton-html5/imports/api/polls/server/handlers/sendPollChatMsg.js
index 34101bf31f..9f4c934aac 100644
--- a/bigbluebutton-html5/imports/api/polls/server/handlers/sendPollChatMsg.js
+++ b/bigbluebutton-html5/imports/api/polls/server/handlers/sendPollChatMsg.js
@@ -1,4 +1,7 @@
 import addSystemMsg from '../../../group-chat-msg/server/modifiers/addSystemMsg';
+import Polls from '/imports/api/polls';
+import removePoll from '../modifiers/removePoll';
+import Logger from '/imports/startup/server/logger';
 
 export default function sendPollChatMsg({ body }, meetingId) {
   const { poll } = body;
@@ -11,8 +14,16 @@ export default function sendPollChatMsg({ body }, meetingId) {
 
   const { answers, numRespondents } = poll;
 
+  const pollData = Polls.findOne({ meetingId });
+
+  if (!pollData) {
+    Logger.error(`Attempted to send chat message of inexisting poll for meetingId: ${meetingId}`);
+    return false;
+  }
+
   let responded = 0;
-  let resultString = 'bbb-published-poll-\n';
+  let resultString = `bbb-published-poll-\n${pollData.question.split('<br/>').join('<br#>').split('\n').join('<br#>')}\n`;
+
   answers.map((item) => {
     responded += item.numVotes;
     return item;
@@ -35,5 +46,6 @@ export default function sendPollChatMsg({ body }, meetingId) {
     message: resultString,
   };
 
+  removePoll(meetingId, pollData.id);
   return addSystemMsg(meetingId, PUBLIC_GROUP_CHAT_ID, payload);
 }
diff --git a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/component.jsx
index 7ac4e74166..859ed751e8 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/component.jsx
@@ -194,6 +194,7 @@ class TimeWindowChatItem extends PureComponent {
       color,
       intl,
       isDefaultPoll,
+      extractPollQuestion,
       messages,
       scrollArea,
       chatAreaId,
@@ -236,6 +237,7 @@ class TimeWindowChatItem extends PureComponent {
               scrollArea={scrollArea}
               color={color}
               isDefaultPoll={isDefaultPoll(messages[0].text.replace('bbb-published-poll-<br/>', ''))}
+              extractPollQuestion={extractPollQuestion}
             />
           </div>
         </div>
diff --git a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/container.jsx b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/container.jsx
index 2971429b24..e7346b6541 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/container.jsx
@@ -9,8 +9,19 @@ const CHAT_CONFIG = Meteor.settings.public.chat;
 const SYSTEM_CHAT_TYPE = CHAT_CONFIG.type_system;
 const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
 
+const extractPollQuestion = (pollText) => {
+  if (!pollText) return {};
+
+  const pollQuestion = pollText.split('<br/>')[0];
+  pollText = pollText.replace(`${pollQuestion}<br/>`,'');
+
+  return { pollQuestion, pollText };
+};
+
 const isDefaultPoll = (pollText) => {
-  const pollValue = pollText.replace(/<br\/>|[ :|%\n\d+]/g, '');
+  const { pollQuestion, pollText: newPollText} = extractPollQuestion(pollText);
+
+  const pollValue = newPollText.replace(/<br\/>|[ :|%\n\d+]/g, '');
   switch (pollValue) {
     case 'A': case 'AB': case 'ABC': case 'ABCD':
     case 'ABCDE': case 'YesNo': case 'TrueFalse':
@@ -47,6 +58,7 @@ export default function TimeWindowChatItemContainer(props) {
         read: message.read,
         messages,
         isDefaultPoll,
+        extractPollQuestion,
         user,
         timestamp,
         systemMessage: messageId.startsWith(SYSTEM_CHAT_TYPE) || !sender,
diff --git a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/message-chat-item/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/message-chat-item/component.jsx
index 9438912c5b..40c94aa1db 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/message-chat-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/time-window-chat-item/message-chat-item/component.jsx
@@ -41,6 +41,10 @@ const intlMessages = defineMessages({
     id: 'app.polling.pollingTitle',
     description: 'heading for chat poll legend',
   },
+  pollQuestionTitle: {
+    id: 'app.polling.pollQuestionTitle',
+    description: 'title displayed before poll question',
+  },
 });
 
 class MessageChatItem extends PureComponent {
@@ -166,24 +170,33 @@ class MessageChatItem extends PureComponent {
       className,
       color,
       isDefaultPoll,
+      extractPollQuestion,
     } = this.props;
 
     const formatBoldBlack = s => s.bold().fontcolor('black');
 
+    // Sanitize. See: https://gist.github.com/sagewall/47164de600df05fb0f6f44d48a09c0bd
+    const sanitize = (value) => {
+      const div = document.createElement('div');
+      div.appendChild(document.createTextNode(value));
+      return div.innerHTML;
+    };
+
     let _text = text.replace('bbb-published-poll-<br/>', '');
 
+    const { pollQuestion, pollText: newPollText } = extractPollQuestion(_text);
+    _text = newPollText;
+
     if (!isDefaultPoll) {
       const entries = _text.split('<br/>');
       const options = [];
       _text = _text.split('<br#>').join('<br/>');
 
       entries.map((e) => {
-        // Sanitize. See: https://gist.github.com/sagewall/47164de600df05fb0f6f44d48a09c0bd
         e = e.split('<br#>').join('<br/>');
-        const div = document.createElement('div');
-        div.appendChild(document.createTextNode(e));
-        _text = _text.replace(e, div.innerHTML);
-        e = div.innerHTML;
+        const sanitizedEntry = sanitize(e);
+        _text = _text.replace(e, sanitizedEntry);
+        e = sanitizedEntry;
 
         options.push([e.slice(0, e.indexOf(':'))]);
         return e;
@@ -203,12 +216,22 @@ class MessageChatItem extends PureComponent {
       });
     }
 
+    if (isDefaultPoll) {
+      _text = formatBoldBlack(_text);
+    }
+
+    if (pollQuestion.trim() !== '') {
+      const sanitizedPollQuestion = sanitize(pollQuestion.split('<br#>').join(' '));
+
+      _text = `${formatBoldBlack(intl.formatMessage(intlMessages.pollQuestionTitle))}<br/>${sanitizedPollQuestion}<br/><br/>${_text}`;
+    }
+
     return (
       <p
         className={className}
         style={{ borderLeft: `3px ${color} solid` }}
         ref={(ref) => { this.text = ref; }}
-        dangerouslySetInnerHTML={{ __html: isDefaultPoll ? formatBoldBlack(_text) : _text }}
+        dangerouslySetInnerHTML={{ __html: _text }}
         data-test="chatPollMessageText"
       />
     );
-- 
GitLab