trestle 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +12 -5
  3. data/Gemfile +1 -0
  4. data/README.md +1 -1
  5. data/app/assets/bundle/trestle/bundle.css +0 -0
  6. data/app/assets/bundle/trestle/bundle.js +0 -0
  7. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  8. data/app/assets/bundle/trestle/fa-brands-400.svg +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  10. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  11. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  12. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  13. data/app/assets/bundle/trestle/fa-regular-400.svg +0 -0
  14. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  15. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  16. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  17. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  18. data/app/assets/bundle/trestle/fa-solid-900.svg +0 -0
  19. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  20. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  21. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  22. data/app/assets/bundle/trestle/flatpickr/ar.js +0 -0
  23. data/app/assets/bundle/trestle/flatpickr/at.js +0 -0
  24. data/app/assets/bundle/trestle/flatpickr/az.js +0 -0
  25. data/app/assets/bundle/trestle/flatpickr/be.js +0 -0
  26. data/app/assets/bundle/trestle/flatpickr/bg.js +0 -0
  27. data/app/assets/bundle/trestle/flatpickr/bn.js +0 -0
  28. data/app/assets/bundle/trestle/flatpickr/bs.js +0 -0
  29. data/app/assets/bundle/trestle/flatpickr/cat.js +0 -0
  30. data/app/assets/bundle/trestle/flatpickr/cs.js +0 -0
  31. data/app/assets/bundle/trestle/flatpickr/cy.js +0 -0
  32. data/app/assets/bundle/trestle/flatpickr/da.js +0 -0
  33. data/app/assets/bundle/trestle/flatpickr/de.js +0 -0
  34. data/app/assets/bundle/trestle/flatpickr/default.js +0 -0
  35. data/app/assets/bundle/trestle/flatpickr/eo.js +0 -0
  36. data/app/assets/bundle/trestle/flatpickr/es.js +0 -0
  37. data/app/assets/bundle/trestle/flatpickr/et.js +0 -0
  38. data/app/assets/bundle/trestle/flatpickr/fa.js +0 -0
  39. data/app/assets/bundle/trestle/flatpickr/fi.js +0 -0
  40. data/app/assets/bundle/trestle/flatpickr/fo.js +0 -0
  41. data/app/assets/bundle/trestle/flatpickr/fr.js +0 -0
  42. data/app/assets/bundle/trestle/flatpickr/ga.js +0 -0
  43. data/app/assets/bundle/trestle/flatpickr/gr.js +0 -0
  44. data/app/assets/bundle/trestle/flatpickr/he.js +0 -0
  45. data/app/assets/bundle/trestle/flatpickr/hi.js +0 -0
  46. data/app/assets/bundle/trestle/flatpickr/hr.js +0 -0
  47. data/app/assets/bundle/trestle/flatpickr/hu.js +0 -0
  48. data/app/assets/bundle/trestle/flatpickr/id.js +0 -0
  49. data/app/assets/bundle/trestle/flatpickr/is.js +0 -0
  50. data/app/assets/bundle/trestle/flatpickr/it.js +0 -0
  51. data/app/assets/bundle/trestle/flatpickr/ja.js +0 -0
  52. data/app/assets/bundle/trestle/flatpickr/ka.js +0 -0
  53. data/app/assets/bundle/trestle/flatpickr/km.js +0 -0
  54. data/app/assets/bundle/trestle/flatpickr/ko.js +0 -0
  55. data/app/assets/bundle/trestle/flatpickr/kz.js +0 -0
  56. data/app/assets/bundle/trestle/flatpickr/lt.js +0 -0
  57. data/app/assets/bundle/trestle/flatpickr/lv.js +0 -0
  58. data/app/assets/bundle/trestle/flatpickr/mk.js +0 -0
  59. data/app/assets/bundle/trestle/flatpickr/mn.js +0 -0
  60. data/app/assets/bundle/trestle/flatpickr/ms.js +0 -0
  61. data/app/assets/bundle/trestle/flatpickr/my.js +0 -0
  62. data/app/assets/bundle/trestle/flatpickr/nl.js +0 -0
  63. data/app/assets/bundle/trestle/flatpickr/no.js +0 -0
  64. data/app/assets/bundle/trestle/flatpickr/pa.js +0 -0
  65. data/app/assets/bundle/trestle/flatpickr/pl.js +0 -0
  66. data/app/assets/bundle/trestle/flatpickr/pt.js +0 -0
  67. data/app/assets/bundle/trestle/flatpickr/ro.js +0 -0
  68. data/app/assets/bundle/trestle/flatpickr/ru.js +0 -0
  69. data/app/assets/bundle/trestle/flatpickr/si.js +0 -0
  70. data/app/assets/bundle/trestle/flatpickr/sk.js +0 -0
  71. data/app/assets/bundle/trestle/flatpickr/sl.js +0 -0
  72. data/app/assets/bundle/trestle/flatpickr/sq.js +0 -0
  73. data/app/assets/bundle/trestle/flatpickr/sr-cyr.js +0 -0
  74. data/app/assets/bundle/trestle/flatpickr/sr.js +0 -0
  75. data/app/assets/bundle/trestle/flatpickr/sv.js +0 -0
  76. data/app/assets/bundle/trestle/flatpickr/th.js +0 -0
  77. data/app/assets/bundle/trestle/flatpickr/tr.js +0 -0
  78. data/app/assets/bundle/trestle/flatpickr/uk.js +0 -0
  79. data/app/assets/bundle/trestle/flatpickr/uz.js +0 -0
  80. data/app/assets/bundle/trestle/flatpickr/uz_latn.js +0 -0
  81. data/app/assets/bundle/trestle/flatpickr/vn.js +0 -0
  82. data/app/assets/bundle/trestle/flatpickr/zh-tw.js +0 -0
  83. data/app/assets/bundle/trestle/flatpickr/zh.js +0 -0
  84. data/app/controllers/trestle/admin_controller.rb +23 -25
  85. data/app/controllers/trestle/application_controller.rb +10 -12
  86. data/app/controllers/trestle/dashboard_controller.rb +11 -13
  87. data/app/controllers/trestle/resource_controller.rb +5 -7
  88. data/app/helpers/trestle/layout_helper.rb +20 -0
  89. data/app/helpers/trestle/navigation_helper.rb +23 -0
  90. data/app/views/layouts/trestle/admin.html.erb +2 -2
  91. data/app/views/trestle/resource/_scopes.html.erb +17 -8
  92. data/app/views/trestle/resource/index.html.erb +1 -1
  93. data/app/views/trestle/shared/_sidebar.html.erb +4 -5
  94. data/frontend/css/components/_fields.scss +5 -0
  95. data/frontend/css/components/_scopes.scss +65 -22
  96. data/frontend/css/layout/_content.scss +5 -2
  97. data/frontend/css/variables/_trestle.scss +5 -5
  98. data/frontend/js/components/navigation.js +63 -0
  99. data/frontend/js/components/sidebar.js +4 -7
  100. data/lib/trestle/evaluation_context.rb +11 -3
  101. data/lib/trestle/form/fields/form_group.rb +6 -4
  102. data/lib/trestle/navigation/group.rb +4 -0
  103. data/lib/trestle/resource.rb +2 -2
  104. data/lib/trestle/resource/builder.rb +3 -2
  105. data/lib/trestle/resource/collection.rb +1 -5
  106. data/lib/trestle/scopes.rb +37 -9
  107. data/lib/trestle/scopes/definition.rb +22 -0
  108. data/lib/trestle/scopes/scope.rb +5 -1
  109. data/lib/trestle/version.rb +1 -1
  110. data/webpack.config.js +4 -1
  111. data/yarn.lock +771 -712
  112. metadata +5 -2
