decidim-core 0.28.1 → 0.28.2
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/announcement/show.erb +2 -2
- data/app/cells/decidim/author/show.erb +5 -5
- data/app/cells/decidim/card/show.erb +1 -1
- data/app/cells/decidim/card_metadata/show.erb +2 -2
- data/app/cells/decidim/data_consent/category.erb +1 -1
- data/app/cells/decidim/nav_links/show.erb +2 -2
- data/app/cells/decidim/notification/moderated.erb +12 -0
- data/app/cells/decidim/notification_cell.rb +5 -1
- data/app/cells/decidim/profile/details.erb +1 -1
- data/app/cells/decidim/progress_bar/show.erb +1 -1
- data/app/cells/decidim/progress_bar_cell.rb +2 -0
- data/app/cells/decidim/report_button/flag_modal.erb +5 -1
- data/app/cells/decidim/resource_types_filter/show.erb +3 -3
- data/app/cells/decidim/statistic/show.erb +2 -2
- data/app/cells/decidim/upload_modal/modal.erb +3 -4
- data/app/controllers/concerns/decidim/force_authentication.rb +1 -1
- data/app/controllers/concerns/decidim/use_organization_time_zone.rb +1 -1
- data/app/controllers/decidim/gamification/badges_controller.rb +2 -0
- data/app/controllers/decidim/links_controller.rb +15 -2
- data/app/helpers/concerns/decidim/flash_helper_extensions.rb +2 -2
- data/app/helpers/decidim/check_boxes_tree_helper.rb +1 -2
- data/app/mailers/decidim/application_mailer.rb +40 -6
- data/app/packs/src/decidim/a11y.js +14 -0
- data/app/packs/src/decidim/abide_form_validator_fixer.js +44 -0
- data/app/packs/src/decidim/direct_uploads/upload_modal.js +2 -6
- data/app/packs/src/decidim/index.js +29 -1
- data/app/packs/stylesheets/decidim/_accordion.scss +2 -2
- data/app/packs/stylesheets/decidim/_cards.scss +2 -2
- data/app/packs/stylesheets/decidim/_layout.scss +3 -3
- data/app/packs/stylesheets/decidim/_modal_update.scss +1 -3
- data/app/presenters/decidim/admin_log/organization_presenter.rb +1 -1
- data/app/presenters/decidim/log/resource_presenter.rb +7 -1
- data/app/services/decidim/log/diff_changeset_calculator.rb +1 -1
- data/app/views/decidim/account/show.html.erb +2 -2
- data/app/views/decidim/application/_document.html.erb +2 -2
- data/app/views/decidim/endorsements/update_buttons_and_counters.js.erb +2 -1
- data/app/views/decidim/gamification/badges/index.html.erb +34 -33
- data/app/views/decidim/links/_modal.html.erb +1 -1
- data/app/views/decidim/links/new.html.erb +3 -1
- data/app/views/decidim/manifests/show.json.erb +1 -1
- data/app/views/decidim/messaging/conversations/create.js.erb +1 -1
- data/app/views/decidim/notifications_settings/show.html.erb +6 -6
- data/app/views/decidim/pages/_tabbed.html.erb +2 -2
- data/app/views/decidim/searches/_filters.html.erb +2 -2
- data/app/views/decidim/shared/_filters.html.erb +2 -2
- data/app/views/decidim/shared/_orders.html.erb +2 -2
- data/app/views/decidim/shared/filters/_collection.html.erb +5 -3
- data/app/views/decidim/shared/filters/_dropdown_label.html.erb +21 -19
- data/app/views/layouts/decidim/_wrapper.html.erb +1 -1
- data/app/views/layouts/decidim/footer/_main_links.html.erb +3 -1
- data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +4 -2
- data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +2 -0
- data/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +2 -2
- data/config/locales/ar.yml +1 -5
- data/config/locales/bg.yml +878 -1
- data/config/locales/ca.yml +2 -0
- data/config/locales/cs.yml +1 -1
- data/config/locales/de.yml +3 -1
- data/config/locales/el.yml +8 -1
- data/config/locales/en.yml +3 -1
- data/config/locales/es-MX.yml +8 -6
- data/config/locales/es-PY.yml +8 -6
- data/config/locales/es.yml +32 -30
- data/config/locales/eu.yml +4 -2
- data/config/locales/fi-plain.yml +3 -1
- data/config/locales/fi.yml +4 -2
- data/config/locales/fr-CA.yml +2 -0
- data/config/locales/fr.yml +2 -0
- data/config/locales/ga-IE.yml +8 -0
- data/config/locales/gl.yml +1 -0
- data/config/locales/hu.yml +1 -2
- data/config/locales/it.yml +7 -1
- data/config/locales/ja.yml +3 -1
- data/config/locales/kaa.yml +5 -0
- data/config/locales/lb.yml +7 -1
- data/config/locales/lt.yml +8 -2
- data/config/locales/lv.yml +8 -1
- data/config/locales/nl.yml +7 -1
- data/config/locales/no.yml +7 -1
- data/config/locales/pl.yml +35 -0
- data/config/locales/pt-BR.yml +0 -1
- data/config/locales/pt.yml +7 -1
- data/config/locales/ro-RO.yml +8 -0
- data/config/locales/ru.yml +8 -0
- data/config/locales/sk.yml +8 -1
- data/config/locales/sl.yml +8 -0
- data/config/locales/sv.yml +8 -1
- data/config/locales/tr-TR.yml +21 -4
- data/config/locales/uk.yml +10 -0
- data/config/locales/zh-CN.yml +0 -1
- data/config/locales/zh-TW.yml +8 -1
- data/lib/decidim/core/seeds.rb +1 -1
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +76 -6
- data/lib/decidim/core/test/shared_examples/logo_email.rb +2 -2
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +6 -1
- data/lib/decidim/events/base_event.rb +4 -0
- data/lib/decidim/organization_settings.rb +10 -2
- metadata +12 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 524ec4d380f620c07119a6ccbee1b28408f6072799aa32cd74a1836f1ede5070
|
|
4
|
+
data.tar.gz: 4e1b60ce9a2cb9e340b0db3a22f66b326ade8f05cb8551352b39fe4198a06bbb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c8ff8135707ab3ae9aa1d483cd41d104385c079e8dcbd575c3c618ae05c524c345b340bd4b82c47eccf533dc98e187985ba76ddb2293332977449ed8af95b4b3
|
|
7
|
+
data.tar.gz: 9188473aa2d7c440f2aa773e9e08824b2c847f8a29a6d1d1ff75900e9a2fd325f860d80d8faad5d2498dc594f20b92ad9e8f7e6b98551ba9f68ffe24a879dcc1
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<% data = has_tooltip? ? { tooltip: render(:profile_minicard).html_safe } : nil %>
|
|
2
|
-
<
|
|
3
|
-
<%= content_tag :
|
|
2
|
+
<span class="author" data-author>
|
|
3
|
+
<%= content_tag :span, class: "author__container#{" is-compact" if layout == :compact}", data: do %>
|
|
4
4
|
<% if layout == :compact %>
|
|
5
5
|
<%= render :avatar %>
|
|
6
6
|
|
|
7
|
-
<
|
|
7
|
+
<span>
|
|
8
8
|
<%= render :name %>
|
|
9
9
|
|
|
10
10
|
<% context_actions.each do |action| %>
|
|
11
11
|
<%= render action %>
|
|
12
12
|
<% end %>
|
|
13
|
-
</
|
|
13
|
+
</span>
|
|
14
14
|
<% elsif layout == :avatar %>
|
|
15
15
|
<%= render :avatar %>
|
|
16
16
|
<% else %>
|
|
@@ -24,4 +24,4 @@
|
|
|
24
24
|
<%= render action %>
|
|
25
25
|
<% end %>
|
|
26
26
|
<% end %>
|
|
27
|
-
</
|
|
27
|
+
</span>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div class="py-4 space-y-2">
|
|
2
|
-
<a href="" class="text-lg text-secondary font-semibold hover:underline"><%= title %></a>
|
|
2
|
+
<a href="" class="text-lg text-secondary font-semibold hover:underline"><%= decidim_html_escape(title) %></a>
|
|
3
3
|
<div class="flex items-center divide-x divide-gray-3">
|
|
4
4
|
<% metadata.first(4).each do |item| %>
|
|
5
5
|
<div class="flex items-center gap-1 px-4 lg:px-6 first:pl-0 last:pr-0 max-w-xs">
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
<% hook_output = render_hook(item[:hook]) %>
|
|
4
4
|
<% next if hook_output.blank? %>
|
|
5
5
|
|
|
6
|
-
<%= content_tag :
|
|
6
|
+
<%= content_tag :div, data: item[:data_attributes] do %>
|
|
7
7
|
<%= icon item[:icon] if item[:icon].present? %>
|
|
8
8
|
<%= hook_output %>
|
|
9
9
|
<% end %>
|
|
10
10
|
<% else %>
|
|
11
|
-
<%= content_tag :
|
|
11
|
+
<%= content_tag :div, data: item[:data_attributes] do %>
|
|
12
12
|
<%= icon item[:icon] if item[:icon].present? %>
|
|
13
13
|
<% if item[:text].present? %>
|
|
14
14
|
<%= link_to_if enable_links? && item.has_key?(:url), item[:text], item[:url] %>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="cookies__category-trigger">
|
|
3
3
|
<label for="dc-<%= category[:slug] %>" class="cookies__category-toggle">
|
|
4
4
|
<input
|
|
5
|
-
|
|
5
|
+
<%== %(checked="checked") if category[:mandatory] %>
|
|
6
6
|
id="dc-<%= category[:slug] %>"
|
|
7
7
|
type="checkbox"
|
|
8
8
|
name="<%= category[:slug] %>"
|
|
@@ -1,10 +1,10 @@
|
|
|
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-
|
|
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">
|
|
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" aria-hidden="true">
|
|
8
8
|
<% model.each do |item| %>
|
|
9
9
|
<li>
|
|
10
10
|
<%= link_to item[:url], class: "participatory-space__nav-item" do %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<div class="notification" data-notification>
|
|
2
|
+
<div class="notification__wrapper">
|
|
3
|
+
<div class="notification__time" title="<%= l(notification.created_at) %>"> <%= notification.created_at_in_words %></div>
|
|
4
|
+
<div class="notification__snippet">
|
|
5
|
+
<span class="notification__snippet-title text-gray"><%= t("decidim.notifications.show.moderated") %></span>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
<%= link_to model, remote: true, method: :delete, class: "notification__button", data: { "notification-read": "" } do %>
|
|
9
|
+
<span class="sr-only md:not-sr-only"><%= t("mark_as_read", scope: "layouts.decidim.notifications_dashboard") %></span>
|
|
10
|
+
<%= icon "check-line", class: "fill-current" %>
|
|
11
|
+
<% end %>
|
|
12
|
+
</div>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<%= content_tag :div, units_name_text, class: "progress-bar__units" if units_name %>
|
|
8
8
|
|
|
9
9
|
<% if total != 0 %>
|
|
10
|
-
<div class="progress-bar" role="progressbar"
|
|
10
|
+
<div class="progress-bar" role="progressbar" aria-label="<%= units_name.present? ? units_name_text : t("decidim.shared.progress") %>" aria-valuenow="<%= number_with_precision(percentage, separator: ".", precision: 2) %>" aria-valuemin="0" aria-valuemax="100" aria-valuetext="<%= number_to_percentage(percentage, precision: 2) %>">
|
|
11
11
|
<div style="width: <%= percentage %>%"></div>
|
|
12
12
|
</div>
|
|
13
13
|
<% end %>
|
|
@@ -34,11 +34,15 @@
|
|
|
34
34
|
<%= f.check_box :hide,
|
|
35
35
|
label: t("decidim.shared.flag_modal.hide_content"),
|
|
36
36
|
include_hidden: false,
|
|
37
|
+
id: hide_checkbox_id,
|
|
37
38
|
data: {
|
|
38
39
|
label_action: t("decidim.shared.flag_modal.hide"),
|
|
39
40
|
label_report: t("decidim.shared.flag_modal.report"),
|
|
40
41
|
hide: "true"
|
|
41
|
-
},
|
|
42
|
+
},
|
|
43
|
+
label_options: {
|
|
44
|
+
for: hide_checkbox_id
|
|
45
|
+
} %>
|
|
42
46
|
<% end %>
|
|
43
47
|
<% end %>
|
|
44
48
|
|
|
@@ -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-auto-close="true"
|
|
2
|
+
<button id="dropdown-trigger-resource" data-component="dropdown" data-target="dropdown-menu-resource" data-auto-close="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,7 +8,7 @@
|
|
|
8
8
|
<%= icon "arrow-down-s-line" %>
|
|
9
9
|
<%= icon "arrow-up-s-line" %>
|
|
10
10
|
</button>
|
|
11
|
-
<%= filter_form_for filter, form_path, class
|
|
11
|
+
<%= filter_form_for filter, form_path, :class => "new_filter", :id => "dropdown-menu-resource", "aria-hidden" => true do |form| %>
|
|
12
12
|
<%= form.collection_radio_buttons(
|
|
13
13
|
filter_param_key,
|
|
14
14
|
resource_types,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
:last,
|
|
17
17
|
{ checked: filter_param }
|
|
18
18
|
) do |builder|
|
|
19
|
-
builder.label { builder.radio_button(class: "reset-defaults", hidden: true) + content_tag(:
|
|
19
|
+
builder.label { builder.radio_button(class: "reset-defaults", hidden: true) + content_tag(:span, text_with_resource_icon(builder.value, builder.text), class: "filter") }
|
|
20
20
|
end %>
|
|
21
21
|
<% end %>
|
|
22
22
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div class="statistic <%= stat_dom_class %>" data-statistic>
|
|
2
|
-
<
|
|
2
|
+
<span class="statistic__title" title="<%= stat_title %>">
|
|
3
3
|
<%= stat_title %>
|
|
4
|
-
</
|
|
4
|
+
</span>
|
|
5
5
|
<span class="statistic__number">
|
|
6
6
|
<%= stat_number %>
|
|
7
7
|
</span>
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
<%= icon "upload-cloud-2-line", class: "w-8 h-8 text-gray fill-current" %>
|
|
38
38
|
<%= t("decidim.forms.upload_help.dropzone") %>
|
|
39
39
|
</span>
|
|
40
|
-
<
|
|
40
|
+
<label class="button button__sm button__secondary" for="files-<%= modal_id %>">
|
|
41
41
|
<span><%= t("decidim.forms.upload.select_file") %></span>
|
|
42
42
|
<%= icon "arrow-right-line", class: "fill-current" %>
|
|
43
|
-
</
|
|
43
|
+
</label>
|
|
44
44
|
</div>
|
|
45
45
|
</div>
|
|
46
46
|
</div>
|
|
@@ -60,8 +60,7 @@
|
|
|
60
60
|
<%= t("decidim.shared.confirm_modal.cancel") %>
|
|
61
61
|
</button>
|
|
62
62
|
<button type="button" class="button button__sm md:button__lg button__secondary" data-dropzone-save data-dialog-close="<%= modal_id %>" disabled>
|
|
63
|
-
<%= t("
|
|
64
|
-
<%= icon "arrow-right-line", class: "fill-current" %>
|
|
63
|
+
<%= t("save", scope: "decidim.forms.upload.labels") %>
|
|
65
64
|
</button>
|
|
66
65
|
</div>
|
|
67
66
|
<% end %>
|
|
@@ -17,7 +17,7 @@ module Decidim
|
|
|
17
17
|
# Breaks the request lifecycle, if user is not authenticated.
|
|
18
18
|
# Otherwise returns.
|
|
19
19
|
def ensure_authenticated!
|
|
20
|
-
return true unless current_organization
|
|
20
|
+
return true unless current_organization&.force_users_to_authenticate_before_access_organization
|
|
21
21
|
|
|
22
22
|
# Next stop: Check whether auth is ok
|
|
23
23
|
unless user_signed_in?
|
|
@@ -14,7 +14,8 @@ module Decidim
|
|
|
14
14
|
rescue_from URI::InvalidURIError, with: :modal
|
|
15
15
|
|
|
16
16
|
def new
|
|
17
|
-
headers["X-Robots-Tag"] = "
|
|
17
|
+
headers["X-Robots-Tag"] = "none"
|
|
18
|
+
headers["Link"] = %(<#{url_for}>; rel="canonical")
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
private
|
|
@@ -36,7 +37,19 @@ module Decidim
|
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
def external_url
|
|
39
|
-
@external_url ||= URI.parse(
|
|
40
|
+
@external_url ||= URI.parse(escape_url(params[:external_url]))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def escape_url(external_url)
|
|
44
|
+
before_fragment, fragment = external_url.split("#", 2)
|
|
45
|
+
escaped_before_fragment = URI::Parser.new.escape(before_fragment)
|
|
46
|
+
|
|
47
|
+
if fragment
|
|
48
|
+
escaped_fragment = URI::Parser.new.escape(fragment)
|
|
49
|
+
"#{escaped_before_fragment}##{escaped_fragment}"
|
|
50
|
+
else
|
|
51
|
+
escaped_before_fragment
|
|
52
|
+
end
|
|
40
53
|
end
|
|
41
54
|
end
|
|
42
55
|
end
|
|
@@ -106,9 +106,9 @@ module Decidim
|
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def message(value)
|
|
109
|
-
return content_tag(:
|
|
109
|
+
return content_tag(:div, value, class: "flash__message flex items-center") unless value.is_a?(Hash)
|
|
110
110
|
|
|
111
|
-
content_tag(:
|
|
111
|
+
content_tag(:div, class: "flash__message") do
|
|
112
112
|
concat value[:title]
|
|
113
113
|
concat content_tag(:span, value[:body], class: "flash__message-body")
|
|
114
114
|
end
|
|
@@ -7,23 +7,57 @@ module Decidim
|
|
|
7
7
|
include LocalisedMailer
|
|
8
8
|
include MultitenantAssetHost
|
|
9
9
|
after_action :set_smtp
|
|
10
|
+
after_action :set_from
|
|
10
11
|
|
|
11
12
|
default from: Decidim.config.mailer_sender
|
|
12
13
|
layout "decidim/mailer"
|
|
13
14
|
|
|
14
15
|
private
|
|
15
16
|
|
|
17
|
+
attr_reader :organization
|
|
18
|
+
|
|
16
19
|
def set_smtp
|
|
17
|
-
return if
|
|
20
|
+
return if organization.nil? || organization.smtp_settings.blank? || organization.smtp_settings.except("from", "from_label", "from_email").all?(&:blank?)
|
|
18
21
|
|
|
19
|
-
mail.from = @organization.smtp_settings["from"].presence || mail.from
|
|
20
22
|
mail.reply_to = mail.reply_to || Decidim.config.mailer_reply
|
|
21
23
|
mail.delivery_method.settings.merge!(
|
|
22
|
-
address:
|
|
23
|
-
port:
|
|
24
|
-
user_name:
|
|
25
|
-
password: Decidim::AttributeEncryptor.decrypt(
|
|
24
|
+
address: organization.smtp_settings["address"],
|
|
25
|
+
port: organization.smtp_settings["port"],
|
|
26
|
+
user_name: organization.smtp_settings["user_name"],
|
|
27
|
+
password: Decidim::AttributeEncryptor.decrypt(organization.smtp_settings["encrypted_password"])
|
|
26
28
|
) { |_k, o, v| v.presence || o }.compact_blank!
|
|
27
29
|
end
|
|
30
|
+
|
|
31
|
+
def set_from
|
|
32
|
+
return if organization.nil?
|
|
33
|
+
return if already_defined_name_in_mail?(mail.from.first)
|
|
34
|
+
|
|
35
|
+
mail.from = sender
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def sender
|
|
39
|
+
return Decidim.config.mailer_sender if return_mailer_sender?
|
|
40
|
+
return default_sender if organization.smtp_settings.blank?
|
|
41
|
+
return default_sender if organization.smtp_settings["from"].nil?
|
|
42
|
+
return default_sender if organization.smtp_settings["from"].empty?
|
|
43
|
+
|
|
44
|
+
smtp_settings_from = organization.smtp_settings["from"]
|
|
45
|
+
return smtp_settings_from if already_defined_name_in_mail?(smtp_settings_from)
|
|
46
|
+
|
|
47
|
+
email_address_with_name(smtp_settings_from, organization.name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def default_sender
|
|
51
|
+
email_address_with_name(Decidim.config.mailer_sender, organization.name)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def already_defined_name_in_mail?(mail_address)
|
|
55
|
+
# if there is an space, there is already a name in the address
|
|
56
|
+
mail_address.match?(/ /)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def return_mailer_sender?
|
|
60
|
+
already_defined_name_in_mail?(Decidim.config.mailer_sender) && organization.smtp_settings.present?
|
|
61
|
+
end
|
|
28
62
|
end
|
|
29
63
|
end
|
|
@@ -104,6 +104,20 @@ const createDropdown = (component) => {
|
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
106
|
|
|
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
|
+
|
|
107
121
|
Dropdowns.render(component.id, dropdownOptions);
|
|
108
122
|
}
|
|
109
123
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This script modifies the behavior of Abide form validation to address the issue of form validation errors
|
|
3
|
+
* appearing prematurely in input fields.
|
|
4
|
+
*
|
|
5
|
+
* The primary goal is to hide error messages until the input field loses focus.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
class AbideFormValidatorFixer {
|
|
9
|
+
initialize() {
|
|
10
|
+
const forms = document.querySelectorAll("main [data-live-validate='true']");
|
|
11
|
+
|
|
12
|
+
forms.forEach((form) => {
|
|
13
|
+
if (this.isElementVisible(form)) {
|
|
14
|
+
this.setupForm(form);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
isElementVisible(element) {
|
|
20
|
+
return element.offsetParent !== null && getComputedStyle(element).display !== "none";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setupForm(form) {
|
|
24
|
+
const inputs = form.querySelectorAll("input");
|
|
25
|
+
|
|
26
|
+
inputs.forEach((input) => {
|
|
27
|
+
const errorElement = input.closest("label")?.querySelector(".form-error") || input.parentElement.querySelector(".form-error");
|
|
28
|
+
if (!errorElement) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
form.removeAttribute("data-live-validate");
|
|
32
|
+
input.addEventListener("input", this.hideErrorElement.bind(this, errorElement));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
hideErrorElement(errorElement) {
|
|
37
|
+
errorElement.classList.remove("is-visible");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
42
|
+
const validatorFixer = new AbideFormValidatorFixer();
|
|
43
|
+
validatorFixer.initialize();
|
|
44
|
+
});
|
|
@@ -154,20 +154,16 @@ export default class UploadModal {
|
|
|
154
154
|
// Disabled save button when any children have data-state="error"
|
|
155
155
|
this.saveButton.disabled = Array.from(files).filter(({ dataset: { state } }) => state === STATUS.ERROR).length > 0;
|
|
156
156
|
|
|
157
|
-
const dataSelectFileButton = this.emptyItems.querySelector("[data-select-file-button]");
|
|
158
|
-
|
|
159
157
|
// Only allow to continue the upload when the multiple option is true (default: false)
|
|
160
158
|
const continueUpload = !files.length || this.options.multiple
|
|
161
159
|
this.input.disabled = !continueUpload
|
|
162
160
|
if (continueUpload) {
|
|
163
161
|
this.emptyItems.classList.remove("is-disabled");
|
|
164
|
-
|
|
162
|
+
this.emptyItems.querySelector("label").removeAttribute("disabled");
|
|
165
163
|
} else {
|
|
166
164
|
this.emptyItems.classList.add("is-disabled");
|
|
167
|
-
|
|
165
|
+
this.emptyItems.querySelector("label").disabled = true;
|
|
168
166
|
}
|
|
169
|
-
|
|
170
|
-
dataSelectFileButton.addEventListener("click", () => this.input.click());
|
|
171
167
|
}
|
|
172
168
|
|
|
173
169
|
createUploadItem(file, errors, opts = {}) {
|
|
@@ -50,6 +50,7 @@ import "src/decidim/impersonation"
|
|
|
50
50
|
import "src/decidim/gallery"
|
|
51
51
|
import "src/decidim/direct_uploads/upload_field"
|
|
52
52
|
import "src/decidim/data_consent"
|
|
53
|
+
import "src/decidim/abide_form_validator_fixer"
|
|
53
54
|
import "src/decidim/sw"
|
|
54
55
|
|
|
55
56
|
// local deps that require initialization
|
|
@@ -90,6 +91,33 @@ window.Decidim = window.Decidim || {
|
|
|
90
91
|
|
|
91
92
|
window.morphdom = morphdom
|
|
92
93
|
|
|
94
|
+
// REDESIGN_PENDING: deprecated
|
|
95
|
+
window.initFoundation = (element) => {
|
|
96
|
+
$(element).foundation();
|
|
97
|
+
|
|
98
|
+
// Fix compatibility issue with the `a11y-accordion-component` package that
|
|
99
|
+
// uses the `data-open` attribute to indicate the open state for the accordion
|
|
100
|
+
// trigger.
|
|
101
|
+
//
|
|
102
|
+
// In Foundation, these listeners are initiated on the document node always,
|
|
103
|
+
// regardless of the element for which foundation is initiated. Therefore, we
|
|
104
|
+
// need the document node here instead of the `element` passed to this
|
|
105
|
+
// function.
|
|
106
|
+
const $document = $(document);
|
|
107
|
+
|
|
108
|
+
$document.off("click.zf.trigger", window.Foundation.Triggers.Listeners.Basic.openListener);
|
|
109
|
+
$document.on("click.zf.trigger", "[data-open]", (ev, ...restArgs) => {
|
|
110
|
+
// Do not apply for the accordion triggers.
|
|
111
|
+
const accordion = ev.currentTarget?.closest("[data-component='accordion']");
|
|
112
|
+
if (accordion) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Otherwise call the original implementation
|
|
117
|
+
Reflect.apply(window.Foundation.Triggers.Listeners.Basic.openListener, ev.currentTarget, [ev, ...restArgs]);
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
93
121
|
Rails.start()
|
|
94
122
|
|
|
95
123
|
/**
|
|
@@ -104,7 +132,7 @@ const initializer = (element = document) => {
|
|
|
104
132
|
window.focusGuard = window.focusGuard || new FocusGuard(document.body);
|
|
105
133
|
|
|
106
134
|
// REDESIGN_PENDING: deprecated
|
|
107
|
-
|
|
135
|
+
window.initFoundation(element);
|
|
108
136
|
|
|
109
137
|
svg4everybody();
|
|
110
138
|
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
[data-component="accordion"]
|
|
6
6
|
[id*="comment"][class="comment-reply"][aria-hidden="true"] {
|
|
7
|
-
display:
|
|
7
|
+
display: none;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
[data-component="accordion"]
|
|
11
11
|
[id*="comment"][class="comment-reply"][aria-hidden="false"] {
|
|
12
|
-
display:
|
|
12
|
+
display: block;
|
|
13
13
|
}
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
&-month,
|
|
135
135
|
&-day,
|
|
136
136
|
&-year {
|
|
137
|
-
@apply inline-flex items-center justify-evenly empty:[&>
|
|
137
|
+
@apply inline-flex items-center justify-evenly empty:[&>div]:hidden;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
&__list-metadata {
|
|
144
144
|
@apply mt-auto inline-flex flex-wrap gap-x-4 md:gap-0;
|
|
145
145
|
|
|
146
|
-
& >
|
|
146
|
+
& > div {
|
|
147
147
|
@apply inline-flex items-center gap-1 px-0 md:px-6 border-gray-3 border-0 md:border-r first:pl-0 last:pr-0 last:border-r-0 text-sm text-gray-2;
|
|
148
148
|
|
|
149
149
|
& > svg {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
[data-content] {
|
|
9
|
-
@apply
|
|
9
|
+
@apply relative flex flex-col;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
.layout-2col {
|
|
34
|
-
@apply md:grid grid-cols-12 container grow
|
|
34
|
+
@apply md:grid grid-cols-12 container grow auto-rows-max;
|
|
35
35
|
|
|
36
36
|
&__aside {
|
|
37
37
|
@apply col-span-4 lg:col-span-3 md:pr-16 py-6 md:py-12 gap-6 md:gap-12 flex flex-col justify-between items-start md:justify-start before:content-[''] before:absolute before:top-0 before:left-0 before:h-full before:w-1/2 before:-z-10 md:before:bg-background;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
&__main {
|
|
41
|
-
@apply col-span-8 lg:col-span-9 bg-white md:pl-16 py-6 md:py-12;
|
|
41
|
+
@apply col-span-8 lg:col-span-9 bg-white md:pl-16 py-6 md:py-12 min-h-[60vh];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
&__reverse &__aside {
|
|
@@ -10,6 +10,8 @@ module Decidim
|
|
|
10
10
|
# overwrite `BasePresenter#resource_presenter` to return your custom resource presenter.
|
|
11
11
|
# The only requirement for custom renderers is that they should respond to `present`.
|
|
12
12
|
class ResourcePresenter
|
|
13
|
+
include Decidim::SanitizeHelper
|
|
14
|
+
|
|
13
15
|
# Public: Initializes the presenter.
|
|
14
16
|
#
|
|
15
17
|
# resource - An instance of a model that can be located by
|
|
@@ -65,7 +67,11 @@ module Decidim
|
|
|
65
67
|
#
|
|
66
68
|
# Returns an HTML-safe String.
|
|
67
69
|
def present_resource_name
|
|
68
|
-
|
|
70
|
+
if resource.present? && resource.respond_to?(:presenter) && resource.presenter.respond_to?(:title)
|
|
71
|
+
resource.presenter.title(html_escape: true)
|
|
72
|
+
else
|
|
73
|
+
decidim_escape_translated(extra["title"]).html_safe
|
|
74
|
+
end
|
|
69
75
|
end
|
|
70
76
|
end
|
|
71
77
|
end
|
|
@@ -86,7 +86,7 @@ module Decidim
|
|
|
86
86
|
locales.flat_map do |locale|
|
|
87
87
|
previous_value = values.first.try(:[], locale)
|
|
88
88
|
new_value = values.last.try(:[], locale)
|
|
89
|
-
if previous_value == new_value
|
|
89
|
+
if previous_value == new_value || (previous_value.nil? && new_value.blank?)
|
|
90
90
|
nil
|
|
91
91
|
else
|
|
92
92
|
label = generate_label(attribute, locale)
|