decidim-core 0.28.4 → 0.28.6
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/diff_cell.rb +4 -0
- data/app/cells/decidim/newsletter_templates/image_text_cta_cell.rb +1 -1
- data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +5 -3
- data/app/cells/decidim/resource_types_filter/show.erb +1 -1
- data/app/cells/decidim/resource_types_filter_cell.rb +6 -6
- data/app/cells/decidim/translation_bar/show.erb +3 -3
- data/app/cells/decidim/translation_bar_cell.rb +1 -1
- data/app/cells/decidim/user_activity/show.erb +1 -1
- data/app/commands/decidim/create_omniauth_registration.rb +14 -8
- data/app/commands/decidim/destroy_account.rb +3 -0
- data/app/commands/decidim/search.rb +14 -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 +6 -2
- data/app/controllers/decidim/reports_controller.rb +1 -1
- data/app/controllers/decidim/user_activities_controller.rb +1 -1
- data/app/forms/decidim/account_form.rb +5 -2
- 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/map_helper.rb +6 -1
- data/app/helpers/decidim/orders_helper.rb +2 -1
- data/app/helpers/decidim/participatory_space_helpers.rb +1 -1
- data/app/helpers/decidim/sanitize_helper.rb +11 -2
- data/app/models/decidim/attachment.rb +1 -1
- data/app/models/decidim/user.rb +0 -4
- data/app/models/decidim/user_base_entity.rb +4 -0
- data/app/packs/src/decidim/append_redirect_url_to_modals.js +14 -6
- data/app/packs/src/decidim/direct_uploads/upload_field.js +21 -8
- data/app/packs/src/decidim/index.js +5 -0
- data/app/packs/src/decidim/map/provider/here.js +1 -1
- 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/_hashtags.scss +5 -0
- data/app/packs/stylesheets/decidim/_header.scss +20 -2
- data/app/packs/stylesheets/decidim/_profile.scss +1 -1
- data/app/packs/stylesheets/decidim/_progress-bar.scss +1 -1
- data/app/packs/stylesheets/decidim/application.scss +1 -0
- data/app/packs/stylesheets/decidim/legacy/conference-diploma.scss +2 -1
- data/app/presenters/decidim/attachment_presenter.rb +1 -1
- data/app/presenters/decidim/log/user_presenter.rb +1 -0
- data/app/services/decidim/base_diff_renderer.rb +28 -2
- data/app/services/decidim/email_notification_generator.rb +14 -5
- data/app/services/decidim/static_map_generator.rb +1 -1
- data/app/views/decidim/last_activities/index.html.erb +1 -1
- data/app/views/decidim/pages/_tabbed.html.erb +2 -2
- data/app/views/decidim/reported_mailer/hide.html.erb +1 -1
- data/app/views/decidim/reported_mailer/report.html.erb +1 -1
- data/app/views/decidim/searches/_count.html.erb +1 -1
- data/app/views/decidim/searches/_filters.html.erb +40 -38
- data/app/views/decidim/shared/_orders.html.erb +2 -2
- data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +1 -1
- data/config/locales/ar.yml +55 -12
- data/config/locales/bg.yml +17 -8
- data/config/locales/bn-BD.yml +1 -0
- data/config/locales/bs-BA.yml +100 -0
- data/config/locales/ca-IT.yml +2115 -0
- data/config/locales/ca.yml +69 -22
- data/config/locales/cs.yml +62 -15
- data/config/locales/de.yml +67 -20
- data/config/locales/el.yml +17 -2
- data/config/locales/en.yml +47 -0
- data/config/locales/eo.yml +2 -0
- data/config/locales/es-MX.yml +61 -14
- data/config/locales/es-PY.yml +65 -18
- data/config/locales/es.yml +72 -25
- data/config/locales/eu.yml +308 -250
- data/config/locales/fi-plain.yml +50 -11
- data/config/locales/fi.yml +87 -48
- data/config/locales/fr-CA.yml +57 -10
- data/config/locales/fr.yml +55 -8
- data/config/locales/ga-IE.yml +11 -0
- data/config/locales/gl.yml +33 -2
- data/config/locales/hu.yml +17 -10
- data/config/locales/id-ID.yml +32 -3
- data/config/locales/is-IS.yml +18 -2
- data/config/locales/it.yml +84 -14
- data/config/locales/ja.yml +70 -23
- data/config/locales/lb.yml +32 -7
- data/config/locales/lt.yml +9 -3
- data/config/locales/lv.yml +26 -2
- data/config/locales/nl.yml +33 -6
- data/config/locales/no.yml +25 -0
- data/config/locales/pl.yml +15 -6
- data/config/locales/pt-BR.yml +18 -8
- data/config/locales/pt.yml +31 -0
- data/config/locales/ro-RO.yml +475 -207
- data/config/locales/ru.yml +33 -1
- data/config/locales/sk.yml +39 -7
- data/config/locales/sl.yml +4 -0
- data/config/locales/sr-CS.yml +2 -0
- data/config/locales/sv.yml +35 -16
- data/config/locales/tr-TR.yml +32 -8
- data/config/locales/uk.yml +20 -2
- data/config/locales/zh-CN.yml +27 -2
- data/config/locales/zh-TW.yml +14 -0
- 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 +16 -2
- data/lib/decidim/attributes.rb +2 -0
- data/lib/decidim/content_parsers/blob_parser.rb +95 -0
- data/lib/decidim/content_parsers/user_parser.rb +1 -1
- 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 +29 -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 +15 -2
- data/lib/decidim/core/test/shared_examples/reports_examples.rb +48 -6
- data/lib/decidim/core/test/shared_examples/uncommentable_component_examples.rb +26 -0
- data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +26 -0
- data/lib/decidim/core/version.rb +1 -1
- 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/map/provider/dynamic_map/here.rb +1 -40
- data/lib/decidim/map/provider/static_map/here.rb +34 -0
- data/lib/decidim/nicknamizable.rb +1 -1
- data/lib/decidim/participatory_space_user.rb +4 -0
- data/lib/decidim/query_extensions.rb +0 -26
- data/lib/decidim/reportable.rb +6 -2
- data/lib/decidim/settings_manifest.rb +2 -0
- data/lib/decidim/translatable_attributes.rb +10 -1
- data/lib/decidim/view_model.rb +1 -0
- data/lib/tasks/upgrade/decidim_fix_categorization.rake +34 -8
- data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +23 -20
- metadata +30 -8
- data/app/packs/src/decidim/vendor/leaflet-tilelayer-here.js +0 -212
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88c7b06f4bb2ad092e2e306434bd645d1f27f8e467bc34ab341093f1213ef70b
|
4
|
+
data.tar.gz: 45be0ca0bc0b4f11581b1e12c931cbc1c9a80a321ed9c7e1822bc79ff7d9d59f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79b66628f6569dd4f570d3388bf185583b5d9fe1edee9545da9948cb8371e9b7722edd651db0805a73aeeb272e8b8c2df4c55b07b9237da062761992e43e8c13
|
7
|
+
data.tar.gz: 969da677904a158b3b7744f58a834162dbc10c6b8d94a609aac305744a6c061b439117793d52d964edcbbfe656476239651ac0d6dc34d32c22fc3da79f0b32b6
|
@@ -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
|
@@ -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
|
@@ -3,7 +3,9 @@
|
|
3
3
|
<%= render :metadata %>
|
4
4
|
<%= cell "decidim/content_blocks/menu_breadcrumb_last_activity", model, hide_participatory_space: true %>
|
5
5
|
</div>
|
6
|
-
<
|
7
|
-
|
8
|
-
|
6
|
+
<nav role="navigation" aria-label="<%= t("decidim.accessibility.secondary_menu") %>">
|
7
|
+
<ul class="menu-bar__secondary-dropdown__menu">
|
8
|
+
<%= render :links %>
|
9
|
+
</ul>
|
10
|
+
</nav>
|
9
11
|
</div>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<ul id="dropdown-menu-resource">
|
12
12
|
<% resource_types.each do |resource_type| %>
|
13
13
|
<li role="menuitem">
|
14
|
-
<%= link_to
|
14
|
+
<%= link_to filter_url(resource_type[0]), class: "filter#{" is-active" if filter_param == resource_type[0]}" do %>
|
15
15
|
<span class="sr-only"><%= resource_type[1] %></span>
|
16
16
|
<%= text_with_resource_icon(*resource_type) %>
|
17
17
|
<% end %>
|
@@ -29,8 +29,12 @@ module Decidim
|
|
29
29
|
options[:id] || "filters"
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
options[:
|
32
|
+
def filter_url(resource_type)
|
33
|
+
if options[:source] == :last_activities
|
34
|
+
last_activities_path(filter: { with_resource_type: resource_type })
|
35
|
+
else
|
36
|
+
profile_activity_path(nickname: params[:nickname], filter: { resource_type: })
|
37
|
+
end
|
34
38
|
end
|
35
39
|
|
36
40
|
def filter_param_key
|
@@ -41,10 +45,6 @@ module Decidim
|
|
41
45
|
@filter_param ||= params.dig(:filter, filter_param_key) || all_types_key
|
42
46
|
end
|
43
47
|
|
44
|
-
def filter
|
45
|
-
options[:filter]
|
46
|
-
end
|
47
|
-
|
48
48
|
def all_resource_types_option
|
49
49
|
[all_types_key, I18n.t("all", scope: "decidim.last_activities")]
|
50
50
|
end
|
@@ -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>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="profile__activity">
|
2
|
-
<%= cell "decidim/resource_types_filter", resource_types,
|
2
|
+
<%= cell "decidim/resource_types_filter", resource_types, source: :profile_activity %>
|
3
3
|
<div class="profile__activity__container" id="activities-container">
|
4
4
|
<% if activities.length == 0 %>
|
5
5
|
<%= cell "decidim/announcement", t("decidim.user_activity.index.no_activities_warning") %>
|
@@ -45,6 +45,8 @@ module Decidim
|
|
45
45
|
|
46
46
|
attr_reader :form, :verified_email
|
47
47
|
|
48
|
+
REGEXP_SANITIZER = /[<>?%&\^*#@()\[\]=+:;"{}\\|]/
|
49
|
+
|
48
50
|
def create_or_find_user
|
49
51
|
@user = User.find_or_initialize_by(
|
50
52
|
email: verified_email,
|
@@ -63,16 +65,11 @@ module Decidim
|
|
63
65
|
@user.save!
|
64
66
|
else
|
65
67
|
@user.email = (verified_email || form.email)
|
66
|
-
@user.name = form.name
|
68
|
+
@user.name = form.name.gsub(REGEXP_SANITIZER, "")
|
67
69
|
@user.nickname = form.normalized_nickname
|
68
70
|
@user.newsletter_notifications_at = nil
|
69
71
|
@user.password = SecureRandom.hex
|
70
|
-
if form.avatar_url.present?
|
71
|
-
url = URI.parse(form.avatar_url)
|
72
|
-
filename = File.basename(url.path)
|
73
|
-
file = url.open
|
74
|
-
@user.avatar.attach(io: file, filename:)
|
75
|
-
end
|
72
|
+
attach_avatar(form.avatar_url) if form.avatar_url.present?
|
76
73
|
@user.skip_confirmation! if verified_email
|
77
74
|
@user.tos_agreement = "1"
|
78
75
|
@user.save!
|
@@ -81,6 +78,15 @@ module Decidim
|
|
81
78
|
end
|
82
79
|
end
|
83
80
|
|
81
|
+
def attach_avatar(avatar_url)
|
82
|
+
url = URI.parse(avatar_url)
|
83
|
+
filename = File.basename(url.path)
|
84
|
+
file = url.open
|
85
|
+
@user.avatar.attach(io: file, filename:)
|
86
|
+
rescue OpenURI::HTTPError, Errno::ECONNREFUSED
|
87
|
+
# Do not attach the avatar, as it fails to fetch it.
|
88
|
+
end
|
89
|
+
|
84
90
|
def create_identity
|
85
91
|
@user.identities.create!(
|
86
92
|
provider: form.provider,
|
@@ -126,7 +132,7 @@ module Decidim
|
|
126
132
|
provider: form.provider,
|
127
133
|
uid: form.uid,
|
128
134
|
email: form.email,
|
129
|
-
name: form.name,
|
135
|
+
name: form.name.gsub(REGEXP_SANITIZER, ""),
|
130
136
|
nickname: form.normalized_nickname,
|
131
137
|
avatar_url: form.avatar_url,
|
132
138
|
raw_data: form.raw_data
|
@@ -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
|
@@ -37,6 +37,12 @@ module Decidim
|
|
37
37
|
klass.order_by_id_list(result_ids.take(HIGHLIGHTED_RESULTS_COUNT))
|
38
38
|
end
|
39
39
|
|
40
|
+
uncommentable_resources = uncommentable_resources(results) if results.present?
|
41
|
+
if uncommentable_resources.present?
|
42
|
+
results -= uncommentable_resources
|
43
|
+
results_count -= uncommentable_resources.count
|
44
|
+
end
|
45
|
+
|
40
46
|
results_by_type.update(class_name => {
|
41
47
|
count: results_count,
|
42
48
|
results:
|
@@ -89,5 +95,13 @@ module Decidim
|
|
89
95
|
query = query.global_search(I18n.transliterate(term)) if term.present?
|
90
96
|
query
|
91
97
|
end
|
98
|
+
|
99
|
+
def uncommentable_resources(results)
|
100
|
+
results.where(id: results.select { |obj| related_uncommentable_resources?(obj) }.map(&:id))
|
101
|
+
end
|
102
|
+
|
103
|
+
def related_uncommentable_resources?(object)
|
104
|
+
object.respond_to?(:commentable) && !object.commentable.commentable?
|
105
|
+
end
|
92
106
|
end
|
93
107
|
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
|
@@ -24,7 +24,11 @@ module Decidim
|
|
24
24
|
def show
|
25
25
|
return redirect_to profile_members_path if profile_holder.is_a?(Decidim::UserGroup)
|
26
26
|
|
27
|
-
redirect_to profile_activity_path(nickname: params[:nickname])
|
27
|
+
redirect_to profile_activity_path(nickname: params[:nickname].downcase)
|
28
|
+
end
|
29
|
+
|
30
|
+
def tooltip
|
31
|
+
render json: { data: cell("decidim/author", profile_holder.presenter).profile_minicard }
|
28
32
|
end
|
29
33
|
|
30
34
|
def following
|
@@ -112,7 +116,7 @@ module Decidim
|
|
112
116
|
def profile_holder
|
113
117
|
return if params[:nickname].blank?
|
114
118
|
|
115
|
-
@profile_holder ||= Decidim::UserBaseEntity.find_by("
|
119
|
+
@profile_holder ||= Decidim::UserBaseEntity.find_by("nickname = ? AND decidim_organization_id = ?", params[:nickname].downcase, current_organization.id)
|
116
120
|
end
|
117
121
|
end
|
118
122
|
end
|
@@ -16,7 +16,7 @@ module Decidim
|
|
16
16
|
CreateReport.call(@form, reportable, current_user) do
|
17
17
|
on(:ok) do
|
18
18
|
flash[:notice] = I18n.t("decidim.reports.create.success")
|
19
|
-
|
19
|
+
redirect_to reportable.reload.reported_content_url
|
20
20
|
end
|
21
21
|
|
22
22
|
on(:invalid) do
|
@@ -22,7 +22,7 @@ module Decidim
|
|
22
22
|
def user
|
23
23
|
return unless params[:nickname]
|
24
24
|
|
25
|
-
@user ||= current_organization.users.find_by("
|
25
|
+
@user ||= current_organization.users.find_by("nickname = ?", params[:nickname].downcase)
|
26
26
|
end
|
27
27
|
|
28
28
|
def activities
|
@@ -21,7 +21,10 @@ module Decidim
|
|
21
21
|
|
22
22
|
validates :name, presence: true, format: { with: Decidim::User::REGEXP_NAME }
|
23
23
|
validates :email, presence: true, "valid_email_2/email": { disposable: true }
|
24
|
-
validates :nickname,
|
24
|
+
validates :nickname,
|
25
|
+
presence: true,
|
26
|
+
format: { with: Decidim::User::REGEXP_NICKNAME, message: :format },
|
27
|
+
length: { maximum: Decidim::User.nickname_max_length }
|
25
28
|
|
26
29
|
validates :nickname, length: { maximum: Decidim::User.nickname_max_length, allow_blank: true }
|
27
30
|
validates :password, password: { name: :name, email: :email, username: :nickname }, if: -> { password.present? }
|
@@ -66,7 +69,7 @@ module Decidim
|
|
66
69
|
|
67
70
|
def unique_nickname
|
68
71
|
return true if Decidim::UserBaseEntity.where(
|
69
|
-
"decidim_organization_id = ? AND
|
72
|
+
"decidim_organization_id = ? AND nickname = ? ",
|
70
73
|
context.current_organization.id,
|
71
74
|
nickname.downcase
|
72
75
|
).where.not(id: context.current_user.id).empty?
|
@@ -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
|
@@ -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
|
@@ -28,7 +28,7 @@ module Decidim
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def participatory_space_floating_help
|
31
|
-
return if help_section.blank?
|
31
|
+
return if help_section.blank? || strip_tags(translated_attribute(help_section).html_safe).blank?
|
32
32
|
|
33
33
|
floating_help(help_id) { translated_attribute(help_section).html_safe }
|
34
34
|
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)
|
data/app/models/decidim/user.rb
CHANGED
@@ -13,8 +13,6 @@ module Decidim
|
|
13
13
|
include Decidim::UserReportable
|
14
14
|
include Decidim::Traceable
|
15
15
|
|
16
|
-
REGEXP_NICKNAME = /\A[\w-]+\z/
|
17
|
-
|
18
16
|
class Roles
|
19
17
|
def self.all
|
20
18
|
Decidim.config.user_roles
|
@@ -51,8 +49,6 @@ module Decidim
|
|
51
49
|
|
52
50
|
has_one_attached :download_your_data_file
|
53
51
|
|
54
|
-
scope :not_deleted, -> { where(deleted_at: nil) }
|
55
|
-
|
56
52
|
scope :managed, -> { where(managed: true) }
|
57
53
|
scope :not_managed, -> { where(managed: false) }
|
58
54
|
|
@@ -21,11 +21,13 @@ module Decidim
|
|
21
21
|
|
22
22
|
# Regex for name & nickname format validations
|
23
23
|
REGEXP_NAME = /\A(?!.*[<>?%&\^*#@()\[\]=+:;"{}\\|])/
|
24
|
+
REGEXP_NICKNAME = /\A[a-z0-9_-]+\z/
|
24
25
|
|
25
26
|
has_one_attached :avatar
|
26
27
|
validates_avatar :avatar, uploader: Decidim::AvatarUploader
|
27
28
|
|
28
29
|
validates :name, format: { with: REGEXP_NAME }
|
30
|
+
validates :nickname, format: { with: REGEXP_NICKNAME }, unless: -> { deleted? || managed? }
|
29
31
|
|
30
32
|
scope :confirmed, -> { where.not(confirmed_at: nil) }
|
31
33
|
scope :not_confirmed, -> { where(confirmed_at: nil) }
|
@@ -34,6 +36,8 @@ module Decidim
|
|
34
36
|
scope :not_blocked, -> { where(blocked: false) }
|
35
37
|
scope :available, -> { where(deleted_at: nil, blocked: false, managed: false) }
|
36
38
|
|
39
|
+
scope :not_deleted, -> { where(deleted_at: nil) }
|
40
|
+
|
37
41
|
# Public: Returns a collection with all the public entities this user is following.
|
38
42
|
#
|
39
43
|
# This cannot be done as with a `has_many :following, through: :following_follows`
|
@@ -53,10 +53,18 @@ $(() => {
|
|
53
53
|
}
|
54
54
|
|
55
55
|
$(document).on("click.zf.trigger", (event) => {
|
56
|
-
|
57
|
-
const
|
56
|
+
// Try to get the <a> directly or find the closest parent <a>
|
57
|
+
const $target = $(event.target).closest("a");
|
58
58
|
|
59
|
-
if
|
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) {
|
60
68
|
return;
|
61
69
|
}
|
62
70
|
|
@@ -64,10 +72,10 @@ $(() => {
|
|
64
72
|
attr("id", "redirect_url").
|
65
73
|
attr("name", "redirect_url").
|
66
74
|
attr("value", redirectUrl).
|
67
|
-
appendTo(`${
|
75
|
+
appendTo(`${dialogTarget} form`);
|
68
76
|
|
69
|
-
$(`${
|
70
|
-
const querystring = jQuery.param({
|
77
|
+
$(`${dialogTarget} a`).attr("href", (index, href) => {
|
78
|
+
const querystring = jQuery.param({"redirect_url": redirectUrl});
|
71
79
|
return href + (href.match(/\?/) ? "&" : "?") + querystring;
|
72
80
|
});
|
73
81
|
});
|
@@ -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
|