From 230a012f0090c496fc5cdb011bcc8ed732fd0f5c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 3 Mar 2019 22:18:23 +0100 Subject: Add polls (#10111) * Add polls Fix #1629 * Add tests * Fixes * Change API for creating polls * Use name instead of content for votes * Remove poll validation for remote polls * Add polls to public pages * When updating the poll, update options just in case they were changed * Fix public pages showing both poll and other media --- config/locales/en.yml | 10 ++++++++++ config/routes.rb | 4 ++++ 2 files changed, 14 insertions(+) (limited to 'config') diff --git a/config/locales/en.yml b/config/locales/en.yml index 7363a7457..b1f6166b4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -734,6 +734,16 @@ en: older: Older prev: Prev truncate: "…" + polls: + errors: + already_voted: You have already voted on this poll + duplicate_options: contain duplicate items + duration_too_long: is too far into the future + duration_too_short: is too soon + expired: The poll has already ended + over_character_limit: cannot be longer than %{MAX} characters each + too_few_options: must have more than one item + too_many_options: can't contain more than %{MAX} items preferences: languages: Languages other: Other diff --git a/config/routes.rb b/config/routes.rb index 9a83d0f88..ac10f9fba 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -362,6 +362,10 @@ Rails.application.routes.draw do resource :accounts, only: [:show, :create, :destroy], controller: 'lists/accounts' end + resources :polls, only: [:create, :show] do + resources :votes, only: :create, controller: 'polls/votes' + end + namespace :push do resource :subscription, only: [:create, :show, :update, :destroy] end -- cgit From 3de71887d849103ed62e8b04b54c630763881010 Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 4 Mar 2019 18:03:12 +0100 Subject: Add non-JS fallback for polls on public pages (#10155) --- .../stream_entries/_detailed_status.html.haml | 3 ++- app/views/stream_entries/_poll.html.haml | 25 ++++++++++++++++++++++ app/views/stream_entries/_simple_status.html.haml | 3 ++- config/locales/en.yml | 5 +++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 app/views/stream_entries/_poll.html.haml (limited to 'config') diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index b9327a546..b19d2452a 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -23,7 +23,8 @@ .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - if status.poll - = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json + = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do + = render partial: 'stream_entries/poll', locals: { poll: status.poll } - elsif !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first diff --git a/app/views/stream_entries/_poll.html.haml b/app/views/stream_entries/_poll.html.haml new file mode 100644 index 000000000..974aff9bd --- /dev/null +++ b/app/views/stream_entries/_poll.html.haml @@ -0,0 +1,25 @@ +- options = (!poll.expired? && poll.hide_totals?) ? poll.unloaded_options : poll.loaded_options +- voted = poll.votes.where(account: current_user.account).exists? +- show_results = voted || poll.expired? + +.poll + %ul + - options.each do |option| + %li + - if show_results + - percent = 100 * option.votes_count / poll.votes_count + %span.poll__chart{ style: "width: #{percent}%" } + %label.poll__text>< + %span.poll__number= percent + = option.title + - else + %label.poll__text>< + %span.poll__input{ class: poll.multiple ? 'checkbox' : nil}>< + = option.title + .poll__footer + - unless show_results + %button.button.button-secondary{ disabled: true } + = t('statuses.poll.vote') + %span= t('statuses.poll.total_votes', count: poll.votes_count) + ยท + %span= poll.expires_at diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index a000c02f4..68e48edbb 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -27,7 +27,8 @@ .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - if status.poll - = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json + = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do + = render partial: 'stream_entries/poll', locals: { poll: status.poll } - elsif !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first diff --git a/config/locales/en.yml b/config/locales/en.yml index b1f6166b4..2d23b1eb6 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -853,6 +853,11 @@ en: ownership: Someone else's toot cannot be pinned private: Non-public toot cannot be pinned reblog: A boost cannot be pinned + poll: + total_votes: + one: "%{count} vote" + other: "%{count} votes" + vote: Vote show_more: Show more sign_in_to_participate: Sign in to participate in the conversation title: '%{name}: "%{quote}"' -- cgit