trestle 0.10.0 → 0.10.1

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +4 -0
  3. data/app/assets/bundle/trestle/admin.css +3 -3
  4. data/app/assets/bundle/trestle/admin.js +13 -13
  5. data/app/assets/bundle/trestle/photoswipe-2d522a3abaa59f8a8f73.digested.js +6 -0
  6. data/app/helpers/trestle/avatar_helper.rb +20 -14
  7. data/app/helpers/trestle/card_helper.rb +27 -9
  8. data/app/helpers/trestle/container_helper.rb +37 -6
  9. data/app/helpers/trestle/display_helper.rb +11 -0
  10. data/app/helpers/trestle/flash_helper.rb +1 -10
  11. data/app/helpers/trestle/form_helper.rb +32 -18
  12. data/app/helpers/trestle/format_helper.rb +47 -17
  13. data/app/helpers/trestle/gravatar_helper.rb +48 -0
  14. data/app/helpers/trestle/grid_helper.rb +12 -14
  15. data/app/helpers/trestle/headings_helper.rb +2 -23
  16. data/app/helpers/trestle/i18n_helper.rb +1 -0
  17. data/app/helpers/trestle/icon_helper.rb +16 -3
  18. data/app/helpers/trestle/layout_helper.rb +1 -0
  19. data/app/helpers/trestle/modal_helper.rb +21 -2
  20. data/app/helpers/trestle/navigation_helper.rb +1 -0
  21. data/app/helpers/trestle/pagination_helper.rb +1 -0
  22. data/app/helpers/trestle/params_helper.rb +32 -0
  23. data/app/helpers/trestle/sort_helper.rb +38 -7
  24. data/app/helpers/trestle/status_helper.rb +19 -3
  25. data/app/helpers/trestle/tab_helper.rb +42 -7
  26. data/app/helpers/trestle/table_helper.rb +23 -23
  27. data/app/helpers/trestle/timestamp_helper.rb +18 -25
  28. data/app/helpers/trestle/title_helper.rb +2 -0
  29. data/app/helpers/trestle/toolbars_helper.rb +2 -1
  30. data/app/helpers/trestle/turbo/frame_helper.rb +25 -14
  31. data/app/helpers/trestle/url_helper.rb +124 -54
  32. data/app/views/kaminari/trestle/_first_page.html.erb +1 -2
  33. data/app/views/kaminari/trestle/_gap.html.erb +0 -1
  34. data/app/views/kaminari/trestle/_last_page.html.erb +1 -2
  35. data/app/views/kaminari/trestle/_page.html.erb +1 -2
  36. data/app/views/kaminari/trestle/_paginator.html.erb +0 -1
  37. data/app/views/layouts/trestle/admin.html.erb +3 -3
  38. data/app/views/layouts/trestle/modal.html.erb +2 -2
  39. data/app/views/trestle/application/_layout.html.erb +22 -18
  40. data/app/views/trestle/application/_tabs.html.erb +1 -1
  41. data/app/views/trestle/flash/_alert.html.erb +3 -1
  42. data/app/views/trestle/flash/_flash.html.erb +7 -4
  43. data/app/views/trestle/resource/_scopes.html.erb +3 -3
  44. data/app/views/trestle/resource/create.turbo_stream.erb +1 -0
  45. data/app/views/trestle/resource/destroy.turbo_stream.erb +2 -0
  46. data/app/views/trestle/resource/index.html.erb +10 -12
  47. data/app/views/trestle/resource/update.turbo_stream.erb +1 -0
  48. data/app/views/trestle/shared/_sidebar.html.erb +8 -8
  49. data/app/views/trestle/table/_table.html.erb +2 -2
  50. data/config/locales/pt-BR.yml +13 -13
  51. data/frontend/css/components/_scopes.scss +6 -7
  52. data/frontend/css/core/_theme.scss +3 -3
  53. data/frontend/css/layout/_sidebar.scss +2 -0
  54. data/frontend/js/controllers/flatpickr_controller.js +2 -2
  55. data/frontend/js/controllers/lightbox_controller.js +3 -3
  56. data/frontend/js/controllers/modal_trigger_controller.js +2 -2
  57. data/frontend/js/controllers/sidebar_controller.js +13 -3
  58. data/frontend/js/controllers/tab_errors_controller.js +2 -2
  59. data/frontend/js/core/backdrop.js +30 -28
  60. data/frontend/js/core/error_modal.js +7 -9
  61. data/frontend/js/core/fetch.js +2 -0
  62. data/lib/trestle/admin.rb +9 -2
  63. data/lib/trestle/configuration.rb +3 -0
  64. data/lib/trestle/engine.rb +1 -1
  65. data/lib/trestle/evaluation_context.rb +2 -4
  66. data/lib/trestle/form/automatic.rb +1 -1
  67. data/lib/trestle/form/field.rb +1 -1
  68. data/lib/trestle/form/fields/check_box.rb +1 -1
  69. data/lib/trestle/form/fields/collection_check_boxes.rb +1 -1
  70. data/lib/trestle/form/fields/collection_radio_buttons.rb +1 -1
  71. data/lib/trestle/form/fields/date_select.rb +1 -1
  72. data/lib/trestle/form/fields/datetime_select.rb +1 -1
  73. data/lib/trestle/form/fields/form_control.rb +2 -2
  74. data/lib/trestle/form/fields/form_group.rb +4 -4
  75. data/lib/trestle/form/fields/radio_button.rb +1 -1
  76. data/lib/trestle/form/fields/static_field.rb +1 -1
  77. data/lib/trestle/form/fields/time_select.rb +1 -1
  78. data/lib/trestle/form/renderer.rb +2 -4
  79. data/lib/trestle/hook/helpers.rb +21 -0
  80. data/lib/trestle/navigation/block.rb +8 -15
  81. data/lib/trestle/navigation/group.rb +2 -2
  82. data/lib/trestle/navigation/item.rb +21 -4
  83. data/lib/trestle/registry.rb +14 -11
  84. data/lib/trestle/resource/builder.rb +9 -6
  85. data/lib/trestle/resource/toolbar.rb +4 -4
  86. data/lib/trestle/resource.rb +7 -5
  87. data/lib/trestle/scopes/block.rb +8 -12
  88. data/lib/trestle/scopes/definition.rb +6 -2
  89. data/lib/trestle/scopes/scope.rb +13 -10
  90. data/lib/trestle/tab.rb +2 -2
  91. data/lib/trestle/table/column.rb +4 -3
  92. data/lib/trestle/table/row.rb +1 -1
  93. data/lib/trestle/toolbar/builder.rb +6 -6
  94. data/lib/trestle/toolbar/context.rb +2 -4
  95. data/lib/trestle/toolbar/item.rb +10 -19
  96. data/lib/trestle/toolbar/menu.rb +9 -9
  97. data/lib/trestle/version.rb +1 -1
  98. data/lib/trestle.rb +2 -2
  99. data/package.json +7 -7
  100. data/yarn.lock +517 -564
  101. metadata +5 -5
  102. data/app/assets/bundle/trestle/photoswipe-063ce7be40e10b3e6848.digested.js +0 -6
  103. data/app/views/layouts/trestle/admin.turbo_stream.erb +0 -4
