spree_admin 5.1.1 → 5.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/spree/admin/components/_bulk_panel.scss +58 -10
  3. data/app/assets/stylesheets/spree/admin/components/_buttons.scss +1 -16
  4. data/app/assets/stylesheets/spree/admin/components/_filters.scss +1 -1
  5. data/app/assets/stylesheets/spree/admin/components/_main.scss +46 -0
  6. data/app/assets/stylesheets/spree/admin/components/_tables.scss +24 -1
  7. data/app/assets/stylesheets/spree/admin/shared/_base.scss +7 -0
  8. data/app/controllers/spree/admin/dashboard_controller.rb +6 -0
  9. data/app/controllers/spree/admin/digital_assets_controller.rb +1 -0
  10. data/app/controllers/spree/admin/option_values_controller.rb +9 -0
  11. data/app/controllers/spree/admin/reports_controller.rb +14 -2
  12. data/app/controllers/spree/admin/storefront_controller.rb +1 -1
  13. data/app/helpers/spree/admin/base_helper.rb +10 -0
  14. data/app/helpers/spree/admin/bulk_operations_helper.rb +5 -3
  15. data/app/helpers/spree/admin/navigation_helper.rb +1 -1
  16. data/app/helpers/spree/admin/orders_filters_helper.rb +5 -4
  17. data/app/helpers/spree/admin/products_helper.rb +1 -1
  18. data/app/javascript/spree/admin/application.js +2 -0
  19. data/app/javascript/spree/admin/controllers/admin_controller.js +18 -0
  20. data/app/models/spree/admin/updater.rb +9 -5
  21. data/app/views/kaminari/admin-twitter-bootstrap-4/_first_page.html.erb +3 -5
  22. data/app/views/kaminari/admin-twitter-bootstrap-4/_last_page.html.erb +3 -5
  23. data/app/views/kaminari/admin-twitter-bootstrap-4/_next_page.html.erb +4 -5
  24. data/app/views/kaminari/admin-twitter-bootstrap-4/_paginator.html.erb +1 -1
  25. data/app/views/kaminari/admin-twitter-bootstrap-4/_prev_page.html.erb +4 -5
  26. data/app/views/layouts/spree/admin.html.erb +4 -1
  27. data/app/views/spree/admin/admin_users/show.html.erb +3 -2
  28. data/app/views/spree/admin/dashboard/_updater.html.erb +15 -5
  29. data/app/views/spree/admin/dashboard/getting_started.html.erb +1 -3
  30. data/app/views/spree/admin/dashboard/show.html.erb +2 -2
  31. data/app/views/spree/admin/integrations/index.html.erb +16 -16
  32. data/app/views/spree/admin/pages/index.html.erb +2 -1
  33. data/app/views/spree/admin/payment_methods/_form.html.erb +47 -54
  34. data/app/views/spree/admin/payment_methods/edit.html.erb +8 -4
  35. data/app/views/spree/admin/payment_methods/new.html.erb +7 -4
  36. data/app/views/spree/admin/products/_bulk_operations.html.erb +3 -2
  37. data/app/views/spree/admin/products/form/_variants.html.erb +1 -1
  38. data/app/views/spree/admin/profile/edit.html.erb +6 -8
  39. data/app/views/spree/admin/promotions/new.html.erb +51 -5
  40. data/app/views/spree/admin/shared/_content_header.html.erb +6 -5
  41. data/app/views/spree/admin/shared/_edit_resource_links.html.erb +1 -1
  42. data/app/views/spree/admin/shared/_header.html.erb +4 -3
  43. data/app/views/spree/admin/shared/_new_resource_links.html.erb +1 -1
  44. data/app/views/spree/admin/shared/_stock_nav.html.erb +2 -4
  45. data/app/views/spree/admin/shared/sidebar/_enterprise_edition_notice.html.erb +1 -1
  46. data/app/views/spree/admin/storefront/edit.html.erb +6 -6
  47. data/app/views/spree/admin/stores/edit.html.erb +0 -1
  48. data/app/views/spree/admin/stores/form/_checkout.html.erb +20 -24
  49. data/app/views/spree/admin/stores/form/_emails.html.erb +16 -18
  50. data/app/views/spree/admin/users/index.html.erb +2 -1
  51. data/app/views/spree/admin/variants/edit.html.erb +3 -6
  52. data/config/routes.rb +2 -1
  53. metadata +9 -9
  54. data/app/views/spree/admin/promotions/_form.html.erb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccc54cd595d9baf8f9e0f76c71b4682977fcac768b4ac6f5fe911fdd24c5d373
