decidim-participatory_processes 0.20.1 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/participatory_processes/admin/participatory_processes.js.es6 +6 -0
  3. data/app/cells/decidim/participatory_processes/statistic/show.erb +9 -0
  4. data/app/cells/decidim/participatory_processes/statistic_cell.rb +20 -0
  5. data/app/cells/decidim/participatory_processes/statistics/show.erb +17 -0
  6. data/app/cells/decidim/participatory_processes/statistics_cell.rb +18 -0
  7. data/app/commands/decidim/participatory_processes/admin/create_participatory_process.rb +13 -3
  8. data/app/commands/decidim/participatory_processes/admin/update_participatory_process.rb +16 -5
  9. data/app/controllers/concerns/decidim/participatory_processes/admin/filterable.rb +27 -0
  10. data/app/controllers/decidim/participatory_processes/admin/participatory_processes_controller.rb +6 -16
  11. data/app/controllers/decidim/participatory_processes/participatory_processes_controller.rb +17 -3
  12. data/app/forms/decidim/participatory_processes/admin/participatory_process_form.rb +13 -0
  13. data/app/functions/decidim/participatory_processes/participatory_process_finder.rb +10 -0
  14. data/app/functions/decidim/participatory_processes/participatory_process_list.rb +11 -0
  15. data/app/helpers/decidim/participatory_processes/admin/participatory_process_helper.rb +23 -0
  16. data/app/models/decidim/participatory_process.rb +12 -1
  17. data/app/models/decidim/participatory_process_user_role.rb +32 -0
  18. data/app/permissions/decidim/participatory_processes/permissions.rb +9 -0
  19. data/app/presenters/decidim/participatory_processes/participatory_process_stats_presenter.rb +32 -22
  20. data/app/queries/decidim/participatory_processes/stats_followers_count.rb +46 -0
  21. data/app/queries/decidim/participatory_processes/stats_participants_count.rb +98 -0
  22. data/app/serializers/decidim/participatory_processes/participatory_process_importer.rb +2 -0
  23. data/app/serializers/decidim/participatory_processes/participatory_process_serializer.rb +1 -0
  24. data/app/types/decidim/participatory_processes/participatory_process_group_type.rb +20 -0
  25. data/app/types/decidim/participatory_processes/participatory_process_input_filter.rb +13 -0
  26. data/app/types/decidim/participatory_processes/participatory_process_input_sort.rb +15 -0
  27. data/app/types/decidim/participatory_processes/participatory_process_step_type.rb +7 -4
  28. data/app/types/decidim/participatory_processes/participatory_process_type.rb +8 -4
  29. data/app/views/decidim/participatory_processes/admin/participatory_processes/_form.html.erb +31 -0
  30. data/app/views/decidim/participatory_processes/admin/participatory_processes/index.html.erb +18 -15
  31. data/app/views/decidim/participatory_processes/participatory_processes/_metrics.html.erb +1 -1
  32. data/app/views/decidim/participatory_processes/participatory_processes/{statistics.html.erb → all_metrics.html.erb} +0 -0
  33. data/app/views/decidim/participatory_processes/participatory_processes/show.html.erb +15 -1
  34. data/app/views/layouts/decidim/_process_navigation.html.erb +1 -1
  35. data/app/views/layouts/decidim/admin/participatory_process.html.erb +2 -2
  36. data/config/locales/ar.yml +9 -4
  37. data/config/locales/ca.yml +15 -5
  38. data/config/locales/cs.yml +15 -5
  39. data/config/locales/de.yml +6 -4
  40. data/config/locales/el.yml +1 -0
  41. data/config/locales/en.yml +15 -5
  42. data/config/locales/es-MX.yml +14 -4
  43. data/config/locales/es-PY.yml +14 -4
  44. data/config/locales/es.yml +15 -5
  45. data/config/locales/eu.yml +6 -4
  46. data/config/locales/fi-plain.yml +14 -4
  47. data/config/locales/fi.yml +14 -4
  48. data/config/locales/fr.yml +6 -4
  49. data/config/locales/gl.yml +6 -4
  50. data/config/locales/hu.yml +14 -4
  51. data/config/locales/id-ID.yml +6 -4
  52. data/config/locales/is-IS.yml +4 -0
  53. data/config/locales/it.yml +6 -4
  54. data/config/locales/nl.yml +6 -4
  55. data/config/locales/no.yml +11 -4
  56. data/config/locales/pl.yml +6 -4
  57. data/config/locales/pt-BR.yml +6 -4
  58. data/config/locales/pt.yml +6 -4
  59. data/config/locales/ru.yml +5 -3
  60. data/config/locales/sv.yml +6 -4
  61. data/config/locales/tr-TR.yml +6 -4
  62. data/config/locales/uk.yml +5 -3
  63. data/db/migrate/20200114142253_add_scope_type_to_participatory_processes.rb +7 -0
  64. data/db/migrate/20200204154917_add_show_metrics_to_participatory_processes.rb +7 -0
  65. data/lib/decidim/participatory_processes/engine.rb +21 -4
  66. data/lib/decidim/participatory_processes/participatory_space.rb +6 -0
  67. data/lib/decidim/participatory_processes/query_extensions.rb +40 -0
  68. data/lib/decidim/participatory_processes/test/factories.rb +20 -0
  69. data/lib/decidim/participatory_processes/version.rb +1 -1
  70. metadata +27 -11
  71. data/app/views/decidim/participatory_processes/participatory_process_widgets/show.html.erb +0 -17
  72. data/app/views/decidim/participatory_processes/participatory_processes/_statistics.html.erb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e51dd87a6714362621127c05f6e897001e7d80e22f20c7275a8698664159e6e
