spree_admin 5.4.0.rc5 → 5.4.0.rc7
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/tailwind/spree/admin/base/_theme.css +2 -1
- data/app/assets/tailwind/spree/admin/components/_bulk-panel.css +1 -1
- data/app/assets/tailwind/spree/admin/components/_buttons.css +1 -1
- data/app/assets/tailwind/spree/admin/components/_cards.css +3 -7
- data/app/assets/tailwind/spree/admin/components/_forms.css +1 -1
- data/app/assets/tailwind/spree/admin/components/_list-groups.css +1 -1
- data/app/assets/tailwind/spree/admin/components/_variants-form.css +7 -0
- data/app/controllers/concerns/spree/admin/order_concern.rb +1 -1
- data/app/controllers/spree/admin/imports_controller.rb +2 -1
- data/app/controllers/spree/admin/orders/user_controller.rb +1 -1
- data/app/controllers/spree/admin/product_translations_controller.rb +64 -0
- data/app/controllers/spree/admin/products_controller.rb +7 -1
- data/app/controllers/spree/admin/stock_movements_controller.rb +37 -0
- data/app/helpers/spree/admin/base_helper.rb +3 -1
- data/app/helpers/spree/admin/table_helper.rb +1 -1
- data/app/javascript/spree/admin/controllers/variants_form_controller.js +9 -0
- data/app/models/spree/admin/form_builder.rb +1 -1
- data/app/presenters/spree/admin/order_summary_presenter.rb +11 -0
- data/app/views/spree/admin/dashboard/show.html.erb +1 -1
- data/app/views/spree/admin/exports/_export.html.erb +1 -1
- data/app/views/spree/admin/import_rows/_product.html.erb +4 -0
- data/app/views/spree/admin/imports/new.html.erb +1 -1
- data/app/views/spree/admin/markets/_form.html.erb +1 -1
- data/app/views/spree/admin/option_types/_form.html.erb +9 -1
- data/app/views/spree/admin/option_types/_option_value_fields.html.erb +15 -1
- data/app/views/spree/admin/orders/_shipment.html.erb +1 -1
- data/app/views/spree/admin/payments/_payment.html.erb +1 -1
- data/app/views/spree/admin/payments/new.html.erb +1 -1
- data/app/views/spree/admin/payments/source_forms/_previous_cards.html.erb +1 -1
- data/app/views/spree/admin/payments/source_forms/_store_credit.html.erb +1 -1
- data/app/views/spree/admin/product_translations/index.html.erb +108 -0
- data/app/views/spree/admin/products/form/_variants.html.erb +3 -0
- data/app/views/spree/admin/products/form/variants/_variant_template.html.erb +3 -0
- data/app/views/spree/admin/shared/_filters_search_bar.html.erb +1 -1
- data/app/views/spree/admin/shared/_head.html.erb +1 -1
- data/app/views/spree/admin/shared/_media_form.html.erb +1 -1
- data/app/views/spree/admin/shipments/edit.html.erb +6 -6
- data/app/views/spree/admin/stock_movements/index.html.erb +15 -0
- data/app/views/spree/admin/tables/_column_selector.html.erb +1 -1
- data/app/views/spree/admin/tables/_query_builder.html.erb +1 -1
- data/app/views/spree/admin/tables/_table.html.erb +3 -3
- data/app/views/spree/admin/tables/columns/_stock_movement_originator.html.erb +28 -0
- data/app/views/spree/admin/translations/edit.html.erb +1 -1
- data/app/views/spree/admin/variants/form/_pricing.html.erb +1 -1
- data/config/initializers/spree_admin_navigation.rb +18 -3
- data/config/initializers/spree_admin_tables.rb +63 -0
- data/config/locales/en.yml +12 -4
- data/config/routes.rb +3 -0
- data/lib/spree/admin/engine.rb +2 -0
- metadata +12 -7
- data/db/migrate/20250217171018_create_action_text_video_embeds.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f6458ffb6c4174e9a472f42a28640be1fdcb253e8bfb49e1aac5f7d62f9e725c
|
|
4
|
+
data.tar.gz: 27987a653ae8d1c11515fc323bcac9e4c6e2da4da241992d0e903bbe3619b117
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9352b948c77b39c924911ade674732ec98a9a7ba2bf787fb58fc2b3015396197e9375ec21f7b51ca62d1a088c5533d0efff9a5e10ecb94b6a072c3ac79c48aab
|
|
7
|
+
data.tar.gz: 2a6320babac28aa0948ce2a15b7e48e8797dab9a496d536fc26504da383c5a50bad83c30faef640d021d622795f71bacd1feef104091aa1bcfa676f81de4d617
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
--color-info: var(--color-blue-900);
|
|
15
15
|
|
|
16
16
|
/* Typography */
|
|
17
|
-
--font-sans: "
|
|
17
|
+
--font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
|
|
18
|
+
--font-mono: "Geist Mono", ui-monospace, monospace;
|
|
18
19
|
|
|
19
20
|
/* Override Tailwind's text-* scale to match Spree design system */
|
|
20
21
|
--text-2xs: 0.625rem;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
.btn {
|
|
12
12
|
@apply inline-flex items-center justify-center text-center align-middle gap-2;
|
|
13
13
|
@apply cursor-pointer select-none no-underline;
|
|
14
|
-
@apply px-
|
|
14
|
+
@apply px-2.5 py-1.5 text-base font-medium leading-normal border border-transparent rounded-xl;
|
|
15
15
|
@apply transition-colors duration-100 ease-linear;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -13,10 +13,6 @@
|
|
|
13
13
|
@apply p-0 mb-3;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
.card .card {
|
|
17
|
-
@apply rounded-xl;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
16
|
/* Card with table */
|
|
21
17
|
.card > .table,
|
|
22
18
|
.card .table-responsive > .table {
|
|
@@ -74,7 +70,7 @@
|
|
|
74
70
|
}
|
|
75
71
|
|
|
76
72
|
.card-body {
|
|
77
|
-
@apply flex-auto p-
|
|
73
|
+
@apply flex-auto p-3;
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
.card-body .form-group:last-child {
|
|
@@ -87,7 +83,7 @@
|
|
|
87
83
|
}
|
|
88
84
|
|
|
89
85
|
.card-header {
|
|
90
|
-
@apply flex items-center mb-0
|
|
86
|
+
@apply flex items-center mb-0 px-3 h-12 border-b border-gray-100 rounded-t-[calc(var(--radius-xl)-1px)];
|
|
91
87
|
}
|
|
92
88
|
|
|
93
89
|
.card-header .card-title {
|
|
@@ -107,7 +103,7 @@
|
|
|
107
103
|
}
|
|
108
104
|
|
|
109
105
|
.card-footer {
|
|
110
|
-
@apply p-
|
|
106
|
+
@apply p-3;
|
|
111
107
|
}
|
|
112
108
|
|
|
113
109
|
.card-footer:last-child {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
.select-input,
|
|
24
24
|
.form-control-sm,
|
|
25
25
|
.custom-select-sm {
|
|
26
|
-
@apply block w-full py-
|
|
26
|
+
@apply block w-full py-1.5 px-2.5 text-base font-normal leading-normal;
|
|
27
27
|
@apply text-gray-950 bg-white border border-gray-200 rounded-lg shadow-xs;
|
|
28
28
|
@apply focus:outline-offset-2 focus:outline-blue-500 focus:border-gray-200 focus:ring-0;
|
|
29
29
|
@apply transition-all duration-100 ease-in-out;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
.list-group-item {
|
|
11
|
-
@apply relative block py-
|
|
11
|
+
@apply relative block py-2.5 px-3 text-gray-950 no-underline border border-gray-200 hover:bg-gray-25;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.list-group-item:first-child {
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
.variants-form .variants-table .column-checkbox,
|
|
75
|
+
.variants-form .variants-table .column-thumbnail,
|
|
75
76
|
.variants-form .variants-table .column-variant,
|
|
76
77
|
.variants-form .variants-table .column-price,
|
|
77
78
|
.variants-form .variants-table .column-quantity,
|
|
@@ -83,6 +84,11 @@
|
|
|
83
84
|
@apply justify-center grow-0 basis-8;
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
.variants-form .variants-table .column-thumbnail {
|
|
88
|
+
@apply grow-0 shrink-0;
|
|
89
|
+
flex-basis: 36px;
|
|
90
|
+
}
|
|
91
|
+
|
|
86
92
|
.variants-form .variants-table .column-variant {
|
|
87
93
|
@apply select-none grow-[3] basis-0;
|
|
88
94
|
}
|
|
@@ -136,6 +142,7 @@
|
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
.variants-form .variants-table__body__row.nested .column-checkbox,
|
|
145
|
+
.variants-form .variants-table__body__row.nested .column-thumbnail,
|
|
139
146
|
.variants-form .variants-table__body__row.nested .column-variant {
|
|
140
147
|
@apply left-5 relative;
|
|
141
148
|
}
|
|
@@ -45,7 +45,8 @@ module Spree
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def assign_params
|
|
48
|
-
|
|
48
|
+
requested_type = params.dig(:import, :type) || params[:type]
|
|
49
|
+
@object.type = available_types.map(&:to_s).find { |type| type == requested_type } || available_types.first.to_s
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
def available_types
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class ProductTranslationsController < BaseController
|
|
4
|
+
include Pagy::Method
|
|
5
|
+
|
|
6
|
+
before_action :load_locales
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
@total_products = store_product_ids.count
|
|
10
|
+
@coverage = build_coverage
|
|
11
|
+
@products = paginated_products
|
|
12
|
+
@translated_locales_map = build_translated_locales_map(@products.map(&:id))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def load_locales
|
|
18
|
+
@default_locale = current_store.default_locale
|
|
19
|
+
@locales = (current_store.supported_locales_list - [@default_locale]).sort
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def store_product_ids
|
|
23
|
+
@store_product_ids ||= current_store.product_ids
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def build_coverage
|
|
27
|
+
return [] if @locales.empty?
|
|
28
|
+
|
|
29
|
+
counts = Spree::Product::Translation
|
|
30
|
+
.where(spree_product_id: store_product_ids)
|
|
31
|
+
.where(locale: @locales)
|
|
32
|
+
.where.not(name: [nil, ''])
|
|
33
|
+
.group(:locale)
|
|
34
|
+
.count
|
|
35
|
+
|
|
36
|
+
@locales.map do |locale|
|
|
37
|
+
translated = counts[locale] || 0
|
|
38
|
+
percentage = @total_products.positive? ? (translated * 100.0 / @total_products).round : 0
|
|
39
|
+
{ locale: locale, translated: translated, total: @total_products, percentage: percentage }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def paginated_products
|
|
44
|
+
scope = current_store.products.order(:name)
|
|
45
|
+
scope = scope.ransack(params[:q]).result if params[:q].present?
|
|
46
|
+
@pagy, products = pagy(scope, limit: params[:per_page] || 25)
|
|
47
|
+
products
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def build_translated_locales_map(product_ids)
|
|
51
|
+
return {} if product_ids.empty? || @locales.empty?
|
|
52
|
+
|
|
53
|
+
rows = Spree::Product::Translation
|
|
54
|
+
.where(spree_product_id: product_ids, locale: @locales)
|
|
55
|
+
.where.not(name: [nil, ''])
|
|
56
|
+
.pluck(:spree_product_id, :locale)
|
|
57
|
+
|
|
58
|
+
rows.each_with_object({}) do |(product_id, locale), hash|
|
|
59
|
+
(hash[product_id] ||= []) << locale
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -179,10 +179,16 @@ module Spree
|
|
|
179
179
|
|
|
180
180
|
@product_variant_ids = {}
|
|
181
181
|
@product_variant_prefix_ids = {}
|
|
182
|
+
@product_variant_images = {}
|
|
182
183
|
|
|
183
|
-
@product.variants.includes(:option_values).each do |variant|
|
|
184
|
+
@product.variants.includes(:option_values, primary_media: { attachment_attachment: :blob }).each do |variant|
|
|
184
185
|
@product_variant_ids[variant.human_name] = variant.id.to_s
|
|
185
186
|
@product_variant_prefix_ids[variant.human_name] = variant.to_param
|
|
187
|
+
|
|
188
|
+
image = variant.primary_media
|
|
189
|
+
if image.present? && image.attached? && image.variable?
|
|
190
|
+
@product_variant_images[variant.human_name] = helpers.spree_image_url(image, variant: :mini)
|
|
191
|
+
end
|
|
186
192
|
end
|
|
187
193
|
end
|
|
188
194
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class StockMovementsController < ResourceController
|
|
4
|
+
include ProductsBreadcrumbConcern
|
|
5
|
+
include TableConcern
|
|
6
|
+
|
|
7
|
+
before_action :add_breadcrumbs
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def collection_default_sort
|
|
12
|
+
'created_at desc'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def scope
|
|
16
|
+
super.joins(stock_item: [:variant, :stock_location]).
|
|
17
|
+
merge(current_store.variants.eligible).
|
|
18
|
+
reorder('')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def collection_includes
|
|
22
|
+
{
|
|
23
|
+
stock_item: {
|
|
24
|
+
stock_location: [],
|
|
25
|
+
variant: [option_values: :option_type, product: [variants: [:images], master: [:images]], images: []]
|
|
26
|
+
},
|
|
27
|
+
originator: []
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def add_breadcrumbs
|
|
32
|
+
add_breadcrumb Spree.t(:stock), spree.admin_stock_items_path
|
|
33
|
+
add_breadcrumb Spree.t(:stock_movements), spree.admin_stock_movements_path
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -293,7 +293,9 @@ module Spree
|
|
|
293
293
|
max = options[:max] || 100
|
|
294
294
|
percentage = (value.to_f / max * 100).round
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
css_class = options[:class] || 'progress'
|
|
297
|
+
|
|
298
|
+
content_tag(:div, class: css_class) do
|
|
297
299
|
content_tag(:div,
|
|
298
300
|
{ class: 'progress-bar', role: 'progressbar', style: "width: #{percentage}%",
|
|
299
301
|
aria: { valuenow: value, valuemin: min, valuemax: max } }) do
|
|
@@ -359,7 +359,7 @@ module Spree
|
|
|
359
359
|
private
|
|
360
360
|
|
|
361
361
|
def sort_dropdown_toggle(current_direction, current_label)
|
|
362
|
-
dropdown_toggle(class: 'btn-light btn-sm
|
|
362
|
+
dropdown_toggle(class: 'btn-light btn-sm') do
|
|
363
363
|
safe_join([
|
|
364
364
|
icon(current_direction == 'asc' ? 'sort-ascending' : 'sort-descending'),
|
|
365
365
|
content_tag(:span, current_label),
|
|
@@ -35,6 +35,7 @@ export default class extends CheckboxSelectAll {
|
|
|
35
35
|
currencies: Array,
|
|
36
36
|
variantIds: Object,
|
|
37
37
|
variantPrefixIds: Object,
|
|
38
|
+
variantImages: Object,
|
|
38
39
|
currentStockLocationId: String,
|
|
39
40
|
stockLocations: Array,
|
|
40
41
|
optionValuesSelectOptions: Array,
|
|
@@ -533,6 +534,14 @@ export default class extends CheckboxSelectAll {
|
|
|
533
534
|
}
|
|
534
535
|
}
|
|
535
536
|
|
|
537
|
+
const variantImageUrl = this.variantImagesValue?.[internalName]
|
|
538
|
+
if (variantImageUrl) {
|
|
539
|
+
const thumbnailContainer = variantTarget.querySelector('[data-slot="variantThumbnail"]')
|
|
540
|
+
if (thumbnailContainer) {
|
|
541
|
+
thumbnailContainer.innerHTML = `<div class="overflow-hidden rounded-md border border-gray-300" style="width: 36px; height: 36px;"><img src="${variantImageUrl}" width="36" height="36" alt="" class="object-cover transition-transform duration-300 ease-out hover:scale-120" loading="lazy"></div>`
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
536
545
|
let previousVariant = null
|
|
537
546
|
|
|
538
547
|
if (i > 0) {
|
|
@@ -389,7 +389,7 @@ module Spree
|
|
|
389
389
|
|
|
390
390
|
@template.content_tag(:div, class: 'input-group') do
|
|
391
391
|
prepend_html = if prepend.present?
|
|
392
|
-
@template.content_tag(:div, prepend, class: 'pl-
|
|
392
|
+
@template.content_tag(:div, prepend, class: 'pl-2 text-gray-400')
|
|
393
393
|
else
|
|
394
394
|
''.html_safe
|
|
395
395
|
end
|
|
@@ -13,6 +13,7 @@ module Spree
|
|
|
13
13
|
[
|
|
14
14
|
*metadata_rows,
|
|
15
15
|
:separator,
|
|
16
|
+
market_row,
|
|
16
17
|
locale_row,
|
|
17
18
|
currency_row,
|
|
18
19
|
subtotal_row,
|
|
@@ -72,6 +73,16 @@ module Spree
|
|
|
72
73
|
rows
|
|
73
74
|
end
|
|
74
75
|
|
|
76
|
+
def market_row
|
|
77
|
+
return nil if order.market.blank?
|
|
78
|
+
|
|
79
|
+
{
|
|
80
|
+
label: Spree.t(:market),
|
|
81
|
+
value: order.market.name,
|
|
82
|
+
id: 'market'
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
75
86
|
def locale_row
|
|
76
87
|
return nil if order.locale.blank?
|
|
77
88
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<%= Spree.t('admin.dashboard.hi') %> <%= try_spree_current_user.first_name %>!
|
|
5
5
|
</h2>
|
|
6
6
|
<p class="mb-4">
|
|
7
|
-
<%= Spree.t('admin.dashboard.
|
|
7
|
+
<%= Spree.t('admin.dashboard.whats_happening_on_html', store_name: current_store.name) %>
|
|
8
8
|
</p>
|
|
9
9
|
</div>
|
|
10
10
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<%= turbo_frame_tag :drawer do %>
|
|
2
|
-
<%= drawer_header(Spree.t(:import) + ' ' + Spree.t(@import.type.demodulize.pluralize
|
|
2
|
+
<%= drawer_header(Spree.t(:import) + ' ' + Spree.t(@import.type.demodulize.underscore.pluralize)) %>
|
|
3
3
|
<%= form_for @import, url: spree.admin_imports_path, data: { controller: 'import-form' } do |f| %>
|
|
4
4
|
<div class="drawer-body">
|
|
5
5
|
<%= f.hidden_field :type %>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<div class="card-body">
|
|
9
9
|
<%= f.spree_text_field :name, required: true %>
|
|
10
10
|
|
|
11
|
-
<%= f.spree_select :country_ids, @countries.map { |country| ["#{Spree::Country.iso_to_emoji_flag(country.iso)} #{country.name}", country.id] }, { include_blank: false, label: Spree.t(:
|
|
11
|
+
<%= f.spree_select :country_ids, @countries.map { |country| ["#{Spree::Country.iso_to_emoji_flag(country.iso)} #{country.name}", country.id] }, { include_blank: false, label: Spree.t(:countries), autocomplete: true, multiple: true } %>
|
|
12
12
|
|
|
13
13
|
<%= f.spree_select :currency, currency_options(f.object.currency), { label: Spree.t(:currency), required: true, autocomplete: true } %>
|
|
14
14
|
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
<%= f.spree_text_field :name, label: Spree.t(:internal_name), data: { slug_form_target: :url }, help_text: raw("This is used internally to identify the option type. <strong>It must be unique.</strong>") %>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
15
|
+
<div class="grid grid-cols-12 gap-6 mb-6">
|
|
16
|
+
<div class="col-span-12 md:col-span-6">
|
|
17
|
+
<%= f.spree_select :kind,
|
|
18
|
+
Spree::OptionType::KINDS.map { |k| [Spree.t("option_type_kinds.#{k}"), k] },
|
|
19
|
+
{ label: Spree.t(:kind), help: Spree.t(:option_type_kind_info) } %>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
15
22
|
<div class="grid grid-cols-12 gap-6">
|
|
16
23
|
<div class="col-span-12 md:col-span-6">
|
|
17
24
|
<%= f.spree_check_box :filterable, help_text: raw(Spree.t('option_type_filterable_info')) %>
|
|
@@ -38,6 +45,7 @@
|
|
|
38
45
|
<th scope="col"></th>
|
|
39
46
|
<th scope="col"><%= raw(Spree.t(:presentation) + required_span_tag) %></th>
|
|
40
47
|
<th scope="col"><%= raw(Spree.t(:internal_name) + required_span_tag) %></th>
|
|
48
|
+
<th scope="col"><%= Spree.t(:color_code) %></th>
|
|
41
49
|
<th scope="col"></th>
|
|
42
50
|
</tr>
|
|
43
51
|
</thead>
|
|
@@ -51,7 +59,7 @@
|
|
|
51
59
|
<tr data-nested-form-target="target"></tr>
|
|
52
60
|
|
|
53
61
|
<tr class="hover-none">
|
|
54
|
-
<td colspan="
|
|
62
|
+
<td colspan="5" class="text-center p-2">
|
|
55
63
|
<button type="button" data-action="nested-form#add" class="btn btn-secondary py-3 w-full" id="add_option_value_button">
|
|
56
64
|
<%= icon('plus') %>
|
|
57
65
|
<%= Spree.t(:add_one) %>
|
|
@@ -14,12 +14,26 @@
|
|
|
14
14
|
<% end %>
|
|
15
15
|
<%= f.hidden_field :id %>
|
|
16
16
|
</td>
|
|
17
|
-
<td class="w-
|
|
17
|
+
<td class="w-40 presentation">
|
|
18
18
|
<%= f.text_field :presentation, class: "form-input", data: { slug_form_target: :name, action: 'slug-form#updateUrlFromName' } %>
|
|
19
19
|
</td>
|
|
20
20
|
<td class="w-40 name">
|
|
21
21
|
<%= f.text_field :name, class: "form-input", data: { slug_form_target: :url } %>
|
|
22
22
|
</td>
|
|
23
|
+
<td class="w-5 color_code">
|
|
24
|
+
<div data-controller="color-picker" data-color-picker-clear-value="true" data-color-picker-default-color-value="#000000">
|
|
25
|
+
<div class="flex items-center gap-2">
|
|
26
|
+
<button type="button"
|
|
27
|
+
data-color-picker-target="picker"
|
|
28
|
+
class="w-8 h-8 rounded border border-gray-300 cursor-pointer shrink-0"
|
|
29
|
+
style="background: <%= f.object.color_code.presence || 'white' %>;">
|
|
30
|
+
</button>
|
|
31
|
+
<span data-color-picker-target="value" class="text-sm text-gray-500"><%= f.object.color_code %></span>
|
|
32
|
+
</div>
|
|
33
|
+
<%= f.hidden_field :color_code, data: { color_picker_target: :input } %>
|
|
34
|
+
<span data-color-picker-target="display" class="hidden"></span>
|
|
35
|
+
</div>
|
|
36
|
+
</td>
|
|
23
37
|
<td class="w-10 actions">
|
|
24
38
|
<button type="button" class="btn btn-danger btn-sm remove_option_value_button" data-action="nested-form#remove">
|
|
25
39
|
<%= icon('trash', class: 'mr-0') %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<% order ||= shipment.order %>
|
|
2
|
-
<%= turbo_frame_tag dom_id(shipment), class: "card
|
|
2
|
+
<%= turbo_frame_tag dom_id(shipment), class: "card" do %>
|
|
3
3
|
<div class="card-header items-center justify-between">
|
|
4
4
|
<div class="flex items-center gap-2">
|
|
5
5
|
<span class="flex items-center"><%= shipment_state(shipment.state) %></span>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<ul class="list-group mb-6">
|
|
20
20
|
<% @payment_methods.each do |payment_method| %>
|
|
21
21
|
<li class="list-group-item p-0 overflow-hidden">
|
|
22
|
-
<%= link_to spree.new_admin_order_payment_path(@order, payment_method_id: payment_method.id), class: "form-check-label flex items-center gap-4 px-
|
|
22
|
+
<%= link_to spree.new_admin_order_payment_path(@order, payment_method_id: payment_method.id), class: "form-check-label flex items-center gap-4 px-3 py-3 w-full cursor-pointer hover:bg-gray-25 text-gray-900 no-underline" do %>
|
|
23
23
|
<div class="form-check flex items-center">
|
|
24
24
|
<%= f.radio_button :payment_method_id, payment_method.id, class: "form-check-input" %>
|
|
25
25
|
</div>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<%= f.fields_for :source, @payment.source do |source_form| %>
|
|
4
4
|
<% previous_cards.each do |card| %>
|
|
5
5
|
<li class="list-group-item p-0">
|
|
6
|
-
<%= source_form.label :id, value: card.id, class: "form-check-label flex items-center gap-4 px-
|
|
6
|
+
<%= source_form.label :id, value: card.id, class: "form-check-label flex items-center gap-4 px-3 py-3 w-full cursor-pointer hover:bg-gray-25" do %>
|
|
7
7
|
<div class="form-check flex items-center">
|
|
8
8
|
<%= source_form.radio_button :id, card.id, class: "form-check-input" %>
|
|
9
9
|
</div>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<%= f.fields_for :source, @payment.source do |source_form| %>
|
|
4
4
|
<% @store_credits.each do |credit| %>
|
|
5
5
|
<li class="list-group-item p-0">
|
|
6
|
-
<%= source_form.label :id, value: credit.id, class: "form-check-label flex items-center gap-4 px-
|
|
6
|
+
<%= source_form.label :id, value: credit.id, class: "form-check-label flex items-center gap-4 px-3 py-3 w-full cursor-pointer hover:bg-gray-25" do %>
|
|
7
7
|
<div class="form-check flex items-center">
|
|
8
8
|
<%= source_form.radio_button :id, credit.id, class: "form-check-input", checked: @payment.source.id == credit.id || @store_credits.first.id == credit.id %>
|
|
9
9
|
</div>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<% content_for :page_title do %>
|
|
2
|
+
<%= Spree.t(:translations) %>
|
|
3
|
+
<% end %>
|
|
4
|
+
|
|
5
|
+
<% content_for :page_actions do %>
|
|
6
|
+
<%= link_to_with_icon 'table-import', Spree.t(:import), spree.new_admin_import_path(type: 'Spree::Imports::ProductTranslations'), class: 'btn btn-light', data: { action: 'drawer#open', turbo_frame: :drawer } if can?(:create, Spree::Import) %>
|
|
7
|
+
<%= link_to_export_modal if can?(:create, Spree::Export) %>
|
|
8
|
+
<% end if @locales.any? %>
|
|
9
|
+
|
|
10
|
+
<% if @locales.empty? %>
|
|
11
|
+
<div class="card-lg">
|
|
12
|
+
<div class="text-center py-16">
|
|
13
|
+
<%= icon 'language', class: 'w-12 h-12 mx-auto mb-4 text-gray-400' %>
|
|
14
|
+
<h3 class="text-lg font-medium text-gray-900 mb-2"><%= Spree.t('admin.product_translations.no_locales_title') %></h3>
|
|
15
|
+
<p class="text-gray-500 mb-4"><%= Spree.t('admin.product_translations.no_locales_description') %></p>
|
|
16
|
+
<%= link_to Spree.t('admin.product_translations.manage_markets'), spree.admin_markets_path, class: 'btn btn-primary' %>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<% else %>
|
|
20
|
+
<%= render 'spree/admin/shared/export_modal', export_type: Spree::Exports::ProductTranslations %>
|
|
21
|
+
|
|
22
|
+
<div class="card-lg mb-6">
|
|
23
|
+
<div class="card-header">
|
|
24
|
+
<h3 class="card-title"><%= Spree.t('admin.product_translations.coverage') %></h3>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="card-body p-0">
|
|
27
|
+
<div class="table-responsive">
|
|
28
|
+
<table class="table mb-0">
|
|
29
|
+
<thead>
|
|
30
|
+
<tr>
|
|
31
|
+
<th><%= Spree.t('admin.product_translations.locale') %></th>
|
|
32
|
+
<th class="text-center"><%= Spree.t('admin.product_translations.translated') %></th>
|
|
33
|
+
<th class="text-center"><%= Spree.t('admin.product_translations.total') %></th>
|
|
34
|
+
<th style="width: 40%;"><%= Spree.t('admin.product_translations.progress') %></th>
|
|
35
|
+
</tr>
|
|
36
|
+
</thead>
|
|
37
|
+
<tbody>
|
|
38
|
+
<% @coverage.each do |row| %>
|
|
39
|
+
<tr>
|
|
40
|
+
<td>
|
|
41
|
+
<strong><%= Spree.t('i18n.this_file_language', locale: row[:locale], default: row[:locale]) %></strong>
|
|
42
|
+
<span class="text-gray-400 ml-1"><%= row[:locale] %></span>
|
|
43
|
+
</td>
|
|
44
|
+
<td class="text-center"><%= row[:translated] %></td>
|
|
45
|
+
<td class="text-center"><%= row[:total] %></td>
|
|
46
|
+
<td>
|
|
47
|
+
<div class="flex items-center gap-3">
|
|
48
|
+
<%= progress_bar_component(row[:percentage].to_i, min: 0, max: 100, class: 'progress w-4/5') %>
|
|
49
|
+
<span class="text-sm text-gray-500 whitespace-nowrap"><%= row[:percentage] %>%</span>
|
|
50
|
+
</div>
|
|
51
|
+
</td>
|
|
52
|
+
</tr>
|
|
53
|
+
<% end %>
|
|
54
|
+
</tbody>
|
|
55
|
+
</table>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="card-lg">
|
|
61
|
+
<div class="card-header">
|
|
62
|
+
<h3 class="card-title"><%= Spree.t(:products) %></h3>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="card-body p-0">
|
|
65
|
+
<% if @products.any? %>
|
|
66
|
+
<div class="table-responsive">
|
|
67
|
+
<table class="table">
|
|
68
|
+
<thead>
|
|
69
|
+
<tr>
|
|
70
|
+
<th><%= Spree.t(:product) %></th>
|
|
71
|
+
<% @locales.each do |locale| %>
|
|
72
|
+
<th class="text-center"><%= locale %></th>
|
|
73
|
+
<% end %>
|
|
74
|
+
</tr>
|
|
75
|
+
</thead>
|
|
76
|
+
<tbody>
|
|
77
|
+
<% @products.each do |product| %>
|
|
78
|
+
<tr>
|
|
79
|
+
<td>
|
|
80
|
+
<%= link_to spree.edit_admin_translation_path(resource_type: 'Spree::Product', id: product.id),
|
|
81
|
+
data: { action: 'drawer#open', turbo_frame: :drawer }, class: 'flex items-center gap-3 no-underline' do %>
|
|
82
|
+
<%= render 'spree/admin/shared/product_image', object: product %>
|
|
83
|
+
<span class="text-gray-900 font-medium">
|
|
84
|
+
<%= product.name %>
|
|
85
|
+
</span>
|
|
86
|
+
<% end %>
|
|
87
|
+
</td>
|
|
88
|
+
<% @locales.each do |locale| %>
|
|
89
|
+
<td class="text-center">
|
|
90
|
+
<% if @translated_locales_map[product.id]&.include?(locale) %>
|
|
91
|
+
<%= icon 'circle-check-filled', class: 'text-green-500' %>
|
|
92
|
+
<% else %>
|
|
93
|
+
<span class="text-gray-300">—</span>
|
|
94
|
+
<% end %>
|
|
95
|
+
</td>
|
|
96
|
+
<% end %>
|
|
97
|
+
</tr>
|
|
98
|
+
<% end %>
|
|
99
|
+
</tbody>
|
|
100
|
+
</table>
|
|
101
|
+
<%= render 'spree/admin/shared/index_table_options', collection: @products %>
|
|
102
|
+
</div>
|
|
103
|
+
<% else %>
|
|
104
|
+
<%= render 'spree/admin/shared/no_resource_found', new_object_url: nil %>
|
|
105
|
+
<% end %>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
<% end %>
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<% if @product_prices.present? %> data-variants-form-prices-value="<%= @product_prices.to_json %>" <% end %>
|
|
23
23
|
<% if @product_variant_ids.present? %> data-variants-form-variant-ids-value="<%= @product_variant_ids.to_json %>" <% end %>
|
|
24
24
|
<% if @product_variant_prefix_ids.present? %> data-variants-form-variant-prefix-ids-value="<%= @product_variant_prefix_ids.to_json %>" <% end %>
|
|
25
|
+
<% if @product_variant_images.present? %> data-variants-form-variant-images-value="<%= @product_variant_images.to_json %>" <% end %>
|
|
25
26
|
>
|
|
26
27
|
<div class="options-creator">
|
|
27
28
|
<%= render 'spree/admin/products/form/variants/option_template', option_types_for_select: option_types_for_select %>
|
|
@@ -145,6 +146,8 @@
|
|
|
145
146
|
</div>
|
|
146
147
|
</div>
|
|
147
148
|
<% end%>
|
|
149
|
+
<div class="variants-table__header__cell column-thumbnail">
|
|
150
|
+
</div>
|
|
148
151
|
<div class="variants-table__header__cell column-variant">
|
|
149
152
|
<%= Spree.t(:variant) %>
|
|
150
153
|
<button data-variants-form-target="deleteButton" data-action="variants-form#deleteSelected" type="button" class="btn btn-danger btn-sm hidden ml-12">
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
<% end %>
|
|
15
|
+
<div class="variants-table__body__cell column-thumbnail pr-2" data-slot="variantThumbnail">
|
|
16
|
+
<%= render 'spree/admin/shared/no_image', width: 36, height: 36 %>
|
|
17
|
+
</div>
|
|
15
18
|
<div class="variants-table__body__cell column-variant" data-slot="variantName">
|
|
16
19
|
Medium
|
|
17
20
|
</div>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<% badge_name ||= label %>
|
|
3
3
|
<% placeholder ||= [Spree.t(:search), controller_name.humanize.downcase].join(' ') %>
|
|
4
4
|
|
|
5
|
-
<div class="form-input flex items-center py-0 focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-blue-500 grow max-lg:max-w-[300px] mr-auto
|
|
5
|
+
<div class="form-input flex items-center py-0 focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-blue-500 grow max-lg:max-w-[300px] mr-auto max-lg:mb-4 transition-all duration-100 ease-in-out" id="filters-search-bar">
|
|
6
6
|
<%= icon "search", class: "mr-4 text-gray-600" %>
|
|
7
7
|
<%= search_field_tag "q[#{param}]", params.dig(:q, param), class: "outline-none border-0 h-full focus:border-0 focus:ring-0 p-0 text-base w-full", placeholder: placeholder, data: { filters_target: :input, badge_name: badge_name } %>
|
|
8
8
|
</div>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
21
21
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
22
|
-
<link href="https://fonts.googleapis.com/css2?family=
|
|
22
|
+
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap" rel="stylesheet">
|
|
23
23
|
|
|
24
24
|
<%= stylesheet_link_tag 'spree/admin/application', media: :all, data: { turbo_track: "reload" } %>
|
|
25
25
|
<%= tinymce_assets %>
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
<%= form_with model: @shipment, url: spree.admin_order_shipment_path(@order, @shipment), class: "w-full flex justify-between items-center" do |f| %>
|
|
3
3
|
<div>
|
|
4
4
|
<%= f.select :selected_shipping_rate_id, options_for_select(@shipment.shipping_rates.map {|sr| ["#{sr.name} #{sr.display_price}", sr.id] }, @shipment.selected_shipping_rate_id),
|
|
5
|
-
{}, class: 'form-select', autofocus: true %>
|
|
5
|
+
{}, class: 'form-select form-select-sm', autofocus: true %>
|
|
6
6
|
</div>
|
|
7
7
|
<div class="flex h-full items-center gap-2">
|
|
8
8
|
<% if can? :update, @shipment %>
|
|
9
|
-
<%= turbo_save_button_tag Spree.t('actions.save'), data: { turbo_frame: :_top }, type: :submit, class: 'btn btn-primary' %>
|
|
10
|
-
<%= link_to Spree.t('actions.discard'), spree.edit_admin_order_path(@order), class: "btn btn-light" %>
|
|
9
|
+
<%= turbo_save_button_tag Spree.t('actions.save'), data: { turbo_frame: :_top }, type: :submit, class: 'btn btn-sm btn-primary' %>
|
|
10
|
+
<%= link_to Spree.t('actions.discard'), spree.edit_admin_order_path(@order), class: "btn btn-sm btn-light" %>
|
|
11
11
|
<% end %>
|
|
12
12
|
</div>
|
|
13
13
|
<% end %>
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
<%= form_with model: @shipment, url: spree.admin_order_shipment_path(@order, @shipment), class: "w-full py-1 flex justify-between items-center" do |f| %>
|
|
17
17
|
<div class="flex items-center text-nowrap gap-x-3 items-center grow mr-3">
|
|
18
18
|
<%= f.label :tracking, Spree.t(:tracking_number), class: 'mb-0' %>
|
|
19
|
-
<%= f.text_field :tracking, class: 'form-input', required: true, autofocus: true %>
|
|
19
|
+
<%= f.text_field :tracking, class: 'form-input form-input-sm', required: true, autofocus: true %>
|
|
20
20
|
</div>
|
|
21
21
|
<div class="flex h-full items-center gap-2">
|
|
22
22
|
<% if can? :update, @shipment %>
|
|
23
|
-
<%= turbo_save_button_tag Spree.t('actions.save'), data: { turbo_frame: dom_id(@shipment) }, type: :submit, class: 'btn btn-primary' %>
|
|
24
|
-
<%= link_to Spree.t('actions.discard'), spree.edit_admin_order_path(@order), class: "btn btn-light" %>
|
|
23
|
+
<%= turbo_save_button_tag Spree.t('actions.save'), data: { turbo_frame: dom_id(@shipment) }, type: :submit, class: 'btn btn-sm btn-primary' %>
|
|
24
|
+
<%= link_to Spree.t('actions.discard'), spree.edit_admin_order_path(@order), class: "btn btn-sm btn-light" %>
|
|
25
25
|
<% end %>
|
|
26
26
|
</div>
|
|
27
27
|
<% end %>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<% content_for :page_title do %>
|
|
2
|
+
<%= Spree.t(:stock) %>
|
|
3
|
+
<% end %>
|
|
4
|
+
|
|
5
|
+
<% content_for :page_tabs do %>
|
|
6
|
+
<%= render "spree/admin/shared/stock_nav" %>
|
|
7
|
+
<% end %>
|
|
8
|
+
|
|
9
|
+
<% content_for :page_actions do %>
|
|
10
|
+
<%= render_admin_partials(:stock_movements_actions_partials) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<%= render_admin_partials(:stock_movements_header_partials) %>
|
|
14
|
+
|
|
15
|
+
<%= render_table @collection, :stock_movements, edit_object_url: nil %>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<%= hidden_field_tag :redirect_url, request.fullpath %>
|
|
8
8
|
|
|
9
9
|
<%= dropdown(portal: false) do %>
|
|
10
|
-
<%= dropdown_toggle(class: 'btn-light btn-sm
|
|
10
|
+
<%= dropdown_toggle(class: 'btn-light btn-sm') do %>
|
|
11
11
|
<%= icon 'columns-3' %>
|
|
12
12
|
<span><%= Spree.t('admin.tables.columns') %></span>
|
|
13
13
|
<%= icon 'chevron-down' %>
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
<%= render 'spree/admin/shared/export_modal', export_type: export_type %>
|
|
12
12
|
<% end %>
|
|
13
13
|
<div class="<%= local_assigns[:container_class] || 'card-lg' %>" data-controller="table" data-table-url-value="<%= request.path %>">
|
|
14
|
-
<div class="p-
|
|
14
|
+
<div class="p-2 border-b border-gray-200">
|
|
15
15
|
<div class="flex flex-col lg:flex-row gap-3 items-start lg:items-center justify-between">
|
|
16
16
|
<div class="flex gap-2 items-center flex-wrap">
|
|
17
17
|
<%= search_form_for @search, url: url_for, html: { data: { turbo_frame: frame_name, turbo_action: 'advance', controller: 'auto-submit search-clear', auto_submit_delay_value: 300 } } do |f| %>
|
|
18
|
-
<div class="form-input flex items-center py-0 pr-1 focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-blue-500 lg:w-[300px] mr-auto h-[
|
|
18
|
+
<div class="form-input flex items-center py-0 pr-1 focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-blue-500 lg:w-[300px] mr-auto h-[2rem] transition-all duration-100 ease-in-out">
|
|
19
19
|
<%= icon "search", class: "mr-4 text-gray-600 shrink-0" %>
|
|
20
20
|
<%= search_field_tag "q[#{search_param}]",
|
|
21
21
|
params.dig(:q, search_param),
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
date_to_input_name: "q[#{date_range_param}_lt]",
|
|
56
56
|
date_from_value: params.dig(:q, :"#{date_range_param}_gt"),
|
|
57
57
|
date_to_value: params.dig(:q, :"#{date_range_param}_lt"),
|
|
58
|
-
css_classes: "btn-light btn-sm
|
|
58
|
+
css_classes: "btn-light btn-sm" %>
|
|
59
59
|
<%# Preserve search and filter state when submitting date range %>
|
|
60
60
|
<% if params.dig(:q, search_param).present? %>
|
|
61
61
|
<%= hidden_field_tag "q[#{search_param}]", params.dig(:q, search_param) %>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<%# locals: (record:, column:, value:) %>
|
|
2
|
+
<% originator = record.originator %>
|
|
3
|
+
<% if originator.is_a?(Spree::StockTransfer) %>
|
|
4
|
+
<%= originator.class.model_name.human %>
|
|
5
|
+
<% if can?(:show, originator) %>
|
|
6
|
+
<%= link_to originator.number, spree.admin_stock_transfer_path(originator), data: { turbo_frame: '_top' } %>
|
|
7
|
+
<% else %>
|
|
8
|
+
<%= originator.number %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% elsif originator.is_a?(Spree::Shipment) %>
|
|
11
|
+
<%= originator.class.model_name.human %>
|
|
12
|
+
<% if can?(:show, originator.order) %>
|
|
13
|
+
<%= link_to originator.number, spree.edit_admin_order_path(originator.order), data: { turbo_frame: '_top' } %>
|
|
14
|
+
<% else %>
|
|
15
|
+
<%= originator.number %>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% elsif originator.is_a?(Spree::ReturnAuthorization) %>
|
|
18
|
+
<%= originator.class.model_name.human %>
|
|
19
|
+
<% if can?(:show, originator.order) %>
|
|
20
|
+
<%= link_to originator.number, spree.edit_admin_order_path(originator.order), data: { turbo_frame: '_top' } %>
|
|
21
|
+
<% else %>
|
|
22
|
+
<%= originator.number %>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% elsif originator.present? %>
|
|
25
|
+
<%= originator.class.model_name.human %>
|
|
26
|
+
<% else %>
|
|
27
|
+
<span class="text-gray-400"><%= Spree.t(:manual) %></span>
|
|
28
|
+
<% end %>
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<p class="text-center mb-3"><%= Spree.t('admin.translations.no_translations_configured') %></p>
|
|
33
33
|
|
|
34
34
|
<% if can?(:edit, current_store) %>
|
|
35
|
-
<%= link_to_with_icon 'world', Spree.t('admin.
|
|
35
|
+
<%= link_to_with_icon 'world', Spree.t('admin.manage_markets'), spree.admin_markets_path, class: 'btn btn-primary', data: { 'turbo-frame': '_top' } %>
|
|
36
36
|
<% end %>
|
|
37
37
|
</div>
|
|
38
38
|
</div>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</h5>
|
|
6
6
|
|
|
7
7
|
<% if can?(:manage, Spree::Store) %>
|
|
8
|
-
<%= link_to_with_icon '
|
|
8
|
+
<%= link_to_with_icon 'world', Spree.t('admin.manage_markets'), spree.admin_markets_path, class: 'btn btn-sm btn-light' %>
|
|
9
9
|
<% end %>
|
|
10
10
|
</div>
|
|
11
11
|
<div class="card-body p-0">
|
|
@@ -107,8 +107,16 @@ Rails.application.config.after_initialize do
|
|
|
107
107
|
label: :stock,
|
|
108
108
|
url: :admin_stock_items_path,
|
|
109
109
|
position: 20,
|
|
110
|
-
active: -> { %w[stock_items stock_transfers].include?(controller_name) },
|
|
111
|
-
if: -> { can?(:manage, Spree::StockItem) || can?(:manage, Spree::StockTransfer) }
|
|
110
|
+
active: -> { %w[stock_items stock_movements stock_transfers].include?(controller_name) },
|
|
111
|
+
if: -> { can?(:manage, Spree::StockItem) || can?(:manage, Spree::StockMovement) || can?(:manage, Spree::StockTransfer) }
|
|
112
|
+
|
|
113
|
+
# Translations
|
|
114
|
+
products.add :translations,
|
|
115
|
+
label: :translations,
|
|
116
|
+
url: :admin_product_translations_path,
|
|
117
|
+
position: 25,
|
|
118
|
+
active: -> { controller_name == 'product_translations' },
|
|
119
|
+
if: -> { can?(:manage, Spree::Product) && current_store.supported_locales_list.size > 1 }
|
|
112
120
|
|
|
113
121
|
# Taxonomies
|
|
114
122
|
products.add :taxonomies,
|
|
@@ -411,10 +419,17 @@ Rails.application.config.after_initialize do
|
|
|
411
419
|
active: -> { controller_name == 'stock_items' },
|
|
412
420
|
if: -> { can?(:manage, Spree::StockItem) }
|
|
413
421
|
|
|
422
|
+
stock_tabs_nav.add :stock_movements,
|
|
423
|
+
label: :stock_movements,
|
|
424
|
+
url: :admin_stock_movements_path,
|
|
425
|
+
position: 20,
|
|
426
|
+
active: -> { controller_name == 'stock_movements' },
|
|
427
|
+
if: -> { can?(:manage, Spree::StockMovement) }
|
|
428
|
+
|
|
414
429
|
stock_tabs_nav.add :stock_transfers,
|
|
415
430
|
label: :stock_transfers,
|
|
416
431
|
url: :admin_stock_transfers_path,
|
|
417
|
-
position:
|
|
432
|
+
position: 30,
|
|
418
433
|
active: -> { controller_name == 'stock_transfers' },
|
|
419
434
|
if: -> { can?(:manage, Spree::StockTransfer) }
|
|
420
435
|
|
|
@@ -933,6 +933,69 @@ Rails.application.config.after_initialize do
|
|
|
933
933
|
default: false,
|
|
934
934
|
position: 70
|
|
935
935
|
|
|
936
|
+
# Register Stock Movements table
|
|
937
|
+
Spree.admin.tables.register(:stock_movements, model_class: Spree::StockMovement, search_param: :stock_item_variant_product_name_cont, row_actions: false, new_resource: false)
|
|
938
|
+
|
|
939
|
+
Spree.admin.tables.stock_movements.add :variant,
|
|
940
|
+
label: :variant,
|
|
941
|
+
type: :custom,
|
|
942
|
+
sortable: false,
|
|
943
|
+
filterable: true,
|
|
944
|
+
default: true,
|
|
945
|
+
position: 10,
|
|
946
|
+
ransack_attribute: 'stock_item_variant_product_name',
|
|
947
|
+
partial: 'spree/admin/variants/variant',
|
|
948
|
+
partial_locals: ->(record) { { variant: record.variant } }
|
|
949
|
+
|
|
950
|
+
Spree.admin.tables.stock_movements.add :stock_location,
|
|
951
|
+
label: :stock_location,
|
|
952
|
+
type: :custom,
|
|
953
|
+
filter_type: :autocomplete,
|
|
954
|
+
sortable: false,
|
|
955
|
+
filterable: true,
|
|
956
|
+
default: true,
|
|
957
|
+
position: 20,
|
|
958
|
+
ransack_attribute: 'stock_item_stock_location_id',
|
|
959
|
+
operators: %i[eq],
|
|
960
|
+
search_url: ->(view_context) { view_context.spree.admin_stock_locations_select_options_path(format: :json) },
|
|
961
|
+
partial: 'spree/admin/tables/columns/stock_item_location',
|
|
962
|
+
partial_locals: ->(record) { { record: record.stock_item } }
|
|
963
|
+
|
|
964
|
+
Spree.admin.tables.stock_movements.add :quantity,
|
|
965
|
+
label: :quantity,
|
|
966
|
+
type: :number,
|
|
967
|
+
sortable: true,
|
|
968
|
+
filterable: false,
|
|
969
|
+
default: true,
|
|
970
|
+
position: 30
|
|
971
|
+
|
|
972
|
+
Spree.admin.tables.stock_movements.add :originator,
|
|
973
|
+
label: :originator,
|
|
974
|
+
type: :custom,
|
|
975
|
+
filter_type: :select,
|
|
976
|
+
sortable: false,
|
|
977
|
+
filterable: true,
|
|
978
|
+
default: true,
|
|
979
|
+
position: 40,
|
|
980
|
+
ransack_attribute: 'originator_type',
|
|
981
|
+
operators: %i[eq],
|
|
982
|
+
value_options: -> {
|
|
983
|
+
[
|
|
984
|
+
{ value: 'Spree::Shipment', label: Spree::Shipment.model_name.human },
|
|
985
|
+
{ value: 'Spree::StockTransfer', label: Spree::StockTransfer.model_name.human },
|
|
986
|
+
{ value: 'Spree::ReturnAuthorization', label: Spree::ReturnAuthorization.model_name.human }
|
|
987
|
+
]
|
|
988
|
+
},
|
|
989
|
+
partial: 'spree/admin/tables/columns/stock_movement_originator'
|
|
990
|
+
|
|
991
|
+
Spree.admin.tables.stock_movements.add :created_at,
|
|
992
|
+
label: :created_at,
|
|
993
|
+
type: :datetime,
|
|
994
|
+
sortable: true,
|
|
995
|
+
filterable: true,
|
|
996
|
+
default: true,
|
|
997
|
+
position: 50
|
|
998
|
+
|
|
936
999
|
# Register Metafield Definitions table
|
|
937
1000
|
Spree.admin.tables.register(:metafield_definitions, model_class: Spree::MetafieldDefinition, search_param: :search, row_actions: true)
|
|
938
1001
|
|
data/config/locales/en.yml
CHANGED
|
@@ -99,7 +99,7 @@ en:
|
|
|
99
99
|
hi: Hi
|
|
100
100
|
top_products: Top products
|
|
101
101
|
view_report: View report
|
|
102
|
-
|
|
102
|
+
whats_happening_on_html: Here's what's happening on <strong>%{store_name}</strong> today.
|
|
103
103
|
digital_shipment_fulfillment_note: This shipment will be marked as fulfilled once the user downloads the digital product
|
|
104
104
|
display_on_options:
|
|
105
105
|
back_end: Only on admin panel
|
|
@@ -143,7 +143,7 @@ en:
|
|
|
143
143
|
page_subtitle: Connect your store to third-party services to enhance customer experience.
|
|
144
144
|
json_preview:
|
|
145
145
|
no_api_response: No API response found for this resource
|
|
146
|
-
|
|
146
|
+
manage_markets: Manage Markets
|
|
147
147
|
manage_properties: Manage Properties
|
|
148
148
|
manage_stock_locations: Manage Stock Locations
|
|
149
149
|
manage_taxons: Manage Categories
|
|
@@ -244,6 +244,15 @@ en:
|
|
|
244
244
|
schedule: Schedule
|
|
245
245
|
scheduled: Price list has been scheduled
|
|
246
246
|
unschedule: Unschedule
|
|
247
|
+
product_translations:
|
|
248
|
+
coverage: Translation coverage
|
|
249
|
+
locale: Locale
|
|
250
|
+
manage_markets: Manage Markets
|
|
251
|
+
no_locales_description: Set up markets with additional locales to start translating your products.
|
|
252
|
+
no_locales_title: No additional locales configured
|
|
253
|
+
progress: Progress
|
|
254
|
+
total: Total
|
|
255
|
+
translated: Translated
|
|
247
256
|
products:
|
|
248
257
|
active: Active
|
|
249
258
|
all_statuses: All statuses
|
|
@@ -366,9 +375,8 @@ en:
|
|
|
366
375
|
manual: Manual
|
|
367
376
|
manual_info: Curate products manually. You can add or remove them in bulk.
|
|
368
377
|
translations:
|
|
369
|
-
manage_markets: Manage Markets
|
|
370
378
|
no_translations_configured: No translations configured. Please setup Markets to use translations.
|
|
371
|
-
upload_new_asset: Upload new
|
|
379
|
+
upload_new_asset: Upload new media
|
|
372
380
|
user:
|
|
373
381
|
last_order_placed: Last order placed
|
|
374
382
|
no_store_credit: Customer has no Store Credit available
|
data/config/routes.rb
CHANGED
|
@@ -27,8 +27,11 @@ Spree::Core::Engine.add_routes do
|
|
|
27
27
|
# variant search
|
|
28
28
|
post 'variants/search'
|
|
29
29
|
get 'variants/search', defaults: { format: :json }
|
|
30
|
+
# product translations
|
|
31
|
+
resources :product_translations, only: [:index]
|
|
30
32
|
# stock
|
|
31
33
|
resources :stock_items, only: [:index, :update, :destroy]
|
|
34
|
+
resources :stock_movements, only: [:index]
|
|
32
35
|
resources :stock_transfers, except: [:edit, :update]
|
|
33
36
|
# price lists
|
|
34
37
|
resources :price_lists do
|
data/lib/spree/admin/engine.rb
CHANGED
|
@@ -96,6 +96,8 @@ module Spree
|
|
|
96
96
|
:stock_items_header_partials,
|
|
97
97
|
:stock_locations_actions_partials,
|
|
98
98
|
:stock_locations_header_partials,
|
|
99
|
+
:stock_movements_actions_partials,
|
|
100
|
+
:stock_movements_header_partials,
|
|
99
101
|
:stock_nav_partials,
|
|
100
102
|
:stock_transfers_actions_partials,
|
|
101
103
|
:stock_transfers_filters_partials,
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_admin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.4.0.
|
|
4
|
+
version: 5.4.0.rc7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: spree
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 5.4.0.
|
|
19
|
+
version: 5.4.0.rc7
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 5.4.0.
|
|
26
|
+
version: 5.4.0.rc7
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: active_link_to
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -357,6 +357,7 @@ files:
|
|
|
357
357
|
- app/controllers/spree/admin/price_list_products_controller.rb
|
|
358
358
|
- app/controllers/spree/admin/price_lists_controller.rb
|
|
359
359
|
- app/controllers/spree/admin/price_rules_controller.rb
|
|
360
|
+
- app/controllers/spree/admin/product_translations_controller.rb
|
|
360
361
|
- app/controllers/spree/admin/products_controller.rb
|
|
361
362
|
- app/controllers/spree/admin/profile_controller.rb
|
|
362
363
|
- app/controllers/spree/admin/promotion_actions_controller.rb
|
|
@@ -379,6 +380,7 @@ files:
|
|
|
379
380
|
- app/controllers/spree/admin/shipping_methods_controller.rb
|
|
380
381
|
- app/controllers/spree/admin/stock_items_controller.rb
|
|
381
382
|
- app/controllers/spree/admin/stock_locations_controller.rb
|
|
383
|
+
- app/controllers/spree/admin/stock_movements_controller.rb
|
|
382
384
|
- app/controllers/spree/admin/stock_transfers_controller.rb
|
|
383
385
|
- app/controllers/spree/admin/store_credit_categories_controller.rb
|
|
384
386
|
- app/controllers/spree/admin/store_credits_controller.rb
|
|
@@ -615,6 +617,7 @@ files:
|
|
|
615
617
|
- app/views/spree/admin/gift_cards/new.html.erb
|
|
616
618
|
- app/views/spree/admin/gift_cards/show.html.erb
|
|
617
619
|
- app/views/spree/admin/import_mappings/update.turbo_stream.erb
|
|
620
|
+
- app/views/spree/admin/import_rows/_product.html.erb
|
|
618
621
|
- app/views/spree/admin/import_rows/_variant.html.erb
|
|
619
622
|
- app/views/spree/admin/import_rows/show.html.erb
|
|
620
623
|
- app/views/spree/admin/imports/_footer.html.erb
|
|
@@ -774,6 +777,7 @@ files:
|
|
|
774
777
|
- app/views/spree/admin/price_rules/forms/_volume_rule.html.erb
|
|
775
778
|
- app/views/spree/admin/price_rules/forms/_zone_rule.html.erb
|
|
776
779
|
- app/views/spree/admin/price_rules/new.html.erb
|
|
780
|
+
- app/views/spree/admin/product_translations/index.html.erb
|
|
777
781
|
- app/views/spree/admin/products/_edit_page_title.html.erb
|
|
778
782
|
- app/views/spree/admin/products/_form.html.erb
|
|
779
783
|
- app/views/spree/admin/products/_import_button.html.erb
|
|
@@ -942,6 +946,7 @@ files:
|
|
|
942
946
|
- app/views/spree/admin/stock_locations/edit.html.erb
|
|
943
947
|
- app/views/spree/admin/stock_locations/index.html.erb
|
|
944
948
|
- app/views/spree/admin/stock_locations/new.html.erb
|
|
949
|
+
- app/views/spree/admin/stock_movements/index.html.erb
|
|
945
950
|
- app/views/spree/admin/stock_transfers/_destination_movement_form.html.erb
|
|
946
951
|
- app/views/spree/admin/stock_transfers/_new_variant_modal.html.erb
|
|
947
952
|
- app/views/spree/admin/stock_transfers/_new_variant_template.html.erb
|
|
@@ -993,6 +998,7 @@ files:
|
|
|
993
998
|
- app/views/spree/admin/tables/columns/_stock_item_backorderable.html.erb
|
|
994
999
|
- app/views/spree/admin/tables/columns/_stock_item_count_on_hand.html.erb
|
|
995
1000
|
- app/views/spree/admin/tables/columns/_stock_item_location.html.erb
|
|
1001
|
+
- app/views/spree/admin/tables/columns/_stock_movement_originator.html.erb
|
|
996
1002
|
- app/views/spree/admin/tables/columns/_user_location.html.erb
|
|
997
1003
|
- app/views/spree/admin/tables/columns/_webhook_deliveries_stats.html.erb
|
|
998
1004
|
- app/views/spree/admin/tables/columns/_webhook_delivery_actions.html.erb
|
|
@@ -1095,7 +1101,6 @@ files:
|
|
|
1095
1101
|
- config/locales/en.yml
|
|
1096
1102
|
- config/routes.rb
|
|
1097
1103
|
- config/tailwind.config.js
|
|
1098
|
-
- db/migrate/20250217171018_create_action_text_video_embeds.rb
|
|
1099
1104
|
- lib/generators/spree/admin/devise/devise_generator.rb
|
|
1100
1105
|
- lib/generators/spree/admin/install/install_generator.rb
|
|
1101
1106
|
- lib/generators/spree/admin/install/templates/app/assets/tailwind/spree_admin.css.tt
|
|
@@ -1170,9 +1175,9 @@ licenses:
|
|
|
1170
1175
|
- BSD-3-Clause
|
|
1171
1176
|
metadata:
|
|
1172
1177
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1173
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.
|
|
1178
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.rc7
|
|
1174
1179
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1175
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.0.
|
|
1180
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.0.rc7
|
|
1176
1181
|
post_install_message:
|
|
1177
1182
|
rdoc_options: []
|
|
1178
1183
|
require_paths:
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
class CreateActionTextVideoEmbeds < ActiveRecord::Migration[6.1]
|
|
2
|
-
def change
|
|
3
|
-
create_table :action_text_video_embeds, if_not_exists: true do |t|
|
|
4
|
-
t.string :url, null: false
|
|
5
|
-
t.string :thumbnail_url, null: false
|
|
6
|
-
t.text :raw_html, null: false
|
|
7
|
-
|
|
8
|
-
t.timestamps
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|