decidim-initiatives 0.11.2 → 0.12.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -6
  3. data/app/assets/config/decidim_initiatives_manifest.css +4 -0
  4. data/app/assets/config/decidim_initiatives_manifest.js +0 -2
  5. data/app/assets/stylesheet/decidim/initiatives/{application.css.scss → initiatives.scss} +0 -1
  6. data/app/cells/decidim/initiatives/initiative_cell.rb +19 -0
  7. data/app/cells/decidim/initiatives/initiative_m/author.erb +10 -0
  8. data/app/cells/decidim/initiatives/initiative_m/footer.erb +28 -0
  9. data/app/cells/decidim/initiatives/initiative_m/tags.erb +9 -0
  10. data/app/cells/decidim/initiatives/initiative_m_cell.rb +45 -0
  11. data/app/commands/decidim/initiatives/vote_initiative.rb +22 -0
  12. data/app/controllers/concerns/decidim/initiatives/admin/initiative_admin.rb +0 -4
  13. data/app/controllers/concerns/decidim/initiatives/needs_initiative.rb +18 -23
  14. data/app/controllers/decidim/initiatives/admin/application_controller.rb +13 -0
  15. data/app/controllers/decidim/initiatives/admin/committee_requests_controller.rb +4 -4
  16. data/app/controllers/decidim/initiatives/admin/initiative_attachments_controller.rb +1 -1
  17. data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +11 -11
  18. data/app/controllers/decidim/initiatives/admin/initiatives_type_scopes_controller.rb +5 -5
  19. data/app/controllers/decidim/initiatives/admin/initiatives_types_controller.rb +7 -7
  20. data/app/controllers/decidim/initiatives/application_controller.rb +30 -0
  21. data/app/controllers/decidim/initiatives/committee_requests_controller.rb +4 -5
  22. data/app/controllers/decidim/initiatives/create_initiative_controller.rb +3 -3
  23. data/app/controllers/decidim/initiatives/initiative_types_controller.rb +2 -2
  24. data/app/controllers/decidim/initiatives/initiative_votes_controller.rb +3 -17
  25. data/app/controllers/decidim/initiatives/initiatives_controller.rb +3 -7
  26. data/app/controllers/decidim/initiatives/initiatives_type_scopes_controller.rb +2 -2
  27. data/app/events/decidim/initiatives/endorse_initiative_event.rb +4 -45
  28. data/app/events/decidim/initiatives/milestone_completed_event.rb +17 -0
  29. data/app/models/decidim/initiative.rb +5 -4
  30. data/app/models/decidim/initiatives_committee_member.rb +1 -0
  31. data/app/permissions/decidim/initiatives/admin/permissions.rb +188 -0
  32. data/app/permissions/decidim/initiatives/permissions.rb +139 -0
  33. data/app/presenters/decidim/initiative_presenter.rb +16 -0
  34. data/app/views/decidim/initiatives/_initiative.html.erb +1 -35
  35. data/app/views/decidim/initiatives/admin/committee_requests/index.html.erb +2 -3
  36. data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +3 -3
  37. data/app/views/decidim/initiatives/admin/initiatives/edit.html.erb +8 -8
  38. data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +4 -4
  39. data/app/views/decidim/initiatives/admin/initiatives_type_scopes/edit.html.erb +1 -1
  40. data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +0 -2
  41. data/app/views/decidim/initiatives/admin/initiatives_types/_initiative_type_scopes.html.erb +2 -2
  42. data/app/views/decidim/initiatives/admin/initiatives_types/edit.html.erb +1 -1
  43. data/app/views/decidim/initiatives/admin/initiatives_types/index.html.erb +2 -2
  44. data/app/views/decidim/initiatives/committee_requests/new.html.erb +3 -5
  45. data/app/views/decidim/initiatives/initiatives/_index_header.html.erb +2 -2
  46. data/app/views/decidim/initiatives/initiatives/_vote_button.html.erb +17 -15
  47. data/app/views/decidim/initiatives/initiatives/_vote_cabin.html.erb +1 -1
  48. data/app/views/decidim/initiatives/initiatives/index.html.erb +0 -1
  49. data/app/views/decidim/initiatives/initiatives/show.html.erb +0 -1
  50. data/app/views/decidim/initiatives/initiatives/signature_identities.html.erb +15 -13
  51. data/app/views/layouts/decidim/admin/initiative.html.erb +9 -6
  52. data/app/views/layouts/decidim/admin/initiatives.html.erb +11 -3
  53. data/app/views/layouts/decidim/initiative_creation.html.erb +0 -1
  54. data/config/locales/ca.yml +31 -11
  55. data/config/locales/en.yml +32 -11
  56. data/config/locales/es.yml +33 -12
  57. data/config/locales/eu.yml +32 -11
  58. data/config/locales/fi.yml +32 -11
  59. data/config/locales/fr.yml +32 -11
  60. data/config/locales/gl.yml +32 -11
  61. data/config/locales/it.yml +32 -11
  62. data/config/locales/nl.yml +32 -11
  63. data/config/locales/pl.yml +42 -13
  64. data/config/locales/pt-BR.yml +32 -11
  65. data/config/locales/pt.yml +32 -11
  66. data/config/locales/sv.yml +32 -11
  67. data/config/locales/uk.yml +43 -14
  68. data/db/migrate/20171109132011_enable_pg_trgm_extension_for_initiatives.rb +18 -0
  69. data/lib/decidim/initiatives/admin_engine.rb +1 -15
  70. data/lib/decidim/initiatives/engine.rb +6 -11
  71. data/lib/decidim/initiatives/participatory_space.rb +12 -4
  72. data/lib/decidim/initiatives/test/factories.rb +17 -1
  73. data/lib/decidim/initiatives/version.rb +1 -1
  74. metadata +27 -29
  75. data/app/controllers/concerns/decidim/initiatives/action_authorization.rb +0 -38
  76. data/app/models/decidim/initiatives/abilities/admin/attachments_ability.rb +0 -55
  77. data/app/models/decidim/initiatives/abilities/admin/committee_admin_ability.rb +0 -36
  78. data/app/models/decidim/initiatives/abilities/admin/committee_user_ability.rb +0 -50
  79. data/app/models/decidim/initiatives/abilities/admin/components_ability.rb +0 -24
  80. data/app/models/decidim/initiatives/abilities/admin/initiative_admin_ability.rb +0 -65
  81. data/app/models/decidim/initiatives/abilities/admin/initiative_type_ability.rb +0 -42
  82. data/app/models/decidim/initiatives/abilities/admin/initiative_user_ability.rb +0 -68
  83. data/app/models/decidim/initiatives/abilities/current_user_ability.rb +0 -58
  84. data/app/models/decidim/initiatives/abilities/everyone_ability.rb +0 -22
  85. data/app/models/decidim/initiatives/abilities/non_logged_user_ability.rb +0 -33
  86. data/app/models/decidim/initiatives/abilities/vote_ability.rb +0 -57
  87. data/app/views/decidim/initiatives/initiatives/_supports_count.html.erb +0 -6
  88. data/db/migrate/20171109132011_enable_pg_extensions.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85b49951df772290c17d5dbbcbc158714fd9c7ae3d61367db4a14939af58d4ff
