spree_admin 5.0.0.rc1 → 5.0.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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/spree/admin/components/_bulk_panel.scss +11 -1
  3. data/app/assets/stylesheets/spree/admin/components/_cards.scss +3 -4
  4. data/app/assets/stylesheets/spree/admin/components/_dropdowns.scss +1 -1
  5. data/app/assets/stylesheets/spree/admin/components/_main.scss +22 -5
  6. data/app/assets/stylesheets/spree/admin/components/_modals.scss +1 -1
  7. data/app/assets/stylesheets/spree/admin/global/_variables.scss +8 -2
  8. data/app/assets/stylesheets/spree/admin/shared/_base.scss +12 -1
  9. data/app/controllers/spree/admin/dashboard_controller.rb +4 -1
  10. data/app/controllers/spree/admin/products_controller.rb +1 -8
  11. data/app/controllers/spree/admin/storefront_controller.rb +1 -1
  12. data/app/controllers/spree/admin/translations_controller.rb +1 -1
  13. data/app/helpers/spree/admin/base_helper.rb +69 -63
  14. data/app/helpers/spree/admin/bulk_operations_helper.rb +86 -0
  15. data/app/helpers/spree/admin/modal_helper.rb +29 -0
  16. data/app/helpers/spree/admin/navigation_helper.rb +89 -11
  17. data/app/helpers/spree/admin/orders_helper.rb +0 -19
  18. data/app/helpers/spree/admin/stores_helper.rb +8 -36
  19. data/app/helpers/spree/admin/webhooks_subscribers_helper.rb +1 -1
  20. data/app/javascript/spree/admin/controllers/variants_form_controller.js +10 -3
  21. data/app/views/active_storage/_upload_form.html.erb +4 -8
  22. data/app/views/layouts/spree/admin.html.erb +4 -0
  23. data/app/views/spree/admin/assets/edit.html.erb +3 -8
  24. data/app/views/spree/admin/coupon_codes/index.html.erb +4 -6
  25. data/app/views/spree/admin/custom_domains/_custom_domains.html.erb +1 -1
  26. data/app/views/spree/admin/custom_domains/index.html.erb +1 -1
  27. data/app/views/spree/admin/customer_returns/index.html.erb +4 -17
  28. data/app/views/spree/admin/dashboard/_setup_progress.html.erb +4 -2
  29. data/app/views/spree/admin/dashboard/_sidebar.html.erb +2 -0
  30. data/app/views/spree/admin/dashboard/_top_products.html.erb +34 -24
  31. data/app/views/spree/admin/dashboard/analytics.html.erb +3 -1
  32. data/app/views/spree/admin/dashboard/show.html.erb +4 -8
  33. data/app/views/spree/admin/digital_assets/_table.html.erb +1 -1
  34. data/app/views/spree/admin/digital_assets/edit.html.erb +3 -11
  35. data/app/views/spree/admin/digital_assets/new.html.erb +3 -11
  36. data/app/views/spree/admin/exports/index.html.erb +22 -24
  37. data/app/views/spree/admin/exports/new.html.erb +3 -9
  38. data/app/views/spree/admin/line_items/new.html.erb +2 -5
  39. data/app/views/spree/admin/oauth_applications/index.html.erb +57 -58
  40. data/app/views/spree/admin/option_types/_filter.html.erb +1 -1
  41. data/app/views/spree/admin/option_types/index.html.erb +7 -11
  42. data/app/views/spree/admin/orders/_customer_summary.html.erb +0 -2
  43. data/app/views/spree/admin/orders/_filters.html.erb +3 -8
  44. data/app/views/spree/admin/orders/_header.html.erb +2 -0
  45. data/app/views/spree/admin/orders/_list.html.erb +2 -4
  46. data/app/views/spree/admin/orders/_summary.html.erb +1 -1
  47. data/app/views/spree/admin/orders/billing_address/create.turbo_stream.erb +3 -6
  48. data/app/views/spree/admin/orders/billing_address/edit.html.erb +3 -6
  49. data/app/views/spree/admin/orders/billing_address/new.html.erb +3 -6
  50. data/app/views/spree/admin/orders/billing_address/update.turbo_stream.erb +3 -6
  51. data/app/views/spree/admin/orders/contact_information/edit.html.erb +3 -6
  52. data/app/views/spree/admin/orders/customer_returns/edit.html.erb +1 -10
  53. data/app/views/spree/admin/orders/edit.html.erb +3 -5
  54. data/app/views/spree/admin/orders/index.html.erb +1 -1
  55. data/app/views/spree/admin/orders/return_authorizations/_form.html.erb +1 -1
  56. data/app/views/spree/admin/orders/return_authorizations/show.html.erb +45 -43
  57. data/app/views/spree/admin/orders/shipping_address/create.turbo_stream.erb +3 -6
  58. data/app/views/spree/admin/orders/shipping_address/edit.html.erb +3 -6
  59. data/app/views/spree/admin/orders/shipping_address/new.html.erb +3 -6
  60. data/app/views/spree/admin/orders/shipping_address/update.turbo_stream.erb +3 -6
  61. data/app/views/spree/admin/pages/_filters.html.erb +1 -1
  62. data/app/views/spree/admin/pages/edit.html.erb +2 -5
  63. data/app/views/spree/admin/pages/index.html.erb +4 -4
  64. data/app/views/spree/admin/payment_methods/index.html.erb +10 -8
  65. data/app/views/spree/admin/post_categories/index.html.erb +4 -6
  66. data/app/views/spree/admin/posts/_filters.html.erb +2 -7
  67. data/app/views/spree/admin/posts/_post.html.erb +1 -11
  68. data/app/views/spree/admin/posts/index.html.erb +5 -9
  69. data/app/views/spree/admin/products/_bulk_operations.html.erb +59 -94
  70. data/app/views/spree/admin/products/_filters.html.erb +13 -8
  71. data/app/views/spree/admin/products/_form.html.erb +3 -3
  72. data/app/views/spree/admin/products/_list.html.erb +2 -10
  73. data/app/views/spree/admin/products/_product.html.erb +1 -4
  74. data/app/views/spree/admin/products/bulk_modal.html.erb +3 -8
  75. data/app/views/spree/admin/products/edit.html.erb +3 -0
  76. data/app/views/spree/admin/products/form/_variants.html.erb +1 -0
  77. data/app/views/spree/admin/products/index.html.erb +5 -5
  78. data/app/views/spree/admin/promotion_actions/new.html.erb +7 -12
  79. data/app/views/spree/admin/promotion_rules/new.html.erb +7 -12
  80. data/app/views/spree/admin/promotions/_filters.html.erb +27 -0
  81. data/app/views/spree/admin/promotions/index.html.erb +7 -35
  82. data/app/views/spree/admin/properties/index.html.erb +10 -9
  83. data/app/views/spree/admin/refund_reasons/index.html.erb +37 -35
  84. data/app/views/spree/admin/refunds/edit.html.erb +3 -8
  85. data/app/views/spree/admin/reimbursement_types/index.html.erb +42 -40
  86. data/app/views/spree/admin/reports/_report.html.erb +1 -1
  87. data/app/views/spree/admin/return_authorization_reasons/index.html.erb +41 -41
  88. data/app/views/spree/admin/return_authorizations/_filters.html.erb +1 -1
  89. data/app/views/spree/admin/return_authorizations/_list.html.erb +1 -10
  90. data/app/views/spree/admin/return_authorizations/index.html.erb +1 -1
  91. data/app/views/spree/admin/roles/_form.html.erb +1 -1
  92. data/app/views/spree/admin/roles/index.html.erb +26 -24
  93. data/app/views/spree/admin/shared/_bulk_modal.html.erb +6 -7
  94. data/app/views/spree/admin/shared/_developers_nav.html.erb +2 -2
  95. data/app/views/spree/admin/shared/_filter_submit.html.erb +6 -0
  96. data/app/views/spree/admin/shared/_head.html.erb +3 -1
  97. data/app/views/spree/admin/shared/_modal.html.erb +2 -8
  98. data/app/views/spree/admin/shared/_multi_product_picker.html.erb +2 -4
  99. data/app/views/spree/admin/shared/_no_resource_found.html.erb +1 -1
  100. data/app/views/spree/admin/shared/_posts_tabs.html.erb +2 -2
  101. data/app/views/spree/admin/shared/_product_image.html.erb +1 -10
  102. data/app/views/spree/admin/shared/_refunds.html.erb +1 -1
  103. data/app/views/spree/admin/shared/_returns_and_refunds_nav.html.erb +3 -3
  104. data/app/views/spree/admin/shared/_shipping_nav.html.erb +2 -2
  105. data/app/views/spree/admin/shared/_stock_nav.html.erb +2 -2
  106. data/app/views/spree/admin/shared/_tax_nav.html.erb +2 -2
  107. data/app/views/spree/admin/shared/_user.html.erb +2 -2
  108. data/app/views/spree/admin/shared/_user_dropdown.html.erb +2 -2
  109. data/app/views/spree/admin/shared/sidebar/_orders_nav.html.erb +19 -29
  110. data/app/views/spree/admin/shared/sidebar/_products_nav.html.erb +6 -25
  111. data/app/views/spree/admin/shared/sidebar/_returns_nav.html.erb +8 -15
  112. data/app/views/spree/admin/shared/sidebar/_store_dropdown.html.erb +36 -7
  113. data/app/views/spree/admin/shared/sidebar/_store_nav.html.erb +28 -52
  114. data/app/views/spree/admin/shared/sidebar/_storefront_nav.html.erb +19 -26
  115. data/app/views/spree/admin/shared/sortable_tree/_taxonomy.html.erb +3 -23
  116. data/app/views/spree/admin/shipping_categories/index.html.erb +28 -26
  117. data/app/views/spree/admin/shipping_methods/_actions.html.erb +1 -1
  118. data/app/views/spree/admin/shipping_methods/index.html.erb +23 -21
  119. data/app/views/spree/admin/stock_items/_filters.html.erb +2 -7
  120. data/app/views/spree/admin/stock_items/index.html.erb +5 -8
  121. data/app/views/spree/admin/stock_locations/_stock_location.html.erb +16 -13
  122. data/app/views/spree/admin/stock_locations/index.html.erb +24 -21
  123. data/app/views/spree/admin/stock_transfers/_filters.html.erb +1 -1
  124. data/app/views/spree/admin/stock_transfers/_new_variant_modal.html.erb +3 -5
  125. data/app/views/spree/admin/stock_transfers/index.html.erb +6 -6
  126. data/app/views/spree/admin/store_credit_categories/_form.html.erb +1 -1
  127. data/app/views/spree/admin/store_credit_categories/edit.html.erb +6 -4
  128. data/app/views/spree/admin/store_credit_categories/index.html.erb +28 -24
  129. data/app/views/spree/admin/store_credits/index.html.erb +2 -2
  130. data/app/views/spree/admin/storefront/edit.html.erb +7 -9
  131. data/app/views/spree/admin/stores/form/_basic.html.erb +2 -2
  132. data/app/views/spree/admin/stores/form/_policies.html.erb +1 -1
  133. data/app/views/spree/admin/stores/new.html.erb +8 -6
  134. data/app/views/spree/admin/tax_categories/index.html.erb +24 -22
  135. data/app/views/spree/admin/tax_rates/index.html.erb +26 -24
  136. data/app/views/spree/admin/taxonomies/index.html.erb +4 -4
  137. data/app/views/spree/admin/taxonomies/show.html.erb +2 -2
  138. data/app/views/spree/admin/themes/_theme_preview_image.html.erb +1 -10
  139. data/app/views/spree/admin/themes/index.html.erb +2 -2
  140. data/app/views/spree/admin/translations/_translations_unavailable.html.erb +6 -8
  141. data/app/views/spree/admin/users/_filters.html.erb +2 -7
  142. data/app/views/spree/admin/users/_tabs.html.erb +4 -4
  143. data/app/views/spree/admin/users/_user.html.erb +1 -4
  144. data/app/views/spree/admin/users/bulk_modal.html.erb +3 -8
  145. data/app/views/spree/admin/users/index.html.erb +25 -58
  146. data/app/views/spree/admin/variants/_variant.html.erb +8 -2
  147. data/app/views/spree/admin/variants/form/_media_asset.html.erb +1 -7
  148. data/app/views/spree/admin/variants/form/_pricing.html.erb +5 -4
  149. data/app/views/spree/admin/webhooks_subscribers/_form.html.erb +1 -1
  150. data/app/views/spree/admin/webhooks_subscribers/index.html.erb +25 -22
  151. data/app/views/spree/admin/webhooks_subscribers/show.html.erb +3 -3
  152. data/app/views/spree/admin/zones/index.html.erb +34 -32
  153. data/config/locales/en.yml +1 -46
  154. data/lib/spree/admin/engine.rb +50 -0
  155. metadata +13 -14
  156. data/app/views/spree/admin/orders/_extra_filters.html.erb +0 -0
  157. data/app/views/spree/admin/products/_empty_list.html.erb +0 -1
  158. data/app/views/spree/admin/products/form/_extra_filters.html.erb +0 -0
  159. data/app/views/spree/admin/products/form/_extra_form.html.erb +0 -0
  160. data/app/views/spree/admin/products/form/_extra_form_sidebar.erb +0 -0
  161. data/app/views/spree/admin/stores/form/_custom.html.erb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c46d7797c6b7f96882ad96c43ea5a208adeca65c74816b1541a4eec33c6dbdd7
