decidim-decidim_awesome 0.11.4 → 0.12.3

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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -6
  3. data/README.md +33 -39
  4. data/Rakefile +12 -0
  5. data/app/cells/concerns/decidim/decidim_awesome/global_menu_cell_override.rb +14 -2
  6. data/app/cells/concerns/decidim/decidim_awesome/proposal_l_cell_override.rb +5 -4
  7. data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/show.erb +4 -4
  8. data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/vote_block_for.erb +1 -1
  9. data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal_cell.rb +3 -5
  10. data/app/commands/concerns/decidim/decidim_awesome/system/{register_organization_override.rb → create_organization_override.rb} +1 -1
  11. data/app/commands/concerns/decidim/decidim_awesome/update_account_override.rb +4 -4
  12. data/app/commands/decidim/decidim_awesome/admin/create_constraint.rb +1 -1
  13. data/app/commands/decidim/decidim_awesome/create_editor_image.rb +2 -2
  14. data/app/controllers/concerns/decidim/decidim_awesome/admin/maintenance_context.rb +0 -28
  15. data/app/controllers/concerns/decidim/decidim_awesome/needs_hashcash.rb +41 -0
  16. data/app/controllers/concerns/decidim/decidim_awesome/not_found_redirect.rb +2 -2
  17. data/app/controllers/decidim/decidim_awesome/admin/admin_authorizations_controller.rb +2 -2
  18. data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +0 -10
  19. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +2 -1
  20. data/app/controllers/decidim/decidim_awesome/admin/custom_redirects_controller.rb +1 -2
  21. data/app/controllers/decidim/decidim_awesome/admin/hashcash_controller.rb +39 -0
  22. data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +1 -1
  23. data/app/controllers/decidim/decidim_awesome/admin/{maintenance_controller.rb → private_data_controller.rb} +9 -9
  24. data/app/controllers/decidim/decidim_awesome/utils_controller.rb +17 -0
  25. data/app/forms/concerns/decidim/decidim_awesome/proposals/{proposal_wizard_create_step_form_override.rb → proposal_form_customizations.rb} +1 -1
  26. data/app/forms/concerns/decidim/decidim_awesome/proposals/proposal_form_override.rb +7 -1
  27. data/app/forms/concerns/decidim/decidim_awesome/system/organization_form_override.rb +2 -2
  28. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +13 -0
  29. data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +1 -1
  30. data/app/helpers/decidim/decidim_awesome/map_helper.rb +4 -2
  31. data/app/models/decidim/decidim_awesome/paper_trail_version.rb +1 -1
  32. data/app/overrides/decidim/devise/registrations/new/add_hashcash.html.erb.deface +3 -0
  33. data/app/overrides/decidim/devise/sessions/new/add_hashcash.html.erb.deface +3 -0
  34. data/app/overrides/layouts/decidim/_head/add_awesome_custom_styles.html.erb.deface +3 -0
  35. data/app/overrides/layouts/decidim/_head/add_awesome_tags.html.erb.deface +0 -2
  36. data/app/packs/entrypoints/decidim_admin_decidim_awesome_search_form.scss +1 -0
  37. data/app/packs/entrypoints/decidim_decidim_awesome_hashcash.js +4 -0
  38. data/app/packs/src/decidim/decidim_awesome/admin/auto_edit.js +10 -6
  39. data/app/packs/src/decidim/decidim_awesome/admin/custom_fields_builder.js +4 -2
  40. data/app/packs/src/decidim/decidim_awesome/admin/verifications.js +6 -3
  41. data/app/packs/src/decidim/decidim_awesome/awesome_map/api/proposals_fetcher.js +1 -1
  42. data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/controller.js +1 -1
  43. data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/proposals_controller.js +1 -1
  44. data/app/packs/src/decidim/decidim_awesome/awesome_map/controls_ui.js +6 -6
  45. data/app/packs/src/decidim/decidim_awesome/awesome_map/load_map.js +1 -1
  46. data/app/packs/src/decidim/decidim_awesome/forms/autosave.js +3 -3
  47. data/app/packs/src/decidim/decidim_awesome/forms/custom_fields_renderer.js +1 -113
  48. data/app/packs/src/decidim/decidim_awesome/proposals/images.js +1 -1
  49. data/app/packs/src/vendor/form_builder_langs/ar-SA.lang +111 -0
  50. data/app/packs/src/vendor/form_builder_langs/ar-TN.lang +94 -0
  51. data/app/packs/src/vendor/form_builder_langs/ca-ES.lang +110 -0
  52. data/app/packs/src/vendor/form_builder_langs/cs-CZ.lang +105 -0
  53. data/app/packs/src/vendor/form_builder_langs/da-DK.lang +110 -0
  54. data/app/packs/src/vendor/form_builder_langs/de-DE.lang +109 -0
  55. data/app/packs/src/vendor/form_builder_langs/el-GR.lang +110 -0
  56. data/app/packs/src/vendor/form_builder_langs/en-US.lang +117 -0
  57. data/app/packs/src/vendor/form_builder_langs/es-ES.lang +103 -0
  58. data/app/packs/src/vendor/form_builder_langs/fa-IR.lang +108 -0
  59. data/app/packs/src/vendor/form_builder_langs/fi-FI.lang +107 -0
  60. data/app/packs/src/vendor/form_builder_langs/fr-FR.lang +117 -0
  61. data/app/packs/src/vendor/form_builder_langs/he-IL.lang +108 -0
  62. data/app/packs/src/vendor/form_builder_langs/hi-IN.lang +110 -0
  63. data/app/packs/src/vendor/form_builder_langs/hu-HU.lang +108 -0
  64. data/app/packs/src/vendor/form_builder_langs/id-ID.lang +110 -0
  65. data/app/packs/src/vendor/form_builder_langs/it-IT.lang +107 -0
  66. data/app/packs/src/vendor/form_builder_langs/ja-JP.lang +108 -0
  67. data/app/packs/src/vendor/form_builder_langs/my-MM.lang +108 -0
  68. data/app/packs/src/vendor/form_builder_langs/nb-NO.lang +94 -0
  69. data/app/packs/src/vendor/form_builder_langs/nl-NL.lang +94 -0
  70. data/app/packs/src/vendor/form_builder_langs/pl-PL.lang +122 -0
  71. data/app/packs/src/vendor/form_builder_langs/pt-BR.lang +110 -0
  72. data/app/packs/src/vendor/form_builder_langs/pu-IN.lang +110 -0
  73. data/app/packs/src/vendor/form_builder_langs/qz-MM.lang +108 -0
  74. data/app/packs/src/vendor/form_builder_langs/ro-RO.lang +94 -0
  75. data/app/packs/src/vendor/form_builder_langs/ru-RU.lang +110 -0
  76. data/app/packs/src/vendor/form_builder_langs/sl-SI.lang +110 -0
  77. data/app/packs/src/vendor/form_builder_langs/th-TH.lang +111 -0
  78. data/app/packs/src/vendor/form_builder_langs/tr-TR.lang +115 -0
  79. data/app/packs/src/vendor/form_builder_langs/uk-UA.lang +108 -0
  80. data/app/packs/src/vendor/form_builder_langs/vi-VN.lang +94 -0
  81. data/app/packs/src/vendor/form_builder_langs/zh-CN.lang +100 -0
  82. data/app/packs/src/vendor/form_builder_langs/zh-TW.lang +94 -0
  83. data/app/packs/src/vendor/hashcash.js +83 -0
  84. data/app/packs/src/vendor/sha1.js +143 -0
  85. data/app/packs/src/vendor/stamp.js +50 -0
  86. data/app/packs/stylesheets/decidim/decidim_awesome/admin/admin_accountability.scss +67 -0
  87. data/app/packs/stylesheets/decidim/decidim_awesome/forms/autosave.scss +2 -12
  88. data/app/permissions/decidim/decidim_awesome/permissions.rb +3 -2
  89. data/app/presenters/decidim/decidim_awesome/private_data_presenter.rb +2 -2
  90. data/app/uploaders/decidim/decidim_awesome/image_uploader.rb +12 -0
  91. data/app/views/decidim/decidim_awesome/admin/admin_accountability/index.html.erb +5 -4
  92. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/callout.html.erb +2 -2
  93. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/conflict.html.erb +4 -4
  94. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/edit.html.erb +6 -5
  95. data/app/views/decidim/decidim_awesome/admin/checks/index.html.erb +6 -6
  96. data/app/views/decidim/decidim_awesome/admin/config/_autoedit_box_label.html.erb +2 -2
  97. data/app/views/decidim/decidim_awesome/admin/config/_constraints.html.erb +3 -3
  98. data/app/views/decidim/decidim_awesome/admin/config/_form_admins.html.erb +4 -3
  99. data/app/views/decidim/decidim_awesome/admin/config/_form_editors.html.erb +1 -1
  100. data/app/views/decidim/decidim_awesome/admin/config/_form_proposal_custom_fields.html.erb +4 -4
  101. data/app/views/decidim/decidim_awesome/admin/config/_form_scoped_styles.html.erb +3 -3
  102. data/app/views/decidim/decidim_awesome/admin/config/_form_surveys.html.erb +40 -2
  103. data/app/views/decidim/decidim_awesome/admin/config/_form_verifications.html.erb +1 -1
  104. data/app/views/decidim/decidim_awesome/admin/hashcash/_filters.html.erb +55 -0
  105. data/app/views/decidim/decidim_awesome/admin/hashcash/index.html.erb +33 -0
  106. data/app/views/decidim/decidim_awesome/admin/hashcash/ip_addresses.html.erb +29 -0
  107. data/app/views/decidim/decidim_awesome/admin/hashcash/show.html.erb +42 -0
  108. data/app/views/decidim/decidim_awesome/admin/menu_hacks/index.html.erb +2 -2
  109. data/app/views/decidim/decidim_awesome/admin/{maintenance → private_data}/_private_data.html.erb +2 -2
  110. data/app/views/decidim/decidim_awesome/admin/{maintenance/show.html.erb → private_data/index.html.erb} +2 -3
  111. data/app/views/decidim/decidim_awesome/admin/proposals/_private_body.html.erb +1 -1
  112. data/app/views/decidim/decidim_awesome/admin/shared/_filters_with_date.html.erb +41 -32
  113. data/app/views/decidim/decidim_awesome/amendments/_modal.html.erb +2 -2
  114. data/app/views/decidim/decidim_awesome/hashcash/_hidden_field.html.erb +5 -0
  115. data/app/views/decidim/decidim_awesome/map_component/map/_map_template.html.erb +1 -1
  116. data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +2 -2
  117. data/app/views/layouts/decidim/decidim_awesome/admin/maintenance.html.erb +2 -11
  118. data/config/assets.rb +3 -1
  119. data/config/i18n-tasks.yml +1 -0
  120. data/config/locales/ca.yml +69 -30
  121. data/config/locales/cs.yml +68 -29
  122. data/config/locales/de.yml +67 -28
  123. data/config/locales/en.yml +81 -32
  124. data/config/locales/es.yml +68 -29
  125. data/config/locales/eu.yml +31 -31
  126. data/config/locales/fr.yml +82 -31
  127. data/config/locales/ja.yml +31 -31
  128. data/lib/decidim/decidim_awesome/admin_engine.rb +8 -5
  129. data/lib/decidim/decidim_awesome/awesome.rb +49 -27
  130. data/lib/decidim/decidim_awesome/checksums.yml +47 -42
  131. data/lib/decidim/decidim_awesome/context_analyzers/request_analyzer.rb +2 -2
  132. data/lib/decidim/decidim_awesome/engine.rb +16 -6
  133. data/lib/decidim/decidim_awesome/menu.rb +151 -138
  134. data/lib/decidim/decidim_awesome/test/initializer.rb +4 -1
  135. data/lib/decidim/decidim_awesome/test/shared_examples/box_label_editor_examples.rb +14 -14
  136. data/lib/decidim/decidim_awesome/test/shared_examples/config_examples.rb +2 -4
  137. data/lib/decidim/decidim_awesome/test/shared_examples/custom_fields_examples.rb +8 -8
  138. data/lib/decidim/decidim_awesome/test/shared_examples/custom_styles_examples.rb +6 -6
  139. data/lib/decidim/decidim_awesome/test/shared_examples/editor_examples.rb +5 -4
  140. data/lib/decidim/decidim_awesome/test/shared_examples/scoped_admins_examples.rb +5 -5
  141. data/lib/decidim/decidim_awesome/test/shared_examples/summary_examples.rb +16 -9
  142. data/lib/decidim/decidim_awesome/version.rb +2 -2
  143. data/lib/decidim/decidim_awesome.rb +0 -1
  144. data/lib/tasks/decidim_awesome_upgrade_tasks.rake +4 -5
  145. data/package.json +9 -18
  146. metadata +82 -26
  147. data/app/jobs/decidim/decidim_awesome/migrate_legacy_images_job.rb +0 -107
  148. data/app/uploaders/decidim/cw/decidim_awesome/image_uploader.rb +0 -26
  149. data/config/rubocop/disabled.yml +0 -11
  150. data/config/rubocop/faker.yml +0 -480
  151. data/config/rubocop/rails.yml +0 -88
  152. data/config/rubocop/rspec.yml +0 -65
  153. data/config/rubocop/ruby.yml +0 -1210
  154. data/lib/decidim/decidim_awesome/content_parsers/editor_images_parser.rb +0 -39
  155. data/lib/tasks/decidim_awesome_active_storage_migrations_tasks.rake +0 -35
  156. /data/{app/middleware/decidim/decidim_awesome → lib/decidim/decidim_awesome/middleware}/current_config.rb +0 -0
