decidim-decidim_awesome 0.11.1 → 0.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +54 -2
  4. data/app/cells/concerns/decidim/decidim_awesome/proposal_l_cell_override.rb +6 -24
  5. data/app/cells/decidim/decidim_awesome/content_blocks/map_cell.rb +0 -4
  6. data/app/cells/decidim/decidim_awesome/voting/proposal_metadata_cell.rb +18 -3
  7. data/app/commands/concerns/decidim/decidim_awesome/proposals/create_proposal_override.rb +2 -2
  8. data/app/commands/concerns/decidim/decidim_awesome/proposals/update_proposal_override.rb +2 -2
  9. data/app/commands/concerns/decidim/decidim_awesome/system/register_organization_override.rb +29 -0
  10. data/app/commands/concerns/decidim/decidim_awesome/system/update_organization_override.rb +35 -0
  11. data/app/commands/concerns/decidim/decidim_awesome/update_account_override.rb +30 -0
  12. data/app/commands/decidim/decidim_awesome/admin/create_scoped_style.rb +3 -2
  13. data/app/commands/decidim/decidim_awesome/admin/destroy_scoped_style.rb +6 -4
  14. data/app/controllers/concerns/decidim/decidim_awesome/admin_accountability/admin/filterable_helper.rb +3 -2
  15. data/app/controllers/concerns/decidim/decidim_awesome/check_login_authorizations.rb +60 -0
  16. data/app/controllers/concerns/decidim/decidim_awesome/needs_awesome_config.rb +0 -2
  17. data/app/controllers/concerns/decidim/decidim_awesome/proposals/memoize_extra_fields.rb +23 -0
  18. data/app/controllers/concerns/decidim/decidim_awesome/proposals/orderable_override.rb +9 -22
  19. data/app/controllers/concerns/decidim/decidim_awesome/use_user_time_zone.rb +32 -0
  20. data/app/controllers/decidim/decidim_awesome/admin/admin_accountability_controller.rb +7 -7
  21. data/app/controllers/decidim/decidim_awesome/admin/admin_authorizations_controller.rb +122 -0
  22. data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +1 -1
  23. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +7 -1
  24. data/app/controllers/decidim/decidim_awesome/admin/constraints_controller.rb +5 -1
  25. data/app/controllers/decidim/decidim_awesome/admin/maintenance_controller.rb +1 -1
  26. data/app/controllers/decidim/decidim_awesome/admin/scoped_styles_controller.rb +12 -4
  27. data/app/controllers/decidim/decidim_awesome/required_authorizations_controller.rb +58 -0
  28. data/app/forms/concerns/decidim/decidim_awesome/account_form_override.rb +25 -0
  29. data/app/forms/concerns/decidim/decidim_awesome/system/organization_form_override.rb +34 -0
  30. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +41 -8
  31. data/app/helpers/decidim/decidim_awesome/map_helper.rb +28 -26
  32. data/app/models/decidim/decidim_awesome/paper_trail_version.rb +5 -1
  33. data/app/overrides/decidim/account/show/add_timezone_select.html.erb.deface +3 -0
  34. data/app/overrides/decidim/admin/officializations/index/add_modal.html.erb.deface +3 -0
  35. data/app/overrides/decidim/admin/officializations/index/add_td.html.erb.deface +5 -0
  36. data/app/overrides/decidim/admin/officializations/index/add_th.html.erb.deface +5 -0
  37. data/app/overrides/decidim/system/organizations/_advanced_settings/add_awesome_config.html.erb.deface +9 -0
  38. data/app/overrides/layouts/decidim/_head/add_awesome_tags.html.erb.deface +1 -1
  39. data/app/overrides/layouts/decidim/admin/_header/add_awesome_custom_styles.html.erb.deface +3 -0
  40. data/app/overrides/layouts/decidim/admin/_header/add_awesome_tags.html.erb.deface +1 -0
  41. data/app/packs/src/decidim/decidim_awesome/admin/proposal_sortings.js +0 -5
  42. data/app/packs/src/decidim/decidim_awesome/admin/verification_selects.js +21 -0
  43. data/app/packs/src/decidim/decidim_awesome/admin/verifications.js +43 -0
  44. data/app/packs/src/decidim/decidim_awesome/awesome_admin.js +1 -0
  45. data/app/packs/src/decidim/decidim_awesome/awesome_admin_global.js +1 -0
  46. data/app/packs/stylesheets/decidim/decidim_awesome/admin/verifications.scss +99 -0
  47. data/app/packs/stylesheets/decidim/decidim_awesome/awesome_admin_global.scss +1 -0
  48. data/app/permissions/decidim/decidim_awesome/admin/permissions.rb +42 -11
  49. data/app/permissions/decidim/decidim_awesome/permissions.rb +7 -0
  50. data/app/presenters/decidim/decidim_awesome/admin_log/component_presenter_override.rb +3 -5
  51. data/app/presenters/decidim/decidim_awesome/admin_log/user_presenter_override.rb +46 -0
  52. data/app/views/decidim/decidim_awesome/account/_timezone_select.html.erb +3 -0
  53. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/authorization.html.erb +20 -0
  54. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/callout.html.erb +3 -0
  55. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/conflict.html.erb +5 -0
  56. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/edit.html.erb +41 -0
  57. data/app/views/decidim/decidim_awesome/admin/config/_form_scoped_admin_styles.html.erb +1 -0
  58. data/app/views/decidim/decidim_awesome/admin/config/_form_scoped_styles.html.erb +48 -0
  59. data/app/views/decidim/decidim_awesome/admin/config/_form_surveys.html.erb +8 -0
  60. data/app/views/decidim/decidim_awesome/admin/config/_form_verifications.html.erb +15 -0
  61. data/app/views/decidim/decidim_awesome/admin/constraints/no_permissions.html.erb +6 -0
  62. data/app/views/decidim/decidim_awesome/admin/officializations/_participants_td.html.erb +25 -0
  63. data/app/views/decidim/decidim_awesome/admin/officializations/_participants_th.html.erb +1 -0
  64. data/app/views/decidim/decidim_awesome/admin/officializations/_verification_modal.html.erb +9 -0
  65. data/app/views/decidim/decidim_awesome/required_authorizations/index.html.erb +66 -0
  66. data/app/views/decidim/decidim_awesome/system/organizations/_admin_allowed_authorizations.html.erb +5 -0
  67. data/app/views/layouts/decidim/decidim_awesome/_custom_styles.html.erb +1 -1
  68. data/app/views/layouts/decidim/decidim_awesome/admin/_custom_styles.html.erb +3 -0
  69. data/app/views/layouts/decidim/decidim_awesome/admin/admin_authorizations.html.erb +7 -0
  70. data/config/i18n-tasks.yml +6 -0
  71. data/config/locales/ca.yml +172 -10
  72. data/config/locales/cs.yml +169 -6
  73. data/config/locales/de.yml +88 -5
  74. data/config/locales/en.yml +115 -1
  75. data/config/locales/es.yml +173 -10
  76. data/config/locales/eu.yml +617 -23
  77. data/config/locales/fr.yml +121 -7
  78. data/config/locales/hu.yml +10 -4
  79. data/config/locales/it.yml +14 -6
  80. data/config/locales/ja.yml +167 -5
  81. data/config/locales/lt.yml +0 -4
  82. data/config/locales/nl.yml +7 -4
  83. data/config/locales/pt-BR.yml +14 -7
  84. data/config/locales/pt-PT.yml +0 -1
  85. data/config/locales/ro-RO.yml +11 -4
  86. data/config/locales/sv.yml +15 -4
  87. data/lib/decidim/decidim_awesome/admin_engine.rb +2 -0
  88. data/lib/decidim/decidim_awesome/authorizator.rb +34 -0
  89. data/lib/decidim/decidim_awesome/awesome.rb +58 -5
  90. data/lib/decidim/decidim_awesome/awesome_helpers.rb +48 -19
  91. data/lib/decidim/decidim_awesome/checksums.yml +10 -0
  92. data/lib/decidim/decidim_awesome/engine.rb +20 -4
  93. data/lib/decidim/decidim_awesome/menu.rb +45 -9
  94. data/lib/decidim/decidim_awesome/request_memoizer.rb +16 -0
  95. data/lib/decidim/decidim_awesome/test/factories.rb +0 -4
  96. data/lib/decidim/decidim_awesome/test/initializer.rb +4 -0
  97. data/lib/decidim/decidim_awesome/test/shared_examples/config_examples.rb +1 -1
  98. data/lib/decidim/decidim_awesome/test/shared_examples/custom_styles_examples.rb +156 -0
  99. data/lib/decidim/decidim_awesome/test/shared_examples/summary_examples.rb +26 -10
  100. data/lib/decidim/decidim_awesome/version.rb +1 -1
  101. data/package.json +6 -5
  102. metadata +42 -7
  103. data/app/views/decidim/decidim_awesome/admin/config/_form_styles.html.erb +0 -30
