decidim-initiatives 0.23.2 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/stylesheet/decidim/initiatives/initiatives.scss +6 -0
  4. data/app/assets/stylesheet/decidim/initiatives/print-initiative.css.scss +22 -0
  5. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb +4 -8
  6. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives_cell.rb +5 -1
  7. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives_settings_form/show.erb +2 -1
  8. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives_settings_form_cell.rb +12 -1
  9. data/app/cells/decidim/initiatives/initiative_m/tags.erb +1 -1
  10. data/app/commands/decidim/initiatives/admin/update_initiative.rb +3 -3
  11. data/app/commands/decidim/initiatives/admin/update_initiative_answer.rb +3 -3
  12. data/app/commands/decidim/initiatives/approve_membership_request.rb +40 -0
  13. data/app/commands/decidim/initiatives/create_initiative.rb +5 -4
  14. data/app/commands/decidim/initiatives/revoke_membership_request.rb +40 -0
  15. data/app/commands/decidim/initiatives/send_initiative_to_technical_validation.rb +57 -0
  16. data/app/commands/decidim/initiatives/spawn_committee_request.rb +18 -0
  17. data/app/commands/decidim/initiatives/update_initiative.rb +74 -0
  18. data/app/controllers/decidim/initiatives/admin/committee_requests_controller.rb +15 -4
  19. data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +1 -1
  20. data/app/controllers/decidim/initiatives/admin/moderations/reports_controller.rb +18 -0
  21. data/app/controllers/decidim/initiatives/committee_requests_controller.rb +32 -0
  22. data/app/controllers/decidim/initiatives/initiative_signatures_controller.rb +1 -3
  23. data/app/controllers/decidim/initiatives/initiatives_controller.rb +58 -1
  24. data/app/events/decidim/initiatives/approve_membership_request_event.rb +61 -0
  25. data/app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb +19 -0
  26. data/app/events/decidim/initiatives/revoke_membership_request_event.rb +61 -0
  27. data/app/events/decidim/initiatives/spawn_committee_request_event.rb +61 -0
  28. data/app/forms/decidim/initiatives/admin/initiative_form.rb +8 -4
  29. data/app/forms/decidim/initiatives/admin/initiative_type_form.rb +3 -0
  30. data/app/forms/decidim/initiatives/initiative_form.rb +25 -2
  31. data/app/forms/decidim/initiatives/vote_form.rb +3 -1
  32. data/app/helpers/decidim/initiatives/admin/initiative_admin_menu_helper.rb +15 -0
  33. data/app/helpers/decidim/initiatives/create_initiative_helper.rb +3 -2
  34. data/app/models/concerns/decidim/initiatives/has_area.rb +1 -1
  35. data/app/models/decidim/initiative.rb +0 -1
  36. data/app/permissions/decidim/initiatives/admin/permissions.rb +5 -4
  37. data/app/permissions/decidim/initiatives/permissions.rb +47 -20
  38. data/app/queries/decidim/initiatives/initiatives_promoted.rb +1 -1
  39. data/app/queries/decidim/initiatives/organization_prioritized_initiatives.rb +13 -2
  40. data/app/serializers/decidim/initiatives/initiative_serializer.rb +3 -0
  41. data/app/services/decidim/initiatives/dummy_timestamp.rb +1 -1
  42. data/app/services/decidim/initiatives/initiative_search.rb +15 -13
  43. data/app/services/decidim/initiatives/pdf_signature_example.rb +27 -27
  44. data/app/views/decidim/initiatives/admin/initiatives/edit.html.erb +1 -1
  45. data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +6 -0
  46. data/app/views/decidim/initiatives/admin/initiatives_type_scopes/edit.html.erb +24 -17
  47. data/app/views/decidim/initiatives/admin/initiatives_type_scopes/new.html.erb +17 -11
  48. data/app/views/decidim/initiatives/create_initiative/_finish_help.html.erb +2 -7
  49. data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +4 -17
  50. data/app/views/decidim/initiatives/create_initiative/finish.html.erb +11 -11
  51. data/app/views/decidim/initiatives/initiative_signatures/error_on_vote.js.erb +5 -0
  52. data/app/views/decidim/initiatives/initiatives/_committee_members.html.erb +73 -0
  53. data/app/views/decidim/initiatives/initiatives/_filters_small_view.html.erb +1 -1
  54. data/app/views/decidim/initiatives/initiatives/_form.html.erb +112 -0
  55. data/app/views/decidim/initiatives/initiatives/_result.html.erb +1 -1
  56. data/app/views/decidim/initiatives/initiatives/_send_to_technical_validation.html.erb +8 -0
  57. data/app/views/decidim/initiatives/initiatives/edit.html.erb +78 -0
  58. data/app/views/decidim/initiatives/initiatives/print.html.erb +156 -0
  59. data/app/views/decidim/initiatives/initiatives/show.html.erb +19 -7
  60. data/app/views/layouts/decidim/admin/initiative.html.erb +0 -1
  61. data/app/views/layouts/decidim/admin/initiatives.html.erb +2 -15
  62. data/config/locales/ar.yml +2 -29
  63. data/config/locales/ca.yml +90 -30
  64. data/config/locales/cs.yml +98 -38
  65. data/config/locales/de.yml +91 -31
  66. data/config/locales/el.yml +2 -35
  67. data/config/locales/en.yml +94 -34
  68. data/config/locales/es-MX.yml +94 -34
  69. data/config/locales/es-PY.yml +94 -34
  70. data/config/locales/es.yml +93 -33
  71. data/config/locales/eu.yml +2 -29
  72. data/config/locales/fi-plain.yml +94 -34
  73. data/config/locales/fi.yml +94 -34
  74. data/config/locales/fr-CA.yml +96 -36
  75. data/config/locales/fr.yml +96 -36
  76. data/config/locales/gl.yml +2 -33
  77. data/config/locales/hu.yml +3 -32
  78. data/config/locales/id-ID.yml +2 -29
  79. data/config/locales/is-IS.yml +2 -14
  80. data/config/locales/it.yml +2 -35
  81. data/config/locales/ja.yml +2 -35
  82. data/config/locales/lv.yml +2 -33
  83. data/config/locales/nl.yml +31 -34
  84. data/config/locales/no.yml +2 -32
  85. data/config/locales/pl.yml +101 -33
  86. data/config/locales/pt-BR.yml +2 -29
  87. data/config/locales/pt.yml +3 -36
  88. data/config/locales/ro-RO.yml +2 -35
  89. data/config/locales/ru.yml +2 -22
  90. data/config/locales/sk.yml +2 -31
  91. data/config/locales/sr-CS.yml +0 -7
  92. data/config/locales/sv.yml +2 -34
  93. data/config/locales/tr-TR.yml +68 -34
  94. data/config/locales/uk.yml +2 -22
  95. data/config/locales/zh-CN.yml +2 -35
  96. data/db/migrate/20171017095143_update_initiative_scoped_type.rb +0 -1
  97. data/db/migrate/20191107134847_add_scopes_to_initiatives_votes.rb +1 -1
  98. data/db/migrate/20191118105634_allow_multiple_offline_votes.rb +1 -1
  99. data/db/migrate/20210310120720_add_followable_counter_cache_to_initiatives.rb +16 -0
  100. data/lib/decidim/api/initiative_api_type.rb +26 -0
  101. data/lib/decidim/api/initiative_committee_member_type.rb +18 -0
  102. data/lib/decidim/api/initiative_type.rb +49 -0
  103. data/lib/decidim/api/initiative_type_interface.rb +8 -3
  104. data/lib/decidim/initiatives.rb +1 -0
  105. data/lib/decidim/initiatives/admin_engine.rb +23 -1
  106. data/lib/decidim/initiatives/api.rb +3 -0
  107. data/lib/decidim/initiatives/engine.rb +14 -9
  108. data/lib/decidim/initiatives/initiatives_filter_form_builder.rb +19 -12
  109. data/lib/decidim/initiatives/participatory_space.rb +6 -6
  110. data/lib/decidim/initiatives/query_extensions.rb +42 -19
  111. data/lib/decidim/initiatives/test/factories.rb +36 -0
  112. data/lib/decidim/initiatives/version.rb +1 -1
  113. metadata +34 -17
  114. data/app/types/decidim/initiatives/initiative_api_type.rb +0 -26
  115. data/app/types/decidim/initiatives/initiative_committee_member_type.rb +0 -18
  116. data/app/types/decidim/initiatives/initiative_type.rb +0 -42
