decidim-core 0.29.0 → 0.29.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/cells/decidim/activity_cell.rb +0 -3
- 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/newsletter_templates/image_text_cta_cell.rb +1 -1
- data/app/cells/decidim/translation_bar/show.erb +2 -2
- 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/sanitize_helper.rb +11 -2
- data/app/helpers/decidim/scopes_helper.rb +3 -2
- data/app/models/decidim/action_log.rb +11 -1
- data/app/models/decidim/attachment.rb +1 -1
- 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/_labels.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/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 +2 -2
- 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/config/locales/ar.yml +16 -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 +7 -1
- data/config/locales/de.yml +20 -16
- data/config/locales/el.yml +7 -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 +7 -3
- data/config/locales/fr.yml +6 -2
- data/config/locales/ga-IE.yml +9 -0
- data/config/locales/gl.yml +8 -1
- data/config/locales/hu.yml +3 -4
- data/config/locales/id-ID.yml +8 -0
- data/config/locales/is-IS.yml +8 -1
- data/config/locales/it.yml +19 -0
- data/config/locales/ja.yml +18 -16
- data/config/locales/lb.yml +9 -0
- data/config/locales/lt.yml +5 -2
- data/config/locales/lv.yml +8 -0
- data/config/locales/nl.yml +10 -1
- data/config/locales/no.yml +9 -0
- data/config/locales/pl.yml +1 -2
- data/config/locales/pt-BR.yml +244 -1
- data/config/locales/pt.yml +14 -0
- data/config/locales/ro-RO.yml +319 -180
- data/config/locales/ru.yml +8 -0
- data/config/locales/sk.yml +9 -1
- data/config/locales/sv.yml +541 -96
- data/config/locales/tr-TR.yml +10 -1
- data/config/locales/uk.yml +8 -1
- data/config/locales/zh-CN.yml +9 -0
- data/config/locales/zh-TW.yml +8 -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 +107 -9
- 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: 83ba22655575833dce2ce20e91060aa195abccf10cd5d185dbadbc04e79fcd93
|
4
|
+
data.tar.gz: a53c89d6b0c01046408b2872119406ffbd1a80a50b943256b872c8575b069e4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07db0787cc696b27044eb8765477b338a16f7263cd29d9231dfd8e7145f5c4b63b19753a90b4d35c5e7614c1a69d47104435fcb2ecf12badea9a1163709ccbef
|
7
|
+
data.tar.gz: 034e07f956b0ad613172afdd3a56cbb3e37e273555537919073bf75b63dfe8b2ab7ec5502ecf87fb224cd5d525ad009a01e0db6742815ce61eec643c0fa1f1ae
|
@@ -105,9 +105,6 @@ module Decidim
|
|
105
105
|
hash << I18n.locale.to_s
|
106
106
|
hash << model.class.name.underscore
|
107
107
|
hash << model.cache_key_with_version if model.respond_to?(:cache_key_with_version)
|
108
|
-
if (author_cell = author)
|
109
|
-
hash.push(Digest::MD5.hexdigest(author_cell.send(:cache_hash)))
|
110
|
-
end
|
111
108
|
|
112
109
|
hash.join(Decidim.cache_key_separator)
|
113
110
|
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 %>
|
@@ -47,8 +47,26 @@ module Decidim
|
|
47
47
|
@context_actions_options ||= options[:context_actions].map(&:to_sym)
|
48
48
|
end
|
49
49
|
|
50
|
+
def profile_minicard
|
51
|
+
render
|
52
|
+
end
|
53
|
+
|
50
54
|
private
|
51
55
|
|
56
|
+
# If the options hash has the demo key it means we are in the decidim-design engine,
|
57
|
+
# so it is not a real-world scenario with actual users
|
58
|
+
def data
|
59
|
+
@data ||= begin
|
60
|
+
internal_data = { author: true }
|
61
|
+
if has_tooltip? && !options.has_key?(:demo)
|
62
|
+
internal_data["remote_tooltip"] = true
|
63
|
+
internal_data["tooltip-url"] = decidim.profile_tooltip_path(raw_model.nickname)
|
64
|
+
end
|
65
|
+
|
66
|
+
internal_data
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
52
70
|
def layout
|
53
71
|
@layout ||= LAYOUTS.include?(options[:layout]) ? options[:layout] : :default
|
54
72
|
end
|
@@ -160,5 +178,13 @@ module Decidim
|
|
160
178
|
def resource_name
|
161
179
|
@resource_name ||= from_context.class.name.demodulize.underscore
|
162
180
|
end
|
181
|
+
|
182
|
+
def has_tooltip?
|
183
|
+
return false if model.deleted?
|
184
|
+
return false if model.respond_to?(:blocked?) && model.blocked?
|
185
|
+
return true if options.has_key?(:tooltip)
|
186
|
+
|
187
|
+
model.has_tooltip?
|
188
|
+
end
|
163
189
|
end
|
164
190
|
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 %>
|
@@ -70,6 +70,10 @@ module Decidim
|
|
70
70
|
|
71
71
|
# DiffRenderer class for the current_version's item; falls back to `BaseDiffRenderer`.
|
72
72
|
def diff_renderer_class
|
73
|
+
renderer_class = "#{current_version.item_type}DiffRenderer".safe_constantize
|
74
|
+
|
75
|
+
return renderer_class if renderer_class
|
76
|
+
|
73
77
|
if current_version.item_type.deconstantize == "Decidim"
|
74
78
|
"#{current_version.item_type.pluralize}::DiffRenderer".constantize
|
75
79
|
else
|
@@ -69,7 +69,7 @@ module Decidim
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def user_has_verified_groups?
|
72
|
-
current_user && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
|
72
|
+
current_user && current_organization.user_groups_enabled? && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
|
73
73
|
end
|
74
74
|
|
75
75
|
def endorse_translated
|
@@ -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
|
@@ -54,6 +54,7 @@ module Decidim
|
|
54
54
|
emendation.body = { I18n.locale => form.emendation_params.with_indifferent_access[:body] }
|
55
55
|
emendation.component = amendable.component
|
56
56
|
emendation.add_author(current_user, user_group)
|
57
|
+
emendation.category = amendable.category if amendable.respond_to?(:category)
|
57
58
|
emendation.save!
|
58
59
|
emendation
|
59
60
|
end
|
@@ -37,6 +37,9 @@ module Decidim
|
|
37
37
|
current_user.name = ""
|
38
38
|
current_user.nickname = ""
|
39
39
|
current_user.email = ""
|
40
|
+
current_user.personal_url = ""
|
41
|
+
current_user.about = ""
|
42
|
+
current_user.notifications_sending_frequency = "none"
|
40
43
|
current_user.delete_reason = @form.delete_reason
|
41
44
|
current_user.admin = false if current_user.admin?
|
42
45
|
current_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
|
@@ -140,8 +140,36 @@ module Decidim
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
+
def current_url(params = request.parameters)
|
144
|
+
return url_for(params) if respond_to?(:current_participatory_space) || respond_to?(:current_component)
|
145
|
+
|
146
|
+
each_decidim_engine do |helpers|
|
147
|
+
return helpers.url_for(params)
|
148
|
+
rescue ActionController::UrlGenerationError
|
149
|
+
# Continue to next engine in case the URL is not available.
|
150
|
+
end
|
151
|
+
|
152
|
+
main_app.url_for(params)
|
153
|
+
rescue ActionController::UrlGenerationError
|
154
|
+
"#{request.base_url}#{"?#{params.to_query}" unless params.empty?}"
|
155
|
+
end
|
156
|
+
|
143
157
|
private
|
144
158
|
|
159
|
+
def each_decidim_engine
|
160
|
+
Rails.application.railties.each do |engine|
|
161
|
+
next unless engine.is_a?(Rails::Engine)
|
162
|
+
next unless engine.isolated?
|
163
|
+
next unless engine.engine_name.start_with?("decidim_")
|
164
|
+
next unless respond_to?(engine.engine_name)
|
165
|
+
|
166
|
+
yield public_send(engine.engine_name)
|
167
|
+
end
|
168
|
+
return unless respond_to?(:decidim)
|
169
|
+
|
170
|
+
yield decidim
|
171
|
+
end
|
172
|
+
|
145
173
|
def tag_builder
|
146
174
|
@tag_builder ||= ActionView::Helpers::TagHelper::TagBuilder.new(self)
|
147
175
|
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
|
@@ -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, **)
|
42
|
+
renderer = Decidim::ContentProcessor.renderer_klass(:blob).constantize.new(html)
|
43
|
+
renderer.render(**)
|
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,13 +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
57
|
options = options.merge(include_blank: I18n.t("decidim.scopes.prompt")) unless options.has_key?(:include_blank)
|
58
58
|
|
59
59
|
form.select(
|
60
60
|
name,
|
61
61
|
ordered_scopes_descendants_for_select(root),
|
62
|
-
options
|
62
|
+
options,
|
63
|
+
html_options
|
63
64
|
)
|
64
65
|
end
|
65
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)
|
@@ -53,21 +53,31 @@ $(() => {
|
|
53
53
|
}
|
54
54
|
|
55
55
|
$(document).on("click.zf.trigger", (event) => {
|
56
|
-
|
57
|
-
const
|
58
|
-
|
59
|
-
if
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
});
|
56
|
+
// Try to get the <a> directly or find the closest parent <a>
|
57
|
+
const $target = $(event.target).closest("a");
|
58
|
+
|
59
|
+
// Check if an <a> was found
|
60
|
+
if (!$target) {
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
|
64
|
+
const dialogTarget = `#${$target.data("dialog-open")}`;
|
65
|
+
const redirectUrl = $target.data("redirectUrl");
|
66
|
+
|
67
|
+
if (!dialogTarget || !redirectUrl) {
|
68
|
+
return;
|
70
69
|
}
|
70
|
+
|
71
|
+
$("<input type='hidden' />").
|
72
|
+
attr("id", "redirect_url").
|
73
|
+
attr("name", "redirect_url").
|
74
|
+
attr("value", redirectUrl).
|
75
|
+
appendTo(`${dialogTarget} form`);
|
76
|
+
|
77
|
+
$(`${dialogTarget} a`).attr("href", (index, href) => {
|
78
|
+
const querystring = jQuery.param({"redirect_url": redirectUrl});
|
79
|
+
return href + (href.match(/\?/) ? "&" : "?") + querystring;
|
80
|
+
});
|
71
81
|
});
|
72
82
|
|
73
83
|
$(document).on("closed.zf.reveal", (event) => {
|
@@ -21,6 +21,7 @@ const updateActiveUploads = (modal) => {
|
|
21
21
|
const files = document.querySelector(`[data-active-uploads=${modal.modal.id}]`)
|
22
22
|
const previousId = Array.from(files.querySelectorAll("[type=hidden][id]"))
|
23
23
|
const isMultiple = modal.options.multiple
|
24
|
+
const isTitled = modal.options.titled
|
24
25
|
|
25
26
|
// fastest way to clean children nodes
|
26
27
|
files.textContent = ""
|
@@ -34,16 +35,26 @@ const updateActiveUploads = (modal) => {
|
|
34
35
|
let hidden = ""
|
35
36
|
if (file.hiddenField) {
|
36
37
|
// if there is hiddenField, this file is new
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
let fileField = null;
|
39
|
+
if (isMultiple) {
|
40
|
+
fileField = `${modal.options.resourceName}[${modal.options.addAttribute}][${ix}][file]`
|
41
|
+
} else if (isTitled) {
|
42
|
+
fileField = `${modal.options.resourceName}[${modal.options.addAttribute}][file]`
|
43
|
+
} else {
|
44
|
+
fileField = `${modal.options.resourceName}[${modal.options.addAttribute}]`;
|
45
|
+
}
|
40
46
|
|
41
47
|
hidden = `<input type="hidden" name="${fileField}" value="${file.hiddenField}" />`
|
42
48
|
} else {
|
43
49
|
// otherwise, we keep the attachmentId
|
44
|
-
|
45
|
-
|
46
|
-
|
50
|
+
let fileField = null;
|
51
|
+
if (isMultiple) {
|
52
|
+
fileField = `${modal.options.resourceName}[${modal.options.addAttribute}][${ix}][id]`;
|
53
|
+
} else if (isTitled) {
|
54
|
+
fileField = `${modal.options.resourceName}[${modal.options.addAttribute}][id]`;
|
55
|
+
} else {
|
56
|
+
fileField = `${modal.options.resourceName}[${modal.options.addAttribute}]`;
|
57
|
+
}
|
47
58
|
|
48
59
|
// convert all node attributes to string
|
49
60
|
const attributes = Array.from(previousId.find(({ id }) => id === file.attachmentId).attributes).reduce((acc, { name, value }) => `${acc} ${name}="${value}"`, "")
|
@@ -51,10 +62,12 @@ const updateActiveUploads = (modal) => {
|
|
51
62
|
hidden += `<input type="hidden" name="${fileField}" value="${file.attachmentId}" />`
|
52
63
|
}
|
53
64
|
|
54
|
-
if (
|
65
|
+
if (isTitled) {
|
55
66
|
const titleValue = modal.modal.querySelectorAll('input[type="text"]')[ix].value
|
56
67
|
// NOTE - Renaming the attachment is not supported when multiple uploader is disabled
|
57
|
-
const titleField =
|
68
|
+
const titleField = isMultiple
|
69
|
+
? `${modal.options.resourceName}[${modal.options.addAttribute}][${ix}][title]`
|
70
|
+
: `${modal.options.resourceName}[${modal.options.addAttribute}][title]`
|
58
71
|
hidden += `<input type="hidden" name="${titleField}" value="${escapeQuotes(titleValue)}" />`
|
59
72
|
|
60
73
|
title = titleValue
|
@@ -77,6 +77,9 @@ export default class UploadModal {
|
|
77
77
|
uploader.upload.create((error, blob) => {
|
78
78
|
if (error) {
|
79
79
|
uploader.errors = [error]
|
80
|
+
this.uploadItems.replaceChild(this.createUploadItem(file, [error], { value: 100 }), item);
|
81
|
+
this.updateDropZone();
|
82
|
+
|
80
83
|
} else {
|
81
84
|
// attach the file hash to submit the form, when the file has been uploaded
|
82
85
|
file.hiddenField = blob.signed_id
|
@@ -69,6 +69,7 @@ import handleNotificationActions from "src/decidim/notifications_actions"
|
|
69
69
|
import RemoteModal from "src/decidim/remote_modal"
|
70
70
|
import selectActiveIdentity from "src/decidim/identity_selector_dialog"
|
71
71
|
import createTooltip from "src/decidim/tooltips"
|
72
|
+
import fetchRemoteTooltip from "src/decidim/remote_tooltips"
|
72
73
|
import createToggle from "src/decidim/toggle"
|
73
74
|
import {
|
74
75
|
createAccordion,
|
@@ -195,6 +196,8 @@ const initializer = (element = document) => {
|
|
195
196
|
// Initialize data-toggles
|
196
197
|
element.querySelectorAll("[data-toggle]").forEach((elem) => createToggle(elem))
|
197
198
|
|
199
|
+
element.querySelectorAll("[data-remote-tooltip]").forEach((elem) => fetchRemoteTooltip(elem))
|
200
|
+
|
198
201
|
element.querySelectorAll(".new_report").forEach((elem) => changeReportFormBehavior(elem))
|
199
202
|
}
|
200
203
|
|