@@ -4,6 +4,8 @@ module Decidim
4
4
  module DecidimAwesome
5
5
  include ActiveSupport::Configurable
6
6
 
7
+ autoload :AwesomeHelpers, "decidim/decidim_awesome/awesome_helpers"
8
+ autoload :RequestMemoizer, "decidim/decidim_awesome/request_memoizer"
7
9
  autoload :Config, "decidim/decidim_awesome/config"
8
10
  autoload :SystemChecker, "decidim/decidim_awesome/system_checker"
9
11
  autoload :ContextAnalyzers, "decidim/decidim_awesome/context_analyzers"
@@ -13,6 +15,7 @@ module Decidim
13
15
  autoload :Lock, "decidim/decidim_awesome/lock"
14
16
  autoload :TranslatedCustomFieldsType, "decidim/decidim_awesome/api/types/translated_custom_fields_type"
15
17
  autoload :LocalizedCustomFieldsType, "decidim/decidim_awesome/api/types/localized_custom_fields_type"
18
+ autoload :Authorizator, "decidim/decidim_awesome/authorizator"
16
19
 
17
20
  # Awesome comes with some components for participatory spaces
18
21
  # Currently :awesome_map and :awesome_iframe, list them here
@@ -126,7 +129,7 @@ module Decidim
126
129
  false
127
130
  end
128
131
 
129
- # allows admins to created specific CSS snippets affecting only some specific parts
132
+ # allows admins to created specific CSS snippets affecting only some public frontend specific parts
130
133
  # Valid values differ a little from the previous convention:
131
134
  # :disabled => false and non available, hidden from admins