4
- data.tar.gz: 620305f1c0192fa325840d638a85bfea843c475d1752d720e76309cd7a712e70
3
+ metadata.gz: 2d739759631aca0408a7ae0aba4ff332eae1e0f2f0da9687baa753fdecfb1882
4
+ data.tar.gz: 5db3ca8acfbc423b83176a45dd67bc6b24083824264b367ccdc7b603b1b8bb68
5
5
  SHA512:
6
- metadata.gz: 5206e778fc1a08899d6585eda85c66fedff736ef8cb37a1b869486bad53c8afcfe72d6a93127c56a8bac49d7d7e212c5ba11b6ae47bc9bd46a6889b4d8528adf
7
- data.tar.gz: ee14a93572445a8560bc7055fded2f46c3a001ffaf382bed0fc1260051c8152dadcd25c644b335ecfa3e157b6b16a9c4eca9e9bc13d0ab67a33fce87b387b3a2
6
+ metadata.gz: 71fd380d50a0bf51fac1e84ee82de34dae3c8412ddac11e7f102d91809f928af6c6d62e58c2809649067aeabcdbf8fb4992831a37876567f372901d177809b06
7
+ data.tar.gz: c33eca9c58ce8cb093178232584a70916ccc314920de56443475abf129363d94e0f8cd86840ad1ae29536cbadbb8252b490ddaa93ce88002e613fd6432d00e97
@@ -2,11 +2,17 @@ $(() => {
2
2
  ((exports) => {
3
3
  const $participatoryProcessScopeEnabled = $("#participatory_process_scopes_enabled");
4
4
  const $participatoryProcessScopeId = $("#participatory_process_scope_id");
5
+ const $participatoryProcessScopeTypeId = $("#participatory_process_scope_type_max_depth_id");
5
6
 
6
7
  if ($(".edit_participatory_process, .new_participatory_process").length > 0) {
7
8
  $participatoryProcessScopeEnabled.on("change", (event) => {
8
9
  const checked = event.target.checked;
9
10
  exports.theDataPicker.enabled($participatoryProcessScopeId, checked);
11
+ if (checked === true) {
12
+ $participatoryProcessScopeTypeId.removeAttr("disabled");
13
+ } else {
14
+ $participatoryProcessScopeTypeId.attr("disabled", true)
15
+ }
10
16
  })
11
17
  exports.theDataPicker.enabled($participatoryProcessScopeId, $participatoryProcessScopeEnabled.prop("checked"));
12
18
  }
@@ -0,0 +1,9 @@
1
+ <div class="process-stats__data">
2
+ <span class="process-stats__number">
3
+ <%= stat_number %>
4
+ </span>
5
+
6
+ <h4 class="process-stats__title">
7
+ <%= stat_title %>
8
+ </h4>
9
+ </div>
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatoryProcesses
5
+ # This cell renders a Statistic of a ParticipatoryProcesses
6
+ class StatisticCell < Decidim::ViewModel
7
+ include ActionView::Helpers::NumberHelper
8
+
9
+ private
10
+
11
+ def stat_number
12
+ number_with_delimiter(model[:stat_number])
13
+ end
14
+
15
+ def stat_title
16
+ t(model[:stat_title], scope: "decidim.participatory_processes.statistics")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ <section class="row statistics" id="participatory_process-statistics">
2
+ <div class="columns large-8">
3
+ <div class="row column">
4
+ <h4 class="section-heading">
5
+ <%= stats_heading %>
6
+ </h4>
7
+
8
+ <div class="process-stats">
9
+ <% if model.present? %>
10
+ <%= cell("decidim/participatory_processes/statistic", collection: model) %>
11
+ <% else %>
12
+ <span class="muted"><%= no_stats %></span>
13
+ <% end %>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </section>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatoryProcesses
5
+ # This cell renders the Statistics of a ParticipatoryProcesses
6
+ class StatisticsCell < Decidim::ViewModel
7
+ private
8
+
9
+ def stats_heading
10
+ t("statistics.headline", scope: "decidim.participatory_processes")
11
+ end
12
+
13
+ def no_stats
14
+ t("statistics.no_stats", scope: "decidim.participatory_processes")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -22,10 +22,11 @@ module Decidim
22
22
  def call
23
23
  return broadcast(:invalid) if form.invalid?
24
24
 
25
- process = create_participatory_process
25
+ create_participatory_process
26
26
 
27
27
  if process.persisted?
28
28
  add_admins_as_followers(process)
29
+ link_related_processes
29
30
  broadcast(:ok, process)
30
31
  else
31
32
  form.errors.add(:hero_image, process.errors[:hero_image]) if process.errors.include? :hero_image
@@ -36,10 +37,10 @@ module Decidim
36
37
 
37
38
  private
38
39
 
39
- attr_reader :form
40
+ attr_reader :form, :process
40
41
 
41
42
  def create_participatory_process
42
- process = ParticipatoryProcess.new(
43
+ @process = ParticipatoryProcess.new(
43
44
  organization: form.current_organization,
44
45
  title: form.title,
45
46
  subtitle: form.subtitle,
@@ -52,6 +53,7 @@ module Decidim
52
53
  promoted: form.promoted,
53
54
  scopes_enabled: form.scopes_enabled,
54
55
  scope: form.scope,
56
+ scope_type_max_depth: form.scope_type_max_depth,
55
57
  private_space: form.private_space,
56
58
  developer_group: form.developer_group,
57
59
  local_area: form.local_area,
@@ -105,6 +107,14 @@ module Decidim
105
107
  Decidim::CreateFollow.new(form, admin).call
106
108
  end
107
109
  end
110
+
111
+ def related_processes
112
+ @related_processes ||= Decidim::ParticipatoryProcess.where(id: form.related_process_ids)
113
+ end
114
+
115
+ def link_related_processes
116
+ process.link_participatory_space_resources(related_processes, "related_processes")
117
+ end
108
118
  end
109
119
  end
110
120
  end
@@ -41,13 +41,14 @@ module Decidim
41
41
 
42
42
  def update_participatory_process
43
43
  @participatory_process.assign_attributes(attributes)
44
- if @participatory_process.valid?
45
- @participatory_process.save!
44
+ return unless @participatory_process.valid?
45
+
46
+ @participatory_process.save!
46
47
 
47
- Decidim.traceability.perform_action!(:update, @participatory_process, form.current_user) do
48
- @participatory_process
49
- end
48
+ Decidim.traceability.perform_action!(:update, @participatory_process, form.current_user) do
49
+ @participatory_process
50
50
  end
51
+ link_related_processes
51
52
  end
52
53
 
53
54
  def attributes
@@ -65,6 +66,7 @@ module Decidim
65
66
  short_description: form.short_description,
66
67
  scopes_enabled: form.scopes_enabled,
67
68
  scope: form.scope,
69
+ scope_type_max_depth: form.scope_type_max_depth,
68
70
  private_space: form.private_space,
69
71
  developer_group: form.developer_group,
70
72
  local_area: form.local_area,
@@ -76,10 +78,19 @@ module Decidim
76
78
  start_date: form.start_date,
77
79
  end_date: form.end_date,
78
80
  participatory_process_group: form.participatory_process_group,
81
+ show_metrics: form.show_metrics,
79
82
  show_statistics: form.show_statistics,
80
83
  announcement: form.announcement
81
84
  }
82
85
  end
86
+
87
+ def related_processes
88
+ @related_processes ||= Decidim::ParticipatoryProcess.where(id: form.related_process_ids)
89
+ end
90
+
91
+ def link_related_processes
92
+ @participatory_process.link_participatory_space_resources(related_processes, "related_processes")
93
+ end
83
94
  end
84
95
  end
85
96
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module ParticipatoryProcesses
7
+ module Admin
8
+ module Filterable
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Decidim::Admin::Filterable
13
+
14
+ private
15
+
16
+ def base_query
17
+ collection
18
+ end
19
+
20
+ def extra_filters
21
+ [:decidim_participatory_process_group_id_eq]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -7,18 +7,19 @@ module Decidim
7
7
  #
8
8
  class ParticipatoryProcessesController < Decidim::ParticipatoryProcesses::Admin::ApplicationController
9
9
  include Decidim::Admin::ParticipatorySpaceAdminContext
10
+ include Decidim::ParticipatoryProcesses::Admin::Filterable
10
11
  participatory_space_admin_layout only: [:edit]
11
- include Decidim::Paginable
12
12
 
13
13
  helper ProcessGroupsForSelectHelper
14
+ helper Decidim::ParticipatoryProcesses::Admin::ParticipatoryProcessHelper
14
15
 
15
- helper_method :current_participatory_process, :current_participatory_space, :query
16
+ helper_method :current_participatory_process, :current_participatory_space, :process_group
16
17
 
17
18
  layout "decidim/admin/participatory_processes"
18
19
 
19
20
  def index
20
21
  enforce_permission_to :read, :process_list
21
- @participatory_processes = collection
22
+ @participatory_processes = filtered_collection
22
23
  end
23
24
 
24
25
  def new
@@ -76,22 +77,11 @@ module Decidim
76
77
  private
77
78
 
78
79
  def process_group
79
- @process_group ||= ParticipatoryProcessGroup.find_by(id: params[:group_id])
80
- end
81
-
82
- def participatory_processes
83
- @participatory_processes ||= Rectify::Query.merge(
84
- ParticipatoryProcessesWithUserRole.for(current_user),
85
- ParticipatoryProcessesByGroup.for(process_group)
86
- )
87
- end
88
-
89
- def query
90
- @query ||= participatory_processes.ransack(params[:q])
80
+ @process_group ||= ParticipatoryProcessGroup.find_by(id: ransack_params[:decidim_participatory_process_group_id_eq])
91
81
  end
92
82
 
93
83
  def collection
94
- @collection ||= paginate(query.result)
84
+ @collection ||= ParticipatoryProcessesWithUserRole.for(current_user)
95
85
  end
96
86
 
97
87
  def current_participatory_process
@@ -6,10 +6,16 @@ module Decidim
6
6
  # public layout.
7
7
  class ParticipatoryProcessesController < Decidim::ParticipatoryProcesses::ApplicationController
8
8
  include ParticipatorySpaceContext
9
- participatory_space_layout only: [:show, :statistics]
9
+ participatory_space_layout only: [:show, :all_metrics]
10
10
  include FilterResource
11
11
 
12
- helper_method :collection, :promoted_participatory_processes, :participatory_processes, :stats, :metrics, :default_date_filter
12
+ helper_method :collection,
13
+ :promoted_participatory_processes,
14
+ :participatory_processes,
15
+ :stats,
16
+ :metrics,
17
+ :default_date_filter,
18
+ :related_processes
13
19
 
14
20
  def index
15
21
  raise ActionController::RoutingError, "Not Found" if published_processes.none?
@@ -22,7 +28,7 @@ module Decidim
22
28
  enforce_permission_to :read, :process, process: current_participatory_space
23
29
  end
24
30
 
25
- def statistics
31
+ def all_metrics
26
32
  enforce_permission_to :read, :process, process: current_participatory_space
27
33
  end
28
34
 
@@ -92,6 +98,14 @@ module Decidim
92
98
 
93
99
  "all"
94
100
  end
101
+
102
+ def related_processes
103
+ @related_processes ||=
104
+ current_participatory_space
105
+ .linked_participatory_space_resources(:participatory_processes, "related_processes")
106
+ .published
107
+ .all
108
+ end
95
109
  end
96
110
  end
97
111
  end
@@ -29,10 +29,13 @@ module Decidim
29
29
  attribute :area_id, Integer
30
30
  attribute :participatory_process_group_id, Integer
31
31
  attribute :scope_id, Integer
32
+ attribute :related_process_ids, Array[Integer]
33
+ attribute :scope_type_max_depth_id, Integer
32
34
 
33
35
  attribute :private_space, Boolean
34
36
  attribute :promoted, Boolean
35
37
  attribute :scopes_enabled, Boolean
38
+ attribute :show_metrics, Boolean
36
39
  attribute :show_statistics, Boolean
37
40
 
38
41
  attribute :end_date, Decidim::Attributes::LocalizedDate
@@ -61,12 +64,18 @@ module Decidim
61
64
  def map_model(model)
62
65
  self.scope_id = model.decidim_scope_id
63
66
  self.participatory_process_group_id = model.decidim_participatory_process_group_id
67
+ self.related_process_ids = model.linked_participatory_space_resources(:participatory_process, "related_processes").pluck(:id)
68
+ @processes = Decidim::ParticipatoryProcess.where(organization: model.organization).where.not(id: model.id)
64
69
  end
65
70
 
66
71
  def scope
67
72
  @scope ||= current_organization.scopes.find_by(id: scope_id)
68
73
  end
69
74
 
75
+ def scope_type_max_depth
76
+ @scope_type_max_depth ||= current_organization.scope_types.find_by(id: scope_type_max_depth_id)
77
+ end
78
+
70
79
  def area
71
80
  @area ||= current_organization.areas.find_by(id: area_id)
72
81
  end
@@ -75,6 +84,10 @@ module Decidim
75
84
  Decidim::ParticipatoryProcessGroup.find_by(id: participatory_process_group_id)
76
85
  end
77
86
 
87
+ def processes
88
+ @processes ||= Decidim::ParticipatoryProcess.where(organization: current_organization)
89
+ end
90
+
78
91
  private
79
92
 
80
93
  def organization_participatory_processes
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatoryProcesses
5
+ # Adds slug finder for participatory_processes
6
+ class ParticipatoryProcessFinder < Decidim::Core::ParticipatorySpaceFinder
7
+ argument :slug, types.String, "The slug of the participatory process"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatoryProcesses
5
+ # Adds some filter values for participatory_processes
6
+ class ParticipatoryProcessList < Decidim::Core::ParticipatorySpaceListBase
7
+ argument :filter, ParticipatoryProcessInputFilter, "This argument let's you filter the results"
8
+ argument :order, ParticipatoryProcessInputSort, "This argument let's you order the results"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatoryProcesses
5
+ module Admin
6
+ # Helpers related to the Admin of Participatory Process layout.
7
+ module ParticipatoryProcessHelper
8
+ def scope_type_depth_select_options
9
+ {
10
+ include_blank: true,
11
+ selected: current_participatory_process.try(:decidim_scope_type_id)
12
+ }
13
+ end
14
+
15
+ def scope_type_depth_select_html_options
16
+ html_options = {}
17
+ html_options[:disabled] = "disabled" unless current_participatory_process.try(:scopes_enabled)
18
+ html_options
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -49,6 +49,10 @@ module Decidim
49
49
  foreign_type: "decidim_participatory_space_type",
50
50
  dependent: :destroy,
51
51
  as: :participatory_space
52
+ belongs_to :scope_type_max_depth,
53
+ foreign_key: "decidim_scope_type_id",
54
+ class_name: "Decidim::ScopeType",
55
+ optional: true
52
56
 
53
57
  has_many :components, as: :participatory_space, dependent: :destroy
54
58
 
@@ -149,9 +153,16 @@ module Decidim
149
153
  "#{admin_module_name}::Moderators".constantize.for(self)
150
154
  end
151
155
 
156
+ def user_roles(role_name = nil)
157
+ roles = Decidim::ParticipatoryProcessUserRole.where(participatory_process: self)
158
+ return roles if role_name.blank?
159
+
160
+ roles.where(role: role_name)
161
+ end
162
+
152
163
  # Allow ransacker to search for a key in a hstore column (`title`.`en`)
153
164
  ransacker :title do |parent|
154
- Arel::Nodes::InfixOperation.new("->", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s))
165
+ Arel::Nodes::InfixOperation.new("->>", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s))
155
166
  end
156
167
  end
157
168
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Defines a relation between a user and a participatory process, and what
5
+ # kind of relation does the user has.
6
+ class ParticipatoryProcessUserRole < ApplicationRecord
7
+ include Traceable
8
+ include Loggable
9
+
10
+ belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User", optional: true
11
+ belongs_to :participatory_process, foreign_key: "decidim_participatory_process_id", class_name: "Decidim::ParticipatoryProcess", optional: true
12
+
13
+ alias participatory_space participatory_process
14
+
15
+ ROLES = %w(admin collaborator moderator valuator).freeze
16
+ validates :role, inclusion: { in: ROLES }, uniqueness: { scope: [:user, :participatory_process] }
17
+ validate :user_and_participatory_process_same_organization
18
+
19
+ def self.log_presenter_class_for(_log)
20
+ Decidim::ParticipatoryProcesses::AdminLog::ParticipatoryProcessUserRolePresenter
21
+ end
22
+
23
+ private
24
+
25
+ # Private: check if the process and the user have the same organization
26
+ def user_and_participatory_process_same_organization
27
+ return if !participatory_process || !user
28
+
29
+ errors.add(:participatory_process, :invalid) unless user.organization == participatory_process.organization
30
+ end
31
+ end
32
+ end