Skip to content

Commit c81c4e6

Browse files
committed
Extract a Spotlight::TabPanelComponent for building bootstrap tab panels
1 parent cac38ef commit c81c4e6

31 files changed

+817
-951
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<%= tag.div role: 'tabpanel', class: @classes.join(' '), id: @id, data: @data do %>
2+
<%= content %>
3+
<% end %>
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
module Spotlight
4+
# Component for a single tab panel pane, with responsibility for also building
5+
# out the tab panel's control
6+
class TabComponent < ViewComponent::Base
7+
def initialize(id:, label:, active: false, label_data: {})
8+
super
9+
10+
@id = id
11+
@label = label
12+
@active = active
13+
@classes = ['tab-pane', ('active' if active)].compact
14+
@label_data = label_data
15+
end
16+
17+
def render_label
18+
tag.li role: 'presentation', class: 'nav-item' do
19+
link_to @label,
20+
"##{@id}",
21+
aria: {
22+
controls: @id
23+
},
24+
role: 'tab',
25+
data: { toggle: 'tab' }.merge(@label_data),
26+
class: ['nav-link', ('active' if @active)].compact.join(' ')
27+
end
28+
end
29+
end
30+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<% tabs_content = capture do %>
2+
<ul class="nav nav-tabs" role="tablist">
3+
<% tabs.each do |tab| %>
4+
<%= tab.render_label %>
5+
<% end %>
6+
</ul>
7+
<% end %>
8+
9+
<%= tabs_content if @tab_position == :outside %>
10+
11+
<div role="tabpanel">
12+
<%= tabs_content if @tab_position == :inside %>
13+
14+
<div class="tab-content">
15+
<% tabs.each do |tab| %>
16+
<%= tab %>
17+
<% end %>
18+
</div>
19+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# frozen_string_literal: true
2+
3+
module Spotlight
4+
# Component for building out a basic tabbed interface
5+
class TabPanelComponent < ViewComponent::Base
6+
renders_many :tabs, Spotlight::TabComponent
7+
8+
def initialize(tab_position: :inside)
9+
super
10+
@tab_position = tab_position
11+
end
12+
end
13+
end

app/views/spotlight/appearances/edit.html.erb

+29-50
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,9 @@
1616
</ul>
1717
</div>
1818
<% end %>
19-
<div role="tabpanel">
20-
<ul class="nav nav-tabs" role="tablist">
21-
<% if current_exhibit.themes.many? %>
22-
<li role="presentation" class="nav-item">
23-
<a href="#site-theme" aria-controls="site-theme" role="tab" data-toggle="tab" class="nav-link active"><%= t(:'.site_theme.heading') %></a>
24-
</li>
25-
<% end %>
26-
27-
<li role="presentation" class="nav-item">
28-
<a href="#site-masthead" aria-controls="site-masthead" role="tab" data-toggle="tab" class="nav-link <%= 'active' unless current_exhibit.themes.many? %>"><%= t(:'.site_masthead.heading') %></a>
29-
</li>
30-
31-
<li role="presentation" class="nav-item">
32-
<a href="#site-thumbnail" aria-controls="site-thumbnail" role="tab" data-toggle="tab" class="nav-link"><%= t(:'.site_thumbnail.heading') %></a>
33-
</li>
34-
35-
<li role="presentation" class="nav-item">
36-
<a href="#main-menu" aria-controls="main-menu" role="tab" data-toggle="tab" class="nav-link"><%= t(:'.main_navigation.menu') %></a>
37-
</li>
38-
</ul>
39-
<div class="tab-content">
40-
<% if current_exhibit.themes.many? %>
41-
<div role="tabpanel" class="tab-pane active" id="site-theme">
19+
<%= render Spotlight::TabPanelComponent.new do |component| %>
20+
<% if current_exhibit.themes.many? %>
21+
<% component.tab(id: 'site-theme', active: true, label: t(:'.site_theme.heading')) do %>
4222
<p class="instructions"><%= t(:'.site_theme.help') %></p>
4323
<%= f.form_group :theme, label: { text: t(:'.site_theme.label') } do %>
4424
<% current_exhibit.themes.each do |theme| %>
@@ -48,37 +28,36 @@
4828
</div>
4929
<% end %>
5030
<% end %>
51-
</div>
5231
<% end %>
32+
<% end %>
5333