@@ -15,16 +15,27 @@ module Decidim
15
15
  # GET /initiatives/:initiative_id/committee_requests/:id/approve
16
16
  def approve
17
17
  enforce_permission_to :approve, :initiative_committee_member, request: membership_request
18
- membership_request.accepted!
19
18
 
20
- redirect_to initiative_committee_requests_path(membership_request.initiative)
19
+ ApproveMembershipRequest.call(membership_request) do
20
+ on(:ok) do
21
+ redirect_to edit_initiative_path(current_initiative), flash: {
22
+ notice: I18n.t("success", scope: "decidim.initiatives.committee_requests.approve")
23
+ }
24
+ end
25
+ end
21
26
  end
22
27
 
23
28
  # DELETE /initiatives/:initiative_id/committee_requests/:id/revoke
24
29
  def revoke
25
30
  enforce_permission_to :revoke, :initiative_committee_member, request: membership_request
26
- membership_request.rejected!
27
- redirect_to initiative_committee_requests_path(membership_request.initiative)
31
+
32
+ RevokeMembershipRequest.call(membership_request) do
33
+ on(:ok) do
34
+ redirect_to edit_initiative_path(current_initiative), flash: {
35
+ notice: I18n.t("success", scope: "decidim.initiatives.committee_requests.revoke")
36
+ }
37
+ end
38
+ end
28
39
  end
