decidim-decidim_awesome 0.6.5 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -8
  3. data/app/assets/config/decidim_admin_decidim_awesome_manifest.css +2 -2
  4. data/app/assets/config/decidim_admin_decidim_awesome_manifest.js +1 -1
  5. data/app/assets/config/decidim_decidim_awesome_manifest.css +2 -2
  6. data/app/assets/config/decidim_decidim_awesome_manifest.js +3 -2
  7. data/app/assets/config/legacy_decidim_admin_decidim_awesome_manifest.js +2 -0
  8. data/app/assets/config/legacy_decidim_decidim_awesome_manifest.js +4 -0
  9. data/app/assets/javascripts/decidim/decidim_awesome/admin/auto_edit.js.es6 +77 -0
  10. data/app/assets/javascripts/decidim/decidim_awesome/admin/codemirror.js.es6 +14 -0
  11. data/app/assets/javascripts/decidim/decidim_awesome/admin/form_builder.js.es6 +80 -0
  12. data/app/assets/javascripts/decidim/decidim_awesome/admin/legacy_form_builder.js.es6 +80 -0
  13. data/app/assets/javascripts/decidim/decidim_awesome/admin/user_picker.js.es6 +24 -0
  14. data/app/assets/javascripts/decidim/decidim_awesome/awesome_admin.js +7 -0
  15. data/app/assets/javascripts/decidim/decidim_awesome/{application.js → awesome_application.js} +1 -2
  16. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/hashtags.js.es6 +48 -0
  17. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/layers.js.es6 +107 -0
  18. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/load_map.js.es6 +15 -0
  19. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/map.js.es6 +170 -178
  20. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/markers.js.es6 +56 -0
  21. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/meetings.js.es6 +7 -6
  22. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/proposals.js.es6 +18 -5
  23. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/utilities.js.es6 +57 -0
  24. data/app/assets/javascripts/decidim/decidim_awesome/editors/legacy_quill_editor.js.es6 +172 -0
  25. data/app/assets/javascripts/decidim/decidim_awesome/editors/quill_editor.js.es6 +34 -9
  26. data/app/assets/javascripts/decidim/decidim_awesome/editors/tabs_focus.js.es6 +24 -0
  27. data/app/assets/javascripts/decidim/decidim_awesome/forms/custom_fields_builder.js.es6 +211 -0
  28. data/app/assets/javascripts/decidim/decidim_awesome/forms/rich_text_plugin.js.es6 +106 -0
  29. data/app/assets/javascripts/decidim/decidim_awesome/legacy_admin.js +7 -0
  30. data/app/assets/javascripts/decidim/decidim_awesome/legacy_application.js +3 -0
  31. data/app/assets/javascripts/decidim/decidim_awesome/proposals/custom_fields.js.es6 +21 -0
  32. data/app/assets/stylesheets/decidim/decidim_awesome/admin/auto_edits.scss +15 -0
  33. data/app/assets/stylesheets/decidim/decidim_awesome/admin/codemirror.scss +27 -0
  34. data/app/assets/stylesheets/decidim/decidim_awesome/admin/constraints.scss +12 -0
  35. data/app/assets/stylesheets/decidim/decidim_awesome/admin/custom_fields.scss +66 -0
  36. data/app/assets/stylesheets/decidim/decidim_awesome/admin/user_picker.scss +35 -0
  37. data/app/assets/stylesheets/decidim/decidim_awesome/{admin.scss → awesome_admin.scss} +19 -4
  38. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_application.scss +22 -0
  39. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/leaflet.scss.erb +9 -0
  40. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/map.scss +95 -1
  41. data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_editor.scss +1 -1
  42. data/app/assets/stylesheets/decidim/decidim_awesome/editors/quill_editor.scss +16 -1
  43. data/app/awesome_overrides/forms/decidim/proposals/proposal_wizard_create_step_form_override.rb +28 -0
  44. data/app/awesome_overrides/presenters/decidim/menu_presenter_override.rb +11 -3
  45. data/app/cells/decidim/decidim_awesome/content_blocks/map/show.erb +74 -0
  46. data/app/cells/decidim/decidim_awesome/content_blocks/map_cell.rb +54 -0
  47. data/app/cells/decidim/decidim_awesome/content_blocks/map_form/show.erb +61 -0
  48. data/app/cells/decidim/decidim_awesome/content_blocks/map_form_cell.rb +19 -0
  49. data/app/commands/concerns/decidim/decidim_awesome/admin/needs_constraint_helpers.rb +32 -0
  50. data/app/commands/decidim/decidim_awesome/admin/create_proposal_custom_field.rb +45 -0
  51. data/app/commands/decidim/decidim_awesome/admin/create_scoped_admin.rb +38 -0
  52. data/app/commands/decidim/decidim_awesome/admin/destroy_constraint.rb +4 -0
  53. data/app/commands/decidim/decidim_awesome/admin/destroy_proposal_custom_field.rb +40 -0
  54. data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_admin.rb +40 -0
  55. data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_style.rb +1 -1
  56. data/app/commands/decidim/decidim_awesome/admin/rename_scope_label.rb +58 -0
  57. data/app/commands/decidim/decidim_awesome/admin/update_config.rb +5 -1
  58. data/app/controllers/concerns/decidim/decidim_awesome/admin_not_found_redirect.rb +39 -0
  59. data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +1 -1
  60. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +33 -20
  61. data/app/controllers/decidim/decidim_awesome/admin/constraints_controller.rb +4 -0
  62. data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +2 -2
  63. data/app/controllers/decidim/decidim_awesome/admin/proposal_custom_fields_controller.rb +38 -0
  64. data/app/controllers/decidim/decidim_awesome/admin/scoped_admins_controller.rb +38 -0
  65. data/app/controllers/decidim/decidim_awesome/admin/scoped_styles_controller.rb +38 -0
  66. data/app/controllers/decidim/decidim_awesome/map_component/map_controller.rb +1 -4
  67. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +50 -0
  68. data/app/forms/decidim/decidim_awesome/admin/constraint_form.rb +3 -1
  69. data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +11 -7
  70. data/app/helpers/decidim/decidim_awesome/amendments_helper_override.rb +48 -0
  71. data/app/helpers/decidim/decidim_awesome/map_helper.rb +66 -53
  72. data/app/helpers/decidim/decidim_awesome/proposals/application_helper_override.rb +78 -0
  73. data/app/middleware/decidim/decidim_awesome/current_config.rb +182 -0
  74. data/app/models/decidim/decidim_awesome/awesome_config.rb +15 -0
  75. data/app/models/decidim/decidim_awesome/user_override.rb +25 -0
  76. data/app/permissions/decidim/decidim_awesome/admin/permissions.rb +2 -0
  77. data/app/uploaders/decidim/decidim_awesome/image_uploader.rb +0 -5
  78. data/app/views/decidim/decidim_awesome/admin/checks/index.html.erb +2 -2
  79. data/app/views/decidim/decidim_awesome/admin/config/_autoedit_box_label.html.erb +7 -0
  80. data/app/views/decidim/decidim_awesome/admin/config/_constraints.html.erb +2 -2
  81. data/app/views/decidim/decidim_awesome/admin/config/_form_admins.html.erb +21 -0
  82. data/app/views/decidim/decidim_awesome/admin/config/_form_editors.html.erb +0 -3
  83. data/app/views/decidim/decidim_awesome/admin/config/_form_proposal_custom_fields.html.erb +25 -0
  84. data/app/views/decidim/decidim_awesome/admin/config/_form_proposals.html.erb +0 -2
  85. data/app/views/decidim/decidim_awesome/admin/config/_form_styles.html.erb +4 -6
  86. data/app/views/decidim/decidim_awesome/admin/config/show.html.erb +1 -2
  87. data/app/views/decidim/decidim_awesome/admin/proposals/_editor.html.erb +4 -0
  88. data/app/views/decidim/decidim_awesome/custom_fields/_form_render.html.erb +6 -0
  89. data/app/views/decidim/decidim_awesome/map_component/map/show.html.erb +3 -32
  90. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +101 -0
  91. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +83 -0
  92. data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +1 -0
  93. data/app/views/layouts/decidim/admin/decidim_awesome.html.erb +25 -11
  94. data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +8 -1
  95. data/app/views/layouts/decidim/decidim_awesome/_custom_styles.html.erb +1 -1
  96. data/app/views/v0.23/decidim/proposals/collaborative_drafts/_show.html.erb +134 -0
  97. data/app/views/v0.23/layouts/decidim/_head.html.erb +2 -2
  98. data/app/views/v0.23/layouts/decidim/admin/_header.html.erb +2 -2
  99. data/app/views/v0.24/decidim/proposals/collaborative_drafts/_show.html.erb +128 -0
  100. data/app/views/{v0.22 → v0.24}/layouts/decidim/_head.html.erb +4 -2
  101. data/app/views/{v0.22 → v0.24}/layouts/decidim/admin/_header.html.erb +3 -2
  102. data/config/locales/ca.yml +75 -3
  103. data/config/locales/cs.yml +75 -3
  104. data/config/locales/en.yml +104 -11
  105. data/config/locales/es.yml +74 -2
  106. data/config/locales/eu.yml +76 -4
  107. data/config/locales/fr.yml +214 -142
  108. data/config/locales/it.yml +284 -0
  109. data/config/locales/ja.yml +284 -0
  110. data/config/locales/nl.yml +208 -136
  111. data/config/locales/sv.yml +109 -37
  112. data/db/migrate/20210628150825_change_awesome_config_var_type.rb +12 -0
  113. data/lib/decidim/decidim_awesome/admin_engine.rb +16 -4
  114. data/lib/decidim/decidim_awesome/awesome_helpers.rb +17 -10
  115. data/lib/decidim/decidim_awesome/checksums.yml +19 -9
  116. data/lib/decidim/decidim_awesome/config.rb +54 -9
  117. data/lib/decidim/decidim_awesome/context_analyzers/request_analyzer.rb +27 -21
  118. data/lib/decidim/decidim_awesome/custom_fields.rb +94 -0
  119. data/lib/decidim/decidim_awesome/engine.rb +64 -8
  120. data/lib/decidim/decidim_awesome/iframe_component/component.rb +1 -1
  121. data/lib/decidim/decidim_awesome/map_component/component.rb +8 -2
  122. data/lib/decidim/decidim_awesome/menu_hacker.rb +17 -15
  123. data/lib/decidim/decidim_awesome/system_checker.rb +1 -1
  124. data/lib/decidim/decidim_awesome/test/shared_examples/box_label_editor.rb +116 -0
  125. data/lib/decidim/decidim_awesome/test/shared_examples/current_config_examples.rb +143 -0
  126. data/lib/decidim/decidim_awesome/test/shared_examples/editor_examples.rb +4 -0
  127. data/lib/decidim/decidim_awesome/test/shared_examples/scoped_admins_examples.rb +428 -0
  128. data/lib/decidim/decidim_awesome/version.rb +2 -2
  129. data/lib/decidim/decidim_awesome.rb +41 -8
  130. data/vendor/assets/javascripts/codemirror.js +9801 -0
  131. data/vendor/assets/javascripts/delta.min.js +405 -0
  132. data/vendor/assets/javascripts/delta.min.js.map +1 -0
  133. data/vendor/assets/javascripts/europa.min.js +4 -0
  134. data/vendor/assets/javascripts/form-builder.min.js +19 -0
  135. data/vendor/assets/javascripts/form-render.min.js +19 -0
  136. data/vendor/assets/javascripts/inscrybmde.min.js +1 -1
  137. data/vendor/assets/javascripts/jquery-ui.min.js +13 -0
  138. data/vendor/assets/javascripts/jquery.truncate.js +105 -0
  139. data/vendor/assets/javascripts/keymap/sublime.js +720 -0
  140. data/vendor/assets/javascripts/mode/css/css.js +864 -0
  141. data/vendor/assets/javascripts/select2.js +6147 -0
  142. data/vendor/assets/langs/en-US.lang +110 -0
  143. data/vendor/assets/stylesheets/codemirror.css +350 -0
  144. data/vendor/assets/stylesheets/inscrybmde.min.scss +194 -0
  145. data/vendor/assets/stylesheets/jquery-ui.min.css +7 -0
  146. data/vendor/assets/stylesheets/select2-foundation-theme.css +249 -0
  147. data/vendor/assets/stylesheets/select2.css +515 -0
  148. metadata +101 -34
  149. data/app/assets/images/decidim/decidim_awesome/loading.gif +0 -0
  150. data/app/assets/javascripts/decidim/decidim_awesome/admin.js +0 -2
  151. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/legacy_map.js.es6 +0 -225
  152. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/legacy_proposals.js.es6 +0 -82
  153. data/app/assets/javascripts/decidim/decidim_awesome/editors/markdown_view.js.es6 +0 -12
  154. data/app/assets/stylesheets/decidim/decidim_awesome/application.scss +0 -8
  155. data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_view.scss +0 -27
  156. data/app/awesome_overrides/presenters/decidim/proposals/proposal_presenter_override.rb +0 -64
  157. data/lib/decidim/decidim_awesome/content_renderers/markdown_renderer.rb +0 -18
  158. data/lib/decidim/decidim_awesome/content_renderers.rb +0 -9
  159. data/vendor/assets/stylesheets/inscrybmde.min.css +0 -8
