Skip to content

Commit

Permalink
feat: Allow to choose notification settings when attachment added (#627)
Browse files Browse the repository at this point in the history
* fix: Override Create attachment admin command

* fix: Force email notification on attachment event

* fix: Override attachment form

* feat: Allow admins to toggle notification sending

* refactor: Remove override and add extend

* lint: Fix rubocop offenses

---------

Co-authored-by: Lucie Grau <[email protected]>
  • Loading branch information
Quentinchampenois and luciegrau authored Nov 25, 2024
1 parent 337c338 commit 1fe41e8
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 8 deletions.
44 changes: 44 additions & 0 deletions app/forms/decidim/admin/attachment_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

module Decidim
module Admin
# A form object used to create attachments in a participatory process.
#
class AttachmentForm < Form
include TranslatableAttributes

attribute :file
translatable_attribute :title, String
translatable_attribute :description, String
attribute :weight, Integer, default: 0
attribute :attachment_collection_id, Integer
attribute :send_notification_to_followers, Boolean, default: false

mimic :attachment

validates :file, presence: true, unless: :persisted?
validates :file, passthru: { to: Decidim::Attachment }
validates :title, :description, translatable_presence: true
validates :attachment_collection, presence: true, if: ->(form) { form.attachment_collection_id.present? }
validates :attachment_collection_id, inclusion: { in: :attachment_collection_ids }, allow_blank: true

delegate :attached_to, to: :context, prefix: false

alias organization current_organization

def attachment_collections
@attachment_collections ||= attached_to.attachment_collections
end

def attachment_collection
@attachment_collection ||= attachment_collections.find_by(id: attachment_collection_id)
end

private

def attachment_collection_ids
@attachment_collection_ids ||= attachment_collections.pluck(:id)
end
end
end
end
33 changes: 33 additions & 0 deletions app/views/decidim/admin/attachments/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<div class="card">
<div class="card-divider">
<h2 class="card-title">
<%= title %>
</h2>
</div>

<div class="card-section">
<div class="row column">
<%= form.translated :text_field, :title, autofocus: true %>
</div>

<div class="row column">
<%= form.number_field :weight %>
</div>

<div class="row column">
<%= form.translated :text_field, :description %>
</div>

<div class="row column">
<%= form.select :attachment_collection_id, @form.attachment_collections.collect { |c| [translated_attribute(c.name), c.id] }, include_blank: true %>
</div>

<div class="row column">
<%= form.upload :file, required: true %>
</div>

<div class="row column">
<%= form.check_box :send_notification_to_followers, label: t(".send_notification_to_followers") %>
</div>
</div>
</div>
23 changes: 15 additions & 8 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,31 @@ class Application < Rails::Application
end

config.after_initialize do
# Controllers
require "extends/controllers/decidim/devise/sessions_controller_extends"
require "extends/controllers/decidim/editor_images_controller_extends"
require "extends/controllers/decidim/proposals/proposals_controller_extends"
require "extends/controllers/decidim/newsletters_controller_extends"
require "extends/controllers/decidim/admin/scopes_controller_extends"
require "extends/controllers/decidim/scopes_controller_extends"
require "extends/services/decidim/iframe_disabler_extends"
require "extends/helpers/decidim/check_boxes_tree_helper_extends"
require "extends/helpers/decidim/icon_helper_extends"
require "extends/commands/decidim/initiatives/admin/update_initiative_answer_extends"
require "extends/controllers/decidim/initiatives/committee_requests_controller_extends"
# Models
require "extends/models/decidim/budgets/project_extends"
require "extends/models/decidim/authorization_extends"
require "extends/models/decidim/decidim_awesome/proposal_extra_field_extends"
# Services
require "extends/services/decidim/iframe_disabler_extends"
# Helpers
require "extends/helpers/decidim/icon_helper_extends"
require "extends/helpers/decidim/check_boxes_tree_helper_extends"
# Forms
require "extends/forms/decidim/initiatives/initiative_form_extends"
require "extends/forms/decidim/initiatives/admin/initiative_form_extends"
# Commands
require "extends/commands/decidim/initiatives/admin/update_initiative_answer_extends"
require "extends/commands/decidim/budgets/admin/import_proposals_to_budgets_extends"
require "extends/controllers/decidim/newsletters_controller_extends"
require "extends/commands/decidim/admin/destroy_participatory_space_private_user_extends"
require "extends/controllers/decidim/proposals/proposals_controller_extends"
require "extends/forms/decidim/initiatives/initiative_form_extends"
require "extends/models/decidim/decidim_awesome/proposal_extra_field_extends"
require "extends/commands/decidim/admin/create_attachment_extends"

Decidim::GraphiQL::Rails.config.tap do |config|
config.initial_query = "{\n deployment {\n version\n branch\n remote\n upToDate\n currentCommit\n latestCommit\n locallyModified\n }\n}".html_safe
Expand Down
3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ en:
confirm_destroy: Confirm destroy
destroy: Destroy
edit: Edit
attachments:
form:
send_notification_to_followers: Send a notification to all the people following the consultation who have agreed to receive email notifications
exports:
export_as: "%{name} as %{export_format}"
notice: Your export is currently in progress. You'll receive an email when it's complete.
Expand Down
3 changes: 3 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ fr:
confirm_destroy: Confirmer la suppression
destroy: Supprimer
edit: Modifier
attachments:
form:
send_notification_to_followers: Envoyer une notification à toutes les personnes qui suivent la concertation ayant accepté de recevoir des notifications par mail
exports:
export_as: "%{name} au format %{export_format}"
notice: Votre exportation est en cours. Vous recevrez un e-mail quand elle sera terminée.
Expand Down
25 changes: 25 additions & 0 deletions lib/extends/commands/decidim/admin/create_attachment_extends.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require "active_support/concern"

module CreateAttachmentExtends
extend ActiveSupport::Concern

included do
def notify_followers
return unless @attachment.attached_to.is_a?(Decidim::Followable)
return unless form.send_notification_to_followers

Decidim::EventsManager.publish(
event: "decidim.events.attachments.attachment_created",
event_class: Decidim::AttachmentCreatedEvent,
resource: @attachment,
followers: @attachment.attached_to.followers,
extra: { force_email: true },
force_send: true
)
end
end
end

Decidim::Admin::CreateAttachment.include(CreateAttachmentExtends)
104 changes: 104 additions & 0 deletions spec/commands/decidim/admin/create_attachment_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# frozen_string_literal: true

require "spec_helper"

module Decidim::Admin
describe CreateAttachment do
subject { described_class.call(form, attached_to, user) }
let(:user) { create(:user) }
let(:send_notification) { true }
let(:form) do
instance_double(
AttachmentForm,
title: {
en: "An image",
ca: "Una imatge",
es: "Una imagen"
},
description: {
en: "A city",
ca: "Una ciutat",
es: "Una ciudad"
},
file: file,
attachment_collection: nil,
send_notification_to_followers: send_notification,
weight: 0
)
end
let(:file) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) }
let(:attached_to) { create(:participatory_process) }