@@ -6,7 +6,7 @@ module Decidim
6
6
  module DecidimAwesome
7
7
  module Admin
8
8
  # System compatibility analyzer
9
- class MaintenanceController < DecidimAwesome::Admin::ApplicationController
9
+ class PrivateDataController < DecidimAwesome::Admin::ApplicationController
10
10
  include NeedsAwesomeConfig
11
11
  include MaintenanceContext
12
12
  include Decidim::Admin::Filterable
@@ -19,36 +19,36 @@ module Decidim
19
19
  enforce_permission_to :edit_config, :private_data, private_data:
20
20
  end
21
21
 
22
- def show
22
+ def index
23
23
  respond_to do |format|
24
24
  format.json do
25
25
  render json: private_data_finder.for(params[:resources].to_s.split(",")).map { |resource| present(resource) }
26
26
  end
27
27
  format.all do
28
- render :show
28
+ render :index
29
29
  end
30
30
  end
31
31
  end
32
32
 
33
- def destroy_private_data
33
+ def destroy
34
34
  if private_data && private_data.total.to_i.positive?
35
35
  Decidim::ActionLogger.log("destroy_private_data", current_user, resource, nil, count: private_data.total)
36
36
 
37
37
  Lock.new(current_organization).get!(resource)
38
38
  DestroyPrivateDataJob.set(wait: 1.second).perform_later(resource)
