decidim-core 0.28.2 → 0.28.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) 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/commands/decidim/create_omniauth_registration.rb +10 -4
  12. data/app/controllers/concerns/decidim/devise_controllers.rb +1 -0
  13. data/app/controllers/concerns/decidim/paginable.rb +1 -1
  14. data/app/controllers/decidim/application_controller.rb +1 -0
  15. data/app/helpers/decidim/paginate_helper.rb +3 -5
  16. data/app/models/decidim/attachment.rb +3 -3
  17. data/app/models/decidim/component.rb +4 -1
  18. data/app/models/decidim/content_block.rb +2 -2
  19. data/app/models/decidim/user.rb +12 -12
  20. data/app/packs/src/decidim/input_character_counter.js +1 -1
  21. data/app/packs/stylesheets/decidim/_dropdown.scss +9 -9
  22. data/app/packs/stylesheets/decidim/_forms.scss +4 -4
  23. data/app/packs/stylesheets/decidim/_tooltip.scss +10 -10
  24. data/app/packs/stylesheets/decidim/editor.scss +1 -1
  25. data/app/services/decidim/download_your_data_exporter.rb +36 -25
  26. data/app/services/decidim/open_data_exporter.rb +8 -7
  27. data/app/views/decidim/manifests/show.json.erb +4 -4
  28. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  29. data/app/views/layouts/decidim/footer/_main_intro.html.erb +1 -1
  30. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +1 -1
  31. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +1 -1
  32. data/config/locales/ca.yml +3 -3
  33. data/config/locales/cs.yml +2 -0
  34. data/config/locales/fi-plain.yml +3 -3
  35. data/config/locales/fi.yml +28 -28
  36. data/config/locales/is-IS.yml +3 -0
  37. data/config/locales/sv.yml +124 -87
  38. data/db/migrate/20181025082245_add_timestamps_to_components.rb +5 -1
  39. data/decidim-core.gemspec +0 -1
  40. data/lib/decidim/asset_router/storage.rb +214 -11
  41. data/lib/decidim/core/engine.rb +8 -0
  42. data/lib/decidim/core/test/shared_examples/attachable_interface_examples.rb +1 -1
  43. data/lib/decidim/core/test/shared_examples/follows_examples.rb +8 -3
  44. data/lib/decidim/core/test/shared_examples/paginated_resource_examples.rb +5 -5
  45. data/lib/decidim/core/version.rb +1 -1
  46. data/lib/decidim/seven_zip_wrapper.rb +29 -0
  47. data/lib/tasks/upgrade/decidim_fix_categorization.rake +101 -1
  48. metadata +7 -21
  49. data/app/services/decidim/zip_stream/writer.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 524ec4d380f620c07119a6ccbee1b28408f6072799aa32cd74a1836f1ede5070
4
- data.tar.gz: 4e1b60ce9a2cb9e340b0db3a22f66b326ade8f05cb8551352b39fe4198a06bbb
3
+ metadata.gz: 7ed7b2e2e440e7ab68c508dc8242f6adbee52c292cfa8fd3fd43e42fc75e8f8f
4
+ data.tar.gz: ee75d95c1002bc872483de673a2e21e23c100d387d2bd50d86bb05ed5a91d1fa
5
5
  SHA512:
6
- metadata.gz: c8ff8135707ab3ae9aa1d483cd41d104385c079e8dcbd575c3c618ae05c524c345b340bd4b82c47eccf533dc98e187985ba76ddb2293332977449ed8af95b4b3
7
- data.tar.gz: 9188473aa2d7c440f2aa773e9e08824b2c847f8a29a6d1d1ff75900e9a2fd325f860d80d8faad5d2498dc594f20b92ad9e8f7e6b98551ba9f68ffe24a879dcc1
6
+ metadata.gz: d82a46910165f8510bec81d79677b26057d49e88ddc9ddd3fda2443b0d8529804faebb2eb8949313b4cf4c25fc8fd406da049dc2e33d172430d7614dc043b9cd
7
+ data.tar.gz: e86a808c22abc5db470d2bcf7d9427a2d8ea13588a73fcbde936fbd22c381d606f30b45353e3638f39150e16966cf75edcf6d81698164b3bdef9055b1881a02f
@@ -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>
@@ -45,6 +45,10 @@ module Decidim
45
45
  HTML
46
46
  end
47
47
 
