decidim-core 0.0.8.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_core_manifest.js +0 -1
  3. data/app/assets/javascripts/decidim/form_filter.component.js.es6 +12 -2
  4. data/app/assets/stylesheets/decidim/_decidim.scss +1 -2
  5. data/app/assets/stylesheets/decidim/extras/_embed.scss +21 -0
  6. data/app/assets/stylesheets/decidim/modules/_cards.scss +1 -1
  7. data/app/assets/stylesheets/decidim/modules/_icons.scss +1 -1
  8. data/app/commands/decidim/create_registration.rb +1 -1
  9. data/app/commands/decidim/invite_user.rb +7 -8
  10. data/app/controllers/concerns/decidim/filter_resource.rb +2 -3
  11. data/app/controllers/concerns/decidim/payload_info.rb +1 -1
  12. data/app/controllers/decidim/authorizations_controller.rb +0 -4
  13. data/app/controllers/decidim/pages_controller.rb +8 -11
  14. data/app/controllers/decidim/participatory_process_groups_controller.rb +1 -1
  15. data/app/controllers/decidim/participatory_process_widgets_controller.rb +4 -0
  16. data/app/controllers/decidim/widgets_controller.rb +7 -3
  17. data/app/forms/decidim/registration_form.rb +4 -4
  18. data/app/helpers/decidim/layout_helper.rb +1 -1
  19. data/app/helpers/decidim/map_helper.rb +21 -21
  20. data/app/helpers/decidim/resource_helper.rb +4 -4
  21. data/app/helpers/decidim/widget_urls_helper.rb +2 -2
  22. data/app/mailers/decidim/export_mailer.rb +29 -0
  23. data/app/middleware/decidim/current_organization.rb +1 -1
  24. data/app/models/decidim/feature.rb +5 -0
  25. data/app/models/decidim/organization.rb +1 -1
  26. data/app/models/decidim/participatory_process.rb +1 -1
  27. data/app/models/decidim/user.rb +1 -1
  28. data/app/presenters/decidim/home_stats_presenter.rb +74 -0
  29. data/app/queries/decidim/stats_users_count.rb +24 -0
  30. data/app/services/decidim/public_processes.rb +4 -2
  31. data/app/services/decidim/resource_search.rb +1 -1
  32. data/app/services/decidim/static_map_generator.rb +1 -3
  33. data/app/uploaders/decidim/image_uploader.rb +1 -1
  34. data/app/views/decidim/export_mailer/export.html.erb +1 -0
  35. data/app/views/decidim/participatory_process_widgets/show.html.erb +16 -27
  36. data/app/views/decidim/participatory_processes/show.html.erb +7 -7
  37. data/app/views/decidim/widgets/show.js.erb +27 -17
  38. data/app/views/layouts/decidim/widget.html.erb +55 -3
  39. data/app/views/pages/home/_statistics.html.erb +2 -10
  40. data/config/i18n-tasks.yml +1 -0
  41. data/config/initializers/devise.rb +11 -4
  42. data/config/locales/ca.yml +14 -3
  43. data/config/locales/en.yml +14 -3
  44. data/config/locales/es.yml +13 -2
  45. data/config/locales/eu.yml +0 -2
  46. data/config/locales/fi.yml +0 -2
  47. data/config/locales/fr.yml +386 -1
  48. data/config/locales/nl.yml +1 -3
  49. data/db/seeds.rb +1 -1
  50. data/lib/decidim/core.rb +10 -2
  51. data/lib/decidim/core/api/decidim_type.rb +4 -0
  52. data/lib/decidim/core/api/translated_field_type.rb +2 -2
  53. data/lib/decidim/core/engine.rb +13 -0
  54. data/lib/decidim/core/test/shared_examples/comments_examples.rb +16 -18
  55. data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +2 -2
  56. data/lib/decidim/core/test/shared_examples/reports_examples.rb +9 -9
  57. data/lib/decidim/core/version.rb +1 -1
  58. data/lib/decidim/exporters.rb +9 -0
  59. data/lib/decidim/exporters/csv.rb +54 -0
  60. data/lib/decidim/exporters/export_data.rb +22 -0
  61. data/lib/decidim/exporters/exporter.rb +28 -0
  62. data/lib/decidim/exporters/json.rb +22 -0
  63. data/lib/decidim/feature_manifest.rb +18 -0
  64. data/lib/decidim/file_zipper.rb +28 -0
  65. data/lib/decidim/form_builder.rb +27 -14
  66. data/lib/decidim/has_reference.rb +1 -1
  67. data/lib/decidim/i18n_exceptions.rb +3 -2
  68. data/lib/decidim/query_extensions.rb +1 -1
  69. data/lib/decidim/reportable.rb +1 -1
  70. data/lib/decidim/resource_manifest.rb +0 -7
  71. data/lib/decidim/stats_registry.rb +110 -0
  72. data/vendor/assets/javascripts/form_datepicker.js.es6 +3 -1
  73. metadata +53 -29
  74. data/app/assets/stylesheets/decidim/widget.scss.erb +0 -25