54-
<div role="tabpanel" class="tab-pane <%= 'active' unless current_exhibit.themes.many? %>" id="site-masthead">
55-
<p class="instructions"><%= t(:'.site_masthead.help') %></p>
56-
<%= f.fields_for(:masthead, current_exhibit.masthead || current_exhibit.build_masthead) do |m| %>
57-
<%= render '/spotlight/featured_images/form', f: m, initial_crop_selection: Spotlight::Engine.config.masthead_initial_crop_selection, crop_type: :masthead %>
58-
<% end %>
59-
</div>
34+
<% component.tab(id: 'site-masthead', active: !current_exhibit.themes.many?, label: t(:'.site_masthead.heading')) do %>
35+
<p class="instructions"><%= t(:'.site_masthead.help') %></p>
36+
<%= f.fields_for(:masthead, current_exhibit.masthead || current_exhibit.build_masthead) do |m| %>
37+
<%= render '/spotlight/featured_images/form', f: m, initial_crop_selection: Spotlight::Engine.config.masthead_initial_crop_selection, crop_type: :masthead %>
38+
<% end %>``
39+
<% end %>
6040

61-
<div role="tabpanel" class="tab-pane" id="site-thumbnail">
62-
<p class="instructions"><%= t(:'.site_thumbnail.help') %></p>
63-
<%= f.fields_for(:thumbnail, current_exhibit.thumbnail || current_exhibit.build_thumbnail) do |m| %>
64-
<%= render '/spotlight/featured_images/form', f: m, initial_crop_selection: Spotlight::Engine.config.thumbnail_initial_crop_selection, crop_type: :thumbnail %>
65-
<% end %>
66-
</div>
41+
<% component.tab(id: 'site-thumbnail', label: t(:'.site_thumbnail.heading')) do %>
42+
<p class="instructions"><%= t(:'.site_thumbnail.help') %></p>
43+
<%= f.fields_for(:thumbnail, current_exhibit.thumbnail || current_exhibit.build_thumbnail) do |m| %>
44+
<%= render '/spotlight/featured_images/form', f: m, initial_crop_selection: Spotlight::Engine.config.thumbnail_initial_crop_selection, crop_type: :thumbnail %>
45+
<% end %>
46+
<% end %>
6747

68-
<div role="tabpanel" class="tab-pane" id="main-menu">
69-
<%= field_set_tag do %>
70-
<p class="instructions"><%= t(:'.main_navigation.help') %></p>
71-
<div class="card-group dd main_navigation_admin col-sm-7" id="nested-navigation" data-behavior="nestable" data-max-depth="1">
72-
<ol class="dd-list">
73-
<%= f.fields_for :main_navigations do |label| %>
74-
<%= render layout: 'spotlight/shared/dd3_item', locals: { id: label.object.nav_type, field: label, label: label.object.label_or_default, default_value: label.object.default_label, enabled_method: :display } do; end %>
75-
<% end %>
76-
</ol>
77-
</div>
78-
<% end %>
79-
</div>
80-
</div>
81-
</div>
48+
<% component.tab(id: 'main-menu', label: t(:'.main_navigation.menu')) do %>
49+
<%= field_set_tag do %>
50+
<p class="instructions"><%= t(:'.main_navigation.help') %></p>
51+
<div class="card-group dd main_navigation_admin col-sm-7" id="nested-navigation" data-behavior="nestable" data-max-depth="1">
52+
<ol class="dd-list">
53+
<%= f.fields_for :main_navigations do |label| %>
54+
<%= render layout: 'spotlight/shared/dd3_item', locals: { id: label.object.nav_type, field: label, label: label.object.label_or_default, default_value: label.object.default_label, enabled_method: :display } do; end %>
55+
<% end %>
56+
</ol>
57+
</div>
58+
<% end %>
59+
<% end %>
60+
<% end %>
8261

