trestle 0.9.5 → 0.9.6

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +12 -6
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +9 -2
  6. data/README.md +5 -0
  7. data/app/assets/bundle/trestle/bundle.css +6 -6
  8. data/app/assets/bundle/trestle/bundle.js +40 -38
  9. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  10. data/app/assets/bundle/trestle/fa-brands-400.svg +41 -41
  11. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  12. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  13. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  14. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  15. data/app/assets/bundle/trestle/fa-regular-400.svg +2 -2
  16. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  17. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  18. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  19. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  20. data/app/assets/bundle/trestle/fa-solid-900.svg +13 -7
  21. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  22. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  23. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  24. data/app/assets/bundle/trestle/flatpickr/ar-dz.js +1 -0
  25. data/app/assets/bundle/trestle/flatpickr/ar.js +1 -1
  26. data/app/assets/bundle/trestle/flatpickr/at.js +1 -1
  27. data/app/assets/bundle/trestle/flatpickr/az.js +1 -1
  28. data/app/assets/bundle/trestle/flatpickr/be.js +1 -1
  29. data/app/assets/bundle/trestle/flatpickr/bg.js +1 -1
  30. data/app/assets/bundle/trestle/flatpickr/bn.js +1 -1
  31. data/app/assets/bundle/trestle/flatpickr/bs.js +1 -1
  32. data/app/assets/bundle/trestle/flatpickr/cat.js +1 -1
  33. data/app/assets/bundle/trestle/flatpickr/ckb.js +1 -0
  34. data/app/assets/bundle/trestle/flatpickr/cs.js +1 -1
  35. data/app/assets/bundle/trestle/flatpickr/cy.js +1 -1
  36. data/app/assets/bundle/trestle/flatpickr/da.js +1 -1
  37. data/app/assets/bundle/trestle/flatpickr/de.js +1 -1
  38. data/app/assets/bundle/trestle/flatpickr/default.js +1 -1
  39. data/app/assets/bundle/trestle/flatpickr/eo.js +1 -1
  40. data/app/assets/bundle/trestle/flatpickr/es.js +1 -1
  41. data/app/assets/bundle/trestle/flatpickr/et.js +1 -1
  42. data/app/assets/bundle/trestle/flatpickr/fa.js +1 -1
  43. data/app/assets/bundle/trestle/flatpickr/fi.js +1 -1
  44. data/app/assets/bundle/trestle/flatpickr/fo.js +1 -1
  45. data/app/assets/bundle/trestle/flatpickr/fr.js +1 -1
  46. data/app/assets/bundle/trestle/flatpickr/ga.js +1 -1
  47. data/app/assets/bundle/trestle/flatpickr/gr.js +1 -1
  48. data/app/assets/bundle/trestle/flatpickr/he.js +1 -1
  49. data/app/assets/bundle/trestle/flatpickr/hi.js +1 -1
  50. data/app/assets/bundle/trestle/flatpickr/hr.js +1 -1
  51. data/app/assets/bundle/trestle/flatpickr/hu.js +1 -1
  52. data/app/assets/bundle/trestle/flatpickr/hy.js +1 -0
  53. data/app/assets/bundle/trestle/flatpickr/id.js +1 -1
  54. data/app/assets/bundle/trestle/flatpickr/is.js +1 -1
  55. data/app/assets/bundle/trestle/flatpickr/it.js +1 -1
  56. data/app/assets/bundle/trestle/flatpickr/ja.js +1 -1
  57. data/app/assets/bundle/trestle/flatpickr/ka.js +1 -1
  58. data/app/assets/bundle/trestle/flatpickr/km.js +1 -1
  59. data/app/assets/bundle/trestle/flatpickr/ko.js +1 -1
  60. data/app/assets/bundle/trestle/flatpickr/kz.js +1 -1
  61. data/app/assets/bundle/trestle/flatpickr/lt.js +1 -1
  62. data/app/assets/bundle/trestle/flatpickr/lv.js +1 -1
  63. data/app/assets/bundle/trestle/flatpickr/mk.js +1 -1
  64. data/app/assets/bundle/trestle/flatpickr/mn.js +1 -1
  65. data/app/assets/bundle/trestle/flatpickr/ms.js +1 -1
  66. data/app/assets/bundle/trestle/flatpickr/my.js +1 -1
  67. data/app/assets/bundle/trestle/flatpickr/nl.js +1 -1
  68. data/app/assets/bundle/trestle/flatpickr/nn.js +1 -0
  69. data/app/assets/bundle/trestle/flatpickr/no.js +1 -1
  70. data/app/assets/bundle/trestle/flatpickr/pa.js +1 -1
  71. data/app/assets/bundle/trestle/flatpickr/pl.js +1 -1
  72. data/app/assets/bundle/trestle/flatpickr/pt.js +1 -1
  73. data/app/assets/bundle/trestle/flatpickr/ro.js +1 -1
  74. data/app/assets/bundle/trestle/flatpickr/ru.js +1 -1
  75. data/app/assets/bundle/trestle/flatpickr/si.js +1 -1
  76. data/app/assets/bundle/trestle/flatpickr/sk.js +1 -1
  77. data/app/assets/bundle/trestle/flatpickr/sl.js +1 -1
  78. data/app/assets/bundle/trestle/flatpickr/sq.js +1 -1
  79. data/app/assets/bundle/trestle/flatpickr/sr-cyr.js +1 -1
  80. data/app/assets/bundle/trestle/flatpickr/sr.js +1 -1
  81. data/app/assets/bundle/trestle/flatpickr/sv.js +1 -1
  82. data/app/assets/bundle/trestle/flatpickr/th.js +1 -1
  83. data/app/assets/bundle/trestle/flatpickr/tr.js +1 -1
  84. data/app/assets/bundle/trestle/flatpickr/uk.js +1 -1
  85. data/app/assets/bundle/trestle/flatpickr/uz.js +1 -1
  86. data/app/assets/bundle/trestle/flatpickr/uz_latn.js +1 -1
  87. data/app/assets/bundle/trestle/flatpickr/vn.js +1 -1
  88. data/app/assets/bundle/trestle/flatpickr/zh-tw.js +1 -1
  89. data/app/assets/bundle/trestle/flatpickr/zh.js +1 -1
  90. data/app/assets/javascripts/trestle/i18n.js.erb +1 -1
  91. data/app/controllers/trestle/dashboard_controller.rb +2 -2
  92. data/app/helpers/trestle/avatar_helper.rb +6 -2
  93. data/app/helpers/trestle/container_helper.rb +12 -4
  94. data/app/helpers/trestle/params_helper.rb +4 -1
  95. data/app/helpers/trestle/url_helper.rb +1 -11
  96. data/app/views/trestle/flash/_alert.html.erb +3 -1
  97. data/app/views/trestle/flash/_debug.html.erb +13 -8
  98. data/app/views/trestle/flash/_flash.html.erb +1 -1
  99. data/config/routes.rb +1 -1
  100. data/frontend/css/components/_alerts.scss +31 -0
  101. data/frontend/css/components/_avatar.scss +14 -0
  102. data/frontend/css/components/_buttons.scss +0 -1
  103. data/frontend/css/components/_datepicker.scss +1 -0
  104. data/frontend/css/components/_modal.scss +2 -0
  105. data/frontend/css/components/_tags.scss +2 -0
  106. data/frontend/css/components/_timestamp.scss +1 -1
  107. data/frontend/css/layout/_sidebar.scss +3 -2
  108. data/frontend/css/variables/_bootstrap.scss +1 -0
  109. data/frontend/css/variables/_trestle.scss +20 -0
  110. data/frontend/js/components/dialog.js +8 -3
  111. data/frontend/theme/trestle/theme/_defaults.scss +4 -4
  112. data/lib/generators/trestle/install/templates/_theme.scss +1 -1
  113. data/lib/generators/trestle/install/templates/trestle.rb.erb +6 -1
  114. data/lib/trestle/adapters/active_record_adapter.rb +16 -0
  115. data/lib/trestle/form/automatic.rb +2 -0
  116. data/lib/trestle/form/field.rb +1 -1
  117. data/lib/trestle/form/renderer.rb +4 -1
  118. data/lib/trestle/registry.rb +61 -0
  119. data/lib/trestle/reloader.rb +1 -1
  120. data/lib/trestle/table/automatic.rb +7 -0
  121. data/lib/trestle/version.rb +1 -1
  122. data/lib/trestle.rb +29 -14
  123. data/package.json +20 -23
  124. data/webpack.config.js +36 -48
  125. data/yarn.lock +2947 -4595
  126. metadata +9 -3