39
39
  end
40
- redirect_to decidim_admin_decidim_awesome.maintenance_path("private_data"),
41
- notice: I18n.t("destroying_private_data", scope: "decidim.decidim_awesome.admin.maintenance.private_data", title: present_private_data(resource).name)
40
+ redirect_to decidim_admin_decidim_awesome.private_data_path,
41
+ notice: I18n.t("destroying", scope: "decidim.decidim_awesome.admin.private_data.private_data", title: present(resource).name)
42
42
  end
43
43
 
44
44
  private
45
45
 
46
46
  def resource
47
- @resource ||= Component.find_by(id: params[:resource_id])
47
+ @resource ||= Component.find_by(id: params[:id])
48
48
  end
49
49
 
50
50
  def private_data
51
- @private_data ||= present_private_data(resource) if resource
51
+ @private_data ||= present(resource) if resource
52
52
  end
53
53
 
54
54
  def collection
@@ -60,7 +60,7 @@ module Decidim
60
60
  end
61
61
 
62
62
  def present(resource)
63
- present_private_data(resource)
63
+ PrivateDataPresenter.new(resource)
64
64
  end
65
65
 
66
66
  def private_data_finder
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ # Abstract component class for components without any admin controllers (only settings)
6
+ class UtilsController < DecidimAwesome::ApplicationController
7
+ def form_builder_i18n
8
+ lang = I18n.locale
9
+ folder = "app/packs/src/vendor/form_builder_langs/"
10
+ file = Decidim::DecidimAwesome::Engine.root.join(folder, "#{lang}.lang")
11
+ file = Dir[Decidim::DecidimAwesome::Engine.root.join(folder, "#{lang}-*.lang")].first unless File.exist?(file)
12
+ file = Decidim::DecidimAwesome::Engine.root.join(folder, "en-US.lang") unless file && File.exist?(file)
13
+ render plain: File.read(file)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -4,7 +4,7 @@
4
4
  module Decidim