4
- data.tar.gz: 969cf056d3745ae281b89421893ccef0ade5f41bcabacd5bc81254cc8404aa7b
3
+ metadata.gz: edab2a99241e4db5473957b6cc3294ee86cd82c5d5c09b96c1674b88b74570b8
4
+ data.tar.gz: 8ae3514c6c648be6fd26e42c0bd8811f0dfd2a38a4cb06448791ad1b45e24db8
5
5
  SHA512:
6
- metadata.gz: 1dbf7da3b5c957af7f63e69425516a4ecf45901cba3364db52356e63d00ced386a9031863025c67a68a5519d93ad904a1f6af4c2facd6ef4544e8c8104733846
7
- data.tar.gz: bc6c07589f1aef8e58de7c5f025f98155cfa65a7bc6f0db41661ccd156cebf46d1134ff37192cbe9df8d77b66292ff7e0e6f21e0b3b205039f7098b25b38a2d6
6
+ metadata.gz: 1ce82d6b487a7a5db6e39c32e2b8da9e66a77331e2f79c22a1b402283ab7bb7b8bb105666c76c74c937e8f3a923d630cda21ddd1cd246b2b6ea89e5368ab12e8
7
+ data.tar.gz: 63efa374a215c5b3ccc8756e2ce0d0dc3397f4896cb899f47d494d3987b7fddf8792e367e28d814f95b6e9279a6b834258a438986f78cb61714a92fbeb49d1a3
@@ -3,14 +3,59 @@
3
3
  align-items: center;
4
4
  border-radius: $border-radius-lg;
5
5
  background-color: $white;
6
- padding: 0.5rem;
7
6
  box-shadow: $dropdown-box-shadow;
8
7
  animation: bounceInUp;
9
8
  animation-duration: 0.5s;
10
- gap: 0.5rem;
11
9
 
12
10
  .btn {
13
- height: 2rem;
11
+ border-width: 0;
12
+ padding-top: 0;
13
+ padding-bottom: 0;
14
+ height: 2.75rem;
15
+ border-radius: 0;
16
+ }
17
+
18
+ > * {
19
+ height: 2.75rem;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+
24
+ &:first-child {
25
+ border-top-left-radius: $border-radius-lg;
26
+ border-bottom-left-radius: $border-radius-lg;
27
+
28
+ .btn {
29
+ border-top-left-radius: $border-radius-lg;
30
+ border-bottom-left-radius: $border-radius-lg;
31
+ }
32
+ }
33
+
34
+ &:last-child {
35
+ border-top-right-radius: $border-radius-lg;
36
+ border-bottom-right-radius: $border-radius-lg;
37
+
38
+ .btn {
39
+ border-top-right-radius: $border-radius-lg;
40
+ border-bottom-right-radius: $border-radius-lg;
41
+ }
42
+ }
43
+
44
+ &:after {
45
+ content: '';
46
+ display: block;
47
+ width: 1px;
48
+ height: 100%;
49
+ background-color: $gray-50;
50
+ }
51
+
52
+ &:last-child:after {
53
+ display: none;
54
+ }
55
+ }
56
+
57
+ .btn-close {
58
+ width: 2.5rem;
14
59
  }
15
60
  }
16
61
 
@@ -38,11 +83,14 @@
38
83
  }
39
84
 
