trestle 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -6
  3. data/Gemfile +0 -1
  4. data/README.md +3 -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/{lib → app/controllers/concerns}/trestle/controller/breadcrumbs.rb +0 -0
  23. data/{lib → app/controllers/concerns}/trestle/controller/callbacks.rb +0 -0
  24. data/{lib → app/controllers/concerns}/trestle/controller/dialog.rb +0 -0
  25. data/{lib → app/controllers/concerns}/trestle/controller/helpers.rb +0 -0
  26. data/{lib → app/controllers/concerns}/trestle/controller/layout.rb +0 -0
  27. data/{lib → app/controllers/concerns}/trestle/controller/location.rb +0 -0
  28. data/{lib → app/controllers/concerns}/trestle/controller/title.rb +0 -0
  29. data/{lib → app/controllers/concerns}/trestle/controller/toolbars.rb +0 -0
  30. data/{lib → app/controllers/concerns}/trestle/resource/controller/actions.rb +1 -1
  31. data/{lib → app/controllers/concerns}/trestle/resource/controller/data_methods.rb +1 -1
  32. data/{lib → app/controllers/concerns}/trestle/resource/controller/redirection.rb +1 -1
  33. data/{lib → app/controllers/concerns}/trestle/resource/controller/toolbar.rb +1 -1
  34. data/app/controllers/trestle/admin_controller.rb +33 -0
  35. data/{lib → app/controllers}/trestle/application_controller.rb +0 -0
  36. data/app/controllers/trestle/dashboard_controller.rb +13 -11
  37. data/app/controllers/trestle/resource_controller.rb +8 -0
  38. data/app/helpers/trestle/grid_helper.rb +7 -3
  39. data/app/helpers/trestle/hook_helper.rb +8 -6
  40. data/app/views/trestle/resource/edit.html.erb +2 -2
  41. data/app/views/trestle/resource/index.html.erb +1 -1
  42. data/app/views/trestle/resource/new.html.erb +1 -1
  43. data/app/views/trestle/resource/show.html.erb +2 -2
  44. data/frontend/css/components/_table.scss +16 -0
  45. data/frontend/css/layout/_sidebar.scss +6 -1
  46. data/frontend/js/components/confirmation.js +4 -2
  47. data/frontend/js/components/dialog.js +3 -0
  48. data/frontend/js/components/form.js +9 -0
  49. data/frontend/js/components/sidebar.js +5 -5
  50. data/frontend/js/components/table.js +33 -2
  51. data/frontend/theme/trestle/theme/bootstrap/_buttons.scss +3 -0
  52. data/lib/trestle.rb +22 -38
  53. data/lib/trestle/adapters.rb +1 -1
  54. data/lib/trestle/admin.rb +1 -4
  55. data/lib/trestle/admin/builder.rb +2 -2
  56. data/lib/trestle/configurable.rb +10 -0
  57. data/lib/trestle/configuration.rb +2 -2
  58. data/lib/trestle/engine.rb +1 -5
  59. data/lib/trestle/form.rb +5 -7
  60. data/lib/trestle/form/builder.rb +2 -3
  61. data/lib/trestle/form/field.rb +13 -3
  62. data/lib/trestle/form/fields.rb +6 -38
  63. data/lib/trestle/form/fields/tag_select.rb +2 -0
  64. data/lib/trestle/form/renderer.rb +4 -2
  65. data/lib/trestle/hook.rb +2 -2
  66. data/lib/trestle/navigation.rb +3 -6
  67. data/lib/trestle/reloader.rb +0 -8
  68. data/lib/trestle/resource.rb +4 -7
  69. data/lib/trestle/resource/builder.rb +1 -1
  70. data/lib/trestle/resource/toolbar.rb +16 -3
  71. data/lib/trestle/scopes.rb +2 -4
  72. data/lib/trestle/tab.rb +2 -0
  73. data/lib/trestle/table.rb +12 -13
  74. data/lib/trestle/table/actions_column.rb +6 -6
  75. data/lib/trestle/table/automatic.rb +3 -3
  76. data/lib/trestle/table/builder.rb +4 -4
  77. data/lib/trestle/table/column.rb +29 -24
  78. data/lib/trestle/table/row.rb +13 -13
  79. data/lib/trestle/table/select_column.rb +19 -7
  80. data/lib/trestle/toolbar.rb +4 -11
  81. data/lib/trestle/version.rb +1 -1
  82. data/trestle.gemspec +5 -6
  83. data/yarn.lock +1226 -1144
  84. metadata +24 -24
  85. data/lib/trestle/admin/controller.rb +0 -35
  86. data/lib/trestle/resource/controller.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ec0dcceb14b2184fb07724245272ba57926c91058ed554cb19653149aa5a61d