132
135
  # Hash => hash of different css text, each key will be used for the contraints
@@ -138,6 +141,18 @@ module Decidim
138
141
  {}
139
142
  end
140
143
 
144
+ # allows admins to created specific CSS snippets affecting only some admin specific parts
145
+ # Valid values differ a little from the previous convention:
146
+ # :disabled => false and non available, hidden from admins
147
+ # Hash => hash of different css text, each key will be used for the contraints
148
+ # Admins create this hash dynamically but some pre-defined css boxes can be created here as:
149
+ # {
150
+ # some_identifier: ".wrapper { background: red; }"
151
+ # }
152
+ config_accessor :scoped_admin_styles do
153
+ {}
154
+ end
155
+
141
156
  # custom fields for proposals using JSON specification:
142
157
  # https://github.com/jsonform/jsonform/wiki
143
158
  # Valid values uses the same structure as :scoped_styles
@@ -156,6 +171,44 @@ module Decidim
156
171
  {}
157
172
  end
158
173
 
174
+ # whether to add a select to user's profile to allow them to select their preferred time zone
175
+ # if set to false, the select won't be shown but it can still be configured by the admins
176
+ # if set to :disabled the feature will be completly removed
177
+ config_accessor :user_timezone do
178
+ false
179
+ end
180
+
181
+ # Forces the user to authorize using some registered verification flow in order to access the platform
182
+ # if set to an empty array, the user will be able to access the platform without any verification but admins can still enforce it
183
+ # if set to :disabled the feature will be completly removed
184
+ # You can initialize some default verification workflow manifests
185
+ config_accessor :force_authorization_after_login do
186
+ []
187
+ end
188
+
189
+ # By default all methods specified in force_authorization_after_login must be granted in order to access the platform
190
+ # if set to true, the user will be able to access the platform if any of the methods is granted
191
+ config_accessor :force_authorization_with_any_method do
192
+ false
193
+ end
194
+
195
+ # When force_authorization_after_login is enabled, this text will be shown to the user as a help text (ie: add a contact information)
196
+ config_accessor :force_authorization_help_text do
197
+ {}
198
+ end
199
+
200
+ # Allows admins to manually authorize users with the specified methods
201
+ # if set to an empty array, the admins will not be able to authorize users but the system admin can still configure it
202
+ # if set to :disabled the feature will be completly removed
203
+ config_accessor :admins_available_authorizations do
204
+ []
205
+ end
206
+
207
+ # This controllers will be skipped from the authorization check
208
+ config_accessor :force_authorization_allowed_controller_names do
209
+ %w(account pages)
210
+ end
211
+
159
212
  # How old must be the private data to be considered expired and therefore presented to the admins for deletion
160
213
  config_accessor :private_data_expiration_time do
161
214
  3.months
@@ -333,11 +386,11 @@ module Decidim
333
386
 
334
387
  def self.collation_for(locale)
335
388
  @collation_for ||= {}
336
- @collation_for[locale] ||= begin
337
- res = ActiveRecord::Base.connection.execute(Arel.sql("SELECT collname FROM pg_collation WHERE collname LIKE '#{locale}-x-icu' LIMIT 1")).first
338
- res ||= ActiveRecord::Base.connection.execute(Arel.sql("SELECT collname FROM pg_collation WHERE collname LIKE '#{locale[0..1]}%' LIMIT 1")).first
389
+ @collation_for[locale] ||= ["#{locale}-x-icu", "#{locale[0..1]}%"].filter_map do |loc|
390
+ sql = ApplicationRecord.sanitize_sql(["SELECT collname FROM pg_collation WHERE collname LIKE ? LIMIT 1", loc])
391
+ res = ActiveRecord::Base.connection.execute(sql).first
339
392
  res["collname"] if res
340
- end
393
+ end.first
341
394
  end
342
395
 
343
396
  def self.enabled?(*config_vars)
@@ -6,25 +6,27 @@ module Decidim
6
6
  # add a global helper with awesome configuration
7
7
  module DecidimAwesome
8
8
  module AwesomeHelpers
9
+ include RequestMemoizer
10
+
9
11
  # Returns the normalized config for an Organization and the current url
10
12
  def awesome_config_instance
11
- return @awesome_config_instance if @awesome_config_instance
12
-
13
- # if already created in the middleware, reuse it as it might have additional constraints
14
- @awesome_config_instance = request.env["decidim_awesome.current_config"]
15
- unless @awesome_config_instance.is_a? Config
16
- @awesome_config_instance = Config.new request.env["decidim.current_organization"]
17
- @awesome_config_instance.context_from_request request
13
+ memoize("current_config") do
14
+ config = Config.new(request.env["decidim.current_organization"])
15
+ config.context_from_request(request)
16
+ config
18
17
  end
19
- @awesome_config_instance
20
18
  end
21
19
 
22
20
  def awesome_config
23
- @awesome_config ||= awesome_config_instance.config
21
+ memoize("awesome_config") do
22
+ awesome_config_instance.config
23
+ end
24
24
  end
25
25
 
26
26
  def javascript_config_vars
27
- awesome_config.except(:scoped_styles, :proposal_custom_fields, :proposal_private_custom_fields, :scoped_admins).to_json.html_safe
27
+ memoize("javascript_config_vars") do
28
+ awesome_config.slice(:allow_images_in_proposals, :allow_images_in_editors, :allow_videos_in_editors, :auto_save_forms).to_json.html_safe
29
+ end
28
30
  end
