lato_cms 3.2.2 → 3.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c972b24f2fdfbdd342a2b106ece261073d0b4517a1df42484863c9a38104920d
4
- data.tar.gz: 3f1f14ba2ef176bbd09bf1073a74fcbe50d4b66c9997ae985ab578b364700ece
3
+ metadata.gz: f4512bf98553bdc298352f97641aeef70356dcc448862a84816ed64ec4df3d3b
4
+ data.tar.gz: 7d7e190cf8997e7c9d6fcd94f7dc1570d9d939312b71a5caaa6cc2eadba697a3
5
5
  SHA512:
6
- metadata.gz: db07c23bf8a9515cc43c05dd14a86fc405511f43c4b027eb5ee75837fb5c7a022597e63dc385cff96311c904f254811aae155e90f02000b6771874c4319ec932
7
- data.tar.gz: 526c40a70c8b222c7d4499c4e977966810af2e1b55cce4b3b64800870755264a04cea9d6a0e6c97768817eaa1e08a4402a684ec7183fcce66d1dcbad0c159f4b
6
+ metadata.gz: e4bbfabdce312042bba9014b34a8ff1423a1dccd84e0798700f334d2836f7cda389a8ce15c04faca2188229271e30e74b1b6044222e1a0735960e875c5c68206
7
+ data.tar.gz: 0f8191d661b29ce420e8ab5657511fe5c3d0af82ce0c60bd6ee11d695b86c2c27735c5d6b4ad806b9df149b46f1423e63512996e0eb99655c51da31fdac8a39f
@@ -6,8 +6,13 @@ module LatoCms
6
6
  before_action :authenticate_lato_cms_admin, only: ADMIN_ONLY_ACTIONS
7
7
 
8
8
  def index