@@ -4,6 +4,8 @@ module Decidim
4
4
  module DecidimAwesome
5
5
  module Admin
6
6
  module ConfigConstraintsHelpers
7
+ OTHER_MANIFESTS = [:none, :system, :process_groups].freeze
8
+
7
9
  include Decidim::TranslatableAttributes
8
10
 
9
11
  def check(status)
@@ -28,7 +30,7 @@ module Decidim
28
30
  end
29
31
 
30
32
  def participatory_space_manifests
31
- manifests = { system: I18n.t("decidim.decidim_awesome.admin.config.system") }
33
+ manifests = OTHER_MANIFESTS.map { |m| [m, I18n.t("decidim.decidim_awesome.admin.config.#{m}")] }.to_h
32
34
  Decidim.participatory_space_manifests.pluck(:name).each do |name|
33
35
  manifests[name.to_sym] = I18n.t("decidim.admin.menu.#{name}")
34
36
  end
@@ -36,7 +38,7 @@ module Decidim
36
38
  end
37
39
 
38
40
  def component_manifests(space = nil)
39
- return {} if space == "system"
41
+ return {} if OTHER_MANIFESTS.include?(space)
40
42
 
41
43
  Decidim.component_manifests.pluck(:name).map do |name|
42
44
  [name.to_sym, I18n.t("decidim.components.#{name}.name")]
