decidim-core 0.29.0.rc3 → 0.29.0

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/address/online.erb +2 -2
  3. data/app/cells/decidim/address_cell.rb +4 -0
  4. data/app/cells/decidim/card_g/show.erb +1 -1
  5. data/app/cells/decidim/card_g_cell.rb +5 -2
  6. data/app/cells/decidim/card_l/image.erb +2 -2
  7. data/app/cells/decidim/card_l_cell.rb +5 -2
  8. data/app/cells/decidim/content_blocks/hero_cell.rb +1 -1
  9. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
  10. data/app/cells/decidim/content_blocks/participatory_space_hero_cell.rb +2 -2
  11. data/app/cells/decidim/nav_links/show.erb +3 -3
  12. data/app/cells/decidim/resource_types_filter/show.erb +11 -12
  13. data/app/commands/decidim/create_omniauth_registration.rb +10 -4
  14. data/app/controllers/concerns/decidim/devise_controllers.rb +1 -0
  15. data/app/controllers/concerns/decidim/paginable.rb +1 -1
  16. data/app/controllers/decidim/application_controller.rb +1 -0
  17. data/app/helpers/decidim/menu_helper.rb +1 -1
  18. data/app/helpers/decidim/paginate_helper.rb +3 -5
  19. data/app/models/decidim/attachment.rb +8 -7
  20. data/app/models/decidim/component.rb +4 -1
  21. data/app/models/decidim/content_block.rb +2 -2
  22. data/app/models/decidim/user.rb +12 -12
  23. data/app/packs/src/decidim/a11y.js +11 -15
  24. data/app/packs/src/decidim/attachments/file_or_link_tabs.js +7 -3
  25. data/app/packs/src/decidim/input_character_counter.js +1 -1
  26. data/app/packs/stylesheets/decidim/_dropdown.scss +9 -9
  27. data/app/packs/stylesheets/decidim/_filters.scss +3 -1
  28. data/app/packs/stylesheets/decidim/_footer.scss +1 -1
  29. data/app/packs/stylesheets/decidim/_forms.scss +4 -4
  30. data/app/packs/stylesheets/decidim/_tooltip.scss +10 -10
  31. data/app/packs/stylesheets/decidim/editor.scss +1 -1
  32. data/app/presenters/decidim/menu_item_presenter.rb +1 -1
  33. data/app/services/decidim/open_data_exporter.rb +8 -7
  34. data/app/views/decidim/manifests/show.json.erb +4 -4
  35. data/app/views/decidim/pages/_tabbed.html.erb +3 -3
  36. data/app/views/decidim/shared/_filters.html.erb +5 -5
  37. data/app/views/decidim/shared/_orders.html.erb +3 -2
  38. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -1
  39. data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
  40. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  41. data/app/views/layouts/decidim/footer/_main.html.erb +1 -1
  42. data/app/views/layouts/decidim/footer/_main_intro.html.erb +1 -1
  43. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +1 -1
  44. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +1 -1
  45. data/app/views/layouts/decidim/header/_main_links_mobile_item_account.html.erb +1 -1
  46. data/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +2 -2
  47. data/config/locales/ca.yml +3 -3
  48. data/config/locales/cs.yml +14 -0
  49. data/config/locales/fi-plain.yml +3 -3
  50. data/config/locales/fi.yml +28 -28
  51. data/config/locales/sv.yml +72 -64
  52. data/db/migrate/20181025082245_add_timestamps_to_components.rb +5 -1
  53. data/lib/decidim/asset_router/storage.rb +216 -13
  54. data/lib/decidim/core/test/shared_examples/attachable_interface_examples.rb +1 -1
  55. data/lib/decidim/core/test/shared_examples/follows_examples.rb +8 -3
  56. data/lib/decidim/core/test/shared_examples/paginated_resource_examples.rb +5 -5
  57. data/lib/decidim/core/version.rb +1 -1
  58. data/lib/tasks/upgrade/decidim_fix_categorization.rake +100 -0
  59. metadata +8 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d58ac45e047a62b04a7625b6da1c4ee92c2a62d9bf4e1969cdfb324257e5ef9
4
- data.tar.gz: 94a06bf8519d6234945a39dc86cc9794149fa3dc09c89273dcd475a64a3ad78b
3
+ metadata.gz: 37f39b870aa9a840fbf4c415858b3210d520511f8efb0327bb90e8aa0126f243
4
+ data.tar.gz: 16fa93602fc35d288ddeef831f50f3e3878714ea4fae6547064c9be0a148fad0
5
5
  SHA512:
6
- metadata.gz: 6e90186e86e894822888b13cbaabe6c8c2a752d73a477cb13b39be5fd785d9b92082e5e403de91790f43c19a78f83bb85253e4fa0475f086f64e90258b2593b3
7
- data.tar.gz: f297c4b6a5fad64c57984fc063778cddda2404f3861e75b8a16c4fff83986caedc44354bba11a58551c5815dae0c9785b5f8d159a9a7e0930d2f080341b69579
6
+ metadata.gz: 0ae69c163d580612c4a8f4f4cf8d9c460aebc24270a67f4a245d25f4fceb2988075664aab8f97977ae19b75d90c42e1cdb03ad2591bd546c5acf9f8562d5852f
7
+ data.tar.gz: 23132fff12f59d0bb72b073e6729ccb5f439f5c59493d8a3f8f7026dbb45cf20e56f1cac34b07bc8a2d10e757b4cd6efe60bc93180f22d2a4764db597913a1b6
@@ -5,8 +5,8 @@
5
5
  <div class="address">
6
6
  <div class="address__location"><%= t(model.type_of_meeting, scope: "decidim.meetings.meetings.filters.type_values") %></div>
7
7
  <% if display_online_meeting_url? %>
8
- <a href="<%= model.online_meeting_url %>" target="_blank" rel="noopener noreferrer" class="address__hints underline break-all">
9
- <%= model.online_meeting_url %>
8
+ <a href="<%= online_meeting_url %>" target="_blank" rel="noopener noreferrer" class="address__hints underline break-all">
9
+ <%= online_meeting_url %>
10
10
  <% end %>
11
11
  </a>
12
12
  </div>
@@ -43,6 +43,10 @@ module Decidim
43
43
  HTML
44
44
  end
45
45
 
46
+ def online_meeting_url
47
+ URI::Parser.new.escape(model.online_meeting_url)
48
+ end
49
+
46
50
  def display_online_meeting_url?
47
51
  return true unless model.respond_to?(:online?)
48
52
  return true unless model.respond_to?(:iframe_access_level_allowed_for_user?)
@@ -1,7 +1,7 @@
1
1
  <%= link_to resource_path, class: classes[:default], id: resource_id do %>
2
2
  <div class="<%= classes[:img] %>">
3
3
  <% if has_image? %>
4
- <%= image_tag resource_image_path, alt: alt_title %>
4
+ <%= image_tag resource_image_url, alt: alt_title %>
5
5
  <% else %>
6
6
  <%= external_icon "media/images/placeholder-card-g.svg", class: "card__placeholder-g" %>
7
7
  <% end %>
@@ -52,12 +52,15 @@ module Decidim
52
52
  @id_base_name ||= resource.class.name.gsub(/\ADecidim::/, "").underscore.split("/").join("__")
53
53
  end
54
54
 
55
- def resource_image_path
55
+ def resource_image_url
56
+ # Backwards compatibility.
57
+ return resource_image_path if respond_to?(:resource_image_path)
58
+
56
59
  nil
57
60
  end
58
61
 
59
62
  def has_image?
60
- resource_image_path.present?
63
+ resource_image_url.present?
61
64
  end
62
65
 
63
66
  def show_description?
@@ -1,6 +1,6 @@
1
1
  <div class="card__list-image">
2
- <% if resource_image_path.present? %>
3
- <%= image_tag resource_image_path, class: "w-full h-full object-cover" %>
2
+ <% if has_image? %>
3
+ <%= image_tag resource_image_url, class: "w-full h-full object-cover" %>
4
4
  <% else %>
5
5
  <div class="w-full h-full relative">
6
6
  <div class="w-full h-full bg-primary opacity-10 absolute top-0 left-0 z-10">
