solidus_admin 0.0.2 → 0.2.0

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 (251) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.json +7 -0
  3. data/README.md +2 -2
  4. data/Rakefile +26 -0
  5. data/app/assets/builds/.keep +0 -0
  6. data/app/assets/builds/solidus_admin/tailwind.css +2799 -0
  7. data/app/assets/config/solidus_admin_manifest.js +1 -0
  8. data/app/assets/stylesheets/solidus_admin/application.tailwind.css +4 -0
  9. data/app/assets/stylesheets/solidus_admin/dark.css +12 -0
  10. data/app/assets/stylesheets/solidus_admin/dimmed.css +11 -0
  11. data/app/components/solidus_admin/adjustment_reasons/index/component.rb +43 -0
  12. data/app/components/solidus_admin/base_component.rb +29 -1
  13. data/app/components/solidus_admin/layout/feedback/component.html.erb +15 -0
  14. data/app/components/solidus_admin/layout/feedback/component.rb +4 -0
  15. data/app/components/solidus_admin/layout/feedback/component.yml +3 -0
  16. data/app/components/solidus_admin/layout/navigation/account/component.html.erb +74 -0
  17. data/app/components/solidus_admin/layout/navigation/account/component.js +16 -0
  18. data/app/components/solidus_admin/layout/navigation/account/component.rb +36 -0
  19. data/app/components/solidus_admin/{sidebar → layout/navigation}/component.html.erb +9 -9
  20. data/app/components/solidus_admin/layout/navigation/component.rb +26 -0
  21. data/app/components/solidus_admin/{sidebar → layout/navigation}/item/component.html.erb +5 -5
  22. data/app/components/solidus_admin/{sidebar → layout/navigation}/item/component.rb +2 -2
  23. data/app/components/solidus_admin/layout/page_helpers.rb +55 -0
  24. data/app/components/solidus_admin/{skip_link → layout/skip_link}/component.rb +2 -4
  25. data/app/components/solidus_admin/option_types/index/component.rb +71 -0
  26. data/app/components/solidus_admin/orders/cart/component.html.erb +77 -0
  27. data/app/components/solidus_admin/orders/cart/component.js +37 -0
  28. data/app/components/solidus_admin/orders/cart/component.rb +7 -0
  29. data/app/components/solidus_admin/orders/cart/component.yml +3 -0
  30. data/app/components/solidus_admin/orders/cart/result/component.html.erb +26 -0
  31. data/app/components/solidus_admin/orders/cart/result/component.rb +11 -0
  32. data/app/components/solidus_admin/orders/index/component.rb +92 -23
  33. data/app/components/solidus_admin/orders/index/component.yml +10 -4
  34. data/app/components/solidus_admin/orders/show/address/component.html.erb +67 -0
  35. data/app/components/solidus_admin/orders/show/address/component.js +9 -0
  36. data/app/components/solidus_admin/orders/show/address/component.rb +53 -0
  37. data/app/components/solidus_admin/orders/show/address/component.yml +14 -0
  38. data/app/components/solidus_admin/orders/show/component.html.erb +76 -0
  39. data/app/components/solidus_admin/orders/show/component.js +7 -0
  40. data/app/components/solidus_admin/orders/show/component.rb +40 -0
  41. data/app/components/solidus_admin/orders/show/component.yml +21 -0
  42. data/app/components/solidus_admin/orders/show/customer_search/component.html.erb +14 -0
  43. data/app/components/solidus_admin/orders/show/customer_search/component.js +14 -0
  44. data/app/components/solidus_admin/orders/show/customer_search/component.rb +7 -0
  45. data/app/components/solidus_admin/orders/show/customer_search/component.yml +2 -0
  46. data/app/components/solidus_admin/orders/show/customer_search/result/component.html.erb +17 -0
  47. data/app/components/solidus_admin/orders/show/customer_search/result/component.rb +11 -0
  48. data/app/components/solidus_admin/orders/show/email/component.html.erb +18 -0
  49. data/app/components/solidus_admin/orders/show/email/component.rb +15 -0
  50. data/app/components/solidus_admin/orders/show/email/component.yml +8 -0
  51. data/app/components/solidus_admin/orders/show/summary/component.html.erb +14 -0
  52. data/app/components/solidus_admin/orders/show/summary/component.rb +7 -0
  53. data/app/components/solidus_admin/orders/show/summary/component.yml +8 -0
  54. data/app/components/solidus_admin/payment_methods/index/component.rb +103 -0
  55. data/app/components/solidus_admin/payment_methods/index/component.yml +10 -0
  56. data/app/components/solidus_admin/products/index/component.rb +48 -41
  57. data/app/components/solidus_admin/products/index/component.yml +8 -7
  58. data/app/components/solidus_admin/products/show/component.html.erb +32 -38
  59. data/app/components/solidus_admin/products/show/component.rb +2 -0
  60. data/app/components/solidus_admin/products/show/component.yml +5 -5
  61. data/app/components/solidus_admin/products/status/component.rb +20 -18
  62. data/app/components/solidus_admin/products/status/component.yml +1 -0
  63. data/app/components/solidus_admin/products/stock/component.rb +38 -0
  64. data/app/components/solidus_admin/products/stock/component.yml +5 -0
  65. data/app/components/solidus_admin/promotion_categories/index/component.rb +56 -0
  66. data/app/components/solidus_admin/promotions/index/component.rb +104 -0
  67. data/app/components/solidus_admin/promotions/index/component.yml +10 -0
  68. data/app/components/solidus_admin/properties/index/component.rb +64 -0
  69. data/app/components/solidus_admin/refund_reasons/index/component.rb +53 -0
  70. data/app/components/solidus_admin/refunds_and_returns/component.rb +40 -0
  71. data/app/components/solidus_admin/refunds_and_returns/component.yml +3 -0
  72. data/app/components/solidus_admin/reimbursement_types/index/component.rb +27 -0
  73. data/app/components/solidus_admin/return_reasons/index/component.rb +42 -0
  74. data/app/components/solidus_admin/shipping/component.rb +30 -0
  75. data/app/components/solidus_admin/shipping/component.yml +3 -0
  76. data/app/components/solidus_admin/shipping_categories/index/component.rb +46 -0
  77. data/app/components/solidus_admin/shipping_methods/index/component.rb +61 -0
  78. data/app/components/solidus_admin/stock_items/edit/component.html.erb +89 -0
  79. data/app/components/solidus_admin/stock_items/edit/component.js +17 -0
  80. data/app/components/solidus_admin/stock_items/edit/component.rb +23 -0
  81. data/app/components/solidus_admin/stock_items/edit/component.yml +10 -0
  82. data/app/components/solidus_admin/stock_items/index/component.rb +174 -0
  83. data/app/components/solidus_admin/stock_items/index/component.yml +10 -0
  84. data/app/components/solidus_admin/stock_locations/index/component.rb +89 -0
  85. data/app/components/solidus_admin/stock_locations/index/component.yml +3 -0
  86. data/app/components/solidus_admin/store_credit_reasons/index/component.rb +52 -0
  87. data/app/components/solidus_admin/stores/index/component.rb +58 -0
  88. data/app/components/solidus_admin/tax_categories/index/component.rb +58 -0
  89. data/app/components/solidus_admin/tax_rates/index/component.rb +88 -0
  90. data/app/components/solidus_admin/taxes/component.rb +25 -0
  91. data/app/components/solidus_admin/taxes/component.yml +3 -0
  92. data/app/components/solidus_admin/taxonomies/index/component.rb +53 -0
  93. data/app/components/solidus_admin/ui/badge/component.rb +18 -8
  94. data/app/components/solidus_admin/ui/badge/component.yml +3 -0
  95. data/app/components/solidus_admin/ui/button/component.rb +32 -32
  96. data/app/components/solidus_admin/ui/details_list/component.html.erb +10 -0
  97. data/app/components/solidus_admin/ui/details_list/component.rb +7 -0
  98. data/app/components/solidus_admin/ui/dropdown/component.html.erb +50 -0
  99. data/app/components/solidus_admin/ui/dropdown/component.js +16 -0
  100. data/app/components/solidus_admin/ui/dropdown/component.rb +28 -0
  101. data/app/components/solidus_admin/ui/dropdown/component.yml +2 -0
  102. data/app/components/solidus_admin/ui/forms/address/component.html.erb +36 -0
  103. data/app/components/solidus_admin/ui/forms/address/component.js +34 -0
  104. data/app/components/solidus_admin/ui/forms/address/component.rb +14 -0
  105. data/app/components/solidus_admin/ui/forms/field/component.html.erb +5 -4
  106. data/app/components/solidus_admin/ui/forms/field/component.rb +53 -15
  107. data/app/components/solidus_admin/ui/forms/input/component.rb +11 -5
  108. data/app/components/solidus_admin/ui/forms/search/component.html.erb +52 -0
  109. data/app/components/solidus_admin/ui/forms/search/component.js +116 -0
  110. data/app/components/solidus_admin/ui/forms/search/component.rb +8 -0
  111. data/app/components/solidus_admin/ui/forms/search/component.yml +4 -0
  112. data/app/components/solidus_admin/ui/forms/search/result/component.rb +12 -0
  113. data/app/components/solidus_admin/ui/forms/search_field/component.html.erb +20 -0
  114. data/app/{javascript/solidus_admin/controllers/hello_controller.js → components/solidus_admin/ui/forms/search_field/component.js} +4 -2
  115. data/app/components/solidus_admin/ui/forms/search_field/component.rb +10 -0
  116. data/app/components/solidus_admin/ui/forms/search_field/component.yml +2 -0
  117. data/app/components/solidus_admin/ui/forms/switch/component.rb +27 -31
  118. data/app/components/solidus_admin/ui/forms/switch_field/component.html.erb +20 -0
  119. data/app/components/solidus_admin/ui/forms/switch_field/component.rb +11 -0
  120. data/app/components/solidus_admin/ui/icon/component.rb +4 -0
  121. data/app/components/solidus_admin/ui/modal/component.html.erb +37 -0
  122. data/app/components/solidus_admin/ui/modal/component.rb +12 -0
  123. data/app/components/solidus_admin/ui/modal/component.yml +2 -0
  124. data/app/components/solidus_admin/ui/pages/index/component.html.erb +30 -0
  125. data/app/components/solidus_admin/ui/pages/index/component.rb +119 -0
  126. data/app/components/solidus_admin/ui/pages/index/component.yml +4 -0
  127. data/app/components/solidus_admin/ui/panel/component.html.erb +26 -12
  128. data/app/components/solidus_admin/ui/panel/component.rb +17 -0
  129. data/app/components/solidus_admin/ui/panel/component.yml +1 -3
  130. data/app/components/solidus_admin/ui/resource_item/component.html.erb +10 -0
  131. data/app/components/solidus_admin/ui/resource_item/component.rb +9 -0
  132. data/app/components/solidus_admin/ui/tab/component.rb +9 -8
  133. data/app/components/solidus_admin/ui/table/component.html.erb +147 -135
  134. data/app/components/solidus_admin/ui/table/component.js +56 -17
  135. data/app/components/solidus_admin/ui/table/component.rb +94 -70
  136. data/app/components/solidus_admin/ui/table/component.yml +0 -1
  137. data/app/components/solidus_admin/ui/table/ransack_filter/component.html.erb +72 -0
  138. data/app/components/solidus_admin/ui/table/ransack_filter/component.js +73 -0
  139. data/app/components/solidus_admin/ui/table/ransack_filter/component.rb +68 -0
  140. data/app/components/solidus_admin/ui/table/ransack_filter/component.yml +3 -0
  141. data/app/components/solidus_admin/ui/table/toolbar/component.rb +21 -0
  142. data/app/components/solidus_admin/ui/thumbnail/component.rb +46 -0
  143. data/app/components/solidus_admin/ui/toast/component.html.erb +9 -5
  144. data/app/components/solidus_admin/ui/toast/component.js +9 -6
  145. data/app/components/solidus_admin/ui/toast/component.rb +2 -2
  146. data/app/components/solidus_admin/ui/toggletip/component.html.erb +14 -10
  147. data/app/components/solidus_admin/ui/toggletip/component.js +22 -4
  148. data/app/components/solidus_admin/ui/toggletip/component.rb +8 -85
  149. data/app/components/solidus_admin/users/index/component.rb +96 -0
  150. data/app/components/solidus_admin/users/index/component.yml +15 -0
  151. data/app/components/solidus_admin/zones/index/component.rb +63 -0
  152. data/app/controllers/solidus_admin/addresses_controller.rb +92 -0
  153. data/app/controllers/solidus_admin/adjustment_reasons_controller.rb +40 -0
  154. data/app/controllers/solidus_admin/base_controller.rb +1 -0
  155. data/app/controllers/solidus_admin/controller_helpers/authorization.rb +5 -1
  156. data/app/controllers/solidus_admin/controller_helpers/locale.rb +2 -2
  157. data/app/controllers/solidus_admin/controller_helpers/search.rb +48 -0
  158. data/app/controllers/solidus_admin/controller_helpers/theme.rb +30 -0
  159. data/app/controllers/solidus_admin/countries_controller.rb +12 -0
  160. data/app/controllers/solidus_admin/customers_controller.rb +29 -0
  161. data/app/controllers/solidus_admin/line_items_controller.rb +45 -0
  162. data/app/controllers/solidus_admin/option_types_controller.rb +46 -0
  163. data/app/controllers/solidus_admin/orders_controller.rb +104 -7
  164. data/app/controllers/solidus_admin/payment_methods_controller.rb +52 -0
  165. data/app/controllers/solidus_admin/products_controller.rb +26 -17
  166. data/app/controllers/solidus_admin/promotion_categories_controller.rb +29 -0
  167. data/app/controllers/solidus_admin/promotions_controller.rb +46 -0
  168. data/app/controllers/solidus_admin/properties_controller.rb +33 -0
  169. data/app/controllers/solidus_admin/refund_reasons_controller.rb +40 -0
  170. data/app/controllers/solidus_admin/reimbursement_types_controller.rb +31 -0
  171. data/app/controllers/solidus_admin/return_reasons_controller.rb +40 -0
  172. data/app/controllers/solidus_admin/shipping_categories_controller.rb +40 -0
  173. data/app/controllers/solidus_admin/shipping_methods_controller.rb +40 -0
  174. data/app/controllers/solidus_admin/stock_items_controller.rb +67 -0
  175. data/app/controllers/solidus_admin/stock_locations_controller.rb +40 -0
  176. data/app/controllers/solidus_admin/store_credit_reasons_controller.rb +40 -0
  177. data/app/controllers/solidus_admin/stores_controller.rb +40 -0
  178. data/app/controllers/solidus_admin/tax_categories_controller.rb +40 -0
  179. data/app/controllers/solidus_admin/tax_rates_controller.rb +40 -0
  180. data/app/controllers/solidus_admin/taxonomies_controller.rb +46 -0
  181. data/app/controllers/solidus_admin/users_controller.rb +50 -0
  182. data/app/controllers/solidus_admin/zones_controller.rb +40 -0
  183. data/app/javascript/solidus_admin/controllers/components.js +3 -1
  184. data/app/javascript/solidus_admin/controllers/confirm_controller.js +21 -0
  185. data/app/javascript/solidus_admin/controllers/details_click_outside_controller.js +12 -0
  186. data/app/javascript/solidus_admin/controllers/readonly_when_submitting_controller.js +17 -0
  187. data/app/javascript/solidus_admin/controllers/sortable_controller.js +33 -0
  188. data/app/views/layouts/solidus_admin/application.html.erb +16 -10
  189. data/app/views/layouts/solidus_admin/preview.html.erb +2 -1
  190. data/app/views/solidus_admin/base/unauthorized.html.erb +4 -0
  191. data/config/importmap.rb +2 -0
  192. data/config/initializers/view_component.rb +20 -0
  193. data/config/locales/adjustment_reasons.en.yml +6 -0
  194. data/config/locales/customers.en.yml +7 -0
  195. data/config/locales/errors.en.yml +7 -0
  196. data/config/locales/line_items.en.yml +9 -0
  197. data/config/locales/{main_nav.en.yml → menu_item.en.yml} +8 -2
  198. data/config/locales/option_types.en.yml +6 -0
  199. data/config/locales/orders.en.yml +9 -0
  200. data/config/locales/payment_methods.en.yml +6 -0
  201. data/config/locales/promotion_categories.en.yml +6 -0
  202. data/config/locales/promotions.en.yml +6 -0
  203. data/config/locales/properties.en.yml +6 -0
  204. data/config/locales/refund_reasons_.en.yml +6 -0
  205. data/config/locales/reimbursement_types.en.yml +4 -0
  206. data/config/locales/return_reasons.en.yml +6 -0
  207. data/config/locales/shipping_categories.en.yml +6 -0
  208. data/config/locales/shipping_methods.en.yml +6 -0
  209. data/config/locales/stock_items.en.yml +4 -0
  210. data/config/locales/stock_locations.en.yml +6 -0
  211. data/config/locales/store_credit_reasons.en.yml +6 -0
  212. data/config/locales/stores.en.yml +6 -0
  213. data/config/locales/tax_categories.en.yml +6 -0
  214. data/config/locales/tax_rates.en.yml +6 -0
  215. data/config/locales/taxonomies.en.yml +6 -0
  216. data/config/locales/users.en.yml +6 -0
  217. data/config/locales/zones.en.yml +6 -0
  218. data/config/routes.rb +50 -3
  219. data/config/tailwind.config.js +119 -0
  220. data/docs/{customizing_main_navigation.md → customizing_menu_items.md} +2 -2
  221. data/docs/customizing_tailwindcss.md +57 -0
  222. data/docs/customizing_view_components.md +17 -38
  223. data/lib/generators/solidus_admin/install/install_generator.rb +13 -4
  224. data/lib/generators/solidus_admin/install/templates/config/initializers/{solidus_admin.rb → solidus_admin.rb.tt} +10 -14
  225. data/lib/solidus_admin/admin_resources.rb +23 -0
  226. data/lib/solidus_admin/configuration.rb +95 -67
  227. data/lib/solidus_admin/install_tailwindcss.rb +102 -0
  228. data/lib/solidus_admin/{main_nav_item.rb → menu_item.rb} +2 -2
  229. data/lib/solidus_admin/version.rb +1 -1
  230. data/lib/solidus_admin.rb +1 -2
  231. data/lib/tasks/tailwind.rake +10 -0
  232. data/solidus_admin.gemspec +3 -4
  233. metadata +193 -50
  234. data/app/assets/stylesheets/solidus_admin/application.tailwind.css.erb +0 -35
  235. data/app/components/solidus_admin/feedback/component.html.erb +0 -11
  236. data/app/components/solidus_admin/feedback/component.rb +0 -4
  237. data/app/components/solidus_admin/feedback/component.yml +0 -5
  238. data/app/components/solidus_admin/orders/index/component.html.erb +0 -31
  239. data/app/components/solidus_admin/products/index/component.html.erb +0 -30
  240. data/app/components/solidus_admin/sidebar/account_nav/component.html.erb +0 -67
  241. data/app/components/solidus_admin/sidebar/account_nav/component.rb +0 -15
  242. data/app/components/solidus_admin/sidebar/component.rb +0 -21
  243. data/app/components/solidus_admin/ui/panel/component.js +0 -14
  244. data/config/solidus_admin/tailwind.config.js.erb +0 -95
  245. data/docs/customizing_tailwind.md +0 -78
  246. data/lib/solidus_admin/tailwindcss.rb +0 -58
  247. data/lib/tasks/tailwindcss.rake +0 -55
  248. /data/app/components/solidus_admin/{sidebar/account_nav → layout/navigation/account}/component.yml +0 -0
  249. /data/app/components/solidus_admin/{sidebar → layout/navigation}/component.js +0 -0
  250. /data/app/components/solidus_admin/{sidebar → layout/navigation}/component.yml +0 -0
  251. /data/app/components/solidus_admin/{skip_link → layout/skip_link}/component.yml +0 -0