@@ -2,81 +2,151 @@ module Trestle
2
2
  module UrlHelper
3
3
  MODAL_ACTIONS = [:new, :show, :edit]
4
4
 
5
- def admin_link_to(content, instance_or_url=nil, options={}, &block)
5
+ # Generates a link to an admin, optionally for a specific instance on a resourceful admin.
6
+ #
7
+ # It has a few additional conveniences over using the standard `link_to` helper:
8
+ #
9
+ # 1) It can automatically infer the admin from the given instance.
10
+ # 2) It will automatically add data-controller="modal-trigger" when linking to a form
11
+ # action that is set to show as a modal.
12
+ # 3) It sets data-turbo-frame appropriately for modal and non-modal contexts to ensure
13
+ # the admin can correctly detect modal requests.
14
+ #
15
+ # content - HTML or text content to use as the link content
16
+ # (will be ignored if a block is provided)
17
+ # instance - Optional model instance, or explicit String path
18
+ # admin - Optional admin instance to link to. Will be inferred from instance if provided,
19
+ # otherwise falling back to the current admin if available
20
+ # action - Optional admin action to link to. Will default to :show if instance is provided,
21
+ # otherwise the admin's root action (usually :index) will be used
22
+ # method - Optional request method (e.g. :delete), that will be set as `data-turbo-method`
23
+ # params - Hash of URL parameters to pass to `instance_path` or `path` admin methods (default: {})
24
+ # options - Hash of options to forward to the `link_to` helper (default: {})
25
+ # block - Optional block to capture to use as the link content
26
+ #
27
+ # Examples
28
+ #
29
+ # <%= admin_link_to article.name, article %>
30
+ #
31
+ # <%= admin_link_to admin: :dashboard, action: :index do %>
32
+ # <%= icon "fas fa-gauge" %> Dashboard
33
+ # <% end %>
34
+ #
35
+ # Returns a HTML-safe String.
36
+ # Raises ActionController::UrlGenerationError if the admin cannot be automatically inferred.
37
+ def admin_link_to(content=nil, instance=nil, admin: nil, action: nil, method: nil, params: {}, **options, &block)
6
38
  # Block given - ignore content parameter and capture content from block