@@ -66,12 +66,15 @@ module Decidim
66
66
  "#{class_base_name}__#{class_name}"
67
67
  end
68
68
 
69
- def resource_image_path
69
+ def resource_image_url
70
+ # Backwards compatibility.
71
+ return resource_image_path if respond_to?(:resource_image_path)
72
+
70
73
  nil
71
74
  end
72
75
 
73
76
  def has_image?
74
- resource_image_path.present?
77
+ resource_image_url.present?
75
78
  end
76
79
 
77
80
  def has_link_to_resource?
@@ -15,7 +15,7 @@ module Decidim
15
15
  end
16
16
 
17
17
  def background_image
18
- model.images_container.attached_uploader(:background_image).path(variant: :big)
18
+ model.images_container.attached_uploader(:background_image).variant_url(:big)
19
19
  end
20
20
 
21
21
  private
@@ -1,4 +1,4 @@
1
- <section id="highlighted_content_banner" class="home__section-image" style="--hero-image:url('<%= current_organization.attached_uploader(:highlighted_content_banner_image).path %>');">
1
+ <section id="highlighted_content_banner" class="home__section-image" style="--hero-image:url('<%= current_organization.attached_uploader(:highlighted_content_banner_image).url %>');">
2
2
  <div class="home__section-content-banner home__section">
3
3
  <div>
4
4
  <h2 class="home__section-content-banner__title">
@@ -32,9 +32,9 @@ module Decidim
32
32
  # If it is called from the landing page content block, use the background image defined there
33
33
  # Else, use the banner image defined in the space (for assemblies)
34
34
  def image_path
35
- return model.images_container.attached_uploader(:background_image).path if model.respond_to?(:images_container)
35
+ return model.images_container.attached_uploader(:background_image).url if model.respond_to?(:images_container)
36
36
 
37
- attached_uploader(:banner_image).path
37
+ attached_uploader(:banner_image).url
38
38
  end
39
39
 
40
40
  def has_hashtag?
@@ -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" aria-hidden="true">
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" %>
@@ -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-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
- <%= filter_form_for filter, form_path, :class => "new_filter", :id => "dropdown-menu-resource", "aria-hidden" => true do |form| %>
12
- <%= form.collection_radio_buttons(
13
- filter_param_key,
14
- resource_types,
15
- :first,
16
- :last,
17
- { checked: filter_param }
18
- ) do |builder|
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
- end %>
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>
@@ -55,7 +55,12 @@ module Decidim
55
55
  # If user has left the account unconfirmed and later on decides to sign
56
56
  # in with omniauth with an already verified account, the account needs
57
57
  # to be marked confirmed.
58
- @user.skip_confirmation! if !@user.confirmed? && @user.email == verified_email
58
+ if !@user.confirmed? && @user.email == verified_email
59
+ @user.skip_confirmation!
60
+ @user.after_confirmation
61
+ end
62
+ @user.tos_agreement = "1"
63
+ @user.save!
59
64
  else
60
65
  @user.email = (verified_email || form.email)
61
66
  @user.name = form.name
@@ -69,10 +74,11 @@ module Decidim
69
74
  @user.avatar.attach(io: file, filename:)
70
75
  end
71
76
  @user.skip_confirmation! if verified_email
72
- end
77
+ @user.tos_agreement = "1"
78
+ @user.save!
73
79
 
74
- @user.tos_agreement = "1"
75
- @user.save!
80
+ @user.after_confirmation if verified_email
81
+ end
76
82
  end
77
83
 
78
84
  def create_identity
@@ -21,6 +21,7 @@ module Decidim
21
21
  include Decidim::SafeRedirect
22
22
  include NeedsSnippets
23
23
  include UserBlockedChecker
24
+ include ActiveStorage::SetCurrent
24
25
 
25
26
  helper Decidim::TranslationsHelper
26
27
  helper Decidim::MetaTagsHelper
@@ -7,7 +7,7 @@ module Decidim
7
7
  module Paginable
8
8
  extend ActiveSupport::Concern
9
9
 
