spree_admin 5.0.0 → 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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/spree/admin/components/_bulk_panel.scss +11 -1
- data/app/assets/stylesheets/spree/admin/components/_cards.scss +3 -4
- data/app/assets/stylesheets/spree/admin/components/_dropdowns.scss +1 -1
- data/app/assets/stylesheets/spree/admin/components/_main.scss +8 -1
- data/app/assets/stylesheets/spree/admin/components/_modals.scss +1 -1
- data/app/assets/stylesheets/spree/admin/global/_variables.scss +8 -2
- data/app/controllers/spree/admin/products_controller.rb +1 -8
- data/app/controllers/spree/admin/storefront_controller.rb +1 -1
- data/app/controllers/spree/admin/translations_controller.rb +1 -1
- data/app/helpers/spree/admin/base_helper.rb +49 -57
- data/app/helpers/spree/admin/bulk_operations_helper.rb +86 -0
- data/app/helpers/spree/admin/modal_helper.rb +29 -0
- data/app/helpers/spree/admin/navigation_helper.rb +76 -1
- data/app/helpers/spree/admin/orders_helper.rb +0 -19
- data/app/helpers/spree/admin/stores_helper.rb +5 -34
- data/app/javascript/spree/admin/controllers/variants_form_controller.js +6 -0
- data/app/views/active_storage/_upload_form.html.erb +4 -8
- data/app/views/spree/admin/assets/edit.html.erb +3 -8
- data/app/views/spree/admin/coupon_codes/index.html.erb +4 -6
- data/app/views/spree/admin/custom_domains/_custom_domains.html.erb +1 -1
- data/app/views/spree/admin/custom_domains/index.html.erb +1 -1
- data/app/views/spree/admin/customer_returns/index.html.erb +4 -17
- data/app/views/spree/admin/dashboard/_setup_progress.html.erb +4 -2
- data/app/views/spree/admin/dashboard/show.html.erb +1 -1
- data/app/views/spree/admin/digital_assets/_table.html.erb +1 -1
- data/app/views/spree/admin/digital_assets/edit.html.erb +3 -11
- data/app/views/spree/admin/digital_assets/new.html.erb +3 -11
- data/app/views/spree/admin/exports/index.html.erb +22 -24
- data/app/views/spree/admin/exports/new.html.erb +3 -9
- data/app/views/spree/admin/line_items/new.html.erb +2 -5
- data/app/views/spree/admin/oauth_applications/index.html.erb +57 -58
- data/app/views/spree/admin/option_types/_filter.html.erb +1 -1
- data/app/views/spree/admin/option_types/index.html.erb +7 -11
- data/app/views/spree/admin/orders/_filters.html.erb +2 -7
- data/app/views/spree/admin/orders/_list.html.erb +2 -4
- data/app/views/spree/admin/orders/billing_address/create.turbo_stream.erb +3 -6
- data/app/views/spree/admin/orders/billing_address/edit.html.erb +3 -6
- data/app/views/spree/admin/orders/billing_address/new.html.erb +3 -6
- data/app/views/spree/admin/orders/billing_address/update.turbo_stream.erb +3 -6
- data/app/views/spree/admin/orders/contact_information/edit.html.erb +3 -6
- data/app/views/spree/admin/orders/customer_returns/edit.html.erb +1 -10
- data/app/views/spree/admin/orders/index.html.erb +1 -1
- data/app/views/spree/admin/orders/return_authorizations/_form.html.erb +1 -1
- data/app/views/spree/admin/orders/return_authorizations/show.html.erb +45 -43
- data/app/views/spree/admin/orders/shipping_address/create.turbo_stream.erb +3 -6
- data/app/views/spree/admin/orders/shipping_address/edit.html.erb +3 -6
- data/app/views/spree/admin/orders/shipping_address/new.html.erb +3 -6
- data/app/views/spree/admin/orders/shipping_address/update.turbo_stream.erb +3 -6
- data/app/views/spree/admin/pages/_filters.html.erb +1 -1
- data/app/views/spree/admin/pages/edit.html.erb +2 -5
- data/app/views/spree/admin/pages/index.html.erb +4 -4
- data/app/views/spree/admin/payment_methods/index.html.erb +10 -8
- data/app/views/spree/admin/post_categories/index.html.erb +4 -6
- data/app/views/spree/admin/posts/_filters.html.erb +2 -7
- data/app/views/spree/admin/posts/_post.html.erb +1 -11
- data/app/views/spree/admin/posts/index.html.erb +5 -9
- data/app/views/spree/admin/products/_bulk_operations.html.erb +59 -94
- data/app/views/spree/admin/products/_filters.html.erb +12 -7
- data/app/views/spree/admin/products/_list.html.erb +2 -10
- data/app/views/spree/admin/products/_product.html.erb +1 -4
- data/app/views/spree/admin/products/bulk_modal.html.erb +3 -8
- data/app/views/spree/admin/products/index.html.erb +5 -5
- data/app/views/spree/admin/promotion_actions/new.html.erb +7 -12
- data/app/views/spree/admin/promotion_rules/new.html.erb +7 -12
- data/app/views/spree/admin/promotions/_filters.html.erb +27 -0
- data/app/views/spree/admin/promotions/index.html.erb +7 -35
- data/app/views/spree/admin/properties/index.html.erb +10 -9
- data/app/views/spree/admin/refund_reasons/index.html.erb +37 -35
- data/app/views/spree/admin/refunds/edit.html.erb +3 -8
- data/app/views/spree/admin/reimbursement_types/index.html.erb +42 -40
- data/app/views/spree/admin/reports/_report.html.erb +1 -1
- data/app/views/spree/admin/return_authorization_reasons/index.html.erb +41 -41
- data/app/views/spree/admin/return_authorizations/_filters.html.erb +1 -1
- data/app/views/spree/admin/return_authorizations/_list.html.erb +1 -10
- data/app/views/spree/admin/return_authorizations/index.html.erb +1 -1
- data/app/views/spree/admin/roles/_form.html.erb +1 -1
- data/app/views/spree/admin/roles/index.html.erb +26 -24
- data/app/views/spree/admin/shared/_bulk_modal.html.erb +6 -7
- data/app/views/spree/admin/shared/_filter_submit.html.erb +6 -0
- data/app/views/spree/admin/shared/_modal.html.erb +2 -8
- data/app/views/spree/admin/shared/_multi_product_picker.html.erb +2 -4
- data/app/views/spree/admin/shared/_no_resource_found.html.erb +1 -1
- data/app/views/spree/admin/shared/_product_image.html.erb +1 -10
- data/app/views/spree/admin/shared/_refunds.html.erb +1 -1
- data/app/views/spree/admin/shared/sidebar/_orders_nav.html.erb +1 -1
- data/app/views/spree/admin/shared/sidebar/_store_dropdown.html.erb +36 -7
- data/app/views/spree/admin/shared/sidebar/_store_nav.html.erb +4 -0
- data/app/views/spree/admin/shared/sortable_tree/_taxonomy.html.erb +3 -23
- data/app/views/spree/admin/shipping_categories/index.html.erb +28 -26
- data/app/views/spree/admin/shipping_methods/_actions.html.erb +1 -1
- data/app/views/spree/admin/shipping_methods/index.html.erb +23 -21
- data/app/views/spree/admin/stock_items/_filters.html.erb +2 -7
- data/app/views/spree/admin/stock_items/index.html.erb +5 -8
- data/app/views/spree/admin/stock_locations/_stock_location.html.erb +16 -13
- data/app/views/spree/admin/stock_locations/index.html.erb +24 -21
- data/app/views/spree/admin/stock_transfers/_filters.html.erb +1 -1
- data/app/views/spree/admin/stock_transfers/_new_variant_modal.html.erb +3 -5
- data/app/views/spree/admin/stock_transfers/index.html.erb +6 -6
- data/app/views/spree/admin/store_credit_categories/_form.html.erb +1 -1
- data/app/views/spree/admin/store_credit_categories/edit.html.erb +6 -4
- data/app/views/spree/admin/store_credit_categories/index.html.erb +28 -24
- data/app/views/spree/admin/store_credits/index.html.erb +2 -2
- data/app/views/spree/admin/storefront/edit.html.erb +7 -9
- data/app/views/spree/admin/stores/form/_policies.html.erb +1 -1
- data/app/views/spree/admin/stores/new.html.erb +8 -6
- data/app/views/spree/admin/tax_categories/index.html.erb +24 -22
- data/app/views/spree/admin/tax_rates/index.html.erb +26 -24
- data/app/views/spree/admin/taxonomies/index.html.erb +4 -4
- data/app/views/spree/admin/taxonomies/show.html.erb +2 -2
- data/app/views/spree/admin/themes/_theme_preview_image.html.erb +1 -10
- data/app/views/spree/admin/themes/index.html.erb +2 -2
- data/app/views/spree/admin/translations/_translations_unavailable.html.erb +6 -8
- data/app/views/spree/admin/users/_filters.html.erb +2 -7
- data/app/views/spree/admin/users/_tabs.html.erb +4 -4
- data/app/views/spree/admin/users/_user.html.erb +1 -4
- data/app/views/spree/admin/users/bulk_modal.html.erb +3 -8
- data/app/views/spree/admin/users/index.html.erb +25 -58
- data/app/views/spree/admin/variants/form/_media_asset.html.erb +1 -7
- data/app/views/spree/admin/variants/form/_pricing.html.erb +1 -1
- data/app/views/spree/admin/webhooks_subscribers/_form.html.erb +1 -1
- data/app/views/spree/admin/webhooks_subscribers/index.html.erb +25 -22
- data/app/views/spree/admin/webhooks_subscribers/show.html.erb +3 -3
- data/app/views/spree/admin/zones/index.html.erb +34 -32
- data/config/locales/en.yml +1 -3
- metadata +12 -9
- data/app/views/spree/admin/products/_empty_list.html.erb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d55b4e39523cee4652dddb953445f27d15190d2cff8e40d3f012329c3e3612ec
|
4
|
+
data.tar.gz: e919c13188d0b35f8c17afaa52fd6e26ea2eae5713e2f5c7d2abb81ea7b7cb9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
64
|
-
|
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:
|
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;
|
@@ -82,7 +82,7 @@ turbo-frame[loading] .spinner-border, turbo-frame[busy] .spinner-border {
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
|
85
|
-
.badge {
|
85
|
+
.badge:not(.badge-info) {
|
86
86
|
@extend .badge-light;
|
87
87
|
}
|
88
88
|
}
|
@@ -156,3 +156,10 @@ turbo-frame[loading] .spinner-border, turbo-frame[busy] .spinner-border {
|
|
156
156
|
top: 0.5rem;
|
157
157
|
}
|
158
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
|
+
}
|
@@ -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":
|
30
|
-
"action-border":
|
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;
|
@@ -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
|
-
|
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(
|
69
|
+
@back_path = spree.edit_admin_store_path(section: "general-settings")
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -21,6 +21,9 @@ module Spree
|
|
21
21
|
@spree_update_available ||= !Rails.env.test? && spree_updater.update_available?
|
22
22
|
end
|
23
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]
|
24
27
|
def settings_active?
|
25
28
|
@settings_active || %w[stores zones shipping_methods oauth_applications
|
26
29
|
payment_methods refund_reasons reimbursement_types
|
@@ -30,10 +33,19 @@ module Spree
|
|
30
33
|
documents stripe_tax_registrations members subscriptions stock_locations webhooks_subscribers].include?(controller_name)
|
31
34
|
end
|
32
35
|
|
36
|
+
# @return [Array<String>] the available countries for checkout
|
33
37
|
def available_countries_iso
|
34
38
|
@available_countries_iso ||= current_store.countries_available_for_checkout.pluck(:iso)
|
35
39
|
end
|
36
40
|
|
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
|
37
49
|
def render_avatar(user, options = {})
|
38
50
|
return unless user.present?
|
39
51
|
|
@@ -42,10 +54,10 @@ module Spree
|
|
42
54
|
options[:class] ||= 'avatar'
|
43
55
|
|
44
56
|
if user.respond_to?(:avatar) && user.avatar.attached? && user.avatar.variable?
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
57
|
+
spree_image_tag(
|
58
|
+
user.avatar,
|
59
|
+
width: options[:width],
|
60
|
+
height: options[:height],
|
49
61
|
class: options[:class],
|
50
62
|
style: "width: #{options[:width]}px; height: #{options[:height]}px;"
|
51
63
|
)
|
@@ -54,12 +66,19 @@ module Spree
|
|
54
66
|
end
|
55
67
|
end
|
56
68
|
|
69
|
+
# returns the available display on options, eg backend, frontend, both
|
70
|
+
# @return [Array<Array<String, String>>] the available display on options
|
57
71
|
def display_on_options
|
58
72
|
Spree::DisplayOn::DISPLAY.map do |display_on|
|
59
73
|
[Spree.t("admin.display_on_options.#{display_on}"), display_on]
|
60
74
|
end
|
61
75
|
end
|
62
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
|
63
82
|
def error_message_on(object, method, _options = {})
|
64
83
|
object = convert_to_model(object)
|
65
84
|
obj = object.respond_to?(:errors) ? object : instance_variable_get("@#{object}")
|
@@ -72,6 +91,10 @@ module Spree
|
|
72
91
|
end
|
73
92
|
end
|
74
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
|
75
98
|
def icon(icon_name, options = {})
|
76
99
|
if icon_name.ends_with?('.svg')
|
77
100
|
icon_name = File.basename(icon_name, File.extname(icon_name))
|
@@ -91,42 +114,19 @@ module Spree
|
|
91
114
|
content_tag :i, nil, class: "ti ti-#{icon_name} #{options[:class]}", style: styles
|
92
115
|
end
|
93
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
|
94
120
|
def flag_emoji(iso)
|
95
121
|
::Country.new(iso).emoji_flag
|
96
122
|
end
|
97
123
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
current_store.supported_currencies.split(',')
|
105
|
-
),
|
106
|
-
class: 'custom-select',
|
107
|
-
disabled: current_store.supported_currencies.split(',').count == 1
|
108
|
-
)
|
109
|
-
end
|
110
|
-
|
111
|
-
case options[:type]
|
112
|
-
when :integer
|
113
|
-
number_field_tag(name, value, preference_field_options(options))
|
114
|
-
when :decimal
|
115
|
-
number_field_tag(name, value, preference_field_options(options))
|
116
|
-
when :boolean
|
117
|
-
hidden_field_tag(name, 0, id: "#{name}_hidden") +
|
118
|
-
check_box_tag(name, 1, value, preference_field_options(options))
|
119
|
-
when :string
|
120
|
-
text_field_tag(name, value, preference_field_options(options))
|
121
|
-
when :password
|
122
|
-
password_field_tag(name, value, preference_field_options(options))
|
123
|
-
when :text
|
124
|
-
text_area_tag(name, value, preference_field_options(options))
|
125
|
-
else
|
126
|
-
text_field_tag(name, value, preference_field_options(options))
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
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
|
130
130
|
def preference_field_for(form, field, options)
|
131
131
|
case options[:type]
|
132
132
|
when :integer
|
@@ -146,6 +146,11 @@ module Spree
|
|
146
146
|
end
|
147
147
|
end
|
148
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
|
149
154
|
def preference_field_options(options)
|
150
155
|
field_options = case options[:type]
|
151
156
|
when :integer
|
@@ -191,6 +196,10 @@ module Spree
|
|
191
196
|
size: options[:size])
|
192
197
|
end
|
193
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
|
194
203
|
def preference_fields(object, form)
|
195
204
|
return unless object.respond_to?(:preferences)
|
196
205
|
|
@@ -227,31 +236,14 @@ module Spree
|
|
227
236
|
dom_id(record, 'spree')
|
228
237
|
end
|
229
238
|
|
239
|
+
# renders a red dot with a * to indicate that a field is required
|
240
|
+
# @return [String] the required span tag
|
230
241
|
def required_span_tag
|
231
242
|
content_tag(:span, ' *', class: 'required font-weight-bold text-danger')
|
232
243
|
end
|
233
244
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
url = if [Spree::Product, Spree::Post].include?(resource.class)
|
238
|
-
spree_storefront_resource_url(resource, preview_id: resource.id)
|
239
|
-
else
|
240
|
-
spree_storefront_resource_url(resource)
|
241
|
-
end
|
242
|
-
|
243
|
-
link_to_with_icon(
|
244
|
-
'eye',
|
245
|
-
Spree.t('admin.utilities.preview', name: resource_name),
|
246
|
-
url,
|
247
|
-
class: 'text-left dropdown-item', id: "adminPreview#{resource_name}", target: :blank, data: { turbo: false }
|
248
|
-
)
|
249
|
-
end
|
250
|
-
|
251
|
-
def path_from_url(url)
|
252
|
-
url.to_s.gsub('https://', '').gsub('http://', '')
|
253
|
-
end
|
254
|
-
|
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']
|
255
247
|
def allowed_file_types_for_upload
|
256
248
|
Rails.application.config.active_storage.web_image_content_types
|
257
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
|
@@ -16,6 +16,7 @@ module Spree
|
|
16
16
|
|
17
17
|
# the per_page_dropdown is used on index pages like orders, products, promotions etc.
|
18
18
|
# this method generates the select_tag
|
19
|
+
# @return [String]
|
19
20
|
def per_page_dropdown
|
20
21
|
per_page_default = if @products
|
21
22
|
Spree::Admin::RuntimeConfig.admin_products_per_page
|
@@ -48,6 +49,8 @@ module Spree
|
|
48
49
|
|
49
50
|
# helper method to create proper url to apply per page ing
|
50
51
|
# fixes https://github.com/spree/spree/issues/6888
|
52
|
+
# @param per_page [Integer] the number of items per page
|
53
|
+
# @return [Hash] the params to apply per page
|
51
54
|
def per_page_dropdown_params(per_page)
|
52
55
|
args = params.permit!.to_h.clone
|
53
56
|
args.delete(:page)
|
@@ -56,6 +59,12 @@ module Spree
|
|
56
59
|
args
|
57
60
|
end
|
58
61
|
|
62
|
+
# render a button link to edit a resource
|
63
|
+
# if the current user doesn't have permission to update the resource, the button will not be rendered
|
64
|
+
# @param resource [Spree::Product, Spree::User, Spree::Order] the resource to edit
|
65
|
+
# @param options [Hash] the options for the link
|
66
|
+
# @option options [String] :url the url to edit the resource (optional)
|
67
|
+
# @return [String] the link to edit the resource
|
59
68
|
def link_to_edit(resource, options = {})
|
60
69
|
url = options[:url] || edit_object_url(resource)
|
61
70
|
options[:data] ||= {}
|
@@ -64,6 +73,12 @@ module Spree
|
|
64
73
|
link_to_with_icon('pencil', Spree.t(:edit), url, options) if can?(:update, resource)
|
65
74
|
end
|
66
75
|
|
76
|
+
# render a button to delete a resource with a confirmation modal
|
77
|
+
# if the current user doesn't have permission to destroy the resource, the button will not be rendered
|
78
|
+
# @param resource [Spree::Product, Spree::User, Spree::Order] the resource to delete
|
79
|
+
# @param options [Hash] the options for the link
|
80
|
+
# @option options [String] :url the url to delete the resource (optional)
|
81
|
+
# @return [String] the link to delete the resource
|
67
82
|
def link_to_delete(resource, options = {})
|
68
83
|
url = options[:url] || object_url(resource)
|
69
84
|
name = options[:name] || Spree.t('actions.destroy')
|
@@ -81,6 +96,12 @@ module Spree
|
|
81
96
|
end
|
82
97
|
end
|
83
98
|
|
99
|
+
# renders a link with an icon
|
100
|
+
# @param icon_name [String] the name of the icon, eg: 'pencil', see: https://tabler.io/icons
|
101
|
+
# @param text [String] the text of the link
|
102
|
+
# @param url [String] the url of the link
|
103
|
+
# @param options [Hash] the options for the link
|
104
|
+
# @return [String] the link with the icon
|
84
105
|
def link_to_with_icon(icon_name, text, url, options = {})
|
85
106
|
options[:class] ||= (options[:class].to_s + " with-tip").strip
|
86
107
|
options[:title] ||= text if options[:no_text]
|
@@ -95,6 +116,12 @@ module Spree
|
|
95
116
|
link_to(text.html_safe, url, options)
|
96
117
|
end
|
97
118
|
|
119
|
+
# renders an active link with an icon, using the active_link_to method from https://github.com/comfy/active_link_to gem
|
120
|
+
# @param icon_name [String] the name of the icon, eg: 'pencil', see: https://tabler.io/icons
|
121
|
+
# @param text [String] the text of the link
|
122
|
+
# @param url [String] the url of the link
|
123
|
+
# @param options [Hash] the options for the link
|
124
|
+
# @return [String] the active link with the icon
|
98
125
|
def active_link_to_with_icon(icon_name, text, url, options = {})
|
99
126
|
options[:class] = (options[:class].to_s + " with-tip").strip
|
100
127
|
options[:title] = text if options[:no_text]
|
@@ -109,7 +136,13 @@ module Spree
|
|
109
136
|
active_link_to(text.html_safe, url, options)
|
110
137
|
end
|
111
138
|
|
139
|
+
# renders a button with an icon (optional)
|
112
140
|
# Override: Add disable_with option to prevent multiple request on consecutive clicks
|
141
|
+
# @param text [String] the text of the button
|
142
|
+
# @param icon_name [String] the name of the icon, eg: 'pencil', see: https://tabler.io/icons
|
143
|
+
# @param button_type [String] the type of the button, eg: 'submit', 'button'
|
144
|
+
# @param options [Hash] the options for the button
|
145
|
+
# @return [String] the button with the icon
|
113
146
|
def button(text, icon_name = nil, button_type = 'submit', options = {})
|
114
147
|
if icon_name
|
115
148
|
text = "#{icon(icon_name, class: "icon icon-#{icon_name}")} #{text}"
|
@@ -128,6 +161,8 @@ module Spree
|
|
128
161
|
end
|
129
162
|
|
130
163
|
def button_link_to(text, url, html_options = {})
|
164
|
+
Spree::Deprecation.warn("button_link_to is deprecated. Use standard link_to instead.")
|
165
|
+
|
131
166
|
if html_options[:method] &&
|
132
167
|
!html_options[:method].to_s.casecmp('get').zero? &&
|
133
168
|
!html_options[:remote]
|
@@ -149,6 +184,10 @@ module Spree
|
|
149
184
|
end
|
150
185
|
end
|
151
186
|
|
187
|
+
# renders a badge (active/inactive)
|
188
|
+
# @param condition [Boolean] the condition to check
|
189
|
+
# @param options [Hash] the options for the badge
|
190
|
+
# @return [String] the badge with the icon
|
152
191
|
def active_badge(condition, options = {})
|
153
192
|
label = options[:label]
|
154
193
|
label ||= condition ? Spree.t(:say_yes) : Spree.t(:say_no)
|
@@ -161,6 +200,11 @@ module Spree
|
|
161
200
|
end
|
162
201
|
end
|
163
202
|
|
203
|
+
# renders a back button to the previous page
|
204
|
+
# @param default_url [String] the default url to go back to
|
205
|
+
# @param object [Spree::Product, Spree::User, Spree::Order] the object list to go back to
|
206
|
+
# @param label [String] the label of the back button (optional)
|
207
|
+
# @return [String] the back button
|
164
208
|
def page_header_back_button(default_url, object = nil, label = nil)
|
165
209
|
url = default_url
|
166
210
|
|
@@ -175,10 +219,15 @@ module Spree
|
|
175
219
|
end
|
176
220
|
end
|
177
221
|
|
222
|
+
# renders an external link with an icon (eg. spree documentation website)
|
223
|
+
# @param label [String] the label of the link
|
224
|
+
# @param url [String] the url of the link
|
225
|
+
# @param opts [Hash] the options for the link
|
226
|
+
# @return [String] the external link with the icon
|
178
227
|
def external_link_to(label, url, opts = {}, &block)
|
179
228
|
opts[:target] ||= :blank
|
180
229
|
opts[:rel] ||= :nofollow
|
181
|
-
opts[:class] ||= "d-inline-flex align-items-center text-blue"
|
230
|
+
opts[:class] ||= "d-inline-flex align-items-center text-blue text-decoration-none"
|
182
231
|
|
183
232
|
if block_given?
|
184
233
|
link_to url, opts, &block
|
@@ -189,6 +238,32 @@ module Spree
|
|
189
238
|
end
|
190
239
|
end
|
191
240
|
|
241
|
+
# renders a link to preview a resource on the storefront using the spree_storefront_resource_url helper
|
242
|
+
# @param resource [Spree::Product, Spree::Post] the resource to preview
|
243
|
+
# @param options [Hash] the options for the link
|
244
|
+
# @return [String] the link to preview the resource
|
245
|
+
def external_page_preview_link(resource, options = {})
|
246
|
+
resource_name = options[:name] || resource.class.name.demodulize
|
247
|
+
|
248
|
+
url = if [Spree::Product, Spree::Post].include?(resource.class)
|
249
|
+
spree_storefront_resource_url(resource, preview_id: resource.id)
|
250
|
+
else
|
251
|
+
spree_storefront_resource_url(resource)
|
252
|
+
end
|
253
|
+
|
254
|
+
link_to_with_icon(
|
255
|
+
'eye',
|
256
|
+
Spree.t('admin.utilities.preview', name: resource_name),
|
257
|
+
url,
|
258
|
+
class: 'text-left dropdown-item', id: "adminPreview#{resource_name}", target: :blank, data: { turbo: false }
|
259
|
+
)
|
260
|
+
end
|
261
|
+
|
262
|
+
# renders a help bubble with an icon
|
263
|
+
# @param text [String] the text of the help bubble
|
264
|
+
# @param placement [String] the placement of the help bubble
|
265
|
+
# @param css [String] the css class of the help bubble
|
266
|
+
# @return [String] the help bubble with the icon
|
192
267
|
def help_bubble(text = '', placement = 'bottom', css: nil)
|
193
268
|
css ||= 'text-muted'
|
194
269
|
content_tag :small, icon('info-square-rounded', class: css), data: { placement: placement }, class: "with-tip #{css}", title: text
|
@@ -69,25 +69,6 @@ module Spree
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
# Renders all the extension partials that may have been specified in the extensions
|
73
|
-
def event_links(order, events)
|
74
|
-
links = []
|
75
|
-
events.each do |event|
|
76
|
-
next unless order.send("can_#{event}?")
|
77
|
-
|
78
|
-
label = Spree.t(event, scope: 'admin.order.events', default: Spree.t(event))
|
79
|
-
links << button_link_to(
|
80
|
-
label.capitalize,
|
81
|
-
[event.to_sym, :admin, order],
|
82
|
-
method: :put,
|
83
|
-
icon: event.to_s + '.svg',
|
84
|
-
data: { turbo_confirm: Spree.t(:order_sure_want_to, event: label) },
|
85
|
-
class: 'btn-light'
|
86
|
-
)
|
87
|
-
end
|
88
|
-
safe_join(links, ''.html_safe)
|
89
|
-
end
|
90
|
-
|
91
72
|
def line_item_shipment_price(line_item, quantity)
|
92
73
|
Spree::Money.new(line_item.price * quantity, currency: line_item.currency)
|
93
74
|
end
|