8362
<div class="form-actions">
8463
<div class="primary-actions">

app/views/spotlight/bulk_updates/edit.html.erb

+11-25
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,16 @@
88
<%= render 'progress_panel' %>
99
</div>
1010

11-
<div role="tabpanel">
12-
<ul class="nav nav-tabs" role="tablist">
13-
<li role="presentation" class="nav-item">
14-
<a href="#overview" aria-controls="overview" role="tab" data-toggle="tab" class="nav-link active"><%= t(:'.overview.heading') %></a>
15-
</li>
16-
<li role="presentation" class="nav-item">
17-
<a href="#download" aria-controls="download" role="tab" data-toggle="tab" class="nav-link"><%= t(:'.download.heading') %></a>
18-
</li>
19-
<li role="presentation" class="nav-item">
20-
<a href="#upload" aria-controls="upload" role="tab" data-toggle="tab" class="nav-link"><%= t(:'.upload.heading') %></a>
21-
</li>
22-
</ul>
11+
<%= render Spotlight::TabPanelComponent.new do |component| %>
12+
<% component.tab(id: 'overview', label: t(:'.overview.heading'), active: true) do %>
13+
<%= render 'overview' %>
14+
<% end %>
2315

24-
<div class="tab-content">
25-
<div role="tabpanel" class="tab-pane active" id="overview">
26-
<%= render 'overview' %>
27-
</div>
16+
<% component.tab(id: 'download', label: t(:'.download.heading')) do %>
17+
<%= render 'download' %>
18+
<% end %>
2819

29-
<div role="tabpanel" class="tab-pane" id="download">
30-
<%= render 'download' %>
31-
</div>
32-
33-
<div role="tabpanel" class="tab-pane" id="upload">
34-
<%= render 'upload' %>
35-
</div>
36-
</div>
37-
</div>
20+
<% component.tab(id: 'upload', label: t(:'.upload.heading')) do %>
21+
<%= render 'upload' %>
22+
<% end %>
23+
<% end %>
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
<div role="tabpanel" class="tab-pane" id="delete">
2-
<div class="alert alert-danger">
3-
<h2 class="alert-heading h4"><%= t(:".heading") %></h2>
4-
<div class="row">
5-
<p class='col-9'><%= t(:".warning_html", export_link: link_to(t(:'spotlight.exhibits.export.download'), spotlight.edit_exhibit_path(current_exhibit, anchor: 'export'))) %></p>
6-
<div class='col-3'>
7-
<%= delete_link current_exhibit, class: 'btn btn-secondary' %>
8-
</div>
1+
<div class="alert alert-danger">
2+
<h2 class="alert-heading h4"><%= t(:".heading") %></h2>
3+
<div class="row">
4+
<p class='col-9'><%= t(:".warning_html", export_link: link_to(t(:'spotlight.exhibits.export.download'), spotlight.edit_exhibit_path(current_exhibit, anchor: 'export'))) %></p>
5+
<div class='col-3'>
6+
<%= delete_link current_exhibit, class: 'btn btn-secondary' %>
97
</div>
108
</div>
119
</div>
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
<div role="tabpanel" class="tab-pane <%= 'active' if @tab == 'export' %>" id="export">
2-
<div class="row col-md-12">
3-
<p class="instructions"><%= t :'.instructions' %></p>
4-
<div class="primary-actions">
5-
<%= link_to t(:'.download'), get_exhibit_path(current_exhibit, format: 'json'), class: 'btn btn-primary' %>
6-
</div>
1+
<div class="row col-md-12">
2+
<p class="instructions"><%= t :'.instructions' %></p>
3+
<div class="primary-actions">
4+
<%= link_to t(:'.download'), get_exhibit_path(current_exhibit, format: 'json'), class: 'btn btn-primary' %>
75
</div>
86
</div>
+12-14
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
<div role="tabpanel" class="tab-pane <%= 'active' if @tab == 'import' %>" id="import">
2-
<%= bootstrap_form_for [:import, current_exhibit], html: { class: 'clearfix', multipart: true } do |f| %>
3-
<div class="row col-md-12">
4-
<p class="instructions"><%= t :'.instructions' %></p>
5-
<div class="form-group">
6-
<%= file_field_tag :file, class: 'form-control' %>
7-
<%= hidden_field_tag :tab, 'import' %>
8-
</div>
9-
<div class="form-actions">
10-
<div class="primary-actions">
11-
<%= f.submit t(:'.button'), class: 'btn btn-primary' %>
12-
</div>
1+
<%= bootstrap_form_for [:import, current_exhibit], html: { class: 'clearfix', multipart: true } do |f| %>
2+
<div class="row col-md-12">
3+
<p class="instructions"><%= t :'.instructions' %></p>
4+
<div class="form-group">
5+
<%= file_field_tag :file, class: 'form-control' %>
6+
<%= hidden_field_tag :tab, 'import' %>
7+
</div>
8+
<div class="form-actions">
9+
<div class="primary-actions">
10+
<%= f.submit t(:'.button'), class: 'btn btn-primary' %>
1311
</div>
1412
</div>
15-
<% end %>
16-
</div>
13+
</div>
14+
<% end %>
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,57 @@
1-
<div role="tabpanel" class="tab-pane <%= 'active' if @tab == 'language' %>" id="language">
2-
<p class="instructions"><%= t :'spotlight.exhibits.languages.selection_instructions' %></p>
1+
<p class="instructions"><%= t :'spotlight.exhibits.languages.selection_instructions' %></p>
32

