standard_view 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -10
  3. data/Rakefile +3 -8
  4. data/app/helpers/standard_view/application_helper.rb +38 -0
  5. data/app/helpers/standard_view/badge_helper.rb +22 -0
  6. data/app/helpers/standard_view/flash_helper.rb +16 -0
  7. data/app/helpers/standard_view/formatting_helper.rb +21 -0
  8. data/app/helpers/standard_view/masthead_helper.rb +27 -0
  9. data/app/helpers/standard_view/navigation_helper.rb +51 -0
  10. data/app/views/application/_attributes_card.html.erb +32 -0
  11. data/app/views/application/_flash_messages.html.erb +7 -0
  12. data/app/views/application/_icon.html.erb +5 -0
  13. data/app/views/application/_javascripts.html.erb +25 -0
  14. data/app/views/application/_list_item.html.erb +11 -0
  15. data/app/views/application/_masthead.html.erb +21 -0
  16. data/app/views/application/_masthead_brand.html.erb +1 -0
  17. data/app/views/application/_masthead_nav.html.erb +6 -0
  18. data/app/views/application/_masthead_nav_items.html.erb +8 -0
  19. data/app/views/application/_masthead_nav_menu.html.erb +8 -0
  20. data/app/views/application/_masthead_nav_menu_icon.html.erb +1 -0
  21. data/app/views/application/_masthead_nav_menu_items.html.erb +10 -0
  22. data/app/views/application/_stylesheet_font_awesome.html.erb +6 -0
  23. data/app/views/application/_stylesheets.html.erb +12 -0
  24. data/app/views/application/index.html.erb +1 -0
  25. data/app/views/application/show.html.erb +1 -0
  26. data/app/views/layouts/standard_view/application.html.erb +8 -7
  27. data/app/views/standard_view/_breadcrumbs.html.erb +48 -0
  28. data/app/views/standard_view/_index.html.erb +83 -0
  29. data/app/views/standard_view/_list_item.html.erb +29 -0
  30. data/app/views/standard_view/_navigation_aside.html.erb +5 -0
  31. data/app/views/standard_view/_navigation_tabs.html.erb +5 -0
  32. data/app/views/standard_view/_page_content.html.erb +8 -0
  33. data/app/views/standard_view/_paginated_collection.html.erb +8 -0
  34. data/app/views/standard_view/_show.html.erb +48 -0
  35. data/config/initializers/material.rb +9 -0
  36. data/config/initializers/simple_form.rb +184 -0
  37. data/config/initializers/simple_form_bootstrap.rb +457 -0
  38. data/config/initializers/will_paginate.rb +57 -0
  39. data/config/locales/en.yml +12 -0
  40. data/lib/standard_view/engine.rb +11 -0
  41. data/lib/standard_view/version.rb +3 -1
  42. data/lib/standard_view.rb +7 -3
  43. metadata +169 -21
  44. data/app/assets/config/standard_view_manifest.js +0 -2
  45. data/app/assets/javascripts/standard_view/application.js +0 -14
  46. data/app/assets/stylesheets/standard_view/application.css +0 -15
  47. data/app/controllers/standard_view/application_controller.rb +0 -5
  48. data/app/jobs/standard_view/application_job.rb +0 -4
  49. data/app/mailers/standard_view/application_mailer.rb +0 -6
  50. data/app/models/standard_view/application_record.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5827cffd3358d0245c71acdf53421f8f99bb066abc266c96d987a729d9f2b844
4
- data.tar.gz: 0b305b4b2fcf519f17f52f06bd6f11c61e29bb9600033f381d16b5b5f5b6ccf2
3
+ metadata.gz: 824ed5917b07dfd7e64412849c15dad8645763bf244cb7386e0c1d05f52922f5
4
+ data.tar.gz: e156d437fc328b5365dc16712a19435e0ca4a704a081fa3d1e5a7fd89fd6b00c
5
5
  SHA512:
