Show user what options they have voted (#11195)
* Add own_votes field to poll results in REST API Fixes #10679 * Display user votes in WebUI * Update styling * Add vote checkmark to public pages
This commit is contained in:
		
							parent
							
								
									26b810561a
								
							
						
					
					
						commit
						b359974d9b
					
				
					 6 changed files with 31 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -73,8 +73,9 @@ export function normalizePoll(poll) {
 | 
			
		|||
 | 
			
		||||
  const emojiMap = makeEmojiMap(normalPoll);
 | 
			
		||||
 | 
			
		||||
  normalPoll.options = poll.options.map(option => ({
 | 
			
		||||
  normalPoll.options = poll.options.map((option, index) => ({
 | 
			
		||||
    ...option,
 | 
			
		||||
    voted: poll.own_votes && poll.own_votes.includes(index),
 | 
			
		||||
    title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import spring from 'react-motion/lib/spring';
 | 
			
		|||
import escapeTextContentForBrowser from 'escape-html';
 | 
			
		||||
import emojify from 'mastodon/features/emoji/emoji';
 | 
			
		||||
import RelativeTimestamp from './relative_timestamp';
 | 
			
		||||
import Icon from 'mastodon/components/icon';
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  closed: { id: 'poll.closed', defaultMessage: 'Closed' },
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +104,7 @@ class Poll extends ImmutablePureComponent {
 | 
			
		|||
    const percent            = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
 | 
			
		||||
    const leading            = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
 | 
			
		||||
    const active             = !!this.state.selected[`${optionIndex}`];
 | 
			
		||||
    const voted              = option.get('voted') || (poll.get('own_votes') && poll.get('own_votes').includes(optionIndex));
 | 
			
		||||
 | 
			
		||||
    let titleEmojified = option.get('title_emojified');
 | 
			
		||||
    if (!titleEmojified) {
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +133,10 @@ class Poll extends ImmutablePureComponent {
 | 
			
		|||
          />
 | 
			
		||||
 | 
			
		||||
          {!showResults && <span className={classNames('poll__input', { checkbox: poll.get('multiple'), active })} />}
 | 
			
		||||
          {showResults && <span className='poll__number'>{Math.round(percent)}%</span>}
 | 
			
		||||
          {showResults && <span className='poll__number'>
 | 
			
		||||
            {!!voted && <Icon id='check' className='poll__vote__mark' />}
 | 
			
		||||
            {Math.round(percent)}%
 | 
			
		||||
          </span>}
 | 
			
		||||
 | 
			
		||||
          <span dangerouslySetInnerHTML={{ __html: titleEmojified }} />
 | 
			
		||||
        </label>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,13 +95,19 @@
 | 
			
		|||
 | 
			
		||||
  &__number {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    width: 36px;
 | 
			
		||||
    width: 48px;
 | 
			
		||||
    font-weight: 700;
 | 
			
		||||
    padding: 0 10px;
 | 
			
		||||
    text-align: right;
 | 
			
		||||
    margin-top: auto;
 | 
			
		||||
    margin-bottom: auto;
 | 
			
		||||
    flex: 0 0 36px;
 | 
			
		||||
    flex: 0 0 48px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__vote__mark {
 | 
			
		||||
    float: left;
 | 
			
		||||
    color: $valid-value-color;
 | 
			
		||||
    line-height: 18px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__footer {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,10 @@ class Poll < ApplicationRecord
 | 
			
		|||
    account.id == account_id || votes.where(account: account).exists?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def own_votes(account)
 | 
			
		||||
    votes.where(account: account).pluck(:choice)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  delegate :local?, to: :account
 | 
			
		||||
 | 
			
		||||
  def remote?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ class REST::PollSerializer < ActiveModel::Serializer
 | 
			
		|||
  has_many :emojis, serializer: REST::CustomEmojiSerializer
 | 
			
		||||
 | 
			
		||||
  attribute :voted, if: :current_user?
 | 
			
		||||
  attribute :own_votes, if: :current_user?
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
    object.id.to_s
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +22,10 @@ class REST::PollSerializer < ActiveModel::Serializer
 | 
			
		|||
    object.voted?(current_user.account)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def own_votes
 | 
			
		||||
    object.own_votes(current_user.account)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def current_user?
 | 
			
		||||
    !current_user.nil?
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,19 @@
 | 
			
		|||
- show_results = (user_signed_in? && poll.voted?(current_account)) || poll.expired?
 | 
			
		||||
- own_votes = user_signed_in? ? poll.own_votes(current_account) : []
 | 
			
		||||
 | 
			
		||||
.poll
 | 
			
		||||
  %ul
 | 
			
		||||
    - poll.loaded_options.each do |option|
 | 
			
		||||
    - poll.loaded_options.each_with_index do |option, index|
 | 
			
		||||
      %li
 | 
			
		||||
        - if show_results
 | 
			
		||||
          - percent = poll.votes_count > 0 ? 100 * option.votes_count / poll.votes_count : 0
 | 
			
		||||
          %span.poll__chart{ style: "width: #{percent}%" }
 | 
			
		||||
 | 
			
		||||
          %label.poll__text><
 | 
			
		||||
            %span.poll__number= percent.round
 | 
			
		||||
            %span.poll__number><
 | 
			
		||||
              - if own_votes.include?(index)
 | 
			
		||||
                %i.poll__vote__mark.fa.fa-check
 | 
			
		||||
              = percent.round
 | 
			
		||||
            = Formatter.instance.format_poll_option(status, option, autoplay: autoplay)
 | 
			
		||||
        - else
 | 
			
		||||
          %label.poll__text><
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue