decidim-initiatives 0.23.6 → 0.24.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) 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/commands/decidim/initiatives/admin/update_initiative.rb +3 -3
  10. data/app/commands/decidim/initiatives/admin/update_initiative_answer.rb +3 -3
  11. data/app/commands/decidim/initiatives/approve_membership_request.rb +40 -0
  12. data/app/commands/decidim/initiatives/create_initiative.rb +5 -4
  13. data/app/commands/decidim/initiatives/revoke_membership_request.rb +40 -0
  14. data/app/commands/decidim/initiatives/send_initiative_to_technical_validation.rb +57 -0
  15. data/app/commands/decidim/initiatives/spawn_committee_request.rb +18 -0
  16. data/app/commands/decidim/initiatives/update_initiative.rb +74 -0
  17. data/app/controllers/decidim/initiatives/admin/committee_requests_controller.rb +15 -4
  18. data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +1 -1
  19. data/app/controllers/decidim/initiatives/admin/moderations/reports_controller.rb +18 -0
  20. data/app/controllers/decidim/initiatives/committee_requests_controller.rb +32 -0
  21. data/app/controllers/decidim/initiatives/initiatives_controller.rb +58 -1
  22. data/app/events/decidim/initiatives/approve_membership_request_event.rb +61 -0
  23. data/app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb +19 -0
  24. data/app/events/decidim/initiatives/revoke_membership_request_event.rb +61 -0
  25. data/app/events/decidim/initiatives/spawn_committee_request_event.rb +61 -0
  26. data/app/forms/decidim/initiatives/admin/initiative_form.rb +8 -4
  27. data/app/forms/decidim/initiatives/admin/initiative_type_form.rb +3 -0
  28. data/app/forms/decidim/initiatives/initiative_form.rb +25 -2
  29. data/app/forms/decidim/initiatives/vote_form.rb +1 -1
  30. data/app/helpers/decidim/initiatives/admin/initiative_admin_menu_helper.rb +15 -0
  31. data/app/helpers/decidim/initiatives/create_initiative_helper.rb +3 -2
  32. data/app/models/concerns/decidim/initiatives/has_area.rb +1 -1
  33. data/app/models/decidim/initiative.rb +0 -1
  34. data/app/permissions/decidim/initiatives/admin/permissions.rb +5 -4
  35. data/app/permissions/decidim/initiatives/permissions.rb +47 -20
  36. data/app/queries/decidim/initiatives/initiatives_promoted.rb +1 -1
  37. data/app/queries/decidim/initiatives/organization_prioritized_initiatives.rb +13 -2
  38. data/app/serializers/decidim/initiatives/initiative_serializer.rb +3 -0
  39. data/app/services/decidim/initiatives/dummy_timestamp.rb +1 -1
  40. data/app/services/decidim/initiatives/initiative_search.rb +15 -13
  41. data/app/services/decidim/initiatives/pdf_signature_example.rb +27 -27
  42. data/app/views/decidim/initiatives/admin/initiatives/edit.html.erb +1 -1
  43. data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +6 -0
  44. data/app/views/decidim/initiatives/admin/initiatives_type_scopes/edit.html.erb +24 -17
  45. data/app/views/decidim/initiatives/admin/initiatives_type_scopes/new.html.erb +17 -11
  46. data/app/views/decidim/initiatives/admin/initiatives_types/index.html.erb +1 -1
  47. data/app/views/decidim/initiatives/create_initiative/_finish_help.html.erb +2 -7
  48. data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +4 -17
  49. data/app/views/decidim/initiatives/create_initiative/finish.html.erb +11 -11
  50. data/app/views/decidim/initiatives/initiatives/_committee_members.html.erb +73 -0
  51. data/app/views/decidim/initiatives/initiatives/_form.html.erb +112 -0
  52. data/app/views/decidim/initiatives/initiatives/_result.html.erb +1 -1
  53. data/app/views/decidim/initiatives/initiatives/_send_to_technical_validation.html.erb +8 -0
  54. data/app/views/decidim/initiatives/initiatives/edit.html.erb +78 -0
  55. data/app/views/decidim/initiatives/initiatives/print.html.erb +156 -0
  56. data/app/views/decidim/initiatives/initiatives/show.html.erb +19 -7
  57. data/app/views/layouts/decidim/admin/initiative.html.erb +0 -1
  58. data/app/views/layouts/decidim/admin/initiatives.html.erb +2 -15
  59. data/config/locales/ar.yml +3 -28
  60. data/config/locales/ca.yml +62 -32
  61. data/config/locales/cs.yml +112 -52
  62. data/config/locales/de.yml +91 -31
  63. data/config/locales/el.yml +3 -34
  64. data/config/locales/en.yml +94 -34
  65. data/config/locales/es-MX.yml +9 -36
  66. data/config/locales/es-PY.yml +9 -36
  67. data/config/locales/es.yml +10 -37
  68. data/config/locales/eu.yml +3 -28
  69. data/config/locales/fi-plain.yml +94 -34
  70. data/config/locales/fi.yml +94 -34
  71. data/config/locales/fr-CA.yml +96 -36
  72. data/config/locales/fr.yml +96 -36
  73. data/config/locales/gl.yml +3 -36
  74. data/config/locales/hu.yml +3 -32
  75. data/config/locales/id-ID.yml +3 -28
  76. data/config/locales/is-IS.yml +3 -13
  77. data/config/locales/it.yml +3 -34
  78. data/config/locales/ja.yml +2 -35
  79. data/config/locales/lv.yml +3 -32
  80. data/config/locales/nl.yml +31 -34
  81. data/config/locales/no.yml +2 -32
  82. data/config/locales/pl.yml +78 -33
  83. data/config/locales/pt-BR.yml +3 -28
  84. data/config/locales/pt.yml +4 -35
  85. data/config/locales/ro-RO.yml +3 -35
  86. data/config/locales/ru.yml +3 -21
  87. data/config/locales/sk.yml +3 -30
  88. data/config/locales/sr-CS.yml +0 -7
  89. data/config/locales/sv.yml +2 -37
  90. data/config/locales/tr-TR.yml +68 -34
  91. data/config/locales/uk.yml +3 -21
  92. data/config/locales/zh-CN.yml +2 -35
  93. data/db/migrate/20171017095143_update_initiative_scoped_type.rb +0 -1
  94. data/db/migrate/20191107134847_add_scopes_to_initiatives_votes.rb +1 -1
  95. data/db/migrate/20191118105634_allow_multiple_offline_votes.rb +1 -1
  96. data/lib/decidim/api/initiative_api_type.rb +26 -0
  97. data/lib/decidim/api/initiative_committee_member_type.rb +18 -0
  98. data/lib/decidim/api/initiative_type.rb +49 -0
  99. data/lib/decidim/api/initiative_type_interface.rb +8 -3
  100. data/lib/decidim/initiatives/admin_engine.rb +23 -1
  101. data/lib/decidim/initiatives/api.rb +3 -0
  102. data/lib/decidim/initiatives/engine.rb +14 -9
  103. data/lib/decidim/initiatives/initiatives_filter_form_builder.rb +19 -12
  104. data/lib/decidim/initiatives/participatory_space.rb +6 -6
  105. data/lib/decidim/initiatives/query_extensions.rb +42 -19
  106. data/lib/decidim/initiatives/test/factories.rb +36 -0
  107. data/lib/decidim/initiatives/version.rb +1 -1
  108. data/lib/decidim/initiatives.rb +1 -0
  109. metadata +34 -19
  110. data/app/types/decidim/initiatives/initiative_api_type.rb +0 -26
  111. data/app/types/decidim/initiatives/initiative_committee_member_type.rb +0 -18
  112. data/app/types/decidim/initiatives/initiative_type.rb +0 -42
@@ -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?
@@ -5,6 +5,8 @@ module Decidim
5
5
  module Admin
6
6
  # A form object used to collect the all the initiative type attributes.
7
7
  class InitiativeTypeForm < Decidim::Form
8
+ DEFAULT_MINIMUM_COMMITTEE_MEMBERS = 2
9
+
8
10
  include TranslatableAttributes
9
11
 
10
12
  mimic :initiatives_type
@@ -39,6 +41,7 @@ module Decidim
39
41
 
40
42
  def minimum_committee_members
41
43
  return 0 unless promoting_committee_enabled?
44
+ return DEFAULT_MINIMUM_COMMITTEE_MEMBERS if super.blank?
42
45
 
43
46
  super
44
47
  end
@@ -5,6 +5,7 @@ module Decidim
5
5
  # A form object used to collect the data for a new initiative.
6
6
  class InitiativeForm < Form
7
7
  include TranslatableAttributes
8
+ include AttachmentAttributes
8
9
 
9
10
  mimic :initiative
10
11
 
@@ -18,6 +19,10 @@ module Decidim
18
19
  attribute :signature_end_date, Date
19
20
  attribute :state, String
20
21
  attribute :attachment, AttachmentForm
22
+ attribute :hashtag, String
23
+
24
+ attachments_attribute :photos
25
+ attachments_attribute :documents
21
26
 
22
27
  validates :title, :description, presence: true
23
28
  validates :title, length: { maximum: 150 }
@@ -40,6 +45,14 @@ module Decidim
40
45
  state == "created" || state.nil?
41
46
  end
42
47
 
48
+ def state_updatable?
49
+ false
50
+ end
51
+
52
+ def area_updatable?
53
+ @area_updatable ||= current_user.admin? || context.initiative.created?
54
+ end
55
+
43
56
  def scope_id
44
57
  return nil if initiative_type.only_global_scope_enabled?
45
58
 
@@ -51,7 +64,7 @@ module Decidim
51
64
  end
52
65
 
53
66
  def initiative_type
54
- @initiative_type ||= InitiativesType.find(type_id)
67
+ @initiative_type ||= type_id ? InitiativesType.find(type_id) : context.initiative.type
55
68
  end
56
69
 
57
70
  def available_scopes
@@ -66,12 +79,22 @@ module Decidim
66
79
  @scope ||= Scope.find(scope_id) if scope_id.present?
67
80
  end
68
81
 
82
+ def scoped_type_id
83
+ return unless type && scope_id
84
+
85
+ type.scopes.find_by(decidim_scopes_id: scope_id.presence).id
86
+ end
87
+
69
88
  private
70
89
 
90
+ def type
91
+ @type ||= type_id ? Decidim::InitiativesType.find(type_id) : context.initiative.type
92
+ end
93
+
71
94
  def scope_exists
72
95
  return if scope_id.blank?
73
96
 
74
- errors.add(:scope_id, :invalid) unless InitiativesTypeScope.where(type: initiative_type, scope: scope).exists?
97
+ errors.add(:scope_id, :invalid) unless InitiativesTypeScope.exists?(type: initiative_type, scope: scope)
75
98
  end
76
99
 
77
100
  # This method will add an error to the `attachment` field only if there's
@@ -141,7 +141,7 @@ module Decidim
141
141
 
142
142
  # Private: Checks if there's any existing vote that matches the user's data.
143
143
  def already_voted?
144
- errors.add(:document_number, :taken) if initiative.votes.where(hash_id: hash_id, scope: scope).exists?
144
+ errors.add(:document_number, :taken) if initiative.votes.exists?(hash_id: hash_id, scope: scope)
145
145
  end
146
146
 
147
147
  def author
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ module Admin
6
+ module InitiativeAdminMenuHelper
7
+ include Decidim::Admin::SidebarMenuHelper
8
+
9
+ def admin_initiatives_menu
10
+ @admin_initiatives_menu ||= sidebar_menu(:admin_initiatives_menu)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -10,9 +10,10 @@ module Decidim
10
10
  type = ::Decidim::InitiativesType.find(initiative_form.type_id)
11
11
  allowed_signatures = type.allowed_signature_types_for_initiatives
12
12
 
13
- if allowed_signatures == %w(online)
13
+ case allowed_signatures
14
+ when %w(online)
14
15
  online_signature_type_options
15
- elsif allowed_signatures == %w(offline)
16
+ when %w(offline)
16
17
  offline_signature_type_options
17
18
  else
18
19
  all_signature_type_options
@@ -23,7 +23,7 @@ module Decidim
23
23
  def area_belongs_to_organization
24
24
  return unless area && organization
25
25
 