29
40
 
30
41
  private
@@ -49,7 +49,7 @@ module Decidim
49
49
  @form = form(Decidim::Initiatives::Admin::InitiativeForm)
50
50
  .from_params(params, initiative: current_initiative)
51
51
 
52
- UpdateInitiative.call(current_initiative, @form, current_user) do
52
+ Decidim::Initiatives::Admin::UpdateInitiative.call(current_initiative, @form, current_user) do
53
53
  on(:ok) do |initiative|
54
54
  flash[:notice] = I18n.t("initiatives.update.success", scope: "decidim.initiatives.admin")
55
55
  redirect_to edit_initiative_path(initiative)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ module Admin
6
+ module Moderations
7
+ # This controller allows admins to manage moderation reports in an conference.
8
+ class ReportsController < Decidim::Admin::Moderations::ReportsController
9
+ include InitiativeAdmin
10
+
11
+ def permissions_context
12
+ super.merge(current_participatory_space: current_participatory_space)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -40,6 +40,38 @@ module Decidim
40
40
  end
41
41
  end
42
42
  end
43
+
44
+ # GET /initiatives/:initiative_id/committee_requests/:id/approve
45
+ def approve
46
+ enforce_permission_to :approve, :initiative_committee_member, request: membership_request
47
+
48
+ ApproveMembershipRequest.call(membership_request) do
49
+ on(:ok) do
50
+ redirect_to edit_initiative_path(current_initiative), flash: {
51
+ notice: I18n.t("success", scope: "decidim.initiatives.committee_requests.approve")
52
+ }
53
+ end
54
+ end
55
+ end
56
+
57
+ # DELETE /initiatives/:initiative_id/committee_requests/:id/revoke
58
+ def revoke
59
+ enforce_permission_to :revoke, :initiative_committee_member, request: membership_request
60
+
61
+ RevokeMembershipRequest.call(membership_request) do
62
+ on(:ok) do
63
+ redirect_to edit_initiative_path(current_initiative), flash: {
64
+ notice: I18n.t("success", scope: "decidim.initiatives.committee_requests.revoke")
65
+ }
66
+ end
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def membership_request
73
+ @membership_request ||= InitiativesCommitteeMember.find(params[:id])
74
+ end
43
75
  end