40
85
  .bulk-operations-counter {
41
- display: inline-flex;
42
- align-items: center;
43
- justify-content: center;
44
- gap: 0.25rem;
45
- margin-left: 1rem;
46
- margin-right: 1rem;
47
- border-left: 1px solid $gray-50;
86
+ padding-left: 1rem;
87
+ padding-right: 0;
88
+
89
+ .bulk-operations-counter-label {
90
+ margin-right: 1rem;
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ gap: 0.5rem;
95
+ }
48
96
  }
@@ -131,7 +131,7 @@ button[disabled] .show-when-enabled { display: none; }
131
131
 
132
132
  &:hover {
133
133
  opacity: 0.8 !important;
134
- background-color: $gray-100 !important;
134
+ background-color: $gray-50 !important;
135
135
  }
136
136
  }
137
137
 
@@ -184,18 +184,3 @@ button[disabled] .show-when-enabled { display: none; }
184
184
  min-width: 24px;
185
185
  height: 24px;
186
186
  }
187
-
188
- .page-link {
189
- @extend .btn;
190
- @extend .btn-sm;
191
- @extend .btn-light;
192
- @extend .ml-1;
193
- @extend .p-2;
194
-
195
- .ti {
196
- @extend .mr-0;
197
- }
198
- }
199
- .page-link.disabled {
200
- cursor: not-allowed;
201
- }
@@ -1,6 +1,6 @@
1
1
  .filter-wrap {
2
2
  padding: 0.5rem;
3
- border-bottom: 1px solid $gray-50;
3
+ border-bottom: 1px solid $table-border-color;
4
4
  gap: 0.5rem;
5
5
  position: sticky;
6
6
  top: $header-height;
@@ -25,6 +25,37 @@
25
25
  font-size: 1.25rem;
26
26
  }
27
27
 
28
+ #page-tabs {
29
+ border-bottom: 1px solid $border-color;
30
+ margin-bottom: 1rem;
31
+ padding-left: 1.5rem;
32
+ padding-right: 1.5rem;
33
+ margin-top: -1rem;
34
+
35
+ .nav {
36
+ gap: 1rem;
37
+ display: flex;
38
+ flex-wrap: nowrap;
39
+ overflow-x: auto;
40
+ padding-left: 0;
41
+ margin-bottom: -1px;
42
+
43
+ .nav-link {
44
+ border-radius: 0;
45
+ padding-bottom: 1rem;
46
+ padding-top: 1rem;
47
+ padding-left: 0rem;
48
+ padding-right: 0rem;
49
+
50
+ &.active {
51
+ background-color: transparent;
52
+ color: theme-color('primary');
53
+ font-weight: 600;
54
+ }
55
+ }
56
+ }
57
+ }
58
+
28
59
  .store-dropdown {
29
60
  display: flex;
30
61
  align-items: center;
@@ -245,6 +276,21 @@
245
276
  }
246
277
  }
247
278
 
