trestle 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1da0a5de448522e343cd8c8f25e58f14533b7ea
4
- data.tar.gz: f52dc44dba3f0abc4f1d89c655f0c21c677a9dd1
3
+ metadata.gz: 64b62775f02866abaf0937d6a4e0bec5d86a1a31
4
+ data.tar.gz: 7707fa64f42e4c771721b9c306c143ce2614e18f
5
5
  SHA512:
6
- metadata.gz: 5c9e0a7742fb539291bec72dee7621a12a49fc84f46f60e8a864dc9ce67bfa0003b4e30a52e5e2d9c9b6507303b2f58c901faa8a36cf2a052225a0ffc061392e
7
- data.tar.gz: aa7b9b0cd797638546ad2bbdbc479950bdf4d9576871a1c8b72232eee753dd6fad01e24044bf7a9d5f81426e70a67903542afd8db6b29788ee4c771f3b96b69a
6
+ metadata.gz: a7bed2fddf9f950463693e7ec502aaf08439240a27075e61d2fc575381e165da4b0c407406d4a02990524c37ea9ce730a76886bea2c57ebee03b0ab935d34b51
7
+ data.tar.gz: c0dcd718a1bb3ac020924d09bd99f1658da42c7b53122af829822837a1a0c1631bfc942bb6a274d4301e7de5b4e90d00ad32cb242c30485abf88450ba3186dab
data/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  > A modern, responsive admin framework for Ruby on Rails
13
13
 
14
- <img src="https://trestle.io/images/Trestle-Screenshot-1.png?" width="50%" /><img src="https://trestle.io/images/Trestle-Screenshot-2.png?" width="50%" />
14
+ <img src="https://trestle.io/images/Trestle-Screenshot-1-1x.png?" width="50%" /><img src="https://trestle.io/images/Trestle-Screenshot-2-1x.png?" width="50%" />
15
15
 
16
16
 
17
17
  ## Getting Started
@@ -43,10 +43,10 @@ $headings-font-weight: 400 !default;
43
43
  $btn-default-bg: #dbdbdb !default;
44
44
  $btn-default-color: white !default;
45
45
 
