Skip to content

Commit

Permalink
Merge pull request #102 from datasektionen/feat/close-polls
Browse files Browse the repository at this point in the history
Ability to close polls
  • Loading branch information
adriansalamon authored Nov 24, 2024
2 parents 26957be + 3f84f82 commit ac2b4c5
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 25 deletions.
16 changes: 13 additions & 3 deletions lib/haj/polls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ defmodule Haj.Polls do
"""
def update_poll(%Poll{} = poll, attrs) do
poll
|> Poll.changeset(attrs)
|> Repo.update()
res =
poll
|> Poll.changeset(attrs)
|> Repo.update()

broadcast_updated_poll(res)
res
end

@doc """
Expand Down Expand Up @@ -410,4 +414,10 @@ defmodule Haj.Polls do
defp broadcast(poll_id, event, payload) do
PubSub.broadcast(Haj.PubSub, "poll:#{poll_id}", {event, payload})
end

defp broadcast_updated_poll({:ok, poll}) do
PubSub.broadcast(Haj.PubSub, "poll:#{poll.id}", {:poll_updated, %{poll: poll}})
end

defp broadcast_updated_poll({:error, _changeset}), do: :ok
end
3 changes: 2 additions & 1 deletion lib/haj/polls/poll.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule Haj.Polls.Poll do
field :title, :string
field :display_votes, :boolean, default: false
field :allow_user_options, :boolean, default: false
field :open, :boolean, default: true

has_many :options, Haj.Polls.Option
has_many :votes, Haj.Polls.Vote
Expand All @@ -17,7 +18,7 @@ defmodule Haj.Polls.Poll do
@doc false
def changeset(poll, attrs) do
poll
|> cast(attrs, [:title, :description, :display_votes, :allow_user_options])
|> cast(attrs, [:title, :description, :display_votes, :allow_user_options, :open])
|> validate_required([:title, :description, :display_votes, :allow_user_options])
end
end
68 changes: 47 additions & 21 deletions lib/haj_web/live/poll_live/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ defmodule HajWeb.PollLive.Show do
@impl true
def mount(%{"id" => id}, _session, socket) do
poll = Polls.get_poll!(id)
options = Polls.list_options_for_poll(id)
user_votes = Polls.list_user_votes_for_poll(id, socket.assigns.current_user.id)
{options, user_votes} = get_options(id, socket.assigns.current_user.id)

if connected?(socket) do
Polls.subscribe(id)
end

{:ok,
assign(socket, poll: poll, user_votes: user_votes)
|> stream(:options, options)}
end

defp get_options(poll_id, user_id) do
options = Polls.list_options_for_poll(poll_id)
user_votes = Polls.list_user_votes_for_poll(poll_id, user_id)

options =
Enum.map(options, fn option ->
Map.put(option, :voted, Enum.any?(user_votes, fn vote -> vote.option_id == option.id end))
end)

{:ok,
assign(socket, poll: poll, user_votes: user_votes)
|> stream(:options, options)}
{options, user_votes}
end

@impl true
Expand All @@ -38,12 +44,18 @@ defmodule HajWeb.PollLive.Show do
end

defp apply_action(socket, :new_option, _params) do
socket
|> assign(:page_title, "Nytt alternativ")
|> assign(:option, %Option{
poll_id: socket.assigns.poll.id,
creator_id: socket.assigns.current_user.id
})
if socket.assigns.poll.open do
socket
|> assign(:page_title, "Nytt alternativ")
|> assign(:option, %Option{
poll_id: socket.assigns.poll.id,
creator_id: socket.assigns.current_user.id
})
else
socket
|> put_flash(:error, "Röstningen är stängd")
|> push_patch(to: ~p"/polls/#{socket.assigns.poll}")
end
end

@impl true
Expand Down Expand Up @@ -88,10 +100,21 @@ defmodule HajWeb.PollLive.Show do
|> stream_insert(:options, option, at: pos - 1)}
end

@impl true
def handle_info({:poll_updated, %{poll: poll}}, socket) do
{options, user_votes} = get_options(poll.id, socket.assigns.current_user.id)

{:noreply, assign(socket, poll: poll, user_votes: user_votes) |> stream(:options, options)}
end

@impl true
def handle_event("vote", %{"id" => id}, socket) do
{:ok, _} = Polls.toggle_user_vote_for_option(id, socket.assigns.current_user.id)
{:noreply, socket}
if socket.assigns.poll.open do
{:ok, _} = Polls.toggle_user_vote_for_option(id, socket.assigns.current_user.id)
{:noreply, socket}
else
{:noreply, put_flash(socket, :error, "Röstningen är stängd")}
end
end

@impl true
Expand All @@ -101,7 +124,12 @@ defmodule HajWeb.PollLive.Show do
<div class="flex flex-col items-center justify-between xs:flex-row">
<div class="mr-auto flex w-full flex-col items-baseline justify-between pt-4">
<span class="text-2xl font-bold"><%= @poll.title %></span>
<span class="text-sm text-gray-600"><%= @poll.description %></span>
<span class="flex flex-col text-sm text-gray-600">
<span><%= @poll.description %></span>
<span :if={not @poll.open}>
Röstningen är stängd
</span>
</span>
</div>
<div class="mt-4 w-full flex-none xs:w-fit">
Expand All @@ -115,18 +143,19 @@ defmodule HajWeb.PollLive.Show do
role="list"
phx-update="stream"
id="options"
class="mt-4 divide divide-gray-100 grid grid-cols-2 gap-x-4"
class="divide mt-4 grid gap-x-4 divide-gray-100 md:grid-cols-2"
>
<div
:for={{id, option} <- @streams.options}
id={id}
class="flex flex-col rounded-md px-2 py-5 hover:bg-gray-50"
class="flex flex-col rounded-md px-4 py-5 hover:bg-gray-50"
>
<div class="flex flex-wrap items-center justify-between gap-x-2">
<label
:if={@poll.open}
phx-click="vote"
phx-value-id={option.id}
class="px-2 py-2 hover:cursor-pointer md:px-4"
class="mr-2 py-2 hover:cursor-pointer"
>
<input
type="checkbox"
Expand Down Expand Up @@ -159,10 +188,7 @@ defmodule HajWeb.PollLive.Show do
</div>
</div>
<p
:if={option.description}
class="text-xs/5 mt-1 ml-2 flex items-center gap-x-2 text-gray-500 md:ml-4"
>
<p :if={option.description} class="text-xs/5 mt-1 flex items-center gap-x-2 text-gray-500">
<%= option.description %>
</p>
</div>
Expand Down
1 change: 1 addition & 0 deletions lib/haj_web/live/settings_live/polls/form_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defmodule HajWeb.PollLive.FormComponent do
>
<.input field={@form[:title]} type="text" label="Title" />
<.input field={@form[:description]} type="text" label="Description" />
<.input field={@form[:open]} type="checkbox" label="Open for voting" />
<.input field={@form[:display_votes]} type="checkbox" label="Display votes" />
<.input field={@form[:allow_user_options]} type="checkbox" label="Allow user options" />
<:actions>
Expand Down
9 changes: 9 additions & 0 deletions priv/repo/migrations/20241124210659_add_poll_open_option.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Haj.Repo.Migrations.AddPollOpenOption do
use Ecto.Migration

def change do
alter table(:polls) do
add :open, :boolean, default: true
end
end
end

0 comments on commit ac2b4c5

Please sign in to comment.