10
- OPTIONS = [10, 20, 50, 100].freeze
10
+ OPTIONS = [25, 50, 100].freeze
11
11
 
12
12
  included do
13
13
  helper_method :per_page, :page_offset
@@ -24,6 +24,7 @@ module Decidim
24
24
  include DisableRedirectionToExternalHost
25
25
  include NeedsPasswordChange
26
26
  include LinkedResourceReference
27
+ include ActiveStorage::SetCurrent
27
28
 
28
29
  helper Decidim::MetaTagsHelper
29
30
  helper Decidim::DecidimFormHelper
@@ -57,7 +57,7 @@ module Decidim
57
57
  self,
58
58
  element_class: "font-semibold underline",
59
59
  active_class: "is-active",
60
- container_options: { class: "space-y-4 break-inside-avoid" },
60
+ container_options: { class: "space-y-4 break-inside-avoid", role: :menu },
61
61
  label: t("layouts.decidim.footer.decidim_title")
62
62
  )
63
63
  end
@@ -11,16 +11,14 @@ module Decidim
11
11
  def decidim_paginate(collection, paginate_params = {})
12
12
  return if collection.total_pages <= 1
13
13
 
14
+ per_page = (params[:per_page] || paginate_params[:per_page] || Decidim::Paginable::OPTIONS.first).to_i
15
+
14
16
  content_tag :div, class: "flex flex-col-reverse md:flex-row items-center justify-between gap-1 py-8 md:py-16", data: { pagination: "" } do
15
17
  template = ""
16
- template += render(partial: "decidim/shared/results_per_page", formats: [:html]) if collection.total_pages.positive?
18
+ template += render(partial: "decidim/shared/results_per_page", locals: { per_page: }, formats: [:html]) if collection.total_pages.positive?
17
19
  template += paginate collection, window: 2, outer_window: 1, theme: "decidim", params: paginate_params
18
20
  template.html_safe
19
21
  end
20
22
  end
21
-
22
- def per_page
23
- params[:per_page].to_i || Decidim::Paginable::OPTIONS.first
24
- end
25
23
  end
26
24
  end
@@ -84,11 +84,12 @@ module Decidim
84
84
  #
85
85
  # Returns String.
86
86
  def url
87
- if file?
88
- attached_uploader(:file).path
89
- elsif link?
90
- link
91
- end
87
+ @url ||=
88
+ if file?
89
+ attached_uploader(:file).url
90
+ elsif link?
91
+ link
92
+ end
92
93
  end
93
94
 
94
95
  # The URL to download the thumbnail of the file. Only works with images.
@@ -97,7 +98,7 @@ module Decidim
97
98
  def thumbnail_url
98
99
  return unless photo?
99
100
 
100
- attached_uploader(:file).path(variant: :thumbnail)
101
+ @thumbnail_url ||= attached_uploader(:file).variant_url(:thumbnail)
101
102
  end
102
103
 
103
104
  # The URL to download the a big version of the file. Only works with images.
@@ -106,7 +107,7 @@ module Decidim
106
107
  def big_url
107
108
  return unless photo?
108
109
 
109
- attached_uploader(:file).path(variant: :big)
110
+ @big_url ||= attached_uploader(:file).variant_url(:big)
110
111
  end
111
112
 
112
113
  def set_content_type_and_size
@@ -14,7 +14,10 @@ module Decidim
14
14
 
15
15
  belongs_to :participatory_space, polymorphic: true
16
16
 
17
- default_scope { order(arel_table[:weight].asc, arel_table[:manifest_name].asc) }
17
+ scope :registered_component_manifests, -> { where(manifest_name: Decidim.component_registry.manifests.collect(&:name)) }
18
+ scope :registered_space_manifests, -> { where(participatory_space_type: Decidim.participatory_space_registry.manifests.collect(&:model_class_name)) }
19
+
20
+ default_scope { registered_component_manifests.registered_space_manifests.order(arel_table[:weight].asc, arel_table[:manifest_name].asc) }
18
21
 
19
22
  delegate :organization, :categories, to: :participatory_space
20
23
 
@@ -60,8 +60,8 @@ module Decidim
60
60
  #
