decidim-core 0.0.8.1 → 0.1.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 (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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3668d75cf2fd8dbfe3c88982c0a7aa8593a75cb4
4
- data.tar.gz: acc926a4029093ffe432873e2098a147873dc478
3
+ metadata.gz: abd55b4bc86a454e483127b15d235ed2a056e718
4
+ data.tar.gz: 4d29c9e66aea8a4c43110cda9b6487310d5c8429
5
5
  SHA512:
6
- metadata.gz: 3a06d36ae7005c0e40ead54624635638e0c5f21a07049a68ab35f050d79fe96dc4be797c18065cc6abef48422feb397aa745549a0bb2c9d5964b3a1cd1d85a43
7
- data.tar.gz: 75ebe0193d06c570996545553101d291d77727e4c53bd5944d8845214cd7f68f66a9907e83c1ffe9961ae2d65c9722e0c062cb37c9b9c13da1655230cd99bf74
6
+ metadata.gz: a2e6c3415e64aa2e6430062cfca573d1aef0e28dc42d04ff7dec6332e7018b20672d9e76c1efd95974c5d6f1f362655515c3fa96d5d813364e178b0dc1f259cf
7
+ data.tar.gz: df609842f94d94b53b37c5611988c853f710453bc5e2a98b46bd370c39879a867f9764c5ee3adf1ecbff4614030a20d7e22ce614fa19eafdc3d64962cb8d6158
@@ -6,5 +6,4 @@
6
6
  //= link decidim/map.js
7
7
  //= link decidim/map.css
8
8
  //= link_directory ../../../vendor/assets/javascripts/datepicker-locales
9
- //= link decidim/widget.css
10
9
  //= link decidim/widget.js
@@ -9,6 +9,7 @@
9
9
  class FormFilterComponent {
10
10
  constructor($form) {
11
11
  this.$form = $form;
12
+ this.id = this.$form.attr('id') || this._getUID();
12
13
  this.mounted = false;
13
14
 
14
15
  this._onFormChange = this._onFormChange.bind(this);
@@ -24,7 +25,7 @@
24
25
  if (this.mounted) {
25
26
  this.mounted = false;
26
27
  this.$form.off('change', 'input, select', this._onFormChange);
27
- exports.Decidim.History.unregisterCallback(`filters-${this.$form.attr('id')}`)
28
+ exports.Decidim.History.unregisterCallback(`filters-${this.id}`)
28
29
  }
29
30
  }
30
31
 
@@ -37,7 +38,7 @@
37
38
  if (this.$form.length > 0 && !this.mounted) {
38
39
  this.mounted = true;
39
40
  this.$form.on('change', 'input, select', this._onFormChange);
40
- exports.Decidim.History.registerCallback(`filters-${this.$form.attr('id')}`, () => {
41
+ exports.Decidim.History.registerCallback(`filters-${this.id}`, () => {
41
42
  this._onPopState();
42
43
  });
43
44
  }
@@ -187,6 +188,15 @@
187
188
 
188
189
  exports.Decidim.History.pushState(newUrl);
189
190
  }
191
+
192
+ /**
193
+ * Generates a unique identifier for the form.
194
+ * @private
195
+ * @returns {String} - Returns a unique identifier
196
+ */
197
+ _getUID() {
198
+ return `filter-form-${new Date().setUTCMilliseconds()}-${Math.floor(Math.random() * 10000000)}`;
199
+ }
190
200
  }
191
201
 
192
202
  exports.Decidim = exports.Decidim || {};
@@ -1,4 +1,3 @@
1
- //@import compass
2
1
  @import "variables";
3
2
  @import "utils/*";
4
3
 
@@ -7,4 +6,4 @@
7
6
 
8
7
  @import "modules/modules";
9
8
  @import "layouts/*";
10
- @import "extras/*";
9
+ @import "extras/*";
@@ -9,3 +9,24 @@
9
9
  overflow-y: auto;
10
10
  }
11
11
  }
12
+
13
+ $widget-padding: 8px;
14
+
15
+ body.widget {
16
+ background: #fff;
17
+ padding: $widget-padding;
18
+ margin: 0;
19
+
20
+ .participatory-process{
21
+ margin-bottom: $widget-padding;
22
+ }
23
+
24
+ .card {
25
+ margin: 0;
26
+ }
27
+
28
+ .organization {
29
+ margin-top: $widget-padding;
30
+ text-align: right;
31
+ }
32
+ }
@@ -73,8 +73,8 @@ $datetime-bg: $primary;
73
73
  font-weight: 800;
74
74
  letter-spacing: .05em;
75
75
  color: $muted;
76
- align-self: flex-start;
77
76
  display: flex;