46
- $state-success-bg: lighten(#dff0d8, 2.5%) !default;
47
- $state-info-bg: lighten(#d9edf7, 2.5%) !default;
48
- $state-warning-bg: lighten(#fcf8e3, 2.5%) !default;
49
- $state-danger-bg: lighten(#f2dede, 2.5%) !default;
46
+ $state-success-bg: lighten(#dff0d8, 5%) !default;
47
+ $state-info-bg: lighten(#d9edf7, 5%) !default;
48
+ $state-warning-bg: lighten(#fcf8e3, 5%) !default;
49
+ $state-danger-bg: lighten(#f2dede, 5%) !default;
50
50
 
51
51
  $alert-padding: 20px !default;
52
52
  $alert-border-radius: 2px !default;
@@ -3,6 +3,24 @@ class Trestle::ApplicationController < ActionController::Base
3
3
 
4
4
  layout 'trestle/admin'
5
5
 
6
+ # Global helpers
7
+ self.helpers_path += Rails.application.helpers_paths
8
+ helper Trestle.config.helper_module
9
+ helper *Trestle.config.helpers
10
+
11
+ # Global callbacks
12
+ Trestle.config.before_actions.each do |action|
13
+ before_action(action.options, &action.block)
14
+ end
15
+
16
+ Trestle.config.after_actions.each do |action|
17
+ after_action(action.options, &action.block)
18
+ end
19
+
20
+ Trestle.config.around_actions.each do |action|
21
+ around_action(action.options, &action.block)
22
+ end
23
+
6
24
  protected
7
25
  def breadcrumbs
8
26
  @breadcrumbs ||= Trestle::Breadcrumb::Trail.new(Trestle.config.root_breadcrumbs)
@@ -0,0 +1,24 @@
1
+ module Trestle
2
+ module ContainerHelper
3
+ def container(&block)
4
+ context = Context.new(self)
5
+ content = capture(context, &block)
6
+
7
+ content_tag(:div, class: "main-content-container") do
8
+ concat content_tag(:div, content, class: "main-content")
9
+ concat content_tag(:aside, context.sidebar, class: "main-content-sidebar") unless context.sidebar.blank?
10
+ end
11
+ end
12
+
13
+ class Context
14
+ def initialize(template)
15
+ @template = template
16
+ end
17
+
18
+ def sidebar(&block)
19
+ @sidebar = @template.capture(&block) if block_given?
20
+ @sidebar
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,7 +1,7 @@
1
1
  module Trestle
2
2
  module GridHelper
3
3
  def row
4
- content_tag(:div, class: 'row') { yield }
4
+ content_tag(:div, class: "row") { yield }
5
5
  end
6
6
 
7
7
  def col(columns)
@@ -1,8 +1,6 @@
1
1
  module Trestle
2
2
  module TableHelper
3
3
  def table(collection, options={}, &block)
4
- options = options.reverse_merge(admin: admin) if defined?(admin)
5
-
6
4
  table = Table::Builder.build(options, &block)
7
5
  render "trestle/table/table", table: table, collection: collection
8
6
  end
@@ -13,14 +13,15 @@ module Trestle
13
13
  end
14
14
 
15
15
  if admin
16
- link_to(content, admin_url_for(instance, admin), options)
16
+ link_to(content, admin_url_for(instance, admin: admin), options)
17
17
  else
18
18
  content
19
19
  end
20
20
  end
21
21
 
22
- def admin_url_for(instance, admin=self.admin)
23
- admin.path(:show, id: admin.to_param(instance)) if admin
22
+ def admin_url_for(instance, options={})
23
+ admin = Trestle.lookup(options[:admin] || self.admin)
24
+ admin.path(options[:action] || :show, id: admin.to_param(instance)) if admin
24
25
  end
25
26
 
26
27
  def admin_for(instance)
@@ -15,6 +15,7 @@
15
15
  <%= content_for(:title) %>
16
16
  </h1>
17
17
 
18
+ <% unless local_assigns.fetch(:hide_breadcrumbs, false) %>
18
19
  <ol class="breadcrumb">
19
20
  <% breadcrumbs.each do |breadcrumb| %>
20
21
  <li class="breadcrumb-item<% if breadcrumb == breadcrumbs.last %> active<% end %>">
@@ -22,4 +23,5 @@
22
23
  </li>
23
24
  <% end %>
24
25
  </ol>
26
+ <% end %>
25
27
  </header>
@@ -1,19 +1,19 @@
1
- <%= render "header" %>
1
+ <%= render "header", hide_breadcrumbs: local_assigns.fetch(:hide_breadcrumbs, false) if local_assigns.fetch(:header, true) %>
2
2
 
3
3
  <div class="main-content-area">
4
4
  <%= render "flash" %>
5
5
  <%= render "utilities" %>
6
6
  <%= render "tabs" %>
7
7
 
8
- <div class="main-content-container">
9
- <div class="main-content">
8
+ <% if local_assigns.fetch(:wrapper, true) %>
9
+ <%= container do |c| %>
10
10
  <%= yield %>
11
- </div>
12
11
 
13
- <% if content_for?(:sidebar) %>
14
- <aside class="main-content-sidebar">
12
+ <% c.sidebar do %>
15
13
  <%= content_for(:sidebar) %>
16
- </aside>
14
+ <% end if content_for?(:sidebar) %>
17
15
  <% end %>
18
- </div>
16
+ <% else %>
17
+ <%= yield %>
18
+ <% end %>
19
19
  </div>
data/config/routes.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  Trestle::Engine.routes.draw do
2
- root to: "trestle/dashboard#index"
3
-
4
2
  Trestle.admins.each do |name, admin|
5
3
  instance_eval(&admin.routes)
6
4
  end
5
+
6
+ root to: "trestle/dashboard#index"
7
7
  end
@@ -0,0 +1,26 @@
1
+ module Trestle
2
+ module Generators
3
+ class AdminGenerator < ::Rails::Generators::NamedBase
4
+ desc "Creates a non-resourceful Trestle admin"
5
+
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def create_admin
9
+ template "admin.rb.erb", File.join("app/admin", class_path, "#{singular_name}_admin.rb")
10
+ end
11
+
12
+ def create_template
13
+ template "index.html.erb", File.join("app/views/admin", class_path, singular_name, "index.html.erb")
14
+ end
15
+
16
+ protected
17
+ def module_name
18
+ class_name.deconstantize
19
+ end
20
+
21
+ def module?
22
+ module_name.present?
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ Trestle.admin(:<%= singular_name %><% if module? %>, scope: <%= module_name %><% end %>) do
2
+ menu do
3
+ item :<%= singular_name %>, icon: "fa fa-star"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ <%% content_for(:title, "<%= singular_name.titleize %>") %>
2
+
3
+ <%%= render layout: "layout", locals: { wrapper: true, sidebar: false, hide_breadcrumbs: false } do %>
4
+ To customize this template, please edit <code><%= File.join("app/views/admin", class_path, singular_name, "index.html.erb") %></code>.
5
+ <%% end %>
@@ -53,6 +53,26 @@ Trestle.configure do |config|
53
53
 
54
54
  # == Extension Options
55
55
  #
56
+ # Specify helper modules to expose to the admin.
57
+ #
58
+ # config.helper :all
59
+
60
+ # Register callbacks to run before, after or around all Trestle actions.
61
+ #
62
+ # config.before_action do |controller|
63
+ # Rails.logger.debug("Before action")
64
+ # end
65
+ #
66
+ # config.after_action do |controller|
67
+ # Rails.logger.debug("After action")
68
+ # end
69
+ #
70
+ # config.around_action do |controller, block|
71
+ # Rails.logger.debug("Around action (before)")
72
+ # block.call
73
+ # Rails.logger.debug("Around ation (after)")
74
+ # end
75
+
56
76
  # Specify a custom hook to be injected into the admin.
57
77
  #
58
78
  # config.hook(:stylesheets) do
@@ -6,7 +6,7 @@ module Trestle
6
6
  source_root File.expand_path("../templates", __FILE__)
7
7
 
8
8
  def create_admin
9
- template "admin.rb.erb", File.join('app/admin', class_path, "#{plural_name}_admin.rb")
9
+ template "admin.rb.erb", File.join("app/admin", class_path, "#{plural_name}_admin.rb")
10
10
  end
11
11
 
12
12
  protected
@@ -37,12 +37,8 @@ module Trestle
37
37
  scope.merge(other)
38
38
  end
39
39
 
40
- def sort(collection, params)
41
- if params[:sort]
42
- collection.reorder(params[:sort] => params[:order] || "asc")
43
- else
44
- collection
45
- end
40
+ def sort(collection, field, order)
41
+ collection.reorder(field => order)
46
42
  end
47
43
 
48
44
  def paginate(collection, params)
@@ -9,6 +9,8 @@ module Trestle
9
9
  class_attribute :controller
10
10
  self.controller = Controller
11
11
 
12
+ delegate :helper, :before_action, :after_action, :around_action, to: :@controller
13
+
12
14
  def initialize(name, options={})
13
15
  # Create admin subclass
14
16
  @admin = Class.new(admin_class)
@@ -37,7 +39,7 @@ module Trestle
37
39
  end
38
40
 
39
41
  def table(options={}, &block)
40
- admin.table = Table::Builder.build(options.reverse_merge(sortable: true, admin: admin), &block)
42
+ admin.table = Table::Builder.build(options.reverse_merge(admin: admin, sortable: true), &block)
41
43
  end
42
44
 
43
45
  def form(&block)
@@ -50,18 +52,13 @@ module Trestle
50
52
  end
51
53
 
52
54
  def controller(&block)
53
- @controller.class_eval(&block)
55
+ @controller.class_eval(&block) if block_given?
56
+ @controller
54
57
  end
55
58
 
56
59
  def routes(&block)
57
60
  @admin.additional_routes = block
58
61
  end
59
-
60
- def helper(*helpers)
61
- controller do
62
- helper *helpers
63
- end
64
- end
65
62
  end
66
63
  end
67
64
  end
@@ -2,43 +2,116 @@ module Trestle
2
2
  class Configuration
3
3
  include Configurable
4
4
 
5
+ ## Customization Options
6
+
7
+ # Page title shown in the main admin header and <title> tag
5
8
  option :site_title, -> { I18n.t("trestle.title", default: "Trestle") }
6
- option :footer, -> { I18n.t("trestle.footer", default: "Powered by Trestle") }
7
9
 
10
+ # Custom image in place of the site title for mobile and expanded/desktop navigation
8
11
  option :site_logo
12
+
13
+ # Custom image for the collapsed/tablet navigation
9
14
  option :site_logo_small
10
15
 
11
- option :path, "/admin"
12
- option :automount, true
16
+ # Text shown in the admin page footer
17
+ option :footer, -> { I18n.t("trestle.footer", default: "Powered by Trestle") }
13
18
 
14
- option :turbolinks, defined?(Turbolinks)
15
19
 
16
- option :display_methods, [:display_name, :full_name, :name, :title, :username, :login, :email, :to_s]
20
+ ## Mounting Options
17
21
 
18
- option :persistent_params, [:sort, :order, :scope]
22
+ # Path at which to mount the Trestle admin
23
+ option :path, "/admin"
19
24
 
20
- option :default_adapter, Adapters::Adapter.compose(Adapters::ActiveRecordAdapter, Adapters::DraperAdapter)
25
+ # Automatically mount the admin within the Rails application's routes
26
+ option :automount, true
21
27
 
28
+
29
+ ## Navigation Options
30
+
31
+ # Initial breadcrumbs to display in the breadcrumb trail
22
32
  option :root_breadcrumbs, -> { [Trestle::Breadcrumb.new(I18n.t("admin.breadcrumbs.home", default: "Home"), Trestle.config.path)] }
23
33
 
34
+ # Default icon class to use when it is not explicitly provided
24
35
  option :default_navigation_icon, "fa fa-arrow-circle-o-right"
25
36
 
26
- option :javascript_i18n_keys, ["admin.confirmation.title", "admin.confirmation.delete", "admin.confirmation.cancel"]
27
-
37
+ # [Internal] List of navigation menu blocks
28
38
  option :menus, []
29
39
 
40
+ # Register a global navigation menu block
30
41
  def menu(&block)
31
42
  menus << Navigation::Block.new(&block)
32
43
  end
33
44
 
45
+
46
+ ## Extension Options
47
+
48
+ # [Internal] List of helper modules to include in all Trestle controllers
49
+ option :helpers, []
50
+
51
+ # [Internal] Container module for block-defined helpers
52
+ option :helper_module, Module.new
53
+
54
+ # Register global helpers available to all Trestle admins
55
+ def helper(*helpers, &block)
56
+ self.helpers += helpers
57
+ self.helper_module.module_eval(&block) if block_given?
58
+ end
59
+
60
+ # Enable or disable Turbolinks within the Trestle admin
61
+ option :turbolinks, defined?(Turbolinks)
62
+
63
+ # List of parameters that should persist across requests when paginating or reordering
64
+ option :persistent_params, [:sort, :order, :scope]
65
+
66
+ # List of methods to try calling on an instance when displayed by the `display` helper
67
+ option :display_methods, [:display_name, :full_name, :name, :title, :username, :login, :email, :to_s]
68
+
69
+ # Default adapter class used by all admin resources
70
+ option :default_adapter, Adapters::Adapter.compose(Adapters::ActiveRecordAdapter, Adapters::DraperAdapter)
71
+
72
+ # Register a custom form field class
73
+ def form_field(name, klass)
74
+ Form::Builder.register(name, klass)
75
+ end
76
+
77
+ # [Internal] List of registered hooks
34
78
  option :hooks, Hash.new { |h, k| h[k] = [] }
35
79
 
80
+ # Register an extension hook
36
81
  def hook(name, &block)
37
82
  hooks[name.to_s] << block
38
83
  end
39
84
 
40
- def form_field(name, klass)
41
- Form::Builder.register(name, klass)
85
+ # List of i18n keys to pass into the Trestle.i18n JavaScript object
86
+ option :javascript_i18n_keys, ["admin.confirmation.title", "admin.confirmation.delete", "admin.confirmation.cancel"]
87
+
88
+
89
+ ## Callbacks
90
+
91
+ Action = Struct.new(:options, :block)
92
+
93
+ # [Internal] List of global before actions
94
+ option :before_actions, []
95
+
96
+ # Register a global before action
97
+ def before_action(options={}, &block)
98
+ before_actions << Action.new(options, block)
99
+ end
100
+
101
+ # [Internal] List of global after actions
102
+ option :after_actions, []
103
+
104
+ # Register a global after action
105
+ def after_action(options={}, &block)
106
+ after_actions << Action.new(options, block)
107
+ end
108
+
109
+ # [Internal] List of global around actions
110
+ option :around_actions, []
111
+
112
+ # Register a global around action
113
+ def around_action(options={}, &block)
114
+ around_actions << Action.new(options, block)
42
115
  end
43
116
  end
44
117
  end
@@ -62,6 +62,10 @@ module Trestle
62
62
  admin.sort = block
63
63
  end
64
64
 
65
+ def sort_column(column, &block)
66
+ admin.column_sorts[column.to_sym] = block
67
+ end
68
+
65
69
  def paginate(&block)
66
70
  admin.paginate = block
67
71
  end
@@ -49,7 +49,7 @@ module Trestle
49
49
  def prepare_collection(params)
50
50
  collection = initialize_collection(params)
51
51
  collection = apply_scopes(collection, params)
52
- collection = sort(collection, params)
52
+ collection = apply_sorting(collection, params)
53
53
  collection = paginate(collection, params)
54
54
  collection = decorate_collection(collection)
55
55
  collection
@@ -87,6 +87,25 @@ module Trestle
87
87
  result
88
88
  end
89
89
 
90
+ def column_sorts
91
+ @column_sorts ||= {}
92
+ end
93
+
94
+ def apply_sorting(collection, params)
95
+ return collection unless params[:sort]
96
+
97
+ field = params[:sort].to_sym
98
+
99
+ order = params[:order].downcase
100
+ order = "asc" unless %w(asc desc).include?(order)
101
+
102
+ if column_sorts.has_key?(field)
103
+ instance_exec(collection, order, &column_sorts[field])
104
+ else
105
+ sort(collection, field, order)
106
+ end
107
+ end
108
+
90
109
  def table
91
110
  super || Table::Automatic.new(self)
92
111
  end
@@ -129,7 +148,7 @@ module Trestle
129
148
  def infer_model_class
130
149
  parent.const_get(admin_name.classify)
131
150
  rescue NameError
132
- nil
151
+ raise NameError, "Unable to find model #{admin_name.classify}. Specify a different model using Trestle.resource(:#{admin_name}, model: MyModel)"
133
152
  end
134
153
 
135
154
  def default_model_name
@@ -19,22 +19,25 @@ module Trestle
19
19
  end
20
20
 
21
21
  class ActionsBuilder
22
- attr_reader :template, :instance
22
+ attr_reader :instance
23
23
 
24
- def initialize(template, instance)
25
- @template, @instance = template, instance
24
+ delegate :table, to: :@column
25
+
26
+ def initialize(column, template, instance)
27
+ @column, @template, @instance = column, template, instance
28
+ end
29
+
30
+ def delete
31
+ button(@template.icon("fa fa-trash"), @template.admin_url_for(instance, admin: table.options[:admin], action: :destroy), method: :delete, class: "btn-danger", data: { toggle: "confirm-delete", placement: "left" })
26
32
  end
27
33
 
28
34
  def button(content, url, options={})
29
35
  options[:class] = Array(options[:class])
30
36
  options[:class] << "btn" unless options[:class].include?("btn")
31
37
 
32
- template.concat template.link_to(content, url, options)
33
- end
34
-
35
- def delete
36
- button(template.icon("fa fa-trash"), template.admin.path(:destroy, id: template.admin.to_param(instance)), method: :delete, class: "btn-danger", data: { toggle: "confirm-delete", placement: "left" })
38
+ @template.concat @template.link_to(content, url, options)
37
39
  end
40
+ alias_method :link, :button
38
41
  end
39
42
 
40
43
  class Renderer < Column::Renderer
@@ -54,7 +57,7 @@ module Trestle
54
57
  end
55
58
 
56
59
  def content(instance)
57
- builder = ActionsBuilder.new(@template, instance)
60
+ builder = ActionsBuilder.new(@column, @template, instance)
58
61
 
59
62
  @template.with_output_buffer do
60
63
  @template.instance_exec(builder, &@column.block)
@@ -8,7 +8,7 @@ module Trestle
8
8
  end
9
9
 
10
10
  def row(options={}, &block)
11
- table.row = Row.new(options, &block)
11
+ table.row = Row.new(table, options, &block)
12
12
  end
13
13
 
14
14
  def selectable_column
@@ -1,10 +1,10 @@
1
1
  module Trestle
2
2
  class Table
3
3
  class Row
4
- attr_reader :options, :block
4
+ attr_reader :table, :options, :block
5
5
 
6
- def initialize(options={}, &block)
7
- @options = options
6
+ def initialize(table, options={}, &block)
7
+ @table, @options = table, options
8
8
  @block = block if block_given?
9
9
  end
10
10
 
@@ -13,16 +13,24 @@ module Trestle
13
13
  end
14
14
 
15
15
  class Renderer
16
+ delegate :table, to: :@row
17
+
16
18
  def initialize(row, template)
17
19
  @row, @template = row, template
18
20
  end
19
21
 
20
22
  def options(instance)
21
- options = Trestle::Options.new(data: { url: @template.admin_url_for(instance) })
23
+ options = Trestle::Options.new
24
+ options.merge!(data: { url: admin_url_for(instance) }) if table.options[:admin]
22
25
  options.merge!(@row.options)
23
26
  options.merge!(@template.instance_exec(instance, &@row.block)) if @row.block
24
27
  options
25
28
  end
29
+
30
+ protected
31
+ def admin_url_for(instance)
32
+ @template.admin_url_for(instance, admin: table.options[:admin])
33
+ end
26
34
  end
27
35
  end
28
36
  end
data/lib/trestle/table.rb CHANGED
@@ -26,7 +26,7 @@ module Trestle
26
26
  end
27
27
 
28
28
  def row
29
- @row || Row.new
29
+ @row || Row.new(self)
30
30
  end
31
31
 
32
32
  class Renderer
@@ -1,3 +1,3 @@
1
1
  module Trestle
2
- VERSION = "0.8.2"
2
+ VERSION = "0.8.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trestle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Pohlenz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-31 00:00:00.000000000 Z
11
+ date: 2017-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -230,6 +230,7 @@ files:
230
230
  - app/controllers/trestle/application_controller.rb
231
231
  - app/controllers/trestle/dashboard_controller.rb
232
232
  - app/helpers/trestle/avatar_helper.rb
233
+ - app/helpers/trestle/container_helper.rb
233
234
  - app/helpers/trestle/display_helper.rb
234
235
  - app/helpers/trestle/form_helper.rb
235
236
  - app/helpers/trestle/grid_helper.rb
@@ -277,6 +278,9 @@ files:
277
278
  - config/locales/en.rb
278
279
  - config/locales/en.yml
279
280
  - config/routes.rb
281
+ - lib/generators/trestle/admin/admin_generator.rb
282
+ - lib/generators/trestle/admin/templates/admin.rb.erb
283
+ - lib/generators/trestle/admin/templates/index.html.erb
280
284
  - lib/generators/trestle/install/install_generator.rb
281
285
  - lib/generators/trestle/install/templates/_custom.scss
282
286
  - lib/generators/trestle/install/templates/_variables.scss