@@ -0,0 +1,3 @@
1
+ en:
2
+ title: "Cart"
3
+ search_placeholder: "Find a variant by name or SKU"
@@ -0,0 +1,26 @@
1
+ <%= render component('ui/forms/search/result').new do %>
2
+ <%= form_for(@order.line_items.build(variant: @variant), url: solidus_admin.order_line_items_path(@order), method: :post, html: {
3
+ "data-controller": "readonly-when-submitting",
4
+ class: "flex items-center",
5
+ }) do |f| %>
6
+ <%= hidden_field_tag("#{f.object_name}[variant_id]", @variant.id) %>
7
+ <div class="flex gap-2 grow">
8
+ <%= render component("ui/thumbnail").new(
9
+ src: @image&.url(:small),
10
+ alt: @variant.name
11
+ ) %>
12
+ <div class="flex-col">
13
+ <div class="leading-5 text-black font-semibold text-sm"><%= @variant.name %></div>
14
+ <div class="leading-5 text-gray-500 font-normal text-sm">
15
+ SKU:
16
+ <%= @variant.sku %>
17
+ <%= @variant.options_text.presence&.prepend("- ") %>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <div class="flex gap-2 items-center">
22
+ <span class="text-gray-500 font-normal text-sm"><%= render component("products/stock").from_variant(@variant) %></span>
23
+ <span class="text-black font-normal text-sm"><%= @variant.display_price.to_html %></span>
24
+ </div>
25
+ <% end %>
26
+ <% end %>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Cart::Result::Component < SolidusAdmin::BaseComponent
4
+ with_collection_parameter :variant
5
+
6
+ def initialize(order:, variant:)
7
+ @order = order
8
+ @variant = variant
9
+ @image = @variant.images.first || @variant.product.gallery.images.first
10
+ end
11
+ end
@@ -1,34 +1,89 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
4
- def initialize(page:)
5
- @page = page
3
+ class SolidusAdmin::Orders::Index::Component < SolidusAdmin::UI::Pages::Index::Component
4
+ def model_class
5
+ Spree::Order
6
6
  end