7
39
  if block_given?
8
- instance_or_url, options = content, instance_or_url || {}
9
- content = capture(&block)
40
+ instance, content = content, capture(&block)
10
41
  end
11
42
 
12
- if instance_or_url.is_a?(String)
13
- # Treat string URL as regular link
14
- link_to(content, instance_or_url, options)
15
- else
16
- # Normalize options if instance is not provided
17
- if instance_or_url.is_a?(Hash)
18
- instance, options = nil, instance_or_url
19
- else
20
- instance = instance_or_url
21
- end
22
-
23
- # Determine admin
24
- if options.key?(:admin)
25
- admin = Trestle.lookup(options.delete(:admin))
26
- elsif instance
27
- admin = admin_for(instance)
28
- end
43
+ # Treat string URL as regular link
44
+ if instance.is_a?(String)
45
+ return link_to(content, instance, options)
46
+ end
29
47
 
30
- admin ||= self.admin if respond_to?(:admin)
48
+ # Determine target admin
49
+ target = lookup_admin_from_options(
50
+ instance: instance,
51
+ admin: admin,
52
+ fallback: self&.admin,
53
+ raise: true
54
+ )
31
55
 
32
- if admin
33
- # Ensure admin has controller context
34
- admin = admin.new(self) if admin.is_a?(Class)
56
+ # Set default action depending on instance or not
57
+ action ||= (instance ? :show : target.root_action)
35
58
 
36
- # Generate path
37
- action = options.delete(:action) || :show
38
- params = options.delete(:params) || {}
59
+ path = admin_url_for(instance, admin: target, action: action, **params)
39
60
 
40
- if admin.respond_to?(:instance_path) && instance
41
- path = admin.instance_path(instance, params.reverse_merge(action: action))
42
- else
43
- params[:id] ||= admin.to_param(instance) if instance
44
- path = admin.path(action, params)
45
- end
61
+ # Determine link data options
62
+ options[:data] ||= {}
46
63
 
47
- # Determine link data options
48
- options[:data] ||= {}
64
+ if MODAL_ACTIONS.include?(action) && target&.form&.modal?
65
+ options[:data][:controller] ||= "modal-trigger"
66
+ else
67
+ options[:data][:turbo_frame] ||= (modal_request? ? "modal" : "_top")
68
+ end
49
69
 
50
- if MODAL_ACTIONS.include?(action) && admin.respond_to?(:form) && admin.form.modal?
51
- options[:data][:controller] ||= "modal-trigger"
52
- else
53
- options[:data][:turbo_frame] ||= (modal_request? ? "modal" : "_top")
54
- end
70
+ options[:data][:turbo_method] ||= method if method
55
71
 
56
- link_to(content, path, options)
57
- else
58
- raise ActionController::UrlGenerationError, "An admin could not be inferred. Please specify an admin using the :admin option."
59
- end
60
- end
72
+ link_to(content, path, options)
61
73
  end
62
74
 
63
- def admin_url_for(instance, options={})
64
- admin = Trestle.lookup(options.delete(:admin)) if options.key?(:admin)
65
- admin ||= admin_for(instance)
66
- return unless admin
75
+ # Returns the admin path for a given instance.
76
+ #
77
+ # An admin can either be explicitly specified (as a symbol or admin class),
78
+ # or it can be automatically inferred based the instance type using `admin_for`.
79
+ #
80
+ # instance - The model instance to generate a path for
81
+ # admin - Optional admin (symbol or admin class)
82
+ # action - Optional admin action to generate the URL for. Will default to :show if
83
+ # instance is provided, otherwise the admin's root action (usually :index)
84
+ # will be used
85
+ # raise - Whether to raise a ActionController::UrlGenerationError if the admin
86
+ # cannot be determined, either from the admin parameter or automatically
87
+ # params - Hash of URL parameters to pass to `instance_path` or `path` admin methods
88
+ #
89
+ # Examples
90
+ #
91
+ # <%= admin_url_for(article, action: :edit) %>
92
+ # <%= admin_url_for(article, admin: :special_articles) %>
93
+ #
94
+ # Returns a String, or nil if the admin cannot be automatically inferred.
95
+ def admin_url_for(instance=nil, admin: nil, action: nil, raise: false, **params)
96
+ target = lookup_admin_from_options(
97
+ instance: instance,
98
+ admin: admin,
99
+ fallback: self&.admin,
100
+ raise: raise
101
+ )
102
+ return unless target
67
103
 