@@ -44,17 +46,17 @@ module Decidim
44
46
  end
45
47
 
46
48
  def participatory_spaces_list(manifest)
47
- space = participatory_space_for_manifest(manifest)
49
+ space = model_for_manifest(manifest)
48
50
  return {} if space.blank?
49
51
 
50
52
  space.where(organization: current_organization).map do |item|
51
- [item.slug, translated_attribute(item.title)]
53
+ [item.try(:slug) || item.id.to_s, translated_attribute(item.title)]
52
54
  end.to_h
53
55
  end
54
56
 
55
57
  def components_list(manifest, slug)
56
- space = participatory_space_for_manifest(manifest)
57
- return {} if space.blank?
58
+ space = model_for_manifest(manifest)
59
+ return {} unless space&.column_names&.include? "slug"
58
60
 
59
61
  components = Component.where(participatory_space: space.find_by(slug: slug))
60
62
  components.map do |item|
@@ -84,9 +86,11 @@ module Decidim
84
86
 
85
87
  private
86
88
 
87
- def participatory_space_for_manifest(manifest)
89
+ def model_for_manifest(manifest)
88
90
  return nil if manifest.blank?
89
91
 
92
+ return Decidim::ParticipatoryProcessGroup if manifest == "process_groups"
93
+
90
94
  space = Decidim.find_participatory_space_manifest(manifest)
