typus 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,6 +1,27 @@
1
1
  = 3.2.0 (unreleased)
2
2
 
3
- = 3.1.0 (unreleased)
3
+ = 3.1.1 (unreleased)
4
+
5
+ * [CHANGED] Removed user guide. Docs can now be found at http://docs.typuscmf.com/
6
+
7
+ * [NEW] New configuration setting which allows serving Typus from a subdomain. (42b5d8ae)
8
+
9
+ * [FIXED] HABTM associations were not working as expected when using namespaced
10
+ models.
11
+
12
+ * [CHANGED] Configuration can be read from subfolders so you can organize better
13
+ your models. I'm starting to use a file per model and I'd recommend you start
14
+ using it ... (8a3fc09f)
15
+
16
+ * [FIXED] Helper Method `display_virtual` was not defined. (2b7e1948)
17
+
18
+ * [FIXED] Do not show Trash link when user can't edit items.
19
+
20
+ * [CHANGED] Updated Rubies list for Travis-CI.
21
+
22
+ * [CHANGED] Default development/test database is now **Postgresql**.
23
+
24
+ = 3.1.0
4
25
 
5
26
  * [NEW] Filter with scopes.
6
27
 
data/Gemfile CHANGED
@@ -67,3 +67,5 @@ group :development do
67
67
  # gem "rb-fsevent"
68
68
  # gem "growl_notify"
69
69
  end
70
+
71
+ gem "SystemTimer", :platform => :ruby_18
data/README.md CHANGED
@@ -48,9 +48,14 @@ To test clone the git repo and run the following commands:
48
48
  $ bundle install --path vendor/bundle
49
49
  $ bundle exec rake
50
50
 
51
+ **Note:** In `OSX Lion` it's possible you need to create a `postgres`
52
+ user to be able to run tests.
53
+
54
+ CREATE USER postgres SUPERUSER;
55
+
51
56
  ## Links
52
57
 
