mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-19 14:17:59 +01:00
render polls
This commit is contained in:
parent
56fb4a154f
commit
d0f53463a2
8 changed files with 94 additions and 5 deletions
|
@ -4,14 +4,16 @@ defmodule Philomena.Polls.Poll do
|
||||||
|
|
||||||
alias Philomena.Topics.Topic
|
alias Philomena.Topics.Topic
|
||||||
alias Philomena.Users.User
|
alias Philomena.Users.User
|
||||||
|
alias Philomena.PollOptions.PollOption
|
||||||
|
|
||||||
schema "polls" do
|
schema "polls" do
|
||||||
belongs_to :topic, Topic
|
belongs_to :topic, Topic
|
||||||
belongs_to :deleted_by, User
|
belongs_to :deleted_by, User
|
||||||
|
has_many :options, PollOption
|
||||||
|
|
||||||
field :title, :string
|
field :title, :string
|
||||||
field :vote_method, :string
|
field :vote_method, :string
|
||||||
field :active_until, :naive_datetime
|
field :active_until, :utc_datetime
|
||||||
field :total_votes, :integer, default: 0
|
field :total_votes, :integer, default: 0
|
||||||
field :hidden_from_users, :boolean, default: false
|
field :hidden_from_users, :boolean, default: false
|
||||||
field :deletion_reason, :string, default: ""
|
field :deletion_reason, :string, default: ""
|
||||||
|
|
|
@ -61,7 +61,7 @@ defmodule Philomena.Posts do
|
||||||
|> repo.one()
|
|> repo.one()
|
||||||
|
|
||||||
Ecto.build_assoc(topic, :posts, [topic_position: (last_position || -1) + 1] ++ attributes)
|
Ecto.build_assoc(topic, :posts, [topic_position: (last_position || -1) + 1] ++ attributes)
|
||||||
|> Post.creation_changeset(user, params)
|
|> Post.creation_changeset(params, user)
|
||||||
|> repo.insert()
|
|> repo.insert()
|
||||||
end)
|
end)
|
||||||
|> Multi.run(:update_topic, fn repo, %{post: %{id: post_id}} ->
|
|> Multi.run(:update_topic, fn repo, %{post: %{id: post_id}} ->
|
||||||
|
|
|
@ -40,7 +40,7 @@ defmodule Philomena.Posts.Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
def creation_changeset(post, user, attrs) do
|
def creation_changeset(post, attrs, user) do
|
||||||
post
|
post
|
||||||
|> cast(attrs, [:body, :anonymous])
|
|> cast(attrs, [:body, :anonymous])
|
||||||
|> set_name_at_post_time(user)
|
|> set_name_at_post_time(user)
|
||||||
|
|
|
@ -12,7 +12,7 @@ defmodule PhilomenaWeb.TopicController do
|
||||||
topic =
|
topic =
|
||||||
Topic
|
Topic
|
||||||
|> where(forum_id: ^forum.id, slug: ^slug, hidden_from_users: false)
|
|> where(forum_id: ^forum.id, slug: ^slug, hidden_from_users: false)
|
||||||
|> preload(:user)
|
|> preload([:user, poll: :option])
|
||||||
|> Repo.one()
|
|> Repo.one()
|
||||||
|
|
||||||
conn = conn |> assign(:topic, topic)
|
conn = conn |> assign(:topic, topic)
|
||||||
|
|
13
lib/philomena_web/templates/topic/poll/_display.html.slime
Normal file
13
lib/philomena_web/templates/topic/poll/_display.html.slime
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
= if @poll.hidden_from_users do
|
||||||
|
.walloftext
|
||||||
|
.block.block--fixed.block--warning
|
||||||
|
h1 This poll has been deleted
|
||||||
|
p
|
||||||
|
' Reason:
|
||||||
|
strong
|
||||||
|
= @poll.deletion_reason || "Unknown (likely deleted in error). Please contact a moderator."
|
||||||
|
|
||||||
|
- else
|
||||||
|
.poll
|
||||||
|
.poll-area
|
||||||
|
= render PhilomenaWeb.TopicView, "_poll_results.html", poll: @poll, conn: @conn
|
44
lib/philomena_web/templates/topic/poll/_results.html.slime
Normal file
44
lib/philomena_web/templates/topic/poll/_results.html.slime
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
.poll-results
|
||||||
|
h4.poll__header
|
||||||
|
' Poll results:
|
||||||
|
= @poll.title
|
||||||
|
|
||||||
|
.poll-option-list
|
||||||
|
elixir:
|
||||||
|
winning = winning_option(@poll)
|
||||||
|
winners? = @poll.total_votes > 0
|
||||||
|
|
||||||
|
= for option <- ranked_options(@poll) do
|
||||||
|
div class=option_class(option, winning, winners?)
|
||||||
|
.poll-option__text
|
||||||
|
span.poll-option__label = option.label
|
||||||
|
|
||||||
|
.poll-option__counts
|
||||||
|
span
|
||||||
|
=> percent_of_total(option, @poll)
|
||||||
|
=> option.vote_count
|
||||||
|
=> pluralize("vote", "votes", option.vote_count)
|
||||||
|
|
||||||
|
.poll-bar
|
||||||
|
svg.poll-bar__image width=percent_of_total(option, @poll) height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"
|
||||||
|
rect class=poll_bar_class(option, winning, winners?) width="1" height="1"
|
||||||
|
|
||||||
|
= if active?(@poll) do
|
||||||
|
' Poll ends
|
||||||
|
= pretty_time(@poll.active_until)
|
||||||
|
' .
|
||||||
|
|
||||||
|
= if @poll.total_votes > 0 do
|
||||||
|
=> @poll.total_votes
|
||||||
|
=> pluralize("vote", "votes", @poll.total_votes)
|
||||||
|
- else
|
||||||
|
' No votes have been
|
||||||
|
' cast so far.
|
||||||
|
|
||||||
|
- else
|
||||||
|
' Poll ended
|
||||||
|
=> pretty_time(@poll.active_until)
|
||||||
|
' with
|
||||||
|
=> @poll.total_votes
|
||||||
|
= pluralize("vote", "votes", @poll.total_votes)
|
||||||
|
' .
|
|
@ -29,7 +29,8 @@ h1 = @topic.title
|
||||||
= render PhilomenaWeb.Topic.SubscriptionView, "_subscription.html", forum: @forum, topic: @topic, watching: @watching, conn: @conn
|
= render PhilomenaWeb.Topic.SubscriptionView, "_subscription.html", forum: @forum, topic: @topic, watching: @watching, conn: @conn
|
||||||
|
|
||||||
/ Display the poll, if any
|
/ Display the poll, if any
|
||||||
/= render partial: 'polls/display', locals: { poll: @topic.poll }
|
= if @topic.poll do
|
||||||
|
= render PhilomenaWeb.Topic.PollView, "_display.html.slime", poll: @poll, conn: @conn
|
||||||
|
|
||||||
/ The actual posts
|
/ The actual posts
|
||||||
.posts-area
|
.posts-area
|
||||||
|
|
29
lib/philomena_web/views/topic/poll_view.ex
Normal file
29
lib/philomena_web/views/topic/poll_view.ex
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
defmodule PhilomenaWeb.Topic.PollView do
|
||||||
|
use PhilomenaWeb, :view
|
||||||
|
|
||||||
|
def ranked_options(poll) do
|
||||||
|
poll.options
|
||||||
|
|> Enum.sort_by(&{-&1.vote_count, &1.id})
|
||||||
|
end
|
||||||
|
|
||||||
|
def winning_option(poll) do
|
||||||
|
poll
|
||||||
|
|> ranked_options()
|
||||||
|
|> hd()
|
||||||
|
end
|
||||||
|
|
||||||
|
def active?(poll) do
|
||||||
|
not poll.hidden_from_users and poll.active_until > DateTime.utc_now()
|
||||||
|
end
|
||||||
|
|
||||||
|
def percent_of_total(_option, %{total_votes: 0}), do: 0
|
||||||
|
def percent_of_total(%{vote_count: vote_count}, %{total_votes: total_votes}) do
|
||||||
|
:io_lib.format("~.2f%", [(vote_count / total_votes * 100)])
|
||||||
|
end
|
||||||
|
|
||||||
|
def option_class(%{id: option_id}, %{id: option_id}, true), do: "poll-option-top"
|
||||||
|
def option_class(_option, _top_option, _winners?), do: nil
|
||||||
|
|
||||||
|
def poll_bar_class(%{id: option_id}, %{id: option_id}, true), do: "poll-bar__fill poll-bar__fill--top"
|
||||||
|
def poll_bar_class(_option, _top_option, _winners?), do: "poll-bar__fill"
|
||||||
|
end
|
Loading…
Reference in a new issue