decidim-debates 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|