5
5
  module DecidimAwesome
6
6
  module Proposals
7
- module ProposalWizardCreateStepFormOverride
7
+ module ProposalFormCustomizations
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  included do
@@ -8,7 +8,13 @@ module Decidim
8
8
 
9
9
  included do
10
10
  alias_method :decidim_original_map_model, :map_model
11
- attribute :private_body, String
11
+ attribute :private_body, Decidim::Attributes::RichText
12
+
13
+ if name == "Decidim::Proposals::ProposalForm"
14
+ # the original decidim uses CleanString, as no images are allowed for non admins
15
+ # The RichText attribute transforms signed_id blobs to ObjectIDs
16
+ attribute :body, Decidim::Attributes::RichText
17
+ end
12
18
 
13
19
  def map_model(model)
14
20
  decidim_original_map_model(model)
@@ -9,7 +9,7 @@ module Decidim
9
9
  included do
10
10
  alias_method :decidim_original_map_model, :map_model
11
11
 
12
- attribute :awesome_admins_available_authorizations, Array[String]
12
+ attribute :awesome_admins_available_authorizations, [String]
13
13
 
14
14
  def map_model(model)
15
15
  decidim_original_map_model(model)
@@ -19,7 +19,7 @@ module Decidim
19
19
  def clean_awesome_admins_available_authorizations
20
20
  return unless awesome_admins_available_authorizations
21
21
 
22
- awesome_admins_available_authorizations.select(&:present?)
22
+ awesome_admins_available_authorizations.compact_blank
23
23
  end
24
24
 
25
25
  private
@@ -20,6 +20,10 @@ module Decidim
20
20
  attribute :user_timezone, Boolean
21
21
  attribute :force_authorization_after_login, Array
22
22
  attribute :force_authorization_with_any_method, Boolean
23
+ attribute :hashcash_signup, Boolean
24
+ attribute :hashcash_signup_bits, Integer, default: Decidim::DecidimAwesome.hashcash_signup_bits
25
+ attribute :hashcash_login, Boolean
26
+ attribute :hashcash_login_bits, Integer, default: Decidim::DecidimAwesome.hashcash_login_bits
23
27
  translatable_attribute :force_authorization_help_text, String
24
28
  attribute :scoped_admins, Hash
25
29
  attribute :menu, [MenuForm]
@@ -49,6 +53,8 @@ module Decidim
49
53
  validates :validate_body_min_length, presence: true, numericality: { greater_than_or_equal_to: 0 }
50
54
  validates :validate_body_max_caps_percent, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }
51
55
  validates :validate_body_max_marks_together, presence: true, numericality: { greater_than_or_equal_to: 1 }
56
+ validates :hashcash_signup_bits, presence: true, numericality: { greater_than_or_equal_to: 10, less_than_or_equal_to: 50 }
57
+ validates :hashcash_login_bits, presence: true, numericality: { greater_than_or_equal_to: 10, less_than_or_equal_to: 50 }
52
58
  validate :force_authorization_after_login_is_valid
53
59
  # TODO: validate non general admins are here
54
60
 
@@ -57,6 +63,7 @@ module Decidim
57
63
  instance.force_authorization_after_login = instance.force_authorization_after_login.compact_blank if instance.force_authorization_after_login.present?
58
64
  instance.valid_keys = extract_valid_keys_from_params(params)
59
65
  instance.sanitize_labels!
66
+ instance.sanitize_arrays!
60
67
  instance
61
68
  end
62
69
 
@@ -135,6 +142,12 @@ module Decidim
135
142
  end
136
143
  end
137
144
 
145
+ def sanitize_arrays!
146
+ scoped_admins.transform_values! do |code|
147
+ code.is_a?(Array) ? code.compact_blank : code
148
+ end
149
+ end
150
+
138
151
  private
139
152
 
140
153
  def force_authorization_after_login_is_valid
@@ -8,7 +8,7 @@ module Decidim
8
8
 
9
9
  include Decidim::TranslatableAttributes
10
10
 
11
- delegate :menus, :config_enabled?, to: "Decidim::DecidimAwesome::Menu"
11
+ delegate :menus, :main_path_for, :config_enabled?, to: "Decidim::DecidimAwesome::Menu"
12
12
 
