decidim-accountability 0.21.0 → 0.22.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/accountability/admin/accountability_admin.js.es6 +6 -42
  3. data/app/assets/stylesheets/decidim/accountability/accountability/_categories.scss +8 -1
  4. data/app/assets/stylesheets/decidim/accountability/accountability/_lines_breadcrumb.scss +8 -0
  5. data/app/assets/stylesheets/decidim/accountability/accountability/_results.scss +0 -3
  6. data/app/cells/decidim/accountability/highlighted_results_for_component/show.erb +3 -3
  7. data/app/cells/decidim/accountability/highlighted_results_for_component_cell.rb +1 -1
  8. data/app/commands/decidim/accountability/admin/create_imported_result.rb +106 -0
  9. data/app/commands/decidim/accountability/admin/update_imported_result.rb +110 -0
  10. data/app/controllers/decidim/accountability/admin/import_results_controller.rb +34 -0
  11. data/app/controllers/decidim/accountability/admin/results_controller.rb +2 -20
  12. data/app/controllers/decidim/accountability/versions_controller.rb +7 -8
  13. data/app/jobs/application_job.rb +4 -0
  14. data/app/jobs/decidim/accountability/admin/import_results_csv_job.rb +19 -0
  15. data/app/mailers/decidim/accountability/import_mailer.rb +26 -0
  16. data/app/queries/decidim/accountability/metrics/results_metric_manage.rb +2 -8
  17. data/app/services/decidim/accountability/results_csv_importer.rb +139 -0
  18. data/app/views/decidim/accountability/admin/import_results/new.html.erb +22 -0
  19. data/app/views/decidim/accountability/admin/results/_form.html.erb +1 -5
  20. data/app/views/decidim/accountability/admin/results/index.html.erb +1 -0
  21. data/app/views/decidim/accountability/admin/results/proposals_picker.html.erb +1 -0
  22. data/app/views/decidim/accountability/import_mailer/import.html.erb +25 -0
  23. data/app/views/decidim/accountability/results/_linked_results.html.erb +1 -1
  24. data/app/views/decidim/accountability/results/_results_leaf.html.erb +5 -5
  25. data/app/views/decidim/accountability/results/_results_parent.html.erb +2 -2
  26. data/app/views/decidim/accountability/results/_scope_filters.html.erb +16 -3
  27. data/app/views/decidim/accountability/results/_search.html.erb +3 -3
  28. data/app/views/decidim/accountability/results/_stats_box.html.erb +11 -4
  29. data/app/views/decidim/accountability/results/_timeline.html.erb +2 -2
  30. data/app/views/decidim/accountability/versions/index.html.erb +7 -25
  31. data/app/views/decidim/accountability/versions/show.html.erb +9 -31
  32. data/app/views/decidim/participatory_spaces/_result.html.erb +3 -3
  33. data/config/locales/ar.yml +1 -24
  34. data/config/locales/bg-BG.yml +220 -0
  35. data/config/locales/ca.yml +19 -22
  36. data/config/locales/cs.yml +44 -47
  37. data/config/locales/da-DK.yml +1 -0
  38. data/config/locales/de.yml +19 -22
  39. data/config/locales/el.yml +222 -0
  40. data/config/locales/en.yml +19 -22
  41. data/config/locales/es-MX.yml +19 -22
  42. data/config/locales/es-PY.yml +19 -22
  43. data/config/locales/es.yml +19 -22
  44. data/config/locales/et-EE.yml +1 -0
  45. data/config/locales/eu.yml +1 -24
  46. data/config/locales/fi-plain.yml +19 -22
  47. data/config/locales/fi.yml +32 -35
  48. data/config/locales/fr-CA.yml +222 -0
  49. data/config/locales/fr.yml +18 -22
  50. data/config/locales/ga-IE.yml +1 -0
  51. data/config/locales/gl.yml +1 -24
  52. data/config/locales/hr-HR.yml +1 -0
  53. data/config/locales/hu.yml +18 -22
  54. data/config/locales/id-ID.yml +1 -24
  55. data/config/locales/is-IS.yml +1 -21
  56. data/config/locales/it.yml +37 -40
  57. data/config/locales/ja-JP.yml +221 -0
  58. data/config/locales/lt-LT.yml +1 -0
  59. data/config/locales/lv-LV.yml +218 -0
  60. data/config/locales/mt-MT.yml +1 -0
  61. data/config/locales/nl.yml +18 -22
  62. data/config/locales/no.yml +25 -28
  63. data/config/locales/pl.yml +46 -49
  64. data/config/locales/pt-BR.yml +2 -25
  65. data/config/locales/pt.yml +59 -62
  66. data/config/locales/ro-RO.yml +223 -0
  67. data/config/locales/ru.yml +1 -24
  68. data/config/locales/sk-SK.yml +224 -0
  69. data/config/locales/sk.yml +207 -0
  70. data/config/locales/sl.yml +129 -0
  71. data/config/locales/sr-CS.yml +205 -0
  72. data/config/locales/sv.yml +21 -24
  73. data/config/locales/tr-TR.yml +1 -24
  74. data/config/locales/uk.yml +1 -21
  75. data/db/migrate/20200320105903_index_foreign_keys_in_decidim_accountability_results.rb +7 -0
  76. data/lib/decidim/accountability/admin_engine.rb +4 -3
  77. data/lib/decidim/accountability/version.rb +1 -1
  78. metadata +54 -24
  79. data/app/views/decidim/accountability/admin/results/_proposals.html.erb +0 -12
  80. data/app/views/decidim/accountability/versions/_version.html.erb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23e9e9da0373bafcee830512c9e911e0176767832d826719ccae2a52b441f2f2