4
- data.tar.gz: a235a85a56dc09c438697ef9fb40d6efcbbb5bd82dd189ba8a0a420436499131
3
+ metadata.gz: 2e4f368e7e323149582fc5f3b1b534f3df4960a0542e62dabd662d7f8b125712
4
+ data.tar.gz: 5c308bcdb44e01d2da25acffee04de184d2095953c83e43eddc70998b0c643a8
5
5
  SHA512:
6
- metadata.gz: 37f74292693c899abc25c6724868399d2a5766adfeee672c883fd535c05be90d497766aee0a869139836f180a1e08f163ae42e38dcb41c33a52a64b064afdf6a
7
- data.tar.gz: a2f8e3ee32fb82992e330848f809419a21e92af2281cd811b92e43e46f80fbc372b1e8830589f11524f9e3a10c9d6c1248d83a8d1fec7f9aa2a3ce7d7ab6db88
6
+ metadata.gz: d0ca8ef5da535026a5ff015ef53d63b128ae9c0661d272c9c661758bba7afd38382db99c60f02adaf4c61699e787551bf2a3fb06eaea4ebef5a2eab83ac59a0f
7
+ data.tar.gz: 92fc692caeda181328619c2ca9a95b2fc427aae50f72d1cfa847bc07f3bd392e53fa2937837cc1bfb7913b599b7d427ef8d5b3e558b8eca4f148637e1538442a
data/README.md CHANGED
@@ -71,14 +71,14 @@ __Decidim::Initiatives.first_notification_percentage__ and __Decidim::Initiative
71
71
 