13
13
  def check(status)
14
14
  content_tag(:span, icon(status ? "check-line" : "close-line", class: "inline-block", aria_label: status, role: "img"), class: "fill-#{status ? "success" : "alert"}")
@@ -10,7 +10,7 @@ module Decidim
10
10
  end
11
11
 
12
12
  # rubocop:disable Metrics/CyclomaticComplexity
13
- # rubocop:disable Metrics/PerceivedComplexity:
13
+ # rubocop:disable Metrics/PerceivedComplexity
14
14
  def awesome_map_for(components, &)
15
15
  return unless map_utility_dynamic
16
16
 
@@ -57,7 +57,7 @@ module Decidim
57
57
  end
58
58
  end
59
59
  # rubocop:enable Metrics/CyclomaticComplexity
60
- # rubocop:enable Metrics/PerceivedComplexity:
60
+ # rubocop:enable Metrics/PerceivedComplexity
61
61
 
62
62
  def step_settings
63
63
  settings_source.try(:current_settings)
@@ -71,6 +71,7 @@ module Decidim
71
71
  try(:current_component) || self
72
72
  end
73
73
 
74
+ # rubocop:disable Rails/HelperInstanceVariable
74
75
  def current_categories(categories)
75
76
  return @current_categories if @current_categories
76
77
 
@@ -114,6 +115,7 @@ module Decidim
114
115
  color: format("#%02x%02x%02x", r, g, b)
115
116
  )
116
117
  end
118
+ # rubocop:enable Rails/HelperInstanceVariable
117
119
 
118
120
  # HSV values in [0..1[
119
121
  # returns [r, g, b] values from 0 to 255
@@ -20,7 +20,7 @@ module Decidim
20
20
  # add users that might have been completly destroyed in any organization
21
21
  relevant_user_ids += user_ids_from_object_changes - Decidim::User.select("id").where(id: user_ids_from_object_changes).pluck(:id)
22
22
 
23
- role_changes.where("object_changes ~ ANY (array[?])", relevant_user_ids.map { |id| "decidim_user_id:\n- ?\n- #{id}" })
23
+ role_changes.where("object_changes ~ ANY (array[?])", relevant_user_ids.map { |id| "decidim_user_id:\n- ?\n- #{id}(?!\\d)" })
24
24
  }
25
25
 