48
+ def online_meeting_url
49
+ URI::Parser.new.escape(model.online_meeting_url)
50
+ end
51
+
48
52
  def display_online_meeting_url?
49
53
  return true unless model.respond_to?(:online?)
50
54
  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">
@@ -68,12 +68,15 @@ module Decidim
68
68
  "#{class_base_name}__#{class_name}"
69
69
  end
70
70
 
71
- def resource_image_path
71
+ def resource_image_url
72
+ # Backwards compatibility.
73
+ return resource_image_path if respond_to?(:resource_image_path)
74
+
72
75
  nil
73
76
  end
74
77
 
75
78
  def has_image?
76
- resource_image_path.present?
79
+ resource_image_url.present?
77
80
  end
78
81
 
79
82
  def has_link_to_resource?
@@ -16,7 +16,7 @@ module Decidim
16
16
  end
17
17
 
18
18
  def background_image
19
- model.images_container.attached_uploader(:background_image).path(variant: :big)
19
+ model.images_container.attached_uploader(:background_image).variant_url(:big)
20
20
  end
21
21
 
22
22
  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">
@@ -34,9 +34,9 @@ module Decidim
34
34
  # If it is called from the landing page content block, use the background image defined there
35
35
  # Else, use the banner image defined in the space (for assemblies)
36
36
  def image_path
37
- return model.images_container.attached_uploader(:background_image).path if model.respond_to?(:images_container)
37
+ return model.images_container.attached_uploader(:background_image).url if model.respond_to?(:images_container)
38
38
 
39
- attached_uploader(:banner_image).path
39
+ attached_uploader(:banner_image).url
40
40
  end
41
41
 
42
42
  def has_hashtag?
@@ -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
@@ -20,6 +20,7 @@ module Decidim
20
20
  include Decidim::SafeRedirect
21
21
  include NeedsSnippets
22
22
  include UserBlockedChecker
23
+ include ActiveStorage::SetCurrent
23
24
 
24
25
  helper Decidim::TranslationsHelper
25
26
  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
@@ -23,6 +23,7 @@ module Decidim
23
23
  include DisableRedirectionToExternalHost
24
24
  include NeedsPasswordChange
25
25
  include LinkedResourceReference
26
+ include ActiveStorage::SetCurrent
26
27
 
27
28
  helper Decidim::MetaTagsHelper
28
29
  helper Decidim::DecidimFormHelper
@@ -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
@@ -69,7 +69,7 @@ module Decidim
69
69
  end
70
70
 
71
71
  def url
72
- attached_uploader(:file).path
72
+ attached_uploader(:file).url
73
73
  end
74
74
 
75
75
  # The URL to download the thumbnail of the file. Only works with images.
@@ -78,7 +78,7 @@ module Decidim
78
78
  def thumbnail_url
79
79
  return unless photo?
80
80
 
81
- attached_uploader(:file).path(variant: :thumbnail)
81
+ @thumbnail_url ||= attached_uploader(:file).variant_url(:thumbnail)
82
82
  end
83
83
 
84
84
  # The URL to download the a big version of the file. Only works with images.
@@ -87,7 +87,7 @@ module Decidim
87
87
  def big_url
88
88
  return unless photo?
89
89
 
90
- attached_uploader(:file).path(variant: :big)
90
+ @big_url ||= attached_uploader(:file).variant_url(:big)
91
91
  end
92
92
 
93
93
  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.
@@ -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"
@@ -36,6 +36,15 @@
36
36
  .dropdown {
37
37
  @apply absolute border-2 border-gray-3 rounded min-w-max p-4 drop-shadow-md text-left z-10;
38
38
 
39
+ /*
40
+ NOTE: the calculated value is the sum of the arrow offset position plus the half of the arrow size:
41
+ - offset position: 20%
42
+ - arrow size: 1.5rem
43
+ */
44
+ --arrow-offset: 20%;
45
+ --arrow-size: 1.5rem;
46
+ --arrow-visible-size: var(--arrow-size) * 0.5;
47
+
39
48
  & > * {
40
49
  @apply relative z-10 p-3.5 first:pt-1.5 last:pb-1.5;
41
50
  }
@@ -54,15 +63,6 @@
54
63
  }
55
64
  }
56
65
 