7
7
 
8
- class_attribute :fade_row_proc, default: ->(order) { order.paid? && order.shipped? }
8
+ def search_key
9
+ :number_or_shipments_number_or_bill_address_name_or_email_cont
10
+ end
11
+
12
+ def search_url
13
+ solidus_admin.orders_path(scope: params[:scope])
14
+ end
9
15
 
10
- def title
11
- Spree::Order.model_name.human.pluralize
16
+ def row_url(order)
17
+ spree.edit_admin_order_path(order)
12
18
  end
13
19
 
14
- def prev_page_link
15
- @page.first? ? nil : solidus_admin.url_for(host: request.host, port: request.port, **request.params, page: @page.number - 1)
20
+ def row_fade(order)
21
+ order.paid? && order.shipped?
16
22
  end
17
23
 
18
- def next_page_link
19
- @page.last? ? nil : solidus_admin.url_for(host: request.host, port: request.port, **request.params, page: @page.next_param)
24
+ def page_actions
25
+ render component("ui/button").new(
26
+ tag: :a,
27
+ text: t('.add'),
28
+ href: spree.new_admin_order_path,
29
+ icon: "add-line",
30
+ )
20
31
  end
21
32
 
22
- def batch_actions
23
- []
33
+ def scopes
34
+ [
35
+ { label: t('.scopes.complete'), name: 'completed', default: true },
36
+ { label: t('.scopes.in_progress'), name: 'in_progress' },
37
+ { label: t('.scopes.returned'), name: 'returned' },
38
+ { label: t('.scopes.canceled'), name: 'canceled' },
39
+ { label: t('.scopes.all_orders'), name: 'all' },
40
+ ]
24
41
  end