29
31
 
30
32
  def show_public_intergram?
@@ -35,11 +37,15 @@ module Decidim
35
37
  end
36
38
 
37
39
  def unfiltered_awesome_config
38
- @unfiltered_awesome_config ||= awesome_config_instance.unfiltered_config
40
+ memoize("unfiltered_awesome_config") do
41
+ awesome_config_instance.unfiltered_config
42
+ end
39
43
  end
40
44
 
41
45
  def organization_awesome_config
42
- @organization_awesome_config ||= awesome_config_instance.organization_config
46
+ memoize("organization_awesome_config") do
47
+ awesome_config_instance.organization_config
48
+ end
43
49
  end
44
50
 
45
51
  def awesome_version
@@ -47,29 +53,52 @@ module Decidim
47
53
  end
48
54
 
49
55
  # Collects all CSS that is applied in the current URL context
50
- def awesome_custom_styles
51
- @awesome_custom_styles ||= awesome_config_instance.collect_sub_configs_values("scoped_style")
56
+ def awesome_scoped_styles
57
+ memoize("awesome_scoped_styles") do
58
+ awesome_config_instance.collect_sub_configs_values("scoped_style")
59
+ end
60
+ end
61
+
62
+ # Collects all CSS that is applied in the current URL context
63
+ def awesome_scoped_admin_styles
64
+ memoize("awesome_scoped_admin_styles") do
65
+ awesome_config_instance.collect_sub_configs_values("scoped_admin_style")
66
+ end
52
67
  end
53
68
 
54
69
  # Collects all proposal custom fields that is applied in the current URL context
55
70
  def awesome_scoped_admins
56
- @awesome_scoped_admins ||= awesome_config_instance.collect_sub_configs_values("scoped_admin")
71
+ memoize("awesome_scoped_admins") do
72
+ awesome_config_instance.collect_sub_configs_values("scoped_admin")
73
+ end
57
74
  end
58
75
 
59
76
  # Collects all proposal custom fields that is applied in the current URL context
60
77
  def awesome_proposal_custom_fields
61
- @awesome_proposal_custom_fields ||= awesome_config_instance.collect_sub_configs_values("proposal_custom_field")
78
+ memoize("awesome_proposal_custom_fields") do
79
+ awesome_config_instance.collect_sub_configs_values("proposal_custom_field")
80
+ end
62
81
  end
63
82
 
64
83
  def awesome_proposal_private_custom_fields
65
- @awesome_proposal_private_custom_fields ||= awesome_config_instance.collect_sub_configs_values("proposal_private_custom_field")
84
+ memoize("awesome_proposal_private_custom_fields") do
85
+ awesome_config_instance.collect_sub_configs_values("proposal_private_custom_field")
86
+ end
66
87
  end
67
88
 
68
89
  # this will check if the current component has been configured to use a custom voting manifest
69
90
  def awesome_voting_manifest_for(component)
70
- return nil unless component.settings.respond_to? :awesome_voting_manifest
91
+ memoize("awesome_voting_manifest_for_#{component.id}") do
92
+ DecidimAwesome.voting_registry.find(component.settings.try(:awesome_voting_manifest))
93
+ end
94
+ end
71
95
 
72
- DecidimAwesome.voting_registry.find(component.settings.awesome_voting_manifest)
96
+ # Retrives all the "admins_available_authorizations" for the user along with other possible authorizations
97
+ # returns an instance of Decidim::DecidimAwesome::Authorizator
98
+ def awesome_authorizations_for(user)
99
+ memoize("awesome_authorizations_for_#{user.id}") do
100
+ Authorizator.new(user, awesome_config[:admins_available_authorizations])
101
+ end
73
102
  end
74
103
 
75
104
  def version_prefix
@@ -13,16 +13,24 @@ decidim-core:
13
13
  /app/views/layouts/decidim/_head.html.erb:
14
14
  decidim-0.28: e51e400a98821f4ca0fff26ebd4d0741
15
15
  decidim-0.28.1: 8ac1af4e223d9a7a98136760b6194a75
16
+ decidim-0.28.4: 59abccd8b1c5315d5c0b772be0c26d45
16
17
  /app/views/layouts/decidim/_decidim_javascript.html.erb:
17
18
  decidim-0.28: dc60ed8abf7649611f18804b67b1408d
18
19
  /app/presenters/decidim/menu_presenter.rb:
19
20
  decidim-0.28: 220c8865a43bd8b7b12a7f926f7f4324
20
21
  /app/presenters/decidim/menu_item_presenter.rb:
21
22
  decidim-0.28: 4e4cd366a8a313079ac5fab466bd3679
23
+ decidim-0.28.4: f04f0f5112499a86079119d5f9ae8487
22
24
  /app/helpers/decidim/amendments_helper.rb:
23
25
  decidim-0.28: df28f9321d1bc07757746ed608274e3d
24
26
  /app/presenters/decidim/admin_log/component_presenter.rb:
25
27
  decidim-0.28: 77e80d527727acdf117a0c4517a69a7c