279
+ #updater-notice {
280
+ background-color: $white;
281
+ width: 100%;
282
+ display: flex;
283
+ flex-direction: row;
284
+ gap: 1rem;
285
+ justify-content: flex-start;
286
+ align-items: center;
287
+ padding: 0.5rem 0.5rem;
288
+ border: 1px solid $border-color;
289
+ border-radius: $border-radius-lg;
290
+ box-shadow: $box-shadow-xs;
291
+ }
292
+
293
+
248
294
  .documentation-link-container {
249
295
  font-size: $font-size-sm;
250
296
  text-align: center;
@@ -207,7 +207,30 @@ td.actions {
207
207
  }
208
208
 
209
209
  .pagination-container {
210
- border-top: 1px solid $gray-50;
210
+ border-top: 1px solid $table-border-color;
211
211
  padding-top: 0.5rem;
212
212
  padding-bottom: 0.5rem;
213
+
214
+ position: sticky;
215
+ bottom: 0;
216
+ background-color: $card-bg;
217
+ z-index: 100;
218
+ border-bottom-left-radius: $border-radius-lg;
219
+ border-bottom-right-radius: $border-radius-lg;
220
+
221
+ .page-link {
222
+ @extend .btn;
223
+ @extend .btn-sm;
224
+ @extend .btn-light;
225
+ @extend .ml-1;
226
+ @extend .p-2;
227
+
228
+ .ti {
229
+ @extend .mr-0;
230
+ }
231
+ }
232
+ .page-item.disabled {
233
+ cursor: not-allowed;
234
+ opacity: 0.2;
235
+ }
213
236
  }
@@ -720,4 +720,11 @@ code {
720
720
  background-color: $code-bg;
721
721
  border-radius: $border-radius-sm;
722
722
  padding: 0.25rem 0.5rem;
723
+ }
724
+
725
+ kbd {
726
+ @extend .badge;
727
+ @extend .badge-light;
728
+ text-transform: lowercase;
729
+ box-shadow: $box-shadow-xs;
723
730
  }
@@ -64,6 +64,12 @@ module Spree
64
64
  redirect_back(fallback_location: spree.admin_dashboard_path)
65
65
  end
66
66
 
67
+ # PATCH /admin/dashboard/dismiss_updater_notice
68
+ def dismiss_updater_notice
69
+ session[:spree_updater_notice_dismissed] = { value: true, expires_at: 7.days.from_now }
70
+ redirect_back(fallback_location: spree.admin_dashboard_path)
71
+ end
72
+
67
73
  private
68
74
 
69
75
  def load_vendor
@@ -46,6 +46,7 @@ module Spree
46
46
  end
47
47
 
48
48
  def add_breadcrumbs
49
+ add_breadcrumb @product.name, spree.edit_admin_product_path(@product)
49
50
  add_breadcrumb Spree.t(:digital_assets), spree.admin_product_digital_assets_path(@product)
50
51
  end
51
52
  end
@@ -20,6 +20,15 @@ module Spree
20
20
  def permitted_resource_params
21
21
  params.require(:option_value).permit(permitted_option_value_attributes)
22
22
  end
23
+
24
+ # for select_options action, we only require read permission
25
+ def authorize_admin
26
+ if action == :select_options
27
+ authorize! :read, Spree::OptionValue
28
+ else
29
+ super
30
+ end
31
+ end
23
32
  end
24
33
  end
25
34
  end
@@ -31,7 +31,10 @@ module Spree
31
31
  end
32
32
 
33
33
  def build_resource
34
- model_class.new(store: current_store, date_from: params[:date_from], date_to: params[:date_to], currency: params[:currency])
34
+ model_class.new(store: current_store,
35
+ date_from: parse_date_param(params[:date_from]),
36
+ date_to: parse_date_param(params[:date_to])&.end_of_day,
37
+ currency: params[:currency])
35
38
  end
36
39
 
37
40
  def model_class
@@ -55,7 +58,16 @@ module Spree
55
58
  end
56
59
 
57
60
  def permitted_resource_params
58
- params.require(:report).permit(permitted_report_attributes)
61
+ attributes = params.require(:report).permit(permitted_report_attributes)
62
+ attributes[:date_from] = parse_date_param(attributes[:date_from]) if attributes[:date_from].present?
63
+ attributes[:date_to] = parse_date_param(attributes[:date_to])&.end_of_day if attributes[:date_to].present?
64
+ attributes
65
+ end
66
+
67
+ def parse_date_param(date_string)
68
+ return if date_string.blank?
69
+
70
+ date_string.to_date&.in_time_zone(current_timezone)
59
71
  end
60
72
  end
61
73
  end
@@ -29,7 +29,7 @@ module Spree
29
29
  :meta_description, :meta_title, :meta_keywords, :seo_robots,
30
30
  :facebook, :twitter, :instagram, :linkedin, :youtube, :tiktok, :pinterest,
31
31
  :storefront_custom_code_head, :storefront_custom_code_body_start,
32
- :storefront_custom_code_body_end, :storefront_password
32
+ :storefront_custom_code_body_end, :storefront_password, :spotify, :discord
33
33
  )
34
34
  end
35
35
 
@@ -13,6 +13,7 @@ module Spree
13
13
  defined?(SpreeEnterprise)
14
14
  end
15
15
 
16
+ # @return [Spree::Admin::Updater] the spree updater
16
17
  def spree_updater
17
18
  @spree_updater ||= Spree::Admin::Updater
18
19
  end
@@ -21,6 +22,15 @@ module Spree
21
22
  @spree_update_available ||= !Rails.env.test? && spree_updater.update_available?
22
23
  end
23
24
 
25
+ def updater_notice_dismissed?
26
+ dismissal_data = session[:spree_updater_notice_dismissed]
27
+ dismissal_data.is_a?(Hash) && dismissal_data['expires_at'].to_time > Time.current
28
+ end
29
+
30
+ def show_spree_updater_notice?
31
+ Spree::Admin::RuntimeConfig.admin_updater_enabled && can?(:manage, current_store) && spree_update_available? && !updater_notice_dismissed?
32
+ end
33
+
24
34
  # check if the current controller is a settings controller
25
35
  # this is used to display different sidebar navigation for settings pages
26
36
  # @return [Boolean]
@@ -82,9 +82,11 @@ module Spree
82
82
  # render a counter for the bulk operations
83
83
  # @return [String]
84
84
  def bulk_operations_counter
85
- content_tag(:span, class: 'bulk-operations-counter') do
86
- content_tag(:strong, '', data: { bulk_operation_target: 'counter' }) +
87
- Spree.t("admin.selected")
85
+ content_tag(:div, class: 'bulk-operations-counter') do
86
+ content_tag(:span, class: 'bulk-operations-counter-label') do
87
+ content_tag(:strong, '', data: { bulk_operation_target: 'counter' }) +
88
+ Spree.t("admin.selected")
89
+ end
88
90
  end
89
91
  end
90
92
  end
@@ -41,7 +41,7 @@ module Spree
41
41
  button_tag(raw(selected_option), class: 'btn btn-light btn-sm', data: { toggle: 'dropdown', expanded: false }) +
42
42
  content_tag(:div, class: 'dropdown-menu') do
43
43
  per_page_options.map do |option|
44
- link_to option, per_page_dropdown_params(option), class: "dropdown-item #{'active' if option == selected_option}"
44
+ link_to option, per_page_dropdown_params(option), class: "dropdown-item #{'active' if option.to_i == selected_option.to_i}"
45
45
  end.join.html_safe
46
46
  end
47
47
  end
@@ -14,7 +14,8 @@ module Spree
14
14
 
15
15
  if search_params[:created_at_gt].present?
16
16
  search_params[:created_at_gt] = begin
17
- Time.zone.parse(search_params[:created_at_gt]).beginning_of_day
17
+ # Firstly we parse to date to avoid issues with timezones because frontend sends time in local timezone
18
+ search_params[:created_at_gt].to_date&.in_time_zone(current_timezone)
18
19
  rescue StandardError
19
20
  ''
20
21
  end
@@ -22,7 +23,7 @@ module Spree
22
23
 
23
24
  if search_params[:created_at_lt].present?
24
25
  search_params[:created_at_lt] = begin
25
- Time.zone.parse(search_params[:created_at_lt]).end_of_day
26
+ search_params[:created_at_lt].to_date&.in_time_zone(current_timezone)&.end_of_day
26
27
  rescue StandardError
27
28
  ''
28
29
  end
@@ -30,7 +31,7 @@ module Spree
30
31
 
31
32
  if search_params[:completed_at_gt].present?
32
33
  search_params[:completed_at_gt] = begin
33
- Time.zone.parse(search_params[:completed_at_gt]).beginning_of_day
34
+ search_params[:completed_at_gt].to_date&.in_time_zone(current_timezone)
34
35
  rescue StandardError