72
72
  Author, members of the promoter committee and followers will receive it.
73
73
 
74
- ## Exporting online votes
74
+ ## Exporting online signatures
75
75
 
76
- When the supporting method is set to any or face to face it may be necessary to implement
77
- a mechanism to validate that do not exist duplicated supports. To do so the engine provides
78
- a functionality that allows exporting the online votes to validate them against physical
79
- votes.
76
+ When the signature method is set to any or face to face it may be necessary to implement
77
+ a mechanism to validate that there are no duplicated signatures. To do so the engine provides
78
+ a functionality that allows exporting the online signatures to validate them against physical
79
+ signatures.
80
80
 
81
- The votes are exported as a hash string in order to preserve the identity of the voter.
81
+ The signatures are exported as a hash string in order to preserve the identity of the signer together with her privacy.
82
82
  Each hash is composed with the following criteria:
83
83
 
84
84
  * Algorithm used: SHA1
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= link decidim/initiatives/initiatives.css
3
+ *= link decidim/initiatives/social_share.css
4
+ */
@@ -1,7 +1,5 @@
1
1
  //= link decidim/initiatives/social_share.js
2
2
  //= link decidim/initiatives/application.js
3
- //= link decidim/initiatives/application.css
4
- //= link decidim/initiatives/social_share.css
5
3
  //= link decidim/initiatives/identity_selector_dialog.js
6
4
  //= link decidim/initiatives/scoped_type.js
7
5
  //= link decidim/initiatives/admin/invite_users.js
@@ -1,4 +1,3 @@
1
- @import "decidim/editor";
2
1
  @import "popularity_item";
3
2
  @import "statistics";