61
61
  # # This is how you can access the image data, just like with any other
62
62
  # # uploader field. You can use the uploader variants too.
63
- # content_block.images_container.attached_uploader(:my_image).path
64
- # content_block.images_container.attached_uploader(:my_image).path(variant: :big)
63
+ # content_block.images_container.attached_uploader(:my_image).url
64
+ # content_block.images_container.attached_uploader(:my_image).variant_url(:big)
65
65
  #
66
66
  # # This will delete the attached image
67
67
  # content_block.images_container.my_image = nil
@@ -278,6 +278,18 @@ module Decidim
278
278
  false
279
279
  end
280
280
 
281
+ def after_confirmation
282
+ return unless organization.send_welcome_notification?
283
+
284
+ Decidim::EventsManager.publish(
285
+ event: "decidim.events.core.welcome_notification",
286
+ event_class: WelcomeNotificationEvent,
287
+ resource: self,
288
+ affected_users: [self],
289
+ extra: { force_email: true }
290
+ )
291
+ end
292
+
281
293
  protected
282
294
 
283
295
  # Overrides devise email required validation.
@@ -296,18 +308,6 @@ module Decidim
296
308
  super
297
309
  end
298
310
 
299
- def after_confirmation
300
- return unless organization.send_welcome_notification?
301
-
302
- Decidim::EventsManager.publish(
303
- event: "decidim.events.core.welcome_notification",
304
- event_class: WelcomeNotificationEvent,
305
- resource: self,
306
- affected_users: [self],
307
- extra: { force_email: true }
308
- )
309
- end
310
-
311
311
  private
312
312
 
313
313
  # Changes default Devise behaviour to use ActiveJob to send async emails.
@@ -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
 
@@ -36,10 +36,14 @@ const initializeTabs = (container) => {
36
36
  updateTabsState(container);
37
37
  });
38
38
 