28
+ /app/forms/decidim/account_form.rb:
29
+ decidim-0.28: 11a022ae6ae18ad89da168bec4207935
30
+ /app/commands/decidim/update_account.rb:
31
+ decidim-0.28: 363872116fb99372c046b7394d618333
32
+ /app/views/decidim/account/show.html.erb:
33
+ decidim-0.28: a0647f1740d696018f73ec8db8c7587a
26
34
  decidim-proposals:
27
35
  /lib/decidim/proposals/proposal_serializer.rb:
28
36
  decidim-0.28: bbd33bdc60defb734b3fb814666bb622
@@ -47,6 +55,7 @@ decidim-proposals:
47
55
  decidim-0.27: 6e663e5c82c27291b63f29f346df8737
48
56
  /app/cells/decidim/proposals/proposal_l_cell.rb:
49
57
  decidim-0.27.4: 5e111ed30bca9475bed8247e5e056747
58
+ decidim-0.28.3: 6d955d56d9d9f0cba46ba157fa923cfc
50
59
  /app/cells/decidim/proposals/proposal_metadata_cell.rb:
51
60
  decidim-0.26: eedfd7f813aedbd819b519e03ae4a680
52
61
  /app/commands/decidim/proposals/create_proposal.rb:
@@ -55,6 +64,7 @@ decidim-proposals:
55
64
  decidim-0.28: ab3f937f15c6ed945e776fef34b18abf
56
65
  /app/commands/decidim/proposals/admin/create_proposal.rb:
57
66
  decidim-0.28: aa0c093cb10b3ccfb046edd0018eae1d
67
+ decidim-0.28.3: 8d73a8c852f473c118f978ddfab323b1
58
68
  /app/commands/decidim/proposals/update_proposal.rb:
59
69
  decidim-0.28: 1cc15b946512f4d5a54d1cf5aea8450a
60
70
  /app/commands/decidim/proposals/update_collaborative_draft.rb:
@@ -15,6 +15,7 @@ module Decidim
15
15
  isolate_namespace Decidim::DecidimAwesome
16
16
 
17
17
  routes do
18
+ get :required_authorizations, to: "required_authorizations#index"
18
19
  post :editor_images, to: "editor_images#create"
19
20
  end
20
21
 
@@ -22,10 +23,6 @@ module Decidim
22
23
  # https://edgeguides.rubyonrails.org/engines.html#overriding-models-and-controllers
23
24
  # overrides
24
25
  config.to_prepare do
25
- # activate Decidim LayoutHelper for the overriden views
26
- ActiveSupport.on_load :action_controller do
27
- helper Decidim::LayoutHelper if respond_to?(:helper)
28
- end
29
26
  # Include additional helpers globally
30
27
  ActiveSupport.on_load(:action_view) { include Decidim::DecidimAwesome::AwesomeHelpers }
31
28
  # Also for cells
@@ -66,12 +63,24 @@ module Decidim
66
63
  Decidim::Proposals::ProposalType.include(Decidim::DecidimAwesome::AddProposalTypeCustomFields)
67
64
  end
68
65
 
66
+ if DecidimAwesome.enabled?(:admins_available_authorizations)
67
+ Decidim::System::RegisterOrganizationForm.include(Decidim::DecidimAwesome::System::OrganizationFormOverride)
68
+ Decidim::System::UpdateOrganizationForm.include(Decidim::DecidimAwesome::System::OrganizationFormOverride)
69
+ Decidim::System::UpdateOrganization.include(Decidim::DecidimAwesome::System::UpdateOrganizationOverride)
70
+ Decidim::System::RegisterOrganization.include(Decidim::DecidimAwesome::System::RegisterOrganizationOverride)
71
+ end
72
+
69
73
  if DecidimAwesome.enabled?(:proposal_custom_fields, :proposal_private_custom_fields, :weighted_proposal_voting)
70
74
  # add vote weight/private_body to proposals
71
75
  Decidim::Proposals::Proposal.include(Decidim::DecidimAwesome::HasProposalExtraFields)
72
76
  Decidim::Proposals::CollaborativeDraft.include(Decidim::DecidimAwesome::HasProposalExtraFields)
73
77
  end
74
78
 
79
+ if Decidim::DecidimAwesome.enabled?(:user_timezone)
80
+ Decidim::AccountForm.include(Decidim::DecidimAwesome::AccountFormOverride)
81
+ Decidim::UpdateAccount.include(Decidim::DecidimAwesome::UpdateAccountOverride)
82
+ end
83
+
75
84
  if DecidimAwesome.enabled?(:weighted_proposal_voting)
76
85
  # add vote weight to proposal vote
77
86
  Decidim::Proposals::ProposalVote.include(Decidim::DecidimAwesome::HasVoteWeight)
@@ -101,6 +110,9 @@ module Decidim
101
110
 
102
111
  initializer "decidim_decidim_awesome.overrides", after: "decidim.action_controller" do
103
112
  config.to_prepare do
113
+ Decidim::ApplicationController.include(Decidim::DecidimAwesome::CheckLoginAuthorizations) if DecidimAwesome.enabled?(:force_authorization_after_login)
114
+ Decidim::ApplicationController.include(Decidim::DecidimAwesome::UseUserTimeZone) if Decidim::DecidimAwesome.enabled?(:user_timezone)
115
+
104
116
  # Auto-insert some csp directives
105
117
  Decidim::ApplicationController.include(Decidim::DecidimAwesome::ContentSecurityPolicy)
