From 84e15fa14830124d8dba775ea6836cfbd94854c5 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 15 Feb 2022 08:52:51 +0000 Subject: [PATCH] Display '(edited)' next to edited polls (#7789) --- res/css/views/messages/_MPollBody.scss | 6 ++ src/components/views/messages/MPollBody.tsx | 8 +- src/i18n/strings/en_EN.json | 2 +- .../views/messages/MPollBody-test.tsx | 92 ++++++++++++++++--- 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/res/css/views/messages/_MPollBody.scss b/res/css/views/messages/_MPollBody.scss index a03fd46be7..3c6471dd53 100644 --- a/res/css/views/messages/_MPollBody.scss +++ b/res/css/views/messages/_MPollBody.scss @@ -23,6 +23,12 @@ limitations under the License. line-height: $font-24px; margin-top: 0; margin-bottom: 8px; + + .mx_MPollBody_edited { + color: $roomtopic-color; + font-size: $font-12px; + opacity: 0.6; + } } h2::before { diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 1778d79f15..7498995e9a 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -400,8 +400,14 @@ export default class MPollBody extends React.Component { totalText = _t("Based on %(count)s votes", { count: totalVotes }); } + const editedSpan = ( + this.props.mxEvent.replacingEvent() + ? ({ _t("edited") }) + : null + ); + return
-

{ poll.question.text }

+

{ poll.question.text }{ editedSpan }

{ poll.answers.map((answer: PollAnswerSubevent) => { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7fd4410f45..a985e7d5dc 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2136,6 +2136,7 @@ "%(count)s votes cast. Vote to see the results|one": "%(count)s vote cast. Vote to see the results", "Based on %(count)s votes|other": "Based on %(count)s votes", "Based on %(count)s votes|one": "Based on %(count)s vote", + "edited": "edited", "%(count)s votes|other": "%(count)s votes", "%(count)s votes|one": "%(count)s vote", "Error decrypting video": "Error decrypting video", @@ -2156,7 +2157,6 @@ "Edited at %(date)s": "Edited at %(date)s", "Click to view edits": "Click to view edits", "Edited at %(date)s. Click to view edits.": "Edited at %(date)s. Click to view edits.", - "edited": "edited", "Submit logs": "Submit logs", "Can't load this message": "Can't load this message", "toggle event": "toggle event", diff --git a/test/components/views/messages/MPollBody-test.tsx b/test/components/views/messages/MPollBody-test.tsx index debeae09e7..7ed059950f 100644 --- a/test/components/views/messages/MPollBody-test.tsx +++ b/test/components/views/messages/MPollBody-test.tsx @@ -180,6 +180,8 @@ describe("MPollBody", () => { expect(votesCount(body, "italian")).toBe(""); expect(votesCount(body, "wings")).toBe(""); expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("No votes cast"); + expect(body.find('h2').html()) + .toEqual("

What should we order for the party?

"); }); it("finds votes from multiple people", () => { @@ -867,6 +869,54 @@ describe("MPollBody", () => { ).toBe(false); }); + it("Displays edited content and new answer IDs if the poll has been edited", () => { + const pollEvent = new MatrixEvent({ + "type": M_POLL_START.name, + "event_id": "$mypoll", + "room_id": "#myroom:example.com", + "content": newPollStart( + [ + { "id": "o1", [M_TEXT.name]: "old answer 1" }, + { "id": "o2", [M_TEXT.name]: "old answer 2" }, + ], + "old question", + ), + }); + const replacingEvent = new MatrixEvent({ + "type": M_POLL_START.name, + "event_id": "$mypollreplacement", + "room_id": "#myroom:example.com", + "content": { + "m.new_content": newPollStart( + [ + { "id": "n1", [M_TEXT.name]: "new answer 1" }, + { "id": "n2", [M_TEXT.name]: "new answer 2" }, + { "id": "n3", [M_TEXT.name]: "new answer 3" }, + ], + "new question", + ), + }, + }); + pollEvent.makeReplaced(replacingEvent); + const body = newMPollBodyFromEvent(pollEvent, []); + expect(body.find('h2').html()) + .toEqual( + "

new question" + + " (edited)" + + "

", + ); + const inputs = body.find('input[type="radio"]'); + expect(inputs).toHaveLength(3); + expect(inputs.at(0).prop("value")).toEqual("n1"); + expect(inputs.at(1).prop("value")).toEqual("n2"); + expect(inputs.at(2).prop("value")).toEqual("n3"); + const options = body.find('.mx_MPollBody_optionText'); + expect(options).toHaveLength(3); + expect(options.at(0).text()).toEqual("new answer 1"); + expect(options.at(1).text()).toEqual("new answer 2"); + expect(options.at(2).text()).toEqual("new answer 3"); + }); + it("renders a poll with no votes", () => { const votes = []; const body = newMPollBody(votes); @@ -968,17 +1018,25 @@ function newMPollBody( relationEvents: Array, endEvents: Array = [], answers?: POLL_ANSWER[], +): ReactWrapper { + const mxEvent = new MatrixEvent({ + "type": M_POLL_START.name, + "event_id": "$mypoll", + "room_id": "#myroom:example.com", + "content": newPollStart(answers), + }); + return newMPollBodyFromEvent(mxEvent, relationEvents, endEvents); +} + +function newMPollBodyFromEvent( + mxEvent: MatrixEvent, + relationEvents: Array, + endEvents: Array = [], ): ReactWrapper { const voteRelations = newVoteRelations(relationEvents); const endRelations = newEndRelations(endEvents); - return mount( { expect(eventId).toBe("$mypoll"); @@ -1035,7 +1093,10 @@ function endedVotesCount(wrapper: ReactWrapper, value: string): string { ).text(); } -function newPollStart(answers?: POLL_ANSWER[]): M_POLL_START_EVENT_CONTENT { +function newPollStart( + answers?: POLL_ANSWER[], + question?: string, +): M_POLL_START_EVENT_CONTENT { if (!answers) { answers = [ { "id": "pizza", [M_TEXT.name]: "Pizza" }, @@ -1045,16 +1106,25 @@ function newPollStart(answers?: POLL_ANSWER[]): M_POLL_START_EVENT_CONTENT { ]; } + if (!question) { + question = "What should we order for the party?"; + } + + const answersFallback = Array.from(answers.entries()) + .map(([i, a]) => `${i + 1}. ${a[M_TEXT.name]}`) + .join("\n"); + + const fallback = `${question}\n${answersFallback}`; + return { [M_POLL_START.name]: { "question": { - [M_TEXT.name]: "What should we order for the party?", + [M_TEXT.name]: question, }, "kind": M_POLL_KIND_DISCLOSED.name, "answers": answers, }, - [M_TEXT.name]: "What should we order for the party?\n" + - "1. Pizza\n2. Poutine\n3. Italian\n4. Wings", + [M_TEXT.name]: fallback, }; }