26
- errors.add(:area, :invalid) unless areas.where(id: area.id).exists?
26
+ errors.add(:area, :invalid) unless areas.exists?(id: area.id)
27
27
  end
28
28
  end
29
29
  end
@@ -29,7 +29,6 @@ module Decidim
29
29
  class_name: "Decidim::Organization"
30
30
 
31
31
  belongs_to :scoped_type,
32
- foreign_key: "scoped_type_id",
33
32
  class_name: "Decidim::InitiativesTypeScope",
34
33
  inverse_of: :initiatives
35
34
 
@@ -198,10 +198,11 @@ module Decidim
198
198
  end
199
199
 
200
200
  def allowed_to_send_to_technical_validation?
201
- initiative.created? && (
202
- !initiative.created_by_individual? ||
203
- initiative.enough_committee_members?
204
- )
201
+ initiative.discarded? ||
202
+ (initiative.created? && (
203
+ !initiative.created_by_individual? ||
204
+ initiative.enough_committee_members?
205
+ ))
205
206
  end
206
207
  end
207
208
  end
@@ -4,11 +4,6 @@ module Decidim
4
4
  module Initiatives
5
5
  class Permissions < Decidim::DefaultPermissions
6
6
  def permissions
7
- if read_admin_dashboard_action?
8
- user_can_read_admin_dashboard?
9
- return permission_action
10
- end
11
-
12
7
  # Delegate the admin permission checks to the admin permissions class
13
8
  return Decidim::Initiatives::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
14
9
  return permission_action if permission_action.scope != :public
@@ -23,6 +18,8 @@ module Decidim
23
18
  return permission_action unless user
24
19
 
25
20
  create_initiative?
21
+ edit_public_initiative?
22
+ update_public_initiative?
26
23
 
27
24
  vote_initiative?
28
25
  sign_initiative?
@@ -30,6 +27,9 @@ module Decidim
30
27
 
31
28
  initiative_attachment?
32
29
 
30
+ initiative_committee_action?
31
+ send_to_technical_validation?
32
+
33
33
  permission_action
34
34
  end
35
35
 
@@ -72,6 +72,18 @@ module Decidim
72
72
  toggle_allow(creation_enabled?)
73
73
  end
74
74
 
75
+ def edit_public_initiative?
76
+ allow! if permission_action.subject == :initiative &&
77
+ permission_action.action == :edit
78
+ end
79
+
80
+ def update_public_initiative?
81
+ return unless permission_action.subject == :initiative &&
82
+ permission_action.action == :update
83
+
84
+ toggle_allow(initiative.created?)
85
+ end
86
+
75
87
  def creation_enabled?
76
88
  Decidim::Initiatives.creation_enabled && (
77
89
  Decidim::Initiatives.do_not_require_authorization ||
@@ -108,21 +120,6 @@ module Decidim
108
120
  )
109
121
  end
110
122
 
111
- def has_initiatives?
112
- (InitiativesCreated.by(user) | InitiativesPromoted.by(user)).any?
113
- end
114
-
115
- def read_admin_dashboard_action?
116
- permission_action.action == :read &&
117
- permission_action.subject == :admin_dashboard
118
- end
119
-
120
- def user_can_read_admin_dashboard?
121
- return unless user
122
-
123
- allow! if has_initiatives?
124
- end
125
-
126
123
  def vote_initiative?
127
124
  return unless permission_action.action == :vote &&
128
125
  permission_action.subject == :initiative
@@ -189,6 +186,36 @@ module Decidim
189
186
  UserAuthorizations.for(user).any?
190
187
  )
191
188
  end
189
+
190
+ def initiative_committee_action?
191
+ return unless permission_action.subject == :initiative_committee_member
192
+
193
+ request = context.fetch(:request, nil)
194
+ return unless user.admin? || initiative&.has_authorship?(user)
195
+
196
+ case permission_action.action
197
+ when :index
198
+ allow!
199
+ when :approve
200
+ toggle_allow(!request&.accepted?)
201
+ when :revoke
202
+ toggle_allow(!request&.rejected?)
203
+ end
204
+ end
205
+
206
+ def send_to_technical_validation?
207
+ return unless permission_action.action == :send_to_technical_validation &&
208
+ permission_action.subject == :initiative
209
+
210
+ toggle_allow(allowed_to_send_to_technical_validation?)
211
+ end
212
+
213
+ def allowed_to_send_to_technical_validation?
214
+ initiative.created? && (
215
+ !initiative.created_by_individual? ||
216
+ initiative.enough_committee_members?
217
+ )
218
+ end
192
219
  end
