decidim-decidim_awesome 0.8.3 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-decidim_awesome might be problematic. Click here for more details.

Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +54 -45
  4. data/Rakefile +1 -1
  5. data/app/commands/decidim/decidim_awesome/admin/create_constraint.rb +1 -1
  6. data/app/commands/decidim/decidim_awesome/admin/create_custom_redirect.rb +1 -1
  7. data/app/commands/decidim/decidim_awesome/admin/create_menu_hack.rb +1 -1
  8. data/app/commands/decidim/decidim_awesome/admin/create_proposal_custom_field.rb +1 -1
  9. data/app/commands/decidim/decidim_awesome/admin/create_scoped_admin.rb +1 -1
  10. data/app/commands/decidim/decidim_awesome/admin/create_scoped_style.rb +1 -1
  11. data/app/commands/decidim/decidim_awesome/admin/destroy_constraint.rb +1 -1
  12. data/app/commands/decidim/decidim_awesome/admin/destroy_custom_redirect.rb +1 -1
  13. data/app/commands/decidim/decidim_awesome/admin/destroy_menu_hack.rb +1 -1
  14. data/app/commands/decidim/decidim_awesome/admin/destroy_proposal_custom_field.rb +1 -1
  15. data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_admin.rb +1 -1
  16. data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_style.rb +1 -1
  17. data/app/commands/decidim/decidim_awesome/admin/rename_scope_label.rb +1 -1
  18. data/app/commands/decidim/decidim_awesome/admin/update_config.rb +2 -3
  19. data/app/commands/decidim/decidim_awesome/admin/update_constraint.rb +2 -2
  20. data/app/commands/decidim/decidim_awesome/admin/update_custom_redirect.rb +1 -1
  21. data/app/commands/decidim/decidim_awesome/admin/update_menu_hack.rb +1 -1
  22. data/app/commands/decidim/decidim_awesome/command.rb +14 -0
  23. data/app/commands/decidim/decidim_awesome/create_editor_image.rb +1 -1
  24. data/app/controllers/concerns/decidim/decidim_awesome/admin_accountability/admin/filterable.rb +67 -0
  25. data/app/controllers/concerns/decidim/decidim_awesome/admin_accountability/admin/filterable_helper.rb +37 -0
  26. data/app/controllers/decidim/decidim_awesome/admin/admin_accountability_controller.rb +51 -0
  27. data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +6 -3
  28. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +2 -0
  29. data/app/controllers/decidim/decidim_awesome/admin/custom_redirects_controller.rb +2 -0
  30. data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +2 -0
  31. data/app/controllers/decidim/decidim_awesome/editor_images_controller.rb +0 -2
  32. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +14 -0
  33. data/app/forms/decidim/decidim_awesome/admin/menu_form.rb +1 -1
  34. data/app/forms/decidim/decidim_awesome/proposals/proposal_wizard_create_step_form_override.rb +26 -8
  35. data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +12 -8
  36. data/app/helpers/decidim/decidim_awesome/map_helper.rb +14 -11
  37. data/app/jobs/decidim/decidim_awesome/export_admin_actions_job.rb +28 -0
  38. data/app/middleware/decidim/decidim_awesome/current_config.rb +4 -0
  39. data/app/models/decidim/decidim_awesome/awesome_config.rb +0 -1
  40. data/app/models/decidim/decidim_awesome/config_constraint.rb +0 -2
  41. data/app/models/decidim/decidim_awesome/editor_image.rb +0 -3
  42. data/app/models/decidim/decidim_awesome/paper_trail_version.rb +99 -0
  43. data/app/packs/entrypoints/decidim_admin_decidim_awesome.js +3 -2
  44. data/app/packs/images/decidim/decidim_awesome/pokecode-logo.png +0 -0
  45. data/app/packs/src/decidim/decidim_awesome/admin/auto_edit.js +7 -7
  46. data/app/packs/src/decidim/decidim_awesome/admin/check_redirections.js +2 -2
  47. data/app/packs/src/decidim/decidim_awesome/admin/constraints.js +5 -5
  48. data/app/packs/src/decidim/decidim_awesome/admin/custom_fields_builder.js +11 -10
  49. data/app/packs/src/decidim/decidim_awesome/admin/form_exit_warn.js +1 -0
  50. data/app/packs/src/decidim/decidim_awesome/admin/user_picker.js +1 -0
  51. data/app/packs/src/decidim/decidim_awesome/awesome_map/api/fetcher.js +13 -13
  52. data/app/packs/src/decidim/decidim_awesome/awesome_map/awesome_map.js +14 -12
  53. data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/controller.js +16 -12
  54. data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/proposals_controller.js +3 -3
  55. data/app/packs/src/decidim/decidim_awesome/awesome_map/controls_ui.js +25 -26
  56. data/app/packs/src/decidim/decidim_awesome/awesome_map/load_map.js +1 -0
  57. data/app/packs/src/decidim/decidim_awesome/editors/editor.js +33 -12
  58. data/app/packs/src/decidim/decidim_awesome/forms/autosave.js +8 -12
  59. data/app/packs/src/decidim/decidim_awesome/forms/custom_fields_renderer.js +36 -27
  60. data/app/packs/src/decidim/decidim_awesome/forms/rich_text_plugin.js +6 -4
  61. data/app/packs/src/decidim/decidim_awesome/proposals/custom_fields.js +7 -7
  62. data/app/packs/src/decidim/decidim_awesome/proposals/images.js +2 -2
  63. data/app/packs/stylesheets/decidim/decidim_awesome/awesome_admin.scss +8 -5
  64. data/app/permissions/decidim/decidim_awesome/admin/permissions.rb +15 -1
  65. data/app/permissions/decidim/decidim_awesome/permissions.rb +4 -6
  66. data/app/presenters/decidim/decidim_awesome/paper_trail_base_presenter.rb +28 -0
  67. data/app/presenters/decidim/decidim_awesome/participatory_space_role_presenter.rb +45 -0
  68. data/app/presenters/decidim/decidim_awesome/role_base_presenter.rb +102 -0
  69. data/app/presenters/decidim/decidim_awesome/user_entity_presenter.rb +50 -0
  70. data/app/serializers/decidim/decidim_awesome/paper_trail_version_serializer.rb +37 -0
  71. data/app/validators/concerns/decidim/decidim_awesome/etiquette_validator_override.rb +41 -0
  72. data/app/views/decidim/decidim_awesome/admin/admin_accountability/index.html.erb +59 -0
  73. data/app/views/decidim/decidim_awesome/admin/checks/_assets_tester.html.erb +2 -0
  74. data/app/views/decidim/decidim_awesome/admin/config/_form_proposals.html.erb +82 -2
  75. data/app/views/decidim/decidim_awesome/admin/shared/_filters_with_date.html.erb +56 -0
  76. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +1 -1
  77. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +9 -17
  78. data/app/views/layouts/decidim/admin/decidim_awesome.html.erb +1 -1
  79. data/app/views/{v0.25 → v0.27}/layouts/decidim/_head.html.erb +12 -4
  80. data/config/i18n-tasks.yml +4 -0
  81. data/config/locales/ca.yml +22 -2
  82. data/config/locales/cs.yml +7 -2
  83. data/config/locales/de.yml +20 -1
  84. data/config/locales/en.yml +90 -1
  85. data/config/locales/es.yml +2 -2
  86. data/config/locales/fr.yml +22 -2
  87. data/config/locales/it.yml +2 -2
  88. data/config/locales/ja.yml +3 -2
  89. data/config/locales/nl.yml +1 -1
  90. data/config/locales/pt-BR.yml +2 -2
  91. data/db/seeds.rb +1 -1
  92. data/lib/decidim/decidim_awesome/admin_engine.rb +15 -1
  93. data/lib/decidim/decidim_awesome/awesome.rb +55 -1
  94. data/lib/decidim/decidim_awesome/checksums.yml +13 -3
  95. data/lib/decidim/decidim_awesome/config.rb +14 -14
  96. data/lib/decidim/decidim_awesome/context_analyzers/request_analyzer.rb +1 -1
  97. data/lib/decidim/decidim_awesome/engine.rb +36 -9
  98. data/lib/decidim/decidim_awesome/iframe_component/component.rb +2 -1
  99. data/lib/decidim/decidim_awesome/menu_hacker.rb +6 -0
  100. data/lib/decidim/decidim_awesome/system_checker.rb +2 -0
  101. data/lib/decidim/decidim_awesome/test/factories.rb +7 -0
  102. data/lib/decidim/decidim_awesome/test/initializer.rb +10 -2
  103. data/lib/decidim/decidim_awesome/test/shared_examples/action_log_presenter_examples.rb +61 -0
  104. data/lib/decidim/decidim_awesome/test/shared_examples/scoped_admins_examples.rb +7 -4
  105. data/lib/decidim/decidim_awesome/test/shared_examples/summary_examples.rb +2 -2
  106. data/lib/decidim/decidim_awesome/version.rb +2 -2
  107. data/lib/tasks/decidim_awesome_active_storage_migrations_tasks.rake +1 -3
  108. data/package.json +21 -164
  109. metadata +39 -39
  110. data/app/packs/images/decidim/decidim_awesome/platoniq-logo.png +0 -0
  111. data/app/packs/src/vendor/image-resize.min.js +0 -1
  112. data/app/packs/src/vendor/image-upload.min.js +0 -6
  113. data/app/packs/src/vendor/leaflet.featuregroup.subgroup.js +0 -184
  114. /data/app/views/{v0.25 → v0.27}/decidim/proposals/collaborative_drafts/_show.html.erb +0 -0
  115. /data/app/views/{v0.25 → v0.27}/layouts/decidim/admin/_header.html.erb +0 -0