57
- /*
58
- NOTE: the calculated value is the sum of the arrow offset position plus the half of the arrow size:
59
- - offset position: 20%
60
- - arrow size: 1.5rem
61
- */
62
- --arrow-offset: 20%;
63
- --arrow-size: 1.5rem;
64
- --arrow-visible-size: var(--arrow-size) * 0.5;
65
-
66
66
  &__bottom {
67
67
  @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;
68
68
  }
@@ -45,16 +45,16 @@
45
45
  }
46
46
 
47
47
  select {
48
- &:not(.reset-defaults) {
49
- @apply pr-8;
50
- }
51
-
52
48
  @apply appearance-none;
53
49
 
54
50
  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");
55
51
  background-position: right 1rem center;
56
52
  background-repeat: no-repeat;
57
53
  background-size: 0.75rem;
54
+
55
+ &:not(.reset-defaults) {
56
+ @apply pr-8;
57
+ }
58
58
  }
59
59
  }
60
60
 
@@ -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 {
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "seven_zip_ruby"
4
- require "zip"
5
- require_relative "zip_stream/writer"
3
+ require "decidim/seven_zip_wrapper"
6
4
 
7
5
  module Decidim
8
6
  # Public: Generates a 7z(seven zip) file with data files ready to be persisted
@@ -10,8 +8,6 @@ module Decidim
10
8
  #
11
9
  # In fact, the 7z file wraps a ZIP file which finally contains the data files.
12
10
  class DownloadYourDataExporter
13
- include ::Decidim::ZipStream::Writer
14
-
15
11
  DEFAULT_EXPORT_FORMAT = "CSV"
16
12
  ZIP_FILE_NAME = "download-your-data.zip"
17
13
 
@@ -29,36 +25,25 @@ module Decidim
29
25
  end
30
26
 
31
27
  def export
32
- dirname = File.dirname(@path)
33
- FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
34
- File.open(@path, "wb") do |file|
35
- SevenZipRuby::Writer.open(file, password: @password) do |szw|
36
- szw.header_encryption = true
37
- szw.add_data(data, ZIP_FILE_NAME)
38
- end
39
- end
28
+ tmpdir = Dir.mktmpdir("temporary-download-your-data-dir")
29
+ user_data, user_attachments = data_and_attachments_for_user
30
+ save_user_data(tmpdir, user_data)
31
+ save_user_attachments(tmpdir, user_attachments)
32
+
33
+ SevenZipWrapper.compress_and_encrypt(filename: @path, password: @password, input_directory: tmpdir)
40
34
  end
41
35
 
42
36
  private
43
37
 
44
- def data
45
- buffer = Zip::OutputStream.write_buffer do |out|
46
- user_data, attachments = data_for(@user, @export_format)
38
+ attr_reader :user, :export_format
47
39
 
48
- add_user_data_to_zip_stream(out, user_data)
49
- add_attachments_to_zip_stream(out, attachments)
50
- end
51
-
52
- buffer.string
53
- end
54
-
55
- def data_for(user, format)
40
+ def data_and_attachments_for_user
56
41
  export_data = []
57
42
  export_attachments = []
58
43
 
59
44
  download_your_data_entities.each do |object|
60
45
  klass = Object.const_get(object)
61
- export_data << [klass.model_name.name.parameterize.pluralize, Exporters.find_exporter(format).new(klass.user_collection(user), klass.export_serializer).export]
46
+ export_data << [klass.model_name.name.parameterize.pluralize, Exporters.find_exporter(export_format).new(klass.user_collection(user), klass.export_serializer).export]
62
47
  attachments = klass.download_your_data_images(user)
63
48
  export_attachments << [klass.model_name.name.parameterize.pluralize, attachments.flatten] unless attachments.nil?
64
49
  end
@@ -69,5 +54,31 @@ module Decidim
69
54
  def download_your_data_entities
70
55
  @download_your_data_entities ||= DownloadYourDataSerializers.data_entities
71
56
  end
57
+
58
+ def save_user_data(tmpdir, user_data)
59
+ user_data.each do |entity, exporter_data|
60
+ next if exporter_data.read == "\n"
61
+
62
+ file_name = File.join(tmpdir, "#{entity}-#{exporter_data.filename}")
63
+ File.write(file_name, exporter_data.read)
64
+ end
65
+ end
66
+
67
+ def save_user_attachments(tmpdir, user_attachments)
68
+ user_attachments.each do |entity, attachment_block|
69
+ attachment_block.each do |attachment|
70
+ next unless attachment.attached?
71
+
72
+ blobs = attachment.is_a?(ActiveStorage::Attached::One) ? [attachment.blob] : attachment.blobs
73
+ blobs.each do |blob|
74
+ Dir.mkdir(File.join(tmpdir, entity.parameterize))
75
+ file_name = File.join(tmpdir, entity.parameterize, blob.filename.to_s)
76
+ blob.open do |blob_file|
77
+ File.write(file_name, blob_file.read.force_encoding("UTF-8"))
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
72
83
  end
73
84
  end
@@ -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
  }