4
- data.tar.gz: 6cd880e63873b91f6a0dbdd79e066bbd9e04e9a235aacc895a2cb0bc9f0a483c
3
+ metadata.gz: 5aa01ab3845ef9d564662b490d22e56aaf88d857de85adfb06f3a58d8bd827a8
4
+ data.tar.gz: 44725f2f514ebc97eb45725e26d067406b24b5d6e71affd3aa5f6978ba92260b
5
5
  SHA512:
6
- metadata.gz: 04a259f346030214c5963d31cfd3240ecc58cd6c4d0f222b52b4b20a215475043faa6a430370e285e48aba86d8582fbcf7c7b1246af885fb88e76782470a26c7
7
- data.tar.gz: cd0f61547ca931bf560d0f1a5d9393c1c5548c8d220a86bad841e1ff64a6d07f0a52987919d137af4236dd40a815a723e2ed39dd84d8a99fff0854497be36178
6
+ metadata.gz: 591653254ddaa34353fd6f010b51bfa122675f9abae01e027ee0d3dfedae70837e4f230c01549e68d181025d71d36f4d5458030f12857d556b63a3363d684513
7
+ data.tar.gz: 66c9eb1f5bbf2b68d4a4ae82d5f49161b83e1cef65a435d4e923d20c7e0dba61060dbae6031b484e6ed1915e9baf834153af075bc259b1ef25ef6cbe3e88722d
@@ -1,47 +1,11 @@
1
1
  // = require_self
2
2
 