68
- # Ensure admin has controller context
69
- admin = admin.new(self) if admin.is_a?(Class)
104
+ # Set default action depending on instance or not
105
+ action ||= (instance ? :show : target.root_action)
70
106
 
71
- if admin.respond_to?(:instance_path)
72
- admin.instance_path(instance, options)
107
+ if instance
108
+ if target.respond_to?(:instance_path)
109
+ target.instance_path(instance, action: action, **params)
110
+ else
111
+ target.path(action, params.merge(id: target.to_param(instance)))
112
+ end
73
113
  else
74
- admin.path(options[:action] || :show, id: admin.to_param(instance))
114
+ target.path(action, params)
75
115
  end
76
116
  end
77
117
 
118
+ # Looks up the registered Trestle admin for a given model instance.
119
+ #
120
+ # The lookup is performed on the global `Trestle::Registry` instance,
121
+ # which tracks admin resource models unless the resource was created
122
+ # with `register_model: false`.
123
+ #
124
+ # instance - The model instance to look up in the registry
125
+ #
126
+ # Returns a Trestle::Admin subclass or nil if no matching admin found.
78
127
  def admin_for(instance)
79
128
  Trestle.lookup_model(instance.class)
80
129
  end
130
+
131
+ private
132
+ def lookup_admin_from_options(instance: nil, admin: nil, fallback: nil, raise: true)
133
+ if admin
134
+ result = Trestle.lookup(admin)
135
+ elsif instance
136
+ result = Trestle.lookup_model(instance.class) || fallback
137
+ else
138
+ result = fallback
139
+ end
140
+
141
+ if result && result.is_a?(Class)
142
+ # Instantiate admin with current context
143
+ result.new(self)
144
+ elsif result
145
+ result
146
+ elsif raise
147
+ raise ActionController::UrlGenerationError,
148
+ "An admin could not be inferred. Please specify an admin using the :admin option."
149
+ end
150
+ end
81
151
  end
82
152
  end
@@ -4,12 +4,11 @@
4
4
  current_page: a page object for the currently displayed page
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
- remote: data-remote
8
7
  -%>
9
8
  <li class="page-item<% if current_page.first? %> disabled<% end %>">
10
9
  <% if current_page.first? %>
11
10
  <span class="page-link">&laquo;</span>
12
11
  <% else %>
13
- <%= link_to content_tag(:span, "&laquo;".html_safe), url, class: "page-link", remote: remote %>
12
+ <%= link_to tag.span("&laquo;".html_safe), url, class: "page-link" %>
14
13
  <% end %>
15
14
  </li>
@@ -3,7 +3,6 @@
3
3
  current_page: a page object for the currently displayed page
4
4
  total_pages: total number of pages
5
5
  per_page: number of items to fetch per page
6
- remote: data-remote
7
6
  -%>
8
7
  <li class="page-item gap disabled">
9
8
  <span class="page-link"><%= t('views.pagination.truncate').html_safe %></span>
@@ -4,12 +4,11 @@
4
4
  current_page: a page object for the currently displayed page
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
- remote: data-remote
8
7
  -%>
9
8
  <li class="page-item<% if current_page.last? %> disabled<% end %>">
10
9
  <% if current_page.last? %>
11
10
  <span class="page-link">&raquo;</span>
12
11
  <% else %>
13
- <%= link_to content_tag(:span, "&raquo;".html_safe), url, class: "page-link", remote: remote %>
12
+ <%= link_to tag.span("&raquo;".html_safe), url, class: "page-link" %>
14
13
  <% end %>
15
14
  </li>
@@ -5,8 +5,7 @@
5
5
  current_page: a page object for the currently displayed page
6
6
  total_pages: total number of pages
7
7
  per_page: number of items to fetch per page