106
118
  Decidim::Admin::ApplicationController.include(Decidim::DecidimAwesome::ContentSecurityPolicy)
@@ -119,9 +131,12 @@ module Decidim
119
131
  end
120
132
 
121
133
  if DecidimAwesome.enabled?(:weighted_proposal_voting)
134
+ Decidim::Proposals::ProposalsController.include(Decidim::DecidimAwesome::Proposals::MemoizeExtraFields)
122
135
  Decidim::Proposals::ProposalVotesController.include(Decidim::DecidimAwesome::Proposals::ProposalVotesControllerOverride)
123
136
  end
124
137
 
138
+ Decidim::AdminLog::UserPresenter.include(Decidim::DecidimAwesome::AdminLog::UserPresenterOverride) if DecidimAwesome.enabled?(:admins_available_authorizations)
139
+
125
140
  Decidim::AmendmentsController.include(Decidim::DecidimAwesome::LimitPendingAmendments) if DecidimAwesome.enabled?(:allow_limiting_amendments)
126
141
 
127
142
  Decidim::Proposals::ProposalsController.include(Decidim::DecidimAwesome::Proposals::OrderableOverride) if DecidimAwesome.enabled?(:additional_proposal_sortings)
@@ -274,6 +289,7 @@ module Decidim
274
289
  Decidim.icons.register(name: "line-chart-line", icon: "line-chart-line", category: "system", description: "", engine: :decidim_awesome)
275
290
  Decidim.icons.register(name: "spy", icon: "spy-fill", category: "system", description: "", engine: :decidim_awesome)
276
291
  Decidim.icons.register(name: "forbid-line", icon: "forbid-line", category: "system", description: "", engine: :decidim_awesome)
292
+ Decidim.icons.register(name: "file-settings-line", icon: "file-settings-line", category: "system", description: "", engine: :decidim_awesome)
277
293
  end
278
294
  end
279
295
  end
@@ -29,17 +29,20 @@ module Decidim
29
29
 
30
30
  menu.add_item :styles,
31
31
  I18n.t("menu.styles", scope: "decidim.decidim_awesome.admin"),
32
- decidim_admin_decidim_awesome.config_path(:styles),
32
+ decidim_admin_decidim_awesome.config_path(:scoped_styles),
33
33
  position: 4,
34
34
  icon_name: "brush",
35
- if: menus[:styles]
35
+ if: menus[:styles],
36
+ submenu: { target_menu: :custom_styles_submenu }
36
37
 
37
- menu.add_item :proposal_custom_fields,
38
+ menu.add_item :custom_fields,
38
39
  I18n.t("menu.proposal_custom_fields", scope: "decidim.decidim_awesome.admin"),
39
- decidim_admin_decidim_awesome.config_path(:proposal_custom_fields),
40
+ decidim_admin_decidim_awesome.config_path(menus[:proposal_custom_fields] ? :proposal_custom_fields : :proposal_private_custom_fields),
40
41
  position: 5,
41
42
  icon_name: "layers",
42
- if: menus[:proposal_custom_fields],
43
+ active: is_active_link?(decidim_admin_decidim_awesome.config_path(:proposal_custom_fields)) ||
44
+ is_active_link?(decidim_admin_decidim_awesome.config_path(:proposal_private_custom_fields)),
45
+ if: menus[:custom_fields],
43
46
  submenu: { target_menu: :custom_fields_submenu }
44
47
 
45
48
  menu.add_item :admins,
@@ -55,6 +58,8 @@ module Decidim
55
58
  position: 7,
56
59
  icon_name: "menu-line",
57
60
  if: menus[:menu_hacks],
61
+ active: is_active_link?(decidim_admin_decidim_awesome.menu_hacks_path(:menu)) ||
62
+ is_active_link?(decidim_admin_decidim_awesome.menu_hacks_path(:home_content_block_menu)),
58
63
  submenu: { target_menu: :menu_hacks_submenu }
59
64
 
60
65
  menu.add_item :custom_redirects,
@@ -71,11 +76,20 @@ module Decidim
71
76
  icon_name: "chat-1-line",
72
77
  if: menus[:livechat]
73
78
 
79
+ menu.add_item :verifications,
80
+ I18n.t("menu.verifications", scope: "decidim.decidim_awesome.admin"),
81
+ decidim_admin_decidim_awesome.config_path(:verifications),
82
+ position: 10,
83
+ icon_name: "fingerprint-line",
84
+ if: menus[:verifications]
85
+
74
86
  menu.add_item :maintenance,
75
87
  I18n.t("maintenance", scope: "decidim.decidim_awesome.admin.menu.maintenance"),
76
88
  decidim_admin_decidim_awesome.maintenance_path(:private_data),
77
- position: 10,
89
+ position: 11,
78
90
  icon_name: "tools-line",
91
+ active: is_active_link?(decidim_admin_decidim_awesome.maintenance_path(:private_data)) ||
92
+ is_active_link?(decidim_admin_decidim_awesome.checks_maintenance_index_path),
79
93
  submenu: { target_menu: :maintenance_submenu }
80
94
  end
81
95
  end
@@ -98,6 +112,24 @@ module Decidim
98
112
  end
99
113
  end
100
114
 