describe "when valid" do
before do
allow(form).to receive(:invalid?).and_return(false)
end

it "broadcasts :ok and creates the component" do
expect do
subject
end.to broadcast(:ok)

expect(Decidim::Attachment.count).to eq(1)
end

it "notifies the followers" do
follower = create(:user, organization: attached_to.organization)
create(:follow, followable: attached_to, user: follower)

expect(Decidim::EventsManager)
.to receive(:publish)
.with(
event: "decidim.events.attachments.attachment_created",
event_class: Decidim::AttachmentCreatedEvent,
resource: kind_of(Decidim::Attachment),
followers: [follower],
extra: { force_email: true },
force_send: true
)

subject
end

context "when send notification option is false" do
let(:send_notification) { false }

it "does not notify the followers" do
follower = create(:user, organization: attached_to.organization)
create(:follow, followable: attached_to, user: follower)

expect(Decidim::EventsManager)
.not_to receive(:publish)

subject
end
end

it "traces the action", versioning: true do
expect(Decidim.traceability)
.to receive(:perform_action!)
.with(:create, Decidim::Attachment, user)
.and_call_original

expect { subject }.to change(Decidim::ActionLog, :count)
action_log = Decidim::ActionLog.last
expect(action_log.action).to eq("create")
expect(action_log.version).to be_present
end
end

describe "when invalid" do
before do
allow(form).to receive(:invalid?).and_return(true)
end

it "broadcasts invalid" do
expect do
subject
end.to broadcast(:invalid)

expect(Decidim::Attachment.count).to eq(0)
end
end
end
end

0 comments on commit 1fe41e8

Please sign in to comment.