decidim-core 0.29.0.rc3 → 0.29.0.rc4
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/card_g/show.erb +1 -1
- data/app/cells/decidim/card_g_cell.rb +5 -2
- data/app/cells/decidim/card_l/image.erb +2 -2
- data/app/cells/decidim/card_l_cell.rb +5 -2
- data/app/cells/decidim/content_blocks/hero_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
- data/app/cells/decidim/content_blocks/participatory_space_hero_cell.rb +2 -2
- data/app/commands/decidim/create_omniauth_registration.rb +10 -4
- data/app/controllers/concerns/decidim/devise_controllers.rb +1 -0
- data/app/controllers/decidim/application_controller.rb +1 -0
- data/app/models/decidim/attachment.rb +8 -7
- data/app/models/decidim/content_block.rb +2 -2
- data/app/models/decidim/user.rb +12 -12
- data/app/packs/stylesheets/decidim/_filters.scss +3 -1
- data/app/packs/stylesheets/decidim/_footer.scss +1 -1
- data/app/views/decidim/manifests/show.json.erb +4 -4
- data/app/views/layouts/decidim/_logo.html.erb +1 -1
- data/app/views/layouts/decidim/footer/_main.html.erb +1 -1
- data/app/views/layouts/decidim/footer/_main_intro.html.erb +1 -1
- data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +1 -1
- data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +1 -1
- data/app/views/layouts/decidim/header/_main_links_mobile_item_account.html.erb +1 -1
- data/lib/decidim/asset_router/storage.rb +216 -13
- data/lib/decidim/core/test/shared_examples/attachable_interface_examples.rb +1 -1
- data/lib/decidim/core/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3394fbf408e9109f688cd6e8fa7439096050219d59f5ac6328f6be21a51c752d
|
4
|
+
data.tar.gz: b39954abe8812022859ab60690a82dc89078868cfe89b567ea1a2499d7cb7aa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9402884a433f7bd1d3498bc70429be6704f56c2e3eb4fdb4769ea076d1c9473ee555b5580d142cb7560b6a1ea54d027415ec9821303466fb56c8bfa1889ea611
|
7
|
+
data.tar.gz: 4fcd613c47e4d1a8eed16ef0f3217afa43b4a648f49dbe6a787cb82e7919ef2ba290b1c07b2e39da7d91098620046221b2552eaddc091982eacc03e1f4141db1
|
@@ -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
|
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
|
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
|
-
|
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
|
3
|
-
<%= image_tag
|
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
|
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
|
-
|
77
|
+
resource_image_url.present?
|
75
78
|
end
|
76
79
|
|
77
80
|
def has_link_to_resource?
|
@@ -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).
|
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).
|
35
|
+
return model.images_container.attached_uploader(:background_image).url if model.respond_to?(:images_container)
|
36
36
|
|
37
|
-
attached_uploader(:banner_image).
|
37
|
+
attached_uploader(:banner_image).url
|
38
38
|
end
|
39
39
|
|
40
40
|
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
|
-
|
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
|
-
|
77
|
+
@user.tos_agreement = "1"
|
78
|
+
@user.save!
|
73
79
|
|
74
|
-
|
75
|
-
|
80
|
+
@user.after_confirmation if verified_email
|
81
|
+
end
|
76
82
|
end
|
77
83
|
|
78
84
|
def create_identity
|
@@ -84,11 +84,12 @@ module Decidim
|
|
84
84
|
#
|
85
85
|
# Returns String.
|
86
86
|
def url
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
link
|
91
|
-
|
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).
|
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).
|
110
|
+
@big_url ||= attached_uploader(:file).variant_url(:big)
|
110
111
|
end
|
111
112
|
|
112
113
|
def set_content_type_and_size
|
@@ -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).
|
64
|
-
# content_block.images_container.attached_uploader(:my_image).
|
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
|
data/app/models/decidim/user.rb
CHANGED
@@ -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.
|
@@ -8,22 +8,22 @@
|
|
8
8
|
"background_color": "#FFFFFF",
|
9
9
|
"icons": [
|
10
10
|
{
|
11
|
-
"src": "<%= current_organization.attached_uploader(:favicon).
|
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).
|
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).
|
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).
|
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).
|
4
|
+
<%= image_tag organization.attached_uploader(:logo).variant_url(:medium), alt: t("logo", scope: "decidim.accessibility", organization: current_organization_name) %>
|
5
5
|
<% else %>
|
6
6
|
<span><%= current_organization_name %></span>
|
7
7
|
<% end %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<div class="lg:w-1/3">
|
4
4
|
<%= render partial: "layouts/decidim/footer/main_intro" %>
|
5
5
|
</div>
|
6
|
-
<div class="lg:w-2/3 grid grid-cols-1 gap-x-
|
6
|
+
<div class="lg:w-2/3 grid grid-cols-1 gap-x-4 gap-y-10 lg:grid-cols-4 text-md text-white">
|
7
7
|
<%= render partial: "layouts/decidim/footer/main_links" %>
|
8
8
|
</div>
|
9
9
|
</div>
|
@@ -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).
|
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).
|
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>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
<% if current_user.avatar.attached? %>
|
21
21
|
<div class="main-bar__avatar">
|
22
22
|
<%= image_tag(
|
23
|
-
current_user.attached_uploader(:avatar).
|
23
|
+
current_user.attached_uploader(:avatar).variant_url(:thumb),
|
24
24
|
alt: t("decidim.author.avatar", name: decidim_sanitize(current_user.avatar.name))
|
25
25
|
) %>
|
26
26
|
</div>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<% if current_user.avatar.attached? %>
|
7
7
|
<span class="main-bar__avatar">
|
8
8
|
<%= image_tag(
|
9
|
-
current_user.attached_uploader(:avatar).
|
9
|
+
current_user.attached_uploader(:avatar).variant_url(:thumb),
|
10
10
|
alt: t("decidim.author.avatar", name: decidim_sanitize(current_user.avatar.name))
|
11
11
|
) %>
|
12
12
|
</span>
|
@@ -6,6 +6,23 @@ module Decidim
|
|
6
6
|
# saved through ActiveStorage. This handles the different cases for routing
|
7
7
|
# to the remote routes when using an assets CDN or to local routes when
|
8
8
|
# using the local disk storage driver.
|
9
|
+
#
|
10
|
+
# Note that when the assets are stored in a remote storage service, such as
|
11
|
+
# Amazon S3, Google Cloud Storage or Azure Storage, this generates the asset
|
12
|
+
# URL directly to the storage service itself bypassing the Rails server and
|
13
|
+
# saving CPU time from serving the asset redirect requests. This causes a
|
14
|
+
# significant performance improvement on pages that display a lot of images.
|
15
|
+
# It will also produce a less significant performance improvement when using
|
16
|
+
# the local disk storage because in this situation, the images are served
|
17
|
+
# using one request instead of two when served directly from the storage
|
18
|
+
# service rather than through the asset redirect URL.
|
19
|
+
#
|
20
|
+
# When implementing changes to the logic, please keep the remote storage
|
21
|
+
# options and performance implications in mind because the specs for this
|
22
|
+
# utility do not cover the remote storage options because the extra
|
23
|
+
# configuration needed to test, the service itself needed for testing and
|
24
|
+
# the extra dependency overhead for adding these remote storage gems when
|
25
|
+
# they are not needed.
|
9
26
|
class Storage
|
10
27
|
# Initializes the router.
|
11
28
|
#
|
@@ -13,25 +30,36 @@ module Decidim
|
|
13
30
|
# to
|
14
31
|
def initialize(asset)
|
15
32
|
@asset = asset
|
33
|
+
@blob =
|
34
|
+
case asset
|
35
|
+
when ActiveStorage::Blob
|
36
|
+
asset
|
37
|
+
else
|
38
|
+
asset&.blob
|
39
|
+
end
|
16
40
|
end
|
17
41
|
|
18
42
|
# Generates the correct URL to the asset with the provided options.
|
19
43
|
#
|
20
44
|
# @param options The options for the URL that are the normal route options
|
21
45
|
# Rails route helpers accept
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
46
|
+
# @return [String] The URL of the asset
|
47
|
+
def url(**)
|
48
|
+
case asset
|
49
|
+
when ActiveStorage::Attached
|
50
|
+
ensure_current_host(asset.record, **)
|
51
|
+
blob_url(**)
|
52
|
+
when ActiveStorage::Blob
|
53
|
+
blob_url(**)
|
54
|
+
else # ActiveStorage::VariantWithRecord, ActiveStorage::Variant
|
55
|
+
ensure_current_host(nil, **)
|
56
|
+
representation_url(**)
|
29
57
|
end
|
30
58
|
end
|
31
59
|
|
32
60
|
private
|
33
61
|
|
34
|
-
attr_reader :asset
|
62
|
+
attr_reader :asset, :blob
|
35
63
|
|
36
64
|
# Provides the route helpers depending on whether the URL is generated to
|
37
65
|
# the local host or an external CDN (remote).
|
@@ -80,24 +108,199 @@ module Decidim
|
|
80
108
|
}.compact
|
81
109
|
end
|
82
110
|
|
83
|
-
#
|
84
|
-
#
|
111
|
+
# Most of the times the current host should be set through the controller
|
112
|
+
# already when the logic below is unnecessary. This logic is needed e.g.
|
113
|
+
# for serializers where the request context is not available.
|
114
|
+
#
|
115
|
+
# @param record The record for which to check the organization
|
116
|
+
# @param opts Options for building the URL
|
117
|
+
# @return [void]
|
118
|
+
def ensure_current_host(record, **opts)
|
119
|
+
return if asset_url_available?
|
120
|
+
|
121
|
+
options = remote? ? remote_storage_options : routes.default_url_options
|
122
|
+
options = options.merge(opts)
|
123
|
+
|
124
|
+
if opts[:host].blank? && record.present?
|
125
|
+
organization = organization_for(record)
|
126
|
+
options[:host] = organization.host if organization
|
127
|
+
end
|
128
|
+
|
129
|
+
uri =
|
130
|
+
if options[:protocol] == "https" || options[:scheme] == "https"
|
131
|
+
URI::HTTPS.build(options)
|
132
|
+
else
|
133
|
+
URI::HTTP.build(options)
|
134
|
+
end
|
135
|
+
|
136
|
+
ActiveStorage::Current.url_options = { host: uri.to_s }
|
137
|
+
end
|
138
|
+
|
139
|
+
# Determines the organization for the passed record.
|
85
140
|
#
|
86
|
-
# @
|
141
|
+
# @param record The record for which to fetch the organization
|
142
|
+
# @return [Decidim::Organization, nil] The organization for the record or
|
143
|
+
# `nil` if the organization cannot be determined
|
144
|
+
def organization_for(record)
|
145
|
+
if record.is_a?(Decidim::Organization)
|
146
|
+
record
|
147
|
+
elsif record.respond_to?(:organization)
|
148
|
+
record.organization
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns the URL for the given blob object.
|
153
|
+
#
|
154
|
+
# @param blob The blob object
|
155
|
+
# @param options Options for building the URL
|
156
|
+
# @return [String, nil] The URL to the blob object or `nil` if the blob is
|
157
|
+
# not defined.
|
158
|
+
def blob_url(**options)
|
159
|
+
return unless blob
|
160
|
+
|
161
|
+
if options[:only_path] || remote? || !asset_url_available?
|
162
|
+
routes.rails_blob_url(blob, **default_options.merge(options))
|
163
|
+
else
|
164
|
+
blob.url(**options)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Returns a representation URL for the asset either directly through the
|
169
|
+
# storage service or through the Rails representation URL in case the
|
170
|
+
# path URL is requested or if the asset variant has not been processed yet
|
171
|
+
# and is not therefore yet stored at the storage service.
|
172
|
+
#
|
173
|
+
# @return [String] The representation URL for the image variant
|
87
174
|
def representation_url(**options)
|
175
|
+
return rails_representation_url(**options) if options[:only_path] || remote?
|
176
|
+
|
177
|
+
representation_url = variant_url(**options)
|
178
|
+
return representation_url if representation_url.present?
|
179
|
+
|
180
|
+
# In case the representation has not been processed yet, it may not have
|
181
|
+
# a representation URL yet and it therefore needs to be served through
|
182
|
+
# the local representation URL for the first time (or until it has been
|
183
|
+
# processed).
|
184
|
+
if options[:host]
|
185
|
+
rails_representation_url(**options)
|
186
|
+
else
|
187
|
+
representation_url(**options.merge(only_path: true))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Returns the local Rails representation URL meaning that the asset will
|
192
|
+
# be served through the service itself. This may be necessary if the asset
|
193
|
+
# variant (e.g. a thumbnail) has not been processed yet because the
|
194
|
+
# variant representation has not been requested before.
|
195
|
+
#
|
196
|
+
# Due to performance reasons it is advised to avoid requesting the assets
|
197
|
+
# through the Rails representation URLs when possible because that causes
|
198
|
+
# a lot of requests to the Rails backend and slowness to the service under
|
199
|
+
# heavy loads.
|
200
|
+
#
|
201
|
+
# Converts the variation URLs last part to the correct file extension in
|
202
|
+
# case the variation has a different format than the original image. The
|
203
|
+
# conversion needs to be only done for the Rails representation URLs
|
204
|
+
# because once the image is stored at the storage service, it already has
|
205
|
+
# the correct file extension.
|
206
|
+
#
|
207
|
+
# @param options The options for building the URL
|
208
|
+
# @return [String, nil] The converted representation URL or `nil` if the
|
209
|
+
# asset is not defined.
|
210
|
+
def rails_representation_url(**options)
|
211
|
+
return unless asset
|
212
|
+
|
88
213
|
representation_url = routes.rails_representation_url(asset, **default_options.merge(options))
|
214
|
+
|
89
215
|
variation = asset.try(:variation)
|
90
216
|
return representation_url unless variation
|
91
217
|
|
92
218
|
format = variation.try(:format)
|
93
219
|
return representation_url unless format
|
220
|
+
return unless blob
|
94
221
|
|
95
|
-
original_ext = File.extname(
|
222
|
+
original_ext = File.extname(blob.filename.to_s)
|
96
223
|
return representation_url if original_ext == ".#{format}"
|
97
224
|
|
98
|
-
basename = File.basename(
|
225
|
+
basename = File.basename(blob.filename.to_s, original_ext)
|
99
226
|
representation_url.sub(/#{basename}\.#{original_ext.tr(".", "")}$/, "#{basename}.#{format}")
|
100
227
|
end
|
228
|
+
|
229
|
+
# Fetches the image variant's URL at the storage service if the variant
|
230
|
+
# has already been processed and is stored at the storage service. If the
|
231
|
+
# variant has not been processed yet, returns `nil` in which case the
|
232
|
+
# variant has to be served through the service's own representation URL
|
233
|
+
# causing it to be processed and stored at the storage service.
|
234
|
+
#
|
235
|
+
# @param options The options for building the URL
|
236
|
+
# @return [String, nil] The variant URL at the storage service or `nil` if
|
237
|
+
# the variant has not been processed yet and does not yet exist at the
|
238
|
+
# storage service or `nil` when the asset is not defined
|
239
|
+
def variant_url(**options)
|
240
|
+
return unless asset
|
241
|
+
return unless asset_url_available?
|
242
|
+
return unless asset_exist?
|
243
|
+
|
244
|
+
case asset
|
245
|
+
when ActiveStorage::VariantWithRecord
|
246
|
+
# This is used when `ActiveStorage.track_variants` is enabled through
|
247
|
+
# `config.active_storage.track_variants`. In case the variant has not
|
248
|
+
# been processed yet, the `#url` method would return nil.
|
249
|
+
#
|
250
|
+
# Note that if the `asset.processed?` returns `true`, the variant
|
251
|
+
# record has been created in the database but it does not mean that
|
252
|
+
# it has been uploaded to the storage service yet. Likely a bug in
|
253
|
+
# ActiveStorage but to be sure that the asset is uploaded to the
|
254
|
+
# storage service, we also check that.
|
255
|
+
asset.url(**options) if asset.processed?
|
256
|
+
else # ActiveStorage::Variant
|
257
|
+
# Check whether the variant exists at the storage service before
|
258
|
+
# returning its URL. Otherwise the URL would be returned even when the
|
259
|
+
# variant is not yet processed causing 404 errors for the images on
|
260
|
+
# the page.
|
261
|
+
#
|
262
|
+
# Note that the `ActiveStorage::Variant#url` method only accepts
|
263
|
+
# certain keyword arguments where as the other objects allow any
|
264
|
+
# keyword arguments.
|
265
|
+
possible_kwargs = asset.method(:url).parameters.select { |p| p[0] == :key }.map { |p| p[1] }
|
266
|
+
asset.url(**options.slice(*possible_kwargs))
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Determines if the asset exists at the storage service.
|
271
|
+
#
|
272
|
+
# @return [Boolean] A boolean answering the question "does this asset
|
273
|
+
# exist at the storage service?".
|
274
|
+
def asset_exist?
|
275
|
+
return false if asset.key.blank?
|
276
|
+
|
277
|
+
blob.service.exist?(asset.key)
|
278
|
+
end
|
279
|
+
|
280
|
+
# Determines if the current host is required to build the asset URL.
|
281
|
+
#
|
282
|
+
# @return [Boolean] A boolean indicating if the current host is required
|
283
|
+
# to build the asset URL.
|
284
|
+
def current_host_required?
|
285
|
+
return false unless blob
|
286
|
+
return false unless defined?(ActiveStorage::Service::DiskService)
|
287
|
+
|
288
|
+
blob.service.is_a?(ActiveStorage::Service::DiskService)
|
289
|
+
end
|
290
|
+
|
291
|
+
# Determines if the asset URL can be generated.
|
292
|
+
#
|
293
|
+
# @return [Boolean] A boolean indicating if the asset URL can be
|
294
|
+
# generated.
|
295
|
+
def asset_url_available?
|
296
|
+
# If the service is an external service, the URL can be generated
|
297
|
+
# regardless of the current host being set.
|
298
|
+
return true unless current_host_required?
|
299
|
+
|
300
|
+
# For the disk service, the URL can be only generated if the current
|
301
|
+
# host has been set.
|
302
|
+
ActiveStorage::Current.url_options&.dig(:host).present?
|
303
|
+
end
|
101
304
|
end
|
102
305
|
end
|
103
306
|
end
|
@@ -10,7 +10,7 @@ shared_examples_for "attachable interface" do
|
|
10
10
|
|
11
11
|
it "includes the attachment urls" do
|
12
12
|
attachment_urls = response["attachments"].map { |attachment| attachment["url"] }
|
13
|
-
expect(attachment_urls).to
|
13
|
+
expect(attachment_urls).to include_blob_urls(*attachments.map(&:file).map(&:blob))
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/lib/decidim/core/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decidim-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.29.0.
|
4
|
+
version: 0.29.0.rc4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep Jaume Rey Peroy
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-07-
|
13
|
+
date: 2024-07-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: active_link_to
|
@@ -758,28 +758,28 @@ dependencies:
|
|
758
758
|
requirements:
|
759
759
|
- - '='
|
760
760
|
- !ruby/object:Gem::Version
|
761
|
-
version: 0.29.0.
|
761
|
+
version: 0.29.0.rc4
|
762
762
|
type: :development
|
763
763
|
prerelease: false
|
764
764
|
version_requirements: !ruby/object:Gem::Requirement
|
765
765
|
requirements:
|
766
766
|
- - '='
|
767
767
|
- !ruby/object:Gem::Version
|
768
|
-
version: 0.29.0.
|
768
|
+
version: 0.29.0.rc4
|
769
769
|
- !ruby/object:Gem::Dependency
|
770
770
|
name: decidim-dev
|
771
771
|
requirement: !ruby/object:Gem::Requirement
|
772
772
|
requirements:
|
773
773
|
- - '='
|
774
774
|
- !ruby/object:Gem::Version
|
775
|
-
version: 0.29.0.
|
775
|
+
version: 0.29.0.rc4
|
776
776
|
type: :development
|
777
777
|
prerelease: false
|
778
778
|
version_requirements: !ruby/object:Gem::Requirement
|
779
779
|
requirements:
|
780
780
|
- - '='
|
781
781
|
- !ruby/object:Gem::Version
|
782
|
-
version: 0.29.0.
|
782
|
+
version: 0.29.0.rc4
|
783
783
|
description: Adds core features so other engines can hook into the framework.
|
784
784
|
email:
|
785
785
|
- josepjaume@gmail.com
|