35
36
  ''
36
37
  end
@@ -38,7 +39,7 @@ module Spree
38
39
 
39
40
  if search_params[:completed_at_lt].present?
40
41
  search_params[:completed_at_lt] = begin
41
- Time.zone.parse(search_params[:completed_at_lt]).end_of_day
42
+ search_params[:completed_at_lt].to_date&.in_time_zone(current_timezone)&.end_of_day
42
43
  rescue StandardError
43
44
  ''
44
45
  end
@@ -124,7 +124,7 @@ module Spree
124
124
  end
125
125
 
126
126
  def sorted_product_properties(product)
127
- product.product_properties.includes(:property).sort_by { |product_property| product_property.property.position }
127
+ product.product_properties.sort_by { |product_property| product_property.property.position }
128
128
  end
129
129
  end
130
130
  end
@@ -43,6 +43,7 @@ import Sortable from 'stimulus-sortable'
43
43
  import { Tabs } from 'tailwindcss-stimulus-components'
44
44
 
45
45
  import ActiveStorageUpload from 'spree/admin/controllers/active_storage_upload_controller'
46
+ import AdminController from 'spree/admin/controllers/admin_controller'
46
47
  import AssetUploaderController from 'spree/admin/controllers/asset_uploader_controller'
47
48
  import AutocompleteSelectController from 'spree/admin/controllers/autocomplete_select_controller'
48
49
  import BetterSliderController from 'spree/admin/controllers/better_slider_controller'
@@ -87,6 +88,7 @@ import EnableButtonController from 'spree/core/controllers/enable_button_control
87
88
  application.register('active-storage-upload', ActiveStorageUpload)
88
89
  application.register('address-autocomplete', AddressAutocompleteController)
89
90
  application.register('address-form', AddressFormController)
91
+ application.register('admin', AdminController)
90
92
  application.register('asset-uploader', AssetUploaderController)
91
93
  application.register('auto-submit', AutoSubmit)
92
94
  application.register('autocomplete-select', AutocompleteSelectController)
@@ -0,0 +1,18 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ['close', 'save']
5
+
6
+ close() {
7
+ if (this.hasCloseTarget) {
8
+ window.Turbo.visit(this.closeTarget.href)
9
+ }
10
+ }
11
+
12
+ save(event) {
13
+ if (this.hasSaveTarget) {
14
+ event.preventDefault()
15
+ this.saveTarget.click()
16
+ }
17
+ }
18
+ }
@@ -5,7 +5,7 @@ require 'uri'
5
5
  module Spree
6
6
  module Admin
7
7
  class Updater
8
- SPREE_CLOUD_UPDATES_URL = 'https://spreecloud.io/updates.json'
8
+ SPREE_CLOUD_UPDATES_URL = 'https://spreecloud.io/updates.json'.freeze
9
9
 
10
10
  @updates = nil
11
11
 
@@ -13,14 +13,18 @@ module Spree
13
13
  fetch_updates.any?
14
14
  end
15
15
 
16
- def self.latest_version
17
- @latest_version ||= fetch_updates.first&.dig('version')
16
+ def self.latest_release
17
+ @latest_release ||= fetch_updates.first
18
+ end
19
+
20
+ def self.current_release
21
+ @current_release ||= Spree.version
18
22
  end
19
23
 
20
24
  def self.fetch_updates
21
- @updates ||= Rails.cache.fetch("spree/admin/updater/fetch_updates/#{Spree.version}", expires_in: 1.day) do
25
+ @updates ||= Rails.cache.fetch("spree/admin/updater/fetch_updates/#{current_release}", expires_in: 1.day) do
22
26
  uri = URI(SPREE_CLOUD_UPDATES_URL)
23
- params = { version: Spree.version, environment: Rails.env, url: Spree::Store.current.url_or_custom_domain }
27
+ params = { version: current_release, environment: Rails.env, url: Spree::Store.current.url_or_custom_domain }
24
28
  uri.query = URI.encode_www_form(params)
