mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-30 14:57:59 +01:00
fixes #45: add poll administration options
This commit is contained in:
parent
7b49f8d978
commit
d1783cdeb8
9 changed files with 119 additions and 67 deletions
|
@ -51,7 +51,7 @@ defmodule Philomena.Polls do
|
|||
"""
|
||||
def create_poll(attrs \\ %{}) do
|
||||
%Poll{}
|
||||
|> Poll.changeset(attrs)
|
||||
|> Poll.update_changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
|
@ -69,7 +69,7 @@ defmodule Philomena.Polls do
|
|||
"""
|
||||
def update_poll(%Poll{} = poll, attrs) do
|
||||
poll
|
||||
|> Poll.changeset(attrs)
|
||||
|> Poll.update_changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ defmodule Philomena.Polls.Poll do
|
|||
alias Philomena.Topics.Topic
|
||||
alias Philomena.Users.User
|
||||
alias Philomena.PollOptions.PollOption
|
||||
alias Philomena.Schema.Time
|
||||
|
||||
schema "polls" do
|
||||
belongs_to :topic, Topic
|
||||
|
@ -27,13 +28,14 @@ defmodule Philomena.Polls.Poll do
|
|||
poll
|
||||
|> cast(attrs, [])
|
||||
|> validate_required([])
|
||||
|> Time.propagate_time(:active_until, :until)
|
||||
end
|
||||
|
||||
@doc false
|
||||
def creation_changeset(poll, attrs) do
|
||||
def update_changeset(poll, attrs) do
|
||||
poll
|
||||
|> cast(attrs, [:title, :until, :vote_method])
|
||||
|> put_active_until()
|
||||
|> Time.assign_time(:until, :active_until)
|
||||
|> validate_required([:title, :active_until, :vote_method])
|
||||
|> validate_length(:title, max: 140, count: :bytes)
|
||||
|> validate_inclusion(:vote_method, ["single", "multiple"])
|
||||
|
@ -47,19 +49,4 @@ defmodule Philomena.Polls.Poll do
|
|||
|
||||
defp ignore_if_blank(changeset),
|
||||
do: changeset
|
||||
|
||||
defp put_active_until(changeset) do
|
||||
changeset
|
||||
|> get_field(:until)
|
||||
|> RelativeDate.Parser.parse()
|
||||
|> case do
|
||||
{:ok, until} ->
|
||||
changeset
|
||||
|> change(active_until: until)
|
||||
|
||||
_error ->
|
||||
changeset
|
||||
|> add_error(:active_until, "invalid date format")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,7 +58,7 @@ defmodule Philomena.Topics.Topic do
|
|||
|> put_slug()
|
||||
|> change(forum: forum, user: attribution[:user])
|
||||
|> validate_required(:forum)
|
||||
|> cast_assoc(:poll, with: &Poll.creation_changeset/2)
|
||||
|> cast_assoc(:poll, with: &Poll.update_changeset/2)
|
||||
|> cast_assoc(:posts, with: {Post, :topic_creation_changeset, [attribution, anonymous?]})
|
||||
|> validate_length(:posts, is: 1)
|
||||
|> unique_constraint(:slug, name: :index_topics_on_forum_id_and_slug)
|
||||
|
|
49
lib/philomena_web/controllers/topic/poll_controller.ex
Normal file
49
lib/philomena_web/controllers/topic/poll_controller.ex
Normal file
|
@ -0,0 +1,49 @@
|
|||
defmodule PhilomenaWeb.Topic.PollController do
|
||||
use PhilomenaWeb, :controller
|
||||
|
||||
alias Philomena.Forums.Forum
|
||||
alias Philomena.Polls
|
||||
alias Philomena.Repo
|
||||
|
||||
plug :load_and_authorize_resource,
|
||||
model: Forum,
|
||||
id_name: "forum_id",
|
||||
id_field: "short_name",
|
||||
persisted: true
|
||||
|
||||
plug PhilomenaWeb.LoadTopicPlug
|
||||
plug PhilomenaWeb.LoadPollPlug
|
||||
|
||||
plug :verify_authorized
|
||||
plug :preload_options
|
||||
|
||||
def edit(conn, _params) do
|
||||
changeset = Polls.change_poll(conn.assigns.poll)
|
||||
render(conn, "edit.html", title: "Editing Poll", changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"poll" => poll_params}) do
|
||||
case Polls.update_poll(conn.assigns.poll, poll_params) do
|
||||
{:ok, _poll} ->
|
||||
conn
|
||||
|> put_flash(:info, "Poll successfully updated.")
|
||||
|> redirect(to: Routes.forum_topic_path(conn, :show, conn.assigns.forum, conn.assigns.topic))
|
||||
|
||||
{:error, changeset} ->
|
||||
render(conn, "edit.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
defp preload_options(conn, _opts) do
|
||||
poll = Repo.preload(conn.assigns.poll, :options)
|
||||
|
||||
assign(conn, :poll, poll)
|
||||
end
|
||||
|
||||
defp verify_authorized(conn, _opts) do
|
||||
case Canada.Can.can?(conn.assigns.current_user, :hide, conn.assigns.topic) do
|
||||
true -> conn
|
||||
_false -> PhilomenaWeb.NotAuthorizedPlug.call(conn)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -218,9 +218,9 @@ defmodule PhilomenaWeb.Router do
|
|||
resources "/delete", Topic.Post.DeleteController, only: [:create], singleton: true
|
||||
end
|
||||
|
||||
resources "/poll/votes", Topic.Poll.VoteController,
|
||||
as: :poll_vote,
|
||||
only: [:index, :create, :delete]
|
||||
resources "/poll", Topic.PollController, only: [:edit, :update], singleton: true do
|
||||
resources "/votes", Topic.Poll.VoteController, only: [:index, :create, :delete]
|
||||
end
|
||||
end
|
||||
|
||||
resources "/subscription", Forum.SubscriptionController,
|
||||
|
|
|
@ -36,50 +36,7 @@
|
|||
input.toggle-box id="add_poll" name="add_poll" type="checkbox"
|
||||
label for="add_poll" Add a poll
|
||||
.toggle-box-container
|
||||
p
|
||||
' Polls may have a maximum of
|
||||
span.js-max-option-count> 20
|
||||
' options. Leave any options you don't want to use blank.
|
||||
' Only registered users will be able to vote.
|
||||
|
||||
.field.field--block
|
||||
= text_input fp, :title, class: "input input--wide", placeholder: "Poll title", maxlength: 140
|
||||
= error_tag fp, :title
|
||||
|
||||
p.fieldlabel
|
||||
' End date
|
||||
|
||||
.field.field--block
|
||||
= text_input fp, :until, class: "input input--wide", placeholder: "2 weeks from now", maxlength: 255
|
||||
= error_tag fp, :until
|
||||
= error_tag fp, :active_until
|
||||
|
||||
p.fieldlabel
|
||||
' Specify when the poll should end. Once the poll ends, no more
|
||||
' votes can be cast and the final results will be displayed. Good
|
||||
' values to try are "1 week from now" and "24 hours from now". Polls
|
||||
' must last for at least 24 hours.
|
||||
|
||||
p.fieldlabel
|
||||
' Voting method:
|
||||
|
||||
.field.field--block
|
||||
= select fp, :vote_method, ["-": "", "Single option": :single, "Multiple options": :multiple], class: "input"
|
||||
= error_tag fp, :vote_method
|
||||
|
||||
= inputs_for fp, :options, fn fo ->
|
||||
.field.js-poll-option.field--inline.flex--no-wrap.flex--centered
|
||||
= text_input fo, :label, class: "input flex__grow js-option-label", placeholder: "Option"
|
||||
= error_tag fo, :label
|
||||
|
||||
label.input--separate-left.flex__fixed.flex--centered
|
||||
a.js-option-remove href="#"
|
||||
i.fa.fa-trash>
|
||||
' Delete
|
||||
|
||||
button.button.js-poll-add-option type="button"
|
||||
i.fa.fa-plus>
|
||||
' Add option
|
||||
= render PhilomenaWeb.Topic.PollView, "_form.html", Map.put(assigns, :f, fp)
|
||||
|
||||
.block__tab.communication-edit__tab.hidden data-tab="preview"
|
||||
' [Loading preview...]
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
= if can?(@conn, :hide, @topic) do
|
||||
= link "Voters", to: "#", data: [click_tab: "voters", load_tab: Routes.forum_topic_poll_vote_path(@conn, :index, @forum, @topic)]
|
||||
= link "Administrate", to: "#", data: [click_tab: "administration"]
|
||||
|
||||
.block__tab data-tab="voting"
|
||||
= cond do
|
||||
|
@ -29,3 +30,7 @@
|
|||
= if can?(@conn, :hide, @topic) do
|
||||
.block__tab.hidden data-tab="voters"
|
||||
p Loading…
|
||||
.block__tab.hidden data-tab="administration"
|
||||
a.button.button--state-warning.js-staff-action> href=Routes.forum_topic_poll_path(@conn, :edit, @forum, @topic)
|
||||
i.fa.fa-edit>
|
||||
| Edit
|
||||
|
|
44
lib/philomena_web/templates/topic/poll/_form.html.slime
Normal file
44
lib/philomena_web/templates/topic/poll/_form.html.slime
Normal file
|
@ -0,0 +1,44 @@
|
|||
p
|
||||
' Polls may have a maximum of
|
||||
span.js-max-option-count> 20
|
||||
' options. Leave any options you don't want to use blank.
|
||||
' Only registered users will be able to vote.
|
||||
|
||||
.field.field--block
|
||||
= text_input @f, :title, class: "input input--wide", placeholder: "Poll title", maxlength: 140
|
||||
= error_tag @f, :title
|
||||
|
||||
p.fieldlabel
|
||||
' End date
|
||||
|
||||
.field.field--block
|
||||
= text_input @f, :until, class: "input input--wide", placeholder: "2 weeks from now", maxlength: 255
|
||||
= error_tag @f, :until
|
||||
= error_tag @f, :active_until
|
||||
|
||||
p.fieldlabel
|
||||
' Specify when the poll should end. Once the poll ends, no more
|
||||
' votes can be cast and the final results will be displayed. Good
|
||||
' values to try are "1 week from now" and "24 hours from now". Polls
|
||||
' must last for at least 24 hours.
|
||||
|
||||
p.fieldlabel
|
||||
' Voting method:
|
||||
|
||||
.field.field--block
|
||||
= select @f, :vote_method, ["-": "", "Single option": :single, "Multiple options": :multiple], class: "input"
|
||||
= error_tag @f, :vote_method
|
||||
|
||||
= inputs_for @f, :options, fn fo ->
|
||||
.field.js-poll-option.field--inline.flex--no-wrap.flex--centered
|
||||
= text_input fo, :label, class: "input flex__grow js-option-label", placeholder: "Option"
|
||||
= error_tag fo, :label
|
||||
|
||||
label.input--separate-left.flex__fixed.flex--centered
|
||||
a.js-option-remove href="#"
|
||||
i.fa.fa-trash>
|
||||
' Delete
|
||||
|
||||
button.button.js-poll-add-option type="button"
|
||||
i.fa.fa-plus>
|
||||
' Add option
|
10
lib/philomena_web/templates/topic/poll/edit.html.slime
Normal file
10
lib/philomena_web/templates/topic/poll/edit.html.slime
Normal file
|
@ -0,0 +1,10 @@
|
|||
h1 Editing Poll
|
||||
|
||||
= form_for @changeset, Routes.forum_topic_poll_path(@conn, :update, @forum, @topic), fn f ->
|
||||
= render PhilomenaWeb.Topic.PollView, "_form.html", f: f
|
||||
|
||||
br
|
||||
br
|
||||
|
||||
.action
|
||||
= submit "Save", class: "button", data: [disable_with: raw("Saving…")]
|
Loading…
Reference in a new issue