decidim-participatory_processes 0.20.1 → 0.21.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.
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