4
3
  @import "admin";
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ # This cell renders the process card for an instance of an Initiative
6
+ # the default size is the Medium Card (:m)
7
+ class InitiativeCell < Decidim::ViewModel
8
+ def show
9
+ cell card_size, model
10
+ end
11
+
12
+ private
13
+
14
+ def card_size
15
+ "decidim/initiatives/initiative_m"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ <div class="card__author">
2
+ <%= cell(
3
+ "decidim/collapsible_list",
4
+ authors,
5
+ size: :small,
6
+ cell_name: "decidim/author",
7
+ hidden_elements_count_i18n_key: "decidim.initiatives.initiatives.author_list.hidden_authors_count",
8
+ cell_options: { extra_classes: ["author-data--small"] }
9
+ ) %>
10
+ </div>
@@ -0,0 +1,28 @@
1
+ <div class="card__footer card__footer--spaces">
2
+ <div class="card__support">
3
+ <% if model.published? %>
4
+ <div class="card__support__data">
5
+ <%= cell(
6
+ "decidim/progress_bar",
7
+ model.supports_count,
8
+ total: model.scoped_type.supports_required,
9
+ units_name: "decidim.initiatives.initiatives.signatures_count",
10
+ element_id: "initiative-#{model.id}-signatures-count",
11
+ small: true
12
+ ) %>
13
+ </div>
14
+ <% else %>
15
+ <div class="card__support__data"></div>
16
+ <% end %>
17
+
18
+ <% if model.closed? || model.offline? %>
19
+ <%= link_to t("initiatives.initiative.check", scope: "layouts.decidim"),
20
+ resource_path,
21
+ class: "card__button button button--sc small light secondary" %>
22
+ <% else %>
23
+ <%= link_to t("initiatives.initiative.check_and_support", scope: "layouts.decidim"),
24
+ resource_path,
25
+ class: "card__button button button--sc small light secondary" %>
26
+ <% end %>
27
+ </div>
28
+ </div>
@@ -0,0 +1,9 @@
1
+ <% if model.hashtag.present? %>
2
+ <%= link_to_if(
3
+ "##{model.hashtag}",
4
+ "https://twitter.com/hashtag/#{model.hashtag}",
5
+ class: "card__text--category",
6
+ target: "_blank"
7
+ ) %>
8
+ <% end %>
9
+ <%= render partial: "decidim/initiatives/initiatives/tags.html", locals: { resource: model } %>
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ # This cell renders the Medium (:m) initiative card
6
+ # for an given instance of an Initiative
7
+ class InitiativeMCell < Decidim::CardMCell
8
+ include Decidim::Initiatives::Engine.routes.url_helpers
9
+
10
+ property :state
11
+
12
+ private
13
+
14
+ def has_state?
15
+ true
16
+ end
17
+
18
+ def state_classes
19
+ case state
20
+ when "accepted", "published"
21
+ ["success"]
22
+ when "rejected", "discarded"
23
+ ["alert"]
24
+ when "validating"
25
+ ["warning"]
26
+ else
27
+ ["muted"]
28
+ end
29
+ end
30
+
31
+ def resource_path
32
+ initiative_path(model)
33
+ end
34
+
35
+ def resource_icon
36
+ icon "initiatives", class: "icon--big"
37
+ end
38
+
39
+ def authors
40
+ [present(model).author] +
41
+ model.committee_members.approved.non_deleted.map { |member| present(member.user) }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -25,8 +25,12 @@ module Decidim
25
25
  build_initiative_vote
26
26
  return broadcast(:invalid) unless vote.valid?
27
27
 
28
+ percentage_before = @initiative.percentage
28
29
  vote.save!
29
30
  send_notification
31
+ percentage_after = @initiative.reload.percentage
32
+
33
+ notify_percentage_change(percentage_before, percentage_after)
30
34
 
31
35
  broadcast(:ok, vote)
32
36
  end
@@ -52,6 +56,24 @@ module Decidim
52
56
  recipient_ids: @initiative.author.followers.pluck(:id)
53
57
  )
54
58
  end
59
+
60
+ def notify_percentage_change(before, after)
61
+ percentage = [25, 50, 75, 100].find do |milestone|
62
+ before < milestone && after >= milestone
63
+ end
64
+
65
+ return unless percentage
66
+
67
+ Decidim::EventsManager.publish(
68
+ event: "decidim.events.initiatives.milestone_completed",
69
+ event_class: Decidim::Initiatives::MilestoneCompletedEvent,
70
+ resource: @initiative,
71
+ recipient_ids: @initiative.followers.pluck(:id),
72
+ extra: {
73
+ percentage: percentage
74
+ }
75
+ )
76
+ end
55
77
  end
56
78
  end
57
79
  end
@@ -20,10 +20,6 @@ module Decidim
20
20
 
21
21
  alias_method :current_participatory_space, :current_initiative
22
22
  end
23
-
24
- def current_participatory_space
25
- @current_participatory_space ||= Decidim::Initiative.find_by(id: id_from_slug(params[:initiative_slug]))
26
- end
27
23
  end
28
24
  end
29
25
  end
@@ -1,31 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module Decidim
4
6
  module Initiatives
5
7
  # This module, when injected into a controller, ensures there's an
6
8
  # initiative available and deducts it from the context.
7
9
  module NeedsInitiative
8
- def self.enhance_controller(instance_or_module)
9
- instance_or_module.class_eval do
10
- helper_method :current_initiative
11
- end
12
- end
13
-
14
- def self.extended(base)
15
- base.extend Decidim::NeedsOrganization, InstanceMethods
10
+ extend ActiveSupport::Concern
16
11
 