25
29
 
26
30
  http = Net::HTTP.new(uri.host, uri.port)
@@ -6,8 +6,6 @@
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote -%>
8
8
 
9
- <% unless current_page.first? %>
10
- <li class="first page-item">
11
- <%= link_to_unless current_page.first?, icon('double-chevron-left', class: 'mb-0'), url, remote: remote, class: 'page-link', 'aria-label': 'First page' %>
12
- </li>
13
- <% end %>
9
+ <li class="first page-item <%= current_page.first? ? 'disabled' : '' %>">
10
+ <%= link_to icon('double-chevron-left', class: 'text-dark'), url, remote: remote, class: 'page-link', 'aria-label': 'First page' %>
11
+ </li>
@@ -6,8 +6,6 @@
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote -%>
8
8
 
9
- <% unless current_page.last? %>
10
- <li class="last next page-item"><%# "next" class present for border styling in twitter bootstrap %>
11
- <%= link_to_unless current_page.last?, icon('double-chevron-right', class: 'mb-0'), url, remote: remote, class: 'page-link', 'aria-label': 'Last page' %>
12
- </li>
13
- <% end %>
9
+ <li class="last next page-item <%= current_page.last? ? 'disabled' : '' %>">
10
+ <%= link_to icon('double-chevron-right', class: 'text-dark'), url, remote: remote, class: 'page-link', 'aria-label': 'Last page' %>
11
+ </li>
@@ -6,8 +6,7 @@
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote -%>
8
8
 
9
- <% unless current_page.last? %>
10
- <li class="next_page page-item">
11
- <%= link_to_unless current_page.last?, icon('chevron-right', class: 'text-dark'), url, rel: 'next', remote: remote, class: 'page-link', 'aria-label': 'Next page' %>
12
- </li>
13
- <% end %>
9
+ <li class="next page-item <%= current_page.last? ? 'disabled' : '' %>">
10
+ <%= link_to icon('chevron-right', class: 'text-dark'), url, rel: 'next', remote: remote, class: 'page-link', 'aria-label': 'Next page' %>
11
+ </li>
12
+
@@ -12,6 +12,6 @@
12
12
  <ul class="pagination d-inline-flex <%= pagination_class %> mb-0">
13
13
 
14
14
  <%= prev_page_tag %>
15
- <%= next_page_tag unless current_page.last? %>
15
+ <%= next_page_tag %>
16
16
  </ul>
17
17
  <% end %>
@@ -6,8 +6,7 @@
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote -%>
8
8
 
9
- <% unless current_page.first? %>
10
- <li class="prev page-item">
11
- <%= link_to_unless current_page.first?, icon('chevron-left', class: 'text-dark'), url, rel: 'prev', remote: remote, class: 'page-link', 'aria-label': 'Previous page' %>
12
- </li>
13
- <% end %>
9
+ <li class="prev page-item <%= current_page.first? ? 'disabled' : '' %>">
10
+ <%= link_to icon('chevron-left', class: 'text-dark'), url, rel: 'prev', remote: remote, class: 'page-link', 'aria-label': 'Previous page' %>
11
+ </li>
12
+
@@ -5,7 +5,10 @@
5
5
  <%= render "spree/admin/shared/custom_head" %>
6
6
  </head>
7
7
 
8
- <body class="admin min-vh-100 <%= controller_name %> <%= action_name %>">
8
+ <body class="admin min-vh-100 <%= controller_name %> <%= action_name %>"
9
+ data-controller="admin"
10
+ data-action="keydown.esc->admin#close keydown.ctrl+s->admin#save keydown.meta+s->admin#save"
11
+ >
9
12
  <%= render_admin_partials(:body_start_partials) %>
10
13
 
11
14
  <%= render "spree/admin/shared/header" %>
@@ -13,7 +13,7 @@
13
13
  <div class="card-header">
14
14
  <h5 class="card-title">
15
15
  <%= icon 'history', class: 'mr-1' %>