91
95
  return nil unless space
92
96
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module AmendmentsHelperOverride
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # original method
10
+ alias_method :decidim_amendments_form_field_for, :amendments_form_field_for
11
+
12
+ # override with custom fields if scope applies
13
+ def amendments_form_field_for(attribute, form, original_resource)
14
+ custom_fields = awesome_custom_fields(attribute, form)
15
+ return decidim_amendments_form_field_for(attribute, form, original_resource) if custom_fields.blank?
16
+
17
+ render_amendment_custom_fields_override(custom_fields, attribute, form, original_resource)
18
+ end
19
+
20
+ private
21
+
22
+ def render_amendment_custom_fields_override(fields, attribute, form, original_resource)
23
+ custom_fields = Decidim::DecidimAwesome::CustomFields.new(fields)
24
+ custom_fields.translate!
25
+ body = amendments_form_fields_value(original_resource, attribute)
26
+ custom_fields.apply_xml(body) if body.present?
27
+ # TODO: find a way to add errors as form is not the parent form
28
+ # form.object.errors.add(attribute, custom_fields.errors) if custom_fields.errors
29
+ render partial: "decidim/decidim_awesome/custom_fields/form_render", locals: { spec: custom_fields.to_json, form: form, name: attribute }
30
+ end
31
+
32
+ # Amendments don't use a URL specifying participatory space and component
33
+ # context for awesome config constraints must be obtained from the resource
34
+ def awesome_custom_fields(attribute, _form)
35
+ return unless attribute == :body
36
+
37
+ component = amendable.try(:component)
38
+ return unless component
39
+ return if component.settings.participatory_texts_enabled?
40
+
41
+ awesome_config = Decidim::DecidimAwesome::Config.new(component.organization)
42
+ awesome_config.context_from_component(component)
43
+ awesome_config.collect_sub_configs_values("proposal_custom_field")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -5,13 +5,19 @@ module Decidim
5
5
  module MapHelper
6
6
  include Decidim::MapHelper
7
7
 
8
+ # rubocop:disable Metrics/CyclomaticComplexity
9
+ # rubocop:disable Metrics/PerceivedComplexity:
8
10
  def awesome_map_for(components, &block)
9
- return legacy_map_for(components, &block) unless defined?(Decidim::Map)
11
+ return unless map_utility_dynamic
10
12
 
11
- map = dynamic_map_for({}, {}, &block)
12
- return unless map
13
+ map = awesome_builder.map_element({ class: "google-map" }, &block)
14
+ help = content_tag(:div, class: "map__help") do
15
+ sr_content = content_tag(:p, t("screen_reader_explanation", scope: "decidim.map.dynamic"), class: "show-for-sr")
16
+
17
+ sr_content
18
+ end
13
19
 
14
- map_html_options = {
20
+ html_options = {
15
21
  "class" => "awesome-map",
16
22
  "id" => "awesome-map",
17
23
  "data-components" => components.map do |component|
@@ -23,58 +29,40 @@ module Decidim
23
29
  amendments: component.manifest.name == :proposals ? Decidim::Proposals::Proposal.where(component: component).only_emendations.count : 0
24
30
  }
25
31
  end.to_json,
26
- "data-collapsed" => current_component.settings.collapse,
27
- "data-show-not-answered" => current_component.current_settings.show_not_answered,
28
- "data-show-accepted" => current_component.current_settings.show_accepted,
29
- "data-show-withdrawn" => current_component.current_settings.show_withdrawn,
30
- "data-show-evaluating" => current_component.current_settings.show_evaluating
31
- # "data-show-rejected" => current_component.current_settings.show_rejected
32
- }
33
- content_tag(:div, map, map_html_options)
34
- end
35
-
36
- # TODO: remove when 0.22 support is diched
37
- def legacy_map_for(components)
38
- return if Decidim.geocoder.blank?
39
-
40
- map_html_options = {
41
- class: "google-map",
42
- id: "map",
43
- "data-components" => components.map do |component|
44
- {
45
- id: component.id,
46
- type: component.manifest.name,
47
- name: translated_attribute(component.name),
48
- url: Decidim::EngineRouter.main_proxy(component).root_path,
49
- amendments: component.manifest.name == :proposals ? Decidim::Proposals::Proposal.where(component: component).only_emendations.count : 0
50
- }
51
- end.to_json,
52
- "data-collapsed" => current_component.settings.collapse,
53
- "data-show-not-answered" => current_component.current_settings.show_not_answered,
54
- "data-show-accepted" => current_component.current_settings.show_accepted,
55
- "data-show-withdrawn" => current_component.current_settings.show_withdrawn,
56
- "data-show-evaluating" => current_component.current_settings.show_evaluating,
57
- # "data-show-rejected" => current_component.current_settings.show_rejected,
58
- "data-markers-data" => [].to_json
32
+ "data-hide-controls" => settings_source.try(:hide_controls),
33
+ "data-collapsed" => global_settings.collapse,
34
+ "data-truncate" => global_settings.truncate || 255,
35
+ "data-map-center" => global_settings.map_center,
36
+ "data-map-zoom" => global_settings.map_zoom || 8,
37
+ "data-menu-amendments" => global_settings.menu_amendments,
38
+ "data-menu-meetings" => global_settings.menu_meetings,
39
+ "data-menu-hashtags" => global_settings.menu_hashtags,
40
+ "data-show-not-answered" => step_settings&.show_not_answered,
41
+ "data-show-accepted" => step_settings&.show_accepted,
42
+ "data-show-withdrawn" => step_settings&.show_withdrawn,
43
+ "data-show-evaluating" => step_settings&.show_evaluating,
44
+ "data-show-rejected" => step_settings&.show_rejected
59
45
  }