17
- enhance_controller(base)
18
- end
19
-
20
- def self.included(base)
21
- base.include Decidim::NeedsOrganization, InstanceMethods
22
-
23
- enhance_controller(base)
24
- end
25
-
26
- module InstanceMethods
12
+ included do
13
+ include NeedsOrganization
27
14
  include InitiativeSlug
28
15
 
16
+ helper_method :current_initiative
17
+
29
18
  # Public: Finds the current Initiative given this controller's
30
19
  # context.
31
20
  #
@@ -34,14 +23,10 @@ module Decidim
34
23
  @current_initiative ||= detect_initiative
35
24
  end
36
25
 
37
- alias current_participatory_space current_initiative
26
+ alias_method :current_participatory_space, :current_initiative
38
27
 
39
28
  private
40
29
 
41
- def ability_context
42
- super.merge(current_participatory_space: current_initiative)
43
- end
44
-
45
30
  def detect_initiative
46
31
  request.env["current_initiative"] ||
47
32
  Initiative.find_by(
@@ -49,6 +34,16 @@ module Decidim
49
34
  organization: current_organization
50
35
  )
51
36
  end
37
+
38
+ def permission_class_chain
39
+ list = [
40
+ Decidim::Initiatives::Permissions,
41
+ Decidim::Admin::Permissions
42
+ ]
43
+
44
+ return list if permission_scope == :admin
45
+ list << Decidim::Permissions
46
+ end
52
47
  end
53
48
  end
54
49
  end
@@ -6,6 +6,19 @@ module Decidim
6
6
  # The main admin application controller for initiatives
7
7
  class ApplicationController < Decidim::Admin::ApplicationController
8
8
  layout "decidim/admin/initiatives"
9
+
10
+ def permissions_context
11
+ super.merge(
12
+ current_participatory_space: try(:current_participatory_space)
13
+ )
14
+ end
15
+
16
+ def permission_class_chain
17
+ [
18
+ Decidim::Initiatives::Permissions,
19
+ Decidim::Admin::Permissions
20
+ ]
21
+ end
9
22
  end
10
23
  end
11
24
  end
@@ -4,17 +4,17 @@ module Decidim
4
4
  module Initiatives
5
5
  module Admin
6
6
  # Controller in charge of managing committee membership
7
- class CommitteeRequestsController < Decidim::Admin::ApplicationController
7
+ class CommitteeRequestsController < Decidim::Initiatives::Admin::ApplicationController
8
8
  include InitiativeAdmin
9
9
 
10
10
  # GET /admin/initiatives/:initiative_id/committee_requests
11
11
  def index
12
- authorize! :index, InitiativesCommitteeMember
12
+ enforce_permission_to :index, :initiative_committee_member
13
13
  end
14
14
 
15
15
  # GET /initiatives/:initiative_id/committee_requests/:id/approve
16
16
  def approve
17
- authorize! :approve, membership_request
17
+ enforce_permission_to :approve, :initiative_committee_member, request: membership_request
18
18
  membership_request.accepted!
19
19
 
20
20
  redirect_to initiative_committee_requests_path(membership_request.initiative)
@@ -22,7 +22,7 @@ module Decidim
22
22
 
23
23
  # DELETE /initiatives/:initiative_id/committee_requests/:id/revoke
24
24
  def revoke
25
- authorize! :revoke, membership_request
25
+ enforce_permission_to :revoke, :initiative_committee_member, request: membership_request
26
26
  membership_request.rejected!
27
27
  redirect_to initiative_committee_requests_path(membership_request.initiative)
28
28
  end
@@ -4,7 +4,7 @@ module Decidim
4
4
  module Initiatives
5
5
  module Admin
6
6
  # Controller that allows managing all the attachments for an initiative
7
- class InitiativeAttachmentsController < Decidim::Admin::ApplicationController
7
+ class InitiativeAttachmentsController < Decidim::Initiatives::Admin::ApplicationController
8
8
  include InitiativeAdmin
9
9
  include Decidim::Admin::Concerns::HasAttachments
10
10
 
@@ -15,7 +15,7 @@ module Decidim
15
15
 