@@ -2,6 +2,6 @@
2
2
  <%= render "trestle/flash/alert", html_class: "alert-success", icon: icon("alert-icon far fa-check-circle"), alert: normalize_flash_alert(flash[:message]) %>
3
3
  <% elsif flash[:error] -%>
4
4
  <%= render layout: "trestle/flash/alert", locals: { html_class: "alert-danger", icon: icon("alert-icon far fa-times-circle"), alert: normalize_flash_alert(flash[:error]) } do %>
5
- <%= render "trestle/flash/debug" if debug_form_errors? %>
5
+ <%= render "trestle/flash/debug", errors: instance.errors if debug_form_errors? %>
6
6
  <% end %>
7
7
  <% end -%>
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  Trestle::Engine.routes.draw do
2
- Trestle.admins.each do |name, admin|
2
+ Trestle.registry.each do |admin|
3
3
  instance_eval(&admin.routes)
4
4
  end
5
5
 
@@ -32,13 +32,18 @@
32
32
 
33
33
  .alert-icon {
34
34
  margin-right: $alert-padding-x;
35
+
35
36
  font-size: 40px;
37
+ width: 40px;
38
+
39
+ text-align: center;
36
40
 
37
41
  @include media-breakpoint-down(sm) {
38
42
  margin-left: $alert-padding-x * 0.25;
39
43
  margin-right: $alert-padding-x * 0.75;
40
44
 
41
45
  font-size: 32px;
46
+ width: 32px;
42
47
  }
43
48
  }
