trestle 0.10.0 → 0.10.1

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