@@ -1,9 +1,18 @@
1
- <ul class="scopes">
2
- <% admin.scopes.each do |name, scope| %>
3
- <%= content_tag(:li, class: ("active" if scope.active?(params))) do %>
4
- <%= link_to persistent_params.merge(scope: (name unless scope.active?(params))) do %>
5
- <strong><%= scope.label %></strong> (<%= number_with_delimiter(scope.count(admin.collection(params))) %>)
6
- <% end %>
7
- <% end %>
1
+ <%= content_tag(:dl, class: admin.scopes.classes) do %>
2
+ <% admin.scopes.grouped.each do |group, scopes| %>
3
+ <%= content_tag(:dt, group, class: ["scope-group", ("scope-group-empty" if group.blank?)]) if admin.scopes.grouped? %>
4
+
5
+ <dd>
6
+ <ul class="scope-list">
7
+ <% scopes.each do |scope| %>
8
+ <li>
9
+ <%= link_to persistent_params.merge(scope: (scope unless scope.active?(params))), class: ["scope", ("active" if scope.active?(params))] do %>
10
+ <strong><%= scope.label %></strong>
11
+ (<%= number_with_delimiter(scope.count(admin.collection(params))) %>)
12
+ <% end %>
13
+ </li>
14
+ <% end %>
15
+ </ul>
16
+ </dd>
8
17
  <% end %>