26
26
  scope :in_organization, lambda { |organization|
@@ -0,0 +1,3 @@
1
+ <!-- insert_top ".login__links" -->
2
+
3
+ <%= render partial: "decidim/decidim_awesome/hashcash/hidden_field", locals: { zone: :signup } %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_top ".login__links" -->
2
+
3
+ <%= render partial: "decidim/decidim_awesome/hashcash/hidden_field", locals: { zone: :login } %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_after "erb[loud]:contains('content_for :header_snippets')" -->
2
+
3
+ <%= render(partial: "layouts/decidim/decidim_awesome/custom_styles") if awesome_scoped_styles.present? %>
@@ -1,7 +1,5 @@
1
1
  <!-- insert_after "erb[loud]:contains('append_stylesheet_pack_tag')" -->
2
2
 
3
3
  <% append_stylesheet_pack_tag "decidim_decidim_awesome", media: "all" %>
4
- <%= render(partial: "layouts/decidim/decidim_awesome/custom_styles") if awesome_scoped_styles.present? %>
5
-
6
4
  <% append_javascript_pack_tag "decidim_decidim_awesome", defer: false %>
7
5
  <% append_javascript_pack_tag("decidim_decidim_awesome_custom_fields") if Decidim::DecidimAwesome.enabled?(:proposal_custom_fields) %>
@@ -0,0 +1 @@
1
+ @import "stylesheets/decidim/decidim_awesome/admin/admin_accountability";
@@ -0,0 +1,4 @@
1
+ import Hashcash from "src/vendor/hashcash";
2
+
3
+ Hashcash.setup();
4
+
@@ -14,8 +14,8 @@ document.addEventListener("DOMContentLoaded", () => {
14
14
 
15
15
  const key = target.dataset.key;
16
16
  const attribute = target.dataset.var;
17
- const inputField = document.querySelector(`[name="config[${attribute}][${key}]"]`);
18
- const multipleField = document.querySelector(`[name="config[${attribute}][${key}][]"]`);
17
+ const inputFields = document.querySelectorAll(`[name="config[${attribute}][${key}]"]`);
18
+ const multipleFields = document.querySelectorAll(`[name="config[${attribute}][${key}][]"]`);
19
19
  const container = document.querySelector(`.js-box-container[data-key="${key}"]`);
20
20
  const deleteBox = container.querySelector(".awesome-auto-delete");
21
21
 
@@ -32,11 +32,15 @@ document.addEventListener("DOMContentLoaded", () => {
32
32
  const rebuildHtml = (result) => {
33
33
  rebuildLabel(result.key, result.scope);
34
34
  constraints.outerHTML = result.html;
35
- if (inputField) {
36
- inputField.setAttribute("name", `config[${attribute}][${result.key}]`);
35
+ if (inputFields.length > 0) {
36
+ inputFields.forEach((inputField) => {
37
+ inputField.setAttribute("name", `config[${attribute}][${result.key}]`);
38
+ });
37
39
  }
38
- if (multipleField) {
39
- multipleField.setAttribute("name", `config[${attribute}][${result.key}][]`);
40
+ if (multipleFields.length > 0) {
41
+ multipleFields.forEach((multipleField) => {
42
+ multipleField.setAttribute("name", `config[${attribute}][${result.key}][]`);
43
+ });
40
44
  }
41
45
  container.dataset.key = result.key;
42
46
  container.setAttribute("data-key", result.key);
@@ -1,5 +1,6 @@
1
1
  import "formBuilder/dist/form-builder.min.js";
2
2
  import "src/decidim/decidim_awesome/forms/rich_text_plugin"
3
+
3
4
  // formBuilder uses jquery-ui-sortable which is a very dirty npm package with no neat source code available, and causes problems with the webpacker configuration of Decidim.
4
5
  // For the moment, we'll remove the sortable functionality with a dummy jQuery plugin until we find another sortable plugin (or keep it disabled for good)
5
6
  jQuery.fn.sortable = () => {}
@@ -10,6 +11,7 @@ $(() => {
10
11
  $(".awesome-edit-config .proposal_custom_fields_editor").each((_idx, el) => {
11
12
  const key = $(el).closest(".proposal_custom_fields_container").data("key");
12
13
  const configVar = $(el).closest(".proposal_custom_fields_container").data("var");
14
+
13
15
  // DOCS: https://formbuilder.online/docs
14
16
  window.CustomFieldsBuilders.push({
15
17
  el: el,
@@ -17,8 +19,8 @@ $(() => {
17
19
  var: configVar,
18
20
  config: {
19
21
  i18n: {
20
- locale: "en-US",
21
- location: "https://cdn.jsdelivr.net/npm/formbuilder-languages@1.1.0/"
22
+ locale: window.DecidimAwesome.currentLocale,
23
+ location: window.DecidimAwesome.formBuilderLangsLocation
22
24
  },
23
25
  formData: $(`input[name="config[${configVar}][${key}]"]`).val(),
24
26
  disableFields: ["button", "file"],
@@ -17,10 +17,13 @@ document.addEventListener("DOMContentLoaded", () => {
17
17
  });
18
18
 
19
19
 
20
- document.body.addEventListener("ajax:complete", (responseText) => {
21
- const response = JSON.parse(responseText.detail[0].response)
20
+ document.body.addEventListener("ajax:error", (responseText) => {
21
+ container.innerHTML = `<div>${responseText.detail[0]}</div>`;
22
+ });
23
+ document.body.addEventListener("ajax:success", (responseText) => {
24
+ // console.log("ajax:success", responseText);
25
+ const response = responseText.detail[0];
22
26
  const button = document.querySelector(`[data-verification-handler="${response.handler}"][data-verification-user-id="${response.userId}"]`);
23
- // console.log("ajax:complete", responseText, "response", response, "button", button);
24
27
  container.innerHTML = response.message;
25
28
 
26
29
  if (response.granted) {
@@ -58,7 +58,7 @@ export default class ProposalsFetcher extends Fetcher {
58
58
 
59
59
  decorateNode(node) {
60
60
  super.decorateNode(node);
61
- node.authorName = node.author && node.author.name || window.DecidimAwesome.texts.officialAuthor;
61
+ node.authorName = node.author && node.author.name || window.DecidimAwesome.i18n.officialAuthor;
62
62
  node.humanState = window.AwesomeMapProposalTexts[node.state];
63
63
  switch (node.state) {
64
64
  case "accepted":
@@ -16,7 +16,7 @@ export default class Controller {
16
16
  getLabel() {
17
17
  let text = this.component.name;
18
18
  if (!text || this.awesomeMap.config.menu.mergeComponents) {
19
- text = window.DecidimAwesome.texts[this.component.type];
19
+ text = window.DecidimAwesome.i18n[this.component.type];
20
20
  }
21
21
  return `<span class="awesome_map-component" id="awesome_map-component_${this.component.id}" title="0" data-layer="${this.component.type}">${text}</span>`
22
22
  }
@@ -16,7 +16,7 @@ export default class ProposalsController extends Controller {
16
16
  // add control layer for amendments if any
17
17
  if (this.awesomeMap.config.menu.amendments && this.component.amendments && !this.awesomeMap.layers.amendments) {
18
18
  this.awesomeMap.layers.amendments = {
19
- label: `<span class="awesome_map-component" id="awesome_map-amendments_${this.component.id}" title="0" data-layer="amendments">${window.DecidimAwesome.texts.amendments}</span>`,
19
+ label: `<span class="awesome_map-component" id="awesome_map-amendments_${this.component.id}" title="0" data-layer="amendments">${window.DecidimAwesome.i18n.amendments}</span>`,
20
20
  group: new L.FeatureGroup.SubGroup(this.awesomeMap.cluster)
21
21
  }
22
22
  this.awesomeMap.controls.main.addOverlay(this.awesomeMap.layers.amendments.group, this.awesomeMap.layers.amendments.label);
@@ -82,8 +82,8 @@ export default class ControlsUI {
82
82
  addSearchControls() {
83
83
  const section = this.main.getContainer().querySelector(".leaflet-control-layers-list");
84
84
  if (section) {
85
- section.insertAdjacentHTML("beforeend", `<div id="awesome_map-categories-control" class="active"><b class="awesome_map-title-control">${window.DecidimAwesome.texts.categories}</b><div class="categories-container"></div></div>
86
- <div id="awesome_map-hashtags-control"><b class="awesome_map-title-control">${window.DecidimAwesome.texts.hashtags}</b><div class="hashtags-container"></div><a href="#" class="awesome_map-toggle_all_tags">${window.DecidimAwesome.texts.selectDeselectAll}</a></div>`);
85
+ section.insertAdjacentHTML("beforeend", `<div id="awesome_map-categories-control" class="active"><b class="awesome_map-title-control">${window.DecidimAwesome.i18n.categories}</b><div class="categories-container"></div></div>
86
+ <div id="awesome_map-hashtags-control"><b class="awesome_map-title-control">${window.DecidimAwesome.i18n.hashtags}</b><div class="hashtags-container"></div><a href="#" class="awesome_map-toggle_all_tags">${window.DecidimAwesome.i18n.selectDeselectAll}</a></div>`);
87
87
  } else {
88
88
  console.error("Can't find the section to insert the controls");
89
89
  }
@@ -158,7 +158,7 @@ export default class ControlsUI {
158
158
 
159
159
  const label = document.querySelector(`label.awesome_map-hashtag-${hashtag.tag}`);
160
160
  // update number of items
161
- label.setAttribute("title", `${parseInt(label.title || 0, 10) + 1} ${window.DecidimAwesome.texts.items}`);
161
+ label.setAttribute("title", `${parseInt(label.title || 0, 10) + 1} ${window.DecidimAwesome.i18n.items}`);
162
162
  });
163
163
  }
164
164
  }
@@ -171,12 +171,12 @@ export default class ControlsUI {
171
171
  if (label) {
172
172
  label.style.display = "block";
173
173
  // update number of items
174
- label.setAttribute("title", `${parseInt(label.title || 0, 10) + 1} ${window.DecidimAwesome.texts.items}`);
174
+ label.setAttribute("title", `${parseInt(label.title || 0, 10) + 1} ${window.DecidimAwesome.i18n.items}`);
175
175
  }
176
176
  if (parent) {
177
177
  // show parent if apply
178
178
  parent.style.display = "block"
179
- parent.setAttribute("title", `${parseInt(parent.title || 0, 10) + 1} ${window.DecidimAwesome.texts.items}`);
179
+ parent.setAttribute("title", `${parseInt(parent.title || 0, 10) + 1} ${window.DecidimAwesome.i18n.items}`);
180
180
  }
181
181
  }
182
182
 
@@ -224,7 +224,7 @@ export default class ControlsUI {
224
224
  updateStats(uid, total) {
225
225
  // update component stats
226
226
  const $component = $(`#awesome_map-${uid}`);
227
- $component.attr("title", `${total} ${window.DecidimAwesome.texts.items}`);
227
+ $component.attr("title", `${total} ${window.DecidimAwesome.i18n.items}`);
228
228
  }
229
229
 
230
230
  _indeterminateParentInput(cat) {
@@ -25,7 +25,7 @@ document.addEventListener("DOMContentLoaded", () => {
25
25
  const dataset = document.getElementById("awesome-map").dataset;
26
26
  const config = {
27
27
  length: parse(dataset.truncate) || 254,
28
- center: sanitizeCenter(parse(dataset.mapCenter)),
28
+ center: sanitizeCenter(dataset.mapCenter),
29
29
  zoom: parse(dataset.mapZoom),
30
30
  menu: {
31
31
  amendments: parse(dataset.menuAmendments),
@@ -55,12 +55,12 @@ document.addEventListener("DOMContentLoaded", () => {
55
55
  };
56
56
 
57
57
  if (!window.localStorage) {
58
- showMsg(window.DecidimAwesome.texts.autosavedError, true);
58
+ showMsg(window.DecidimAwesome.i18n.autosavedError, true);
59
59
  return;
60
60
  }
61
61
 
62
62
  if (window.localStorage.getItem(storeId)) {
63
- showMsg(window.DecidimAwesome.texts.autosavedRetrieved, false, 5000);
63
+ showMsg(window.DecidimAwesome.i18n.autosavedRetrieved, false, 5000);
64
64
  }
65
65
 
66
66
  // restore if available
@@ -85,7 +85,7 @@ document.addEventListener("DOMContentLoaded", () => {
85
85
  checkboxes[el.id] = el.checked;
86
86
  });
87
87
  window.localStorage.setItem(storeCheckboxesId, JSON.stringify(checkboxes));
88
- showMsg(window.DecidimAwesome.texts.autosavedSuccess);
88
+ showMsg(window.DecidimAwesome.i18n.autosavedSuccess);
89
89
  };
90
90
 
91
91
  // save changes when modifications
@@ -2,53 +2,6 @@ import "formBuilder/dist/form-render.min.js";
2
2
  import "src/decidim/decidim_awesome/forms/rich_text_plugin"
3
3
 
4
4
  export default class CustomFieldsRenderer { // eslint-disable-line no-unused-vars
5
- constructor() {
6
- this.lang = this.getLang(window.DecidimAwesome.currentLocale);
7
- }
8
-
9
- getLang(lang) {
10
- const langs = {
11
- // ar: 'ar-SA', // Not in decidim yet
12
- "ar": "ar-TN",
13
- "ca": "ca-ES",
14
- "cs": "cs-CZ",
15
- "da": "da-DK",
16
- "de": "de-DE",
17
- "el": "el-GR",
18
- "en": "en-US",
19
- "es": "es-ES",
20
- "fa": "fa-IR",
21
- "fi": "fi-FI",
22
- "fr": "fr-FR",
23
- "he": "he-IL",
24
- "hu": "hu-HU",
25
- "it": "it-IT",
26
- "ja": "ja-JP",
27
- "my": "my-MM",
28
- "nb": "nb-NO",
29
- "nl": "nl-NL",
30
- "pl": "pl-PL",
31
- "pt": "pt-BR",
32
- "qz": "qz-MM",
33
- "ro": "ro-RO",
34
- "ru": "ru-RU",
35
- "sl": "sl-SI",
36
- "th": "th-TH",
37
- "tr": "tr-TR",
38
- "uk": "uk-UA",
39
- "vi": "vi-VN",
40
- "zh-TW": "zh-TW",
41
- "zh": "zh-CN"
42
- };
43
- if (langs[lang]) {
44
- return langs[lang];
45
- }
46
- if (langs[lang.substr(0, 2)]) {
47
- return langs[lang.substr(0, 2)];
48
- }
49
- return "en-US";
50
- }
51
-
52
5
  /*
53
6
  * Creates an XML document with a subset of html-compatible dl/dd/dt elements
54
7
  * to store the custom fields answers
@@ -116,70 +69,6 @@ export default class CustomFieldsRenderer { // eslint-disable-line no-unused-var
116
69
  return `<xml>${$dl[0].outerHTML}</xml>`;
117
70
  }
118
71
 
119
- fixBuggyFields() {
120
- if (!this.$element) {
121
- return false;
122
- }
123
-
124
- /**
125
- * Hack to fix required checkboxes being reset
126
- * Issue: https://github.com/decidim-ice/decidim-module-decidim_awesome/issues/82
127
- */
128
- this.$element.find(".formbuilder-checkbox-group").each((_key, group) => {
129
- const inputs = $(".formbuilder-checkbox input", group);
130
- const $label = $(group).find("label");
131
- const data = this.spec.find((obj) => obj.type === "checkbox-group" && obj.name === $label.attr("for"));
132
- let values = data.userData;
133
- if (!inputs.length || !data || !values) {
134
- return;
135
- }
136
-
137
- inputs.each((_idx, input) => {
138
- let index = values.indexOf(input.value);
139
- if (index >= 0) {
140
- values.splice(index, 1)
141
- // setting checked=true do not makes the browser aware that the form is valid if the field is required
142
- if (!input.checked)
143
- {$(input).click();}
144
- } else if (input.checked)
145
- {$(input).click();}
146
- });
147
-
148
- // Fill "other" option
149
- const otherOption = $(".other-option", inputs.parent())[0];
150
- const otherVal = $(".other-val", inputs.parent())[0];
151
- const otherText = values.join(" ");
152
-
153
- if (otherOption) {
154
- if (otherText) {
155
- otherOption.checked = true;
156
- otherOption.value = otherText;
157
- otherVal.value = otherText;
158
- } else {
159
- otherOption.checked = false;
160
- otherOption.value = "";
161
- otherVal.value = "";
162
- }
163
- }
164
- });
165
-
166
- /**
167
- * Hack to fix required radio buttons "other" value
168
- * Issue: https://github.com/decidim-ice/decidim-module-decidim_awesome/issues/133
169
- */
170
- this.$element.find(".formbuilder-radio input.other-val").on("input", (input) => {
171
- const $input = $(input.currentTarget);
172
- const $group = $input.closest(".formbuilder-radio-group");
173
- $group.find("input").each((_key, radio) => {
174
- const name = $(radio).attr("name");
175
- if (name && name.endsWith("[]")) {
176
- $(radio).attr("name", name.slice(0, -2));
177
- }
178
- });
179
- });
180
- return this;
181
- }
182
-
183
72
  // Saves xml to the hidden input
184
73
  storeData() {
185
74
  if (!this.$element) {
@@ -203,7 +92,7 @@ export default class CustomFieldsRenderer { // eslint-disable-line no-unused-var
203
92
  // in case of multilang tabs we only render one form due a limitation in the library for handling several instances
204
93
  this.instance = $element.formRender({
205
94
  i18n: {
206
- locale: this.lang,
95
+ locale: window.DecidimAwesome.currentLocale,
207
96
  location: window.DecidimAwesome.formBuilderLangsLocation
208
97
  },
209
98
  formData: this.spec,
@@ -215,6 +104,5 @@ export default class CustomFieldsRenderer { // eslint-disable-line no-unused-var
215
104
  }
216
105
  }
217
106
  });
218
- this.fixBuggyFields();
219
107
  }
220
108
  }
@@ -15,7 +15,7 @@ document.addEventListener("DOMContentLoaded", () => {
15
15
 
16
16
  const span = document.createElement("span");
17
17
  span.className = "input-character-counter__text";
18
- span.innerHTML = window.DecidimAwesome.texts.dragAndDropImage;
18
+ span.innerHTML = window.DecidimAwesome.i18n.dragAndDropImage;
19
19
  textarea.parentNode.appendChild(span);
20
20
  attach(textarea, {
21
21
  uploadUrl: window.DecidimAwesome.editorUploaderPath,