@@ -71,6 +71,7 @@ module Decidim
71
71
 
72
72
  private
73
73
 
74
+ # rubocop:disable Style/OpenStructUse
74
75
  def menu_item
75
76
  item = current_items.find { |i| md5(i.url) == params[:id] }
76
77
  raise ActiveRecord::RecordNotFound unless item
@@ -84,6 +85,7 @@ module Decidim
84
85
  native?: !item.respond_to?(:overrided?)
85
86
  )
86
87
  end
88
+ # rubocop:enable Style/OpenStructUse
87
89
 
88
90
  def current_items
89
91
  @current_items ||= current_menu.items(include_invisible: true)
@@ -32,8 +32,6 @@ module Decidim
32
32
  # Rescue ajax calls and print the update.js view which prints the info on the message ajax form
33
33
  # Only if the request is AJAX, otherwise behave as Decidim standards
34
34
  def ajax_user_has_no_permission
35
- return user_has_no_permission unless request.xhr?
36
-
37
35
  render json: { message: I18n.t("actions.unauthorized", scope: "decidim.core") }, status: :unprocessable_entity
38
36
  end
39
37
 
@@ -22,12 +22,26 @@ module Decidim
22
22
  attribute :intergram_for_admins_settings, IntergramForm
23
23
  attribute :intergram_for_public, Boolean