53
- - [Documentation](https://github.com/typus/typus/wiki)
58
+ - [Documentation](https://docs.typuscmf.com/)
54
59
  - [Issues](https://github.com/typus/typus/issues)
55
60
  - [Source Code][typus] and [RubyGems][typus_gem]
56
61
  - [Mailing List](http://groups.google.com/group/typus)
@@ -63,7 +68,6 @@ Typus is released under the MIT license.
63
68
 
64
69
  [typus]: http://github.com/typus/typus
65
70
  [typus_demo]: http://demo.typuscmf.com/
66
- [typus_demo_code]: https://github.com/typus/demo
67
71
  [typus_locales]: https://github.com/typus/typus/tree/master/config/locales
68
72
  [typus_gem]: http://rubygems.org/gems/typus
69
73
  [paperclip]: http://rubygems.org/gems/paperclip
data/Rakefile CHANGED
@@ -18,12 +18,7 @@ require 'rake/testtask'
18
18
  Rake::TestTask.new(:test) do |t|
19
19
  t.libs << 'lib'
20
20
  t.libs << 'test'
21
- # t.pattern = 'test/**/*_test.rb'
22
- t.test_files = FileList['test/app/controllers/**/*_test.rb',
23
- 'test/app/models/**/*_test.rb',
24
- 'test/app/mailers/**/*_test.rb',
25
- 'test/config/*_test.rb',
26
- 'test/lib/**/*_test.rb']
21
+ t.test_files = FileList['test/**/*_test.rb']
27
22
  t.verbose = false
28
23
  end
29
24
 
@@ -21,7 +21,6 @@ $(document).ready(function() {
21
21
  'centerOnScroll': true,
22
22
  'scrolling': false,
23
23
  onClosed: function() {
24
- // console.log(arguments);
25
24
  var attribute = Typus.resource_attribute;
26
25
  var text = Typus.resource_to_label;
27
26
  var value = Typus.resource_id;
@@ -22,3 +22,12 @@
22
22
  .search-choice span {
23
23
  color: black!important;
24
24
  }
25
+
26
+ /* frikin' forms hacks */
27
+
28
+ .chzn-search input {
29
+ -webkit-box-sizing: content-box;
30
+ -moz-box-sizing: content-box;
31
+ box-sizing: content-box;
32
+ height:1em;
33
+ }
@@ -9,8 +9,6 @@ class Admin::BaseController < ActionController::Base
9
9
  helper_method :admin_user
10
10
  helper_method :current_role
11
11
 
12
- def user_guide; end
13
-
14
12
  protected
15
13
 
16
14
  def reload_config_and_roles
@@ -17,7 +17,7 @@ class Admin::ResourcesController < Admin::BaseController
17
17
  get_objects
18
18
 
19
19
  custom_actions_for(:index).each do |action|
20
- prepend_resources_action(action.titleize, {:action => action, :id => nil}, {})
20
+ prepend_resources_action(action.titleize, {:action => action, :id => nil})
21
21
  end
22
22
 
23
23
  respond_to do |format|
@@ -64,7 +64,7 @@ class Admin::ResourcesController < Admin::BaseController
64
64
 
65
65
  def edit
66
66
  custom_actions_for(:edit).each do |action|
67
- prepend_resources_action(action.titleize, {:action => action, :id => @item}, {})
67
+ prepend_resources_action(action.titleize, {:action => action, :id => @item})
68
68
  end
69
69
  end
70
70
 
@@ -72,7 +72,7 @@ class Admin::ResourcesController < Admin::BaseController
72
72
  check_resource_ownership if @resource.typus_options_for(:only_user_items)
73
73
 
74
74
  if admin_user.can?('edit', @resource)
75
- prepend_resources_action("Edit", {:action => 'edit', :id => @item}, {})
75
+ prepend_resources_action("Edit", {:action => 'edit', :id => @item})
76
76
  end
77
77
 
78
78
  respond_to do |format|
@@ -215,7 +215,7 @@ class Admin::ResourcesController < Admin::BaseController
215
215
  def set_default_action
216
216
  default_action = @resource.typus_options_for(:default_action_on_item)
217
217
  action = admin_user.can?('edit', @resource.model_name) ? default_action : "show"
218
- add_resource_action(action.titleize, {:action => action}, {})
218
+ prepend_resource_action(action.titleize, {:action => action})
219
219
  end
220
220
 
221
221
  def custom_actions_for(action)
@@ -7,12 +7,12 @@ module Admin::Resources::DataTypes::HasAndBelongsToManyHelper
7
7
  alias_method :table_has_many_field, :table_has_and_belongs_to_many_field
8
8
 
9
9
  def typus_has_and_belongs_to_many_field(attribute, form)
10
- klass = attribute.singularize.capitalize.constantize
11
- resource_ids = "#{attribute.singularize}_ids"
10
+ klass = @resource.reflect_on_association(attribute.to_sym).class_name.constantize
12
11
 
12
+ resource_ids = "#{attribute.singularize}_ids"
13
13
  html_options = { :disabled => attribute_disabled?(resource_ids.to_sym) }
14
-
15
- options = { :attribute => "#{@resource.name.downcase}_#{attribute}" }
14
+ model = @resource.name.downcase.gsub("::", "_")
15
+ options = { :attribute => "#{model}_#{attribute}" }
16
16
 
17
17
  label_text = @resource.human_attribute_name(attribute)
18
18
  if (text = build_label_text_for_has_and_belongs_to_many(klass, html_options, options))
@@ -20,10 +20,10 @@ module Admin::Resources::DataTypes::HasAndBelongsToManyHelper
20
20
  end
21
21
 
22
22
  locals = { :attribute => attribute,
23
- :attribute_id => "#{@resource.table_name}_#{attribute}",
23
+ :attribute_id => "#{model}_#{attribute}",
24
24
  :related_klass => klass,
25
25
  :related_items => klass.all,
26
- :related_ids => "#{@resource.name.downcase}[#{resource_ids}][]",
26
+ :related_ids => "#{model}[#{resource_ids}][]",
27
27
  :values => @item.send(attribute),
28
28
  :form => form,
29
29
  :label_text => label_text.html_safe,
@@ -9,6 +9,7 @@ module Admin::Resources::DataTypes::StringHelper
9
9
  alias_method :display_integer, :display_string
10
10
  alias_method :display_position, :display_string
11
11
  alias_method :display_text, :display_string
12
+ alias_method :display_virtual, :display_string
12
13
 
13
14
  def string_filter(filter)
14
15
  values = set_context.send(filter.to_s.pluralize).to_a
@@ -50,7 +50,7 @@ module Admin::Resources::TableHelper
50
50
  resource_actions.map do |body, url, options, proc|
51
51
  next if proc && proc.respond_to?(:call) && proc.call(item) == false
52
52
  { :message => Typus::I18n.t(body),
53
- :url => params.dup.cleanup.merge(url).merge(:controller => "/admin/#{model.to_resource}", :id => item.id),
53
+ :url => { :controller => "/admin/#{model.to_resource}", :id => item.id }.merge(params.dup.cleanup.merge(url)),
54
54
  :options => options }
55
55
  end
56
56
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  <%
4
4
  mailing_list = link_to('mailing list', 'http://groups.google.com/group/typus')
5
- user_guide = link_to('user guide', admin_user_guide_path)
5
+ user_guide = link_to('user guide', 'http://docs.typuscmf.com/')
6
6
  %>
7
7
 
8
8
  <p>If you need help don't hesitate in joining the <%= mailing_list %> or use
9
- the provided <%= user_guide %>.</p>
9
+ the <%= user_guide %>.</p>
10
10
 
11
11
  <p>Replace this sidebar dropping a file named <code>_sidebar.html.erb</code>
12
12
  on the <code>app/views/admin/dashboard</code> folder.</p>
@@ -1,11 +1,11 @@
1
- <li id="<%= attribute_id %>">
1
+ <li id="<%= attribute_id %>_field">
2
2
  <%= form.label attribute, label_text %>
3
3
  <% if related_items.any? %>
4
4
  <%= hidden_field_tag related_ids %>
5
5
  <%= select_tag related_ids,
6
6
  options_from_collection_for_select(related_items, "id", "to_label", values.map(&:id)),
7
7
  html_options.merge(:multiple => true,
8
- :id => "#{@resource.name.downcase}_#{attribute}",
8
+ :id => attribute_id,
9
9
  :class => "chzn-select",
10
10
  :style => "width: 550px;",
11
11
  "data-placeholder" => Typus::I18n.t("Select Some Options")) %>
@@ -1,14 +1,13 @@
1
1
  Rails.application.routes.draw do
2
2
 
3
- scope "admin", :module => :admin, :as => "admin" do
3
+ routes_block = lambda do
4
4
 
5
- match "/" => redirect("/admin/dashboard")
5
+ dashboard = Typus.subdomain ? "/dashboard" : "/admin/dashboard"
6
6
 
7
+ match "/" => redirect(dashboard)
7
8
  match "dashboard" => "dashboard#index", :as => "dashboard_index"
8
9
  match "dashboard/:application" => "dashboard#show", :as => "dashboard"
9
10
 
10
- match "user_guide" => "base#user_guide"
11
-
12
11
  if Typus.authentication == :session
13
12
  resource :session, :only => [:new, :create], :controller => :session do
14
13
  get :destroy, :as => "destroy"
@@ -29,7 +28,13 @@ Rails.application.routes.draw do
29
28
  Typus.resources.map { |i| i.underscore }.each do |resource|
30
29
  match "#{resource}(/:action(/:id))(.:format)", :controller => resource
31
30
  end
32
-
33
31
  end
34
32
 
33
+ if Typus.subdomain
34
+ constraints :subdomain => Typus.subdomain do
35
+ namespace :admin, :path => "", &routes_block
36
+ end
37
+ else
38
+ scope "admin", {:module => :admin, :as => "admin"}, &routes_block
39
+ end
35
40
  end
@@ -29,6 +29,9 @@ Typus.setup do |config|
29
29
  # config.username = "admin"
30
30
  # config.password = "columbia"
31
31
 
32
+ # Define subdomain to use instead of additional path
33
+ # config.subdomain = "admin"
34
+
32
35
  # Pagination options: These options are passed to `kaminari`.
33
36
  # config.pagination = { :previous_label => "&larr; " + Typus::I18n.t("Previous"),
34
37
  # :next_label => Typus::I18n.t("Next") + " &rarr;" }
@@ -65,6 +65,9 @@ module Typus
65
65
  mattr_accessor :username
66
66
  @@username = "admin"
67
67
 
68
+ mattr_accessor :subdomain
69
+ @@subdomain = nil
70
+
68
71
  ##
69
72
  # Pagination options passed to Kaminari helper.
70
73
  #
@@ -220,14 +223,14 @@ module Typus
220
223
  end
221
224
 
222
225
  def model_configuration_files
223
- app = Typus.root.join("*.yml")
224
- plugins = Rails.root.join("vendor", "plugins", "*", "config", "typus", "*.yml")
226
+ app = Typus.root.join("**", "*.yml")
227
+ plugins = Rails.root.join("vendor", "plugins", "*", "config", "typus", "**", "*.yml")
225
228
  Dir[app, plugins].reject { |f| f.match(/_roles.yml/) }.sort
226
229
  end
227
230
 
228
231
  def role_configuration_files
229
- app = Typus.root.join("*_roles.yml")
230
- plugins = Rails.root.join("vendor", "plugins", "*", "config", "typus", "*_roles.yml")
232
+ app = Typus.root.join("**", "*_roles.yml")
233
+ plugins = Rails.root.join("vendor", "plugins", "*", "config", "typus", "**", "*_roles.yml")
231
234
  Dir[app, plugins].sort
232
235
  end
233
236
 
@@ -1,3 +1,5 @@
1
+ require 'erb'
2
+
1
3
  module Typus
2
4
  module Configuration
3
5
 
@@ -6,7 +8,7 @@ module Typus
6
8
  @@config = {}
7
9
 
8
10
  Typus.model_configuration_files.each do |file|
9
- if data = YAML::load_file(file)
11
+ if data = YAML::load(ERB.new(File.read(file)).result)
10
12
  @@config.merge!(data)
11
13
  end
12
14
  end
@@ -20,7 +22,7 @@ module Typus
20
22
  @@roles = {}
21
23
 
22
24
  Typus.role_configuration_files.each do |file|
23
- if data = YAML::load_file(file)
25
+ if data = YAML::load(ERB.new(File.read(file)).result)
24
26
  data.compact.each do |key, value|
25
27
  @@roles[key] ? @@roles[key].merge!(value) : (@@roles[key] = value)
26
28
  end
@@ -32,4 +34,4 @@ module Typus
32
34
  @@roles = {}
33
35
 
34
36
  end
35
- end
37
+ end
@@ -10,12 +10,12 @@ module Typus
10
10
  end
11
11
 
12
12
  def set_resources_action_for_headless_on_index
13
- add_resources_action("Add New", {:action => "new"}, {})
13
+ add_resources_action("Add New", {:action => "new"})
14
14
  end
15
15
  private :set_resources_action_for_headless_on_index
16
16
 
17
17
  def set_resources_action_for_headless
18
- add_resources_action("All Entries", {:action => 'index', :id => nil}, {})
18
+ add_resources_action("All Entries", {:action => 'index', :id => nil})
19
19
  end
20
20
  private :set_resources_action_for_headless
21
21
 
@@ -13,7 +13,9 @@ module Typus
13
13
  end
14
14
 
15
15
  def set_predefined_filter_for_trash
16
- add_predefined_filter("Trash", "trash", "deleted")
16
+ if admin_user.can?('edit', @resource.model_name)
17
+ add_predefined_filter("Trash", "trash", "deleted")
18
+ end
17
19
  end
18
20
  private :set_predefined_filter_for_trash
19
21
 
@@ -1,3 +1,3 @@
1
1
  module Typus
2
- VERSION = "3.1.0"
2
+ VERSION = "3.1.1"
3
3
  end
@@ -7,7 +7,7 @@ require "typus/version"
7
7
 
8
8
  files = `git ls-files`.split("\n")
9
9
  test_files = `git ls-files -- test/*`.split("\n")
10
- ignores = `git ls-files -- script/*`.split("\n")
10
+ ignores = `git ls-files -- doc/* Guardfile .travis.yml .gitignor .travis.yml .gitignore`.split("\n")
11
11
 
12
12
  # Describe your gem and declare its dependencies:
13
13
  Gem::Specification.new do |s|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typus
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-02 00:00:00.000000000Z
12
+ date: 2011-09-08 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jquery-rails
16
- requirement: &70152604331140 !ruby/object:Gem::Requirement
16
+ requirement: &70333450722940 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70152604331140
24
+ version_requirements: *70333450722940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: kaminari
27
- requirement: &70152604330700 !ruby/object:Gem::Requirement
27
+ requirement: &70333450722120 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70152604330700
35
+ version_requirements: *70333450722120
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rails
38
- requirement: &70152604330180 !ruby/object:Gem::Requirement
38
+ requirement: &70333450720960 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 3.1.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70152604330180
46
+ version_requirements: *70333450720960
47
47
  description: Ruby on Rails Admin Panel (Engine) to allow trusted users edit structured
48
48
  content.
49
49
  email:
@@ -52,11 +52,8 @@ executables: []
52
52
  extensions: []
53
53
  extra_rdoc_files: []
54
54
  files:
55
- - .gitignore
56
- - .travis.yml
57
55
  - CHANGELOG
58
56
  - Gemfile
59
- - Guardfile
60
57
  - MIT-LICENSE
61
58
  - README.md
62
59
  - Rakefile
@@ -111,7 +108,6 @@ files:
111
108
  - app/mailers/admin/mailer.rb
112
109
  - app/views/admin/account/forgot_password.html.erb
113
110
  - app/views/admin/account/new.html.erb
114
- - app/views/admin/base/user_guide.html.erb
115
111
  - app/views/admin/dashboard/_sidebar.html.erb
116
112
  - app/views/admin/dashboard/index.html.erb
117
113
  - app/views/admin/dashboard/styles.html.erb
@@ -320,7 +316,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
320
316
  version: '0'
321
317
  segments:
322
318
  - 0
323
- hash: 4352251271305818957
319
+ hash: 431185922972537498
324
320
  required_rubygems_version: !ruby/object:Gem::Requirement
325
321
  none: false
326
322
  requirements:
@@ -329,10 +325,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
329
325
  version: '0'
330
326
  segments:
331
327
  - 0
332
- hash: 4352251271305818957
328
+ hash: 431185922972537498
333
329
  requirements: []
334
330
  rubyforge_project: typus
335
- rubygems_version: 1.8.9
331
+ rubygems_version: 1.8.7
336
332
  signing_key:
337
333
  specification_version: 3
338
334
  summary: Effortless backend interface for Ruby on Rails applications. (Admin scaffold
data/.gitignore DELETED
@@ -1,15 +0,0 @@
1
- .bundle/
2
- log/*.log
3
- pkg/
4
-
5
- test/dummy/config/email.yml
6
- test/dummy/config/mongoid.yml
7
- test/dummy/db/*.sqlite3
8
- test/dummy/log/*.log
9
- test/dummy/public/system/
10
- test/dummy/tmp/
11
-
12
- vendor/bundle
13
-
14
- # This is a RubyGem so there's no need to keep the `Gemfile.lock`.
15
- Gemfile.lock
@@ -1,12 +0,0 @@
1
- rvm:
2
- - 1.8.7
3
- - ree
4
- - 1.9.2
5
-
6
- notifications:
7
- recipients:
8
- - support@typuscms.com
9
-
10
- branches:
11
- only:
12
- - master
data/Guardfile DELETED
@@ -1,11 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- guard 'livereload' do
5
- watch(%r{app/.+\.(erb|haml)})
6
- watch(%r{app/helpers/.+\.rb})
7
- watch(%r{(public/|app/assets).+\.(css|js|html)})
8
- watch(%r{(app/assets/.+\.css)\.s[ac]ss}) { |m| m[1] }
9
- watch(%r{(app/assets/.+\.js)\.coffee}) { |m| m[1] }
10
- watch(%r{config/locales/.+\.yml})
11
- end
@@ -1,87 +0,0 @@
1
- <%
2
- rails = "http://rubyonrails.org/"
3
- typus = "http://core.typuscmf.com/"
4
- %>
5
-
6
- <% content_for :main_grid do %>
7
- <a name="introduction"></a>
8
-
9
- <h2>Introduction</h2>
10
-
11
- <p>This website is powered by <%= link_to "Ruby on Rails", rails %> and
12
- <%= link_to "Typus", typus %>.</p>
13
-
14
- <p>With <%= link_to "Typus", typus %>, also known as the application backend
15
- or admin interface, you'll be able to update your application contents and
16
- perform the most common operations for the site maintenance.</p>
17
-
18
- <p>You can get more information at <%= link_to typus, typus %>.</p>
19
-
20
- <a name="basics"></a>
21
-
22
- <h2>Basic Actions</h2>
23
-
24
- <h3>Create Entries</h3>
25
-
26
- <p>To create a new entry:</p>
27
-
28
- <ul>
29
- <li>Click on entries tab.</li>
30
- <li>Click "Add New" sub tab.</li>
31
- <li>Start filling in the blanks.</li>
32
- <li>When you are ready, click "Save Entry".</li>
33
- </ul>
34
-
35
- <h3>Editing &amp; Updating Entries</h3>
36
-
37
- <p>To edit entries:</p>
38
-
39
- <ul>
40
- <li>Click on entries tab.</li>
41
- <li>You'll see a list of entries, if you have already create some.</li>
42
- <li>Click on "Edit".</li>
43
- <li>Edit the entry.</li>
44
- <li>When you are ready, click "Update Entry".</li>
45
- </ul>
46
-
47
- <h3>Removing Entries</h3>
48
-
49
- <p>To remove entries:</p>
50
-
51
- <ul>
52
- <li>Click on entries tab.</li>
53
- <li>You'll see a list of entries, if you have already create some.</li>
54
- <li>Click on "Trash".</li>
55
- <li>Click "Ok" on the dialog to confirm you want to remove the entry.</li>
56
- </ul>
57
-
58
- <p>Removing entries will be only available if you have permissions to do so.</p>
59
-
60
- <a name="registered-users"></a>
61
-
62
- <h2>Registered Users</h2>
63
-
64
- <p>Registered users can do a variety of different things on a <strong>Typus</strong>
65
- driven site. The various elements available to the user are determined by their
66
- user level.</p>
67
-
68
- <p>When <code>:session</code> authentication is enabled <strong>Typus</strong>
69
- will enable a a default role which will allow registered users perform all kind
70
- of operations on entries: create, read, update and destroy.</p>
71
-
72
- <p>It's usually recommended having an extra role which some restrictions.</p>
73
- <% end %>
74
-
75
- <div class="grid_2">
76
- <h2>User Guide</h2>
77
-
78
- <ul>
79
- <li><%= link_to "Introduction", "#introduction" %></li>
80
- <li><%= link_to "Basics", "#basics" %></li>
81
- <li><%= link_to "Registered Users", "#registered-users" %></li>
82
- </ul>
83
- </div>
84
-
85
- <div class="grid_8">
86
- <%= yield :main_grid %>
87
- </div>