@@ -1,7 +1,7 @@
1
1
  <% if organization %>
2
2
  <%= link_to decidim.root_url(host: organization.host), "aria-label": t("front_page_link", scope: "decidim.accessibility") do %>
3
3
  <% if organization.logo.attached? %>
4
- <%= image_tag organization.attached_uploader(:logo).variant_path(:medium), alt: t("logo", scope: "decidim.accessibility", organization: organization.name) %>
4
+ <%= image_tag organization.attached_uploader(:logo).variant_url(:medium), alt: t("logo", scope: "decidim.accessibility", organization: organization.name) %>
5
5
  <% else %>
6
6
  <span><%= organization.name %></span>
7
7
  <% end %>
@@ -1,6 +1,6 @@
1
1
  <% if current_organization.official_img_footer.attached? %>
2
2
  <%= link_to current_organization.official_url, class: "block mb-6" do %>
3
- <%= image_tag current_organization.attached_uploader(:official_img_footer).path, alt: current_organization.name, class: "max-h-16" %>
3
+ <%= image_tag current_organization.attached_uploader(:official_img_footer).url, alt: current_organization.name, class: "max-h-16" %>
4
4
  <% end %>
5
5
  <% end %>
6
6
  <div class="text-sm text-white prose">
@@ -35,7 +35,7 @@
35
35
  <span class="main-bar__avatar">
36
36
  <span>
37
37
  <%= image_tag(
38
- current_user.attached_uploader(:avatar).path(variant: :thumb),
38
+ current_user.attached_uploader(:avatar).variant_url(:thumb),
39
39
  alt: t("decidim.author.avatar", name: decidim_sanitize(current_user.avatar.name))
40
40
  ) %>
41
41
  </span>
@@ -15,7 +15,7 @@
15
15
  <% if current_user.avatar.attached? %>
16
16
  <div class="main-bar__avatar">
17
17
  <%= image_tag(
18
- current_user.attached_uploader(:avatar).path(variant: :thumb),
18
+ current_user.attached_uploader(:avatar).variant_url(:thumb),
19
19
  alt: t("decidim.author.avatar", name: decidim_sanitize(current_user.avatar.name))
20
20
  ) %>
21
21
  </div>
@@ -533,8 +533,8 @@ ca:
533
533
  html_content: Contingut HTML
534
534
  name: Bloc HTML
535
535
  last_activity:
536
- name: Última activitat
537
- title: Última activitat
536
+ name: Darrera activitat
537
+ title: Darrera activitat
538
538
  view_all: Veure-ho tot
539
539
  last_activity_settings_form:
540
540
  max_last_activity_users: Número màxim d'avatars de participants amb activitat recent a mostrar
@@ -1041,7 +1041,7 @@ ca:
1041
1041
  last_activities:
1042
1042
  all: Tots els tipus d'activitats
1043
1043
  index:
1044
- last_activity: Última activitat
1044
+ last_activity: Darrera activitat
1045
1045
  name: Darreres activitats
1046
1046
  no_activities_warning: No hi ha res a mostrar per a aquest tipus d'activitat.
1047
1047
  linked_resource_from:
@@ -388,6 +388,7 @@ cs:
388
388
  '1': Vytvořte svůj pozměňovací návrh
389
389
  '2': Porovnejte váš pozměňovací návrh
390
390
  '3': Dokončete váš pozměňovací návrh
391
+ '4': Publikovat svůj pozměňovací návrh
391
392
  anonymous_user: Anonymní
392
393
  application:
393
394
  document:
@@ -1278,6 +1279,7 @@ cs:
1278
1279
  no_notifications: Zatím žádné oznámení.
1279
1280
  show:
1280
1281
  missing_event: Jejda, toto oznámení patří k položce, která již není k dispozici. Můžete ho zahodit.
1282
+ moderated: Obsah upraven
1281
1283
  notifications_digest_mailer:
1282
1284
  header:
1283
1285
  daily: Denní výběr oznámení