4
- data.tar.gz: ec4b694ff3649bb301dffad74fba26fce2dc222c52ffeb48ff205fcda95c1e98
3
+ metadata.gz: 1a0e145542ea21344ab56ce456f98a2eab365820c9cb65da1a2c64e57b7041e1
4
+ data.tar.gz: 9957f9704925389b5adf30d148dee1f41843fd450bd1d5442b40a296b6daf21f
5
5
  SHA512:
6
- metadata.gz: e07e61553b61a4f0ed93efc32178290de7623a37fb58e8caf4ce170e8b09cf1d15b1765b7cd28544e99c841fa5de25bd78d02220308da2ce98cc02fb2af36938
7
- data.tar.gz: 58eb9ad54d778ace1d86fc8e7f39b069604d15049af4f3bd05b6cef8c629b9eec0b11589e44e5f63a371632d1f45396873eb3ac9c395c4ae002108c47f77e2b5
6
+ metadata.gz: c43a3a0a73533519d3fcaac45788fb1bb41c1bf746d5d0b2c4516c172f90f73cf51a1cc88560f0e546e76b3b0d269550ee91e39a5176ec63ba9933fc1f33e6c5
7
+ data.tar.gz: c415ad3ce71f604c39af7dd052556b1b53da73b5c4214ae60802f7024edc38cb761548ee78373f780987a95c8fdb9b753fc7dbfff1b270c400515f6454151f9d
@@ -1,14 +1,15 @@
1
1
  language: ruby
2
2
 
3
+ cache: bundler
4
+
3
5
  before_install:
4
6
  - gem update --system
5
7
  - gem install bundler
6
8
 
7
9
  rvm:
8
- - 2.6.3
10
+ - 2.6.5
9
11
 
10
12
  gemfile:
11
- - gemfiles/rails-4.2.gemfile
12
13
  - gemfiles/rails-5.0.gemfile
13
14
  - gemfiles/rails-5.1.gemfile
14
15
  - gemfiles/rails-5.2.gemfile
@@ -17,10 +18,7 @@ gemfile:
17
18
  addons:
18
19
  chrome: stable
19
20
 
20
- matrix:
21
- exclude:
22
- gemfile: gemfiles/rails-4.2.gemfile
23
-
21
+ jobs:
24
22
  include:
25
23
  gemfile: gemfiles/rails-4.2.gemfile
26
24
  before_install:
data/Gemfile CHANGED
@@ -5,7 +5,6 @@ gemspec
5
5
 
6
6
  group :test do
7
7
  gem 'coveralls', require: false
8
- gem 'simplecov', require: false
9
8
  gem 'guard-rspec', require: false
10
9
 
11
10
  gem 'capybara'
data/README.md CHANGED
@@ -28,7 +28,7 @@ Run `bundle install`, and then run the install generator to create the initial c
28
28
 
29
29
  $ rails generate trestle:install
30
30
 
31
- Then create your first admin resource:
31
+ Then create your first admin resource (assuming you have an existing `Article` model):
32
32
 
33
33
  $ rails generate trestle:resource Article
34
34
 