193
220
  end
194
221
  end
@@ -25,7 +25,7 @@ module Decidim
25
25
  Initiative
26
26
  .joins(:committee_members)
27
27
  .where("decidim_initiatives_committee_members.state = 2")
28
- .where("decidim_initiatives_committee_members.decidim_users_id = ?", user.id)
28
+ .where(decidim_initiatives_committee_members: { decidim_users_id: user.id })
29
29
  end
30
30
  end
31
31
  end
@@ -4,13 +4,24 @@ module Decidim
4
4
  module Initiatives
5
5
  # This query retrieves the organization prioritized initiatives that will appear in the homepage
6
6
  class OrganizationPrioritizedInitiatives < Rectify::Query
7
- attr_reader :organization
7
+ attr_reader :organization, :order
8
8
 
9
- def initialize(organization)
9
+ def initialize(organization, order)
10
10
  @organization = organization
11
+ @order = order
11
12
  end
12
13
 
13
14
  def query
15
+ if order == "most_recent"
16
+ base_query.order_by_most_recently_published
17
+ else
18
+ base_query
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def base_query
14
25
  Decidim::Initiative.where(organization: organization).published.open
15
26
  end
16
27
  end
@@ -24,6 +24,9 @@ module Decidim
24
24
  authors: {
25
25
  id: resource.author_users.map(&:id),
26
26
  name: resource.author_users.map(&:name)
27
+ },
28
+ area: {
29
+ name: resource.area&.name
27
30
  }
28
31
  }
29
32
  end
@@ -15,7 +15,7 @@ module Decidim
15
15
 
16
16
  # Public: Timestamp generated from data
17
17
  def timestamp
18
- @timestamp ||= Base64.encode64(OpenSSL::Digest::SHA1.digest("#{@document}-#{Time.current}")).chop
18
+ @timestamp ||= Base64.encode64(OpenSSL::Digest.digest("SHA1", "#{@document}-#{Time.current}")).chop
19
19
  end
20
20
  end
21
21
  end
@@ -45,18 +45,14 @@ module Decidim
45
45
 
46
46
  # Handle the state filter
47
47
  def search_state
48
- accepted = state.member?("accepted") ? query.accepted : nil
49
- rejected = state.member?("rejected") ? query.rejected : nil
50
- answered = state.member?("answered") ? query.answered : nil
51
- open = state.member?("open") ? query.open : nil
52
- closed = state.member?("closed") ? query.closed : nil
53
-
54
- query
55
- .where(id: accepted)
56
- .or(query.where(id: rejected))
57
- .or(query.where(id: answered))
58
- .or(query.where(id: open))
59
- .or(query.where(id: closed))
48
+ ids = []
49
+ ids += state.member?("accepted") ? query.accepted.ids : []
50
+ ids += state.member?("rejected") ? query.rejected.ids : []
51
+ ids += state.member?("answered") ? query.answered.ids : []
52
+ ids += state.member?("open") ? query.open.ids : []
53
+ ids += state.member?("closed") ? query.closed.ids : []
54
+
55
+ query.where(id: ids)
60
56
  end
61
57
 
62
58
  def search_type_id
@@ -69,7 +65,13 @@ module Decidim
69
65
 
70
66
  def search_author
71
67
  if author == "myself" && options[:current_user]
72
- query.where(decidim_author_id: options[:current_user].id)
68
+ co_authoring_initiative_ids = Decidim::InitiativesCommitteeMember.where(
69
+ decidim_users_id: options[:current_user].id
70
+ ).pluck(:decidim_initiatives_id)
71
+
72
+ query.where(decidim_author_id: options[:current_user].id, decidim_author_type: Decidim::UserBaseEntity.name)
73
+ .or(query.where(id: co_authoring_initiative_ids))
74
+ .unscope(where: :published_at)
73
75
  else
74
76
  query
75
77
  end