decidim-core 0.28.3 → 0.28.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/activity_cell.rb +1 -4
- data/app/cells/decidim/author/show.erb +5 -4
- data/app/cells/decidim/author_cell.rb +26 -0
- data/app/cells/decidim/card_s/show.erb +5 -3
- data/app/cells/decidim/content_blocks/stats_cell.rb +1 -1
- data/app/cells/decidim/diff_cell.rb +4 -0
- data/app/cells/decidim/endorsement_buttons_cell.rb +1 -1
- data/app/cells/decidim/nav_links/show.erb +3 -3
- data/app/cells/decidim/newsletter_templates/image_text_cta_cell.rb +1 -1
- data/app/cells/decidim/resource_types_filter/show.erb +11 -12
- data/app/cells/decidim/translation_bar/show.erb +3 -3
- data/app/cells/decidim/translation_bar_cell.rb +1 -1
- data/app/commands/decidim/amendable/create_draft.rb +1 -0
- data/app/commands/decidim/destroy_account.rb +3 -0
- data/app/controllers/concerns/decidim/devise_authentication_methods.rb +1 -1
- data/app/controllers/concerns/decidim/direct_upload.rb +82 -0
- data/app/controllers/decidim/doorkeeper/credentials_controller.rb +1 -1
- data/app/controllers/decidim/links_controller.rb +1 -1
- data/app/controllers/decidim/profiles_controller.rb +4 -0
- data/app/forms/decidim/upload_validation_form.rb +1 -1
- data/app/helpers/concerns/decidim/user_role_checker.rb +46 -0
- data/app/helpers/decidim/cta_button_helper.rb +1 -1
- data/app/helpers/decidim/layout_helper.rb +28 -0
- data/app/helpers/decidim/map_helper.rb +6 -1
- data/app/helpers/decidim/menu_helper.rb +1 -1
- data/app/helpers/decidim/sanitize_helper.rb +11 -2
- data/app/helpers/decidim/scopes_helper.rb +5 -2
- data/app/models/decidim/action_log.rb +11 -1
- data/app/models/decidim/attachment.rb +1 -1
- data/app/packs/src/decidim/a11y.js +11 -15
- data/app/packs/src/decidim/append_redirect_url_to_modals.js +24 -14
- data/app/packs/src/decidim/direct_uploads/upload_field.js +21 -8
- data/app/packs/src/decidim/direct_uploads/upload_modal.js +3 -0
- data/app/packs/src/decidim/index.js +3 -0
- data/app/packs/src/decidim/remote_tooltips.js +38 -0
- data/app/packs/src/decidim/toggle.js +1 -1
- data/app/packs/src/decidim/tooltips.js +42 -22
- data/app/packs/stylesheets/decidim/_buttons.scss +1 -1
- data/app/packs/stylesheets/decidim/_modal_update.scss +4 -0
- data/app/packs/stylesheets/decidim/_profile.scss +1 -1
- data/app/packs/stylesheets/decidim/_progress-bar.scss +1 -1
- data/app/packs/stylesheets/decidim/legacy/conference-diploma.scss +2 -1
- data/app/presenters/decidim/attachment_presenter.rb +1 -1
- data/app/presenters/decidim/menu_item_presenter.rb +1 -1
- data/app/queries/decidim/last_activity.rb +16 -5
- data/app/services/decidim/base_diff_renderer.rb +26 -2
- data/app/services/decidim/email_notification_generator.rb +14 -5
- data/app/views/decidim/devise/omniauth_registrations/new.html.erb +1 -1
- data/app/views/decidim/offline/show.html.erb +1 -1
- data/app/views/decidim/pages/_tabbed.html.erb +5 -5
- data/app/views/decidim/shared/_filters.html.erb +5 -5
- data/app/views/decidim/shared/_orders.html.erb +3 -2
- data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -1
- data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
- data/app/views/layouts/decidim/_head.html.erb +1 -1
- data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +1 -1
- data/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +2 -2
- data/config/locales/ar.yml +12 -1
- data/config/locales/bg.yml +0 -1
- data/config/locales/bn-BD.yml +1 -0
- data/config/locales/bs-BA.yml +98 -0
- data/config/locales/ca.yml +14 -10
- data/config/locales/cs.yml +6 -1
- data/config/locales/de.yml +18 -14
- data/config/locales/el.yml +3 -1
- data/config/locales/en.yml +5 -1
- data/config/locales/es-MX.yml +6 -2
- data/config/locales/es-PY.yml +6 -2
- data/config/locales/es.yml +12 -8
- data/config/locales/eu.yml +202 -185
- data/config/locales/fi-plain.yml +5 -1
- data/config/locales/fi.yml +40 -36
- data/config/locales/fr-CA.yml +6 -2
- data/config/locales/fr.yml +5 -1
- data/config/locales/ga-IE.yml +5 -0
- data/config/locales/gl.yml +4 -1
- data/config/locales/hu.yml +1 -2
- data/config/locales/id-ID.yml +4 -0
- data/config/locales/is-IS.yml +4 -1
- data/config/locales/it.yml +40 -0
- data/config/locales/ja.yml +18 -16
- data/config/locales/lb.yml +5 -0
- data/config/locales/lt.yml +1 -2
- data/config/locales/lv.yml +4 -0
- data/config/locales/nl.yml +6 -1
- data/config/locales/no.yml +5 -0
- data/config/locales/pl.yml +1 -2
- data/config/locales/pt-BR.yml +199 -1
- data/config/locales/pt.yml +11 -0
- data/config/locales/ro-RO.yml +302 -180
- data/config/locales/ru.yml +4 -0
- data/config/locales/sk.yml +5 -1
- data/config/locales/sv.yml +452 -81
- data/config/locales/tr-TR.yml +6 -1
- data/config/locales/uk.yml +4 -1
- data/config/locales/zh-CN.yml +5 -0
- data/config/locales/zh-TW.yml +4 -1
- data/config/routes.rb +1 -0
- data/decidim-core.gemspec +4 -1
- data/lib/decidim/api/functions/component_list.rb +1 -1
- data/lib/decidim/api/functions/participatory_space_finder_base.rb +11 -1
- data/lib/decidim/api/interfaces/participatory_space_interface.rb +1 -1
- data/lib/decidim/api/types/component_type.rb +7 -0
- data/lib/decidim/api/types/user_group_type.rb +4 -0
- data/lib/decidim/api/types/user_type.rb +4 -0
- data/lib/decidim/attributes/rich_text.rb +38 -0
- data/lib/decidim/attributes/time_with_zone.rb +11 -1
- data/lib/decidim/attributes.rb +2 -0
- data/lib/decidim/content_parsers/blob_parser.rb +93 -0
- data/lib/decidim/content_parsers.rb +1 -0
- data/lib/decidim/content_renderers/blob_renderer.rb +90 -0
- data/lib/decidim/content_renderers.rb +1 -0
- data/lib/decidim/core/engine.rb +35 -1
- data/lib/decidim/core/test/factories.rb +28 -0
- data/lib/decidim/core/test/shared_examples/authorable_interface_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +25 -2
- data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +112 -14
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +11 -0
- data/lib/decidim/diffy_extension.rb +18 -0
- data/lib/decidim/form_builder.rb +1 -1
- data/lib/decidim/map/autocomplete.rb +1 -0
- data/lib/decidim/organization_settings.rb +4 -1
- data/lib/decidim/participatory_space_user.rb +4 -0
- data/lib/decidim/query_extensions.rb +0 -26
- data/lib/decidim/settings_manifest.rb +2 -0
- data/lib/decidim/translatable_attributes.rb +6 -1
- data/lib/decidim/view_model.rb +1 -1
- data/lib/tasks/upgrade/decidim_attachments.rake +14 -0
- data/lib/tasks/upgrade/decidim_fix_categorization.rake +34 -8
- metadata +30 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30504edbc5451f226b04213804ae8b02392132d8f66f9d5ebe9ea58ad264031e
|
|
4
|
+
data.tar.gz: 0ff217364122ef3812f7aa950e4908364126ceca46f135d0d5dc049b1ee19537
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 897aec8c06d1dd2110a5bd880e07061cab5e12495b707ed175afa81468c5ac162cf3d7a6643879eab83a82a9ca76232ff82dcb0d9b29ccf277d328fec6539a35
|
|
7
|
+
data.tar.gz: 88e9607861160a270e3604733a323fc2b1d359779c335ff8ccce97c9e587062c9c916d07682ad0ddda2b50abe2f718d3ce4baeb5bf77cbf3aab77ea231160014
|
|
@@ -106,10 +106,7 @@ module Decidim
|
|
|
106
106
|
hash << id_prefix
|
|
107
107
|
hash << I18n.locale.to_s
|
|
108
108
|
hash << model.class.name.underscore
|
|
109
|
-
hash << model.cache_key_with_version
|
|
110
|
-
if (author_cell = author)
|
|
111
|
-
hash.push(Digest::MD5.hexdigest(author_cell.send(:cache_hash)))
|
|
112
|
-
end
|
|
109
|
+
hash << model.cache_key_with_version if model.respond_to?(:cache_key_with_version)
|
|
113
110
|
|
|
114
111
|
hash.join(Decidim.cache_key_separator)
|
|
115
112
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<%# If the options hash has the demo key it means we are in the decidim-design engine, so it is not a real-world scenario with actual users %>
|
|
2
|
+
<% tooltip = options.has_key?(:demo) ? { tooltip: render(:profile_minicard).html_safe } : nil %>
|
|
3
|
+
<%= content_tag(:span, class: :author, data: ) do %>
|
|
4
|
+
<%= content_tag :span, class: "author__container#{" is-compact" if layout == :compact}", data: tooltip do %>
|
|
4
5
|
<% if layout == :compact %>
|
|
5
6
|
<%= render :avatar %>
|
|
6
7
|
|
|
@@ -24,4 +25,4 @@
|
|
|
24
25
|
<%= render action %>
|
|
25
26
|
<% end %>
|
|
26
27
|
<% end %>
|
|
27
|
-
|
|
28
|
+
<% end %>
|
|
@@ -49,8 +49,26 @@ module Decidim
|
|
|
49
49
|
@context_actions_options ||= options[:context_actions].map(&:to_sym)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
def profile_minicard
|
|
53
|
+
render
|
|
54
|
+
end
|
|
55
|
+
|
|
52
56
|
private
|
|
53
57
|
|
|
58
|
+
# If the options hash has the demo key it means we are in the decidim-design engine,
|
|
59
|
+
# so it is not a real-world scenario with actual users
|
|
60
|
+
def data
|
|
61
|
+
@data ||= begin
|
|
62
|
+
internal_data = { author: true }
|
|
63
|
+
if has_tooltip? && !options.has_key?(:demo)
|
|
64
|
+
internal_data["remote_tooltip"] = true
|
|
65
|
+
internal_data["tooltip-url"] = decidim.profile_tooltip_path(raw_model.nickname)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
internal_data
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
54
72
|
def layout
|
|
55
73
|
@layout ||= LAYOUTS.include?(options[:layout]) ? options[:layout] : :default
|
|
56
74
|
end
|
|
@@ -162,5 +180,13 @@ module Decidim
|
|
|
162
180
|
def resource_name
|
|
163
181
|
@resource_name ||= from_context.class.name.demodulize.underscore
|
|
164
182
|
end
|
|
183
|
+
|
|
184
|
+
def has_tooltip?
|
|
185
|
+
return false if model.deleted?
|
|
186
|
+
return false if model.respond_to?(:blocked?) && model.blocked?
|
|
187
|
+
return true if options.has_key?(:tooltip)
|
|
188
|
+
|
|
189
|
+
model.has_tooltip?
|
|
190
|
+
end
|
|
165
191
|
end
|
|
166
192
|
end
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
<%=
|
|
1
|
+
<%= content_tag :div, id: dom_id(resource), class: "card__search" do %>
|
|
2
2
|
<%= content_tag title_tag, class: "h4 card__search-title" do %>
|
|
3
|
-
<%=
|
|
3
|
+
<%= link_to resource_path, class: "card__search" do %>
|
|
4
|
+
<%= title %>
|
|
5
|
+
<% end %>
|
|
4
6
|
<% end %>
|
|
5
7
|
<% if metadata_cell.present? %>
|
|
6
8
|
<div class="card__search-metadata">
|
|
7
|
-
|
|
9
|
+
<%= cell metadata_cell, resource, links: false %>
|
|
8
10
|
</div>
|
|
9
11
|
<% end %>
|
|
10
12
|
<% end %>
|
|
@@ -71,6 +71,10 @@ module Decidim
|
|
|
71
71
|
|
|
72
72
|
# DiffRenderer class for the current_version's item; falls back to `BaseDiffRenderer`.
|
|
73
73
|
def diff_renderer_class
|
|
74
|
+
renderer_class = "#{current_version.item_type}DiffRenderer".safe_constantize
|
|
75
|
+
|
|
76
|
+
return renderer_class if renderer_class
|
|
77
|
+
|
|
74
78
|
if current_version.item_type.deconstantize == "Decidim"
|
|
75
79
|
"#{current_version.item_type.pluralize}::DiffRenderer".constantize
|
|
76
80
|
else
|
|
@@ -77,7 +77,7 @@ module Decidim
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def user_has_verified_groups?
|
|
80
|
-
current_user && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
|
|
80
|
+
current_user && current_organization.user_groups_enabled? && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def endorse_translated
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<div class="participatory-space__nav-container">
|
|
2
|
-
<button id="dropdown-trigger-participatory-space" data-component="dropdown" data-target="dropdown-menu-participatory-space" data-auto-close="true" data-scroll-to-menu="true">
|
|
2
|
+
<button id="dropdown-trigger-participatory-space" data-component="dropdown" data-target="dropdown-menu-participatory-space" data-auto-close="true" data-scroll-to-menu="true" data-open-md="true">
|
|
3
3
|
<span><%= t("decidim.searches.filters.jump_to") %></span>
|
|
4
4
|
<%= icon "arrow-down-s-line" %>
|
|
5
5
|
<%= icon "arrow-up-s-line" %>
|
|
6
6
|
</button>
|
|
7
|
-
<ul id="dropdown-menu-participatory-space" class="participatory-space__nav"
|
|
7
|
+
<ul id="dropdown-menu-participatory-space" class="participatory-space__nav">
|
|
8
8
|
<% model.each do |item| %>
|
|
9
|
-
<li>
|
|
9
|
+
<li role="menuitem">
|
|
10
10
|
<%= link_to item[:url], class: "participatory-space__nav-item" do %>
|
|
11
11
|
<%= item[:name] %>
|
|
12
12
|
<%= icon "arrow-right-line" %>
|
|
@@ -50,7 +50,7 @@ module Decidim
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def main_image_url
|
|
53
|
-
newsletter.template.images_container.attached_uploader(:main_image).url
|
|
53
|
+
newsletter.template.images_container.attached_uploader(:main_image).url
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def organization_primary_color
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div id="<%= id %>" class="filter-container">
|
|
2
|
-
<button id="dropdown-trigger-resource" data-component="dropdown" data-target="dropdown-menu-resource" data-
|
|
2
|
+
<button id="dropdown-trigger-resource" data-component="dropdown" data-target="dropdown-menu-resource" data-open-md="true">
|
|
3
3
|
<% resource_types.each do |resource_type| %>
|
|
4
4
|
<span data-value="<%= resource_type[0] %>" class="<%= "is-active" if filter_param == resource_type[0] %>">
|
|
5
5
|
<%= text_with_resource_icon(*resource_type) %>
|
|
@@ -8,15 +8,14 @@
|
|
|
8
8
|
<%= icon "arrow-down-s-line" %>
|
|
9
9
|
<%= icon "arrow-up-s-line" %>
|
|
10
10
|
</button>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<% end %>
|
|
11
|
+
<ul id="dropdown-menu-resource">
|
|
12
|
+
<% resource_types.each do |resource_type| %>
|
|
13
|
+
<li role="menuitem">
|
|
14
|
+
<%= link_to decidim.last_activities_path(filter: { with_resource_type: resource_type[0] } ), class: "filter#{" is-active" if filter_param == resource_type[0]}" do %>
|
|
15
|
+
<span class="sr-only"><%= resource_type[1] %></span>
|
|
16
|
+
<%= text_with_resource_icon(*resource_type) %>
|
|
17
|
+
<% end %>
|
|
18
|
+
</li>
|
|
19
|
+
<% end %>
|
|
20
|
+
</ul>
|
|
22
21
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<div
|
|
2
|
-
<div class="
|
|
1
|
+
<div>
|
|
2
|
+
<div class="pt-4 pb-4 text-center bg-background">
|
|
3
3
|
<%= link %>
|
|
4
|
-
<span class="translation-button-help"><%= help_text %></span>
|
|
4
|
+
<span class="translation-button-help ml-4"><%= help_text %></span>
|
|
5
5
|
</div>
|
|
6
6
|
</div>
|
|
@@ -53,6 +53,7 @@ module Decidim
|
|
|
53
53
|
emendation.body = { I18n.locale => form.emendation_params.with_indifferent_access[:body] }
|
|
54
54
|
emendation.component = amendable.component
|
|
55
55
|
emendation.add_author(current_user, user_group)
|
|
56
|
+
emendation.category = amendable.category if amendable.respond_to?(:category)
|
|
56
57
|
emendation.save!
|
|
57
58
|
emendation
|
|
58
59
|
end
|
|
@@ -35,6 +35,9 @@ module Decidim
|
|
|
35
35
|
@user.name = ""
|
|
36
36
|
@user.nickname = ""
|
|
37
37
|
@user.email = ""
|
|
38
|
+
@user.personal_url = ""
|
|
39
|
+
@user.about = ""
|
|
40
|
+
@user.notifications_sending_frequency = "none"
|
|
38
41
|
@user.delete_reason = @form.delete_reason
|
|
39
42
|
@user.admin = false if @user.admin?
|
|
40
43
|
@user.deleted_at = Time.current
|
|
@@ -12,7 +12,7 @@ module Decidim
|
|
|
12
12
|
if user.present? && user.blocked?
|
|
13
13
|
check_user_block_status(user)
|
|
14
14
|
elsif user.needs_password_update?
|
|
15
|
-
change_password_path
|
|
15
|
+
decidim.change_password_path
|
|
16
16
|
elsif first_login_and_not_authorized?(user) && !user.admin? && !pending_redirect?(user)
|
|
17
17
|
decidim_verifications.first_login_authorizations_path
|
|
18
18
|
else
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module DirectUpload
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
include Decidim::NeedsOrganization
|
|
9
|
+
skip_before_action :verify_organization
|
|
10
|
+
|
|
11
|
+
before_action :check_organization!,
|
|
12
|
+
:check_authenticated!,
|
|
13
|
+
:check_user_belongs_to_organization,
|
|
14
|
+
:validate_direct_upload
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def validate_direct_upload
|
|
20
|
+
# We skip the validation if we are in system panel. `current_admin` refers to the main system admin user.
|
|
21
|
+
return if current_admin.present?
|
|
22
|
+
|
|
23
|
+
head :unprocessable_entity unless [
|
|
24
|
+
maximum_allowed_size.try(:to_i) >= blob_args[:byte_size].try(:to_i),
|
|
25
|
+
content_types.any? { |pattern| pattern.match?(blob_args[:content_type]) },
|
|
26
|
+
content_types.any? { |pattern| pattern.match?(MiniMime.lookup_by_extension(extension)&.content_type) },
|
|
27
|
+
allowed_extensions.any? { |pattern| pattern.match?(extension) }
|
|
28
|
+
].all?
|
|
29
|
+
rescue NoMethodError
|
|
30
|
+
head :unprocessable_entity
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def extension
|
|
34
|
+
File.extname(blob_args[:filename]).delete(".")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def maximum_allowed_size
|
|
38
|
+
current_organization.settings.upload_maximum_file_size
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def check_organization!
|
|
42
|
+
head :unauthorized if current_organization.blank? && current_admin.blank?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def check_authenticated!
|
|
46
|
+
head :unauthorized if current_user.blank? && current_admin.blank?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def check_user_belongs_to_organization
|
|
50
|
+
return if current_admin.present?
|
|
51
|
+
|
|
52
|
+
head :unauthorized unless current_organization == current_user.organization
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def allowed_extensions
|
|
56
|
+
if user_has_elevated_role?
|
|
57
|
+
current_organization.settings.upload_allowed_file_extensions_admin
|
|
58
|
+
else
|
|
59
|
+
current_organization.settings.upload_allowed_file_extensions
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def content_types
|
|
64
|
+
if user_has_elevated_role?
|
|
65
|
+
current_organization.settings.upload_allowed_content_types_admin
|
|
66
|
+
else
|
|
67
|
+
current_organization.settings.upload_allowed_content_types
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def user_has_elevated_role?
|
|
74
|
+
[
|
|
75
|
+
current_user&.admin?,
|
|
76
|
+
defined?(Decidim::Assemblies::AssembliesWithUserRole) && Decidim::Assemblies::AssembliesWithUserRole.for(current_user).any?,
|
|
77
|
+
defined?(Decidim::Conferences::ConferencesWithUserRole) && Decidim::Conferences::ConferencesWithUserRole.for(current_user).any?,
|
|
78
|
+
defined?(Decidim::ParticipatoryProcessesWithUserRole) && Decidim::ParticipatoryProcessesWithUserRole.for(current_user).any?
|
|
79
|
+
].any?
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -28,7 +28,7 @@ module Decidim
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def avatar_url
|
|
31
|
-
avatar_url = current_resource_owner.attached_uploader(:avatar).url
|
|
31
|
+
avatar_url = current_resource_owner.attached_uploader(:avatar).url
|
|
32
32
|
return unless avatar_url
|
|
33
33
|
|
|
34
34
|
unless %r{^https?://}.match? avatar_url
|
|
@@ -41,7 +41,7 @@ module Decidim
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def escape_url(external_url)
|
|
44
|
-
before_fragment, fragment = external_url.split("#", 2)
|
|
44
|
+
before_fragment, fragment = URI.decode_www_form_component(external_url).split("#", 2)
|
|
45
45
|
escaped_before_fragment = URI::Parser.new.escape(before_fragment)
|
|
46
46
|
|
|
47
47
|
if fragment
|
|
@@ -27,6 +27,10 @@ module Decidim
|
|
|
27
27
|
redirect_to profile_activity_path(nickname: params[:nickname])
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def tooltip
|
|
31
|
+
render json: { data: cell("decidim/author", profile_holder.presenter).profile_minicard }
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
def following
|
|
31
35
|
@content_cell = "decidim/following"
|
|
32
36
|
@title_key = "following"
|
|
@@ -10,7 +10,7 @@ module Decidim
|
|
|
10
10
|
# Property is named as attribute in upload modal and passthru validator, but
|
|
11
11
|
# it cannot be named as attribute here.
|
|
12
12
|
attribute :property, String
|
|
13
|
-
attribute :blob,
|
|
13
|
+
attribute :blob, Decidim::Attributes::Blob
|
|
14
14
|
attribute :form_class, String
|
|
15
15
|
|
|
16
16
|
validates :resource_class, presence: true
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module UserRoleChecker
|
|
5
|
+
# Shared behaviour for signed_in admins
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def user_has_any_role?(user, participatory_space = nil, broad_check: false)
|
|
11
|
+
return false unless user
|
|
12
|
+
|
|
13
|
+
[
|
|
14
|
+
user.admin,
|
|
15
|
+
user.roles.any?,
|
|
16
|
+
participatory_process_user_role?(user, participatory_space, broad_check:),
|
|
17
|
+
assembly_user_role?(user, participatory_space, broad_check:),
|
|
18
|
+
conference_user_role?(user, participatory_space, broad_check:)
|
|
19
|
+
].any?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def participatory_process_user_role?(user, participatory_process = nil, broad_check: false)
|
|
23
|
+
return false unless Decidim.module_installed?(:participatory_processes)
|
|
24
|
+
return Decidim::ParticipatoryProcessUserRole.exists?(user:) if broad_check
|
|
25
|
+
return false unless participatory_process.is_a?(Decidim::ParticipatoryProcess)
|
|
26
|
+
|
|
27
|
+
Decidim::ParticipatoryProcessUserRole.exists?(user:, participatory_process:)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def assembly_user_role?(user, assembly = nil, broad_check: false)
|
|
31
|
+
return false unless Decidim.module_installed?(:assemblies)
|
|
32
|
+
return Decidim::AssemblyUserRole.exists?(user:) if broad_check
|
|
33
|
+
return false unless assembly.is_a?(Decidim::Assembly)
|
|
34
|
+
|
|
35
|
+
Decidim::AssemblyUserRole.exists?(user:, assembly:)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def conference_user_role?(user, conference = nil, broad_check: false)
|
|
39
|
+
return false unless Decidim.module_installed?(:conferences)
|
|
40
|
+
return Decidim::ConferenceUserRole.exists?(user:) if broad_check
|
|
41
|
+
return false unless conference.is_a?(Decidim::Conference)
|
|
42
|
+
|
|
43
|
+
Decidim::ConferenceUserRole.exists?(user:, conference:)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -16,7 +16,7 @@ module Decidim
|
|
|
16
16
|
# Finds the CTA button path to reuse it in other places.
|
|
17
17
|
def cta_button_path
|
|
18
18
|
if current_organization.cta_button_path.present?
|
|
19
|
-
current_organization.cta_button_path
|
|
19
|
+
"/#{current_organization.cta_button_path}"
|
|
20
20
|
elsif Decidim::ParticipatoryProcess.where(organization: current_organization).published.any?
|
|
21
21
|
decidim_participatory_processes.participatory_processes_path
|
|
22
22
|
elsif current_user
|
|
@@ -169,6 +169,20 @@ module Decidim
|
|
|
169
169
|
end
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
+
def current_url(params = request.parameters)
|
|
173
|
+
return url_for(params) if respond_to?(:current_participatory_space) || respond_to?(:current_component)
|
|
174
|
+
|
|
175
|
+
each_decidim_engine do |helpers|
|
|
176
|
+
return helpers.url_for(params)
|
|
177
|
+
rescue ActionController::UrlGenerationError
|
|
178
|
+
# Continue to next engine in case the URL is not available.
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
main_app.url_for(params)
|
|
182
|
+
rescue ActionController::UrlGenerationError
|
|
183
|
+
"#{request.base_url}#{"?#{params.to_query}" unless params.empty?}"
|
|
184
|
+
end
|
|
185
|
+
|
|
172
186
|
private
|
|
173
187
|
|
|
174
188
|
def empty_organization_description?
|
|
@@ -177,6 +191,20 @@ module Decidim
|
|
|
177
191
|
organization_description.blank? || organization_description == "<p></p>"
|
|
178
192
|
end
|
|
179
193
|
|
|
194
|
+
def each_decidim_engine
|
|
195
|
+
Rails.application.railties.each do |engine|
|
|
196
|
+
next unless engine.is_a?(Rails::Engine)
|
|
197
|
+
next unless engine.isolated?
|
|
198
|
+
next unless engine.engine_name.start_with?("decidim_")
|
|
199
|
+
next unless respond_to?(engine.engine_name)
|
|
200
|
+
|
|
201
|
+
yield public_send(engine.engine_name)
|
|
202
|
+
end
|
|
203
|
+
return unless respond_to?(:decidim)
|
|
204
|
+
|
|
205
|
+
yield decidim
|
|
206
|
+
end
|
|
207
|
+
|
|
180
208
|
def tag_builder
|
|
181
209
|
@tag_builder ||= ActionView::Helpers::TagHelper::TagBuilder.new(self)
|
|
182
210
|
end
|
|
@@ -35,7 +35,12 @@ module Decidim
|
|
|
35
35
|
data: { "external-link": "text-only" }
|
|
36
36
|
}.merge(map_html_options)
|
|
37
37
|
return link_to(map_url, html_options) do
|
|
38
|
-
|
|
38
|
+
# We also add the latitude and the longitude to prevent the Workbox cache to be overly aggressive when updating a map
|
|
39
|
+
image_tag decidim.static_map_path(
|
|
40
|
+
sgid: resource.to_sgid.to_s,
|
|
41
|
+
latitude: resource.latitude,
|
|
42
|
+
longitude: resource.longitude
|
|
43
|
+
), alt: "#{map_service_brand} - #{address_text}"
|
|
39
44
|
end
|
|
40
45
|
end
|
|
41
46
|
end
|
|
@@ -49,7 +49,7 @@ module Decidim
|
|
|
49
49
|
self,
|
|
50
50
|
element_class: "font-semibold underline",
|
|
51
51
|
active_class: "is-active",
|
|
52
|
-
container_options: { class: "space-y-4 break-inside-avoid" },
|
|
52
|
+
container_options: { class: "space-y-4 break-inside-avoid", role: :menu },
|
|
53
53
|
label: t("layouts.decidim.footer.decidim_title")
|
|
54
54
|
)
|
|
55
55
|
end
|
|
@@ -37,13 +37,22 @@ module Decidim
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
# Converts the blob and blob variant references to blob URLs.
|
|
41
|
+
def decidim_rich_text(html, options = {})
|
|
42
|
+
renderer = Decidim::ContentProcessor.renderer_klass(:blob).constantize.new(html)
|
|
43
|
+
renderer.render(options)
|
|
44
|
+
end
|
|
45
|
+
|
|
40
46
|
def decidim_sanitize_editor(html, options = {})
|
|
41
47
|
content_tag(:div, decidim_sanitize(html, options), class: %w(rich-text-display))
|
|
42
48
|
end
|
|
43
49
|
|
|
44
50
|
def decidim_sanitize_editor_admin(html, options = {})
|
|
45
51
|
html = Decidim::IframeDisabler.new(html, options).perform
|
|
46
|
-
decidim_sanitize_editor(
|
|
52
|
+
decidim_sanitize_editor(
|
|
53
|
+
decidim_rich_text(html),
|
|
54
|
+
{ scrubber: Decidim::AdminInputScrubber.new }.merge(options)
|
|
55
|
+
)
|
|
47
56
|
end
|
|
48
57
|
|
|
49
58
|
def decidim_html_escape(text)
|
|
@@ -51,7 +60,7 @@ module Decidim
|
|
|
51
60
|
end
|
|
52
61
|
|
|
53
62
|
def decidim_url_escape(text)
|
|
54
|
-
decidim_html_escape(text).sub(
|
|
63
|
+
decidim_html_escape(text).sub(/^\s*javascript:/, "")
|
|
55
64
|
end
|
|
56
65
|
|
|
57
66
|
def decidim_sanitize_translated(text)
|
|
@@ -53,11 +53,14 @@ module Decidim
|
|
|
53
53
|
# options - An optional Hash with options:
|
|
54
54
|
#
|
|
55
55
|
# Returns nothing.
|
|
56
|
-
def scopes_select_field(form, name, root: false, options: {})
|
|
56
|
+
def scopes_select_field(form, name, root: false, options: {}, html_options: {})
|
|
57
|
+
options = options.merge(include_blank: I18n.t("decidim.scopes.prompt")) unless options.has_key?(:include_blank)
|
|
58
|
+
|
|
57
59
|
form.select(
|
|
58
60
|
name,
|
|
59
61
|
ordered_scopes_descendants_for_select(root),
|
|
60
|
-
options
|
|
62
|
+
options,
|
|
63
|
+
html_options
|
|
61
64
|
)
|
|
62
65
|
end
|
|
63
66
|
|
|
@@ -138,6 +138,7 @@ module Decidim
|
|
|
138
138
|
Decidim::Proposals::Proposal
|
|
139
139
|
Decidim::Surveys::Survey
|
|
140
140
|
Decidim::Assembly
|
|
141
|
+
Decidim::Conference
|
|
141
142
|
Decidim::Initiative
|
|
142
143
|
Decidim::ParticipatoryProcess
|
|
143
144
|
).select do |klass|
|
|
@@ -154,7 +155,16 @@ module Decidim
|
|
|
154
155
|
end
|
|
155
156
|
|
|
156
157
|
def self.publicable_public_resource_types
|
|
157
|
-
@publicable_public_resource_types ||= public_resource_types
|
|
158
|
+
@publicable_public_resource_types ||= public_resource_types
|
|
159
|
+
.select { |klass| klass.constantize.column_names.include?("published_at") } - publicable_exceptions
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def self.publicable_exceptions
|
|
163
|
+
@publicable_exceptions = %w(
|
|
164
|
+
Decidim::Blogs::Post
|
|
165
|
+
).select do |klass|
|
|
166
|
+
klass.safe_constantize.present?
|
|
167
|
+
end
|
|
158
168
|
end
|
|
159
169
|
|
|
160
170
|
def self.ransackable_scopes(auth_object = nil)
|
|
@@ -59,7 +59,6 @@ const createDropdown = (component) => {
|
|
|
59
59
|
const dropdownOptions = {};
|
|
60
60
|
dropdownOptions.dropdown = component.dataset.target;
|
|
61
61
|
dropdownOptions.hover = component.dataset.hover === "true";
|
|
62
|
-
dropdownOptions.isOpen = component.dataset.open === "true";
|
|
63
62
|
dropdownOptions.autoClose = component.dataset.autoClose === "true";
|
|
64
63
|
|
|
65
64
|
// This snippet allows to disable the dropdown based on the current viewport
|
|
@@ -78,6 +77,17 @@ const createDropdown = (component) => {
|
|
|
78
77
|
return
|
|
79
78
|
}
|
|
80
79
|
|
|
80
|
+
dropdownOptions.isOpen = component.dataset.open === "true";
|
|
81
|
+
|
|
82
|
+
const isOpen = Object.keys(screens).some((key) => {
|
|
83
|
+
if (!isScreenSize(key)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return Boolean(component.dataset[`open-${key}`.replace(/-([a-z])/g, (str) => str[1].toUpperCase())]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
dropdownOptions.isOpen = dropdownOptions.isOpen || isOpen;
|
|
90
|
+
|
|
81
91
|
if (!component.id) {
|
|
82
92
|
// when component has no id, we enforce to have it one
|
|
83
93
|
component.id = `dropdown-${Math.random().toString(36).substring(7)}`
|
|
@@ -104,20 +114,6 @@ const createDropdown = (component) => {
|
|
|
104
114
|
});
|
|
105
115
|
}
|
|
106
116
|
|
|
107
|
-
// Disable focus on children elements so we can pass the AXE accessibility tests
|
|
108
|
-
const dropdownMenu = document.getElementById(dropdownOptions.dropdown);
|
|
109
|
-
if (dropdownMenu.getAttribute("aria-hidden") === "true") {
|
|
110
|
-
dropdownMenu.
|
|
111
|
-
querySelectorAll("a, input, button").
|
|
112
|
-
forEach((element) => { element.tabIndex = -1 })
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
component.addEventListener("click", () => {
|
|
116
|
-
dropdownMenu.
|
|
117
|
-
querySelectorAll("a, input, button").
|
|
118
|
-
forEach((element) => { element.tabIndex = 0 })
|
|
119
|
-
})
|
|
120
|
-
|
|
121
117
|
Dropdowns.render(component.id, dropdownOptions);
|
|
122
118
|
}
|
|
123
119
|
|