Skip to content

Commit

Permalink
Archive Debates (decidim#6940)
Browse files Browse the repository at this point in the history
* Archive and unarchive debates

* Add empty message

* Fix erb, rb and i18norm offenses

* Archive debate from debate close form

* Put back accidentally removed create_debates migration

* Add spec for Archive command

* Add spec for archived? method in debate

* Add system spec for archiving debates

* Enable unarchiving from close form

* Add seeds for archived debates

* Change icon class when debate is closed / archived

* Allow admin to archive non-official debates

* Allow open debates to be archived too
  • Loading branch information
verarojman authored and microstudi committed Dec 10, 2020
1 parent 0bb15b5 commit 3dc0783
Show file tree
Hide file tree
Showing 17 changed files with 355 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module Decidim
module Debates
module Admin
# A command with all the business logic when an admin archives a debate.
class ArchiveDebate < Rectify::Command
# Public: Initializes the command.
#
# archive - Boolean, whether to archive (true) or unarchive (false) the debate.
# debate - The debate object to archive.
# user - The user performing the action.
def initialize(archive, debate, user)
@archive = archive
@debate = debate
@user = user
end

# Executes the command. Broadcasts these events:
#
# - :ok when the debate is valid.
# - :invalid if the debate wasn't valid and we couldn't proceed.
#
# Returns nothing.
def call
archive_debate
broadcast(:ok)
rescue ActiveRecord::RecordInvalid
broadcast(:invalid)
end

attr_reader :debate

private

def archive_debate
@debate = Decidim.traceability.perform_action!(
:close,
@debate,
@user
) do
@debate.update!(
archived_at: @archive ? Time.zone.now : nil
)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def close_debate
) do
form.debate.update!(
conclusions: form.conclusions,
closed_at: form.closed_at
closed_at: form.closed_at,
archived_at: (Time.zone.now if form.archive)
)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ def update
end
end

def archive
enforce_permission_to :archive, :debate, debate: debate

archive = params[:archive] == "true"

ArchiveDebate.call(archive, debate, current_user) do
on(:ok) do
flash[:notice] = I18n.t("debates.#{archive ? "archive" : "unarchive"}.success", scope: "decidim.debates.admin")
redirect_to debates_path(archive ? {} : { filter: "archive" })
end

on(:invalid) do
flash.now[:alert] = I18n.t("debates.#{archive ? "archive" : "unarchive"}.invalid", scope: "decidim.debates.admin")
redirect_to debates_path(archive ? {} : { filter: "archive" })
end
end
end

def destroy
enforce_permission_to :delete, :debate, debate: debate

Expand All @@ -74,11 +92,19 @@ def destroy
private

def debates
@debates ||= Debate.where(component: current_component)
@debates ||= archive? ? all_debates.archived : all_debates.not_archived
end

def debate
@debate ||= debates.find(params[:id])
@debate ||= all_debates.find(params[:id])
end

def all_debates
Debate.where(component: current_component)
end

def archive?
params[:filter] == "archive"
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class CloseDebateForm < Decidim::Form
end

attribute :debate, Debate
attribute :archive, Boolean

validates :debate, presence: true
validate :user_can_close_debate
Expand All @@ -23,6 +24,10 @@ def closed_at
debate&.closed_at || Time.current
end

def map_model(model)
self.archive = model.archived_at.present?
end

private

def user_can_close_debate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ module Admin
#
module ApplicationHelper
include Decidim::Admin::ResourceScopeHelper

def link_to_filtered_debates
unfiltered = params[:filter].blank?
link_to(
t("actions.#{unfiltered ? "archived" : "active"}", scope: "decidim.debates", name: t("models.debate.name", scope: "decidim.debates.admin")),
debates_path(unfiltered ? { filter: "archive" } : {}),
class: "button tiny button--title"
)
end
end
end
end
Expand Down
16 changes: 16 additions & 0 deletions decidim-debates/app/models/decidim/debates/debate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class Debate < Debates::ApplicationRecord