9
+ media = query_media
10
+ # "Unused" = no page field references it at all: the only media that can
11
+ # be deleted, so it's worth being able to list just those.
12
+ media = media.where.missing(:page_field_media) if params[:usage] == 'unused'
13
+
9
14
  @media = lato_index_collection(
10
- query_media.order(created_at: :desc),
15
+ media.order(created_at: :desc),
11
16
  columns: %i[name media_type usages actions],
12
17
  sortable_columns: %i[name media_type created_at],
13
18
  searchable_columns: %i[name alt_text title],
@@ -26,6 +31,13 @@ module LatoCms
26
31
  @media = media.order(created_at: :desc).page(params[:page]).per(24)
27
32
  end
28
33
 
34
+ # Read-only detail page: the media's own data plus where it's used. Kept
35
+ # apart from the edit form, which is a modal from the index and has no room
36
+ # for a usage list.
37
+ def show
38
+ @media = query_media.find(params[:id])
39
+ end
40
+
29
41
  def create
30
42
  @media = LatoCms::Media.new
31
43
  end
@@ -105,7 +117,7 @@ module LatoCms
105
117
 
106
118
  respond_to do |format|
107
119
  if file.present? && @media.replace_file!(file)
108
- format.html { redirect_to lato_cms.media_update_path(@media), notice: t('lato_cms.media_file_replaced') }
120
+ format.html { redirect_to lato_cms.media_show_path(@media), notice: t('lato_cms.media_file_replaced') }
109
121
  format.json { render json: @media }
110
122
  else
111
123
  message = t('lato_cms.media_file_replace_failed')
@@ -44,17 +44,28 @@ module LatoCms
44
44
  content_tag(:span, media.media_type, class: 'badge bg-secondary')
45
45
  end
46
46
 
47
- # Index actions cell: edit metadata + delete (delete gated to admins, same
48
- # convention as pages).
47
+ # Index actions cell: detail page + edit metadata + delete (delete gated to
48
+ # admins, same convention as pages). Delete is rendered inert while the
49
+ # media is still referenced: the action would be refused server-side
50
+ # anyway, so the button says why instead of failing after the fact.
49
51
  def lato_cms_media_actions(media)
50
52
  content_tag(:div, class: 'btn-group btn-group-sm') do
53
+ concat link_to(t('lato_cms.cta_show'), lato_cms.media_show_path(media), class: 'btn btn-primary')
51
54
  concat link_to(t('lato_cms.cta_edit'), lato_cms.media_update_path(media), class: 'btn btn-secondary',
52
55
  data: { lato_action_target: 'trigger', turbo_frame: dom_id(media, 'form'), action_title: t('lato_cms.media_update_title') })
53
- if lato_cms_admin?
54
- concat link_to(t('lato_cms.cta_delete'), lato_cms.media_destroy_action_path(media), class: 'btn btn-danger',
55
- data: { turbo_method: 'DELETE', turbo_confirm: t('lato_cms.cta_delete_confirm') })
56
- end
56
+ concat lato_cms_media_delete_action(media) if lato_cms_admin?
57
57
  end
58
58
  end
59
+
60
+ private
61
+
62
+ def lato_cms_media_delete_action(media)
63
+ usage_count = media.usage_count
64
+ return link_to(t('lato_cms.cta_delete'), lato_cms.media_destroy_action_path(media), class: 'btn btn-danger',
65
+ data: { turbo_method: 'DELETE', turbo_confirm: t('lato_cms.cta_delete_confirm') }) if usage_count.zero?
66
+
67
+ content_tag(:span, t('lato_cms.cta_delete'), class: 'btn btn-danger disabled',
68
+ title: t('lato_cms.media_delete_in_use', count: usage_count), data: { controller: 'lato-tooltip' })
69
+ end
59
70
  end
60
71
  end
@@ -45,6 +45,20 @@ module LatoCms
45
45
 
46
46
  scope :of_type, ->(type) { where(media_type: type) if type.present? }
47
47
 
48
+ # Hook picked up by lato's `lato_index_collection` in place of its generic
49
+ # search, whose SQL leaves column names unqualified. The Spaces association
50
+ # joins lato_spaces_groups, which also has a `name` column, so that generic
51
+ # search was ambiguous SQL and the media library's search box raised
52
+ # ("ambiguous column name: name" on SQLite, the same error on Postgres).
53
+ # Qualifying every column here fixes it; alt_text/title are matched as the
54
+ # raw JSON they're stored as, so a hit in any locale counts.
55
+ scope :lato_index_search, ->(search) {
56
+ term = "%#{search.to_s.downcase.strip}%"
57
+ columns = %w[name alt_text title].map { |column| "LOWER(#{table_name}.#{column}) LIKE :term" }
58
+
59
+ where(columns.join(" OR "), term: term)
60
+ }
61
+
48
62
  def self.infer_media_type(content_type)
49
63
  content_type = content_type.to_s
50
64
  return 'image' if content_type.start_with?('image/')
@@ -1,32 +1,25 @@
1
1
  <%# Swaps the file behind an existing media: every page using it renders the
2
- new file. Deliberately separate from the metadata form (different action,
2
+ new file. Deliberately not part of the metadata form (different action,
3
3
  admin only, destructive across every usage). %>
4
- <div class="card border-warning mt-4">
5
- <div class="card-header">
6
- <h3 class="fs-6 mb-0"><%= t('lato_cms.media_replace_file_title') %></h3>
7
- </div>
8
- <div class="card-body">
9
- <p class="text-muted small">
10
- <%= t('lato_cms.media_replace_file_description', count: media.usage_count) %>
11
- </p>
4
+ <p class="text-muted small">
5
+ <%= t('lato_cms.media_replace_file_description', count: media.usage_count) %>
6
+ </p>
12
7
 
13
- <%= form_with model: media, url: lato_cms.media_replace_file_action_path(media), method: :patch, data: {
14
- controller: 'lato-cms-upload',
15
- action: 'submit->lato-cms-upload#submit',
16
- lato_cms_upload_redirect_url_value: lato_cms.media_update_path(media),
17
- lato_cms_upload_processing_label_value: t('lato_cms.media_upload_processing'),
18
- lato_cms_upload_confirm_value: t('lato_cms.media_replace_file_confirm')
19
- } do |form| %>
20
- <div data-lato-cms-upload-target="notice"></div>
8
+ <%= form_with model: media, url: lato_cms.media_replace_file_action_path(media), method: :patch, data: {
9
+ controller: 'lato-cms-upload',
10
+ action: 'submit->lato-cms-upload#submit',
11
+ lato_cms_upload_redirect_url_value: lato_cms.media_show_path(media),
12
+ lato_cms_upload_processing_label_value: t('lato_cms.media_upload_processing'),
13
+ lato_cms_upload_confirm_value: t('lato_cms.media_replace_file_confirm')
14
+ } do |form| %>
15
+ <div data-lato-cms-upload-target="notice"></div>
21
16
 
22
- <%= lato_form_item_input_file_dropzone form, :file %>
23
- <%= render 'lato_cms/media/upload_progress' %>
17
+ <%= lato_form_item_input_file_dropzone form, :file %>
18
+ <%= render 'lato_cms/media/upload_progress' %>
24
19
 
25
- <div class="d-flex justify-content-end">
26
- <button type="submit" class="btn btn-warning" data-lato-cms-upload-target="submit">
27
- <%= t('lato_cms.media_replace_file_cta') %>
28
- </button>
29
- </div>
30
- <% end %>
20
+ <div class="d-flex justify-content-end">
21
+ <button type="submit" class="btn btn-warning" data-lato-cms-upload-target="submit">
22
+ <%= t('lato_cms.media_replace_file_cta') %>
23
+ </button>
31
24
  </div>
32
- </div>
25
+ <% end %>
@@ -1,48 +1,54 @@
1
1
  <% media ||= LatoCms::Media.new %>
2
+ <% tab_id = dom_id(media, 'tab') %>
2
3
 
3
4
  <%= turbo_frame_tag dom_id(media, 'form') do %>
4
- <%= form_with model: media, url: lato_cms.media_update_action_path(media), method: :patch, data: { turbo_frame: '_self', controller: 'lato-form lato-cms-reload-on-modal-close' } do |form| %>
5
- <%= lato_form_notices class: %w[mb-3] %>
6
- <%= lato_form_errors media, class: %w[mb-3] %>
5
+ <%# Two tabs: the metadata form, and the file swap same media, but editing
6
+ its name is a local change while replacing its file edits every page
7
+ using it, so they don't share a submit button. %>
8
+ <ul class="nav nav-tabs mb-3">
9
+ <li class="nav-item">
10
+ <button class="nav-link active" data-bs-toggle="tab" data-bs-target="#<%= tab_id %>_details" type="button">
11
+ <%= t('lato_cms.media_update_tab_details') %>
12
+ </button>
13
+ </li>
14
+ <% if lato_cms_admin? %>
15
+ <li class="nav-item">
16
+ <button class="nav-link" data-bs-toggle="tab" data-bs-target="#<%= tab_id %>_replace" type="button">
17
+ <%= t('lato_cms.media_replace_file_title') %>
18
+ </button>
19
+ </li>
20
+ <% end %>
21
+ </ul>
7
22
 
8
- <%# Preview: images/videos get a large view (the index thumbnail is too small
9
- to judge a file by), everything else keeps the small type icon. %>
10
- <div class="mb-3">
11
- <% if media.image? %>
12
- <%= link_to media.url, target: '_blank', rel: 'noopener', title: t('lato_cms.media_open_original'),
13
- class: 'd-block bg-light rounded overflow-hidden' do %>
14
- <%= image_tag media.preview_url, class: 'd-block mx-auto', style: 'max-width: 100%; max-height: 420px;', alt: media.alt_text %>
15
- <% end %>
16
- <% elsif media.video? %>
17
- <video controls preload="metadata" class="d-block w-100 rounded bg-black" style="max-height: 420px;" src="<%= media.url %>"></video>
18
- <% end %>
23
+ <div class="tab-content">
24
+ <div class="tab-pane fade show active" id="<%= tab_id %>_details">
25
+ <%= form_with model: media, url: lato_cms.media_update_action_path(media), method: :patch, data: { turbo_frame: '_self', controller: 'lato-form lato-cms-reload-on-modal-close' } do |form| %>
26
+ <%= lato_form_notices class: %w[mb-3] %>
27
+ <%= lato_form_errors media, class: %w[mb-3] %>
19
28
 
20
- <div class="d-flex align-items-center gap-2 mt-2">
21
- <% unless media.image? || media.video? %>
22
- <%= lato_cms_media_thumb(media, size: 64) %>
23
- <% end %>
24
- <span class="text-muted small"><%= media.filename %></span>
25
- </div>
26
- </div>
29
+ <%= render 'lato_cms/media/preview', media: media %>
27
30
 
28
- <div class="mb-3">
29
- <%= lato_form_item_label form, :name %>
30
- <%= lato_form_item_input_text form, :name, required: true %>
31
- </div>
31
+ <div class="mb-3">
32
+ <%= lato_form_item_label form, :name %>
33
+ <%= lato_form_item_input_text form, :name, required: true %>
34
+ </div>
32
35
 
33
- <% if media.image? %>
34
- <%= render "lato_cms/media/translations_field", form: form, media: media, attribute: "alt_text" %>
35
- <% end %>
36
- <%= render "lato_cms/media/translations_field", form: form, media: media, attribute: "title" %>
37
-
38
- <%= render 'lato_cms/media/usages', media: media %>
36
+ <% if media.image? %>
37
+ <%= render "lato_cms/media/translations_field", form: form, media: media, attribute: "alt_text" %>
38
+ <% end %>
39
+ <%= render "lato_cms/media/translations_field", form: form, media: media, attribute: "title" %>
39
40
 
40
- <div class="d-flex justify-content-end">
41
- <%= lato_form_submit form, t('lato_cms.cta_update'), class: %w[btn-success] %>
41
+ <div class="d-flex justify-content-between align-items-center">
42
+ <%= link_to t('lato_cms.media_usages_show_cta'), lato_cms.media_show_path(media), class: 'btn btn-link px-0' %>
43
+ <%= lato_form_submit form, t('lato_cms.cta_update'), class: %w[btn-success] %>
44
+ </div>
45
+ <% end %>
42
46
  </div>
43
- <% end %>
44
47
 
45
- <% if lato_cms_admin? %>
46
- <%= render 'lato_cms/media/form_replace_file', media: media %>
47
- <% end %>
48
+ <% if lato_cms_admin? %>
49
+ <div class="tab-pane fade" id="<%= tab_id %>_replace">
50
+ <%= render 'lato_cms/media/form_replace_file', media: media %>
51
+ </div>
52
+ <% end %>
53
+ </div>
48
54
  <% end %>
@@ -0,0 +1,19 @@
1
+ <%# Images and videos get a large view (the index thumbnail is too small to
2
+ judge a file by), everything else keeps the small type icon. %>
3
+ <div class="mb-3">
4
+ <% if media.image? %>
5
+ <%= link_to media.url, target: '_blank', rel: 'noopener', title: t('lato_cms.media_open_original'),
6
+ class: 'd-block bg-light rounded overflow-hidden' do %>
7
+ <%= image_tag media.preview_url, class: 'd-block mx-auto', style: 'max-width: 100%; max-height: 420px;', alt: media.alt_text %>
8
+ <% end %>
9
+ <% elsif media.video? %>
10
+ <video controls preload="metadata" class="d-block w-100 rounded bg-black" style="max-height: 420px;" src="<%= media.url %>"></video>
11
+ <% end %>
12
+
13
+ <div class="d-flex align-items-center gap-2 mt-2">
14
+ <% unless media.image? || media.video? %>
15
+ <%= lato_cms_media_thumb(media, size: 64) %>
16
+ <% end %>
17
+ <%= link_to media.filename, media.url, target: '_blank', rel: 'noopener', class: 'text-muted small' %>
18
+ </div>
19
+ </div>
@@ -1,24 +1,20 @@
1
1
  <%# Where this media is actually rendered: a media is shared, so this is the