44
76
  end
45
77
  end
@@ -47,9 +47,7 @@ module Decidim
47
47
  end
48
48
 
49
49
  on(:invalid) do
50
- render json: {
51
- error: I18n.t("create.error", scope: "decidim.initiatives.initiative_votes")
52
- }, status: :unprocessable_entity
50
+ render :error_on_vote, status: :unprocessable_entity
53
51
  end
54
52
  end
55
53
  end
@@ -21,17 +21,18 @@ module Decidim
21
21
  include InitiativeSlug
22
22
  include FilterResource
23
23
  include Paginable
24
+ include Decidim::FormFactory
24
25
  include Decidim::Initiatives::Orderable
25
26
  include TypeSelectorOptions
26
27
  include NeedsInitiative
27
28
  include SingleInitiativeType
28
29
 
29
30
  helper_method :collection, :initiatives, :filter, :stats
31
+ helper_method :initiative_type
30
32
 
31
33
  # GET /initiatives
32
34
  def index
33
35
  enforce_permission_to :list, :initiative
34
-
35
36
  return unless search.results.blank? && params.dig("filter", "state") != %w(closed)
36
37
 
37
38
  @closed_initiatives = search_klass.new(search_params.merge(state: %w(closed)))
@@ -40,6 +41,7 @@ module Decidim
40
41
  params[:filter] ||= {}
41
42
  params[:filter][:date] = %w(closed)
42
43
  @forced_closed_initiatives = true
44
+
43
45
  @search = @closed_initiatives
44
46
  end
45
47
  end
@@ -49,6 +51,61 @@ module Decidim
49
51
  enforce_permission_to :read, :initiative, initiative: current_initiative
50
52
  end
51
53
 
54
+ # GET /initiatives/:id/send_to_technical_validation
55
+ def send_to_technical_validation
56
+ enforce_permission_to :send_to_technical_validation, :initiative, initiative: current_initiative
57
+
58
+ SendInitiativeToTechnicalValidation.call(current_initiative, current_user) do
59
+ on(:ok) do
60
+ redirect_to EngineRouter.main_proxy(current_initiative).initiatives_path(initiative_slug: nil), flash: {
61
+ notice: I18n.t(
62
+ "success",
63
+ scope: %w(decidim initiatives admin initiatives edit)
64
+ )
65
+ }
66
+ end
67
+ end
68
+ end
69
+
70
+ # GET /initiatives/:slug/edit
71
+ def edit
72
+ enforce_permission_to :edit, :initiative, initiative: current_initiative
73
+ form_attachment_model = form(AttachmentForm).from_model(current_initiative.attachments.first)
74
+ @form = form(Decidim::Initiatives::InitiativeForm)
75
+ .from_model(
76
+ current_initiative,
77
+ initiative: current_initiative
78
+ )
79
+ @form.attachment = form_attachment_model
80
+
81
+ render layout: "decidim/initiative"
82
+ end
83
+
84
+ # PUT /initiatives/:id
85
+ def update
86
+ enforce_permission_to :update, :initiative, initiative: current_initiative
87
+
88
+ params[:id] = params[:slug]
89
+ @form = form(Decidim::Initiatives::InitiativeForm)
90
+ .from_params(params, initiative_type: current_initiative.type, initiative: current_initiative)
91
+
92
+ UpdateInitiative.call(current_initiative, @form, current_user) do
93
+ on(:ok) do |initiative|
94
+ flash[:notice] = I18n.t("success", scope: "decidim.initiatives.update")
95
+ redirect_to initiative_path(initiative)
96
+ end
97
+
98
+ on(:invalid) do
99
+ flash.now[:alert] = I18n.t("error", scope: "decidim.initiatives.update")
100
+ render :edit, layout: "decidim/initiative"
101
+ end
102
+ end
103
+ end
104
+
105
+ def print
106
+ enforce_permission_to :read, :initiative, initiative: current_initiative
107
+ end
108
+
52
109
  private
