lato_cms 3.0.13 → 3.1.1
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/assets/javascripts/lato_cms/controllers/lato_cms_media_field_controller.js +143 -0
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_media_picker_controller.js +110 -0
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_media_reorder_controller.js +37 -0
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_reload_on_modal_close_controller.js +44 -0
- data/app/assets/stylesheets/lato_cms/application.scss +131 -158
- data/app/controllers/lato_cms/application_controller.rb +4 -0
- data/app/controllers/lato_cms/media_controller.rb +121 -0
- data/app/controllers/lato_cms/pages_controller.rb +75 -91
- data/app/helpers/lato_cms/media_helper.rb +50 -0
- data/app/jobs/lato_cms/export_sitemap_csv_job.rb +33 -0
- data/app/jobs/lato_cms/generate_alt_text_job.rb +21 -0
- data/app/jobs/lato_cms/generate_video_poster_job.rb +7 -5
- data/app/jobs/lato_cms/translate_component_fields_job.rb +16 -0
- data/app/models/lato_cms/llm_client.rb +31 -0
- data/app/models/lato_cms/media.rb +270 -0
- data/app/models/lato_cms/page.rb +40 -0
- data/app/models/lato_cms/page_field.rb +52 -80
- data/app/models/lato_cms/page_field_media.rb +8 -0
- data/app/views/lato_cms/media/_form_create.html.erb +20 -0
- data/app/views/lato_cms/media/_form_update.html.erb +60 -0
- data/app/views/lato_cms/media/create.html.erb +13 -0
- data/app/views/lato_cms/media/index.html.erb +22 -0
- data/app/views/lato_cms/media/picker_action.html.erb +98 -0
- data/app/views/lato_cms/media/update.html.erb +13 -0
- data/app/views/lato_cms/pages/_component_accordion.html.erb +15 -0
- data/app/views/lato_cms/pages/fields/_file.html.erb +4 -55
- data/app/views/lato_cms/pages/fields/_gallery.html.erb +4 -60
- data/app/views/lato_cms/pages/fields/_image.html.erb +4 -68
- data/app/views/lato_cms/pages/fields/_media_field.html.erb +62 -0
- data/app/views/lato_cms/pages/fields/_media_item.html.erb +27 -0
- data/app/views/lato_cms/pages/fields/_video.html.erb +4 -69
- data/app/views/lato_cms/pages/index.html.erb +17 -0
- data/app/views/lato_cms/pages/show.html.erb +2 -1
- data/config/locales/en.yml +36 -12
- data/config/locales/it.yml +36 -12
- data/config/routes.rb +12 -0
- data/db/migrate/20260728175413_create_lato_cms_media.rb +11 -0
- data/db/migrate/20260728175414_create_lato_cms_page_field_media.rb +12 -0
- data/db/migrate/20260729120000_change_lato_cms_media_alt_text_to_translations.rb +25 -0
- data/lib/lato_cms/config.rb +12 -1
- data/lib/lato_cms/version.rb +1 -1
- metadata +38 -5
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_file_field_controller.js +0 -225
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_gallery_field_controller.js +0 -190
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_image_field_controller.js +0 -169
- data/app/assets/javascripts/lato_cms/controllers/lato_cms_video_field_controller.js +0 -180
|
@@ -153,7 +153,8 @@ body.controller-pages.action-show {
|
|
|
153
153
|
opacity: 0;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
.controller-pages
|
|
156
|
+
.controller-pages,
|
|
157
|
+
.controller-media {
|
|
157
158
|
.lato-index-desk-col-label-actions {
|
|
158
159
|
width: 1px;
|
|
159
160
|
|
|
@@ -192,214 +193,186 @@ body.controller-pages.action-show {
|
|
|
192
193
|
}
|
|
193
194
|
}
|
|
194
195
|
|
|
195
|
-
// ──
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
border: 1px solid rgba(33, 37, 41, 0.12);
|
|
200
|
-
border-radius: 8px;
|
|
201
|
-
box-shadow: 0 1px 2px rgba(33, 37, 41, 0.04);
|
|
196
|
+
// ── Media field (image/video/file/gallery, picked from the Media library) ──────
|
|
197
|
+
// Square tiles, preview-only: name and remove button only reveal on hover, so
|
|
198
|
+
// a filled field reads as a clean grid of thumbnails, not a form-y file list.
|
|
199
|
+
.lato-cms-media-field__grid {
|
|
202
200
|
display: flex;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
flex-wrap: wrap;
|
|
202
|
+
gap: 10px;
|
|
203
|
+
min-height: 24px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.lato-cms-media-field__tile {
|
|
207
|
+
border-radius: 10px;
|
|
208
|
+
flex: 0 0 auto;
|
|
209
|
+
height: 110px;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
position: relative;
|
|
212
|
+
width: 110px;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.lato-cms-media-field__item {
|
|
216
|
+
background: var(--bs-light);
|
|
217
|
+
border: 1px solid rgba(33, 37, 41, 0.1);
|
|
218
|
+
transition: box-shadow 0.15s;
|
|
209
219
|
|
|
210
220
|
&:hover {
|
|
211
|
-
|
|
212
|
-
box-shadow: 0 3px 10px rgba(33, 37, 41, 0.07);
|
|
221
|
+
box-shadow: 0 3px 10px rgba(33, 37, 41, 0.15);
|
|
213
222
|
}
|
|
214
|
-
}
|
|
215
223
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
display: flex;
|
|
219
|
-
flex-wrap: wrap;
|
|
220
|
-
gap: 0.35rem;
|
|
221
|
-
min-width: 0;
|
|
222
|
-
flex: 1;
|
|
224
|
+
&[draggable="true"] {
|
|
225
|
+
cursor: grab;
|
|
223
226
|
|
|
224
|
-
|
|
225
|
-
|
|
227
|
+
&:active {
|
|
228
|
+
cursor: grabbing;
|
|
229
|
+
}
|
|
226
230
|
}
|
|
227
231
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
232
|
+
&--dragging {
|
|
233
|
+
opacity: 0.35;
|
|
234
|
+
box-shadow: 0 0 0 2px var(--bs-primary);
|
|
231
235
|
}
|
|
232
236
|
}
|
|
233
237
|
|
|
234
|
-
.lato-cms-
|
|
235
|
-
|
|
236
|
-
display:
|
|
237
|
-
|
|
238
|
-
|
|
238
|
+
.lato-cms-media-field__thumb,
|
|
239
|
+
.lato-cms-media-field__player {
|
|
240
|
+
display: block;
|
|
241
|
+
height: 100%;
|
|
242
|
+
object-fit: cover;
|
|
239
243
|
width: 100%;
|
|
240
244
|
}
|
|
241
245
|
|
|
242
|
-
.lato-cms-
|
|
246
|
+
.lato-cms-media-field__icon {
|
|
243
247
|
align-items: center;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
color: var(--bs-danger);
|
|
249
|
-
display: inline-flex;
|
|
250
|
-
flex: 0 0 auto;
|
|
251
|
-
height: 32px;
|
|
248
|
+
color: var(--bs-secondary);
|
|
249
|
+
display: flex;
|
|
250
|
+
font-size: 2rem;
|
|
251
|
+
height: 100%;
|
|
252
252
|
justify-content: center;
|
|
253
|
-
|
|
254
|
-
transition: background 0.15s, color 0.15s;
|
|
255
|
-
width: 32px;
|
|
256
|
-
|
|
257
|
-
&:hover,
|
|
258
|
-
&:focus {
|
|
259
|
-
background: #f1aeb5;
|
|
260
|
-
color: var(--bs-danger);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
.lato-cms-file-field__item--removing {
|
|
265
|
-
background: rgba(220, 53, 69, 0.06);
|
|
266
|
-
border-color: rgba(220, 53, 69, 0.35);
|
|
267
|
-
box-shadow: none;
|
|
268
|
-
|
|
269
|
-
.lato-cms-file-field__info,
|
|
270
|
-
.lato-cms-image-field__preview,
|
|
271
|
-
.lato-cms-video-field__preview,
|
|
272
|
-
.lato-cms-attachment-field__remove,
|
|
273
|
-
> .btn {
|
|
274
|
-
display: none;
|
|
275
|
-
}
|
|
253
|
+
width: 100%;
|
|
276
254
|
}
|
|
277
255
|
|
|
278
|
-
.lato-cms-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
.
|
|
283
|
-
|
|
284
|
-
|
|
256
|
+
.lato-cms-media-field__badge {
|
|
257
|
+
bottom: 4px;
|
|
258
|
+
color: #fff;
|
|
259
|
+
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
|
|
260
|
+
font-size: 0.9rem;
|
|
261
|
+
pointer-events: none;
|
|
262
|
+
position: absolute;
|
|
263
|
+
right: 4px;
|
|
285
264
|
}
|
|
286
265
|
|
|
287
|
-
//
|
|
288
|
-
.lato-cms-
|
|
289
|
-
|
|
266
|
+
// Name overlay: hidden until the tile is hovered.
|
|
267
|
+
.lato-cms-media-field__overlay {
|
|
268
|
+
bottom: 0;
|
|
269
|
+
background: linear-gradient(to top, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0) 65%);
|
|
270
|
+
left: 0;
|
|
271
|
+
opacity: 0;
|
|
272
|
+
padding: 0.4rem;
|
|
273
|
+
pointer-events: none;
|
|
274
|
+
position: absolute;
|
|
275
|
+
right: 0;
|
|
276
|
+
transition: opacity 0.15s;
|
|
290
277
|
}
|
|
291
278
|
|
|
292
|
-
.lato-cms-
|
|
293
|
-
|
|
294
|
-
align-self: center;
|
|
295
|
-
background: var(--bs-light);
|
|
296
|
-
border: 1px solid rgba(33, 37, 41, 0.08);
|
|
297
|
-
border-radius: 6px;
|
|
298
|
-
display: flex;
|
|
299
|
-
flex: 0 0 auto;
|
|
300
|
-
height: 64px;
|
|
301
|
-
justify-content: center;
|
|
302
|
-
overflow: hidden;
|
|
303
|
-
width: 64px;
|
|
279
|
+
.lato-cms-media-field__item:hover .lato-cms-media-field__overlay {
|
|
280
|
+
opacity: 1;
|
|
304
281
|
}
|
|
305
282
|
|
|
306
|
-
.lato-cms-
|
|
307
|
-
|
|
308
|
-
height: 100%;
|
|
309
|
-
object-fit: cover;
|
|
283
|
+
.lato-cms-media-field__name {
|
|
284
|
+
color: #fff;
|
|
310
285
|
display: block;
|
|
311
|
-
|
|
286
|
+
font-size: 0.7rem;
|
|
287
|
+
line-height: 1.2;
|
|
288
|
+
overflow: hidden;
|
|
289
|
+
text-overflow: ellipsis;
|
|
290
|
+
white-space: nowrap;
|
|
312
291
|
}
|
|
313
292
|
|
|
314
|
-
.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
width: 22px;
|
|
319
|
-
height: 22px;
|
|
320
|
-
border-radius: 50%;
|
|
293
|
+
// Remove button: only clickable once revealed, so it can't be hit while invisible.
|
|
294
|
+
.lato-cms-media-field__remove {
|
|
295
|
+
align-items: center;
|
|
296
|
+
background: rgba(220, 53, 69, 0.9);
|
|
321
297
|
border: 0;
|
|
322
|
-
|
|
298
|
+
border-radius: 50%;
|
|
323
299
|
color: #fff;
|
|
324
300
|
display: flex;
|
|
325
|
-
|
|
301
|
+
font-size: 11px;
|
|
302
|
+
height: 22px;
|
|
326
303
|
justify-content: center;
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
304
|
+
opacity: 0;
|
|
305
|
+
pointer-events: none;
|
|
306
|
+
position: absolute;
|
|
307
|
+
right: 4px;
|
|
308
|
+
top: 4px;
|
|
309
|
+
transition: opacity 0.15s, background 0.15s;
|
|
310
|
+
width: 22px;
|
|
330
311
|
|
|
331
312
|
&:hover {
|
|
332
313
|
background: rgb(220, 53, 69);
|
|
333
314
|
}
|
|
334
315
|
}
|
|
335
316
|
|
|
336
|
-
.lato-cms-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
left: 4px;
|
|
340
|
-
font-size: 10px;
|
|
317
|
+
.lato-cms-media-field__item:hover .lato-cms-media-field__remove {
|
|
318
|
+
opacity: 1;
|
|
319
|
+
pointer-events: auto;
|
|
341
320
|
}
|
|
342
321
|
|
|
343
|
-
//
|
|
344
|
-
.lato-cms-
|
|
345
|
-
align-items:
|
|
346
|
-
|
|
322
|
+
// Add tile: dashed placeholder, both the empty state and the "add more" affordance.
|
|
323
|
+
.lato-cms-media-field__tile--add {
|
|
324
|
+
align-items: center;
|
|
325
|
+
background: transparent;
|
|
326
|
+
border: 1px dashed rgba(33, 37, 41, 0.25);
|
|
327
|
+
color: var(--bs-secondary);
|
|
328
|
+
display: flex;
|
|
329
|
+
flex-direction: column;
|
|
330
|
+
font-size: 0.7rem;
|
|
331
|
+
gap: 0.25rem;
|
|
332
|
+
justify-content: center;
|
|
333
|
+
padding: 0.5rem;
|
|
334
|
+
text-align: center;
|
|
335
|
+
text-decoration: none;
|
|
336
|
+
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
|
347
337
|
|
|
348
|
-
.
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
border: 1px solid rgba(33, 37, 41, 0.08);
|
|
352
|
-
border-radius: 6px;
|
|
353
|
-
flex: 0 0 auto;
|
|
354
|
-
overflow: hidden;
|
|
355
|
-
width: 180px;
|
|
356
|
-
}
|
|
338
|
+
.bi {
|
|
339
|
+
font-size: 1.25rem;
|
|
340
|
+
}
|
|
357
341
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
342
|
+
&:hover {
|
|
343
|
+
background: rgba(13, 110, 253, 0.05);
|
|
344
|
+
border-color: var(--bs-primary);
|
|
345
|
+
color: var(--bs-primary);
|
|
346
|
+
}
|
|
362
347
|
}
|
|
363
348
|
|
|
364
|
-
// ──
|
|
365
|
-
.lato-cms-
|
|
366
|
-
display:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
349
|
+
// ── Media picker modal ──────────────────────────────────────────────────────────
|
|
350
|
+
.lato-cms-media-picker__grid {
|
|
351
|
+
display: grid;
|
|
352
|
+
gap: 10px;
|
|
353
|
+
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
|
|
354
|
+
max-height: 360px;
|
|
355
|
+
overflow-y: auto;
|
|
370
356
|
}
|
|
371
357
|
|
|
372
|
-
.lato-cms-
|
|
373
|
-
|
|
374
|
-
border-radius:
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
transition:
|
|
358
|
+
.lato-cms-media-picker__item {
|
|
359
|
+
border: 2px solid transparent;
|
|
360
|
+
border-radius: 8px;
|
|
361
|
+
cursor: pointer;
|
|
362
|
+
padding: 4px;
|
|
363
|
+
text-align: center;
|
|
364
|
+
transition: border-color 0.15s, background 0.15s;
|
|
379
365
|
|
|
380
|
-
&:
|
|
381
|
-
|
|
366
|
+
&:hover {
|
|
367
|
+
background: var(--bs-light);
|
|
382
368
|
}
|
|
383
369
|
|
|
384
|
-
&--
|
|
385
|
-
|
|
386
|
-
|
|
370
|
+
&--selected {
|
|
371
|
+
border-color: var(--bs-primary);
|
|
372
|
+
background: rgba(13, 110, 253, 0.08);
|
|
387
373
|
}
|
|
388
374
|
}
|
|
389
375
|
|
|
390
|
-
.lato-cms-gallery-field__thumb {
|
|
391
|
-
width: 90px;
|
|
392
|
-
height: 90px;
|
|
393
|
-
object-fit: cover;
|
|
394
|
-
display: block;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
.lato-cms-gallery-field__remove {
|
|
398
|
-
position: absolute;
|
|
399
|
-
right: 4px;
|
|
400
|
-
top: 4px;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
376
|
// ── Repeater items ─────────────────────────────────────────────────────────────
|
|
404
377
|
|
|
405
378
|
.lato-cms-repeater-item__toggle {
|
|
@@ -19,6 +19,10 @@ module LatoCms
|
|
|
19
19
|
@query_pages ||= LatoCms::Page.for_lato_spaces_group(@session.get(:spaces_group_id))
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
def query_media
|
|
23
|
+
@query_media ||= LatoCms::Media.for_lato_spaces_group(@session.get(:spaces_group_id))
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
# Section-level guard: any CMS role (operator or admin) may enter.
|
|
23
27
|
def authenticate_lato_cms_access
|
|
24
28
|
return true if @session.user&.lato_cms_access?
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
module LatoCms
|
|
2
|
+
class MediaController < ApplicationController
|
|
3
|
+
ADMIN_ONLY_ACTIONS = %i[destroy_action].freeze
|
|
4
|
+
|
|
5
|
+
before_action { active_sidebar(:lato_cms_media) }
|
|
6
|
+
before_action :authenticate_lato_cms_admin, only: ADMIN_ONLY_ACTIONS
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
@media = lato_index_collection(
|
|
10
|
+
query_media.order(created_at: :desc),
|
|
11
|
+
columns: %i[name media_type actions],
|
|
12
|
+
sortable_columns: %i[name media_type created_at],
|
|
13
|
+
searchable_columns: %i[name alt_text],
|
|
14
|
+
default_sort_by: 'created_at|DESC',
|
|
15
|
+
pagination: 24
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Searchable/filterable grid used inside the field media picker modal
|
|
20
|
+
# (distinct from `index`, which is the full standalone library page).
|
|
21
|
+
def picker_action
|
|
22
|
+
media = query_media
|
|
23
|
+
media = media.of_type(params[:type]) if params[:type].present?
|
|
24
|
+
media = media.where('LOWER(lato_cms_media.name) LIKE :q', q: "%#{params[:q].to_s.downcase}%") if params[:q].present?
|
|
25
|
+
|
|
26
|
+
@media = media.order(created_at: :desc).page(params[:page]).per(24)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def create
|
|
30
|
+
@media = LatoCms::Media.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def create_action
|
|
34
|
+
@media = LatoCms::Media.new(create_params.merge(lato_spaces_group_id: @session.get(:spaces_group_id)))
|
|
35
|
+
|
|
36
|
+
respond_to do |format|
|
|
37
|
+
if @media.save
|
|
38
|
+
format.html { redirect_to lato_cms.media_path, notice: t('lato_cms.media_created') }
|
|
39
|
+
format.json { render json: @media }
|
|
40
|
+
else
|
|
41
|
+
format.html { render :create, status: :unprocessable_entity }
|
|
42
|
+
format.json { render json: @media.errors, status: :unprocessable_entity }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def update
|
|
48
|
+
@media = query_media.find(params[:id])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def update_action
|
|
52
|
+
@media = query_media.find(params[:id])
|
|
53
|
+
|
|
54
|
+
respond_to do |format|
|
|
55
|
+
if @media.update(update_params)
|
|
56
|
+
format.html { redirect_to lato_cms.media_path, notice: t('lato_cms.media_updated') }
|
|
57
|
+
format.json { render json: @media }
|
|
58
|
+
else
|
|
59
|
+
format.html { render :update, status: :unprocessable_entity }
|
|
60
|
+
format.json { render json: @media.errors, status: :unprocessable_entity }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Runs as a Lato::Operation (see GenerateAltTextJob) rather than inline:
|
|
66
|
+
# an LLM call can take a while, and blocking the request risks timing it
|
|
67
|
+
# out. The admin instead lands on a live progress page.
|
|
68
|
+
def regenerate_alt_text_action
|
|
69
|
+
@media = query_media.find(params[:id])
|
|
70
|
+
|
|
71
|
+
unless @media.image? && LatoCms.config.llm_configured?
|
|
72
|
+
respond_to do |format|
|
|
73
|
+
message = t('lato_cms.media_alt_text_regenerate_unavailable')
|
|
74
|
+
format.html { redirect_to lato_cms.media_update_path(@media), alert: message }
|
|
75
|
+
format.json { render json: { error: message }, status: :unprocessable_entity }
|
|
76
|
+
end
|
|
77
|
+
return
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
operation = Lato::Operation.generate('LatoCms::GenerateAltTextJob', { media_id: @media.id }, @session.user_id)
|
|
81
|
+
|
|
82
|
+
if operation.start
|
|
83
|
+
redirect_to lato.operation_path(operation)
|
|
84
|
+
else
|
|
85
|
+
redirect_to lato_cms.media_update_path(@media), alert: t('lato_cms.media_alt_text_regenerate_failed')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def destroy_action
|
|
90
|
+
@media = query_media.find(params[:id])
|
|
91
|
+
in_use = @media.usage_count.positive?
|
|
92
|
+
force = ActiveModel::Type::Boolean.new.cast(params[:force])
|
|
93
|
+
|
|
94
|
+
respond_to do |format|
|
|
95
|
+
if (!in_use || force) && @media.destroy
|
|
96
|
+
format.html { redirect_to lato_cms.media_path, notice: t('lato_cms.media_deleted') }
|
|
97
|
+
format.json { render json: { message: t('lato_cms.media_deleted') } }
|
|
98
|
+
else
|
|
99
|
+
message = in_use ? t('lato_cms.media_delete_in_use', count: @media.usage_count) : t('lato_cms.media_delete_failed')
|
|
100
|
+
format.html { redirect_to lato_cms.media_path, alert: message }
|
|
101
|
+
format.json { render json: { error: message, usage_count: @media.usage_count }, status: :unprocessable_entity }
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def create_params
|
|
109
|
+
params.require(:media).permit(:file, :name, :alt_text)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# :file is intentionally not permitted here: the underlying file is
|
|
113
|
+
# immutable once a Media exists (it can be reused by many fields across
|
|
114
|
+
# many pages, so replacing it in place would silently change what renders
|
|
115
|
+
# everywhere it's referenced). A different file means a new Media.
|
|
116
|
+
def update_params
|
|
117
|
+
alt_text_keys = LatoCms.config.locales.map { |locale| :"alt_text_#{locale}" }
|
|
118
|
+
params.require(:media).permit(:name, *alt_text_keys)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|