2
- blast radius of replacing its file or deleting it. %>
2
+ blast radius of replacing its file, and the reason deleting it can be
3
+ refused. %>
3
4
  <% usages = media.usages %>
4
5
 
5
- <div class="mb-3">
6
- <label class="form-label"><%= t('lato_cms.media_usages_title') %></label>
7
-
8
- <% if usages.empty? %>
9
- <p class="text-muted small mb-0"><%= t('lato_cms.media_usages_empty') %></p>
10
- <% else %>
11
- <ul class="list-group list-group-flush border rounded">
12
- <% usages.each do |page, fields| %>
13
- <li class="list-group-item d-flex justify-content-between align-items-center gap-2">
14
- <div>
15
- <%= link_to page.title, lato_cms.pages_show_path(page), class: 'text-decoration-none' %>
16
- <span class="badge bg-secondary ms-1"><%= page.locale %></span>
17
- <div class="text-muted small"><%= fields.map(&:field_name).uniq.join(', ') %></div>
18
- </div>
19
- <%= link_to t('lato_cms.cta_edit'), lato_cms.pages_show_path(page), class: 'btn btn-sm btn-outline-secondary' %>
20
- </li>
21
- <% end %>
22
- </ul>
23
- <% end %>
24
- </div>
6
+ <% if usages.empty? %>
7
+ <p class="text-muted mb-0"><%= t('lato_cms.media_usages_empty') %></p>
8
+ <% else %>
9
+ <ul class="list-group list-group-flush">
10
+ <% usages.each do |page, fields| %>
11
+ <li class="list-group-item d-flex justify-content-between align-items-center gap-2 px-0">
12
+ <div>
13
+ <div><%= page.title %> <span class="badge bg-secondary ms-1"><%= page.locale.upcase %></span></div>
14
+ <div class="text-muted small"><%= fields.map(&:field_name).uniq.join(', ') %></div>
15
+ </div>
16
+ <%= link_to t('lato_cms.cta_show'), lato_cms.pages_show_path(page), class: 'btn btn-sm btn-outline-secondary' %>
17
+ </li>
18
+ <% end %>
19
+ </ul>
20
+ <% end %>
@@ -1,6 +1,14 @@
1
1
  <%= lato_page_head t('lato_cms.media_index_title'), [{ label: t('lato_cms.media_index_title') }] %>