115
+ def register_custom_styles_submenu!
116
+ Decidim.menu :custom_styles_submenu do |menu|
117
+ menu.add_item :scoped_styles,
118
+ I18n.t("menu.title", scope: "decidim.decidim_awesome.admin.scoped_styles"),
119
+ decidim_admin_decidim_awesome.config_path(:scoped_styles),
120
+ position: 4.1,
121
+ icon_name: "computer-line",
122
+ if: config_enabled?(:scoped_styles)
123
+
124
+ menu.add_item :scoped_admin_styles,
125
+ I18n.t("menu.title", scope: "decidim.decidim_awesome.admin.scoped_admin_styles"),
126
+ decidim_admin_decidim_awesome.config_path(:scoped_admin_styles),
127
+ position: 4.2,
128
+ icon_name: "file-settings-line",
129
+ if: config_enabled?(:scoped_admin_styles)
130
+ end
131
+ end
132
+
101
133
  def register_menu_hacks_submenu!
102
134
  Decidim.menu :menu_hacks_submenu do |menu|
103
135
  menu.add_item :main_menu,
@@ -142,8 +174,11 @@ module Decidim
142
174
  :validate_body_min_length, :validate_body_max_caps_percent,
143
175
  :validate_body_max_marks_together, :validate_body_start_with_caps
144
176
  ),
145
- surveys: config_enabled?(:auto_save_forms),
146
- styles: config_enabled?(:scoped_styles),
177
+ surveys: config_enabled?(:auto_save_forms, :user_timezone),
178
+ styles: config_enabled?(:scoped_styles, :scoped_admin_styles),
179
+ scoped_styles: config_enabled?(:scoped_styles),
180
+ scoped_admin_styles: config_enabled?(:scoped_admin_styles),
181
+ custom_fields: config_enabled?(:proposal_custom_fields, :proposal_private_custom_fields),
147
182
  proposal_custom_fields: config_enabled?(:proposal_custom_fields),
148
183
  proposal_private_custom_fields: config_enabled?(:proposal_private_custom_fields),
149
184
  admins: config_enabled?(:scoped_admins),
@@ -151,7 +186,8 @@ module Decidim
151
186
  menu_hacks_menu: config_enabled?(:menu),
152
187
  menu_hacks_home_content_block_menu: config_enabled?(:home_content_block_menu),
153
188
  custom_redirects: config_enabled?(:custom_redirects),
154
- livechat: config_enabled?(:intergram_for_admins, :intergram_for_public)
189
+ livechat: config_enabled?(:intergram_for_admins, :intergram_for_public),
190
+ verifications: config_enabled?(:force_authorization_after_login)
155
191
  }
156
192
  end
157
193
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module RequestMemoizer
6
+ # memoize a piece of code in the global request instead of the helper instance (helpers are initialized for each view)
7
+ def memoize(key)
8
+ if defined?(request) && request.env["decidim.current_organization"]&.id
9
+ request.env["decidim_awesome.#{key}"] ||= block_given? ? yield : nil
10
+ elsif block_given?
11
+ yield
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "decidim/core/test/factories"
4
- require "decidim/proposals/test/factories"
5
- require "decidim/surveys/test/factories"
6
-
7
3
  FactoryBot.define do
8
4
  factory :awesome_config, class: "Decidim::DecidimAwesome::AwesomeConfig" do
9
5
  var { Faker::Hacker.noun }
@@ -7,9 +7,13 @@ Decidim::DecidimAwesome.configure do |config|
7
7
  :allow_videos_in_editors,
8
8
  :allow_images_in_proposals,
9
9
  :auto_save_forms,
10
+ :user_timezone,
11
+ :force_authorization_after_login,
12
+ :admins_available_authorizations,
10
13
  :intergram_for_admins,
11
14
  :intergram_for_public,
12
15
  :scoped_styles,
16
+ :scoped_admin_styles,
13
17
  :proposal_custom_fields,
14
18
  :proposal_private_custom_fields,
15
19
  :menu,
@@ -40,7 +40,7 @@ shared_examples "forbids disabled feature without redirect" do
40
40
  it "fails with error" do
41
41
  action
42
42
 
43
- expect(response.body).to eq("no permissions for #{feature}")
43
+ expect(response.body).to have_content("No permissions for #{feature}")
44
44
  end
45
45
  end