60
46
 
61
- if Decidim.geocoder[:here_api_key]
62
- map_html_options["data-here-api-key"] = Decidim.geocoder[:here_api_key]
63
- else
64
- # Compatibility mode for old api_id/app_code configurations
65
- map_html_options["data-here-app-id"] = Decidim.geocoder[:here_app_id]
66
- map_html_options["data-here-app-code"] = Decidim.geocoder[:here_app_code]
47
+ content_tag(:div, html_options) do
48
+ content_tag :div, class: "row column" do
49
+ help + map
50
+ end
67
51
  end
52
+ end
53
+ # rubocop:enable Metrics/CyclomaticComplexity
54
+ # rubocop:enable Metrics/PerceivedComplexity:
68
55
 
69
- content = capture { yield }.html_safe
70
- help = content_tag(:div, class: "map__help") do
71
- content_tag(:p, I18n.t("screen_reader_explanation", scope: "decidim.map.dynamic"), class: "show-for-sr")
72
- end
73
- content_tag :div, class: "awesome-map" do
74
- map = content_tag(:div, "", map_html_options)
56
+ def step_settings
57
+ settings_source.try(:current_settings)
58
+ end
75
59
 
76
- help + map + content
77
- end
60
+ def global_settings
61
+ settings_source.try(:settings)
62
+ end
63
+
64
+ def settings_source
65
+ try(:current_component) || self
78
66
  end
79
67
 
80
68
  # rubocop:disable Rails/HelperInstanceVariable
@@ -96,6 +84,30 @@ module Decidim
96
84
 
97
85
  private
98
86
 
87
+ def awesome_builder
88
+ options = {
89
+ popup_template_id: "marker-popup",
90
+ markers: []
91
+ }
92
+ builder = map_utility_dynamic.create_builder(self, options)
93
+
94
+ unless snippets.any?(:map)
95
+ snippets.add(:map, builder.stylesheet_snippets)
96
+ snippets.add(:map, builder.javascript_snippets)
97
+ snippets.add(:head, snippets.for(:map))
98
+ end
99
+
100
+ unless snippets.any?(:awesome_map)
101
+ snippets.add(:awesome_map, stylesheet_link_tag("decidim/decidim_awesome/awesome_map/map"))
102
+ snippets.add(:awesome_map, javascript_include_tag("decidim/decidim_awesome/awesome_map/map"))
103
+ snippets.add(:awesome_map, javascript_include_tag("decidim/decidim_awesome/awesome_map/load_map"))
104
+ snippets.add(:head, snippets.for(:awesome_map))
105
+ end
106
+
107
+ builder
108
+ end
109
+
110
+ # rubocop:disable Style/FormatStringToken
99
111
  def append_category(category)
100
112
  @h += @golden_ratio_conjugate
101
113
  @h %= 1
@@ -108,11 +120,12 @@ module Decidim
108
120
  color: format("#%02x%02x%02x", r, g, b)
109
121
  )
110
122
  end
123
+ # rubocop:enable Style/FormatStringToken
111
124
  # rubocop:enable Rails/HelperInstanceVariable
112
125
 
113
- # rubocop:disable Naming/UncommunicativeMethodParamName
114
126
  # HSV values in [0..1[
115
127
  # returns [r, g, b] values from 0 to 255
128
+ # rubocop:disable Naming/MethodParameterName
116
129
  def hsv_to_rgb(h, s, v)
117
130
  h_i = (h * 6).to_i
118
131
  f = h * 6 - h_i
@@ -151,7 +164,7 @@ module Decidim
151
164
  end
152
165
  [(r * 256).to_i, (g * 256).to_i, (b * 256).to_i]
153
166
  end
154
- # rubocop:enable Naming/UncommunicativeMethodParamName
155
167
  end
168
+ # rubocop:enable Naming/MethodParameterName
156
169
  end