53
110
 
54
111
  alias current_initiative current_participatory_space
@@ -0,0 +1,61 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ class ApproveMembershipRequestEvent < Decidim::Events::BaseEvent
6
+ include Decidim::Events::EmailEvent
7
+ include Decidim::Events::NotificationEvent
8
+
9
+ def email_subject
10
+ I18n.t(
11
+ "decidim.initiatives.events.approve_membership_request.email_subject",
12
+ author_nickname: author_nickname
13
+ )
14
+ end
15
+
16
+ def email_intro
17
+ I18n.t(
18
+ "decidim.initiatives.events.approve_membership_request.email_intro",
19
+ resource_title: resource_title,
20
+ resource_url: resource_url,
21
+ author_profile_url: author_profile_url,
22
+ author_nickname: author_nickname
23
+ )
24
+ end
25
+
26
+ def email_outro
27
+ I18n.t(
28
+ "decidim.initiatives.events.approve_membership_request.email_outro",
29
+ resource_title: resource_title,
30
+ resource_url: resource_url
31
+ )
32
+ end
33
+
34
+ def notification_title
35
+ I18n.t(
36
+ "decidim.initiatives.events.approve_membership_request.notification_title",
37
+ resource_title: resource_title,
38
+ resource_url: resource_url,
39
+ author_profile_url: author_profile_url,
40
+ author_nickname: author_nickname
41
+ ).html_safe
42
+ end
43
+
44
+ private
45
+
46
+ def author_nickname
47
+ author.nickname
48
+ end
49
+
50
+ def author_profile_url
51
+ author.profile_url
52
+ end
53
+
54
+ def author
55
+ @author ||= Decidim::UserPresenter.new(
56
+ Decidim::User.find(@extra["author"]["id"])
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,19 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ class InitiativeSentToTechnicalValidationEvent < Decidim::Events::SimpleEvent
6
+ include Rails.application.routes.mounted_helpers
7
+
8
+ i18n_attributes :admin_initiative_url, :admin_initiative_path
9
+
10
+ def admin_initiative_path
11
+ ResourceLocatorPresenter.new(resource).edit
12
+ end
13
+
14
+ def admin_initiative_url
15
+ decidim_admin_initiatives.edit_initiative_url(resource, resource.mounted_params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,61 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ class RevokeMembershipRequestEvent < Decidim::Events::BaseEvent
6
+ include Decidim::Events::EmailEvent
7
+ include Decidim::Events::NotificationEvent
8
+
9
+ def email_subject
10
+ I18n.t(
11
+ "decidim.initiatives.events.revoke_membership_request.email_subject",
12
+ author_nickname: author_nickname
13
+ )
14
+ end
15
+
16
+ def email_intro
17
+ I18n.t(
18
+ "decidim.initiatives.events.revoke_membership_request.email_intro",
19
+ resource_title: resource_title,
20
+ resource_url: resource_url,
21
+ author_profile_url: author_profile_url,
22
+ author_nickname: author_nickname
23
+ )
24
+ end
25
+
26
+ def email_outro
27
+ I18n.t(
28
+ "decidim.initiatives.events.revoke_membership_request.email_outro",
29
+ resource_title: resource_title,
30
+ resource_url: resource_url
31
+ )
32
+ end
33
+
34
+ def notification_title
35
+ I18n.t(
36
+ "decidim.initiatives.events.revoke_membership_request.notification_title",
37
+ resource_title: resource_title,
38
+ resource_url: resource_url,
39
+ author_profile_url: author_profile_url,
40
+ author_nickname: author_nickname
41
+ ).html_safe
42
+ end
43
+
44
+ private
45
+
46
+ def author_nickname
47
+ author.nickname
48
+ end
49
+
50
+ def author_profile_url
51
+ author.profile_url
52
+ end
53
+
54
+ def author
55
+ @author ||= Decidim::UserPresenter.new(
56
+ Decidim::User.find(@extra["author"]["id"])
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,61 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ class SpawnCommitteeRequestEvent < Decidim::Events::BaseEvent
6
+ include Decidim::Events::EmailEvent
7
+ include Decidim::Events::NotificationEvent
8
+
9
+ def email_subject
10
+ I18n.t(
11
+ "decidim.initiatives.events.spawn_committee_request_event.email_subject",
12
+ applicant_nickname: applicant_nickname
13
+ )
14
+ end
15
+
16
+ def email_intro
17
+ I18n.t(
18
+ "decidim.initiatives.events.spawn_committee_request_event.email_intro",
19
+ resource_title: resource_title,
20
+ resource_url: resource_url,
21
+ applicant_profile_url: applicant_profile_url,
22
+ applicant_nickname: applicant_nickname
23
+ )
24
+ end
25
+
26
+ def email_outro
27
+ I18n.t(
28
+ "decidim.initiatives.events.spawn_committee_request_event.email_outro",
29
+ resource_title: resource_title,
30
+ resource_url: resource_url
31
+ )
32
+ end
33
+
34
+ def notification_title
35
+ I18n.t(
36
+ "decidim.initiatives.events.spawn_committee_request_event.notification_title",
37
+ resource_title: resource_title,
38
+ resource_url: resource_url,
39
+ applicant_profile_url: applicant_profile_url,
40
+ applicant_nickname: applicant_nickname
41
+ ).html_safe
42
+ end
43
+
44
+ private
45
+
46
+ def applicant_nickname
47
+ applicant.nickname
48
+ end
49
+
50
+ def applicant_profile_url
51
+ applicant.profile_url
52
+ end
53
+
54
+ def applicant
55
+ @applicant ||= Decidim::UserPresenter.new(
56
+ Decidim::User.find(@extra["applicant"]["id"])
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
@@ -23,7 +23,7 @@ module Decidim
23
23
  attribute :state, String
24
24
  attribute :attachment, AttachmentForm
25
25
 
26
- validates :title, :description, presence: true
26
+ validates :title, :description, translatable_presence: true
27
27
  validates :area, presence: true, if: ->(form) { form.area_id.present? }
28
28
  validates :signature_type, presence: true, if: :signature_type_updatable?
29
29
  validates :signature_start_date, presence: true, if: ->(form) { form.context.initiative.published? }
@@ -38,6 +38,8 @@ module Decidim
38
38
  validate :notify_missing_attachment_if_errored
39
39
  validate :area_is_not_removed
40
40
 
41
+ # rubocop:disable Metrics/CyclomaticComplexity
42
+ # rubocop:disable Metrics/PerceivedComplexity
41
43
  def map_model(model)
42
44
  self.type_id = model.type.id
43
45
  self.decidim_scope_id = model.scope&.id
@@ -59,12 +61,14 @@ module Decidim
59
61
  end
60
62
  end
61
63
  end
64
+ # rubocop:enable Metrics/CyclomaticComplexity
65
+ # rubocop:enable Metrics/PerceivedComplexity
62
66
 
63
67
  def signature_type_updatable?
64
68
  @signature_type_updatable ||= begin
65
- state ||= context.initiative.state
66
- state == "validating" && context.current_user.admin? || state == "created"
67
- end
69
+ state ||= context.initiative.state
70
+ state == "validating" && context.current_user.admin? || state == "created"
71
+ end
68
72
  end
69
73
 
70
74
  def state_updatable?