46
46
 
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples "creates a new box" do |name|
4
+ it "saves the content in the hash" do
5
+ click_on "Add a new \"#{name}\" CSS box"
6
+
7
+ expect(page).to have_admin_callout("created successfully")
8
+
9
+ sleep 1
10
+ page.execute_script('document.querySelector(".CodeMirror").CodeMirror.setValue("body {background: red;}");')
11
+
12
+ click_on "Update configuration"
13
+
14
+ expect(page).to have_admin_callout("updated successfully")
15
+ expect(page).to have_content("body {background: red;}")
16
+ end
17
+ end
18
+
19
+ shared_examples "saves content" do |key|
20
+ it "updates succesfully" do
21
+ expect(page).to have_content("body {background: red;}")
22
+ expect(page).to have_content("body {background: blue;}")
23
+
24
+ sleep 1
25
+ page.execute_script("document.querySelector(\"[data-key=#{key}] .CodeMirror\").CodeMirror.setValue(\"body {background: green;}\");")
26
+ click_link_or_button "Update configuration"
27
+
28
+ expect(page).to have_admin_callout("updated successfully")
29
+ expect(page).not_to have_content("body {background: red;}")
30
+ expect(page).to have_content("body {background: green;}")
31
+ expect(page).to have_content("body {background: blue;}")
32
+ end
33
+
34
+ it "shows error message if invalid" do
35
+ sleep 1
36
+ page.execute_script("document.querySelector(\"[data-key=#{key}] .CodeMirror\").CodeMirror.setValue(\"I am invalid CSS\");")
37
+ click_link_or_button "Update configuration"
38
+
39
+ expect(page).to have_admin_callout("Error updating configuration!")
40
+ expect(page).not_to have_content("body {background: red;}")
41
+ expect(page).to have_content("body {background: blue;}")
42
+ expect(page).to have_content("I am invalid CSS")
43
+ end
44
+ end
45
+
46
+ shared_examples "updates new box" do
47
+ it "updates the content in the hash" do
48
+ expect(page).to have_content("body {background: red;}")
49
+ expect(page).to have_content("body {background: blue;}")
50
+ end
51
+ end
52
+
53
+ shared_examples "removes a box" do
54
+ let(:styles) do
55
+ {
56
+ "foo" => "body {background: red;}",
57
+ "bar" => "body {background: blue;}"
58
+ }
59
+ end
60
+
61
+ it "updates the content in the hash" do
62
+ expect(page).to have_content("body {background: red;}")
63
+ expect(page).to have_content("body {background: blue;}")
64
+
65
+ within ".scoped_styles_container[data-key=\"foo\"]" do
66
+ accept_confirm { click_link_or_button "Remove this CSS box" }
67
+ end
68
+
69
+ expect(page).to have_admin_callout("removed successfully")
70
+ expect(page).to have_content("body {background: blue;}")
71
+ expect(page).not_to have_content("body {background: red;}")
72
+ expect(Decidim::DecidimAwesome::AwesomeConfig.find_by(organization:, var: "#{var_name}_foo")).not_to be_present
73
+ expect(Decidim::DecidimAwesome::AwesomeConfig.find_by(organization:, var: "#{var_name}_bar")).to be_present
74
+ end
75
+ end
76
+
77
+ shared_examples "adds a constraint" do |name|
78
+ let(:styles) do
79
+ {
80
+ "foo" => "body {background: red;}",
81
+ "bar" => "body {background: blue;}"
82
+ }
83
+ end
84
+
85
+ it "adds a new config helper var" do
86
+ click_on "Add a new \"#{name}\" CSS box"
87
+
88
+ expect(page).to have_content("Processes")
89
+
90
+ expect(Decidim::DecidimAwesome::AwesomeConfig.find_by(organization:, var: "#{var_name}_bar")).to be_present
91
+ expect(Decidim::DecidimAwesome::AwesomeConfig.find_by(organization:,
92
+ var: "#{var_name}_bar").constraints.first.settings).to eq("participatory_space_manifest" => "participatory_processes")
93
+ end
94
+ end
95
+
96
+ shared_examples "removes a constraint" do
97
+ let(:styles) do
98
+ {
99
+ "foo" => "body {background: red;}",
100
+ "bar" => "body {background: blue;}"
101
+ }
102
+ end
103
+
104
+ before do
105
+ visit decidim_admin_decidim_awesome.config_path("#{var_name}s")
106
+ click_on "Add case", id: "new-#{var_name}_bar"
107
+ end
108
+
109
+ it "removes the helper config var" do
110
+ within "#constraint-form-" do
111
+ select "Processes", from: "Apply to participatory spaces of type"
112
+ end
113
+ click_on "Save"
114
+
115
+ within ".scoped_styles_container[data-key=\"bar\"] .constraints-editor" do
116
+ expect(page).to have_content("Processes")
117
+ end
118
+
119
+ within ".scoped_styles_container[data-key=\"bar\"] .constraints-editor" do
120
+ click_on "Delete"
121
+ end
122
+
123
+ within ".scoped_styles_container[data-key=\"bar\"] .constraints-editor" do
124
+ expect(page).not_to have_content("Processes")
125
+ end
126
+
127
+ visit decidim_admin_decidim_awesome.config_path("#{var_name}s")
128
+
129
+ within ".scoped_styles_container[data-key=\"bar\"] .constraints-editor" do
130
+ expect(page).not_to have_content("Processes")
131
+ end
132
+
133
+ expect(Decidim::DecidimAwesome::AwesomeConfig.find_by(organization:, var: "#{var_name}_bar")).to be_present
134
+ expect(Decidim::DecidimAwesome::AwesomeConfig.find_by(organization:, var: "#{var_name}_bar").constraints).not_to be_present
135
+ end
136
+ end
137
+
138
+ shared_examples "extra css is added" do
139
+ it "css is present" do
140
+ expect(page.body).to have_content("body {background: red;}")
141
+ end
142
+
143
+ it "css is applied" do
144
+ expect(page.execute_script("return window.getComputedStyle($('body')[0]).backgroundColor")).to eq("rgb(255, 0, 0)")
145
+ end
146
+ end
147
+
148
+ shared_examples "no extra css is added" do
149
+ it "css is no present" do
150
+ expect(page.body).not_to have_content("body {background: red;}")
151
+ end
152
+
153
+ it "css is not applyied" do
154
+ expect(page.execute_script("return window.getComputedStyle($('body')[0]).backgroundColor")).to eq(default_background_color)
155
+ end
156
+ end