4-
<%= bootstrap_form_for [current_exhibit, Spotlight::Language.new], layout: :horizontal, html: { class: 'row' }, label_col: "col-sm-3", control_col: "col-sm-9" do |f| %>
5-
<div class='col-sm-6'>
6-
<%= f.select('locale', add_exhibit_language_dropdown_options, prompt: t('.selection_prompt')) %>
7-
<%= hidden_field_tag :tab, 'language' %>
8-
</div>
9-
<div class='col-sm-6'>
10-
<%= f.submit nil, class: 'btn btn-primary' %>
11-
</div>
12-
<% end %>
3+
<%= bootstrap_form_for [current_exhibit, Spotlight::Language.new], layout: :horizontal, html: { class: 'row' }, label_col: "col-sm-3", control_col: "col-sm-9" do |f| %>
4+
<div class='col-sm-6'>
5+
<%= f.select('locale', add_exhibit_language_dropdown_options, prompt: t('.selection_prompt')) %>
6+
<%= hidden_field_tag :tab, 'language' %>
7+
</div>
8+
<div class='col-sm-6'>
9+
<%= f.submit nil, class: 'btn btn-primary' %>
10+
</div>
11+
<% end %>
1312

14-
<h2 class="mt-4"><%= t :'spotlight.exhibits.languages.current_header' %></h2>
13+
<h2 class="mt-4"><%= t :'spotlight.exhibits.languages.current_header' %></h2>
1514

16-
<% if current_exhibit.languages.any? && current_exhibit.languages.last.persisted? %>
17-
<p class="instructions"><%= t :'spotlight.exhibits.languages.current_instructions' %></p>
15+
<% if current_exhibit.languages.any? && current_exhibit.languages.last.persisted? %>
16+
<p class="instructions"><%= t :'spotlight.exhibits.languages.current_instructions' %></p>
1817