8
- remote: data-remote
9
8
  -%>
10
9
  <li class="page-item<% if page.current? %> active<% end %>">
11
- <%= link_to content_tag(:span, page), url, class: "page-link", remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil %>
10
+ <%= link_to tag.span(page), url, class: "page-link", rel: page.next? ? 'next' : page.prev? ? 'prev' : nil %>
12
11
  </li>
@@ -3,7 +3,6 @@
3
3
  current_page: a page object for the currently displayed page
4
4
  total_pages: total number of pages
5
5
  per_page: number of items to fetch per page
6
- remote: data-remote
7
6
  paginator: the paginator that renders the pagination tags inside
8
7
  -%>
9
8
  <%= paginator.render do -%>
@@ -36,16 +36,16 @@
36
36
  <%= hook :head %>
37
37
  </head>
38
38
 
39
- <%= content_tag :body, body_attributes do %>
39
+ <%= tag.body(**body_attributes) do %>
40
40
  <div id="app-wrapper" class="app-wrapper" data-controller="wrapper" data-action="click->wrapper#hideMobileSidebar touchstart->wrapper#hideMobileSidebar" data-wrapper-mobile-sidebar-outlet=".app-sidebar">
41
41
  <%= render "trestle/shared/sidebar" %>
42
42
 
43
43
  <div class="app-container">
44
44
  <%= render "trestle/shared/header" %>
45
45
 
46
- <main class="app-main">
46
+ <div class="app-main">
47
47
  <%= yield %>
48
- </main>
48
+ </div>
49
49
 
50
50
  <%= render "trestle/shared/footer" %>
51
51
  </div>
@@ -1,5 +1,5 @@
1
- <%= content_tag(:div, modal_wrapper_attributes) do %>
2
- <%= content_tag(:div, modal_dialog_attributes) do %>
1
+ <%= tag.div(**modal_wrapper_attributes) do %>
2
+ <%= tag.div(**modal_dialog_attributes) do %>
3
3
  <%= yield %>
4
4
  <% end %>
5
5
  <% end %>
@@ -1,22 +1,26 @@
1
- <%= render "header", hide_breadcrumbs: local_assigns.fetch(:hide_breadcrumbs, false) if local_assigns.fetch(:header, true) %>
1
+ <turbo-frame id="main" data-turbo-action="advance">
2
+ <%= render "header", hide_breadcrumbs: local_assigns.fetch(:hide_breadcrumbs, false) if local_assigns.fetch(:header, true) %>
2
3
 
3
- <div class="main-content-area" data-scroll-target>
4
- <turbo-frame id="flash">
5
- <%= render "trestle/flash/flash" %>
6
- </turbo-frame>
4
+ <div class="main-content-area" data-scroll-target>
5
+ <turbo-frame id="flash">
6
+ <%= render "trestle/flash/flash" %>
7
+ </turbo-frame>
7
8
 
8
- <%= render "utilities" %>
9
- <%= render "tabs", data: { controller: "tabs tab-errors" } %>
9
+ <turbo-frame id="content" data-controller="reloadable" data-turbo-action="advance">
10
+ <%= render "utilities" %>
11
+ <%= render "tabs", data: { controller: "tabs tab-errors" } %>
10
12
 
11
- <% if local_assigns.fetch(:wrapper, true) %>
12
- <%= container do |c| %>
13
- <%= yield %>
13
+ <% if local_assigns.fetch(:wrapper, true) %>
14
+ <%= container do |c| %>
15
+ <%= yield %>
14
16
 
15
- <% c.sidebar do %>
16
- <%= content_for(:sidebar) %>
17
- <% end if content_for?(:sidebar) %>
18
- <% end %>
19
- <% else %>
20
- <%= yield %>
21
- <% end %>
22
- </div>
17
+ <% c.sidebar do %>
18
+ <%= content_for(:sidebar) %>
19
+ <% end if content_for?(:sidebar) %>
20
+ <% end %>
21
+ <% else %>
22
+ <%= yield %>
23
+ <% end %>
24
+ </turbo-frame>
25
+ </div>
26
+ </turbo-frame>
@@ -1,5 +1,5 @@
1
1
  <% if tabs.any? || render_sidebar_as_tab? -%>
2
- <%= content_tag :ul, class: "nav nav-tabs", data: local_assigns.fetch(:data, {}) do %>
2
+ <%= tag.ul(class: "nav nav-tabs", data: local_assigns.fetch(:data, {})) do %>
3
3
  <% tabs.each do |name, tab| %>
