Skip to content

Commit 9fa55f1

Browse files
ClearlyClairehiyuki2578
authored andcommitted
Show user what options they have voted (mastodon#11195)
* Add own_votes field to poll results in REST API Fixes mastodon#10679 * Display user votes in WebUI * Update styling * Add vote checkmark to public pages
1 parent 8b25f87 commit 9fa55f1

6 files changed

Lines changed: 31 additions & 6 deletions

File tree

app/javascript/mastodon/actions/importer/normalizer.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ export function normalizePoll(poll) {
7373

7474
const emojiMap = makeEmojiMap(normalPoll);
7575

76-
normalPoll.options = poll.options.map(option => ({
76+
normalPoll.options = poll.options.map((option, index) => ({
7777
...option,
78+
voted: poll.own_votes && poll.own_votes.includes(index),
7879
title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
7980
}));
8081

app/javascript/mastodon/components/poll.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import spring from 'react-motion/lib/spring';
1010
import escapeTextContentForBrowser from 'escape-html';
1111
import emojify from 'mastodon/features/emoji/emoji';
1212
import RelativeTimestamp from './relative_timestamp';
13+
import Icon from 'mastodon/components/icon';
1314

1415
const messages = defineMessages({
1516
closed: { id: 'poll.closed', defaultMessage: 'Closed' },
@@ -103,6 +104,7 @@ class Poll extends ImmutablePureComponent {
103104
const percent = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
104105
const leading = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
105106
const active = !!this.state.selected[`${optionIndex}`];
107+
const voted = option.get('voted') || (poll.get('own_votes') && poll.get('own_votes').includes(optionIndex));
106108

107109
let titleEmojified = option.get('title_emojified');
108110
if (!titleEmojified) {
@@ -131,7 +133,10 @@ class Poll extends ImmutablePureComponent {
131133
/>
132134

133135
{!showResults && <span className={classNames('poll__input', { checkbox: poll.get('multiple'), active })} />}
134-
{showResults && <span className='poll__number'>{Math.round(percent)}%</span>}
136+
{showResults && <span className='poll__number'>
137+
{!!voted && <Icon id='check' className='poll__vote__mark' />}
138+
{Math.round(percent)}%
139+
</span>}
135140

136141
<span dangerouslySetInnerHTML={{ __html: titleEmojified }} />
137142
</label>

app/javascript/styles/mastodon/polls.scss

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,19 @@
9595

9696
&__number {
9797
display: inline-block;
98-
width: 36px;
98+
width: 48px;
9999
font-weight: 700;
100100
padding: 0 10px;
101101
text-align: right;
102102
margin-top: auto;
103103
margin-bottom: auto;
104-
flex: 0 0 36px;
104+
flex: 0 0 48px;
105+
}
106+
107+
&__vote__mark {
108+
float: left;
109+
color: $valid-value-color;
110+
line-height: 18px;
105111
}
106112

107113
&__footer {

app/models/poll.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ def voted?(account)
5454
account.id == account_id || votes.where(account: account).exists?
5555
end
5656

57+
def own_votes(account)
58+
votes.where(account: account).pluck(:choice)
59+
end
60+
5761
delegate :local?, to: :account
5862

5963
def remote?

app/serializers/rest/poll_serializer.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class REST::PollSerializer < ActiveModel::Serializer
88
has_many :emojis, serializer: REST::CustomEmojiSerializer
99

1010
attribute :voted, if: :current_user?
11+
attribute :own_votes, if: :current_user?
1112

1213
def id
1314
object.id.to_s
@@ -21,6 +22,10 @@ def voted
2122
object.voted?(current_user.account)
2223
end
2324

25+
def own_votes
26+
object.own_votes(current_user.account)
27+
end
28+
2429
def current_user?
2530
!current_user.nil?
2631
end

app/views/statuses/_poll.html.haml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
- show_results = (user_signed_in? && poll.voted?(current_account)) || poll.expired?
2+
- own_votes = user_signed_in? ? poll.own_votes(current_account) : []
23

34
.poll
45
%ul
5-
- poll.loaded_options.each do |option|
6+
- poll.loaded_options.each_with_index do |option, index|
67
%li
78
- if show_results
89
- percent = poll.votes_count > 0 ? 100 * option.votes_count / poll.votes_count : 0
910
%span.poll__chart{ style: "width: #{percent}%" }
1011

1112
%label.poll__text><
12-
%span.poll__number= percent.round
13+
%span.poll__number><
14+
- if own_votes.include?(index)
15+
%i.poll__vote__mark.fa.fa-check
16+
= percent.round
1317
= Formatter.instance.format_poll_option(status, option, autoplay: autoplay)
1418
- else
1519
%label.poll__text><

0 commit comments

Comments
 (0)