decidim-core 0.28.2 → 0.28.3

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 (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í