4
- data.tar.gz: 51593866ea9184c76e644c9e87691b94e183ea9bab9d50df371f97bc6a53ae59
3
+ metadata.gz: d55b4e39523cee4652dddb953445f27d15190d2cff8e40d3f012329c3e3612ec
4
+ data.tar.gz: e919c13188d0b35f8c17afaa52fd6e26ea2eae5713e2f5c7d2abb81ea7b7cb9e
5
5
  SHA512:
6
- metadata.gz: ab791c77bbf7061f800a622f19242dfea2ff77d5e11e6fca722ce06239462f7160bda2bfe31b983ef6fc440b0e9caa36802a986574a9c2ab7fee8dc50ab6b281
7
- data.tar.gz: 850bd370e9ec8cc75cf0017d6c866ea7f45c116e33d737977217a6c1e61070e5b2edb9f1275d23cca355cc190ad2c60d17cbf6d57baf49cebd82a6fd49e11303
6
+ metadata.gz: f7534f9a249beb83294f14d274920f12d7eb55504951365b0511e1efd980040a4811ffb9261af1aaf8074a60afb564176aa654c321bf771da211f629862e1281
7
+ data.tar.gz: 50b9265c84d615cade73af58b1af47ff41c043394ac10f9475d1a5cfdaf1398cf3bd274be2880264d846ad15e0ff9701e7b883cf1839b99eef34e198779db873
@@ -5,6 +5,9 @@
5
5
  background-color: $white;