2
2
 
3
3
  <div class="card">
4
+ <div class="card-header d-flex gap-2">
5
+ <%= link_to lato_cms.media_path, class: "btn btn-sm #{params[:usage].blank? ? 'btn-primary' : 'btn-outline-secondary'}" do %>
6
+ <i class="bi bi-images me-1"></i><%= t('lato_cms.media_filter_all') %>
7
+ <% end %>
8
+ <%= link_to lato_cms.media_path(usage: 'unused'), class: "btn btn-sm #{params[:usage] == 'unused' ? 'btn-primary' : 'btn-outline-secondary'}" do %>
9
+ <i class="bi bi-unlink me-1"></i><%= t('lato_cms.media_filter_unused') %>
10
+ <% end %>
11
+ </div>
4
12
  <div class="card-body">
5
13
  <%= lato_index @media,
6
14
  custom_actions: {
@@ -0,0 +1,52 @@
1
+ <%= lato_page_head @media.name, [
2
+ { label: t('lato_cms.media_index_title'), path: lato_cms.media_path },
3
+ { label: @media.name }
4
+ ] %>
5
+
6
+ <div class="card mb-4">
7
+ <div class="card-header d-flex justify-content-between align-items-center gap-2">
8
+ <h2 class="fs-4 mb-0"><%= t('lato_cms.media_summary_title') %></h2>
9
+ <%= link_to t('lato_cms.cta_edit'), lato_cms.media_update_path(@media), class: 'btn btn-sm btn-secondary' %>
10
+ </div>
11
+ <%# Two columns from lg up (preview left, data right), stacked below: the
12
+ preview is the thing you look at first, the metadata the thing you read
13
+ next to it. %>
14
+ <div class="card-body row g-4">
15
+ <div class="col-lg-5">
16
+ <%= render 'lato_cms/media/preview', media: @media %>
17
+ </div>
18
+
19
+ <dl class="col-lg-7 row mb-0">
20
+ <dt class="col-sm-3"><%= LatoCms::Media.human_attribute_name(:name) %></dt>
21
+ <dd class="col-sm-9"><%= @media.name %></dd>
22
+
23
+ <dt class="col-sm-3"><%= t('lato_cms.media_type_label') %></dt>
24
+ <dd class="col-sm-9"><%= lato_cms_media_media_type(@media) %></dd>
25
+
26
+ <%# Alt text is image-only, mirroring the edit form. Both are translatable:
27
+ one row per configured locale, blanks included, so a missing
28
+ translation is visible instead of just absent. %>
29
+ <% attributes = @media.image? ? LatoCms::Media::TRANSLATABLE_ATTRIBUTES : %w[title] %>
30
+ <% attributes.each do |attribute| %>
31
+ <dt class="col-sm-3"><%= t("lato_cms.media_#{attribute}") %></dt>
32
+ <dd class="col-sm-9">
33
+ <% LatoCms.config.locales.each do |locale| %>
34
+ <div class="d-flex gap-2">
35
+ <span class="badge bg-secondary align-self-start"><%= locale.to_s.upcase %></span>
36
+ <span><%= @media.public_send(attribute, locale).presence || content_tag(:span, '—', class: 'text-muted') %></span>
37
+ </div>
38
+ <% end %>
39
+ </dd>
40
+ <% end %>
41
+ </dl>
42
+ </div>
43
+ </div>
44
+
45
+ <div class="card">
46
+ <div class="card-header">
47
+ <h2 class="fs-4 mb-0"><%= t('lato_cms.media_usages_title') %></h2>
48
+ </div>
49
+ <div class="card-body">
50
+ <%= render 'lato_cms/media/usages', media: @media %>
51
+ </div>
52
+ </div>
@@ -125,6 +125,12 @@ en:
125
125
  media_upload_cta: Upload
126
126
  media_upload_processing: Processing...
127
127
  media_usages_title: Used in
128
+ media_filter_all: All
129
+ media_filter_unused: Unused
130
+ media_summary_title: Media details
131
+ media_type_label: Type
132
+ media_update_tab_details: Details
133
+ media_usages_show_cta: See where it is used
128
134
  media_usages_empty: This media is not used in any page yet.
129
135
  media_usages_none: Unused
130
136
  media_usages_count:
@@ -125,6 +125,12 @@ it:
125
125
  media_upload_cta: Carica
126
126
  media_upload_processing: Elaborazione...
127
127
  media_usages_title: Utilizzato in
128
+ media_filter_all: Tutti
129
+ media_filter_unused: Senza utilizzi
130
+ media_summary_title: Dettagli media
131
+ media_type_label: Tipo
132
+ media_update_tab_details: Dettagli
133
+ media_usages_show_cta: Vedi dove è utilizzato
128
134
  media_usages_empty: Questo media non è ancora utilizzato in nessuna pagina.
129
135
  media_usages_none: Non utilizzato
130
136
  media_usages_count:
data/config/routes.rb CHANGED
@@ -30,6 +30,7 @@ LatoCms::Engine.routes.draw do
30
30
  get 'picker', to: 'media#picker_action', as: :media_picker_action
31
31
  get 'create', to: 'media#create', as: :media_create
32
32
  post 'create', to: 'media#create_action', as: :media_create_action
33
+ get ':id', to: 'media#show', as: :media_show
33
34
  get ':id/update', to: 'media#update', as: :media_update
34
35
  patch ':id/update', to: 'media#update_action', as: :media_update_action
35
36
  patch ':id/replace-file', to: 'media#replace_file_action', as: :media_replace_file_action
@@ -1,3 +1,3 @@
1
1
  module LatoCms
2
- VERSION = "3.2.2"
2
+ VERSION = "3.2.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lato_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.2
4
+ version: 3.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregorio Galante
@@ -142,12 +142,14 @@ files:
142
142
  - app/views/lato_cms/media/_form_create.html.erb
143
143
  - app/views/lato_cms/media/_form_replace_file.html.erb
144
144
  - app/views/lato_cms/media/_form_update.html.erb
145
+ - app/views/lato_cms/media/_preview.html.erb
145
146
  - app/views/lato_cms/media/_translations_field.html.erb
146
147
  - app/views/lato_cms/media/_upload_progress.html.erb
147
148
  - app/views/lato_cms/media/_usages.html.erb
148
149
  - app/views/lato_cms/media/create.html.erb
149
150
  - app/views/lato_cms/media/index.html.erb
150
151
  - app/views/lato_cms/media/picker_action.html.erb
152
+ - app/views/lato_cms/media/show.html.erb
151
153
  - app/views/lato_cms/media/update.html.erb
152
154
  - app/views/lato_cms/pages/_component_accordion.html.erb
153
155
  - app/views/lato_cms/pages/_fields_editor.html.erb