77
+ align-self: flex-start;
78
78
  align-items: center;
79
79
  .icon{
80
80
  width: 14px;
@@ -29,4 +29,4 @@ a:hover .icon--action{
29
29
  margin-bottom: -2px;
30
30
  width: 12px;
31
31
  height: 12px;
32
- }
32
+ }
@@ -21,7 +21,7 @@ module Decidim
21
21
 
22
22
  transaction do
23
23
  create_user
24
- create_user_group if form.is_user_group?
24
+ create_user_group if form.user_group?
25
25
  end
26
26
 
27
27
  broadcast(:ok, @user)
@@ -36,14 +36,13 @@ module Decidim
36
36
 
37
37
  def invite_user
38
38
  @user = Decidim::User.create(
39
- {
40
- name: form.name,
41
- email: form.email.downcase,
42
- organization: form.organization,
43
- roles: form.roles,
44
- comments_notifications: true,
45
- replies_notifications: true
46
- })
39
+ name: form.name,
40
+ email: form.email.downcase,
41
+ organization: form.organization,
42
+ roles: form.roles,
43
+ comments_notifications: true,
44
+ replies_notifications: true
45
+ )
47
46
  @user.invite!(
48
47
  form.invited_by,
49
48
  invitation_instructions: form.invitation_instructions
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:disable Metrics/BlockLength
3
2
  require "active_support/concern"
4
3
 
5
4
  module Decidim
@@ -16,11 +15,11 @@ module Decidim
16
15
  end
17
16
 
18
17
  def method_missing(method_name, *_arguments)
19
- @filter.present? && @filter.key?(method_name) ? @filter[method_name] : super
18
+ @filter.present? && @filter.has_key?(method_name) ? @filter[method_name] : super
20
19
  end
21
20
 
22
21
  def respond_to_missing?(method_name, include_private = false)
23
- @filter.present? && @filter.key?(method_name) || super
22
+ @filter.present? && @filter.has_key?(method_name) || super
24
23
  end
25
24
  end
26
25
 
@@ -16,7 +16,7 @@ module Decidim
16
16
  payload[:referer] = request.referer.to_s
17
17
  payload[:request_id] = request.uuid
18
18
  payload[:user_agent] = request.user_agent
19
- payload[:xhr] = request.xhr? ? 'true' : 'false'
19
+ payload[:xhr] = request.xhr? ? "true" : "false"
20
20
  end
21
21
  end
22
22
  end
@@ -49,10 +49,6 @@ module Decidim
49
49
  @handler ||= AuthorizationHandler.handler_for(handler_name, handler_params)
50
50
  end
51
51
 
52
- def handlers
53
- @handlers ||= Decidim.authorization_handlers
54
- end
55
-
56
52
  protected
57
53
 
58
54
  def stored_location
@@ -11,7 +11,7 @@ module Decidim
11
11
 
12
12
  authorize_resource :public_pages, class: false
13
13
  delegate :page, to: :page_finder
14
- helper_method :page, :promoted_participatory_processes, :highlighted_participatory_processes, :participatory_processes, :users
14
+ helper_method :page, :promoted_participatory_processes, :highlighted_participatory_processes, :stats
15
15
 
16
16
  def index
17
17
  @pages = current_organization.static_pages.all.to_a.sort do |a, b|
@@ -23,21 +23,18 @@ module Decidim
23
23
  @page_finder ||= Decidim::PageFinder.new(params[:id], current_organization)
24
24
  end
25
25
 
26
- def users
27
- @users ||= Decidim::User.where(organization: current_organization)
28
- end
29
-
30
- # This should be deleted once the statistics are done properly.
31
- def participatory_processes
32
- @processes ||= OrganizationParticipatoryProcesses.new(current_organization) | PublicParticipatoryProcesses.new
33
- end
34
-
35
26
  def promoted_participatory_processes
36
- @promoted_processes ||= participatory_processes | PromotedParticipatoryProcesses.new
27
+ @promoted_processes ||= OrganizationParticipatoryProcesses.new(current_organization) | PublicParticipatoryProcesses.new | PromotedParticipatoryProcesses.new
37
28
  end
38
29
 
39
30
  def highlighted_participatory_processes
40
31
  @promoted_processes ||= OrganizationParticipatoryProcesses.new(current_organization) | HighlightedParticipatoryProcesses.new
41
32
  end
33
+
34
+ private
35
+
36
+ def stats
37
+ @stats ||= HomeStatsPresenter.new(organization: current_organization)
38
+ end
42
39
  end
43
40
  end
@@ -14,7 +14,7 @@ module Decidim
14
14
  def participatory_processes
15
15
  @participatory_processes ||= group.participatory_processes.published
16
16
  end
17
- alias_method :collection, :participatory_processes
17
+ alias collection participatory_processes
18
18
 
19
19
  def group
20
20
  Decidim::ParticipatoryProcessGroup.find(params[:id])
@@ -10,6 +10,10 @@ module Decidim
10
10
  @model ||= ParticipatoryProcess.find(params[:participatory_process_id])
11
11
  end
12
12
 
13
+ def current_participatory_process
14
+ model
15
+ end
16
+
13
17
  def iframe_url
14
18
  @iframe_url ||= participatory_process_participatory_process_widget_url(model)
15
19
  end
@@ -3,12 +3,12 @@
3
3
  module Decidim
4
4
  class WidgetsController < Decidim::ApplicationController
5
5
  skip_authorization_check only: :show
6
- skip_before_filter :verify_authenticity_token
6
+ skip_before_action :verify_authenticity_token
7
7
  after_action :allow_iframe, only: :show
8
8
 
9
- layout 'decidim/widget'
9
+ layout "decidim/widget"
10
10
 
11
- helper_method :iframe_url
11
+ helper_method :model, :iframe_url, :current_participatory_process
12
12
 
13
13
  def show
14
14
  respond_to do |format|
@@ -19,6 +19,10 @@ module Decidim
19
19
 
20
20
  private
21
21
 
22
+ def current_participatory_process
23
+ @current_participatory_process ||= model.feature.participatory_process
24
+ end
25
+
22
26
  def iframe_url
23
27
  raise NotImplementedError
24
28
  end
@@ -23,13 +23,13 @@ module Decidim
23
23
  validates :password, presence: true, confirmation: true, length: { in: Decidim::User.password_length }
24
24
  validates :tos_agreement, allow_nil: false, acceptance: true
25
25
 
26
- validates :user_group_name, presence: true, if: :is_user_group?
27
- validates :user_group_document_number, presence: true, if: :is_user_group?
28
- validates :user_group_phone, presence: true, if: :is_user_group?
26
+ validates :user_group_name, presence: true, if: :user_group?
27
+ validates :user_group_document_number, presence: true, if: :user_group?
28
+ validates :user_group_phone, presence: true, if: :user_group?
29
29
 
30
30
  validate :email_unique_in_organization
31
31
 
32
- def is_user_group?
32
+ def user_group?
33
33
  sign_up_as == "user_group"
34
34
  end
35
35
 
@@ -44,7 +44,7 @@ module Decidim
44
44
  html_properties["class"] = (["icon--#{name}"] + _icon_classes(options)).join(" ")
45
45
 
46
46
  content_tag :svg, html_properties do
47
- content_tag :use, nil, "xlink:href" => "#{asset_url("decidim/icons.svg")}#icon-#{name}"
47
+ content_tag :use, nil, "xlink:href" => "#{asset_path("decidim/icons.svg")}#icon-#{name}"
48
48
  end
49
49
  end
50
50
 
@@ -9,32 +9,32 @@ module Decidim
9
9
  # options - An optional hash of options (default: { zoom: 17 })
10
10
  # * zoom: A number to represent the zoom value of the map
11
11
  def static_map_link(resource, options = {})
12
- if resource.geocoded?
13
- zoom = options[:zoom] || 17
14
- latitude = resource.latitude
15
- longitude = resource.longitude
12
+ return unless resource.geocoded?
16
13
 
17
- map_url = "https://www.openstreetmap.org/?mlat=#{latitude}&mlon=#{longitude}#map=#{zoom}/#{latitude}/#{longitude}"
14
+ zoom = options[:zoom] || 17
15
+ latitude = resource.latitude
16
+ longitude = resource.longitude
18
17
 
19
- link_to map_url, target: "_blank" do
20
- image_tag decidim.static_map_path(sgid: resource.to_sgid.to_s)
21
- end
18
+ map_url = "https://www.openstreetmap.org/?mlat=#{latitude}&mlon=#{longitude}#map=#{zoom}/#{latitude}/#{longitude}"
19
+
20
+ link_to map_url, target: "_blank" do
21
+ image_tag decidim.static_map_path(sgid: resource.to_sgid.to_s)
22
22
  end
23
23
  end
24
24
 
25
- def dynamic_map_for(markers_data, &block)
26
- if Decidim.geocoder.present?
27
- map_html_options = {
28
- class: "google-map",
29
- id: "map",
30
- "data-markers-data" => markers_data.to_json,
31
- "data-here-app-id" => Decidim.geocoder[:here_app_id],
32
- "data-here-app-code" => Decidim.geocoder[:here_app_code]
33
- }
34
- content = capture { block.call }
35
- content_tag :div, class: "row column" do
36
- content_tag(:div, "", map_html_options) + content
37
- end
25
+ def dynamic_map_for(markers_data)
26
+ return unless Decidim.geocoder.present?
27
+
28
+ map_html_options = {
29
+ class: "google-map",
30
+ id: "map",
31
+ "data-markers-data" => markers_data.to_json,
32
+ "data-here-app-id" => Decidim.geocoder[:here_app_id],
33
+ "data-here-app-code" => Decidim.geocoder[:here_app_code]
34
+ }
35
+ content = capture { yield }
36
+ content_tag :div, class: "row column" do
37
+ content_tag(:div, "", map_html_options) + content
38
38
  end
39
39
  end
40
40
  end
@@ -65,8 +65,8 @@ module Decidim
65
65
  def linked_classes_for(klass)
66
66
  return [] unless klass.respond_to?(:linked_classes_for)
67
67
 
68
- klass.linked_classes_for(current_feature).map do |klass|
69
- [klass.underscore, t(klass.demodulize.downcase, scope: "decidim.filters.linked_classes")]
68
+ klass.linked_classes_for(current_feature).map do |k|
69
+ [k.underscore, t(k.demodulize.downcase, scope: "decidim.filters.linked_classes")]
70
70
  end
71
71
  end
72
72
 
@@ -91,7 +91,7 @@ module Decidim
91
91
  # Returns a String.
92
92
  def _decidim_resource_route(resource, route_type, options)
93
93
  manifest = resource.class.resource_manifest
94
- engine = send(manifest.mounted_engine_name)
94
+ engine = manifest.feature_manifest.engine
95
95
 
96
96
  url_params = {
97
97
  id: resource.id,
@@ -99,7 +99,7 @@ module Decidim
99
99
  participatory_process_id: resource.feature.participatory_process.id
100
100
  }
101
101
 
102
- engine.send("#{manifest.route_name}_#{route_type}", url_params.merge(options))
102
+ engine.routes.url_helpers.send("#{manifest.route_name}_#{route_type}", url_params.merge(options))
103
103
  end
104
104
  end
105
105
  end
@@ -2,8 +2,8 @@
2
2
  module Decidim
3
3
  module WidgetUrlsHelper
4
4
  def embed_modal_for(url)
5
- js_embed_code = "#{content_tag(:script, '', src: url)}"
6
- embed_code = "#{content_tag(:noscript, content_tag(:iframe, '', src: url.gsub(".js", ".html"), frameborder: 0, scrolling: "vertical"))}"
5
+ js_embed_code = String.new(content_tag(:script, "", src: url))
6
+ embed_code = String.new(content_tag(:noscript, content_tag(:iframe, "", src: url.gsub(".js", ".html"), frameborder: 0, scrolling: "vertical")))
7
7
  render partial: "decidim/shared/embed_modal", locals: { js_embed_code: js_embed_code, embed_code: embed_code }
8
8
  end
9
9
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # This mailer sends a notification email containing the export as an
4
+ # attachment.
5
+ class ExportMailer < ApplicationMailer
6
+ # Public: Sends a notification email with the result of an export in a
7
+ # zipped file.
8
+ #
9
+ # user - The user to be notified.
10
+ # name - The name of the export.
11
+ # export_data - The data containing the result of the export.
12
+ #
13
+ # Returns nothing.
14
+ def export(user, name, export_data)
15
+ @user = user
16
+ @organization = user.organization
17
+
18
+ original_file_name = "#{name}.#{export_data.extension}"
19
+
20
+ attachments["#{name}.zip"] = FileZipper.new(
21
+ original_file_name, export_data.read
22
+ ).zip
23
+
24
+ with_user(user) do
25
+ mail(to: "#{user.name} <#{user.email}>", subject: I18n.t("decidim.export_mailer.subject", name: original_file_name))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -24,7 +24,7 @@ module Decidim
24
24
 
25
25
  location = new_location_for(env, organization.host)
26
26
 
27
- [301, { "Location" => location, 'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
27
+ [301, { "Location" => location, "Content-Type" => "text/html", "Content-Length" => "0" }, []]
28
28
  end
29
29
  end
30
30
 
@@ -81,6 +81,11 @@ module Decidim
81
81
  step_settings.fetch(active_step.id.to_s)
82
82
  end
83
83
 
84
+ # Public: Returns the value of the registered primary stat.
85
+ def primary_stat
86
+ @primary_stat ||= manifest.stats.filter(primary: true).with_context([self]).map { |name, value| [name, value] }.first&.last
87
+ end
88
+
84
89
  private
85
90
 
86
91
  def serialize_settings(schema, value)