4
4
  <li class="nav-item">
5
5
  <%= link_to tab.label, "##{tab.id(("modal" if modal_request?))}", class: ["nav-link", ("active" if name == tabs.keys.first)], role: "tab", data: { bs_toggle: "tab" } %>
@@ -12,6 +12,8 @@
12
12
  <p><%= alert[:message] %></p>
13
13
  <% end %>
14
14
 
15
- <%= yield if block_given? %>
15
+ <% if local_assigns[:errors] %>
16
+ <%= render "trestle/flash/debug", errors: errors %>
17
+ <% end %>
16
18
  </div>
17
19
  </div>
@@ -1,7 +1,10 @@
1
1
  <% if flash[:message] -%>
2
- <%= render "trestle/flash/alert", html_class: "alert-success", icon: icon("alert-icon far fa-check-circle"), alert: normalize_flash_alert(flash[:message]) %>
2
+ <%= render "trestle/flash/alert", html_class: "alert-success",
3
+ icon: icon("alert-icon far fa-check-circle"),
4
+ alert: normalize_flash_alert(flash[:message]) %>
3
5
  <% elsif flash[:error] -%>
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", errors: Trestle::DebugErrors.new(instance.errors) if debug_form_errors? %>
6
- <% end %>
6
+ <%= render "trestle/flash/alert", html_class: "alert-danger",
7
+ icon: icon("alert-icon far fa-times-circle"),
8
+ alert: normalize_flash_alert(flash[:error]),
9
+ errors: (Trestle::DebugErrors.new(instance.errors) if debug_form_errors?) %>
7
10
  <% end -%>
@@ -1,12 +1,12 @@
1
- <%= content_tag(:dl, class: admin.scopes.classes) do %>
1
+ <%= tag.dl(class: admin.scopes.classes) do %>
2
2
  <% admin.scopes.grouped.each do |group, scopes| %>
3
- <%= content_tag(:dt, group, class: ["scope-group", ("scope-group-empty" if group.blank?)]) if admin.scopes.grouped? %>
3
+ <%= tag.dt(group, class: ["scope-group", ("scope-group-empty" if group.blank?)]) if admin.scopes.grouped? %>
4
4
 
5
5
  <dd>
6
6
  <ul class="scope-list">
7
7
  <% scopes.each do |scope| %>
8
8
  <li>
9
- <%= link_to persistent_params.merge(scope: (scope unless scope.active?(params))), class: ["scope", ("active" if scope.active?(params))] do %>
9
+ <%= link_to persistent_params.merge(scope: scope), class: ["scope", ("active" if scope.active?(params))] do %>
10
10
  <strong><%= scope.label %></strong>
11
11
  <% if scope.count? %>(<%= number_with_delimiter(scope.count(admin.collection(params))) %>)<% end %>
12
12
  <% end %>
@@ -1 +1,2 @@
1
1
  <%= turbo_stream.replace admin.build_instance({}, params), template: "trestle/resource/#{instance.persisted? ? "show" : "new"}" %>
2
+ <%= turbo_stream.reload if modal_request? && instance.persisted? %>
@@ -1 +1,3 @@
1
1
  <%= turbo_stream.close_modal instance %>
2
+ <%= turbo_stream.flash %>
3
+ <%= turbo_stream.reload %>
@@ -14,19 +14,17 @@
14
14
  <% end if admin.scopes.any? %>
15
15
 
16
16
  <%= render layout: "layout" do %>
17
- <%= index_turbo_frame do %>
18
- <% if hook?("resource.index.header") %>
19
- <header class="main-content-header">
20
- <%= hook("resource.index.header") %>
21
- </header>
22
- <% end %>
17
+ <% if hook?("resource.index.header") %>
18
+ <header class="main-content-header">
19
+ <%= hook("resource.index.header") %>
20
+ </header>
21
+ <% end %>
23
22
 
24
- <%= render "trestle/table/table", table: admin.table, collection: collection %>
23
+ <%= render "trestle/table/table", table: admin.table, collection: collection %>
25
24
 
26
- <footer class="main-content-footer">
27
- <%= hook("resource.index.footer") %>
25
+ <footer class="main-content-footer">
26
+ <%= hook("resource.index.footer") %>
28
27
 