25
42
 
26
43
  def filters
27
44
  [
28
45
  {
29
- name: 'q[completed_at_not_null]',
30
- value: 1,
31
- label: t('.filters.only_show_complete_orders'),
46
+ presentation: t('.filters.status'),
47
+ combinator: 'or',
48
+ attribute: "state",
49
+ predicate: "eq",
50
+ options: Spree::Order.state_machines[:state].states.map do |state|
51
+ [
52
+ state.value.titleize,
53
+ state.value
54
+ ]
55
+ end
56
+ },
57
+ {
58
+ presentation: t('.filters.shipment_state'),
59
+ combinator: 'or',
60
+ attribute: "shipment_state",
61
+ predicate: "eq",
62
+ options: %i[backorder canceled partial pending ready shipped].map do |option|
63
+ [
64
+ option.to_s.capitalize,
65
+ option
66
+ ]
67
+ end
68
+ },
69
+ {
70
+ presentation: t('.filters.payment_state'),
71
+ combinator: 'or',
72
+ attribute: "payment_state",
73
+ predicate: "eq",
74
+ options: %i[balance_due checkout completed credit_owed invalid paid pending processing void].map do |option|
75
+ [
76
+ option.to_s.titleize,
77
+ option
78
+ ]
79
+ end
80
+ },
81
+ {
82
+ presentation: t('.filters.promotions'),
83
+ combinator: 'or',
84
+ attribute: "promotions_id",
85
+ predicate: "in",
86
+ options: Spree::Promotion.all.pluck(:name, :id),
32
87
  },
33
88
  ]
