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.
- checksums.yaml +4 -4
- data/README.md +38 -8
- data/app/assets/config/decidim_admin_decidim_awesome_manifest.css +2 -2
- data/app/assets/config/decidim_admin_decidim_awesome_manifest.js +1 -1
- data/app/assets/config/decidim_decidim_awesome_manifest.css +2 -2
- data/app/assets/config/decidim_decidim_awesome_manifest.js +3 -2
- data/app/assets/config/legacy_decidim_admin_decidim_awesome_manifest.js +2 -0
- data/app/assets/config/legacy_decidim_decidim_awesome_manifest.js +4 -0
- data/app/assets/javascripts/decidim/decidim_awesome/admin/auto_edit.js.es6 +77 -0
- data/app/assets/javascripts/decidim/decidim_awesome/admin/codemirror.js.es6 +14 -0
- data/app/assets/javascripts/decidim/decidim_awesome/admin/form_builder.js.es6 +80 -0
- data/app/assets/javascripts/decidim/decidim_awesome/admin/legacy_form_builder.js.es6 +80 -0
- data/app/assets/javascripts/decidim/decidim_awesome/admin/user_picker.js.es6 +24 -0
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_admin.js +7 -0
- data/app/assets/javascripts/decidim/decidim_awesome/{application.js → awesome_application.js} +1 -2
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/hashtags.js.es6 +48 -0
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/layers.js.es6 +107 -0
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/load_map.js.es6 +15 -0
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/map.js.es6 +170 -178
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/markers.js.es6 +56 -0
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/meetings.js.es6 +7 -6
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/proposals.js.es6 +18 -5
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/utilities.js.es6 +57 -0
- data/app/assets/javascripts/decidim/decidim_awesome/editors/legacy_quill_editor.js.es6 +172 -0
- data/app/assets/javascripts/decidim/decidim_awesome/editors/quill_editor.js.es6 +34 -9
- data/app/assets/javascripts/decidim/decidim_awesome/editors/tabs_focus.js.es6 +24 -0
- data/app/assets/javascripts/decidim/decidim_awesome/forms/custom_fields_builder.js.es6 +211 -0
- data/app/assets/javascripts/decidim/decidim_awesome/forms/rich_text_plugin.js.es6 +106 -0
- data/app/assets/javascripts/decidim/decidim_awesome/legacy_admin.js +7 -0
- data/app/assets/javascripts/decidim/decidim_awesome/legacy_application.js +3 -0
- data/app/assets/javascripts/decidim/decidim_awesome/proposals/custom_fields.js.es6 +21 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/admin/auto_edits.scss +15 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/admin/codemirror.scss +27 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/admin/constraints.scss +12 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/admin/custom_fields.scss +66 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/admin/user_picker.scss +35 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/{admin.scss → awesome_admin.scss} +19 -4
- data/app/assets/stylesheets/decidim/decidim_awesome/awesome_application.scss +22 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/leaflet.scss.erb +9 -0
- data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/map.scss +95 -1
- data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_editor.scss +1 -1
- data/app/assets/stylesheets/decidim/decidim_awesome/editors/quill_editor.scss +16 -1
- data/app/awesome_overrides/forms/decidim/proposals/proposal_wizard_create_step_form_override.rb +28 -0
- data/app/awesome_overrides/presenters/decidim/menu_presenter_override.rb +11 -3
- data/app/cells/decidim/decidim_awesome/content_blocks/map/show.erb +74 -0
- data/app/cells/decidim/decidim_awesome/content_blocks/map_cell.rb +54 -0
- data/app/cells/decidim/decidim_awesome/content_blocks/map_form/show.erb +61 -0
- data/app/cells/decidim/decidim_awesome/content_blocks/map_form_cell.rb +19 -0
- data/app/commands/concerns/decidim/decidim_awesome/admin/needs_constraint_helpers.rb +32 -0
- data/app/commands/decidim/decidim_awesome/admin/create_proposal_custom_field.rb +45 -0
- data/app/commands/decidim/decidim_awesome/admin/create_scoped_admin.rb +38 -0
- data/app/commands/decidim/decidim_awesome/admin/destroy_constraint.rb +4 -0
- data/app/commands/decidim/decidim_awesome/admin/destroy_proposal_custom_field.rb +40 -0
- data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_admin.rb +40 -0
- data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_style.rb +1 -1
- data/app/commands/decidim/decidim_awesome/admin/rename_scope_label.rb +58 -0
- data/app/commands/decidim/decidim_awesome/admin/update_config.rb +5 -1
- data/app/controllers/concerns/decidim/decidim_awesome/admin_not_found_redirect.rb +39 -0
- data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +1 -1
- data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +33 -20
- data/app/controllers/decidim/decidim_awesome/admin/constraints_controller.rb +4 -0
- data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +2 -2
- data/app/controllers/decidim/decidim_awesome/admin/proposal_custom_fields_controller.rb +38 -0
- data/app/controllers/decidim/decidim_awesome/admin/scoped_admins_controller.rb +38 -0
- data/app/controllers/decidim/decidim_awesome/admin/scoped_styles_controller.rb +38 -0
- data/app/controllers/decidim/decidim_awesome/map_component/map_controller.rb +1 -4
- data/app/forms/decidim/decidim_awesome/admin/config_form.rb +50 -0
- data/app/forms/decidim/decidim_awesome/admin/constraint_form.rb +3 -1
- data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +11 -7
- data/app/helpers/decidim/decidim_awesome/amendments_helper_override.rb +48 -0
- data/app/helpers/decidim/decidim_awesome/map_helper.rb +66 -53
- data/app/helpers/decidim/decidim_awesome/proposals/application_helper_override.rb +78 -0
- data/app/middleware/decidim/decidim_awesome/current_config.rb +182 -0
- data/app/models/decidim/decidim_awesome/awesome_config.rb +15 -0
- data/app/models/decidim/decidim_awesome/user_override.rb +25 -0
- data/app/permissions/decidim/decidim_awesome/admin/permissions.rb +2 -0
- data/app/uploaders/decidim/decidim_awesome/image_uploader.rb +0 -5
- data/app/views/decidim/decidim_awesome/admin/checks/index.html.erb +2 -2
- data/app/views/decidim/decidim_awesome/admin/config/_autoedit_box_label.html.erb +7 -0
- data/app/views/decidim/decidim_awesome/admin/config/_constraints.html.erb +2 -2
- data/app/views/decidim/decidim_awesome/admin/config/_form_admins.html.erb +21 -0
- data/app/views/decidim/decidim_awesome/admin/config/_form_editors.html.erb +0 -3
- data/app/views/decidim/decidim_awesome/admin/config/_form_proposal_custom_fields.html.erb +25 -0
- data/app/views/decidim/decidim_awesome/admin/config/_form_proposals.html.erb +0 -2
- data/app/views/decidim/decidim_awesome/admin/config/_form_styles.html.erb +4 -6
- data/app/views/decidim/decidim_awesome/admin/config/show.html.erb +1 -2
- data/app/views/decidim/decidim_awesome/admin/proposals/_editor.html.erb +4 -0
- data/app/views/decidim/decidim_awesome/custom_fields/_form_render.html.erb +6 -0
- data/app/views/decidim/decidim_awesome/map_component/map/show.html.erb +3 -32
- data/app/views/decidim/proposals/admin/proposals/_form.html.erb +101 -0
- data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +83 -0
- data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +1 -0
- data/app/views/layouts/decidim/admin/decidim_awesome.html.erb +25 -11
- data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +8 -1
- data/app/views/layouts/decidim/decidim_awesome/_custom_styles.html.erb +1 -1
- data/app/views/v0.23/decidim/proposals/collaborative_drafts/_show.html.erb +134 -0
- data/app/views/v0.23/layouts/decidim/_head.html.erb +2 -2
- data/app/views/v0.23/layouts/decidim/admin/_header.html.erb +2 -2
- data/app/views/v0.24/decidim/proposals/collaborative_drafts/_show.html.erb +128 -0
- data/app/views/{v0.22 → v0.24}/layouts/decidim/_head.html.erb +4 -2
- data/app/views/{v0.22 → v0.24}/layouts/decidim/admin/_header.html.erb +3 -2
- data/config/locales/ca.yml +75 -3
- data/config/locales/cs.yml +75 -3
- data/config/locales/en.yml +104 -11
- data/config/locales/es.yml +74 -2
- data/config/locales/eu.yml +76 -4
- data/config/locales/fr.yml +214 -142
- data/config/locales/it.yml +284 -0
- data/config/locales/ja.yml +284 -0
- data/config/locales/nl.yml +208 -136
- data/config/locales/sv.yml +109 -37
- data/db/migrate/20210628150825_change_awesome_config_var_type.rb +12 -0
- data/lib/decidim/decidim_awesome/admin_engine.rb +16 -4
- data/lib/decidim/decidim_awesome/awesome_helpers.rb +17 -10
- data/lib/decidim/decidim_awesome/checksums.yml +19 -9
- data/lib/decidim/decidim_awesome/config.rb +54 -9
- data/lib/decidim/decidim_awesome/context_analyzers/request_analyzer.rb +27 -21
- data/lib/decidim/decidim_awesome/custom_fields.rb +94 -0
- data/lib/decidim/decidim_awesome/engine.rb +64 -8
- data/lib/decidim/decidim_awesome/iframe_component/component.rb +1 -1
- data/lib/decidim/decidim_awesome/map_component/component.rb +8 -2
- data/lib/decidim/decidim_awesome/menu_hacker.rb +17 -15
- data/lib/decidim/decidim_awesome/system_checker.rb +1 -1
- data/lib/decidim/decidim_awesome/test/shared_examples/box_label_editor.rb +116 -0
- data/lib/decidim/decidim_awesome/test/shared_examples/current_config_examples.rb +143 -0
- data/lib/decidim/decidim_awesome/test/shared_examples/editor_examples.rb +4 -0
- data/lib/decidim/decidim_awesome/test/shared_examples/scoped_admins_examples.rb +428 -0
- data/lib/decidim/decidim_awesome/version.rb +2 -2
- data/lib/decidim/decidim_awesome.rb +41 -8
- data/vendor/assets/javascripts/codemirror.js +9801 -0
- data/vendor/assets/javascripts/delta.min.js +405 -0
- data/vendor/assets/javascripts/delta.min.js.map +1 -0
- data/vendor/assets/javascripts/europa.min.js +4 -0
- data/vendor/assets/javascripts/form-builder.min.js +19 -0
- data/vendor/assets/javascripts/form-render.min.js +19 -0
- data/vendor/assets/javascripts/inscrybmde.min.js +1 -1
- data/vendor/assets/javascripts/jquery-ui.min.js +13 -0
- data/vendor/assets/javascripts/jquery.truncate.js +105 -0
- data/vendor/assets/javascripts/keymap/sublime.js +720 -0
- data/vendor/assets/javascripts/mode/css/css.js +864 -0
- data/vendor/assets/javascripts/select2.js +6147 -0
- data/vendor/assets/langs/en-US.lang +110 -0
- data/vendor/assets/stylesheets/codemirror.css +350 -0
- data/vendor/assets/stylesheets/inscrybmde.min.scss +194 -0
- data/vendor/assets/stylesheets/jquery-ui.min.css +7 -0
- data/vendor/assets/stylesheets/select2-foundation-theme.css +249 -0
- data/vendor/assets/stylesheets/select2.css +515 -0
- metadata +101 -34
- data/app/assets/images/decidim/decidim_awesome/loading.gif +0 -0
- data/app/assets/javascripts/decidim/decidim_awesome/admin.js +0 -2
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/legacy_map.js.es6 +0 -225
- data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/legacy_proposals.js.es6 +0 -82
- data/app/assets/javascripts/decidim/decidim_awesome/editors/markdown_view.js.es6 +0 -12
- data/app/assets/stylesheets/decidim/decidim_awesome/application.scss +0 -8
- data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_view.scss +0 -27
- data/app/awesome_overrides/presenters/decidim/proposals/proposal_presenter_override.rb +0 -64
- data/lib/decidim/decidim_awesome/content_renderers/markdown_renderer.rb +0 -18
- data/lib/decidim/decidim_awesome/content_renderers.rb +0 -9
- 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 = {
|
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
|
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 =
|
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 =
|
57
|
-
return {}
|
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
|
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
|
11
|
+
return unless map_utility_dynamic
|
10
12
|
|
11
|
-
map =
|
12
|
-
|
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
|
-
|
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-
|
27
|
-
"data-
|
28
|
-
"data-
|
29
|
-
"data-
|
30
|
-
"data-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
77
|
-
|
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
|
|
@@ -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/
|
60
|
-
JavaScript: "//script[contains(@src,'decidim_awesome
|
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" %>
|