decidim-debates 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +15 -0
- data/Rakefile +3 -0
- data/app/assets/images/decidim/debates/icon.svg +1 -0
- data/app/commands/decidim/debates/admin/create_debate.rb +57 -0
- data/app/commands/decidim/debates/admin/update_debate.rb +46 -0
- data/app/commands/decidim/debates/create_debate.rb +68 -0
- data/app/controllers/decidim/debates/admin/application_controller.rb +15 -0
- data/app/controllers/decidim/debates/admin/debates_controller.rb +73 -0
- data/app/controllers/decidim/debates/application_controller.rb +13 -0
- data/app/controllers/decidim/debates/debates_controller.rb +78 -0
- data/app/events/decidim/debates/create_debate_event.rb +42 -0
- data/app/forms/decidim/debates/admin/debate_form.rb +33 -0
- data/app/forms/decidim/debates/debate_form.rb +25 -0
- data/app/helpers/decidim/debates/application_helper.rb +12 -0
- data/app/models/decidim/debates/abilities/admin/admin_ability.rb +21 -0
- data/app/models/decidim/debates/abilities/admin/participatory_process_admin_ability.rb +23 -0
- data/app/models/decidim/debates/abilities/admin/participatory_process_moderator_ability.rb +21 -0
- data/app/models/decidim/debates/abilities/current_user_ability.rb +49 -0
- data/app/models/decidim/debates/application_record.rb +10 -0
- data/app/models/decidim/debates/debate.rb +103 -0
- data/app/presenters/decidim/debates/debate_presenter.rb +20 -0
- data/app/presenters/decidim/debates/official_author_presenter.rb +34 -0
- data/app/services/decidim/debates/debate_search.rb +38 -0
- data/app/views/decidim/debates/admin/debates/_form.html.erb +36 -0
- data/app/views/decidim/debates/admin/debates/edit.html.erb +7 -0
- data/app/views/decidim/debates/admin/debates/index.html.erb +52 -0
- data/app/views/decidim/debates/admin/debates/new.html.erb +7 -0
- data/app/views/decidim/debates/debates/_count.html.erb +1 -0
- data/app/views/decidim/debates/debates/_debate.html.erb +42 -0
- data/app/views/decidim/debates/debates/_debates.html.erb +4 -0
- data/app/views/decidim/debates/debates/_filters.html.erb +20 -0
- data/app/views/decidim/debates/debates/_filters_small_view.html.erb +18 -0
- data/app/views/decidim/debates/debates/_share.html.erb +33 -0
- data/app/views/decidim/debates/debates/index.html.erb +27 -0
- data/app/views/decidim/debates/debates/index.js.erb +9 -0
- data/app/views/decidim/debates/debates/new.html.erb +43 -0
- data/app/views/decidim/debates/debates/show.html.erb +80 -0
- data/config/locales/ca.yml +114 -0
- data/config/locales/en.yml +117 -0
- data/config/locales/es.yml +114 -0
- data/config/locales/eu.yml +114 -0
- data/config/locales/fi.yml +114 -0
- data/config/locales/fr.yml +114 -0
- data/config/locales/gl.yml +114 -0
- data/config/locales/it.yml +114 -0
- data/config/locales/nl.yml +114 -0
- data/config/locales/pl.yml +116 -0
- data/config/locales/pt-BR.yml +114 -0
- data/config/locales/pt.yml +114 -0
- data/config/locales/ru.yml +5 -0
- data/config/locales/sv.yml +114 -0
- data/config/locales/uk.yml +5 -0
- data/db/migrate/20170118141619_create_debates.rb +18 -0
- data/db/migrate/20180117100413_add_debate_information_updates.rb +7 -0
- data/db/migrate/20180118132243_add_author_to_debates.rb +7 -0
- data/db/migrate/20180119150434_add_reference_to_debates.rb +12 -0
- data/db/migrate/20180122090505_add_user_group_author_to_debates.rb +7 -0
- data/lib/decidim/debates/admin.rb +10 -0
- data/lib/decidim/debates/admin_engine.rb +33 -0
- data/lib/decidim/debates/engine.rb +26 -0
- data/lib/decidim/debates/feature.rb +55 -0
- data/lib/decidim/debates/test/factories.rb +52 -0
- data/lib/decidim/debates/version.rb +10 -0
- data/lib/decidim/debates.rb +12 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5c8c3f04834fe68d8d8f398651df6a90dd7c723f783630cd7e448289a46a020c
|
4
|
+
data.tar.gz: c39f1fd9a58bfa76f7a92a5afef691882e2799b90b7f0c9967d9bc3e638b423e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 406ad27d7b9841e2a78bcfc6cbeb4177c6335c556252d83e4cdee5b06c2e3afe567e71c25e15bd4eb2ecba188bc019dadd20e74bbba9b9f275e6f3cc4a3b4326
|
7
|
+
data.tar.gz: 013e15cde4c7431c8853dcf00a38c38db94e3f833c3784928d0e12a7e2bbb909090e0ddfbfdf86531a13c55d6c66c97f49f1483621762703058d99f25e94e59f
|
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Decidim::Debates
|
2
|
+
|
3
|
+
The Debates module adds debate to any participatory process. It adds a CRUD engine to the admin and public view scoped inside the participatory process.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Debates will be available as a Component for any participatory space.
|
8
|
+
|
9
|
+
## Contributing
|
10
|
+
|
11
|
+
See [Decidim](https://github.com/decidim/decidim).
|
12
|
+
|
13
|
+
## License
|
14
|
+
|
15
|
+
See [Decidim](https://github.com/decidim/decidim).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm6.44 24.29a1 1 0 0 1-.34-.06l-3.78-1.42a10.75 10.75 0 0 1-2.32.25c-4.95 0-9-3.36-9-7.5s4-7.5 9-7.5 9 3.36 9 7.5a6.75 6.75 0 0 1-1.88 4.6l.32 3.06a1 1 0 0 1-1 1.07zm-4.06-3.47a1 1 0 0 1 .34.06l2.59 1-.2-2a1 1 0 0 1 .3-.8 4.91 4.91 0 0 0 1.62-3.54c0-3.06-3.15-5.55-7-5.55s-7 2.49-7 5.55 3.15 5.55 7 5.55a8.74 8.74 0 0 0 2.14-.26 1 1 0 0 1 .21-.01z"/></svg>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
module Admin
|
6
|
+
# This command is executed when the user creates a Debate from the admin
|
7
|
+
# panel.
|
8
|
+
class CreateDebate < Rectify::Command
|
9
|
+
def initialize(form)
|
10
|
+
@form = form
|
11
|
+
end
|
12
|
+
|
13
|
+
# Creates the debate if valid.
|
14
|
+
#
|
15
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
16
|
+
def call
|
17
|
+
return broadcast(:invalid) if form.invalid?
|
18
|
+
|
19
|
+
transaction do
|
20
|
+
create_debate
|
21
|
+
send_notification_to_space_followers
|
22
|
+
end
|
23
|
+
broadcast(:ok)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :debate, :form
|
29
|
+
|
30
|
+
def create_debate
|
31
|
+
@debate = Debate.create!(
|
32
|
+
category: form.category,
|
33
|
+
title: form.title,
|
34
|
+
description: form.description,
|
35
|
+
information_updates: form.information_updates,
|
36
|
+
instructions: form.instructions,
|
37
|
+
end_time: form.end_time,
|
38
|
+
start_time: form.start_time,
|
39
|
+
feature: form.current_feature
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def send_notification_to_space_followers
|
44
|
+
Decidim::EventsManager.publish(
|
45
|
+
event: "decidim.events.debates.debate_created",
|
46
|
+
event_class: Decidim::Debates::CreateDebateEvent,
|
47
|
+
resource: debate,
|
48
|
+
recipient_ids: form.current_feature.participatory_space.followers.pluck(:id),
|
49
|
+
extra: {
|
50
|
+
type: "participatory_space"
|
51
|
+
}
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
module Admin
|
6
|
+
# This command is executed when the user changes a Debate from the admin
|
7
|
+
# panel.
|
8
|
+
class UpdateDebate < Rectify::Command
|
9
|
+
# Initializes a UpdateDebate Command.
|
10
|
+
#
|
11
|
+
# form - The form from which to get the data.
|
12
|
+
# debate - The current instance of the page to be updated.
|
13
|
+
def initialize(form, debate)
|
14
|
+
@form = form
|
15
|
+
@debate = debate
|
16
|
+
end
|
17
|
+
|
18
|
+
# Updates the debate if valid.
|
19
|
+
#
|
20
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
21
|
+
def call
|
22
|
+
return broadcast(:invalid) if form.invalid?
|
23
|
+
|
24
|
+
update_debate
|
25
|
+
broadcast(:ok)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :debate, :form
|
31
|
+
|
32
|
+
def update_debate
|
33
|
+
debate.update_attributes!(
|
34
|
+
category: form.category,
|
35
|
+
title: form.title,
|
36
|
+
description: form.description,
|
37
|
+
information_updates: form.information_updates,
|
38
|
+
instructions: form.instructions,
|
39
|
+
end_time: form.end_time,
|
40
|
+
start_time: form.start_time
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
# This command is executed when the user creates a Debate from the public
|
6
|
+
# views.
|
7
|
+
class CreateDebate < Rectify::Command
|
8
|
+
def initialize(form)
|
9
|
+
@form = form
|
10
|
+
end
|
11
|
+
|
12
|
+
# Creates the debate if valid.
|
13
|
+
#
|
14
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
15
|
+
def call
|
16
|
+
return broadcast(:invalid) if form.invalid?
|
17
|
+
|
18
|
+
transaction do
|
19
|
+
create_debate
|
20
|
+
send_notifications
|
21
|
+
end
|
22
|
+
broadcast(:ok, debate)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :debate, :form
|
28
|
+
|
29
|
+
def organization
|
30
|
+
@organization = form.current_feature.organization
|
31
|
+
end
|
32
|
+
|
33
|
+
def i18n_field(field)
|
34
|
+
organization.available_locales.inject({}) do |i18n, locale|
|
35
|
+
i18n.update(locale => field)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_debate
|
40
|
+
@debate = Debate.create!(
|
41
|
+
author: form.current_user,
|
42
|
+
decidim_user_group_id: form.user_group_id,
|
43
|
+
category: form.category,
|
44
|
+
title: i18n_field(form.title),
|
45
|
+
description: i18n_field(form.description),
|
46
|
+
feature: form.current_feature
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def send_notifications
|
51
|
+
send_notification(debate.author.followers.pluck(:id), :user)
|
52
|
+
send_notification(debate.participatory_space.followers.pluck(:id), :participatory_space)
|
53
|
+
end
|
54
|
+
|
55
|
+
def send_notification(recipient_ids, type)
|
56
|
+
Decidim::EventsManager.publish(
|
57
|
+
event: "decidim.events.debates.debate_created",
|
58
|
+
event_class: Decidim::Debates::CreateDebateEvent,
|
59
|
+
resource: debate,
|
60
|
+
recipient_ids: recipient_ids,
|
61
|
+
extra: {
|
62
|
+
type: type.to_s
|
63
|
+
}
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
module Admin
|
6
|
+
# This controller is the abstract class from which all other controllers of
|
7
|
+
# this engine inherit.
|
8
|
+
#
|
9
|
+
# Note that it inherits from `Decidim::Features::BaseController`, which
|
10
|
+
# override its layout and provide all kinds of useful methods.
|
11
|
+
class ApplicationController < Decidim::Admin::Features::BaseController
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
module Admin
|
6
|
+
# This controller allows an admin to manage debates from a Participatory Space
|
7
|
+
class DebatesController < Admin::ApplicationController
|
8
|
+
helper_method :debates
|
9
|
+
|
10
|
+
def new
|
11
|
+
@form = form(Decidim::Debates::Admin::DebateForm).instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@form = form(Decidim::Debates::Admin::DebateForm).from_params(params, current_feature: current_feature)
|
16
|
+
|
17
|
+
CreateDebate.call(@form) do
|
18
|
+
on(:ok) do
|
19
|
+
flash[:notice] = I18n.t("debates.create.success", scope: "decidim.debates.admin")
|
20
|
+
redirect_to debates_path
|
21
|
+
end
|
22
|
+
|
23
|
+
on(:invalid) do
|
24
|
+
flash.now[:alert] = I18n.t("debates.create.invalid", scope: "decidim.debates.admin")
|
25
|
+
render action: "new"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def edit
|
31
|
+
authorize! :edit, debate
|
32
|
+
@form = form(DebateForm).from_model(debate)
|
33
|
+
end
|
34
|
+
|
35
|
+
def update
|
36
|
+
authorize! :edit, debate
|
37
|
+
@form = form(DebateForm).from_params(params, current_feature: current_feature)
|
38
|
+
|
39
|
+
UpdateDebate.call(@form, debate) do
|
40
|
+
on(:ok) do
|
41
|
+
flash[:notice] = I18n.t("debates.update.success", scope: "decidim.debates.admin")
|
42
|
+
redirect_to debates_path
|
43
|
+
end
|
44
|
+
|
45
|
+
on(:invalid) do
|
46
|
+
flash.now[:alert] = I18n.t("debates.update.invalid", scope: "decidim.debates.admin")
|
47
|
+
render action: "edit"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def destroy
|
53
|
+
authorize! :destroy, debate
|
54
|
+
debate.destroy!
|
55
|
+
|
56
|
+
flash[:notice] = I18n.t("debates.destroy.success", scope: "decidim.debates.admin")
|
57
|
+
|
58
|
+
redirect_to debates_path
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def debates
|
64
|
+
@debates ||= Debate.where(feature: current_feature)
|
65
|
+
end
|
66
|
+
|
67
|
+
def debate
|
68
|
+
@debate ||= debates.find(params[:id])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
# This controller is the abstract class from which all other controllers of
|
6
|
+
# this engine inherit.
|
7
|
+
#
|
8
|
+
# Note that it inherits from `Decidim::Components::BaseController`, which
|
9
|
+
# override its layout and provide all kinds of useful methods.
|
10
|
+
class ApplicationController < Decidim::Features::BaseController
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
# Exposes the debate resource so users can view them
|
6
|
+
class DebatesController < Decidim::Debates::ApplicationController
|
7
|
+
helper Decidim::ApplicationHelper
|
8
|
+
helper Decidim::Messaging::ConversationHelper
|
9
|
+
include FormFactory
|
10
|
+
include FilterResource
|
11
|
+
include Paginable
|
12
|
+
|
13
|
+
helper_method :debates, :debate, :paginated_debates, :report_form
|
14
|
+
|
15
|
+
def new
|
16
|
+
authorize! :create, Debate
|
17
|
+
|
18
|
+
@form = form(DebateForm).instance
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
authorize! :create, Debate
|
23
|
+
@form = form(DebateForm).from_params(params, current_feature: current_feature)
|
24
|
+
|
25
|
+
CreateDebate.call(@form) do
|
26
|
+
on(:ok) do |debate|
|
27
|
+
flash[:notice] = I18n.t("debates.create.success", scope: "decidim.debates")
|
28
|
+
redirect_to Decidim::ResourceLocatorPresenter.new(debate).path
|
29
|
+
end
|
30
|
+
|
31
|
+
on(:invalid) do
|
32
|
+
flash.now[:alert] = I18n.t("debates.create.invalid", scope: "decidim.debates")
|
33
|
+
render action: "new"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def paginated_debates
|
41
|
+
@paginated_debates ||= paginate(debates)
|
42
|
+
.includes(:category)
|
43
|
+
end
|
44
|
+
|
45
|
+
def debates
|
46
|
+
@debates ||= search.results
|
47
|
+
end
|
48
|
+
|
49
|
+
def debate
|
50
|
+
@debate ||= debates.find(params[:id])
|
51
|
+
end
|
52
|
+
|
53
|
+
def report_form
|
54
|
+
@report_form ||= form(Decidim::ReportForm).from_params(reason: "spam")
|
55
|
+
end
|
56
|
+
|
57
|
+
def search_klass
|
58
|
+
DebateSearch
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_search_params
|
62
|
+
{
|
63
|
+
page: params[:page],
|
64
|
+
per_page: 12
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def default_filter_params
|
69
|
+
{
|
70
|
+
search_text: "",
|
71
|
+
order_start_time: "asc",
|
72
|
+
origin: "all",
|
73
|
+
category_id: ""
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen-string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
# Notifies users about a new debate. Accepts a Hash in the `extra`
|
6
|
+
# field with the key `:type`, which can hold two different values:
|
7
|
+
#
|
8
|
+
# "user" - The event is being sent to the followers of the debate
|
9
|
+
# author
|
10
|
+
# "participatory_space" - The event is being sento to the followers
|
11
|
+
# of the event's participatory space.
|
12
|
+
class CreateDebateEvent < Decidim::Events::SimpleEvent
|
13
|
+
include Decidim::Events::AuthorEvent
|
14
|
+
|
15
|
+
i18n_attributes :space_title, :space_path
|
16
|
+
|
17
|
+
delegate :author, to: :resource
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def space
|
22
|
+
@space ||= resource.participatory_space
|
23
|
+
end
|
24
|
+
|
25
|
+
def space_path
|
26
|
+
Decidim::ResourceLocatorPresenter.new(space).path
|
27
|
+
end
|
28
|
+
|
29
|
+
def space_title
|
30
|
+
space.title.is_a?(Hash) ? space.title[I18n.locale.to_s] : space.title
|
31
|
+
end
|
32
|
+
|
33
|
+
def i18n_scope
|
34
|
+
@scope ||= if extra[:type].to_s == "user"
|
35
|
+
"decidim.events.debates.create_debate_event.user_followers"
|
36
|
+
else
|
37
|
+
"decidim.events.debates.create_debate_event.space_followers"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Debates
|
5
|
+
module Admin
|
6
|
+
# This class holds a Form to create/update debates from Decidim's admin panel.
|
7
|
+
class DebateForm < Decidim::Form
|
8
|
+
include TranslatableAttributes
|
9
|
+
|
10
|
+
translatable_attribute :title, String
|
11
|
+
translatable_attribute :description, String
|
12
|
+
translatable_attribute :instructions, String
|
13
|
+
translatable_attribute :information_updates, String
|
14
|
+
attribute :start_time, DateTime
|
15
|
+
attribute :end_time, DateTime
|
16
|
+
attribute :decidim_category_id, Integer
|
17
|
+
|
18
|
+
validates :title, translatable_presence: true
|
19
|
+
validates :description, translatable_presence: true
|
20
|
+
validates :instructions, translatable_presence: true
|
21
|
+
validates :start_time, presence: { if: ->(object) { object.end_time.present? } }, date: { before: :end_time, allow_blank: true }
|
22
|
+
validates :end_time, presence: { if: ->(object) { object.start_time.present? } }, date: { after: :start_time, allow_blank: true }
|
23
|
+
|
24
|
+
validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? }
|
25
|
+
|
26
|
+
def category
|
27
|
+
return unless current_feature
|
28
|
+
@category ||= current_feature.categories.where(id: decidim_category_id).first
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|