44
49
 
@@ -74,10 +79,16 @@
74
79
  border-color: $border;
75
80
 
76
81
  a {
82
+ color: $color;
83
+
77
84
  &:hover, &:focus {
78
85
  color: mix($color, $background, 80%);
79
86
  }
80
87
  }
88
+
89
+ code {
90
+ color: $color;
91
+ }
81
92
  }
82
93
 
83
94
  .alert-success {
@@ -88,6 +99,26 @@
88
99
  @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-color);
89
100
  }
90
101
 
102
+ .alert-info {
103
+ @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-color);
104
+ }
105
+
106
+ .alert-warning {
107
+ @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-color);
108
+ }
109
+
110
+ .alert-light {
111
+ @include alert-variant($alert-light-bg, $alert-light-border, $alert-light-color);
112
+ }
113
+
114
+ .alert-dark {
115
+ @include alert-variant($alert-dark-bg, $alert-dark-border, $alert-dark-color);
116
+ }
117
+
118
+ .alert-primary {
119
+ @include alert-variant($alert-primary-bg, $alert-primary-border, $alert-primary-color);
120
+ }
121
+
91
122
 
92
123
  // Debug errors
93
124
 
@@ -41,3 +41,17 @@
41
41
  font-weight: 500;
42
42
  }
43
43
  }