157
170
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Proposals
6
+ module ApplicationHelperOverride
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ alias_method :decidim_text_editor_for_proposal_body, :text_editor_for_proposal_body
11
+ alias_method :decidim_safe_content?, :safe_content?
12
+
13
+ # replace safe content to consider all custom fields save (then embeded html will be rendered)
14
+ def safe_content?
15
+ awesome_proposal_custom_fields.present? || decidim_safe_content?
16
+ end
17
+
18
+ # replace normal method to draw the editor
19
+ def text_editor_for_proposal_body(form)
20
+ custom_fields = awesome_proposal_custom_fields
21
+
22
+ return decidim_text_editor_for_proposal_body(form) if custom_fields.blank?
23
+
24
+ render_proposal_custom_fields_override(custom_fields, form, :body)
25
+ end
26
+
27
+ # replace admin method to draw the editor (multi lang)
28
+ def admin_editor_for_proposal_body(form)
29
+ custom_fields = awesome_proposal_custom_fields
30
+
31
+ return form.translated(:editor, :body, hashtaggable: true) if custom_fields.blank?
32
+
33
+ locales = form.send(:locales)
34
+
35
+ return render_proposal_custom_fields_override(custom_fields, form, "body_#{locales.first}", locales.first) if locales.length == 1
36
+
37
+ tabs_id = form.send(:sanitize_tabs_selector, form.options[:tabs_id] || "#{form.object_name}-body-tabs")
38
+
39
+ label_tabs = form.content_tag(:div, class: "label--tabs") do
40
+ field_label = form.send(:label_i18n, "body", form.label_for("proposal_custom_fields"))
41
+
42
+ language_selector = "".html_safe
43
+ language_selector = form.create_language_selector(locales, tabs_id, "body") if form.options[:label] != false
44
+
45
+ safe_join [field_label, language_selector]
46
+ end
47
+
48
+ tabs_content = form.content_tag(:div, class: "tabs-content", data: { tabs_content: tabs_id }) do
49
+ locales.each_with_index.inject("".html_safe) do |string, (locale, index)|
50
+ tab_content_id = "#{tabs_id}-body-panel-#{index}"
51
+ string + content_tag(:div, class: form.send(:tab_element_class_for, "panel", index), id: tab_content_id) do
52
+ render_proposal_custom_fields_override(custom_fields, form, "body_#{locale}", locale)
53
+ end
54
+ end
55
+ end
56
+
57
+ safe_join [label_tabs, tabs_content]
58
+ end
59
+
60
+ def render_proposal_custom_fields_override(fields, form, name, locale = nil)
61
+ custom_fields = Decidim::DecidimAwesome::CustomFields.new(fields)
62
+ custom_fields.translate!
63
+
64
+ body = if form_presenter.proposal.body.is_a?(Hash) && locale
65
+ form_presenter.body(extras: false, all_locales: true)[locale]
66
+ else
67
+ form_presenter.body(extras: false)
68
+ end
69
+
70
+ custom_fields.apply_xml(body) if body.present?
71
+ form.object.errors.add(name, custom_fields.errors) if custom_fields.errors
72
+ render partial: "decidim/decidim_awesome/custom_fields/form_render", locals: { spec: custom_fields.to_json, form: form, name: name }
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ # A middleware that stores the current awesome context by parsing the request
6
+ class CurrentConfig
7
+ # Initializes the Rack Middleware.
8
+ #
9
+ # app - The Rack application
10
+ def initialize(app)
11
+ @app = app
12
+ end
13
+
14
+ # Main entry point for a Rack Middleware.
15
+ #
16
+ # env - A Hash.
17
+ def call(env)
18
+ @request = Rack::Request.new(env)
19
+ if @request.env["decidim.current_organization"] && processable_path?
20
+ @config = awesome_config_instance
21
+ env["decidim_awesome.current_config"] = @config
22
+ tamper_user_model
23
+ add_flash_message_from_request(env)
24
+
25
+ # puts "requested path: #{env["PATH_INFO"]}"
26
+ # puts "current_organization: #{@request.env["decidim.current_organization"]&.id}"
27
+ # puts "potential_admins: #{Decidim::User.awesome_potential_admins}"
28
+ # puts "scoped admins: #{Decidim::User.awesome_admins_for_current_scope}"
29
+ else
30
+ reset_user_model
31
+ end
32
+
33
+ @app.call(env)
34
+ end
35
+
36
+ private
37
+
38
+ # a workaround to set a flash message if comming from the error controller (route not found)
39
+ def add_flash_message_from_request(env)
40
+ return unless scoped_admins_active?
41
+ return unless @request.params.has_key? "unauthorized"
42
+
43
+ env["rack.session"]["flash"] = ActionDispatch::Flash::FlashHash.new(alert: I18n.t("decidim.core.actions.unauthorized")).to_session_value
44
+ end
45
+
46
+ def awesome_config_instance
47
+ @awesome_config_instance = Config.new @request.env["decidim.current_organization"]
48
+ @awesome_config_instance.context_from_request @request
49
+ @awesome_config_instance
50
+ end
51
+
52
+ def reset_user_model
53
+ return unless scoped_admins_active?
54
+
55
+ Decidim::User.awesome_potential_admins = []
56
+ Decidim::User.awesome_admins_for_current_scope = []
57
+ end
58
+
59
+ def tamper_user_model
60
+ return unless scoped_admins_active?
61
+
62
+ Decidim::User.awesome_potential_admins = potential_admins
63
+
64
+ Decidim::User.awesome_admins_for_current_scope = if safe_get_route? || safe_post_route?
65
+ Decidim::User.awesome_potential_admins
66
+ else
67
+ valid_admins
68
+ end
69
+ end
70
+
71
+ def potential_admins
72
+ @config.collect_sub_configs_values("scoped_admin") do |subconfig|
73
+ subconfig&.constraints&.detect { |c| c.settings["participatory_space_manifest"] == "none" } ? false : true
74
+ end.flatten.uniq.map(&:to_i)
75
+ end
76
+
77
+ def valid_admins
78
+ @config.collect_sub_configs_values("scoped_admin") do |subconfig|
79
+ # allow index controllers if scoped to a subspace/component
80
+ constraints = subconfig&.constraints || []
81
+ additional_constraints = additional_get_constraints(constraints) + additional_post_constraints(constraints)
82
+ # inject additional constraints here for further use
83
+ @config.inject_sub_config_constraints("scoped_admin", subconfig.var[13..], additional_constraints) if subconfig
84
+ @config.valid_in_context?(constraints + additional_constraints)
85
+ end.flatten.uniq.map(&:to_i)
86
+ end
87
+
88
+ # avoid unnecessary processing for non-user routes
89
+ def processable_path?
90
+ return true if safe_get_route?
91
+
92
+ spaces = ContextAnalyzers::RequestAnalyzer.participatory_spaces_routes.keys.join("|^(/admin){0,1}/")
93
+ case @request.path
94
+ when %r{"|^(/admin){0,1}/#{spaces}}
95
+ true
96
+ when %r{^/admin/}
97
+ true
98
+ end
99
+ end
100
+
101
+ def safe_get_route?
102
+ return unless @request.get?
103
+
104
+ case @request.path
105
+ when "/"
106
+ true
107
+ when "/admin/"
108
+ true
109
+ when %r{^/admin/admin_terms}
110
+ true
111
+ when %r{^/profiles/|^/notifications/|^/conversations/|^/pages/}
112
+ true
113
+ end
114
+ end
115
+
116
+ def safe_post_route?
117
+ return unless @request.post? || @request.put? || @request.patch?
118
+
119
+ case @request.path
120
+ when %r{^/admin/admin_terms}
121
+ true
122
+ end
123
+ end
124
+
125
+ # to access certain deeper routes it requires first to click on a parent route, even without Post permissions in there
126
+ # this adds this additional routes to these cases
127
+ # For instance:
128
+ # accessing /admin/participatory_processes/som-procress requires access first to /admin/participatory_processes
129
+ def additional_get_constraints(constraints)
130
+ return [] unless @request.get?
131
+
132
+ additions = []
133
+ constraints.each do |constraint|
134
+ next if constraint.settings["participatory_space_manifest"].blank?
135
+
136
+ # processes groups must give access to processes generic url
137
+ if constraint.settings["participatory_space_manifest"] == "process_groups"
138
+ additions << OpenStruct.new(settings: { "participatory_space_manifest" => "participatory_processes", "match" => "exclusive" })
139
+ end
140
+
141
+ # adds a exclusive constraint to the parent participatory space (so index page can be accessed)
142
+ next unless constraint.settings.size > 1
143
+
144
+ additions << OpenStruct.new(settings: {
145
+ "participatory_space_manifest" => constraint.settings["participatory_space_manifest"],
146
+ "match" => "exclusive"
147
+ })
148
+ end
149
+
150
+ additions
151
+ end
152
+
153
+ # adds access to REST routes with id instead of the slug ot allow editing
154
+ # rubocop:disable Metrics/CyclomaticComplexity
155
+ # rubocop:disable Metrics/PerceivedComplexity
156
+ def additional_post_constraints(constraints)
157
+ return [] unless @request.post? || @request.patch?
158
+
159
+ constraints.filter_map do |constraint|
160
+ settings = constraint.settings.dup
161
+ next unless settings["participatory_space_manifest"].present? && settings["participatory_space_slug"].present?
162
+
163
+ # replicate the constraint with the id of the participatory space
164
+ manifest = Decidim.participatory_space_manifests.find { |s| s.name.to_s == settings["participatory_space_manifest"] }
165
+ next unless manifest
166
+
167
+ model = manifest.model_class_name.try(:constantize)
168
+ next unless model
169
+
170
+ settings["participatory_space_slug"] = model.find_by(slug: settings["participatory_space_slug"])&.id
171
+ OpenStruct.new(settings: settings) if settings["participatory_space_slug"]
172
+ end
173
+ end
174
+ # rubocop:enable Metrics/CyclomaticComplexity
175
+ # rubocop:enable Metrics/PerceivedComplexity
176
+
177
+ def scoped_admins_active?
178
+ Decidim::User.respond_to?(:awesome_admins_for_current_scope) && Decidim::User.respond_to?(:awesome_potential_admins)
179
+ end
180
+ end
181
+ end
182
+ end
@@ -15,9 +15,24 @@ module Decidim
15
15
  validates :organization, presence: true
16
16
  validates :var, uniqueness: { scope: :decidim_organization_id }
17
17
 
18
+ def additional_constraints
19
+ @additional_constraints ||= []
20
+ end
21
+
22
+ def add_constraints(constraints)
23
+ return if constraints.blank?
24
+
25
+ additional_constraints.concat(constraints.respond_to?(:each) ? constraints : [constraints])
26
+ end
27
+
18
28
  def self.for_organization(organization)
19
29
  where(organization: organization)
20
30
  end
31
+
32
+ # use this instead of "constraints" to evaluate dynamically added constants
33
+ def all_constraints
34
+ constraints + additional_constraints
35
+ end
21
36
  end
22
37
  end
23
38
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module UserOverride
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class << self
10
+ attr_accessor :awesome_admins_for_current_scope, :awesome_potential_admins
11
+ end
12
+
13
+ def admin
14
+ return self["admin"] if self["admin"]
15
+
16
+ Decidim::User.awesome_admins_for_current_scope&.include?(id)
17
+ end
18
+
19
+ def admin?
20
+ admin.present?
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -8,6 +8,8 @@ module Decidim
8
8
 
9
9
  def permissions
10
10
  return permission_action if permission_action.scope != :admin
11
+ return permission_action unless user
12
+ return permission_action if user.read_attribute("admin").blank?
11
13
 
12
14
  toggle_allow(config_enabled?(permission_action.subject)) if permission_action.action == :edit_config
13
15
 
@@ -10,11 +10,6 @@ module Decidim
10
10
  process resize_to_fit: [nil, 237]
11
11
  end
12
12
 
13
- # TODO: remove when diching 0.22 support
14
- def extension_white_list
15
- %w(jpg jpeg png)
16
- end
17
-
18
13
  def extension_whitelist
19
14
  %w(jpg jpeg png)
20
15
  end
@@ -56,8 +56,8 @@
56
56
  <strong><%= t ".admin_head_tags" %></strong>
57
57
  <ul class="vertical menu">
58
58
  <% {
59
- CSS: "//link[@rel='stylesheet'][contains(@href,'decidim_awesome/admin')]",
60
- JavaScript: "//script[contains(@src,'decidim_awesome/admin')]"
59
+ CSS: "//link[@rel='stylesheet'][contains(@href,'decidim_awesome/awesome_admin')]",
60
+ JavaScript: "//script[contains(@src,'decidim_awesome')]"
61
61
  }.each do |part, xpath| %>
62
62
  <li>
63
63
  <%= part %>
@@ -0,0 +1,7 @@
1
+ <%= label_tag var do %>
2
+ <%= t("config.#{var}",
3
+ scope: "activemodel.attributes",
4
+ id: "<span class='awesome-auto-edit' data-var='#{var}' data-scope='#{scope}' data-key='#{key}'>#{key}</span>").html_safe %>
5
+ <%= icon_link_to "pencil", "#", t("edit_label", scope: "decidim.decidim_awesome.admin.config.form"), class: "action-icon--edit awesome-auto-edit", data: { "scope" => "#{scope}" } %>
6
+ <%= link_to t("remove", scope: "decidim.decidim_awesome.admin.config.form_#{var}"), delete_path, method: :delete, class: "float-right delete-box", data: { confirm: t("sure_to_remove", scope: "decidim.decidim_awesome.admin.config.form_#{var}") } %>
7
+ <% end %>
@@ -11,11 +11,11 @@
11
11
  <span class="label warning"><%= t ".always" %></span>
12
12
  <% end %>
13
13
 
14
- <ul class="constraints-list">
14
+ <ul class="constraints-list<%= " inactive" if constraints&.detect{|c| c.settings["participatory_space_manifest"]=="none" } %>">
15
15
  <% constraints&.each do |constraint| %>
16
16
  <li>
17
17
  <% constraint.settings.reverse_each do |k, val| %>
18
- <span class="label <%= k %>"><%= translate_constraint_value constraint, k %></span>
18
+ <span class="label <%= k %> constraint-<%= val %>"><%= translate_constraint_value constraint, k %></span>
19
19
  <% end %>
20
20
  <a href="<%= constraint_path(id: constraint.id, key: key) %>" class="edit-condition"><%= t ".edit" %></a>
21
21
  <%= link_to t(".delete"), constraint_path(id: constraint.id), remote: true, method: :delete %>
@@ -0,0 +1,21 @@
1
+ <div class="row column decidim_awesome-form">
2
+ <% if config_enabled? :scoped_admins %>
3
+ <p class="help-text"><%= t("help.scoped_admins", scope: "decidim.decidim_awesome.admin.config.form") %></p>
4
+
5
+ <% form.object.scoped_admins&.each do |key, value| %>
6
+ <div class="scoped_admins_container" data-key="<%= key %>">
7
+ <%= render(partial: "decidim/decidim_awesome/admin/config/autoedit_box_label", locals: { var: "scoped_admins", key: key, scope: "scoped_admin_#{key}", delete_path: decidim_admin_decidim_awesome.scoped_admin_path(key: key) }) %>
8
+ <p class="form-error is-visible" id="scoped-admin-error-<%= $key %>"><%= errors[key.to_sym].join("<br>") if errors %></p>
9
+
10
+ <%= select_tag "config[scoped_admins][#{key}]", options_from_collection_for_select(users_for(value), :id, :text, proc { true }), { include_blank: false , class: "multiusers-select", multiple: true, data: { url: decidim_admin_decidim_awesome.users_path } } %>
11
+
12
+ <%= render(partial: "decidim/decidim_awesome/admin/config/constraints", locals: { key: "scoped_admin_#{key}", constraints: constraints_for("scoped_admin_#{key}") }) %>
13
+ </div>
14
+ <% end %>
15
+
16
+ <%= link_to t("new", scope: "decidim.decidim_awesome.admin.config.form_scoped_admins"), decidim_admin_decidim_awesome.scoped_admins_path, method: :post %>
17
+
18
+ <% end %>
19
+ </div>
20
+
21
+ <%= javascript_include_tag "decidim/decidim_awesome/admin/form_exit_warn" %>