16
16
  # GET /admin/initiatives
17
17
  def index
18
- authorize! :list, Decidim::Initiative
18
+ enforce_permission_to :list, :initiative
19
19
 
20
20
  @query = params[:q]
21
21
  @state = params[:state]
@@ -32,12 +32,12 @@ module Decidim
32
32
 
33
33
  # GET /admin/initiatives/:id
34
34
  def show
35
- authorize! :read, current_initiative
35
+ enforce_permission_to :read, :initiative, initiative: current_initiative
36
36
  end
37
37
 
38
38
  # GET /admin/initiatives/:id/edit
39
39
  def edit
40
- authorize! :edit, current_initiative
40
+ enforce_permission_to :edit, :initiative, initiative: current_initiative
41
41
  @form = form(Decidim::Initiatives::Admin::InitiativeForm)
42
42
  .from_model(
43
43
  current_initiative,
@@ -49,7 +49,7 @@ module Decidim
49
49
 
50
50
  # PUT /admin/initiatives/:id
51
51
  def update
52
- authorize! :update, current_initiative
52
+ enforce_permission_to :update, :initiative, initiative: current_initiative
53
53
 
54
54
  params[:id] = params[:slug]
55
55
  @form = form(Decidim::Initiatives::Admin::InitiativeForm)
@@ -70,7 +70,7 @@ module Decidim
70
70
 
71
71
  # POST /admin/initiatives/:id/publish
72
72
  def publish
73
- authorize! :publish, current_initiative
73
+ enforce_permission_to :publish, :initiative, initiative: current_initiative
74
74
 
75
75
  PublishInitiative.call(current_initiative, current_user) do
76
76
  on(:ok) do
@@ -81,7 +81,7 @@ module Decidim
81
81
 
82
82
  # DELETE /admin/initiatives/:id/unpublish
83
83
  def unpublish
84
- authorize! :unpublish, current_initiative
84
+ enforce_permission_to :unpublish, :initiative, initiative: current_initiative
85
85
 
86
86
  UnpublishInitiative.call(current_initiative, current_user) do
87
87
  on(:ok) do
@@ -92,28 +92,28 @@ module Decidim
92
92
 
93
93
  # DELETE /admin/initiatives/:id/discard
94
94
  def discard
95
- authorize! :discard, current_initiative
95
+ enforce_permission_to :discard, :initiative, initiative: current_initiative
96
96
  current_initiative.discarded!
97
97
  redirect_to decidim_admin_initiatives.initiatives_path
98
98
  end
99
99
 
100
100
  # POST /admin/initiatives/:id/accept
101
101
  def accept
102
- authorize! :accept, current_initiative
102
+ enforce_permission_to :accept, :initiative, initiative: current_initiative
103
103
  current_initiative.accepted!
104
104
  redirect_to decidim_admin_initiatives.initiatives_path
105
105
  end
106
106
 
107
107
  # DELETE /admin/initiatives/:id/reject
108
108
  def reject
109
- authorize! :reject, current_initiative
109
+ enforce_permission_to :reject, :initiative, initiative: current_initiative
110
110
  current_initiative.rejected!
111
111
  redirect_to decidim_admin_initiatives.initiatives_path
112
112
  end
113
113
 
114
114
  # GET /admin/initiatives/:id/send_to_technical_validation
115
115
  def send_to_technical_validation
116
- authorize! :send_to_technical_validation, current_initiative
116
+ enforce_permission_to :send_to_technical_validation, :initiative, initiative: current_initiative
117
117
 
118
118
  SendInitiativeToTechnicalValidation.call(current_initiative, current_user) do
119
119
  on(:ok) do
@@ -129,7 +129,7 @@ module Decidim
129
129
 
130
130
  # GET /admin/initiatives/:id/export_votes
131
131
  def export_votes
132
- authorize! :export_votes, current_initiative
132
+ enforce_permission_to :export_votes, :initiative, initiative: current_initiative
133
133
 
134
134
  votes = current_initiative.votes.votes.map(&:sha1)
135
135
  csv_data = CSV.generate(headers: false) do |csv|