24
24
  attribute :intergram_for_public_settings, IntergramForm
25
+ attribute :validate_title_min_length, Integer, default: 15
26
+ attribute :validate_title_max_caps_percent, Integer, default: 25
27
+ attribute :validate_title_max_marks_together, Integer, default: 1
28
+ attribute :validate_title_start_with_caps, Boolean, default: true
29
+ attribute :validate_body_min_length, Integer, default: 15
30
+ attribute :validate_body_max_caps_percent, Integer, default: 25
31
+ attribute :validate_body_max_marks_together, Integer, default: 1
32
+ attribute :validate_body_start_with_caps, Boolean, default: true
25
33
 
26
34
  # collect all keys anything not specified in the params (UpdateConfig command ignores it)
27
35
  attr_accessor :valid_keys
28
36
 
29
37
  validate :css_syntax, if: ->(form) { form.scoped_styles.present? }
30
38
  validate :json_syntax, if: ->(form) { form.proposal_custom_fields.present? }
39
+ validates :validate_title_min_length, presence: true, numericality: { greater_than_or_equal_to: 1, less_than_or_equal_to: 100 }
40
+ validates :validate_title_max_caps_percent, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }
41
+ validates :validate_title_max_marks_together, presence: true, numericality: { greater_than_or_equal_to: 1 }
42
+ validates :validate_body_min_length, presence: true, numericality: { greater_than_or_equal_to: 0 }
43
+ validates :validate_body_max_caps_percent, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }
44
+ validates :validate_body_max_marks_together, presence: true, numericality: { greater_than_or_equal_to: 1 }
31
45
 
32
46
  # TODO: validate non general admins are here
33
47
 
@@ -5,7 +5,7 @@ module Decidim
5
5
  module Admin
6
6
  class MenuForm < Decidim::Form
7
7
  include Decidim::TranslatableAttributes
8
- VISIBILITY_STATES = %w(default hidden logged non_logged).freeze
8
+ VISIBILITY_STATES = %w(default hidden logged non_logged verified_user).freeze
9
9
 
10
10
  translatable_attribute :raw_label, String
11
11
  attribute :url, String
@@ -11,11 +11,15 @@ module Decidim
11
11
  clear_validators!
12
12
 
13
13
  validates :title, presence: true, etiquette: true