3
- $("#result_decidim_accountability_status_id").change(function () {
4
- /* eslint-disable no-invalid-this */
5
- const progress = $(this).find(":selected").data("progress")
6
- if (progress || progress === 0) {
7
- $("#result_progress").val(progress);
8
- }
9
- });
10
-
11
3
  $(function() {
12
- $(document).on("open.zf.reveal", "#data_picker-modal", function () {
13
- let xhr = null;
14
-
15
- $("#data_picker-autocomplete").autoComplete({
16
- minChars: 2,
17
- source: function(term, response) {
18
- try {
19
- xhr.abort();
20
- } catch (exception) { xhr = null}
21
-
22
- let url = $("#proposal-picker-choose").attr("href")
23
- xhr = $.getJSON(
24
- url,
25
- { term: term },
26
- function(data) { response(data); }
27
- );
28
- },
29
- renderItem: function (item, search) {
30
- let sanitizedSearch = search.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
31
- let re = new RegExp(`(${sanitizedSearch.split(" ").join("|")})`, "gi");
32
- let title = item[0]
33
- let modelId = item[1]
34
- let val = `#${modelId}- ${title}`;
35
- return `<div class="autocomplete-suggestion" data-model-id="${modelId}" data-val ="${title}">${val.replace(re, "<b>$1</b>")}</div>`;
36
- },
37
- onSelect: function(event, term, item) {
38
- let choose = $("#proposal-picker-choose")
39
- let modelId = item.data("modelId")
40
- let val = `#${modelId}- ${item.data("val")}`;
41
- choose.data("picker-value", modelId)
42
- choose.data("picker-text", val)
43
- choose.data("picker-choose", "")
44
- }
45
- })
4
+ $("#result_decidim_accountability_status_id").change(function () {
5
+ /* eslint-disable no-invalid-this */
6
+ const progress = $(this).find(":selected").data("progress")
7
+ if (progress || progress === 0) {
8
+ $("#result_progress").val(progress);
9
+ }
46
10
  });
47
11
  })
@@ -1,5 +1,13 @@
1
1
  .accountability{
2
2
  .categories{
3
+ a:hover{
4
+ text-decoration: underline;
5
+ }
6
+
7
+ a:focus{
8
+ outline: $anchor-outline-focus;
9
+ }
10
+
3
11
  .categories--header{
4
12
  border-bottom: 1px solid $medium-gray;
5
13
  padding-bottom: 1rem;
@@ -10,7 +18,6 @@
10
18
  }
11
19
 
12
20
  span{
13
- text-transform: uppercase;
14
21
  font-size: 1.15rem;
15
22
  color: lighten($dark-gray, 50);
16
23
  }
@@ -13,6 +13,14 @@
13
13
  a{
14
14
  font-weight: 600;
15
15
  color: $dark-gray;
16
+
17
+ &:hover{
18
+ text-decoration: underline;
19
+ }
20
+
21
+ &:focus{
22
+ outline: 2px solid $secondary;
23
+ }
16
24
  }
17
25
 
18
26
  ul{
@@ -10,7 +10,6 @@
10
10
 
11
11
  p{
12
12
  font-weight: 600;
13
- text-transform: uppercase;
14
13
  margin-bottom: .25rem;
15
14
  display: inline-block;
16
15
  margin-right: .5rem;
@@ -44,7 +43,6 @@
44
43
  .scope-filters{
45
44
  div{
46
45
  color: lighten($dark-gray, 50);
47
- text-transform: uppercase;
48
46
  margin-bottom: .15rem;
49
47
  }
50
48
 
@@ -107,7 +105,6 @@
107
105
  margin-bottom: .5rem;
108
106
 
109
107
  .progress-text{
110
- text-transform: uppercase;
111
108
  color: lighten($dark-gray, 30);
112
109
  }
113
110
 
@@ -1,7 +1,7 @@
1
1
  <section class="section row collapse highlighted_results">
2
- <h4 class="section-heading">
2
+ <h3 class="section-heading">
3
3
  <%= translated_attribute(model.name) %> <a href="<%= main_component_path(model) %>" class="text-small"><%= t("decidim.participatory_spaces.highlighted_results.see_all", count: results_count) %></a>
4
- </h4>
4
+ </h3>
5
5
 
6
6
  <div class="row">
7
7
  <div class="columns accountability">
@@ -16,6 +16,6 @@
16
16
  <%= link_to(
17
17
  t("decidim.participatory_spaces.highlighted_results.see_all", count: results_count),
18
18
  main_component_path(model),
19
- class: "button button--sc light secondary button--right"
19
+ class: "button button--sc hollow button--right"
20
20
  ) %>
21
21
  </section>
@@ -25,7 +25,7 @@ module Decidim
25
25
  end
26
26
 
27
27
  def results_to_render
28
- @results_to_render ||= results.limit(4)
28
+ @results_to_render ||= results.includes(:component, :status).limit(4)
29
29
  end
30
30
 
31
31
  def results_count
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Accountability
5
+ module Admin
6
+ # This command is executed when the user creates a Result from the admin
7
+ # panel.
8
+ class CreateImportedResult < Rectify::Command
9
+ def initialize(form, parent_id = nil)
10
+ @form = form
11
+ @parent_id = parent_id
12
+ end
13
+
14
+ # Creates the result if valid.
15
+ #
16
+ # Broadcasts :ok if successful, :invalid otherwise.
17
+ def call
18
+ return broadcast(:invalid) if @form.invalid?
19
+
20
+ transaction do
21
+ create_result
22
+ link_meetings
23
+ link_proposals
24
+ link_projects
25
+ notify_proposal_followers
26
+ end
27
+
28
+ broadcast(:ok)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :result
34
+
35
+ def create_result
36
+ params = {
37
+ component: @form.current_component,
38
+ scope: @form.scope,
39
+ category: @form.category,
40
+ parent_id: @parent_id,
41
+ title: @form.title,
42
+ description: @form.description,
43
+ start_date: @form.start_date,
44
+ end_date: @form.end_date,
45
+ progress: @form.progress,
46
+ decidim_accountability_status_id: @form.decidim_accountability_status_id,
47
+ external_id: @form.external_id.presence,
48
+ weight: @form.weight
49
+ }
50
+
51
+ @result = Decidim.traceability.create!(
52
+ Result,
53
+ @form.current_user,
54
+ params,
55
+ visibility: "all"
56
+ )
57
+ end
58
+
59
+ def proposals
60
+ @proposals ||= result.sibling_scope(:proposals).where(id: @form.proposal_ids)
61
+ end
62
+
63
+ def projects
64
+ @projects ||= result.sibling_scope(:projects).where(id: @form.project_ids)
65
+ end
66
+
67
+ def meeting_ids
68
+ @meeting_ids ||= proposals.flat_map do |proposal|
69
+ proposal.linked_resources(:meetings, "proposals_from_meeting").pluck(:id)
70
+ end.uniq
71
+ end
72
+
73
+ def meetings
74
+ @meetings ||= result.sibling_scope(:meetings).where(id: meeting_ids)
75
+ end
76
+
77
+ def link_proposals
78
+ result.link_resources(proposals, "included_proposals")
79
+ end
80
+
81
+ def link_projects
82
+ result.link_resources(projects, "included_projects")
83
+ end
84
+
85
+ def link_meetings
86
+ result.link_resources(meetings, "meetings_through_proposals")
87
+ end
88
+
89
+ def notify_proposal_followers
90
+ proposals.each do |proposal|
91
+ Decidim::EventsManager.publish(
92
+ event: "decidim.events.accountability.proposal_linked",
93
+ event_class: Decidim::Accountability::ProposalLinkedEvent,
94
+ resource: result,
95
+ affected_users: proposal.notifiable_identities,
96
+ followers: proposal.followers - proposal.notifiable_identities,
97
+ extra: {
98
+ proposal_id: proposal.id
99
+ }
100
+ )
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Accountability
5
+ module Admin
6
+ # This command is executed when the user changes a Result from the admin
7
+ # panel.
8
+ class UpdateImportedResult < Rectify::Command
9
+ # Initializes an UpdateResult Command.
10
+ #
11
+ # form - The form from which to get the data.
12
+ # result - The current instance of the result to be updated.
13
+ def initialize(form, result, parent_id = nil)
14
+ @form = form
15
+ @result = result
16
+ @parent_id = parent_id
17
+ end
18
+
19
+ # Updates the result if valid.
20
+ #
21
+ # Broadcasts :ok if successful, :invalid otherwise.
22
+ def call
23
+ return broadcast(:invalid) if form.invalid?
24
+
25
+ transaction do
26
+ update_result
27
+ link_proposals
28
+ link_meetings
29
+ link_projects
30
+ send_notifications if should_notify_followers?
31
+ end
32
+
33
+ broadcast(:ok)
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :result, :form
39
+
40
+ def update_result
41
+ Decidim.traceability.update!(
42
+ result,
43
+ form.current_user,
44
+ scope: @form.scope,
45
+ category: @form.category,
46
+ parent_id: @parent_id,
47
+ title: @form.title,
48
+ description: @form.description,
49
+ start_date: @form.start_date,
50
+ end_date: @form.end_date,
51
+ progress: @form.progress,
52
+ decidim_accountability_status_id: @form.decidim_accountability_status_id,
53
+ external_id: @form.external_id.presence,
54
+ weight: @form.weight
55
+ )
56
+ end
57
+
58
+ def proposals
59
+ @proposals ||= result.sibling_scope(:proposals).where(id: form.proposal_ids)
60
+ end
61
+
62
+ def projects
63
+ @projects ||= result.sibling_scope(:projects).where(id: form.project_ids)
64
+ end
65
+
66
+ def meeting_ids
67
+ @meeting_ids ||= proposals.flat_map do |proposal|
68
+ proposal.linked_resources(:meetings, "proposals_from_meeting").pluck(:id)
69
+ end.uniq
70
+ end
71
+
72
+ def meetings
73
+ @meetings ||= result.sibling_scope(:meetings).where(id: meeting_ids)
74
+ end
75
+
76
+ def link_proposals
77
+ result.link_resources(proposals, "included_proposals")
78
+ end
79
+
80
+ def link_projects
81
+ result.link_resources(projects, "included_projects")
82
+ end
83
+
84
+ def link_meetings
85
+ result.link_resources(meetings, "meetings_through_proposals")
86
+ end
87
+
88
+ def send_notifications
89
+ result.linked_resources(:proposals, "included_proposals").each do |proposal|
90
+ Decidim::EventsManager.publish(
91
+ event: "decidim.events.accountability.result_progress_updated",
92
+ event_class: Decidim::Accountability::ResultProgressUpdatedEvent,
93
+ resource: result,
94
+ affected_users: proposal.notifiable_identities,
95
+ followers: proposal.followers - proposal.notifiable_identities,
96
+ extra: {
97
+ progress: result.progress,
98
+ proposal_id: proposal.id
99
+ }
100
+ )
101
+ end
102
+ end
103
+
104
+ def should_notify_followers?
105
+ result.previous_changes["progress"].present?
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Accountability
5
+ module Admin
6
+ # This controller allows an admin to import results from a csv file for the Accountability component
7
+ class ImportResultsController < Admin::ApplicationController
8
+ def new
9
+ @errors = []
10
+ end
11
+
12
+ def create
13
+ @csv_file = params[:csv_file]
14
+ redirect_to(new_import_path) && return if @csv_file.blank?
15
+
16
+ Decidim::Accountability::Admin::ImportResultsCSVJob.perform_later(current_user, current_component, @csv_file.read.force_encoding("utf-8").encode("utf-8"))
17
+
18
+ flash[:notice] = I18n.t("imports.create.success", scope: "decidim.accountability.admin")
19
+ redirect_to import_results_path(current_participatory_process, current_component)
20
+ end
21
+
22
+ private
23
+
24
+ def current_component
25
+ @current_component ||= current_participatory_process.components.find(params[:component_id])
26
+ end
27
+
28
+ def current_participatory_process
29
+ @current_participatory_process ||= ParticipatoryProcess.find_by(slug: params[:participatory_process_slug])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -7,6 +7,8 @@ module Decidim
7
7
  class ResultsController < Admin::ApplicationController
8
8
  include Decidim::ApplicationHelper
9
9
  include Decidim::SanitizeHelper
10
+ include Decidim::Proposals::Admin::Picker
11
+
10
12
  helper_method :results, :parent_result, :parent_results, :statuses, :present
11
13
 
12
14
  def new
@@ -70,26 +72,6 @@ module Decidim
70
72
  end
71
73
  end
72
74
 
73
- def proposals
74
- respond_to do |format|
75
- format.html do
76
- render partial: "proposals"
77
- end
78
- format.json do
79
- query = Decidim.find_resource_manifest(:proposals)
80
- .try(:resource_scope, current_component)&.order(title: :asc)
81
- term = params[:term]
82
- if term&.start_with?("#")
83
- term.delete!("#")
84
- query = query.where("CAST(id AS TEXT) LIKE ?", "#{term}%")
85
- else
86
- query = query.where("title ilike ?", "%#{params[:term]}%")
87
- end
88
- render json: query.all.collect { |p| [decidim_html_escape(present(p).title), p.id] }
89
- end
90
- end
91
- end
92
-
93
75
  private
94
76
 
95
77
  def results
@@ -5,20 +5,19 @@ module Decidim
5
5
  # Exposes result versions so users can see how a result
6
6
  # has been updated through time.
7
7
  class VersionsController < Decidim::Accountability::ApplicationController
8
- helper Decidim::TraceabilityHelper
9
8
  helper Decidim::Accountability::BreadcrumbHelper
10
- helper_method :current_version, :result
9
+ helper_method :result
11
10
 
12
- private
11
+ include Decidim::ResourceVersionsConcern
13
12
 
14
- def result
15
- @result ||= Result.includes(:timeline_entries).where(component: current_component).find(params[:result_id])
13
+ def versioned_resource
14
+ result
16
15
  end
17
16
 
18
- def current_version
19
- return nil if params[:id].to_i < 1
17
+ private
20
18
 
21
- @current_version ||= result.versions[params[:id].to_i - 1]
19
+ def result
20
+ @result ||= Result.includes(:timeline_entries).where(component: current_component).find(params[:result_id])
22
21
  end
23
22
  end
24
23
  end