29
- <%= pagination collection: collection, entry_name: admin.model_name, remote: admin.pagination_options[:ajax] %>
30
- </footer>
31
- <% end %>
28
+ <%= pagination collection: collection, entry_name: admin.model_name %>
29
+ </footer>
32
30
  <% end %>
@@ -1 +1,2 @@
1
1
  <%= turbo_stream.replace instance, template: "trestle/resource/show" %>
2
+ <%= turbo_stream.reload if modal_request? %>
@@ -12,27 +12,27 @@
12
12
  <div class="app-sidebar-inner" data-sidebar-target="inner">
13
13
  <nav class="app-nav" data-controller="navigation">
14
14
  <% Trestle.navigation(self).each do |group, items| %>
15
- <%= content_tag(:ul, class: ("collapsed" if group.present? && navigation_group_collapsed?(group)), data: { group: group.id }) do %>
15
+ <%= tag.ul(class: ("collapsed" if group.present? && navigation_group_collapsed?(group)), data: { group: group.id }) do %>
16
16
  <% if group.present? %>
17
- <li class="nav-header"><%= link_to content_tag(:span, group.label), "##{group.id}", data: { action: "navigation#toggle" } %></li>
17
+ <li class="nav-header"><%= link_to tag.span(group.label), "##{group.id}", data: { action: "navigation#toggle" } %></li>
18
18
  <% end %>
19
19
 
20
20
  <% items.each do |item| %>
21
- <%= content_tag(:li, class: ["nav-item", ("active" if current_navigation_item?(item))]) do %>
21
+ <%= tag.li(class: ["nav-item", ("active" if current_navigation_item?(item))]) do %>
22
22
  <%= link_to item.path, item.html_options.merge(data: { controller: "navigation-tooltip" }) do %>
23
23
  <%= icon("nav-icon", item.icon) %>
24
24
  <span class="nav-label" data-navigation-tooltip-target="label"><%= item.label %></span>
25
25
 
26
- <%= content_tag(:span, item.badge.text, class: ["badge", item.badge.html_class]) if item.badge? %>
26
+ <%= tag.span(item.badge.text, class: ["badge", item.badge.html_class]) if item.badge? %>
27
27
  <% end %>
28
28
  <% end %>
29
29
  <% end %>
30
30
  <% end %>
31
31
  <% end %>
32
32
  </nav>
33
-
34
- <button class="toggle-sidebar" data-action="sidebar#toggle">
35
- <span class="visually-hidden"><%= t("trestle.ui.toggle_sidebar", default: "Toggle sidebar") %></span>
36
- </button>
37
33
  </div>
34
+
35
+ <button class="toggle-sidebar" data-action="sidebar#toggle">
36
+ <span class="visually-hidden"><%= t("trestle.ui.toggle_sidebar", default: "Toggle sidebar") %></span>
37
+ </button>
38
38
  </aside>
@@ -1,12 +1,12 @@
1
1
  <% table = table.renderer(self) %>
2
2
 
3
3
  <div class="table-container">
4
- <%= content_tag(:table, id: table.id, class: table.classes, data: table.data) do %>
4
+ <%= tag.table(id: table.id, class: table.classes, data: table.data) do %>
5
5
  <% if table.header? %>
6
6
  <thead>
7
7
  <tr>
8
8
  <% table.columns.each do |column| %>
9
- <%= content_tag(:th, column.header, class: column.classes, data: column.data) %>
9
+ <%= tag.th(column.header, class: column.classes, data: column.data) %>
10
10
  <% end %>
11
11
  </tr>
12
12
  </thead>
@@ -8,9 +8,9 @@ pt-BR:
8
8
  page_entries_info:
9
9
  one_page:
10
10
  display_entries:
11
- zero: "Nenhum %{entry_name} encontrado"
12
- one: "Mostrando <strong>1</strong> %{entry_name}"
13
- other: "Mostrando <strong>all %{count}</strong> %{entry_name}"
11
+ zero: "Nenhum registro de %{entry_name} encontrado"
12
+ one: "Mostrando <strong>1 registro de</strong> %{entry_name}"
13
+ other: "Mostrando <strong>%{count} registros</strong> de %{entry_name}"
14
14
 
15
15
  more_pages:
16
16
  display_entries: "Mostrando %{entry_name} <strong>%{first}&nbsp;-&nbsp;%{last}</strong> de <b>%{total}</b>"
@@ -32,14 +32,14 @@ pt-BR:
32
32
 
33
33
  admin:
34
34
  titles:
35
- index: "Listando %{pluralized_model_name}"
36
- new: "Novo %{model_name}"
37
- edit: "Editando %{model_name}"
35
+ index: "Listando registros de %{pluralized_model_name}"
36
+ new: "Novo registro de %{model_name}"
37
+ edit: "Editando registro de %{model_name}"
38
38
 
39
39
  buttons:
40
- new: "Novo %{model_name}"
41
- save: "Salvar %{model_name}"
42
- delete: "Excluir %{model_name}"
40
+ new: "Novo registro de %{model_name}"
41
+ save: "Salvar registro de %{model_name}"
42
+ delete: "Excluir registro de %{model_name}"
43
43
 
44
44
  breadcrumbs:
45
45
  home: "Home"
@@ -48,7 +48,7 @@ pt-BR:
48
48
  create:
49
49
  success:
50
50
  title: "Sucesso!"
51
- message: "O %{model_name} foi criado com sucesso."
51
+ message: "O registro de %{model_name} foi criado com sucesso."
52
52
 
53
53
  failure:
54
54
  title: "Atenção!"
@@ -57,7 +57,7 @@ pt-BR:
57
57
  update:
58
58
  success:
59
59
  title: "Sucesso!"
60
- message: "O %{model_name} foi atualizado com sucesso."
60
+ message: "O registro de %{model_name} foi atualizado com sucesso."
61
61
 
62
62
  failure:
63
63
  title: "Atenção!"
@@ -66,11 +66,11 @@ pt-BR:
66
66
  destroy:
67
67
  success:
68
68
  title: "Sucesso!"
69
- message: "O %{model_name} foi deletado com sucesso."
69
+ message: "O registro de %{model_name} foi deletado com sucesso."
70
70
 
71
71
  failure:
72
72
  title: "Atenção!"
73
- message: "Falha ao excluir %{model_name}."
73
+ message: "O registro de %{model_name} não pôde ser deletado."
74
74
 
75
75
  table:
76
76
  headers:
@@ -6,23 +6,22 @@
6
6
  }
7
7
 
8
8
  &.grouped {
9
+ background: #fafafa;
10
+
11
+ dd {
12
+ padding: 0.375rem 0.5rem 0.375rem;
13
+ }
14
+
9
15
  @include media-breakpoint-up(md) {
10
16
  display: grid;
11
17
  grid-template-columns: auto 1fr;
12
18
  }
13
19
 
14
-
15
20
  @include media-breakpoint-down(md) {
16
21
  .scope-group-empty:first-child {
17
22
  display: none;
18
23
  }
19
24
  }
20
-
21
- background: #fafafa;
22
-
23
- dd {
24
- padding: 0.375rem 0.5rem 0.375rem;
25
- }
26
25
  }
27
26
 
28
27
  &.columns {
@@ -11,9 +11,9 @@ $theme-colors: (
11
11
  @each $color, $value in $theme-colors {
12
12
  --#{$color}: #{$value};
13
13
 
14
- --#{$color}-h: #{hue($value)};
15
- --#{$color}-s: #{saturation($value)};
16
- --#{$color}-l: #{lightness($value)};
14
+ --#{$color}-h: #{color.channel($value, "hue", $space: hsl)};
15
+ --#{$color}-s: #{color.channel($value, "saturation", $space: hsl)};
16
+ --#{$color}-l: #{color.channel($value, "lightness", $space: hsl)};
17
17
 
18
18
  --#{$color}-hue: var(--#{$color}-h);
19
19
  --#{$color}-saturation: var(--#{$color}-s);
@@ -102,6 +102,8 @@
102
102
  display: flex;
103
103
  flex-direction: column;
104
104
 
105
+ position: relative;
106
+
105
107
  overflow-x: hidden;
106
108
  overflow-y: auto;
107
109
 
@@ -23,7 +23,7 @@ export default class extends ApplicationController {
23
23
  }
24
24
 
25
25
  setup (selectedDates, dateStr, instance) {
26
- this._createClearButton(instance)
26
+ this.#createClearButton(instance)
27
27
  }
28
28
 
29
29
  get options () {
@@ -33,7 +33,7 @@ export default class extends ApplicationController {
33
33
  }
34
34
  }
35
35
 
36
- _createClearButton (instance) {
36
+ #createClearButton (instance) {
37
37
  if (this.element.dataset.allowClear) {
38
38
  const clearButton = document.createElement('button')
39
39