14
- validates :title, length: { in: 15..150 }
15
- validates :body, presence: true, etiquette: true, unless: ->(form) { form.override_validations? }
14
+ validates :title, proposal_length: {
15
+ minimum: ->(form) { form.minimum_title_length },
16
+ maximum: 150
17
+ }
18
+ validates :body, presence: true, unless: ->(form) { form.override_validations? || form.minimum_body_length.zero? }
19
+ validates :body, etiquette: true, unless: ->(form) { form.override_validations? }
16
20
  validates :body, proposal_length: {
17
- minimum: 15,
18
- maximum: ->(record) { record.override_validations? ? 0 : record.component.settings.proposal_length }
21
+ minimum: ->(form) { form.minimum_body_length },
22
+ maximum: ->(form) { form.override_validations? ? 0 : form.component.settings.proposal_length }
19
23
  }
20
24
 
21
25
  validate :body_is_not_bare_template, unless: ->(form) { form.override_validations? }
@@ -23,13 +27,27 @@ module Decidim
23
27
  def override_validations?
24
28
  return false if context.current_component.settings.participatory_texts_enabled
25
29
 
26
- custom_fields.present?
30
+ custom_fields.present? || awesome_config.enabled_for?(:use_markdown_editor)
31
+ end
32
+
33
+ def minimum_title_length
34
+ awesome_config.config[:validate_title_min_length].to_i
35
+ end
36
+
37
+ def minimum_body_length
38
+ awesome_config.config[:validate_body_min_length].to_i
27
39
  end
28
40
 
29
41
  def custom_fields
30
- awesome_config = Decidim::DecidimAwesome::Config.new(context.current_organization)
31
- awesome_config.context_from_component(context.current_component)
32
- awesome_config.collect_sub_configs_values("proposal_custom_field")
42
+ @custom_fields ||= awesome_config.collect_sub_configs_values("proposal_custom_field")
43
+ end
44
+
45
+ def awesome_config
46
+ @awesome_config ||= begin
47
+ conf = Decidim::DecidimAwesome::Config.new(context.current_organization)
48
+ conf.context_from_component(context.current_component)
49
+ conf
50
+ end
33
51
  end
34
52
  end
35
53
  end
@@ -15,7 +15,11 @@ module Decidim
15
15
  def menus