34
89
  end
@@ -36,6 +91,7 @@ class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
36
91
  def columns
37
92
  [
38
93
  number_column,
94
+ state_column,
39
95
  date_column,
40
96
  customer_column,
41
97
  total_column,
@@ -49,17 +105,30 @@ class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
49
105
  {
50
106
  header: :order,
51
107
  data: ->(order) do
52
- order_path = spree.edit_admin_order_path(order)
53
-
54
- if !fade_row_proc.call(order)
55
- link_to order.number, order_path, class: 'font-semibold'
108
+ if !row_fade(order)
109
+ content_tag :div, order.number, class: 'font-semibold'
56
110
  else
57
- link_to order.number, order_path
111
+ content_tag :div, order.number
58
112
  end
59
113
  end
60
114
  }
61
115
  end
62
116
 
117
+ def state_column
118
+ {
119
+ header: :state,
120
+ data: ->(order) do
121
+ color = {
122
+ 'complete' => :green,
123
+ 'returned' => :red,
124
+ 'canceled' => :blue,
125
+ 'cart' => :graphite_light,
126
+ }[order.state] || :yellow
127
+ component('ui/badge').new(name: order.state.humanize, color: color)
128
+ end
129
+ }
130
+ end
131
+
63
132
  def date_column
64
133
  {
65
134
  header: :date,
@@ -71,7 +140,7 @@ class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
71
140
 
72
141
  def customer_column
73
142
  {
74
- class_name: "w-[400px]",
143
+ col: { class: "w-[400px]" },
75
144
  header: :customer,
76
145
  data: ->(order) do
77
146
  customer_email = order.user&.email
@@ -102,7 +171,7 @@ class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
102
171
  {
103
172
  header: :payment,
104
173
  data: ->(order) do
105
- component('ui/badge').new(name: order.payment_state&.humanize, color: order.paid? ? :green : :yellow)
174
+ component('ui/badge').new(name: order.payment_state.humanize, color: order.paid? ? :green : :yellow) if order.payment_state?
106
175
  end
107
176
  }
108
177
  end
@@ -111,7 +180,7 @@ class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
111
180
  {
112
181
  header: :shipment,
113
182
  data: ->(order) do
114
- component('ui/badge').new(name: order.shipment_state&.humanize, color: order.shipped? ? :green : :yellow)
183
+ component('ui/badge').new(name: order.shipment_state.humanize, color: order.shipped? ? :green : :yellow) if order.shipment_state?
115
184
  end
116
185
  }
117
186
  end
@@ -1,13 +1,19 @@
1
- # Add your component translations here.
2
- # Use the translation in the example in your template with `t(".hello")`.
3
1
  en:
4
- create_order: 'Create Order'
5
2
  columns:
6
3
  items:
7
4
  one: 1 Item
8
5
  other: '%{count} Items'
9
6
  filters:
10
- only_show_complete_orders: Only show complete orders
7
+ status: Status
8
+ shipment_state: Shipment State
9
+ payment_state: Payment State
10
+ promotions: Promotions
11
11
  date:
12
12
  formats:
13
13
  short: '%d %b %y'
14
+ scopes:
15
+ all_orders: All
16
+ canceled: Canceled
17
+ complete: Complete
18
+ returned: Returned
19
+ in_progress: In Progress
@@ -0,0 +1,67 @@
1
+ <div class="<%= stimulus_id %>" data-controller="<%= stimulus_id %>">
2
+ <%= render component("orders/show").new(order: @order) %>
3
+
4
+ <%= render component("ui/modal").new(title: t(".title.#{@type}"), close_path: solidus_admin.order_path(@order)) do |modal| %>
5
+ <%= form_for @order, url: solidus_admin.send("order_#{@type}_address_path", @order), html: { id: form_id } do |form| %>
6
+ <div class="w-full flex flex-col mb-4">
7
+ <div class="flex justify-between items-center mb-4 relative">
8
+ <h2 class="text-sm font-semibold">
9
+ <%= t(".subtitle.#{@type}") %>
10
+ </h2>
11
+
12
+ <% if @addresses.present? %>
13
+ <%= render component('ui/dropdown').new(
14
+ text: t(".select_address"),
15
+ "data-#{stimulus_id}-target": "addresses",
16
+ class: "max-h-[26rem] overflow-y-auto"
17
+ ) do %>
18
+ <% @addresses.each do |address| %>
19
+ <%= tag.a(
20
+ format_address(address),
21
+ href: solidus_admin.send("order_#{@type}_address_path", @order, address_id: address.id),
22
+ 'data-turbo-frame': address_frame_id,
23
+ 'data-action': "#{component('ui/dropdown').stimulus_id}#close",
24
+ ) %>
25
+ <% end %>
26
+ <% end %>
27
+ <% end %>
28
+ </div>
29
+
30
+ <div class="w-full flex gap-4">
31
+ <%= turbo_frame_tag address_frame_id do %>
32
+ <%= render component('ui/forms/address').new(address: @address, name: "order[#{@type}_address_attributes]") %>
33
+ <% end %>
34
+ </div>
35
+
36
+ <label class="flex gap-2 items-center">
37
+ <%= form.hidden_field use_attribute, value: '0', id: false %>
38
+
39
+ <%= render component("ui/forms/checkbox").new(
40
+ name: "#{form.object_name}[#{use_attribute}]",
41
+ checked: @address == (@type == 'ship' ? @order.bill_address : @order.ship_address),
42
+ value: '1'
43
+ ) %>
44
+
45
+ <span class="font-normal text-xs">
46
+ <%= t(".use_this_address.#{@type}") %>
47
+ </span>
48
+ </label>
49
+ </div>
50
+ <% end %>
51
+
52
+ <% modal.with_actions do %>
53
+ <%= render component("ui/button").new(
54
+ tag: :a,
55
+ scheme: :secondary,
56
+ text: t(".cancel"),
57
+ href: solidus_admin.order_path(@order)
58
+ ) %>
59
+
60
+ <%= render component("ui/button").new(
61
+ tag: :button,
62
+ text: t(".save"),
63
+ form: form_id
64
+ ) %>
65
+ <% end %>
66
+ <% end %>
67
+ </div>
@@ -0,0 +1,9 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ["addresses"]
5
+
6
+ close() {
7
+ this.addressesTarget.removeAttribute('open')
8
+ }
9
+ }
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::Address::Component < SolidusAdmin::BaseComponent
4
+ include SolidusAdmin::Layout::PageHelpers
5
+
6
+ VALID_TYPES = ['ship', 'bill'].freeze
7
+
8
+ def initialize(order:, address:, user: nil, type: 'ship')
9
+ @order = order
10
+ @user = user
11
+ @address = address
12
+ @addresses = user&.addresses.to_a.reject(&:new_record?)
13
+ @type = validate_address_type(type)
14
+ end
15
+
16
+ def form_id
17
+ @form_id ||= "#{stimulus_id}--form-#{@type}-#{@order.id}"
18
+ end
19
+
20
+ def address_frame_id
21
+ @table_frame_id ||= "#{stimulus_id}--#{@type}-address-frame-#{@order.id}"
22
+ end
23
+
24
+ def use_attribute
25
+ case @type
26
+ when 'ship'
27
+ 'use_shipping'
28
+ when 'bill'
29
+ 'use_billing'
30
+ end
31
+ end
32
+
33
+ def format_address(address)
34
+ safe_join([
35
+ address.name,
36
+ tag.br,
37
+ address.address1,
38
+ tag.br,
39
+ address.address2,
40
+ address.city,
41
+ address.zipcode,
42
+ address.state&.name,
43
+ tag.br,
44
+ address.country.name,
45
+ tag.br,
46
+ address.phone,
47
+ ], " ")
48
+ end
49
+
50
+ def validate_address_type(type)
51
+ VALID_TYPES.include?(type) ? type : raise(ArgumentError, "Invalid address type: #{type}")
52
+ end
53
+ end
@@ -0,0 +1,14 @@
1
+ en:
2
+ save: Save
3
+ cancel: Cancel
4
+ back: Back
5
+ select_address: Select address
6
+ title:
7
+ ship: Edit Shipping Address
8
+ bill: Edit Billing Address
9
+ subtitle:
10
+ ship: Shipping Address
11
+ bill: Billing Address
12
+ use_this_address:
13
+ ship: Use this address also for Billing
14
+ bill: Use this address also for Shipping
@@ -0,0 +1,76 @@
1
+ <%= page("data-action": "turbo:before-cache@window->#{stimulus_id}#closeMenus") do %>
2
+ <%= page_header do %>
3
+ <%= page_header_back(solidus_admin.orders_path) %>
4
+ <%= page_header_title(t('.title', number: @order.number)) %>
5
+ <%= page_header_actions do %>
6
+ <%= render component("ui/button").new(tag: :button, scheme: :secondary, text: t(".discard"), form: form_id) %>
7
+ <%= render component("ui/button").new(tag: :button, text: t(".save"), form: form_id) %>
8
+ <% end %>
9
+ <% end %>
10
+
11
+ <%= page_with_sidebar do %>
12
+ <%= page_with_sidebar_main do %>
13
+ <%= render component("orders/cart").new(order: @order) %>
14
+ <%= render component("orders/show/summary").new(order: @order) %>
15
+ <% end %>
16
+
17
+ <%= page_with_sidebar_aside do %>
18
+ <%= render component('ui/panel').new do |panel| %>
19
+ <% panel.with_menu t(".edit_email"), solidus_admin.order_customer_path(@order) %>
20
+ <% panel.with_menu t(".edit_shipping"), solidus_admin.edit_order_ship_address_path(@order) %>
21
+ <% panel.with_menu t(".edit_billing"), solidus_admin.edit_order_bill_address_path(@order) %>
22
+ <% panel.with_menu t(".remove_customer"), solidus_admin.order_customer_path(@order), method: :delete, class: "text-red-500" if @order.user %>
23
+
24
+ <% panel.with_section(class: 'flex flex-col gap-6') do %>
25
+ <div class="flex flex-col gap-2">
26
+ <span class="font-semibold text-sm"><%= t(".customer") %></span>
27
+ <% if @order.user %>
28
+ <div class="font-normal text-sm"><%= customer_name(@order.user) || tag.span(t('.no_name'), class: "text-gray-500") %></div>
29
+ <div class="font-normal text-sm body-link"><%= link_to @order.user.email, spree.admin_user_path(@order.user) %></div>
30
+ <div class="font-normal text-sm text-gray-500"><%= t(".orders_count", count: @order.user.orders.complete.count) %></div>
31
+ <% else %>
32
+ <%= render component('orders/show/customer_search').new(order: @order) %>
33
+ <% end %>
34
+ </div>
35
+
36
+ <div class="flex flex-col gap-2">
37
+ <span class="font-semibold text-sm"><%= t('.order_email') %></span>
38
+ <div class="font-normal text-sm">
39
+ <% if @order.email? %>
40
+ <%= @order.email %>
41
+ <% else %>
42
+ <%= link_to(t(".add_email"), solidus_admin.order_customer_path(@order), class: "body-link") %>
43
+ <% end %>
44
+ </div>
45
+ </div>
46
+
47
+ <div class="flex flex-col gap-2">
48
+ <span class="font-semibold text-sm"><%= @order.class.human_attribute_name(:ship_address) %></span>
49
+ <div class="font-normal text-sm">
50
+ <% if @order.ship_address %>
51
+ <%= format_address @order.ship_address %>
52
+ <% else %>
53
+ <%= link_to t(".add_shipping"), solidus_admin.edit_order_ship_address_path(@order), class: 'body-link' %>
54
+ <% end %>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="flex flex-col gap-2">
59
+ <span class="font-semibold text-sm"><%= @order.class.human_attribute_name(:bill_address) %></span>
60
+ <div class="font-normal text-sm">
61
+ <% if @order.bill_address.blank? %>
62
+ <%= link_to t(".add_billing"), solidus_admin.edit_order_bill_address_path(@order), class: 'body-link' %>
63
+ <% elsif @order.bill_address == @order.ship_address %>
64
+ <span class="text-gray-500"><%= t('.same_as_shipping') %></span>
65
+ <% else %>
66
+ <%= format_address @order.bill_address %>
67
+ <% end %>
68
+ </div>
69
+ </div>
70
+
71
+ <% end %>
72
+ <% end %>
73
+
74
+ <% end %>
75
+ <% end %>
76
+ <% end %>
@@ -0,0 +1,7 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ closeMenus() {
5
+ this.element.querySelectorAll('details').forEach(details => details.removeAttribute('open'))
6
+ }
7
+ }
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::Component < SolidusAdmin::BaseComponent
4
+ include SolidusAdmin::Layout::PageHelpers
5
+
6
+ def initialize(order:)
7
+ @order = order
8
+ end
9
+
10
+ def form_id
11
+ @form_id ||= "#{stimulus_id}--form-#{@order.id}"
12
+ end
13
+
14
+ def format_address(address)
15
+ return unless address
16
+ safe_join([
17
+ address.name,
18
+ tag.br,
19
+ address.address1,
20
+ tag.br,
21
+ address.address2,
22
+ address.city,
23
+ address.zipcode,
24
+ address.state&.name,
25
+ tag.br,
26
+ address.country.name,
27
+ tag.br,
28
+ address.phone,
29
+ ], " ")
30
+ end
31
+
32
+ def customer_name(user)
33
+ (
34
+ user.default_user_bill_address ||
35
+ user.default_user_ship_address ||
36
+ user.user_addresses.where(default: true).first ||
37
+ user.user_addresses.first
38
+ )&.address&.name
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ en:
2
+ save: Save
3
+ discard: Discard
4
+ title: "Order %{number}"
5
+ customer: Customer
6
+ no_name: No name available
7
+ order_email: Order contact email
8
+ back: Back to orders
9
+ same_as_shipping: Same as shipping address
10
+
11
+ edit_email: "Edit order email"
12
+ add_email: "Add order email"
13
+ edit_shipping: "Edit shipping address"
14
+ add_shipping: "Add shipping address"
15
+ edit_billing: "Edit billing address"
16
+ add_billing: "Add billing address"
17
+ remove_customer: "Remove customer"
18
+
19
+ orders_count:
20
+ one: "%{count} order"
21
+ other: "%{count} orders"
@@ -0,0 +1,14 @@
1
+ <div
2
+ class="w-full relative overflow-visible"
3
+ data-controller="<%= stimulus_id %>"
4
+ data-<%= stimulus_id %>-customers-url-value="<%= solidus_admin.customers_for_order_path(@order) %>"
5
+ data-action="
6
+ <%= component('ui/forms/search').stimulus_id %>:search-><%= stimulus_id %>#search
7
+ <%= component('ui/forms/search').stimulus_id %>:submit-><%= stimulus_id %>#submit
8
+ "
9
+ >
10
+ <%= render component("ui/forms/search").new(
11
+ placeholder: t(".placeholder"),
12
+ id: :order_customer
13
+ ) %>
14
+ </div>
@@ -0,0 +1,14 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ static values = { customersUrl: String }
5
+
6
+ async search({ detail: { query, controller } }) {
7
+ controller.resultsValue =
8
+ (await (await fetch(`${this.customersUrlValue}?q[name_or_variants_including_master_sku_cont]=${query}`)).text())
9
+ }
10
+
11
+ submit(event) {
12
+ event.detail.resultTarget.querySelector('form').submit()
13
+ }
14
+ }
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::CustomerSearch::Component < SolidusAdmin::BaseComponent
4
+ def initialize(order:)
5
+ @order = order
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ en:
2
+ placeholder: "Search customer"
@@ -0,0 +1,17 @@
1
+ <%= render component('ui/forms/search/result').new do %>
2
+ <% if @customer %>
3
+ <%= form_for(@order, url: solidus_admin.order_path(@order), html: {
4
+ "data-controller": "readonly-when-submitting",
5
+ class: "flex items-center",
6
+ }) do |f| %>
7
+ <%= hidden_field_tag("#{f.object_name}[user_id]", @customer.id) %>
8
+ <button type="submit" class="flex gap-2 grow items-center">
9
+ <%= render component("ui/icon").new(name: "user-line", class: 'w-5 h-5 m-2') %>
10
+ <div class="flex-col text-left">
11
+ <div class="leading-5 text-black font-semibold text-sm"><%= @name %></div>
12
+ <div class="leading-5 text-gray-500 font-normal text-sm"><%= @customer.email %></div>
13
+ </div>
14
+ </button>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::CustomerSearch::Result::Component < SolidusAdmin::BaseComponent
4
+ with_collection_parameter :customer
5
+
6
+ def initialize(order:, customer:)
7
+ @order = order
8
+ @customer = customer
9
+ @name = (customer.default_user_bill_address || customer.default_user_ship_address)&.address&.name if customer
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ <div class="<%= stimulus_id %>">
2
+ <%= render component("orders/show").new(order: @order) %>
3
+ <%= render component("ui/modal").new(title: t(".title"), close_path: close_path) do |modal| %>
4
+ <%= form_for @order, url: close_path, html: { id: form_id} do |f| %>
5
+ <%= render component("ui/forms/field").text_field(f, :email) %>
6
+ <label class="font-normal text-sm mt-4 block">
7
+ <%= t('.guest_checkout') %>:
8
+ <output class="font-semibold text-sm"><%= @order.user ? t('.no') : t('.yes') %></output>
9
+ <%= render component('ui/toggletip').new(text: t('.guest_checkout_tip'), class: "align-middle") %>
10
+ </label>
11
+ <% end %>
12
+
13
+ <% modal.with_actions do %>
14
+ <%= render component("ui/button").new(tag: :a, scheme: :secondary, href: close_path, type: :submit, text: t('.cancel')) %>
15
+ <%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
16
+ <% end %>
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::Email::Component < SolidusAdmin::BaseComponent
4
+ def initialize(order:)
5
+ @order = order
6
+ end
7
+
8
+ def form_id
9
+ dom_id(@order, "#{stimulus_id}_email_form")
10
+ end
11
+
12
+ def close_path
13
+ @close_path ||= solidus_admin.order_path(@order)
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ en:
2
+ title: "Edit order email"
3
+ submit: "Save"
4
+ cancel: "Cancel"
5
+ guest_checkout: "Guest checkout"
6
+ guest_checkout_tip: "An order without an associated user account is considered a guest checkout."
7
+ "yes": "Yes"
8
+ "no": "No"