@@ -104,6 +104,8 @@ The following plugins are currently available:
104
104
  | *trestle-sidekiq* | [Sidekiq](http://sidekiq.org/) integration | [GitHub](https://github.com/TrestleAdmin/trestle-sidekiq) \| [RubyGems](https://rubygems.org/gems/trestle-sidekiq) |
105
105
  | *trestle-active_storage* | [Active Storage](https://guides.rubyonrails.org/active_storage_overview.html) integration | [GitHub](https://github.com/richardvenneman/trestle-active_storage) \| [RubyGems](https://rubygems.org/gems/trestle-active_storage) |
106
106
  | *trestle-mobility* | [Mobility](https://github.com/shioyama/mobility) integration | [GitHub](https://github.com/richardvenneman/trestle-mobility) \| [RubyGems](https://rubygems.org/gems/trestle-mobility) |
107
+ | *trestle-omniauth* | OmniAuth authentication plugin | [GitHub](https://github.com/airhorns/trestle-omniauth) \| [RubyGems](https://rubygems.org/gems/trestle-omniauth) |
108
+ | *trestle-auth-otp* | 2FA/OTP user authentication | [GitHub](https://github.com/McRipper/trestle-auth-otp) \| [RubyGems](https://rubygems.org/gems/trestle-auth-otp) |
107
109
 
108
110
 
109
111
  ## License
@@ -1,6 +1,6 @@
1
1
  module Trestle
2
2
  class Resource
3
- class Controller
3
+ module Controller
4
4
  module Actions
5
5
  def index
6
6
  respond_to do |format|
@@ -1,6 +1,6 @@
1
1
  module Trestle
2
2
  class Resource
3
- class Controller
3
+ module Controller
4
4
  module DataMethods
5
5
  extend ActiveSupport::Concern
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Trestle
2
2
  class Resource
3
- class Controller
3
+ module Controller
4
4
  module Redirection
5
5
  protected
6
6
  def redirect_to_return_location(action, instance, default:)
@@ -1,6 +1,6 @@
1
1
  module Trestle
2
2
  class Resource
3
- class Controller
3
+ module Controller
4
4
  module Toolbar
5
5
  def default_toolbar_builder
6
6
  Resource::Toolbar::Builder
@@ -0,0 +1,33 @@
1
+ module Trestle
2
+ class AdminController < ApplicationController
3
+ def index
4
+ end
5
+
6
+ class << self
7
+ attr_reader :admin
8
+
9
+ private
10
+ def local_prefixes
11
+ return admin.view_path_prefixes if admin
12
+ [controller_path.sub(/\/$/, "")]
13
+ end
14
+ end
15
+
16
+ def admin
17
+ @_admin ||= self.class.admin.new(self)
18
+ end
19
+ helper_method :admin
20
+
21
+ protected
22
+ def breadcrumbs
23
+ @_breadcrumbs ||= admin.breadcrumbs.dup
24
+ end
25
+
26
+ def flash_message(type, title:, message:)
27
+ {
28
+ title: admin.t("flash.#{type}.title", default: title),
29
+ message: admin.t("flash.#{type}.message", default: message)
30
+ }
31
+ end
32
+ end
33
+ end
@@ -1,15 +1,17 @@
1
- class Trestle::DashboardController < Trestle::ApplicationController
2
- def index
3
- admin = primary_admin
4
- redirect_to admin.path if admin
5
- end
1
+ module Trestle
2
+ class DashboardController < ApplicationController
3
+ def index
4
+ admin = primary_admin
5
+ redirect_to admin.path if admin
6
+ end
6
7
 
7
- private
8
- def primary_admin
9
- if navigation = Trestle.navigation(self).first
10
- navigation.admin
11
- elsif Trestle.admins.values.any?
12
- Trestle.admins.values.first
8
+ private
9
+ def primary_admin
10
+ if navigation = Trestle.navigation(self).first
11
+ navigation.admin
12
+ elsif Trestle.admins.values.any?
13
+ Trestle.admins.values.first
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -0,0 +1,8 @@
1
+ module Trestle
2
+ class ResourceController < AdminController
3
+ include Resource::Controller::Actions
4
+ include Resource::Controller::DataMethods
5
+ include Resource::Controller::Redirection
6
+ include Resource::Controller::Toolbar
7
+ end
8
+ end
@@ -45,9 +45,13 @@ module Trestle
45
45
  columns = breakpoints.delete("xs") || breakpoints.delete(:xs)
46
46
  end
47
47
 
48
- classes = []
49
- classes << (columns ? "col-#{columns}" : "col")
50
- classes += breakpoints.map { |breakpoint, span| "col-#{breakpoint}-#{span}" }
48
+ if columns.nil? && breakpoints.empty?
49
+ classes = "col"
50
+ else
51
+ classes = []
52
+ classes << "col-#{columns}" if columns
53
+ classes += breakpoints.map { |breakpoint, span| "col-#{breakpoint}-#{span}" }
54
+ end
51
55
 
52
56
  content_tag(:div, class: classes) { yield }
53
57
  end
@@ -1,17 +1,19 @@
1
1
  module Trestle
2
2
  module HookHelper
3
- def hook(name)
4
- if hook?(name)
5
- safe_join(hooks(name).map { |hook|
6
- hook.evaluate(self)
3
+ def hook(name, *args)
4
+ hooks = hooks(name)
5
+
6
+ if hooks.any?
7
+ safe_join(hooks.map { |hook|
8
+ hook.evaluate(self, *args)
7
9
  }, "\n")
8
10
  elsif block_given?
9
- capture(&Proc.new)
11
+ capture(*args, &Proc.new)
10
12
  end
11
13
  end
12
14
 
13
15
  def hook?(name)
14
- hook_sets.any? { |set| set.any?(name) }
16
+ hooks(name).any?
15
17
  end
16
18
 
17
19
  protected
@@ -4,11 +4,11 @@
4
4
  <% breadcrumb(title) %>
5
5
 
6
6
  <% toolbar(:primary) do |t| %>
7
- <%= t.save if admin.actions.include?(:update) %>
7
+ <%= t.save_or_dismiss(:update) %>
8
8
  <% end %>
9
9
 
10
10
  <% toolbar(:secondary) do |t| %>
11
- <%= t.delete if admin.actions.include?(:destroy) %>
11
+ <%= t.delete %>
12
12
  <% end %>
13
13
 
14
14
  <%= trestle_form_for instance, url: admin.actions.include?(:update) ? admin.instance_path(instance, action: :update) : "#", method: :patch do |f| %>
@@ -1,7 +1,7 @@
1
1
  <% content_for(:title, admin.t("titles.index", default: "Listing %{pluralized_model_name}")) %>
2
2
 
3
3
  <% toolbar(:primary) do |t| %>
4
- <%= t.new if admin.actions.include?(:new) %>
4
+ <%= t.new %>
5
5
  <% end %>
6
6
 
7
7
  <% content_for(:utilities) do %>
@@ -4,7 +4,7 @@
4
4
  <% breadcrumb(title) %>
5
5
 
6
6
  <% toolbar(:primary) do |t| %>
7
- <%= t.save if admin.actions.include?(:create) %>
7
+ <%= t.save_or_dismiss(:create) %>
8
8
  <% end %>
9
9
 
10
10
  <%= trestle_form_for instance, url: admin.path(:create), method: :post do |f| %>
@@ -4,11 +4,11 @@
4
4
  <% breadcrumb(title) unless admin.singular? %>
5
5
 
6
6
  <% toolbar(:primary) do |t| %>
7
- <%= t.save if admin.actions.include?(:update) %>
7
+ <%= t.save_or_dismiss(:update) %>
8
8
  <% end %>
9
9
 
10
10
  <% toolbar(:secondary) do |t| %>
11
- <%= t.delete if admin.actions.include?(:destroy) %>
11
+ <%= t.delete %>
12
12
  <% end %>
13
13
 
14
14
  <%= trestle_form_for instance, url: admin.actions.include?(:update) ? admin.instance_path(instance, action: :update) : "#", method: :patch do |f| %>
@@ -64,6 +64,22 @@
64
64
  .select-row {
65
65
  width: 2.5em;
66
66
  text-align: center;
67
+
68
+ .custom-control {
69
+ padding-left: 1.5rem;
70
+ }
71
+
72
+ .custom-control-input {
73
+ width: 1.5rem;
74
+ height: 1.5rem;
75
+ }
76
+
77
+ .custom-control-label {
78
+ &::before,
79
+ &::after {
80
+ left: -1.325rem;
81
+ }
82
+ }
67
83
  }
68
84
 
69
85
  .actions {
@@ -20,7 +20,9 @@
20
20
 
21
21
  .navbar-toggler {
22
22
  outline: none;
23
+
23
24
  margin-left: $grid-gutter-width / 2;
25
+ margin-right: $grid-gutter-width / 2;
24
26
 
25
27
  background: $sidebar-mobile-toggle-bg;
26
28
  border: $sidebar-mobile-toggle-border;
@@ -155,8 +157,11 @@
155
157
 
156
158
  .app-sidebar-title {
157
159
  justify-content: center;
158
- margin-right: 65px;
159
160
  padding: 10px 5px;
161
+
162
+ // Match right margin with navbar toggler width:
163
+ // (margin + border + font-size * icon-width + padding)
164
+ margin-right: calc(#{$grid-gutter-width} + #{$border-width} + #{$navbar-toggler-font-size} * 1.5 + #{$navbar-toggler-padding-x} * 2);
160
165
  }
161
166
 
162
167
  .toggle-sidebar {
@@ -15,11 +15,13 @@ init(function (root) {
15
15
  copyAttributes: 'href target data-remote data-method data-url data-params data-type'
16
16
  }
17
17
 
18
- const CONFIRM = { ...DEFAULTS,
18
+ const CONFIRM = {
19
+ ...DEFAULTS,
19
20
  rootSelector: '[data-toggle="confirm"]'
20
21
  }
21
22
 
22
- const DELETE = { ...DEFAULTS,
23
+ const DELETE = {
24
+ ...DEFAULTS,
23
25
  rootSelector: '[data-toggle="confirm-delete"]',
24
26
  btnOkClass: 'btn btn-sm btn-danger',
25
27
  btnOkLabel: i18n['trestle.confirmation.delete'] || 'Delete'
@@ -128,6 +128,9 @@ export default class Dialog {
128
128
  }
129
129
  }
130
130
 
131
+ // Expose showError as Trestle.Dialog.showError
132
+ Dialog.showError = showError
133
+
131
134
  $(document).on('click', '[data-behavior="dialog"]', function (e) {
132
135
  e.preventDefault()
133
136
 
@@ -22,6 +22,9 @@ init(function (root) {
22
22
 
23
23
  $form
24
24
  .on('ajax:send', function (e) {
25
+ // Only run when triggered directly on form
26
+ if (e.target !== this) return
27
+
25
28
  // Disable submit buttons
26
29
  $(this).find(':submit').prop('disabled', true)
27
30
 
@@ -30,6 +33,9 @@ init(function (root) {
30
33
  if (button) { $(button).addClass('loading') }
31
34
  })
32
35
  .on('ajax:complete', function (e) {
36
+ // Only run when triggered directly on form
37
+ if (e.target !== this) return
38
+
33
39
  const xhr = e.detail[0]
34
40
 
35
41
  // Reset submit buttons
@@ -64,6 +70,9 @@ init(function (root) {
64
70
  }
65
71
  })
66
72
  .on('ajax:success', function (e) {
73
+ // Only run when triggered directly on form
74
+ if (e.target !== this) return
75
+
67
76
  const xhr = e.detail[2]
68
77
 
69
78
  const $context = $(this).closest('[data-context]')
@@ -24,10 +24,10 @@ ready(function () {
24
24
  // Interacting outside of the sidebar closes the navigation
25
25
 
26
26
  $wrapper.on('click touchstart', function (e) {
27
- let navExpanded = $('body').hasClass('mobile-nav-expanded')
27
+ const navExpanded = $('body').hasClass('mobile-nav-expanded')
28
28
 
29
- let clickInHeader = $(e.target).closest('.app-header').length
30
- let clickInSidebar = $(e.target).closest('.app-sidebar').length
29
+ const clickInHeader = $(e.target).closest('.app-header').length
30
+ const clickInSidebar = $(e.target).closest('.app-sidebar').length
31
31
 
32
32
  if (navExpanded && !clickInHeader && !clickInSidebar) {
33
33
  e.stopPropagation()
@@ -62,7 +62,7 @@ ready(function () {
62
62
 
63
63
  $(this).closest('ul').toggleClass('collapsed')
64
64
 
65
- let collapsed = $sidebar.find('.collapsed .nav-header a').map(function () {
65
+ const collapsed = $sidebar.find('.collapsed .nav-header a').map(function () {
66
66
  return $(this).attr('href').replace(/^#/, '')
67
67
  }).toArray()
68
68
 
@@ -71,7 +71,7 @@ ready(function () {
71
71
 
72
72
  // Scroll sidebar to active item
73
73
 
74
- let $active = $sidebar.find('.active')
74
+ const $active = $sidebar.find('.active')
75
75
  if ($active.length) {
76
76
  $sidebar.find('.app-sidebar-inner').scrollTop($active.offset().top - 100)
77
77
  }