scope :open, -> { where(closed_at: nil) }
scope :closed, -> { where.not(closed_at: nil) }
scope :archived, -> { where.not(archived_at: nil) }
scope :not_archived, -> { where(archived_at: nil) }
scope :authored_by, ->(author) { where(author: author) }
scope :commented_by, lambda { |author|
joins(:comments).where(
Expand Down Expand Up @@ -86,6 +88,13 @@ def open?
(ama? && open_ama?) || !ama?
end

# Public: Checks if the debate is archived or not.
#
# Returns a boolean.
def archived?
archived_at.present?
end

# Public: Overrides the `commentable?` Commentable concern method.
def commentable?
component.settings.comments_enabled?
Expand Down Expand Up @@ -157,6 +166,13 @@ def closeable_by?(user)
authored_by?(user)
end

# Checks whether the user can archive the debate.
#
# user - the user to check for authorship
def archivable_by?(user)
authored_by?(user)
end

# Public: Updates the comments counter cache. We have to do it these
# way in order to properly calculate the counter with hidden
# comments.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def permissions
case permission_action.action
when :create, :read
allow!
when :archive
toggle_allow(debate.present?)
when :update
toggle_allow(debate && !debate.closed? && debate.official?)
when :delete, :close
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
<%= f.translated :editor, :conclusions, autofocus: true, rows: 15 %>
</div>
</div>
<div class="card-section">
<div class="row column space-top-10">
<%= f.check_box :archive, label: t(".archive") %>
<p class="help-text"><%= t(".archive_help") %></p>
</div>
</div>
</div>

<div class="button--double form-general-submit">
Expand Down
105 changes: 61 additions & 44 deletions decidim-debates/app/views/decidim/debates/admin/debates/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,72 @@
<%= t(".title") %>
<%= link_to t("actions.new", scope: "decidim.debates", name: t("models.debate.name", scope: "decidim.debates.admin")), new_debate_path, class: "button tiny button--title" if allowed_to? :create, :debate %>
<%= link_to_filtered_debates if allowed_to? :read, :debate %>
</h2>
</div>

<div class="card-section">
<div class="table-scroll">
<table class="table-list">
<thead>
<tr>
<th><%= t("models.debate.fields.title", scope: "decidim.debates") %></th>
<th><%= t("models.debate.fields.start_time", scope: "decidim.debates") %></th>
<th><%= t("models.debate.fields.end_time", scope: "decidim.debates") %></th>
<%= th_resource_scope_label %>
<th class="actions"><%= t("actions.title", scope: "decidim.debates") %></th>
</tr>
</thead>
<tbody>
<% debates.each do |debate| %>
<tr data-id="<%= debate.id %>">
<td>
<%= link_to present(debate).title, resource_locator(debate).path, target: :blank %><br>
</td>
<td>
<% if debate.start_time %>
<%= l debate.start_time, format: :long %>
<% end %>
</td>
<td>
<% if debate.end_time %>
<%= l debate.end_time, format: :long %>
<% end %>
</td>
<%= td_resource_scope_for(debate.scope) %>
<td class="table-list__actions">
<% if allowed_to? :update, :debate, debate: debate %>
<%= icon_link_to "pencil", edit_debate_path(debate), t("actions.edit", scope: "decidim.debates"), class: "action-icon--edit" %>
<% end %>
<% if debates.any? %>
<div class="table-scroll">
<table class="table-list">
<thead>
<tr>
<th><%= t("models.debate.fields.title", scope: "decidim.debates") %></th>
<th><%= t("models.debate.fields.start_time", scope: "decidim.debates") %></th>
<th><%= t("models.debate.fields.end_time", scope: "decidim.debates") %></th>
<%= th_resource_scope_label %>
<th class="actions"><%= t("actions.title", scope: "decidim.debates") %></th>
</tr>
</thead>
<tbody>
<% debates.each do |debate| %>
<tr data-id="<%= debate.id %>">
<td>
<%= link_to present(debate).title, resource_locator(debate).path, target: :blank %><br>
</td>
<td>
<% if debate.start_time %>
<%= l debate.start_time, format: :long %>
<% end %>
</td>
<td>
<% if debate.end_time %>
<%= l debate.end_time, format: :long %>
<% end %>
</td>
<%= td_resource_scope_for(debate.scope) %>
<td class="table-list__actions">
<% if allowed_to? :update, :debate, debate: debate %>
<%= icon_link_to "pencil", edit_debate_path(debate), t("actions.edit", scope: "decidim.debates"), class: "action-icon--edit" %>
<% else %>
<span class="action-space icon"></span>
<% end %>
<% if allowed_to? :close, :debate, debate: debate %>
<%= icon_link_to "lock-locked", edit_debate_debate_close_path(debate_id: debate.id, id: debate.id), t("actions.close", scope: "decidim.debates"), class: "action-icon--close" %>
<% end %>
<% if allowed_to? :close, :debate, debate: debate %>
<%= icon_link_to "lock-locked", edit_debate_debate_close_path(debate_id: debate.id, id: debate.id), t("actions.close", scope: "decidim.debates"), class: "action-icon--close #{"action-icon--highlighted" if debate.closed?}" %>
<% else %>
<span class="action-space icon"></span>
<% end %>
<% if allowed_to? :delete, :debate, debate: debate %>
<%= icon_link_to "circle-x", debate_path(debate), t("actions.destroy", scope: "decidim.debates"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.debates") } %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% if allowed_to? :archive, :debate, debate: debate %>
<%= icon_link_to "folder", archive_debate_path(id: debate.id, archive: !debate.archived?), t("actions.#{ debate.archived? ? "unarchive" : "archive" }", scope: "decidim.debates"), class: "action-icon--archive #{"action-icon--highlighted" if debate.archived?}", method: :post %>
<% else %>
<span class="action-space icon"></span>
<% end %>
<% if allowed_to? :delete, :debate, debate: debate %>
<%= icon_link_to "circle-x", debate_path(debate), t("actions.destroy", scope: "decidim.debates"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.debates") } %>
<% else %>
<span class="action-space icon"></span>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<%= t("debates.empty", scope: "decidim.debates.admin") %>
<% end %>
</div>
</div>
13 changes: 13 additions & 0 deletions decidim-debates/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,27 @@ en:
endorsements_enabled: Endorsements enabled
debates:
actions:
active: Active debates
archive: Archive
archived: Archived debates
close: Close
confirm_destroy: Are you sure?
destroy: Delete
edit: Edit
new: New %{name}
title: Actions
unarchive: Unarchive
admin:
debate_closes:
edit:
archive: Archive this debate
archive_help: Archiving this debate will hide it from the public debates section
close: Close
title: Close debate
debates:
archive:
invalid: There was a problem archiving the debate.
success: Debate successfully archived.
create:
invalid: There was a problem creating the debate.
success: Debate successfully created.
Expand All @@ -66,11 +75,15 @@ en:
edit:
title: Edit debate
update: Update debate
empty: There are no debates matching these criteria.
index:
title: Debates
new:
create: Create debate
title: New debate
unarchive:
invalid: There was a problem unarchiving the debate.
success: Debate successfully unarchived.
update:
invalid: There was a problem updating this debate.
success: Debate successfully updated.
Expand Down
8 changes: 8 additions & 0 deletions decidim-debates/db/migrate/20201126112752_archive_debates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class ArchiveDebates < ActiveRecord::Migration[5.2]
def change
add_column :decidim_debates_debates, :archived_at, :datetime
add_index :decidim_debates_debates, :archived_at
end
end
1 change: 1 addition & 0 deletions decidim-debates/lib/decidim/debates/admin_engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AdminEngine < ::Rails::Engine

routes do
resources :debates do
post :archive, on: :member
resources :debate_closes, only: [:edit, :update]
end
root to: "debates#index"
Expand Down
Loading

0 comments on commit 3dc0783

Please sign in to comment.