9
- </ul>
18
+ <% end %>
@@ -5,7 +5,7 @@
5
5
  <% end %>
6
6
 
7
7
  <% content_for(:utilities) do %>
8
- <%= render "scopes" if admin.scopes.any? %>
8
+ <%= render "scopes" %>
9
9
  <% end if admin.scopes.any? %>
10
10
 
11
11
  <%= render layout: "layout" do %>
@@ -11,24 +11,23 @@
11
11
 
12
12
  <div class="app-sidebar-inner">
13
13
  <nav class="app-nav">
14
- <% collapsed = cookies["trestle:navigation:collapsed"].try(:split, ",") || [] %>
15
14
  <% Trestle.navigation(self).each do |group, items| %>
16
- <ul<% if group.present? && collapsed.include?(group.id) %> class="collapsed"<% end %>>
15
+ <%= content_tag(:ul, class: ("collapsed" if group.present? && navigation_group_collapsed?(group)), data: { group: group.id }) do %>
17
16
  <% if group.present? %>
18
17
  <li class="nav-header"><%= link_to group.label, "##{group.id}" %></li>
19
18
  <% end %>
20
19
 
21
20
  <% items.each do |item| %>
22
- <li<% if current_navigation_item?(item) %> class="active"<% end %>>
21
+ <%= content_tag(:li, class: ("active" if current_navigation_item?(item))) do %>
23
22
  <%= link_to item.path, item.html_options do %>
24
23
  <%= icon("nav-icon", item.icon) %>
25
24
  <span class="nav-label"><%= item.label %></span>
26
25
 
27
26
  <%= content_tag(:span, item.badge.text, class: ["badge", item.badge.html_class]) if item.badge? %>
28
27
  <% end %>
29
- </li>
28
+ <% end %>
30
29
  <% end %>
31
- </ul>
30
+ <% end %>
32
31
  <% end %>
33
32
  </nav>
34
33
 
@@ -12,6 +12,11 @@
12
12
  }
13
13
  }
14
14
 