16
16
  @menus ||= {
17
17
  editors: config_enabled?([:allow_images_in_full_editor, :allow_images_in_small_editor, :use_markdown_editor, :allow_images_in_markdown_editor]),
18
- proposals: config_enabled?(:allow_images_in_proposals),
18
+ proposals: config_enabled?([:allow_images_in_proposals,
19
+ :validate_title_min_length, :validate_title_max_caps_percent,
20
+ :validate_title_max_marks_together, :validate_title_start_with_caps,
21
+ :validate_body_min_length, :validate_body_max_caps_percent,
22
+ :validate_body_max_marks_together, :validate_body_start_with_caps]),
19
23
  surveys: config_enabled?(:auto_save_forms),
20
24
  styles: config_enabled?(:scoped_styles),
21
25
  proposal_custom_fields: config_enabled?(:proposal_custom_fields),
@@ -35,7 +39,7 @@ module Decidim
35
39
 
36
40
  # ensure boolean value
37
41
  def config_enabled?(var)
38
- DecidimAwesome.enabled?(var) ? true : false
42
+ DecidimAwesome.enabled?(var)
39
43
  end
40
44
 
41
45
  def participatory_space_manifests
@@ -49,18 +53,18 @@ module Decidim
49
53
  def component_manifests(space = nil)
50
54
  return {} if OTHER_MANIFESTS.include?(space)
51
55
 
52
- Decidim.component_manifests.pluck(:name).map do |name|
56
+ Decidim.component_manifests.pluck(:name).to_h do |name|
53
57
  [name.to_sym, I18n.t("decidim.components.#{name}.name")]
54
- end.to_h
58
+ end
55
59
  end
56
60
 
57
61
  def participatory_spaces_list(manifest)
58
62
  space = model_for_manifest(manifest)
59
63
  return {} if space.blank?
60
64
 
61
- space.where(organization: current_organization).map do |item|
65
+ space.where(organization: current_organization).to_h do |item|
62
66
  [item.try(:slug) || item.id.to_s, translated_attribute(item.title)]
63
- end.to_h
67
+ end
64
68
  end
65
69
 
66
70
  def components_list(manifest, slug)
@@ -68,9 +72,9 @@ module Decidim
68
72
  return {} unless space&.column_names&.include? "slug"
69
73
 
70
74
  components = Component.where(participatory_space: space.find_by(slug: slug))
71
- components.map do |item|
75
+ components.to_h do |item|
72
76
  [item.id, "#{item.id}: #{translated_attribute(item.name)}"]
73
- end.to_h
77
+ end
74
78
  end
75
79
 
76
80
  def translate_constraint_value(constraint, key)
@@ -98,16 +98,19 @@ module Decidim
98
98
  builder = map_utility_dynamic.create_builder(self, options)
99
99
 
100
100
  # We need awesome map listeners before initialize the official map
101
- unless snippets.any?(:awesome_map)
102
- snippets.add(:awesome_map, javascript_pack_tag("decidim_decidim_awesome_map", defer: false))
103
- snippets.add(:awesome_map, stylesheet_pack_tag("decidim_decidim_awesome_map"))
104
- snippets.add(:head, snippets.for(:awesome_map))
101
+ unless snippets.any?(:awesome_map_styles) || snippets.any?(:awesome_map_scripts)
102
+ snippets.add(:awesome_map_styles, stylesheet_pack_tag("decidim_decidim_awesome_map"))
103
+ snippets.add(:awesome_map_scripts, javascript_pack_tag("decidim_decidim_awesome_map", defer: false))
104
+ snippets.add(:head, snippets.for(:awesome_map_styles))
105
+ snippets.add(DecidimAwesome.legacy_version? ? :head : :foot, snippets.for(:awesome_map_scripts))
105
106
  end
106
107
 
107
- unless snippets.any?(:map)
108
- snippets.add(:map, builder.stylesheet_snippets)
109
- snippets.add(:map, builder.javascript_snippets)
110
- snippets.add(:head, snippets.for(:map))
108
+ unless snippets.any?(:map_styles) || snippets.any?(:map_scripts)
109
+ snippets.add(:map_styles, builder.stylesheet_snippets)
110
+ snippets.add(:map_scripts, builder.javascript_snippets)
111
+
112
+ snippets.add(:head, snippets.for(:map_styles))
113
+ snippets.add(DecidimAwesome.legacy_version? ? :head : :foot, snippets.for(:map_scripts))
111
114
  end
112
115
 
113
116
  builder
@@ -134,10 +137,10 @@ module Decidim
134
137
  # rubocop:disable Naming/MethodParameterName
135
138
  def hsv_to_rgb(h, s, v)
136
139
  h_i = (h * 6).to_i
137
- f = h * 6 - h_i
140
+ f = (h * 6) - h_i
138
141
  p = v * (1 - s)
139
- q = v * (1 - f * s)
140
- t = v * (1 - (1 - f) * s)
142
+ q = v * (1 - (f * s))
143
+ t = v * (1 - ((1 - f) * s))
141
144
  if h_i.zero?
142
145
  r = v
143
146
  g = t
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ class ExportAdminActionsJob < ApplicationJob
6
+ queue_as :default
7
+
8
+ def perform(current_user, format, collection_ids)
9
+ collection = serialized_collection(collection_ids)
10
+
11
+ export_data = Exporters.find_exporter(format).new(collection).export
12
+
13
+ ExportMailer.export(current_user, "admin_actions", export_data).deliver_now
14
+ end
15
+
16
+ private
17
+
18
+ def serialized_collection(collection_ids)
19
+ @serialized_collection ||= begin
20
+ collection = PaperTrailVersion.where(id: collection_ids)
21
+ collection.map do |item|
22
+ PaperTrailVersionSerializer.new(item).serialize
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Style/OpenStructUse
3
4
  module Decidim
4
5
  module DecidimAwesome
5
6
  # A middleware that stores the current awesome context by parsing the request
@@ -85,6 +86,7 @@ module Decidim
85
86
  end.flatten.uniq.map(&:to_i)
86
87
  end
87
88
 
89
+ # rubocop:disable Lint/DuplicateBranch
88
90
  # avoid unnecessary processing for non-user routes
89
91
  def processable_path?
90
92
  return true if safe_get_route?
@@ -121,6 +123,7 @@ module Decidim
121
123
  true
122
124
  end
123
125
  end
126
+ # rubocop:enable Lint/DuplicateBranch
124
127
 
125
128
  # to access certain deeper routes it requires first to click on a parent route, even without Post permissions in there
126
129
  # this adds this additional routes to these cases
@@ -180,3 +183,4 @@ module Decidim
180
183
  end
181
184
  end
182
185
  end
186
+ # rubocop:enable Style/OpenStructUse
@@ -12,7 +12,6 @@ module Decidim
12
12
  class_name: "Decidim::DecidimAwesome::ConfigConstraint",
13
13
  dependent: :destroy
14
14
 
15
- validates :organization, presence: true
16
15
  validates :var, uniqueness: { scope: :decidim_organization_id }
17
16
 
18
17
  def additional_constraints
@@ -6,8 +6,6 @@ module Decidim
6
6
  self.table_name = "decidim_awesome_config_constraints"
7
7
 
8
8
  belongs_to :awesome_config, foreign_key: :decidim_awesome_config_id, class_name: "Decidim::DecidimAwesome::AwesomeConfig"
9
-
10
- validates :awesome_config, presence: true
11
9
  end
12
10
  end
13
11
  end
@@ -10,9 +10,6 @@ module Decidim
10
10
  belongs_to :author, foreign_key: :decidim_author_id, class_name: "Decidim::User"
11
11
  belongs_to :organization, foreign_key: :decidim_organization_id, class_name: "Decidim::Organization"
12
12
 
13
- validates :organization, presence: true
14
- validates :author, presence: true
15
-
16
13
  has_one_attached :file
17
14
  validates_upload :file, uploader: Decidim::DecidimAwesome::ImageUploader
18
15
  end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ class PaperTrailVersion < PaperTrail::Version
6
+ default_scope { order("created_at DESC") }
7
+
8
+ def self.safe_user_roles
9
+ DecidimAwesome.participatory_space_roles.filter(&:safe_constantize)
10
+ end
11
+
12
+ scope :space_role_actions, -> { where(item_type: PaperTrailVersion.safe_user_roles, event: "create") }
13
+
14
+ def self.admin_role_actions(filter = nil)
15
+ base = where(item_type: "Decidim::UserBaseEntity", event: %w(create update))
16
+ case filter
17
+ when nil
18
+ base.where("object_changes LIKE '%\nroles:\n- []\n- - %' OR object_changes LIKE '%\nadmin:\n- false\n- true%'")
19
+ when "admin"
20
+ base.where("object_changes LIKE '%\nadmin:\n- false\n- true%'")
21
+ else
22
+ base.where(Arel.sql("object_changes LIKE '%\nroles:\n- []\n- - #{filter}\n%'"))
23
+ end
24
+ end
25
+
26
+ def present(html: true)
27
+ @present ||= if item_type == "Decidim::UserBaseEntity"
28
+ UserEntityPresenter.new(self, html: html)
29
+ elsif item_type.in?(PaperTrailVersion.safe_user_roles)
30
+ ParticipatorySpaceRolePresenter.new(self, html: html)
31
+ else
32
+ self
33
+ end
34
+ end
35
+
36
+ ransacker :role_type do
37
+ @role_type ||= begin
38
+ queries = PaperTrailVersion.safe_user_roles.map do |role_class|
39
+ table = role_class.safe_constantize.table_name
40
+ %{
41
+ SELECT ("#{table}"."role")::text FROM "#{table}"
42
+ WHERE "#{table}"."id" = "versions"."item_id"
43
+ AND item_type = '#{role_class}'
44
+ }
45
+ end
46
+ Arel.sql("(#{queries.join(" UNION ")})")
47
+ end
48
+ end
49
+
50
+ ransacker :participatory_space_type do
51
+ Arel.sql(%{("item_type")::text})
52
+ end
53
+
54
+ ransacker :user_email do
55
+ @user_email ||= begin
56
+ queries = PaperTrailVersion.safe_user_roles.map do |role_class|
57
+ table = role_class.safe_constantize.table_name
58
+ %(
59
+ SELECT decidim_users.email FROM decidim_users
60
+ JOIN #{table} ON decidim_users.id = #{table}.decidim_user_id
61
+ WHERE #{table}.id = versions.item_id
62
+ AND item_type = '#{role_class}'
63
+ )
64
+ end
65
+ queries << %(
66
+ SELECT decidim_users.email FROM decidim_users
67
+ WHERE decidim_users.id = versions.item_id
68
+ AND item_type = 'Decidim::UserBaseEntity'
69
+ )
70
+ Arel.sql("(#{queries.join(" UNION ")})")
71
+ end
72
+ end
73
+
74
+ ransacker :user_name do
75
+ @user_name ||= begin
76
+ queries = PaperTrailVersion.safe_user_roles.map do |role_class|
77
+ table = role_class.safe_constantize.table_name
78
+ %(
79
+ SELECT decidim_users.name FROM decidim_users
80
+ JOIN #{table} ON decidim_users.id = #{table}.decidim_user_id
81
+ WHERE #{table}.id = versions.item_id
82
+ AND item_type = '#{role_class}'
83
+ )
84
+ end
85
+ queries << %(
86
+ SELECT decidim_users.name FROM decidim_users
87
+ WHERE decidim_users.id = versions.item_id
88
+ AND item_type = 'Decidim::UserBaseEntity'
89
+ )
90
+ Arel.sql("(#{queries.join(" UNION ")})")
91
+ end
92
+ end
93
+
94
+ ransacker :created_at, type: :date do
95
+ Arel.sql("date(created_at)")
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,5 +1,6 @@
1
- import "src/decidim/decidim_awesome/awesome_admin"
2
- import "jquery-ui/ui/widgets/sortable" // This is needed by custom fields builder but if loader there duplicates the jQuery inclusion
1
+ import "src/decidim/decidim_awesome/awesome_admin";
2
+ // This is needed by custom fields builder but if loader there duplicates the jQuery inclusion
3
+ import "jquery-ui/ui/widgets/sortable";
3
4
 
4
5
  // CSS
5
6
  import "entrypoints/decidim_admin_decidim_awesome.scss";
@@ -1,13 +1,13 @@
1
1
  $(() => {
2
2
  let CustomFieldsBuilders = window.CustomFieldsBuilders || [];
3
3
 
4
- $("body").on("click", "a.awesome-auto-edit", (e) => {
5
- e.preventDefault();
6
- const $link = $(e.currentTarget);
4
+ $("body").on("click", "a.awesome-auto-edit", (ev) => {
5
+ ev.preventDefault();
6
+ const $link = $(ev.currentTarget);
7
7
  const scope = $link.data("scope");
8
8
  const $target = $(`span.awesome-auto-edit[data-scope="${scope}"]`);
9
9
  const $constraints = $(`.constraints-editor[data-key="${scope}"]`);
10
- if ($target.length == 0) {
10
+ if ($target.length === 0) {
11
11
  return;
12
12
  }
13
13
 
@@ -41,7 +41,7 @@ $(() => {
41
41
  $container.attr("data-key", result.key);
42
42
  $delete.attr("href", $delete.attr("href").replace(`key=${key}`, `key=${result.key}`))
43
43
  CustomFieldsBuilders.forEach((builder) => {
44
- if (builder.key == key) {
44
+ if (builder.key === key) {
45
45
  builder.key = result.key;
46
46
  }
47
47
  });
@@ -52,12 +52,12 @@ $(() => {
52
52
  $link.hide();
53
53
  $input.select();
54
54
  $input.on("keypress", (evt) => {
55
- if (evt.code == "Enter" || evt.code == "13" || evt.code == "10") {
55
+ if (evt.code === "Enter" || evt.code === "13" || evt.code === "10") {
56
56
  evt.preventDefault();
57
57
  $.ajax(
58
58
  {
59
59
  type: "POST",
60
- url: DecidimAwesome.rename_scope_label_path,
60
+ url: window.DecidimAwesome.rename_scope_label_path,
61
61
  dataType: "json",
62
62
  headers: {
63
63
  "X-CSRF-Token": $("meta[name=csrf-token]").attr("content")
@@ -14,13 +14,13 @@ $(() => {
14
14
 
15
15
  let type = response.type;
16
16
  let status = response.status;
17
- if (response.type == "opaqueredirect") {
17
+ if (response.type === "opaqueredirect") {
18
18
  type = "redirect";
19
19
  status = "302";
20
20
  }
21
21
 
22
22
  if (item.active) {
23
- if (type == "redirect") {
23
+ if (type === "redirect") {
24
24
  $td.addClass("success");
25
25
  } else {
26
26
  $td.addClass("alert");
@@ -4,9 +4,9 @@ $(() => {
4
4
  return;
5
5
  }
6
6
 
7
- $(".decidim_awesome-form").on("click", ".constraints-editor .add-condition,.constraints-editor .edit-condition", (e) => {
8
- e.preventDefault();
9
- const $this = $(e.target)
7
+ $(".decidim_awesome-form").on("click", ".constraints-editor .add-condition,.constraints-editor .edit-condition", (evt) => {
8
+ evt.preventDefault();
9
+ const $this = $(evt.target)
10
10
  const url = $this.attr("href");
11
11
  const $callout = $this.closest(".constraints-editor").find(".callout");
12
12
  $callout.hide();
@@ -21,8 +21,8 @@ $(() => {
21
21
  });
22
22
 
23
23
  // Custom event listener to reload the modal if needed
24
- document.body.addEventListener("constraint:change", (e) => {
25
- const vars = e.detail.map((setting) => `${setting.key}=${setting.value}`);
24
+ document.body.addEventListener("constraint:change", (evt) => {
25
+ const vars = evt.detail.map((setting) => `${setting.key}=${setting.value}`);
26
26
  const url = `${$modal.data("url")}&${vars.join("&")}`;
27
27
  // console.log("constraint:change vars:", vars, "url:", url)
28
28
  $modal.addClass("loading");
@@ -36,7 +36,8 @@ $(() => {
36
36
  "paragraph"
37
37
  ],
38
38
  disabledSubtypes: {
39
- text: ["color"], // default color as it generate hashtags in decidim (TODO: fix hashtag generator with this)
39
+ // default color as it generate hashtags in decidim (TODO: fix hashtag generator with this)
40
+ text: ["color"],
40
41
  // disable default wysiwyg editors as they present problems
41
42
  textarea: ["tinymce", "quill"]
42
43
  }
@@ -45,21 +46,21 @@ $(() => {
45
46
  });
46
47
  });
47
48
 
48
- $(document).on("formBuilder.create", (_event, i, list) => {
49
- if (!list[i]) {
49
+ $(document).on("formBuilder.create", (_event, idx, list) => {
50
+ if (!list[idx]) {
50
51
  return;
51
52
  }
52
53
 
53
- $(list[i].el).formBuilder(list[i].config).promise.then(function(res) {
54
- list[i].instance = res;
54
+ $(list[idx].el).formBuilder(list[idx].config).promise.then(function(res) {
55
+ list[idx].instance = res;
55
56
  // Attach to DOM
56
- list[i].el.FormBuilder = res;
57
+ list[idx].el.FormBuilder = res;
57
58
  // remove spinner
58
- $(list[i].el).find(".loading-spinner").remove();
59
+ $(list[idx].el).find(".loading-spinner").remove();
59
60
  // for external use
60
- $(document).trigger("formBuilder.created", [list[i]]);
61
- if (i < list.length) {
62
- $(document).trigger("formBuilder.create", [i + 1, list]);
61
+ $(document).trigger("formBuilder.created", [list[idx]]);
62
+ if (idx < list.length) {
63
+ $(document).trigger("formBuilder.create", [idx + 1, list]);
63
64
  }
64
65
  });
65
66
  });
@@ -23,6 +23,7 @@ $(() => {
23
23
  }
24
24
 
25
25
  event.returnValue = true;
26
+ return true;
26
27
  });
27
28
  }
28
29
  });
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-invalid-this */
1
2
  import "select2"
2
3
  import "stylesheets/decidim/decidim_awesome/admin/user_picker.scss"
3
4
 
@@ -67,13 +67,13 @@ export default class Fetcher {
67
67
  }
68
68
 
69
69
  findTranslation(translations) {
70
- let text,
71
- lang = document.querySelector("html").getAttribute("lang");
70
+ let lang = document.querySelector("html").getAttribute("lang"),
71
+ text = "";
72
72
 
73
- translations.forEach((t) => {
74
- if (t.text) {
75
- if (!text || t.locale == lang) {
76
- text = t.text
73
+ translations.forEach((txt) => {
74
+ if (txt.text) {
75
+ if (!text || txt.locale === lang) {
76
+ text = txt.text
77
77
  }
78
78
  }
79
79
  });
@@ -85,12 +85,10 @@ export default class Fetcher {
85
85
  if (text) {
86
86
  const gids = text.match(/gid:\/\/[^\s<&]+/g)
87
87
  if (gids) {
88
- tags = gids.filter((gid) => gid.indexOf("/Decidim::Hashtag/") != -1).map((gid) => {
88
+ tags = gids.filter((gid) => gid.indexOf("/Decidim::Hashtag/") !== -1).map((gid) => {
89
89
  const parts = gid.split("/");
90
- const fromSelector = parts[5].charAt(0) == "_";
91
- const tag = fromSelector
92
- ? parts[5].substr(1)
93
- : parts[5];
90
+ const fromSelector = parts[5].charAt(0) === "_";
91
+ const tag = fromSelector ? parts[5].substr(1) : parts[5]; // eslint-disable-line no-ternary, multiline-ternary
94
92
  const name = `#${tag}`;
95
93
  const html = `<a href="/search?term=${name}">${name}</a>`;
96
94
  const hashtag = {
@@ -110,7 +108,8 @@ export default class Fetcher {
110
108
  return tags;
111
109
  }
112
110
 
113
- replaceHashtags(text, hashtags) {
111
+ replaceHashtags(txt, hashtags) {
112
+ let text = txt;
114
113
  hashtags.forEach((tag) => {
115
114
  text = text.replace(tag.gid, tag.name)
116
115
  });
@@ -121,7 +120,8 @@ export default class Fetcher {
121
120
  return text.replace(/gid:\/\/[^\s<&]+/g, "");
122
121
  }
123
122
 
124
- appendHtmlHashtags(text, tags) {
123
+ appendHtmlHashtags(txt, tags) {
124
+ let text = txt;
125
125
  tags.forEach((tag) => {
126
126
  text += ` ${tag.html}`;
127
127
  });