6
6
  padding: 0.5rem;
7
7
  box-shadow: $dropdown-box-shadow;
8
+ animation: bounceInUp;
9
+ animation-duration: 0.5s;
10
+ gap: 0.75rem;
8
11
  }
9
12
 
10
13
  #bulk-panel {
@@ -28,4 +31,11 @@
28
31
  left: 16.66666667%;
29
32
  width: 83.33333333%;
30
33
  }
31
- }
34
+ }
35
+
36
+ .bulk-operations-counter {
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ gap: 0.25rem;
41
+ }
@@ -60,12 +60,11 @@
60
60
  }
61
61
 
62
62
  .card-lg {
63
- @extend .mb-3;
64
- @extend .bg-white;
65
-
63
+ margin-bottom: 1rem;
64
+ background-color: $white;
66
65
  border-radius: $border-radius-lg;
67
66
  border: 1px solid $card-border-color;
68
- padding: 1rem;
67
+ padding: 0;
69
68
  }
70
69
 
71
70
  .card-text {
@@ -26,7 +26,6 @@
26
26
  box-shadow: $dropdown-box-shadow;
27
27
 
28
28
  .dropdown-item, .dropdown-header {
29
- margin-bottom: 0.25rem;
30
29
  padding-left: $input-btn-padding-x;
31
30
  padding-right: $input-btn-padding-x;
32
31
  padding-top: $input-btn-padding-y;
@@ -34,6 +33,7 @@
34
33
  }
35
34
 
36
35
  .dropdown-item {
36
+ margin-bottom: 0.25rem;
37
37
  border-radius: $border-radius;
38
38
  display: flex;
39
39
  align-items: center;
@@ -54,26 +54,35 @@ turbo-frame[loading] .spinner-border, turbo-frame[busy] .spinner-border {
54
54
  border-radius: $border-radius;
55
55
  display: flex;
56
56
  align-items: center;
57
- padding-left: 0.5rem;
58
- padding-right: 0.5rem;
57
+ padding-left: 0.35rem;
58
+ padding-right: 0.35rem;
59
59
  padding-top: 0.35rem;
60
60
  padding-bottom: 0.35rem;
61
61
 
62
62
  .ti {
63
63
  font-size: 1rem;
64
64
  margin-right: 0.5rem;
65
+ border-radius: $border-radius-sm;
66
+ padding: 0.2rem 0.2rem;
65
67
  }
66
68
 
67
69
  &:hover {
68
- background-color: $gray-75;
70
+ background-color: $gray-50;
69
71
  }
70
72
  &.active {
71
73
  color: theme-color('primary');
72
- background-color: $gray-100;
74
+ background-color: $white;
75
+ box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 1px 2px -1px, rgba(0, 0, 0, 0.02) 0px 2px 4px 0px;
73
76
  font-weight: 500;
77
+
78
+ .ti {
79
+ background-color: theme-color('primary');
80
+ color: $white;
81
+ box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 1px 2px -1px, rgba(0, 0, 0, 0.02) 0px 2px 4px 0px;
82
+ }
74
83
  }
75
84
 
76
- .badge {
85
+ .badge:not(.badge-info) {
77
86
  @extend .badge-light;
78
87
  }
79
88
  }
@@ -96,6 +105,7 @@ turbo-frame[loading] .spinner-border, turbo-frame[busy] .spinner-border {
96
105
  &.active, &:active, &:focus {
97
106
  font-weight: 600;
98
107
  background-color: transparent !important;
108
+ box-shadow: none;
99
109
  }
100
110
  }
101
111
  }
@@ -146,3 +156,10 @@ turbo-frame[loading] .spinner-border, turbo-frame[busy] .spinner-border {
146
156
  top: 0.5rem;
147
157
  }
148
158
  }
159
+
160
+ .documentation-link-container {
161
+ font-size: $font-size-sm;
162
+ text-align: center;
163
+ margin-top: 2rem;
164
+ color: $gray-400;
165
+ }
@@ -25,7 +25,7 @@ body.modal-open {
25
25
  }
26
26
  .modal-footer {
27
27
  display: flex;
28
- justify-content: flex-end;
28
+ justify-content: space-between;
29
29
  padding: $modal-inner-padding;
30
30
  background-color: #FAFAFA;
31
31
  border-top: 1px solid $gray-50;
@@ -21,13 +21,16 @@ $black: #000000 !default;
21
21
  $blue: #0077ff !default;
22
22
  $white: #FFFFFF !default;
23
23
 
24
+ $action: #f1faff !default;
25
+ $action-border: #e2ecff !default;
26
+
24
27
  $theme-colors: (
25
28
  "white": $white,
26
29
  "black": $black,
27
30
  "primary": $primary,
28
31
  "secondary": rgba($blue, 0.1),
29
- "action": #f1faff,
30
- "action-border": #e2ecff,
32
+ "action": $action,
33
+ "action-border": $action-border,
31
34
  "active": $gray-25,
32
35
  "partial": #E2E8F0,
33
36
  "warning": #ffe17d,
@@ -67,6 +70,9 @@ $border-color: $gray-100 !default;
67
70
  $input-border-color: $gray-100 !default;
68
71
  $list-group-border-color: $border-color !default;
69
72
  $list-group-hover-bg: $gray-25 !default;
73
+ $list-group-active-bg: $action !default;
74
+ $list-group-active-border-color: $action-border !default;
75
+
70
76
  $thumbnail-border-color: $gray-100 !default;
71
77
  $hr-border-color: $border-color !default;
72
78
  $table-border-color: $gray-50 !default;
@@ -671,4 +671,15 @@ div.uppy-Root {
671
671
 
672
672
  .tooltip-inner {
673
673
  box-shadow: $dropdown-box-shadow;
674
- }
674
+ }
675
+
676
+ .avatar {
677
+ border-radius: 50%;
678
+ background-color: $gray-200;
679
+ color: $gray-500;
680
+ font-size: 1rem;
681
+ font-weight: 500;
682
+ display: flex;
683
+ align-items: center;
684
+ justify-content: center;
685
+ }
@@ -83,7 +83,10 @@ module Spree
83
83
 
84
84
  product_ids = line_items_grouped.map(&:variant_product_id).uniq.compact
85
85
 
86
- return if product_ids.empty?
86
+ if product_ids.empty?
87
+ @top_products = []
88
+ return
89
+ end
87
90
 
88
91
  products = current_store.products.with_deleted.includes(:master, :variants).where(id: product_ids)
89
92
 
@@ -68,10 +68,7 @@ module Spree
68
68
  # update the product again
69
69
  @product.slug = @product.slug_was if @product.slug.blank?
70
70
  invoke_callbacks(:update, :fails)
71
- respond_to do |format|
72
- format.html { render :edit, status: :unprocessable_entity }
73
- format.turbo_stream
74
- end
71
+ render :edit, status: :unprocessable_entity
75
72
  end
76
73
  end
77
74
 
@@ -294,10 +291,6 @@ module Spree
294
291
 
295
292
  private
296
293
 
297
- def update_turbo_stream_enabled?
298
- true
299
- end
300
-
301
294
  def variant_stock_includes
302
295
  [:images, { stock_items: :stock_location, option_values: :option_type }]
303
296
  end
@@ -26,7 +26,7 @@ module Spree
26
26
  :meta_description, :meta_title, :meta_keywords, :seo_robots,
27
27
  :facebook, :twitter, :instagram, :linkedin, :youtube, :tiktok, :pinterest,
28
28
  :storefront_custom_code_head, :storefront_custom_code_body_start,
29
- :storefront_custom_code_body_end
29
+ :storefront_custom_code_body_end, :storefront_password
30
30
  )
31
31
  end
32
32
 
@@ -66,7 +66,7 @@ module Spree
66
66
  @back_path = spree.edit_admin_taxonomy_path(@resource)
67
67
  when Spree::Store
68
68
  @resource_name = @resource.name
69
- @back_path = spree.edit_admin_store_path(@resource, section: "general-settings")
69
+ @back_path = spree.edit_admin_store_path(section: "general-settings")
70
70
  end
71
71
  end
72
72
  end
@@ -3,6 +3,12 @@ module Spree
3
3
  module BaseHelper
4
4
  include Spree::ImagesHelper
5
5
 
6
+ def render_admin_partials(section, options = {})
7
+ Rails.application.config.spree_admin.send(section).map do |partial|
8
+ render partial, options
9
+ end.join.html_safe
10
+ end
11
+
6
12
  def enterprise_edition?
7
13
  defined?(Vendo)
8
14
  end
@@ -15,37 +21,64 @@ module Spree
15
21
  @spree_update_available ||= !Rails.env.test? && spree_updater.update_available?
16
22
  end
17
23
 
24
+ # check if the current controller is a settings controller
25
+ # this is used to display different sidebar navigation for settings pages
26
+ # @return [Boolean]
18
27
  def settings_active?
19
- %w[stores zones shipping_methods oauth_applications
20
- payment_methods refund_reasons reimbursement_types
21
- shipping_categories store_credit_categories
22
- syncs tax_categories tax_rates webhooks accounts
23
- custom_domains audits exports imports return_authorization_reasons
24
- documents stripe_tax_registrations members subscriptions stock_locations webhooks_subscribers].include?(controller_name)
28
+ @settings_active || %w[stores zones shipping_methods oauth_applications
29
+ payment_methods refund_reasons reimbursement_types
30
+ shipping_categories store_credit_categories
31
+ syncs tax_categories tax_rates webhooks accounts
32
+ custom_domains audits exports imports return_authorization_reasons
33
+ documents stripe_tax_registrations members subscriptions stock_locations webhooks_subscribers].include?(controller_name)
25
34
  end
26
35
 
36
+ # @return [Array<String>] the available countries for checkout
27
37
  def available_countries_iso
28
38
  @available_countries_iso ||= current_store.countries_available_for_checkout.pluck(:iso)
29
39
  end
30
40
 
31
- def avatar_url_for(user)
41
+ # render an avatar for a user
42
+ # if user doesn't have an avatar, the user's initials will be displayed on a rounded background
43
+ # @param user [Spree::User] the user to render the avatar for
44
+ # @param options [Hash] the options for the avatar
45
+ # @option options [Integer] :width the width of the avatar, default: 128
46
+ # @option options [Integer] :height the height of the avatar, default: 128
47
+ # @option options [String] :class the CSS class(es) of the avatar, default: 'avatar'
48
+ # @return [String] the avatar
49
+ def render_avatar(user, options = {})
32
50
  return unless user.present?
33
51
 
52
+ options[:width] ||= 128
53
+ options[:height] ||= 128
54
+ options[:class] ||= 'avatar'
55
+
34
56
  if user.respond_to?(:avatar) && user.avatar.attached? && user.avatar.variable?
35
- main_app.cdn_image_url(
36
- user.avatar.variant(spree_image_variant_options(resize_to_fill: [128, 128]))
57
+ spree_image_tag(
58
+ user.avatar,
59
+ width: options[:width],
60
+ height: options[:height],
61
+ class: options[:class],
62
+ style: "width: #{options[:width]}px; height: #{options[:height]}px;"
37
63
  )
38
64
  else
39
- "https://eu.ui-avatars.com/api/?name=#{user.name&.initials}&background=random"
65
+ content_tag(:div, user.name&.initials, class: options[:class], style: "width: #{options[:width]}px; height: #{options[:height]}px;")
40
66
  end
41
67
  end
42
68
 
69
+ # returns the available display on options, eg backend, frontend, both
70
+ # @return [Array<Array<String, String>>] the available display on options
43
71
  def display_on_options
44
72
  Spree::DisplayOn::DISPLAY.map do |display_on|
45
73
  [Spree.t("admin.display_on_options.#{display_on}"), display_on]
46
74
  end
47
75
  end
48
76
 
77
+ # render an error message for a form field
78
+ # @param object [Spree::Model] the object to render the error message for
79
+ # @param method [String] the method to render the error message for
80
+ # @param options [Hash] the options for the error message
81
+ # @return [String] the error message
49
82
  def error_message_on(object, method, _options = {})
50
83
  object = convert_to_model(object)
51
84
  obj = object.respond_to?(:errors) ? object : instance_variable_get("@#{object}")
@@ -58,6 +91,10 @@ module Spree
58
91
  end
59
92
  end
60
93
 
94
+ # render an icon, using the tabler icons library
95
+ # @param icon_name [String] the name of the icon, eg: 'pencil', see: https://tabler.io/icons
96
+ # @param options [Hash] the options for the icon
97
+ # @return [String] the icon
61
98
  def icon(icon_name, options = {})
62
99
  if icon_name.ends_with?('.svg')
63
100
  icon_name = File.basename(icon_name, File.extname(icon_name))
@@ -77,42 +114,19 @@ module Spree
77
114
  content_tag :i, nil, class: "ti ti-#{icon_name} #{options[:class]}", style: styles
78
115
  end
79
116
 
117
+ # returns the flag emoji for a country
118
+ # @param iso [String] the ISO code of the country
119
+ # @return [String] the flag emoji
80
120
  def flag_emoji(iso)
81
121
  ::Country.new(iso).emoji_flag
82
122
  end
83
123
 
84
- def preference_field_tag(name, value, options)
85
- if options[:key] == :currency
86
- return select_tag(
87
- name,
88
- currency_options_for_select(
89
- value,
90
- current_store.supported_currencies.split(',')
91
- ),
92
- class: 'custom-select',
93
- disabled: current_store.supported_currencies.split(',').count == 1
94
- )
95
- end
96
-
97
- case options[:type]
98
- when :integer
99
- number_field_tag(name, value, preference_field_options(options))
100
- when :decimal
101
- number_field_tag(name, value, preference_field_options(options))
102
- when :boolean
103
- hidden_field_tag(name, 0, id: "#{name}_hidden") +
104
- check_box_tag(name, 1, value, preference_field_options(options))
105
- when :string
106
- text_field_tag(name, value, preference_field_options(options))
107
- when :password
108
- password_field_tag(name, value, preference_field_options(options))
109
- when :text
110
- text_area_tag(name, value, preference_field_options(options))
111
- else
112
- text_field_tag(name, value, preference_field_options(options))
113
- end
114
- end
115
-
124
+ # render a form field for a preference, according to the type of the preference (number, decimal, boolean, string, password, text)
125
+ # see https://spreecommerce.org/docs/developer/customization/model-preferences
126
+ # @param form [ActionView::Helpers::FormBuilder] the form builder
127
+ # @param field [String] the name of the field
128
+ # @param options [Hash] the options for the field
129
+ # @return [String] the preference field
116
130
  def preference_field_for(form, field, options)
117
131
  case options[:type]
118
132
  when :integer
@@ -132,6 +146,11 @@ module Spree
132
146
  end
133
147
  end
134
148
 
149
+ # returns the options for a preference field, according to the type of the preference (number, decimal, boolean, string, password, text)
150
+ # @param options [Hash] the options for the field
151
+ # @option options [Symbol] :type the type of the preference, eg. :integer, :decimal, :boolean, :string, :password, :text
152
+ # @option options [Boolean] :disabled whether the field is disabled
153
+ # @return [Hash] the options for the field
135
154
  def preference_field_options(options)
136
155
  field_options = case options[:type]
137
156
  when :integer
@@ -177,6 +196,10 @@ module Spree
177
196
  size: options[:size])
178
197
  end
179
198
 
199
+ # renders all the preference fields for an object
200
+ # @param object [Spree::TaxRate, Spree::Calculator, Spree::PaymentMethod, Spree::ShippingMethod, Spree::Store] the object to render the preference fields for
201
+ # @param form [ActionView::Helpers::FormBuilder] the form builder
202
+ # @return [String] the preference fields
180
203
  def preference_fields(object, form)
181
204
  return unless object.respond_to?(:preferences)
182
205
 
@@ -213,31 +236,14 @@ module Spree
213
236
  dom_id(record, 'spree')
214
237
  end
215
238
 
239
+ # renders a red dot with a * to indicate that a field is required
240
+ # @return [String] the required span tag
216
241
  def required_span_tag
217
242
  content_tag(:span, ' *', class: 'required font-weight-bold text-danger')
218
243
  end
219
244
 
220
- def external_page_preview_link(resource, options = {})
221
- resource_name = options[:name] || resource.class.name.demodulize
222
-
223
- url = if [Spree::Product, Spree::Post].include?(resource.class)
224
- spree_storefront_resource_url(resource, preview_id: resource.id)
225
- else
226
- spree_storefront_resource_url(resource)
227
- end
228
-
229
- link_to_with_icon(
230
- 'eye',
231
- Spree.t('admin.utilities.preview', name: resource_name),
232
- url,
233
- class: 'text-left dropdown-item', id: "adminPreview#{resource_name}", target: :blank, data: { turbo: false }
234
- )
235
- end
236
-
237
- def path_from_url(url)
238
- url.to_s.gsub('https://', '').gsub('http://', '')
239
- end
240
-
245
+ # returns the allowed file types for upload, according to the active storage configuration
246
+ # @return [Array<String>] the allowed file types for upload, eg. ['image/png', 'image/jpeg', 'image/gif', 'image/webp']
241
247
  def allowed_file_types_for_upload
242
248
  Rails.application.config.active_storage.web_image_content_types
243
249
  end
@@ -0,0 +1,86 @@
1
+ module Spree
2
+ module Admin
3
+ module BulkOperationsHelper
4
+ # render a checkbox to select all items for bulk operations
5
+ # @return [String]
6
+ def bulk_operations_select_all_checkbox
7
+ content_tag :div, class: "custom-control custom-checkbox ml-1" do
8
+ check_box_tag(
9
+ nil,
10
+ nil,
11
+ false,
12
+ id: "checkAllMasterCheckbox",
13
+ class: "custom-control-input",
14
+ data: { bulk_operation_target: "checkboxAll" }
15
+ ) +
16
+ content_tag(:label, content_tag(:span, ""), class: "custom-control-label", for: "checkAllMasterCheckbox")
17
+ end
18
+ end
19
+
20
+ # render a checkbox to select an item for bulk operations
21
+ # @param object [Spree::Product, Spree::User, Spree::Order]
22
+ # @return [String]
23
+ def bulk_operations_checkbox(object)
24
+ content_tag :div, class: "custom-control custom-checkbox ml-1" do
25
+ check_box_tag(
26
+ "ids[]",
27
+ object.id,
28
+ false,
29
+ class: "custom-control-input",
30
+ id: "ids_#{object.id}",
31
+ data: { bulk_operation_target: "checkbox" }
32
+ ) +
33
+ content_tag(:label, content_tag(:span, ""), class: "custom-control-label", for: "ids_#{object.id}")
34
+ end
35
+ end
36
+
37
+ # render a link to perform a bulk action
38
+ # @param text [String] the text of the link
39
+ # @param path [String] the path of the link
40
+ # @param options [Hash] the options of the link
41
+ # @option options [String] :icon the icon of the link
42
+ # @option options [String] :url the url to perform the bulk action to be set for the form in bulk modal
43
+ # @option options [String] :class the class of the link
44
+ # @option options [String] :data the data of the link
45
+ # @return [String]
46
+ def bulk_action_link(text, path, options = {})
47
+ options[:data] ||= {}
48
+ options[:data][:action] ||= 'click->bulk-operation#setBulkAction'
49
+ options[:data][:turbo_frame] ||= :bulk_modal
50
+ options[:data][:url] ||= options[:url]
51
+ options[:class] ||= 'btn btn-light'
52
+
53
+ if options[:icon]
54
+ text = icon(options[:icon]) + ' ' + text
55
+ end
56
+
57
+ content_tag :span, data: { toggle: 'modal', target: '#bulk-modal' } do
58
+ link_to text, path, options
59
+ end
60
+ end
61
+
62
+ # render a close button for the bulk modal
63
+ def bulk_operations_close_button
64
+ button_tag(
65
+ '',
66
+ type: 'button',
67
+ class: 'btn-close',
68
+ data: {
69
+ dismiss: 'modal',
70
+ aria_label: Spree.t(:close),
71
+ action: 'bulk-operation#cancel'
72
+ }
73
+ )
74
+ end
75
+
76
+ # render a counter for the bulk operations
77
+ # @return [String]
78
+ def bulk_operations_counter
79
+ content_tag(:span, class: 'bulk-operations-counter ml-1') do
80
+ content_tag(:strong, '', data: { bulk_operation_target: 'counter' }) +
81
+ Spree.t("admin.selected")
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,29 @@
1
+ module Spree
2
+ module Admin
3
+ module ModalHelper
4
+ # render a header for the modal
5
+ # @param title [String, Proc] the title of the modal
6
+ # @return [String]
7
+ def modal_header(title)
8
+ title = capture(&title) if block_given?
9
+ content_tag(:div, class: 'modal-header') do
10
+ content_tag(:h5, title, class: 'modal-title') + modal_close_button
11
+ end.html_safe
12
+ end
13
+
14
+ # render a close button for the modal
15
+ # @return [String]
16
+ def modal_close_button
17
+ button_tag('', type: 'button', class: 'btn-close', data: { dismiss: 'modal', aria_label: Spree.t(:close) }).html_safe
18
+ end
19
+
20
+ # render a discard button for the modal
21
+ # @return [String]
22
+ def modal_discard_button
23
+ button_tag(type: 'button', class: 'btn btn-light', data: { dismiss: 'modal' }) do
24
+ Spree.t('actions.discard')
25
+ end.html_safe
26
+ end
27
+ end
28
+ end
29
+ end