19-
<%= bootstrap_form_for current_exhibit, layout: :horizontal do |f| %>
20-
<div class="row">
21-
<div class="col-md-8">
22-
<table class="table table-striped">
23-
<thead>
24-
<tr>
25-
<th scope="col"><%= t('.table_heading.language') %></th>
26-
<th scope="col" class='text-center'><%= t('.table_heading.public') %></th>
27-
<th scope="col" class='text-center'><%= t('.table_heading.action') %></th>
28-
</tr>
29-
</thead>
30-
<tbody>
31-
<% current_exhibit.languages.each do |language| %>
32-
<%= f.fields_for :languages, language do |languages| %>
33-
<tr>
34-
<td><%= t("locales.#{language.locale}") %></td>
35-
<td class='text-center'>
36-
<div class='checkbox'>
37-
<%= languages.label :public, class: 'sr-only' %>
38-
<%= languages.check_box_without_bootstrap :public %>
39-
</div>
40-
</td>
41-
<td class='text-center'><%= link_to t('.remove'), exhibit_language_path(current_exhibit, language), method: :delete, data: { confirm: t('.modal.confirm') }, class: 'btn btn-sm btn-danger' %></td>
42-
</tr>
43-
<% end %>
18+
<%= bootstrap_form_for current_exhibit, layout: :horizontal do |f| %>
19+
<div class="row">
20+
<div class="col-md-8">
21+
<table class="table table-striped">
22+
<thead>
23+
<tr>
24+
<th scope="col"><%= t('.table_heading.language') %></th>
25+
<th scope="col" class='text-center'><%= t('.table_heading.public') %></th>
26+
<th scope="col" class='text-center'><%= t('.table_heading.action') %></th>
27+
</tr>
28+
</thead>
29+
<tbody>
30+
<% current_exhibit.languages.each do |language| %>
31+
<%= f.fields_for :languages, language do |languages| %>
32+
<tr>
33+
<td><%= t("locales.#{language.locale}") %></td>
34+
<td class='text-center'>
35+
<div class='checkbox'>
36+
<%= languages.label :public, class: 'sr-only' %>
37+
<%= languages.check_box_without_bootstrap :public %>
38+
</div>
39+
</td>
40+
<td class='text-center'><%= link_to t('.remove'), exhibit_language_path(current_exhibit, language), method: :delete, data: { confirm: t('.modal.confirm') }, class: 'btn btn-sm btn-danger' %></td>
41+
</tr>
4442
<% end %>
45-
</tbody>
46-
</table>
47-
</div>
43+
<% end %>
44+
</tbody>
45+
</table>
4846
</div>
49-
<div class="form-actions">
50-
<div class="primary-actions">
51-
<%= hidden_field_tag :tab, 'language' %>
52-
<%= f.submit nil, class: 'btn btn-primary' %>
53-
</div>
47+
</div>
48+
<div class="form-actions">
49+
<div class="primary-actions">
50+
<%= hidden_field_tag :tab, 'language' %>
51+
<%= f.submit nil, class: 'btn btn-primary' %>
5452
</div>
55-
<% end %>
56-
<% else %>
57-
<p><%= t('.no_languages_help_text') %></p>
53+
</div>
5854
<% end %>
59-
</div>
55+
<% else %>
56+
<p><%= t('.no_languages_help_text') %></p>
57+
<% end %>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<%= render 'tags', tags: @exhibits.published.all_tags %>
2+
<%= render 'exhibits', exhibits: @published_exhibits %>
3+
4+
<% if @published_exhibits.total_count > @published_exhibits.size %>
5+
<nav class="d-flex justify-content-center">
6+
<ul class="pagination">
7+
<li class="page-item"><%= link_to_previous_page @published_exhibits, t('views.pagination.previous').html_safe, class: 'page-link' %></li>
8+
<li class="page-item"><%= link_to_next_page @published_exhibits, t('views.pagination.next').html_safe, class: 'page-link' %></li>
9+
</ul>
10+
</nav>
11+
<% end %>

0 commit comments

Comments
 (0)