15
+ ul.invalid-feedback {
16
+ list-style: none;
17
+ padding-left: 0;
18
+ }
19
+
15
20
  .form-text {
16
21
  color: $form-text-color;
17
22
  font-size: 0.9rem;
@@ -1,46 +1,89 @@
1
1
  .scopes {
2
- list-style: none;
3
-
4
- margin-top: -0.25rem;
5
2
  margin-bottom: 0;
6
3
 
7
- padding: 0;
4
+ dd {
5
+ margin-bottom: 0;
6
+ }
7
+
8
+ &.grouped {
9
+ @include media-breakpoint-up(md) {
10
+ display: grid;
11
+ grid-template-columns: auto 1fr;
12
+ }
13
+
14
+
15
+ @include media-breakpoint-down(sm) {
16
+ .scope-group-empty:first-child {
17
+ display: none;
18
+ }
19
+ }
20
+
21
+ background: #fafafa;
22
+
23
+ dd {
24
+ padding: 0.375rem 0.5rem 0.375rem;
25
+ }
26
+ }
27
+
28
+ &.columns {
29
+ grid-template-rows: auto 1fr;
30
+ grid-auto-flow: column;
31
+
32
+ overflow-x: auto;
33
+ }
34
+ }
35
+
36
+ .scope-group {
37
+ line-height: 2;
38
+ font-size: 0.85rem;
39
+ padding: 0.5rem 1rem 0.25rem 0.75rem;
40
+
41
+ background: #f7f7f7;
42
+ }
43
+
44
+ .scope-list {
45
+ list-style: none;
8
46
 
9
47
  display: flex;
10
48
  flex-wrap: wrap;
11
49
 
50
+ position: relative;
51
+ align-items: center;
52
+
53
+ margin-bottom: 0;
54
+ padding: 0;
55
+
12
56
  li {
13
- margin-top: 0.25rem;
14
- margin-right: 0.35rem;
57
+ margin: 0.125rem 0.35rem 0.125rem 0;
15
58
 
16
59
  &:last-child {
17
60
  margin-right: 0;
18
61
  }
19
62
  }
63
+ }
20
64
 
21
- a {
22
- display: inline-block;
65
+ .scope {
66
+ display: inline-block;
23
67
 
24
- background-color: $scope-bg;
68
+ background-color: $scope-bg;
25
69
 
26
- font-size: 0.8rem;
27
- font-weight: normal;
28
- white-space: nowrap;
70
+ font-size: 0.8rem;
71
+ font-weight: normal;
72
+ white-space: nowrap;
29
73
 
30
- border-radius: 50rem;
31
- padding: $scope-padding;
74
+ border-radius: 50rem;
75
+ padding: $scope-padding;
32
76
 
33
- &, &:hover, &:focus {
34
- color: $scope-color;
35
- }
77
+ &, &:hover, &:focus {
78
+ color: $scope-color;
79
+ }
36
80
 
37
- &:hover, &:focus {
38
- background-color: $scope-hover-bg;
39
- text-decoration: none;
40
- }
81
+ &:hover, &:focus {
82
+ background-color: $scope-hover-bg;
83
+ text-decoration: none;
41
84
  }
42
85
 
43
- li.active a {
86
+ &.active {
44
87
  &, &:hover, &:focus, strong {
45
88
  color: $scope-active-color;
46
89
  }
@@ -105,8 +105,7 @@
105
105
 
106
106
  .utilities {
107
107
  display: flex;
108
- justify-content: space-between;
109
-
108
+ justify-content: flex-start;
110
109
  margin-bottom: 10px;
111
110
  }
112
111
 
@@ -146,6 +145,10 @@
146
145
  padding: 15px;
147
146
  }
148
147
 
148
+ .utilities {
149
+ margin-bottom: 10px;
150
+ }
151
+
149
152
  .main-content-header,
150
153
  .main-content-footer {
151
154
  flex-direction: column;
@@ -77,14 +77,14 @@ $tag-hover-border: darken(theme-color("primary"), 10%);
77
77
 
78
78
  // Scopes
79
79
 
80
- $scope-padding: 0.25rem 0.5rem;
80
+ $scope-padding: 0.25rem 0.675rem;
81
81
 
82
- $scope-color: rgba(black, 0.3);
83
- $scope-bg: rgba(black, 0.025);
82
+ $scope-color: rgba(black, 0.4);
83
+ $scope-bg: rgba(black, 0.035);
84
84
 
85
- $scope-label-color: rgba(black, 0.4);
85
+ $scope-label-color: rgba(black, 0.5);
86
86
 
87
- $scope-hover-color: rgba(black, 0.3);
87
+ $scope-hover-color: rgba(black, 0.5);
88
88
  $scope-hover-bg: rgba(black, 0.05);
89
89
 
90
90
  $scope-active-color: white;
@@ -0,0 +1,63 @@
1
+ import cookie from '../core/cookie'
2
+
3
+ const PREFIX = 'trestle:navigation'
4
+ const SEPARATOR = ','
5
+
6
+ class NavigationCookieStore {
7
+ addGroup (id, state) {
8
+ this.updateState(state, (groups) => groups.add(id))
9
+ }
10
+
11
+ removeGroup (id, state) {
12
+ this.updateState(state, (groups) => groups.delete(id))
13
+ }
14
+
15
+ updateState (state, callback) {
16
+ const groups = this.getState(state)
17
+ callback(groups)
18
+ this.saveState(state, groups)
19
+ }
20
+
21
+ getState (state) {
22
+ const str = cookie.get(`${PREFIX}:${state}`)
23
+ return new Set(str.length ? str.split(SEPARATOR) : [])
24
+ }
25
+
26
+ saveState (state, groups) {
27
+ cookie.set(`${PREFIX}:${state}`, [...groups].join(SEPARATOR))
28
+ }
29
+ }
30
+
31
+ class Navigation {
32
+ constructor () {
33
+ this.store = new NavigationCookieStore()
34
+ }
35
+
36
+ toggle (list) {
37
+ if (list.hasClass('collapsed')) {
38
+ this.expand(list)
39
+ } else {
40
+ this.collapse(list)
41
+ }
42
+ }
43
+
44
+ expand (list) {
45
+ list.removeClass('collapsed')
46
+
47
+ const id = list.data('group')
48
+
49
+ this.store.addGroup(id, 'expanded')
50
+ this.store.removeGroup(id, 'collapsed')
51
+ }
52
+
53
+ collapse (list) {
54
+ list.addClass('collapsed')
55
+
56
+ const id = list.data('group')
57
+
58
+ this.store.addGroup(id, 'collapsed')
59
+ this.store.removeGroup(id, 'expanded')
60
+ }
61
+ }
62
+
63
+ export default new Navigation()
@@ -3,6 +3,8 @@ import $ from 'jquery'
3
3
  import { ready } from '../core/events'
4
4
  import cookie from '../core/cookie'
5
5
 
6
+ import Navigation from './navigation'
7
+
6
8
  ready(function () {
7
9
  const $body = $('body')
8
10
  const $wrapper = $('.app-wrapper')
@@ -60,13 +62,8 @@ ready(function () {
60
62
  $sidebar.find('.nav-header a').on('click', function (e) {
61
63
  e.preventDefault()
62
64
 
63
- $(this).closest('ul').toggleClass('collapsed')
64
-
65
- const collapsed = $sidebar.find('.collapsed .nav-header a').map(function () {
66
- return $(this).attr('href').replace(/^#/, '')
67
- }).toArray()
68
-
69
- cookie.set('trestle:navigation:collapsed', collapsed.join(','))
65
+ const list = $(this).closest('ul')
66
+ Navigation.toggle(list)
70
67
  })
71
68
 
72
69
  // Scroll sidebar to active item
@@ -5,12 +5,15 @@ module Trestle
5
5
  # both the Adapter/Navigation instance, as well as the controller/view from where they are invoked.
6
6
  module EvaluationContext
7
7
  protected
8
+ def self.ruby2_keywords(*)
9
+ end unless respond_to?(:ruby2_keywords, true)
10
+
8
11
  # Missing methods are called on the given context if available.
9
12
  #
10
13
  # We include private methods as methods such as current_user
11
14
  # are usually declared as private or protected.
12
- def method_missing(name, *args, &block)
13
- if @context && @context.respond_to?(name, true)
15
+ ruby2_keywords def method_missing(name, *args, &block)
16
+ if context_responds_to?(name)
14
17
  @context.send(name, *args, &block)
15
18
  else
16
19
  super
@@ -18,7 +21,12 @@ module Trestle
18
21
  end
19
22
 
20
23
  def respond_to_missing?(name, include_private=false)
21
- (@context && @context.respond_to?(name, true)) || super
24
+ context_responds_to?(name) || super
25
+ end
26
+
27
+ private
28
+ def context_responds_to?(name)
29
+ @context && @context.respond_to?(name, true)
22
30
  end
23
31
  end
24
32
  end
@@ -16,7 +16,7 @@ module Trestle
16
16
  concat label if name && options[:label] != false
17
17
  concat template.capture(&block) if block
18
18
  concat help_message if options[:help]
19
- concat error_message if name && errors.any?
19
+ concat error_messages if name && errors.any?
20
20
  end
21
21
  end
22
22
 
@@ -33,9 +33,11 @@ module Trestle
33
33
  content_tag(:p, message, class: classes)
34
34
  end
35
35
 
36
- def error_message
37
- content_tag(:p, class: "invalid-feedback") do
38
- safe_join([icon("fa fa-warning"), errors.first], " ")
36
+ def error_messages
37
+ content_tag(:ul, class: "invalid-feedback") do
38
+ safe_join(errors.map { |error|
39
+ content_tag(:li, safe_join([icon("fa fa-warning"), error], " "))
40
+ }, "\n")
39
41
  end
40
42
  end
41
43
 
@@ -41,6 +41,10 @@ module Trestle
41
41
  end
42
42
  end
43
43
 
44
+ def collapse?
45
+ options[:collapse]
46
+ end
47
+
44
48
  def label
45
49
  I18n.t("admin.navigation.groups.#{name}", default: name.to_s.titlecase)
46
50
  end
@@ -51,7 +51,7 @@ module Trestle
51
51
  # Evaluates the admin's scope block(s) using the adapter context
52
52
  # and returns a hash of Scope objects keyed by the scope name.
53
53
  def scopes
54
- @scopes ||= self.class.scopes.evaluate(adapter)
54
+ @scopes ||= Scopes.new(self.class.scopes, adapter)
55
55
  end
56
56
 
57
57
  class << self
@@ -61,7 +61,7 @@ module Trestle
61
61
  end
62
62
 
63
63
  def scopes
64
- @scopes ||= Scopes.new
64
+ @scopes ||= Scopes::Definition.new
65
65
  end
66
66
 
67
67
  def column_sorts
@@ -83,8 +83,9 @@ module Trestle
83
83
  admin.define_adapter_method(:count, &block)
84
84
  end
85
85
 
86
- def scopes(&block)
87
- admin.scopes.append(&block)
86
+ def scopes(options={}, &block)
87
+ admin.scopes.options.merge!(options)
88
+ admin.scopes.append(&block) if block_given?
88
89
  end
89
90
 
90
91
  def scope(name, scope=nil, options={}, &block)
@@ -42,15 +42,11 @@ module Trestle
42
42
  def apply_scopes(collection, params)
43
43
  unscoped = collection(params)
44
44
 
45
- active_scopes(params).reduce(collection) do |collection, scope|
45
+ scopes.active(params).reduce(collection) do |collection, scope|
46
46
  merge_scopes(collection, scope.apply(unscoped))
47
47
  end
48
48
  end
49
49
 
50
- def active_scopes(params)
51
- scopes.values.select { |s| s.active?(params) }
52
- end
53
-
54
50
  def apply_sorting(collection, params)
55
51
  return collection unless params[:sort]
56
52
 
@@ -1,22 +1,50 @@
1
1
  module Trestle
2
2
  class Scopes
3
3
  require_relative "scopes/block"
4
+ require_relative "scopes/definition"
4
5
  require_relative "scopes/scope"
5
6
 
6
- attr_reader :blocks
7
+ include Enumerable
7
8
 
8
- def initialize
9
- @blocks = []
9
+ delegate :options, to: :@definition
10
+
11
+ def initialize(definition, context)
12
+ @definition = definition
13
+ @scopes = @definition.evaluate(context)
14
+ end
15
+
16
+ def classes
17
+ [
18
+ 'scopes',
19
+ ('grouped' if grouped?),
20
+ layout_class,
21
+ options[:class]
22
+ ].compact
23
+ end
24
+
25
+ def each(&block)
26
+ @scopes.values.each(&block)
27
+ end
28
+
29
+ def grouped?
30
+ options[:group] != false && any?(&:group)
31
+ end
32
+
33
+ def grouped
34
+ if grouped?
35
+ group_by(&:group)
36
+ else
37
+ { nil => @scopes.values.flatten }
38
+ end
10
39
  end
11
40
 
12
- def append(&block)
13
- @blocks << Block.new(&block)
41
+ def active(params)
42
+ select { |s| s.active?(params) }
14
43
  end
15
44
 
16
- # Evaluates each of the scope blocks within the given admin context
17
- # and returns a hash of Scope objects keyed by the scope name.
18
- def evaluate(context)
19
- @blocks.map { |block| block.scopes(context) }.flatten.index_by(&:name)
45
+ private
46
+ def layout_class
47
+ "columns" if %w(column columns).include?(options[:layout].to_s)
20
48
  end
21
49
  end
22
50
  end