16
- <%= Spree.t(:audit_log) %>
16
+ <%= Spree.t('admin.audit_log') %>
17
17
  </h5>
18
18
  </div>
19
19
  <div class="card-body">
@@ -37,6 +37,7 @@
37
37
  <%= Spree.t(:email) %>
38
38
  <span>
39
39
  <%= @admin_user.email %>
40
+ <%= clipboard_component(@admin_user.email) %>
40
41
  </span>
41
42
  </li>
42
43
  <li class="list-group-item d-flex justify-content-between align-items-center">
@@ -101,7 +102,7 @@
101
102
  <li class="list-group-item d-flex justify-content-between align-items-center">
102
103
  <%= Spree.t(:invited_by) %>
103
104
  <span>
104
- <%= @admin_user.invited_by.name %>
105
+ <%= link_to @admin_user.invited_by.email, spree.admin_admin_user_path(@admin_user.invited_by), class: 'text-decoration-none', data: { turbo_frame: '_top' } %>
105
106
  </span>
106
107
  </li>
107
108
  <% end %>
@@ -1,9 +1,19 @@
1
- <% if Spree::Admin::RuntimeConfig.admin_updater_enabled && can?(:manage, current_store) && spree_update_available? %>
2
- <div class="alert alert-info">
3
- <div>
4
- <p class="mb-1">There's a newer version of Spree available.</p>
1
+ <% if show_spree_updater_notice? %>
2
+ <div id="updater-notice" class="mb-3">
3
+ <%= image_tag 'favicon_256x256.png', alt: 'Spree', width: 32, height: 32 %>
4
+ <div class="d-flex flex-column">
5
+ <p class="mb-1">
6
+ <strong>Spree <%= spree_updater.latest_release['name'] %></strong> is available.
7
+ <br />Your current version is <strong>Spree <%= spree_updater.current_release %></strong>.
8
+ </p>
5
9
 
6
- <%= link_to_with_icon 'settings-up', 'Update now', 'https://spreecommerce.org/docs/developer/upgrades', target: '_blank', class: 'btn btn-light btn-sm' %>
10
+ <% if spree_updater.latest_release['url'] %>
11
+ <div>
12
+ <%= external_link_to "View release notes", spree_updater.latest_release['url'], target: '_blank', class: 'btn btn-sm btn-link' %>
13
+ </div>
14
+ <% end %>
7
15
  </div>
16
+
17
+ <%= link_to '', spree.admin_dismiss_updater_notice_path, data: { turbo_method: :patch }, class: 'btn-close ml-auto' %>
8
18
  </div>
9
19
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <div class="row pt-3">
2
- <div class="col-lg-8 mb-4">
2
+ <div class="col-lg-8 offset-lg-2 mb-4">
3
3
  <h2 class="page-header-title">
4
4
  <%= Spree.t('admin.getting_started') %>
5
5
  </h2>
@@ -17,6 +17,4 @@
17
17
  <% end %>
18
18
  <% end %>
19
19
  </div>
20
- <div class="col-lg-4">
21
- </div>
22
20
  </div>
@@ -15,8 +15,8 @@
15
15
  <%= form_tag spree.admin_dashboard_analytics_path, method: :get, data: { turbo_frame: :analytics } do %>
16
16
  <%= hidden_field_tag :vendor_id, @vendor.id if @vendor.present? %>
17
17
  <%= render 'spree/admin/shared/calendar_range_picker',
18
- date_from_value: params[:date_from] || 1.month.ago.beginning_of_month,
19
- date_to_value: params[:date_to] || 1.month.ago.end_of_month,
18
+ date_from_value: params[:date_from] || 1.month.ago.end_of_day,
19
+ date_to_value: params[:date_to] || Time.zone.now.beginning_of_day,
20
20
  css_classes: "btn btn-sm border rounded-lg hover-light d-inline-flex align-items-center h-100 dropdown-toggle" %>
21
21
  <% end %>
22
22
  </div>