@@ -308,7 +308,7 @@ nl:
308
308
  title: Gebruikersinstellingen
309
309
  user_groups: Organisaties
310
310
  locale:
311
- name: Engels
311
+ name: Nederlands
312
312
  pages:
313
313
  '404':
314
314
  back_home: Terug naar huis
@@ -340,8 +340,6 @@ nl:
340
340
  see_all_processes: Toon alle processen
341
341
  statistics:
342
342
  headline: Huidige stand van %{organization}
343
- processes: Processen
344
- users: Gebruikers
345
343
  sub_hero:
346
344
  register: Registeren
347
345
  social_share_button:
@@ -20,7 +20,7 @@ if !Rails.env.production? || ENV["SEED"]
20
20
  reference_prefix: Faker::Name.suffix
21
21
  )
22
22
 
23
- 3.times.each do |index|
23
+ 3.times.each do
24
24
  Decidim::Scope.create!(
25
25
  name: Faker::Address.unique.state,
26
26
  organization: organization
@@ -24,6 +24,9 @@ module Decidim
24
24
  autoload :HasCategory, "decidim/has_category"
25
25
  autoload :HasReference, "decidim/has_reference"
26
26
  autoload :Attributes, "decidim/attributes"
27
+ autoload :StatsRegistry, "decidim/stats_registry"
28
+ autoload :Exporters, "decidim/exporters"
29
+ autoload :FileZipper, "decidim/file_zipper"
27
30
 
28
31
  include ActiveSupport::Configurable
29
32
 
@@ -79,13 +82,13 @@ module Decidim
79
82
 
80
83
  # Exposes a configuration option: The application name String.
81
84
  config_accessor :available_locales do
82
- %w(en ca es eu fi)
85
+ %w(en ca es eu fi fr nl)
83
86
  end
84
87
 
85
88
  # Exposes a configuration option: an object to configure geocoder
86
89
  config_accessor :geocoder
87
90
 
88
- # Exposes a configuration option: the currency unit
91
+ # Exposes a configuration option: the currency unit
89
92
  config_accessor :currency_unit { "€" }
90
93
 
91
94
  # Exposes a configuration option: The maximum file size of an attachment.
@@ -155,4 +158,9 @@ module Decidim
155
158
  def self.resource_manifests
156
159
  @resource_manifests ||= feature_manifests.flat_map(&:resource_manifests)
157
160
  end
161
+
162
+ # Public: Stores an instance of StatsRegistry
163
+ def self.stats
164
+ @stats ||= StatsRegistry.new
165
+ end
158
166
  end
@@ -8,5 +8,9 @@ module Decidim
8
8
  field :version, !types.String, "The current decidim's version of this deployment." do
9
9
  resolve ->(obj, _args, _ctx) { obj.version }
10
10
  end
11
+
12
+ field :application_name, !types.String, "The current installation's name." do
13
+ resolve ->(obj, _args, _ctx) { obj.application_name }
14
+ end
11
15
  end
12
16
  end
@@ -20,7 +20,7 @@ module Decidim
20
20
  description "A list of locales to scope the translations to."
21
21
  end
22
22
 
23
- resolve ->(obj, args, _ctx) {
23
+ resolve lambda { |obj, args, _ctx|
24
24
  translations = obj.stringify_keys
25
25
  translations = translations.slice(*args["locales"]) if args["locales"]
26
26
 
@@ -33,7 +33,7 @@ module Decidim
33
33
  description "Returns a single translation given a locale."
34
34
  argument :locale, !types.String, "A locale to search for"
35
35
 
36
- resolve ->(obj, args, _ctx) {
36
+ resolve lambda { |obj, args, _ctx|
37
37
  translations = obj.stringify_keys
38
38
  translations[args["locale"]]
39
39
  }
@@ -119,6 +119,19 @@ module Decidim
119
119
  )
120
120
  end
121
121
  end
122
+
123
+ initializer "decidim.stats" do
124
+ Decidim.stats.register :users_count, priority: StatsRegistry::HIGH_PRIORITY do |organization, start_at, end_at|
125
+ StatsUsersCount.for(organization, start_at, end_at)
126
+ end
127
+
128
+ Decidim.stats.register :processes_count, priority: StatsRegistry::HIGH_PRIORITY do |organization, start_at, end_at|
129
+ processes = (OrganizationParticipatoryProcesses.new(organization) | PublicParticipatoryProcesses.new)
130
+ processes = processes.where("created_at >= ?", start_at) if start_at.present?
131
+ processes = processes.where("created_at <= ?", end_at) if end_at.present?
132
+ processes.count
133
+ end
134
+ end
122
135
  end
123
136
  end
124
137
  end
@@ -3,17 +3,15 @@
3
3
  RSpec.shared_examples "comments" do
4
4
  let!(:organization) { create(:organization) }
5
5
  let!(:user) { create(:user, :confirmed, organization: organization) }
6
- let!(:comments) {
7
- 3.times.map do
6
+ let!(:comments) do
7
+ Array.new(3) do
8
8
  create(:comment, commentable: commentable)
9
9
  end
10
- }
10
+ end
11
11
  let(:authenticated) { false }
12
12
 
13
13
  def visit_commentable_path
14
- if authenticated
15
- login_as user, scope: :user
16
- end
14
+ login_as user, scope: :user if authenticated
17
15
  visit resource_path
18
16
  end
19
17
 
@@ -42,13 +40,13 @@ RSpec.shared_examples "comments" do
42
40
  visit_commentable_path
43
41
 
44
42
  within ".order-by" do
45
- page.find('.dropdown.menu .is-dropdown-submenu-parent').hover
43
+ page.find(".dropdown.menu .is-dropdown-submenu-parent").hover
46
44
  end
47
45
 
48
46
  click_link "Best rated"
49
47
 
50
48
  within "#comments" do
51
- expect(page.find('.comment', match: :first)).to have_content "Most Rated Comment"
49
+ expect(page.find(".comment", match: :first)).to have_content "Most Rated Comment"
52
50
  end
53
51
  end
54
52
 
@@ -98,9 +96,9 @@ RSpec.shared_examples "comments" do
98
96
  expect(page).to have_content "This is a new comment"
99
97
  end
100
98
  else
101
- expect {
99
+ expect do
102
100
  wait_for_email subject: "new comment"
103
- }.to raise_error StandardError
101
+ end.to raise_error StandardError
104
102
  end
105
103
  end
106
104
  end
@@ -173,7 +171,7 @@ RSpec.shared_examples "comments" do
173
171
 
174
172
  expect(page).to have_selector(".add-comment form")
175
173
 
176
- page.find('.opinion-toggle--ok').click
174
+ page.find(".opinion-toggle--ok").click
177
175
 
178
176
  within ".add-comment form" do
179
177
  fill_in "add-comment-#{commentable.commentable_type}-#{commentable.id}", with: "I am in favor about this!"
@@ -181,7 +179,7 @@ RSpec.shared_examples "comments" do
181
179
  end
182
180
 
183
181
  within "#comments" do
184
- expect(page).to have_selector 'span.success.label', text: "In favor"
182
+ expect(page).to have_selector "span.success.label", text: "In favor"
185
183
  end
186
184
  end
187
185
  end
@@ -195,9 +193,9 @@ RSpec.shared_examples "comments" do
195
193
  visit_commentable_path
196
194
 
197
195
  within "#comment_#{comments[0].id}" do
198
- expect(page).to have_selector('.comment__votes--up', text: /0/)
199
- page.find('.comment__votes--up').click
200
- expect(page).to have_selector('.comment__votes--up', text: /1/)
196
+ expect(page).to have_selector(".comment__votes--up", text: /0/)
197
+ page.find(".comment__votes--up").click
198
+ expect(page).to have_selector(".comment__votes--up", text: /1/)
201
199
  end
202
200
  end
203
201
 
@@ -205,9 +203,9 @@ RSpec.shared_examples "comments" do
205
203
  visit_commentable_path
206
204
 
207
205
  within "#comment_#{comments[0].id}" do
208
- expect(page).to have_selector('.comment__votes--down', text: /0/)
209
- page.find('.comment__votes--down').click
210
- expect(page).to have_selector('.comment__votes--down', text: /1/)
206
+ expect(page).to have_selector(".comment__votes--down", text: /0/)
207
+ page.find(".comment__votes--down").click
208
+ expect(page).to have_selector(".comment__votes--down", text: /1/)
211
209
  end
212
210
  end
213
211
  end
@@ -38,7 +38,7 @@ RSpec.shared_examples "manage moderations" do
38
38
  click_link "Moderations"
39
39
 
40
40
  within "tr[data-id=\"#{moderation.id}\"]" do
41
- click_link "Unreport"
41
+ find("a.action-icon--unreport").click
42
42
  end
43
43
 
44
44
  within ".callout-wrapper" do
@@ -50,7 +50,7 @@ RSpec.shared_examples "manage moderations" do
50
50
  click_link "Moderations"
51
51
 
52
52
  within "tr[data-id=\"#{moderation.id}\"]" do
53
- click_link "Hide"
53
+ find("a.action-icon--hide").click
54
54
  end
55
55
 
56
56
  within ".callout-wrapper" do
@@ -5,13 +5,13 @@ RSpec.shared_examples "reports" do
5
5
  it "should be given the option to sign in" do
6
6
  visit reportable_path
7
7
 
8
- expect(page).to have_selector('.author-data__extra')
8
+ expect(page).to have_selector(".author-data__extra")
9
9
 
10
10
  within ".author-data__extra", match: :first do
11
- page.find('button').click
11
+ page.find("button").click
12
12
  end
13
13
 
14
- expect(page).to have_css('#loginModal', visible: true)
14
+ expect(page).to have_css("#loginModal", visible: true)
15
15
  end
16
16
  end
17
17
 
@@ -24,13 +24,13 @@ RSpec.shared_examples "reports" do
24
24
  it "reports the resource" do
25
25
  visit reportable_path
26
26
 
27
- expect(page).to have_selector('.author-data__extra')
27
+ expect(page).to have_selector(".author-data__extra")
28
28
 
29
29
  within ".author-data__extra", match: :first do
30
- page.find('button').click
30
+ page.find("button").click
31
31
  end
32
32
 
33
- expect(page).to have_css('.flag-modal', visible: true)
33
+ expect(page).to have_css(".flag-modal", visible: true)
34
34
 
35
35
  within ".flag-modal" do
36
36
  click_button "Report"
@@ -49,13 +49,13 @@ RSpec.shared_examples "reports" do
49
49
  it "cannot report it twice" do
50
50
  visit reportable_path
51
51
 
52
- expect(page).to have_selector('.author-data__extra')
52
+ expect(page).to have_selector(".author-data__extra")
53
53
 
54
54
  within ".author-data__extra", match: :first do
55
- page.find('button').click
55
+ page.find("button").click
56
56
  end
57
57
 
58
- expect(page).to have_css('.flag-modal', visible: true)
58
+ expect(page).to have_css(".flag-modal", visible: true)
59
59
 
60
60
  expect(page).to have_content "already reported"
61
61
  end
@@ -2,7 +2,7 @@
2
2
  # This holds Decidim's version and the Rails version on which it depends.
3
3
  module Decidim
4
4
  def self.version
5
- "0.0.8.1"
5
+ "0.1.0"
6
6
  end
7
7
 
8
8
  def self.rails_version
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Exporters
4
+ autoload :Exporter, "decidim/exporters/exporter"
5
+ autoload :JSON, "decidim/exporters/json"
6
+ autoload :CSV, "decidim/exporters/csv"
7
+ autoload :ExportData, "decidim/exporters/export_data"
8
+ end
9
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ require "csv"
3
+
4
+ module Decidim
5
+ module Exporters
6
+ # Exports any serialized object (Hash) into a readable CSV. It transforms
7
+ # the columns using slashes in a way that can be afterwards reconstructed
8
+ # into the original nested hash.
9
+ #
10
+ # For example, `{ name: { ca: "Hola", en: "Hello" } }` would result into
11
+ # the columns: `name/ca` and `name/es`.
12
+ class CSV < Exporter
13
+ # Public: Exports a CSV serialized version of the collection using the
14
+ # provided serializer and following the previously described strategy.
15
+ #
16
+ # Returns an ExportData instance.
17
+ def export
18
+ data = ::CSV.generate(headers: headers, write_headers: true, col_sep: ";") do |csv|
19
+ processed_collection.each do |resource|
20
+ csv << headers.map { |header| resource[header] }
21
+ end
22
+ end
23
+
24
+ ExportData.new(data, "csv")
25
+ end
26
+
27
+ private
28
+
29
+ def headers
30
+ return [] if processed_collection.empty?
31
+ processed_collection.first.keys
32
+ end
33
+
34
+ def processed_collection
35
+ @processed_collection ||= collection.map do |resource|
36
+ flatten(@serializer.new(resource).serialize)
37
+ end
38
+ end
39
+
40
+ def flatten(object, key = nil)
41
+ if object.is_a? Hash
42
+ object.inject({}) do |result, (subkey, value)|
43
+ new_key = key ? "#{key}/#{subkey}" : subkey.to_s
44
+ result.merge(flatten(value, new_key))
45
+ end
46
+ elsif object.is_a?(Array)
47
+ { key.to_s => object.map(&:to_s).join(", ") }
48
+ else
49
+ { key.to_s => object }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Exporters
4
+ # Holds the result of an export.
5
+ class ExportData
6
+ attr_reader :extension
7
+
8
+ # Initializes an `ExportData` with the RAW data and the extension.
9
+ def initialize(data, extension)
10
+ @data = data
11
+ @extension = extension
12
+ end
13
+
14
+ # Gives back the raw data of the export.
15
+ #
16
+ # Returns a String with the result of the export.
17
+ def read
18
+ @data
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Exporters
4
+ # Abstract class providing the interface and partial implementation
5
+ # of an exporter. See `Decidim::Exporters::JSON` and `Decidim::Exporters::CSV`
6
+ # for a reference implementation.
7
+ class Exporter
8
+ # Public: Initializes an Exporter.
9
+ #
10
+ # collection - An Array with the collection to be exported.
11
+ # serializer - A Serializer to be used during the export.
12
+ def initialize(collection, serializer)
13
+ @collection = collection
14
+ @serializer = serializer
15
+ end
16
+
17
+ # Public: Should generate an `ExportData` with the result of the export.
18
+ # Responsibility of the subclass.
19
+ def export
20
+ raise NotImplementedError
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :collection, :serializer
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require "json"
3
+
4
+ module Decidim
5
+ module Exporters
6
+ # Exports a JSON version of a provided hash, given a collection and a
7
+ # Serializer.
8
+ class JSON < Exporter
9
+ # Public: Generates a JSON representation of a collection and a
10
+ # Serializer.
11
+ #
12
+ # Returns an ExportData with the export.
13
+ def export
14
+ data = ::JSON.pretty_generate(@collection.map do |resource|
15
+ @serializer.new(resource).serialize
16
+ end)
17
+
18
+ ExportData.new(data, "json")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -135,5 +135,23 @@ module Decidim
135
135
  def resource_manifests
136
136
  @resource_manifests ||= []
137
137
  end
138
+
139
+ # Public: Stores an instance of StatsRegistry
140
+ def stats
141
+ @stats ||= StatsRegistry.new
142
+ end
143
+
144
+ # Public: Registers a stat inside a feature manifest.
145
+ #
146
+ # name - The name of the stat
147
+ # options - A hash of options
148
+ # * primary: Wether the stat is primary or not.
149
+ # * priority: The priority of the stat used for render issues.
150
+ # block - A block that receive the features to filter out the stat.
151
+ #
152
+ # Returns nothing.
153
+ def register_stat(name, options = {}, &block)
154
+ stats.register(name, options, &block)
155
+ end
138
156
  end
139
157
  end