44
+
45
+ .avatar-sm {
46
+ width: 24px !important;
47
+ height: 24px !important;
48
+ }
49
+
50
+ .avatar-lg {
51
+ width: 64px !important;
52
+ height: 64px !important;
53
+
54
+ .avatar-fallback {
55
+ font-size: 1.5rem;
56
+ }
57
+ }
@@ -1,5 +1,4 @@
1
1
  .btn {
2
- border-width: 0;
3
2
  box-shadow: none;
4
3
 
5
4
  &.loading {
@@ -13,6 +13,7 @@
13
13
 
14
14
  &:hover, &:focus {
15
15
  color: #aaa;
16
+ text-decoration: none;
16
17
  }
17
18
 
18
19
  &::before {
@@ -24,6 +24,8 @@
24
24
  }
25
25
 
26
26
  &.background {
27
+ overflow-y: hidden;
28
+
27
29
  .modal-dialog {
28
30
  transform: scale(0.9);
29
31
  opacity: 0.75;
@@ -16,6 +16,8 @@
16
16
  }
17
17
 
18
18
  a.tag {
19
+ font-weight: inherit;
20
+
19
21
  &:hover, &:focus {
20
22
  text-decoration: none;
21
23
  color: $tag-hover-color;
@@ -4,7 +4,7 @@
4
4
 
5
5
  small {
6
6
  display: block;
7
- color: #666;
7
+ opacity: 0.75;
8
8
  }
9
9
 
10
10
  &.timestamp-inline,
@@ -16,11 +16,13 @@
16
16
  height: $header-height;
17
17
 
18
18
  display: flex;
19
- align-items: center;
19
+ align-items: stretch;
20
20
 
21
21
  .navbar-toggler {
22
22
  outline: none;
23
23
 
24
+ align-self: center;
25
+
24
26
  margin-left: $grid-gutter-width / 2;
25
27
  margin-right: $grid-gutter-width / 2;
26
28
 
@@ -44,7 +46,6 @@
44
46
  display: flex;
45
47
  align-items: center;
46
48
 
47
- height: 100%;
48
49
  padding: 10px 15px;
49
50
 
50
51
  font-size: 1.4rem;
@@ -7,6 +7,7 @@ $theme-colors: (
7
7
  "warning": #f3bd71,
8
8
  "danger": #e17572,
9
9
  "light": #bbbbbb,
10
+ "dark": #444444,
10
11
 
11
12
  // Backwards compatibility
12
13
  "default": #bbbbbb
@@ -101,6 +101,26 @@ $alert-danger-bg: #de7471;
101
101
  $alert-danger-color: white;
102
102
  $alert-danger-border: #d85956;
103
103
 
104
+ $alert-info-bg: darken(theme-color("info"), 10%);
105
+ $alert-info-color: white;
106
+ $alert-info-border: darken($alert-info-bg, 10%);
107
+
108
+ $alert-warning-bg: darken(theme-color("warning"), 5%);
109
+ $alert-warning-color: white;
110
+ $alert-warning-border: darken($alert-warning-bg, 5%);
111
+
112
+ $alert-light-bg: theme-color("light");
113
+ $alert-light-color: $body-color;
114
+ $alert-light-border: darken($alert-light-bg, 5%);
115
+
116
+ $alert-dark-bg: theme-color("dark");
117
+ $alert-dark-color: white;
118
+ $alert-dark-border: darken($alert-dark-bg, 10%);
119
+
120
+ $alert-primary-bg: darken(theme-color("primary"), 5%);
121
+ $alert-primary-color: white;
122
+ $alert-primary-border: darken($alert-primary-bg, 10%);
123
+
104
124
 
105
125
  // Modals
106
126
 
@@ -20,14 +20,19 @@ function createElement () {
20
20
  focus: false
21
21
  })
22
22
 
23
- // Remove dialog elements once hidden
24
23
  $el.on('hidden.bs.modal', function () {
24
+ // Restore modal-open class on body if background modals still visible
25
+ if ($el.prevAll('.modal.show').length) {
26
+ $(document.body).addClass('modal-open')
27
+ }
28
+
29
+ // Remove dialog elements once hidden
25
30
  $el.remove()
26
31
  })
27
32
 
28
33
  // Restore the next visible modal to the foreground
29
34
  $el.on('hide.bs.modal', function () {
30
- $el.prevAll('.modal.in').last().removeClass('background')
35
+ $el.prevAll('.modal.show').last().removeClass('background')
31
36
  })
32
37
 
33
38
  // Set X-Trestle-Dialog header on AJAX requests initiated from the dialog
@@ -120,7 +125,7 @@ export default class Dialog {
120
125
  this.$el.modal('show')
121
126
 
122
127
  // Background any existing visible modals
123
- this.$el.prevAll('.modal.in').addClass('background')
128
+ this.$el.prevAll('.modal.show').addClass('background')
124
129
  }
125
130
 
126
131
  hide () {
@@ -8,7 +8,7 @@ $theme-colors: (
8
8
  $theme-color-interval: 8% !default;
9
9
 
10
10
  // The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
11
- $yiq-contrasted-threshold: 150 !default;
11
+ $yiq-contrasted-threshold: 175 !default;
12
12
 
13
13
  // Customize the light and dark text colors for use in our YIQ color contrast function.
14
14
  $yiq-text-dark: #212529 !default;
@@ -115,9 +115,9 @@ $badge-focus-width: $input-btn-focus-width !default;
115
115
 
116
116
  // Alerts
117
117
 
118
- $alert-bg-level: -10 !default;
119
- $alert-border-level: -9 !default;
120
- $alert-color-level: 6 !default;
118
+ $alert-bg-level: 2 !default;
119
+ $alert-border-level: 3 !default;
120
+ $alert-color-level: -12 !default;
121
121
 
122
122
 
123
123
  // Progress bars
@@ -9,5 +9,5 @@
9
9
  //
10
10
  // $theme-colors: (
11
11
  // "primary": #337ab7,
12
- // "secondary": #b3b53d
12
+ // "secondary": #719dc3
13
13
  // );
@@ -15,7 +15,7 @@ Trestle.configure do |config|
15
15
  #
16
16
  # config.site_logo_small = "logo-small.png"
17
17
 
18
- # Speficy a favicon to be used within the admin.
18
+ # Specify a favicon to be used within the admin.
19
19
  #
20
20
  # config.favicon = "favicon.ico"
21
21
 
@@ -103,6 +103,11 @@ Trestle.configure do |config|
103
103
  #
104
104
  # config.persistent_params << :query
105
105
 
106
+ # List of methods to try calling on an instance when displayed by the `display` helper.
107
+ # Defaults to [:display_name, :full_name, :name, :title, :username, :login, :email].
108
+ #
109
+ # config.display_methods.unshift(:admin_label)
110
+
106
111
  # Customize the default adapter class used by all admin resources.
107
112
  # See the documentation on Trestle::Adapters::Adapter for details on
108
113
  # the adapter methods that can be customized.
@@ -60,6 +60,8 @@ module Trestle
60
60
  Attribute::Association.new(column.name, class: -> { reflection.klass }, name: name, polymorphic: reflection.polymorphic?, type_column: reflection.foreign_type)
61
61
  elsif column.name.end_with?("_type") && (name = column.name.sub(/_type$/, '')) && (reflection = model.reflections[name])
62
62
  # Ignore type columns for polymorphic associations
63
+ elsif enum_column?(column)
64
+ Attribute.new(column.name, :enum, values: enum_values(column))
63
65
  else
64
66
  Attribute.new(column.name, column.type, array_column?(column) ? { array: true } : {})
65
67
  end
@@ -81,6 +83,20 @@ module Trestle
81
83
  def array_column?(column)
82
84
  column.respond_to?(:array?) && column.array?
83
85
  end
86
+
87
+ def enum_column?(column)
88
+ model.defined_enums.key?(column.name)
89
+ end
90
+
91
+ def enum_values(column)
92
+ model.defined_enums[column.name].map { |key, value|
93
+ [value, enum_human_name(column, key)]
94
+ }
95
+ end
96
+
97
+ def enum_human_name(column, value)
98
+ human_attribute_name([column.name.pluralize, value].join("."), default: value.humanize)
99
+ end
84
100
  end
85
101
  end
86
102
  end
@@ -32,6 +32,8 @@ module Trestle
32
32
  datetime_field attribute.name
33
33
  when :boolean
34
34
  check_box attribute.name
35
+ when :enum
36
+ collection_radio_buttons attribute.name, attribute.options[:values] || [], :first, :last
35
37
  when :json, :jsonb
36
38
  value = instance.public_send(attribute.name)
37
39
  text_area attribute.name, value: value.try(:to_json)
@@ -45,7 +45,7 @@ module Trestle
45
45
  end
46
46
 
47
47
  def readonly?
48
- options[:readonly] || admin.readonly?
48
+ options[:readonly] || admin.try(:readonly?)
49
49
  end
50
50
 
51
51
  def normalize_options!
@@ -4,6 +4,9 @@ require "action_view/helpers"
4
4
  module Trestle
5
5
  class Form
6
6
  class Renderer
7
+ def self.ruby2_keywords(*)
8
+ end unless respond_to?(:ruby2_keywords, true)
9
+
7
10
  include ::ActionView::Context
8
11
  include ::ActionView::Helpers::CaptureHelper
9
12
 
@@ -40,7 +43,7 @@ module Trestle
40
43
  concat(result)
41
44
  end
42
45
 
43
- def method_missing(name, *args, &block)
46
+ ruby2_keywords def method_missing(name, *args, &block)
44
47
  target = @form.respond_to?(name) ? @form : @template
45
48
 
46
49
  if block_given? && !RAW_BLOCK_HELPERS.include?(name)
@@ -0,0 +1,61 @@
1
+ module Trestle
2
+ class Registry
3
+ include Enumerable
4
+
5
+ # The admins hash is left exposed for backwards compatibility
6
+ attr_reader :admins
7
+
8
+ def initialize
9
+ reset!
10
+ end
11
+
12
+ def each(&block)
13
+ @admins.values.sort_by(&:admin_name).each(&block)
14
+ end
15
+
16
+ def reset!
17
+ @admins = {}
18
+ @models = {}
19
+ end
20
+
21
+ def empty?
22
+ none?
23
+ end
24
+
25
+ def register(admin, register_model: true)
26
+ @admins[admin.admin_name] = admin
27
+
28
+ if register_model && register_admin_for_model_loookup?(admin)
29
+ @models[admin.model.name] ||= admin
30
+ end
31
+
32
+ admin
33
+ end
34
+
35
+ def lookup_admin(admin)
36
+ # Given object is already an admin class
37
+ return admin if admin.is_a?(Class) && admin < Trestle::Admin
38
+
39
+ @admins[admin.to_s]
40
+ end
41
+ alias lookup lookup_admin
42
+
43
+ def lookup_model(model)
44
+ # Lookup each class in the model's ancestor chain
45
+ while model
46
+ admin = @models[model.name]
47
+ return admin if admin
48
+
49
+ model = model.superclass
50
+ end
51
+
52
+ # No admin found
53
+ nil
54
+ end
55
+
56
+ private
57
+ def register_admin_for_model_loookup?(admin)
58
+ admin.respond_to?(:model) && !(admin.respond_to?(:singular?) && admin.singular?)
59
+ end
60
+ end
61
+ end
@@ -26,7 +26,7 @@ module Trestle
26
26
  end
27
27
 
28
28
  def clear
29
- Trestle.admins = {}
29
+ Trestle.registry.reset!
30
30
  end
31
31
 
32
32
  def load_paths
@@ -14,6 +14,13 @@ module Trestle
14
14
  case attribute.type
15
15
  when :association
16
16
  Column.new(attribute.association_name, sort: false)
17
+ when :enum
18
+ Column.new(attribute.name, align: :center, sort: attribute.name) do |instance|
19
+ if value = instance.public_send(attribute.name)
20
+ full_attribute_name = [attribute.name.to_s.pluralize, value].join(".")
21
+ status_tag(admin.human_attribute_name(full_attribute_name, default: value.humanize))
22
+ end
23
+ end
17
24
  else
18
25
  Column.new(attribute.name, link: index.zero?, align: (:center if [:datetime, :boolean].include?(attribute.type)))
19
26
  end
@@ -1,3 +1,3 @@
1
1
  module Trestle
2
- VERSION = "0.9.5"
2
+ VERSION = "0.9.6"
3
3
  end
data/lib/trestle.rb CHANGED
@@ -23,27 +23,29 @@ module Trestle
23
23
  require_relative "trestle/tab"
24
24
  require_relative "trestle/table"
25
25
  require_relative "trestle/admin"
26
+ require_relative "trestle/registry"
26
27
  require_relative "trestle/resource"
27
28
 
28
- mattr_accessor :admins
29
- self.admins = {}
29
+ # The registry records all active Trestle admins and facilitates lookups.
30
+ mattr_accessor :registry
31
+ self.registry = Registry.new
30
32
 
31
- def self.admin(name, options={}, &block)
32
- register(Admin::Builder.create(name, options, &block))
33
+ class << self
34
+ # Expose registry methods on Trestle module
35
+ delegate :register, :lookup, :lookup_model, :admins, to: :registry
33
36
  end
34
37
 
35
- def self.resource(name, options={}, &block)
36
- register(Resource::Builder.create(name, options, &block))
38
+ # Builds and registers a new plain admin
39
+ def self.admin(name, **options, &block)
40
+ register(Admin::Builder.create(name, options, &block))
37
41
  end
38
42
 
39
- def self.register(admin)
40
- self.admins[admin.admin_name] = admin
43
+ # Builds and registers a new admin resource
44
+ def self.resource(name, register_model: true, **options, &block)
45
+ register(Resource::Builder.create(name, options, &block), register_model: register_model)
41
46
  end
42
47
 
43
- def self.lookup(admin)
44
- return admin if admin.is_a?(Class) && admin < Trestle::Admin
45
- self.admins[admin.to_s]
46
- end
48
+ # Configuration methods
47
49
 
48
50
  def self.config
49
51
  @configuration ||= Configuration.new
@@ -53,14 +55,27 @@ module Trestle
53
55
  config.configure(&block)
54
56
  end
55
57
 
58
+ # Builds the global navigation by combining the menu options from the
59
+ # Trestle configuration along with menu blocks from admin resources.
56
60
  def self.navigation(context)
57
- blocks = config.menus + admins.values.map(&:menu).compact
61
+ blocks = config.menus + registry.map(&:menu).compact
58
62
  Navigation.build(blocks, context)
59
63
  end
60
64
 
65
+ # Returns the I18n fallbacks for the given locale.
66
+ #
67
+ # This is used from within a Sprockets asset (JavaScript)
68
+ # to determine which locale files to include.
69
+ #
70
+ # Examples
71
+ #
72
+ # Trestle.i18n_fallbacks("pt-BR") => ["pt-BR", "pt"]
73
+ # Trestle.i18n_fallbacks("ca") => ["ca", "es-ES", "es"] %>
74
+ #
75
+ # Returns an array of locale Strings.
61
76
  def self.i18n_fallbacks(locale=I18n.locale)
62
77
  if I18n.respond_to?(:fallbacks)
63
- I18n.fallbacks[locale]
78
+ I18n.fallbacks[locale].map(&:to_s)
64
79
  elsif locale.to_s.include?("-")
65
80
  fallback = locale.to_s.split("-").first
66
81
  [locale, fallback]
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trestle",
3
- "version": "0.9.0",
3
+ "version": "0.9.6",
4
4
  "description": "A modern, responsive admin framework for Ruby on Rails",
5
5
  "homepage": "https://trestle.io",
6
6
  "repository": "https://github.com/TrestleAdmin/trestle.git",
@@ -13,36 +13,33 @@
13
13
  "watch": "webpack --mode development --watch"
14
14
  },
15
15
  "devDependencies": {
16
- "@babel/core": "^7.6.0",
17
- "@babel/preset-env": "^7.6.0",
18
- "autoprefixer": "^9.6.1",
16
+ "@babel/core": "^7.14.6",
17
+ "@babel/preset-env": "^7.14.7",
18
+ "autoprefixer": "^10.2.6",
19
19
  "babel-loader": "^8.0.6",
20
- "copy-webpack-plugin": "^5.0.4",
21
- "css-loader": "^3.2.0",
22
- "expose-loader": "^0.7.5",
23
- "file-loader": "^6.0.0",
24
- "mini-css-extract-plugin": "^0.9.0",
25
- "node-sass": "^4.14.1",
26
- "optimize-css-assets-webpack-plugin": "^5.0.3",
27
- "postcss-loader": "^3.0.0",
28
- "sass-loader": "^8.0.0",
29
- "uglify-js": "^3.9.3",
30
- "uglifyjs-webpack-plugin": "^2.2.0",
31
- "url-loader": "^4.1.0",
32
- "webpack": "^4.40.2",
33
- "webpack-cli": "^3.3.9"
20
+ "copy-webpack-plugin": "^9.0.1",
21
+ "css-loader": "^5.2.6",
22
+ "css-minimizer-webpack-plugin": "^3.0.2",
23
+ "expose-loader": "^3.0.0",
24
+ "mini-css-extract-plugin": "^2.0.0",
25
+ "node-sass": "^7.0.1",
26
+ "postcss": "^8.3.5",
27
+ "postcss-loader": "^6.1.1",
28
+ "sass-loader": "^12.1.0",
29
+ "webpack": "^5.42.0",
30
+ "webpack-cli": "^4.7.2"
34
31
  },
35
32
  "dependencies": {
36
- "@fortawesome/fontawesome-free": "^5.11.1",
37
- "@rails/ujs": "^6.0.3",
33
+ "@fortawesome/fontawesome-free": "^5.15.3",
34
+ "@rails/ujs": "^6.1.3-1",
38
35
  "bootstrap": "^4.5.0",
39
- "bootstrap-confirmation2": "^4.1.0",
36
+ "bootstrap-confirmation2": "^4.2.1",
40
37
  "bs-custom-file-input": "^1.3.2",
41
38
  "flatpickr": "^4.6.2",
42
- "jquery": "^3.5.1",
39
+ "jquery": "^3.6.0",
43
40
  "magnific-popup": "^1.1.0",
44
41
  "popper.js": "^1.15.0",
45
42
  "select2": "^4.0.10",
46
- "select2-theme-bootstrap4": "^0.2.0-beta.4"
43
+ "select2-theme-bootstrap4": "^1.0.0"
47
44
  }
48
45
  }