6
- metadata.gz: 17708c4ae649a5adf5d22761574b4e5e90800f1bffadf8e14ed7dd01097e24d505bc4f7c39362d0464ea336b8f7da9d3d8641d810fe4d449f3472a67e79c1029
7
- data.tar.gz: 7d71b67689497e243f7d03cef19d35d837ccd3f006514eb3d7d38539846e71306f04606922365725d19e5cbd5cc02f05201ba2988f2e3ce1aef4a1e55753c7f5
6
+ metadata.gz: 01adcd82c9011b0f7251c6cc6063416e71eca9fbbf1ee21dd49aba6efcab0d37d346e78e0455dbd8f781e1c1d8611ffd19df2225bf0d7d6adcb03415a4aa5ee6
7
+ data.tar.gz: 6503b79daf574e4f03bef75e04873537dad8931a7adf50615cd6325254812e82894fd07304d7e94b90f20ace5de00150a184e647adae0ab2cfdb33f0ee43386f
data/README.md CHANGED
@@ -1,10 +1,21 @@
1
1
  # StandardView
2
- Short description and motivation.
3
2
 
4
- ## Usage
5
- How to use my plugin.
3
+ Use Bootstrap to present a nicely standardized view for your models.
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/standard_view.svg)](https://badge.fury.io/rb/standard_view)
6
+ [![Build Status](https://semaphoreci.com/api/v1/freshly/standard_view/branches/develop/badge.svg)](https://semaphoreci.com/freshly/standard_view)
7
+ [![Maintainability](https://api.codeclimate.com/v1/badges/beccb908a058d1c51245/maintainability)](https://codeclimate.com/github/Freshly/standard_view/maintainability)
8
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/beccb908a058d1c51245/test_coverage)](https://codeclimate.com/github/Freshly/standard_view/test_coverage)
9
+
10
+ * [StandardView](#standardview)
11
+ * [Installation](#installation)
12
+ * [Usage](#usage)
13
+ * [Development](#development)
14
+ * [Contributing](#contributing)
15
+ * [License](#license)
6
16
 
7
17
  ## Installation
18
+
8
19
  Add this line to your application's Gemfile:
9
20
 
10
21
  ```ruby
@@ -12,17 +23,27 @@ gem 'standard_view'
12
23
  ```
13
24
 
14
25
  And then execute:
15
- ```bash
16
- $ bundle
17
- ```
26
+
27
+ $ bundle
18
28
 
19
29
  Or install it yourself as:
20
- ```bash
21
- $ gem install standard_view
22
- ```
30
+
31
+ $ gem install standard_view
32
+
33
+ ## Usage
34
+
35
+ TODO: Write usage instructions here
36
+
37
+ ## Development
38
+
39
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
40
+
41
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
23
42
 
24
43
  ## Contributing
25
- Contribution directions go here.
44
+
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Freshly/standard_view.
26
46
 
27
47
  ## License
48
+
28
49
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -17,13 +17,8 @@ end
17
17
  load 'rails/tasks/statistics.rake'
18
18
 
19
19
  require 'bundler/gem_tasks'
20
+ require "rspec/core/rake_task"
20
21
 
21
- require 'rake/testtask'
22
+ RSpec::Core::RakeTask.new(:spec)
22
23
 
23
- Rake::TestTask.new(:test) do |t|
24
- t.libs << 'test'
25
- t.pattern = 'test/**/*_test.rb'
26
- t.verbose = false
27
- end
28
-
29
- task default: :test
24
+ task default: :spec
@@ -1,4 +1,42 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module StandardView
2
4
  module ApplicationHelper
5
+ def action
6
+ ActiveSupport::StringInquirer.new action_name
7
+ end
8
+
9
+ def active_for(options = {})
10
+ "active" if on_page?(options)
11
+ end
12
+
13
+ def on_page?(check_parameters: false, **options)
14
+ current_page?(options, check_parameters: check_parameters)
15
+ rescue ActionController::UrlGenerationError
16
+ false
17
+ end
18
+
19
+ def icon_for(reference, spin: false)
20
+ reference = reference.icon if reference.respond_to?(:icon)
21
+ definition = if reference.nil?
22
+ {}
23
+ elsif reference.respond_to?(:to_h)
24
+ reference.to_h
25
+ else
26
+ I18n.t("icons.#{reference}", default: nil) || reference
27
+ end
28
+
29
+ definition = { name: definition } if definition.present? && !definition.respond_to?(:fetch)
30
+
31
+ icon_tag(definition[:name], definition[:style], spin: spin)
32
+ end
33
+
34
+ def current_page
35
+ params[:page]
36
+ end
37
+
38
+ def icon_tag(name = nil, style = nil, spin: false)
39
+ content_tag(:i, "", class: "fa#{style || "s"} fa-#{name || "question"} #{"fa-spin" if spin}")
40
+ end
3
41
  end
4
42
  end
@@ -0,0 +1,22 @@
1
+ module StandardView
2
+ module BadgeHelper
3
+ def badge(content, type: "dark", right: false, pill: false, extra_class: nil, **options)
4
+ extra = "#{"badge-pill" if pill} #{"float-right mt-1 ml-2" if right} #{extra_class}"
5
+ content_tag :span, content, class: "badge badge-#{type} #{extra}", **options
6
+ end
7
+
8
+ def count_badge(value, type: "dark", extra_class: "ml-1", **options)
9
+ number = value.respond_to?(:count) ? value.count : value
10
+ badge_type = block_given? ? yield(number) : type
11
+ badge number_with_delimiter(number), type: badge_type, extra_class: extra_class, **options
12
+ end
13
+
14
+ def unread_badge(value, **options)
15
+ count_badge(value, **options) { |number| number.zero? ? "dark" : "danger" }
16
+ end
17
+
18
+ def boolean_badge(is, **options)
19
+ badge t(is ? "common.on" : "common.off"), type: is ? "success" : "danger", **options
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StandardView
4
+ module FlashHelper
5
+ ALERT_CLASSES_BY_FLASH_TYPE = {
6
+ success: "alert-success",
7
+ error: "alert-danger",
8
+ alert: "alert-warning",
9
+ notice: "alert-info",
10
+ }.freeze
11
+
12
+ def alert_class_for_flash(flash_type)
13
+ ALERT_CLASSES_BY_FLASH_TYPE.fetch(flash_type.to_sym, flash_type.to_s)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StandardView
4
+ module FormattingHelper
5
+ def title_for_collection(collection)
6
+ title_for_model(collection.model)
7
+ end
8
+
9
+ def title_for_model(model)
10
+ heading_for_model(model).pluralize
11
+ end
12
+
13
+ def heading_for_model(model)
14
+ model.model_name.human.titleize
15
+ end
16
+
17
+ def color_square(color, size: "24px")
18
+ content_tag(:div, "", title: color, style: "width: #{size}; height: #{size}; background: #{color}")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StandardView
4
+ module MastheadHelper
5
+ def masthead_nav_link_for_model(model_class)
6
+ list = Material::List.for(model_class)
7
+ masthead_nav_link list.item_class, list.list_title, active_for(controller: list.route_key)
8
+ end
9
+
10
+ def masthead_menu_link_for_model(model_class)
11
+ list = Material::List.for(model_class)
12
+ masthead_menu_link list.item_class, list.icon, list.list_title, active_for(controller: list.route_key)
13
+ end
14
+
15
+ def masthead_nav_link(destination, text, class_name = nil, **options)
16
+ link_to(destination, class: "nav-item nav-link #{class_name}", **options) { text }
17
+ end
18
+
19
+ def masthead_menu_link(destination, icon_type, text, class_name = nil, **options)
20
+ link_to(destination, class: "dropdown-item #{class_name}", **options) { icon_with_text(icon_type, text) }
21
+ end
22
+
23
+ def icon_with_text(icon_type, text)
24
+ "#{icon_for(icon_type)}&nbsp;#{text}".html_safe
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StandardView
4
+ module NavigationHelper
5
+ def nav_item_overview_for_material(material)
6
+ active_link_class = active_for(controller: material.route_key, action: :show)
7
+ content_tag(:li, class: "nav-item") do
8
+ link_to(t("common.overview"), material, class: "nav-link #{active_link_class}")
9
+ end
10
+ end
11
+
12
+ def nav_item_nested_model_for_record(record, model, count_method = nil)
13
+ nav_item_related_model_for_record(record, model, count_method, nested: true)
14
+ end
15
+
16
+ def nav_item_related_model_for_record(record, model, count_method = nil, nested: false)
17
+ collection = model.model_name.collection
18
+ count_method ||= begin
19
+ default_count_method_name = "#{collection}_count".to_sym
20
+ record.respond_to?(default_count_method_name) ? default_count_method_name : collection
21
+ end
22
+
23
+ link_target = [ collection, record ]
24
+ link_target.reverse! if nested
25
+
26
+ active_link_arguments = { controller: (nested ? model : record).model_name.collection }
27
+ active_link_arguments[:action] = collection unless nested
28
+
29
+ nav_item(
30
+ link_target: link_target,
31
+ icon: model.model_name.singular.to_sym,
32
+ title: title_for_model(model),
33
+ count: record.public_send(count_method.to_sym),
34
+ active_class: active_for(**active_link_arguments),
35
+ )
36
+ end
37
+
38
+ def nav_item(link_target:, icon:, title:, count:, active_class:)
39
+ content_tag(:li, class: "nav-item") do
40
+ link_to(link_target, class: "nav-link #{active_class}") do
41
+ content_tag(:span) do
42
+ concat icon_for(icon)
43
+ concat "&nbsp;".html_safe
44
+ concat title
45
+ concat count_badge(count)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,32 @@
1
+ <% cache material do %>
2
+ <div class="card">
3
+ <div class="card-header">
4
+ <%# if content_for?(:attributes_action) %>
5
+ <%#= content_for(:attributes_action) %>
6
+ <%# else %>
7
+ <%# if controller.action_methods.include?("edit") && (!record.respond_to?(:editable?) || record.editable?) %>
8
+ <%#= link_to t("edit"), { action: :edit }, class: "btn btn-primary btn-sm float-right" %>
9
+ <%# elsif controller.action_methods.include? "destroy" %>
10
+ <%# if (!record.respond_to?(:destroyable?) || record.destroyable?) %>
11
+ <%#= link_to t("destroy"), record, class: "btn btn-danger btn-sm float-right", method: :delete, data: { confirm: t("confirm_destroy") } %>
12
+ <%# end %>
13
+ <%# end %>
14
+ <%#= content_for(:extra_attributes_action) if content_for?(:extra_attributes_action) %>
15
+ <%# end %>
16
+
17
+ <h4 class="mb-0"><%= t(".title") %></h4>
18
+ </div>
19
+ <div class="card-body p-0">
20
+ <table class="table m-0">
21
+ <tbody>
22
+ <% material.sorted_attribute_names.each do |attribute_name| %>
23
+ <tr>
24
+ <th><%= material.human_attribute_name(attribute_name) %></th>
25
+ <td><%= material.human_attribute_value(attribute_name) %></td>
26
+ </tr>
27
+ <% end %>
28
+ </tbody>
29
+ </table>
30
+ </div>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <% if flash.any? %>
2
+ <section id="flash-messages" class="container">
3
+ <% flash.each do |type, message| %>
4
+ <%= content_tag :div, message, class: "alert #{alert_class_for_flash(type)}" %>
5
+ <% end %>
6
+ </section>
7
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% if material.icon_title? %>
2
+ <%= content_tag(:span, icon_for(material), title: material.icon_title) %>
3
+ <% else %>
4
+ <%= icon_for material %>
5
+ <% end %>
@@ -0,0 +1,25 @@
1
+ <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
2
+
3
+ <script
4
+ src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
5
+ integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
6
+ crossorigin="anonymous"
7
+ ></script>
8
+ <script
9
+ src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
10
+ integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
11
+ crossorigin="anonymous"
12
+ ></script>
13
+ <script
14
+ src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
15
+ integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
16
+ crossorigin="anonymous"
17
+ ></script>
18
+ <script
19
+ src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-colorpicker/2.5.3/js/bootstrap-colorpicker.min.js"
20
+ crossorigin="anonymous"
21
+ ></script>
22
+
23
+ <%= javascript_include_tag "application" %>
24
+
25
+ <%= content_for(:page_scripts) if content_for?(:page_scripts) %>
@@ -0,0 +1,11 @@
1
+ <% render_default_partial = true %>
2
+ <% source_partial_path = list_item.source.try(:to_partial_path) %>
3
+ <% if source_partial_path.present? %>
4
+ <% prefix, path = source_partial_path.split("/") %>
5
+ <% if lookup_context.template_exists?(path, prefix, true) %>
6
+ <% render_default_partial = false %>
7
+ <%= render partial: source_partial_path, locals: { path.to_sym => list_item } %>
8
+ <% end %>
9
+ <% end %>
10
+
11
+ <%= render "standard_view/list_item", material: list_item if render_default_partial %>
@@ -0,0 +1,21 @@
1
+ <header class="navbar navbar-expand-lg navbar-dark bg-dark mb-3">
2
+ <div class="container">
3
+ <%= render "masthead_brand" %>
4
+
5
+ <button
6
+ class="navbar-toggler"
7
+ type="button"
8
+ data-toggle="collapse"
9
+ data-target="#masthead-nav"
10
+ aria-controls="masthead-nav"
11
+ aria-expanded="false"
12
+ aria-label="Toggle navigation"
13
+ >
14
+ <span class="navbar-toggler-icon"></span>
15
+ </button>
16
+
17
+ <section class="collapse navbar-collapse" id="masthead-nav">
18
+ <%= render "masthead_nav" %>
19
+ </section>
20
+ </div>
21
+ </header>
@@ -0,0 +1 @@
1
+ <%= link_to t("application.brand"), root_path, class: "navbar-brand" %>
@@ -0,0 +1,6 @@
1
+ <nav class="navbar-nav mr-auto">
2
+ <%= render "masthead_nav_items" %>
3
+ </nav>
4
+ <nav class="navbar-nav">
5
+ <%= render "masthead_nav_menu" %>
6
+ </nav>
@@ -0,0 +1,8 @@
1
+ <!-- Define your own masthead navigation:
2
+ app/views/application/_masthead_nav_items.html.erb => Application Default
3
+ app/views/something_else/_masthead_nav_items.html.erb => Specific Override
4
+
5
+ Example:
6
+ <%#= masthead_nav_link_for_model School %>
7
+ <%#= masthead_nav_link reports_path, t(".reports"), active_for(controller: :reports) %>
8
+ -->
@@ -0,0 +1,8 @@
1
+ <div class="dropdown">
2
+ <%= link_to "#", class: "nav-link dropdown-toggle", id: "masthead-settings-menu", data: { toggle: "dropdown" } do %>
3
+ <%= render "masthead_nav_menu_icon" %>
4
+ <% end %>
5
+ <nav class="dropdown-menu dropdown-menu-right" aria-labelledby="masthead-settings-menu">
6
+ <%= render "masthead_nav_menu_items" %>
7
+ </nav>
8
+ </div>
@@ -0,0 +1 @@
1
+ <%= icon_for :masthead_nav_menu %>
@@ -0,0 +1,10 @@
1
+ <!-- Define your own masthead menu navigation:
2
+ app/views/application/_masthead_nav_menu_items.html.erb => Application Default
3
+ app/views/something_else/_masthead_nav_menu_items.html.erb => Specific Override
4
+
5
+ Example:
6
+ <h6 class="dropdown-header"><%#= t(".build") %></h6>
7
+ <%#= masthead_menu_link_for_model School %>
8
+ <div class="dropdown-divider"></div>
9
+ <%#= masthead_menu_link reports_path, "flag-checkered", t(".reports"), active_for(controller: :reports) %>
10
+ -->
@@ -0,0 +1,6 @@
1
+ <link
2
+ rel="stylesheet"
3
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css"
4
+ integrity="sha256-UzFD2WYH2U1dQpKDjjZK72VtPeWP50NoJjd26rnAdUI="
5
+ crossorigin="anonymous"
6
+ />
@@ -0,0 +1,12 @@
1
+ <link
2
+ href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
3
+ rel="stylesheet"
4
+ integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
5
+ crossorigin="anonymous"
6
+ >
7
+ <link
8
+ rel="stylesheet"
9
+ href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-colorpicker/2.5.3/css/bootstrap-colorpicker.min.css"
10
+ crossorigin="anonymous"
11
+ >
12
+ <%= render "stylesheet_font_awesome" %>
@@ -0,0 +1 @@
1
+ <%= render "standard_view/index" %>
@@ -0,0 +1 @@
1
+ <%= render "standard_view/show" %>
@@ -1,16 +1,17 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>Standard view</title>
4
+ <title>
5
+ <%= "#{content_for(:title)} #{t("application.separator")} " if content_for?(:title) %><%= t("application.title") %>
6
+ </title>
5
7
  <%= csrf_meta_tags %>
6
8
  <%= csp_meta_tag %>
7
-
8
- <%= stylesheet_link_tag "standard_view/application", media: "all" %>
9
- <%= javascript_include_tag "standard_view/application" %>
9
+ <%= render "stylesheets" %>
10
+ <%= render "javascripts" %>
10
11
  </head>
11
12
  <body>
12
-
13
- <%= yield %>
14
-
13
+ <%= render "masthead" %>
14
+ <%= render "flash_messages" %>
15
+ <%= yield %>
15
16
  </body>
16
17
  </html>
@@ -0,0 +1,48 @@
1
+ <nav aria-label="breadcrumb">
2
+ <ol class="breadcrumb">
3
+ <% if material.parent? %>
4
+ <% parent = material.parent %>
5
+ <li class="breadcrumb-item">
6
+ <% if parent.index_path? %>
7
+ <%= link_to title_for_model(parent), public_send(parent.index_path) %>
8
+ <% else %>
9
+ &hellip;
10
+ <% end %>
11
+ </li>
12
+ <li class="breadcrumb-item"><%= link_to parent.breadcrumb_title, parent %></li>
13
+
14
+ <% unless on_page?(controller: parent.route_key, action: material.route_key) %>
15
+ <li class="breadcrumb-item"><%= link_to title_for_model(material), [ material.route_key, parent ] %></li>
16
+ <% end %>
17
+ <% else %>
18
+ <li class="breadcrumb-item">
19
+ <% if material.index_path? %>
20
+ <%= link_to title_for_model(material), public_send(material.index_path) %>
21
+ <% else %>
22
+ &hellip;
23
+ <% end %>
24
+ </li>
25
+ <% end %>
26
+
27
+ <% if on_page?(controller: material.route_key, action: :show) %>
28
+ <li class="breadcrumb-item active" aria-current="page"><%= material.breadcrumb_title %></li>
29
+ <% else %>
30
+ <% if on_page?(controller: material.route_key) %>
31
+ <li class="breadcrumb-item"><%= link_to material.breadcrumb_title, material %></li>
32
+ <% end %>
33
+ <li class="breadcrumb-item active" aria-current="page">
34
+ <% if local_assigns[:label].present? %>
35
+ <%= local_assigns[:label] %>
36
+ <% elsif I18n.exists?("breadcrumbs.#{controller_name}.#{action_name}") %>
37
+ <%= t("breadcrumbs.#{controller_name}.#{action_name}") %>
38
+ <% elsif I18n.exists?("breadcrumbs.actions.#{action_name}") %>
39
+ <%= t("breadcrumbs.actions.#{action_name}") %>
40
+ <% elsif I18n.exists?("breadcrumbs.controllers.#{controller_name}") %>
41
+ <%= t("breadcrumbs.controllers.#{controller_name}") %>
42
+ <% else %>
43
+ <%= action_name.humanize %>
44
+ <% end %>
45
+ </li>
46
+ <% end %>
47
+ </ol>
48
+ </nav>
@@ -0,0 +1,83 @@
1
+ <%# For the good-spirited and impossibly lazy developer, we attempt to jump-start, assuming conventions. %>
2
+ <% is_nested = local_assigns[:nested] %>
3
+
4
+ <% facet_source = local_assigns[:facet_source] %>
5
+ <% if is_nested && facet_source.nil? %>
6
+ <% facet_source = controller_name.singularize.camelize.constantize.find(params[:id]) %>
7
+ <% end %>
8
+
9
+ <% if local_assigns[:facet].nil? %>
10
+ <% facet_name = is_nested ? action_name : controller_name %>
11
+ <% facet_class = local_assigns[:facet_class].presence || "#{facet_name.singularize.camelize}Facet".constantize %>
12
+ <% facet = facet_class.new(current_page: current_page, source: facet_source) %>
13
+ <% end %>
14
+
15
+ <% if local_assigns[:list].nil? %>
16
+ <% list = Material::List.for(facet.record_class) %>
17
+ <% list.contextualize(facet_source) if is_nested %>
18
+ <% end %>
19
+
20
+ <%# Title must remain outside the cache block or it will not be assigned properly (since it affects the page layout) %>
21
+ <% content_for(:title) { list.title } %>
22
+
23
+ <% cache facet do %>
24
+ <%# Within the cache block, mount the facet for rendering %>
25
+ <% list.mount_facet(facet) %>
26
+ <% list_law = law(list.item_class) %>
27
+
28
+ <% if list.parent? %>
29
+ <% if lookup_context.template_exists?("navigation_tabs", controller_name, true) %>
30
+ <% content_for(:navigation_tabs) { render "navigation_tabs", material: list.parent } %>
31
+ <% elsif lookup_context.template_exists?("navigation_aside", controller_name, true) %>
32
+ <% content_for(:navigation_aside) { render "navigation_aside", material: list.parent } %>
33
+ <% end %>
34
+ <% end %>
35
+
36
+ <%= content_tag :main, id: "#{list.parameterized_title}-index", class: "container" do %>
37
+ <header>
38
+ <%= render "standard_view/breadcrumbs", material: list if list.parent? %>
39
+
40
+ <% if on_page?(action: :index) %>
41
+ <%= link_to t("common.new"), { action: :new }, class: "btn btn-primary btn-lg float-right" if list_law.new? %>
42
+ <% end %>
43
+
44
+ <%= content_tag(:h5, class: "text-muted") { heading_for_model(list.parent) } if list.parent? %>
45
+
46
+ <h1 class="mb-3"><%= list.title %></h1>
47
+
48
+ <%= render "standard_view/navigation_tabs" if content_for?(:navigation_tabs) %>
49
+ </header>
50
+
51
+ <%= content_tag(:hr) unless content_for?(:navigation_tabs) %>
52
+
53
+ <% unless content_for?(:page_content) %>
54
+ <% content_for(:page_content) do %>
55
+ <%# if content_for?(:subnav_content) || uses_filter %>
56
+ <%#= content_for(:subnav_content) if content_for?(:subnav_content) %>
57
+
58
+ <%# if uses_filter %>
59
+ <%#= render "filter", field: filter_by, default: local_assigns[:filter_default], model: collection.model %>
60
+ <%# end %>
61
+ <!-- <hr>-->
62
+ <%# end %>
63
+
64
+ <div class="row">
65
+ <div class="col-12">
66
+ <%# filtered_collection = collection %>
67
+ <%# if uses_filter %>
68
+ <%# if params[:filter].present? %>
69
+ <%# filtered_collection = filtered_collection.public_send(params[:filter].to_sym) %>
70
+ <%# elsif has_filter_default && !params[:all].present? %>
71
+ <%# filtered_collection = filtered_collection.public_send(filter_default) %>
72
+ <%# end %>
73
+ <%# end %>
74
+
75
+ <%= render "standard_view/paginated_collection", list: list, is_filtered: facet.filtered? %>
76
+ </div>
77
+ </div>
78
+ <% end %>
79
+ <% end %>
80
+
81
+ <%= render "standard_view/page_content" %>
82
+ <% end %>
83
+ <% end %>
@@ -0,0 +1,29 @@
1
+ <% content_for(:standard_list_item, flush: true) do %>
2
+ <%= render "icon", material: material %>
3
+
4
+ <% if material.list_title_truncated? %>
5
+ <%= content_tag :span, material.list_title, title: material.list_title_value, class: "px-2" %>
6
+ <% else %>
7
+ <%= content_tag :span, material.list_title, class: "px-2" %>
8
+ <% end %>
9
+
10
+ <% if material.label? %>
11
+ <% label_options = { pill: true } %>
12
+ <% label_options[:type] = material.label_style if material.label_style? %>
13
+ <%= badge material.label, **label_options %>
14
+ <% end %>
15
+
16
+ <% if material.badge? %>
17
+ <% badge_options = { right: true } %>
18
+ <% badge_options[:type] = material.badge_style if material.badge_style? %>
19
+ <%= badge material.badge, **badge_options %>
20
+ <% end %>
21
+ <% end %>
22
+
23
+ <% list_item_style_class = material.list_item_style? ? " list-group-item-#{material.list_item_style}" : "" %>
24
+ <% class_name = "list-group-item list-group-item-action#{list_item_style_class}" %>
25
+ <% if material.path? %>
26
+ <%= link_to content_for(:standard_list_item), material, class: class_name %>
27
+ <% else %>
28
+ <%= content_tag :span, content_for(:standard_list_item), class: class_name %>
29
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <nav id="navigation-aside" class="mb-3">
2
+ <ul class="nav flex-column nav-pills">
3
+ <%= content_for(:navigation_aside) %>
4
+ </ul>
5
+ </nav>