39
- uploadsContainer.addEventListener("DOMSubtreeModified", () => {
40
- updateTabsState(container);
41
- console.log("DOMSubtreeModified");
39
+ const observer = new MutationObserver((mutationsList) => {
40
+ mutationsList.forEach((mutation) => {
41
+ if (mutation.type === "childList") {
42
+ updateTabsState(container);
43
+ }
44
+ });
42
45
  });
46
+ observer.observe(uploadsContainer, {childList: true, subtree: true});
43
47
 
44
48
  updateTabsState(container);
45
49
  };
@@ -74,7 +74,7 @@ export default class InputCharacterCounter {
74
74
 
75
75
  // If input is a hidden for WYSIWYG editor add it at the end
76
76
  if (this.$input.parent().is(".editor")) {
77
- this.$input.parent().after(this.$target);
77
+ this.$input.parent().append(container);
78
78
  } else {
79
79
  const wrapper = document.createElement("span")
80
80
  wrapper.className = "input-character-counter"
@@ -72,6 +72,15 @@
72
72
  .dropdown {
73
73
  @apply absolute border-2 border-gray-3 rounded min-w-max p-4 drop-shadow-md text-left z-10;
74
74
 
75
+ /*
76
+ NOTE: the calculated value is the sum of the arrow offset position plus the half of the arrow size:
77
+ - offset position: 20%
78
+ - arrow size: 1.5rem
79
+ */
80
+ --arrow-offset: 20%;
81
+ --arrow-size: 1.5rem;
82
+ --arrow-visible-size: var(--arrow-size) * 0.5;
83
+
75
84
  & > * {
76
85
  @apply relative z-10 p-3.5 first:pt-1.5 last:pb-1.5;
77
86
  }
@@ -90,15 +99,6 @@
90
99
  }
91
100
  }
92
101
 
93
- /*
94
- NOTE: the calculated value is the sum of the arrow offset position plus the half of the arrow size:
95
- - offset position: 20%
96
- - arrow size: 1.5rem
97
- */
98
- --arrow-offset: 20%;
99
- --arrow-size: 1.5rem;
100
- --arrow-visible-size: var(--arrow-size) * 0.5;
101
-
102
102
  &__bottom {
103
103
  @apply top-full right-0 mt-3 translate-x-[calc(var(--arrow-offset)-var(--arrow-visible-size))] before:content-[''] before:absolute before:right-[var(--arrow-offset)] before:-top-2 before:w-[var(--arrow-size)] before:h-[var(--arrow-size)] before:rotate-45 before:bg-white before:rounded before:border-2 before:border-gray-3 after:content-[''] after:absolute after:left-0 after:top-0 after:w-full after:h-full after:bg-white;
104
104
  }
@@ -1,6 +1,8 @@
1
1
  .filter {
2
+ @apply flex gap-2 p-1.5 relative;
3
+
2
4
  label {
3
- @apply flex items-center gap-2 p-1.5 rounded cursor-pointer relative;
5
+ @apply flex items-center gap-2 p-1.5 rounded cursor-pointer relative w-full;
4
6
  }
5
7
 
6
8
  &-container {
@@ -3,7 +3,7 @@ footer {
3
3
  @apply bg-gray-4;
4
4
 
5
5
  &__top {
6
- @apply hidden flex flex-col lg:flex-row lg:block gap-8 container py-10;
6
+ @apply hidden lg:flex flex-row gap-8 container py-10;
7
7
  }
8
8
 
9
9
  &__down {
@@ -53,16 +53,16 @@
53
53
  }
54
54
 
55
55
  select {
56
- &:not(.reset-defaults) {
57
- @apply pr-8;
58
- }
59
-
60
56
  @apply appearance-none;
61
57
 
62
58
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 12 8'%3e%3cpath fill='%233E4C5C' d='M5.99962 4.97656L10.1246 0.851562L11.303 2.0299L5.99962 7.33323L0.696289 2.0299L1.87462 0.851562L5.99962 4.97656Z'/%3e%3c/svg%3e");
63
59
  background-position: right 1rem center;
64
60
  background-repeat: no-repeat;
65
61
  background-size: 0.75rem;
62
+
63
+ &:not(.reset-defaults) {
64
+ @apply pr-8;
65
+ }
66
66
  }
67
67
  }
68
68
 
@@ -1,6 +1,16 @@
1
1
  [role="tooltip"] {
2
2
  @apply absolute bg-black z-10 px-4 py-2 w-max max-w-xs rounded text-left text-white;
3
3
 
4
+ /*
5
+ NOTE: the calculated value is the sum of the arrow offset position plus the half of the arrow size:
6
+ - offset position: 20%
7
+ - arrow size: 16px
8
+ */
9
+ --arrow-offset: 20%;
10
+ --arrow-size: 16px;
11
+ --arrow-visible-size: var(--arrow-size) * 0.5;
12
+ --arrow-margin: var(--arrow-visible-size) * 1.4142135623730951; // due to the rotation, the margin is SQRT2 times the visible size
13
+
4
14
  & > * {
5
15
  @apply relative z-20;
6
16
  }
@@ -41,16 +51,6 @@
41
51
  }
42
52
  }
43
53
 
44
- /*
45
- NOTE: the calculated value is the sum of the arrow offset position plus the half of the arrow size:
46
- - offset position: 20%
47
- - arrow size: 16px
48
- */
49
- --arrow-offset: 20%;
50
- --arrow-size: 16px;
51
- --arrow-visible-size: var(--arrow-size) * 0.5;
52
- --arrow-margin: var(--arrow-visible-size) * 1.4142135623730951; // due to the rotation, the margin is SQRT2 times the visible size
53
-
54
54
  &.top {
55
55
  @apply -translate-x-[calc(100%-var(--arrow-offset))] -translate-y-[calc(100%+var(--arrow-margin))] before:content-[''] before:absolute before:-z-10 before:right-[calc(var(--arrow-offset)-var(--arrow-visible-size))] before:-bottom-[var(--arrow-visible-size)] before:w-[var(--arrow-size)] before:h-[var(--arrow-size)] before:rotate-45 before:bg-black before:rounded-br;
56
56
  }
@@ -21,7 +21,7 @@
21
21
  }
22
22
 
23
23
  .editor-container {
24
- @apply editor-props editor-suggestions-props flex flex-col mb-6 border editor-border;
24
+ @apply editor-props editor-suggestions-props flex flex-col mt-4 border editor-border;
25
25
 
26
26
  &.editor-disabled {
27
27
  .editor-input .ProseMirror {
@@ -26,7 +26,7 @@ module Decidim
26
26
  delegate :content_tag, :safe_join, :link_to, :active_link_to_class, :is_active_link?, :icon, to: :@view
27
27
 
28
28
  def render
29
- content_tag :li, class: link_wrapper_classes do
29
+ content_tag :li, role: :menuitem, class: link_wrapper_classes do
30
30
  output = if url == "#"
31
31
  [content_tag(:span, composed_label, class: "sidebar-menu__item-disabled")]
32
32
  else
@@ -51,13 +51,14 @@ module Decidim
51
51
  headers.push(*exporter.headers)
52
52
  exported = exporter.export
53
53
 
54
- tmpfile = Tempfile.new("#{export_manifest.name}-#{component.id}-")
55
- tmpfile.write(exported.read)
56
- # Do not delete the file when the reference is deleted
57
- ObjectSpace.undefine_finalizer(tmpfile)
58
- tmpfile.close
59
-
60
- collection.push(tmpfile.path)
54
+ tmpdir = Dir::Tmpname.create(export_manifest.name.to_s) do
55
+ # just get an empty file name
56
+ end
57
+ filename = File.join(tmpdir, "#{component.id}.csv")
58
+ Dir.mkdir(tmpdir)
59
+ File.write(filename, exported.read)
60
+
61
+ collection.push(filename)
61
62
  end
62
63
  end
63
64
  end
@@ -8,22 +8,22 @@
8
8
  "background_color": "#FFFFFF",
9
9
  "icons": [
10
10
  {
11
- "src": "<%= current_organization.attached_uploader(:favicon).variant_path :small %>",
11
+ "src": "<%= current_organization.attached_uploader(:favicon).variant_url :small %>",
12
12
  "sizes": "32x32",
13
13
  "type": "image/png"
14
14
  },
15
15
  {
16
- "src": "<%= current_organization.attached_uploader(:favicon).variant_path :medium %>",
16
+ "src": "<%= current_organization.attached_uploader(:favicon).variant_url :medium %>",
17
17
  "sizes": "180x180",
18
18
  "type": "image/png"
19
19
  },
20
20
  {
21
- "src": "<%= current_organization.attached_uploader(:favicon).variant_path :big %>",
21
+ "src": "<%= current_organization.attached_uploader(:favicon).variant_url :big %>",
22
22
  "sizes": "192x192",
23
23
  "type": "image/png"
24
24
  },
25
25
  {
26
- "src": "<%= current_organization.attached_uploader(:favicon).variant_path :huge %>",
26
+ "src": "<%= current_organization.attached_uploader(:favicon).variant_url :huge %>",
27
27
  "sizes": "512x512",
28
28
  "type": "image/png"
29
29
  }
@@ -11,16 +11,16 @@
11
11
 
12
12
  <div class="vertical-tabs">
13
13
  <nav>
14
- <button id="dropdown-trigger-pages" data-component="dropdown" data-target="dropdown-menu-pages" data-auto-close="true">
14
+ <button id="dropdown-trigger-pages" data-component="dropdown" data-target="dropdown-menu-pages" data-open-md="true" data-auto-close="true">
15
15
  <span>
16
16
  <%= translated_attribute(page.title) %>
17
17
  </span>
18
18
  <%= icon "arrow-down-s-line" %>
19
19
  <%= icon "arrow-up-s-line" %>
20
20
  </button>
21
- <ul id="dropdown-menu-pages" class="vertical-tabs__list" aria-hidden="true">
21
+ <ul id="dropdown-menu-pages" class="vertical-tabs__list" role="menu">
22
22
  <% pages.each do |sibling| %>
23
- <li class="<%= "is-active" if page == sibling %>">
23
+ <li class="<%= "is-active" if page == sibling %>" role="menuitem">
24
24
  <%= link_to translated_attribute(sibling.title), page_path(sibling.slug) %>
25
25
  </li>
26
26
  <% end %>