trestle 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
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
  }