spree_admin 5.2.0.rc1 → 5.2.0.rc2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f22556fbb3d151c7c2b05dab509022275e6c59f8de4adb4896bcdf5bc48f8f0d
4
- data.tar.gz: f4dd860a86b552d8fbdd6d5e6492d94d46a9ce125a6fc4a9fa0748cebf5a657e
3
+ metadata.gz: 57e59ddd5613ed6add9a0bc7b66e9effa39e85f763750a3b4e2bede3e8f203da
4
+ data.tar.gz: bf9a3fc04741c70271817e9c81e1709e3a8de2a80f34771a3ce701391c5911d7
5
5
  SHA512:
6
- metadata.gz: 649ede281c65678902ee006fbe831f456aaac7de23d72657009125c9281fd0231f586de5d951c67114c40095bc47d7a96b25f25c4e529b10300b7f0aac8f8dac
7
- data.tar.gz: 70808fb3caba9f95df1108d70e14625e8d9f3f6bd3e8a2495cdf4034720fd4d18f34428ab8931c225e3157b788f2e1c7189592b732f9e9fac372565304aa07d7
6
+ metadata.gz: f513a0d0377068700800f84a23bb46eb61447252dddf16a78bda9deba79a9574c0499b562138c6c9cab7c72c98c733c81a4f1512c695aeb55f023fe2b2e58211
7
+ data.tar.gz: 21d4d0fcaf4029d2c5686dc73627aad315e5167b4c7d30a065bddd9f641f6bfd1dc74c780f8ec8695bb2ba0c748f30c10d997c948e934a0176b1703432bfb5c1
@@ -108,20 +108,18 @@
108
108
  }
109
109
  // new non-bootstrap dropdowns
110
110
  .dropdown-container {
111
+ // Position is handled by Floating UI via inline styles
112
+ // Keep position: absolute but let Floating UI set top/left/right/bottom
111
113
  position: absolute;
112
- top: 100%;
113
- right: 0;
114
114
  animation: fadeIn 0.15s ease-in-out;
115
- transform-origin: top right;
116
115
 
116
+ // Legacy classes kept for backward compatibility but no longer apply positioning
117
+ // Floating UI handles all positioning automatically
117
118
  &.dropdown-container-left {
118
- left: 0;
119
- right: auto;
119
+ // No longer needed - Floating UI handles placement
120
120
  }
121
121
  &.dropdown-container-top {
122
- top: auto;
123
- bottom: 100%;
124
- height: auto;
122
+ // No longer needed - Floating UI handles placement
125
123
  }
126
124
  }
127
125
 
@@ -31,6 +31,8 @@
31
31
  animation: fadeIn 0.2s ease-in-out;
32
32
  width: 100%;
33
33
  z-index: $zindex-dropdown;
34
+ max-height: calc(100vh - #{$header-height} - 4rem);
35
+ overflow-y: auto;
34
36
 
35
37
  @include media-breakpoint-up(md) {
36
38
  width: 50%;
@@ -14,6 +14,7 @@ module Spree
14
14
  helper 'spree/integrations'
15
15
 
16
16
  before_action :authorize_admin
17
+ after_action :set_return_to, only: [:index]
17
18
 
18
19
  protected
19
20
 
@@ -4,7 +4,6 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
4
4
  helper_method :new_object_url, :edit_object_url, :object_url, :collection_url, :model_class, :search_collection, :paginated_collection
5
5
  before_action :load_resource
6
6
  before_action :set_currency, :set_current_store, only: [:new, :create]
7
- after_action :set_return_to, only: [:index]
8
7
 
9
8
  rescue_from ActiveRecord::RecordNotFound, with: :resource_not_found
10
9
 
@@ -10,21 +10,33 @@ module Spree
10
10
  def dropdown_toggle(options = {}, &block)
11
11
  options[:type] = 'button'
12
12
  options[:class] = ['btn'] + Array(options[:class])
13
- options[:data] = { action: 'dropdown#toggle click@window->dropdown#hide' }.merge(options[:data] || {})
13
+ options[:data] = {
14
+ action: 'dropdown#toggle click@window->dropdown#hide',
15
+ dropdown_target: 'toggle'
16
+ }.merge(options[:data] || {})
14
17
  button_tag(options, &block)
15
18
  end
16
19
 
17
20
  def dropdown_menu(options = {}, &block)
18
21
  options[:class] = ['dropdown-container hidden'] + Array(options[:class])
19
22
 
20
- if options[:direction] == 'left'
21
- options[:class] << 'dropdown-container-left'
22
- elsif options[:direction] == 'top'
23
- options[:class] << 'dropdown-container-top'
24
- elsif options[:direction] == 'top-left'
25
- options[:class] << 'dropdown-container-top dropdown-container-left'
23
+ # Extract direction option for backward compatibility and convert to Floating UI placement
24
+ placement = case options.delete(:direction)
25
+ when 'left'
26
+ 'bottom-end'
27
+ when 'top'
28
+ 'top-start'
29
+ when 'top-left'
30
+ 'top-end'
31
+ else
32
+ options[:placement] || 'bottom-start'
26
33
  end
27
- options[:data] = { dropdown_target: 'menu' }.merge(options[:data] || {})
34
+
35
+ options[:data] = {
36
+ dropdown_target: 'menu',
37
+ dropdown_placement_value: placement
38
+ }.merge(options[:data] || {})
39
+
28
40
  content_tag(:div, options, &block)
29
41
  end
30
42
  end
@@ -35,7 +35,6 @@ if (typeof Stimulus === 'undefined') {
35
35
  import AutoSubmit from '@stimulus-components/auto-submit'
36
36
  import CheckboxSelectAll from 'stimulus-checkbox-select-all'
37
37
  import Dialog from "@stimulus-components/dialog"
38
- import Dropdown from '@stimulus-components/dropdown'
39
38
  import TextareaAutogrow from 'stimulus-textarea-autogrow'
40
39
  import Notification from 'stimulus-notification'
41
40
  import PasswordVisibility from 'stimulus-password-visibility'
@@ -56,6 +55,7 @@ import Clipboard from 'spree/admin/controllers/clipboard_controller'
56
55
  import CodeMirrorController from 'spree/admin/controllers/codemirror_controller'
57
56
  import ColorPaletteController from 'spree/admin/controllers/color_palette_controller'
58
57
  import ColorPickerController from 'spree/admin/controllers/color_picker_controller'
58
+ import DropdownController from 'spree/admin/controllers/dropdown_controller'
59
59
  import FiltersController from 'spree/admin/controllers/filters_controller'
60
60
  import FontPickerController from 'spree/admin/controllers/font_picker_controller'
61
61
  import HighlightController from 'spree/admin/controllers/highlight_controller'
@@ -114,7 +114,7 @@ application.register('color-picker', ColorPickerController)
114
114
  application.register('dialog', Dialog)
115
115
  application.register('drawer', Dialog)
116
116
  application.register('disable-submit-button', DisableSubmitButtonController)
117
- application.register('dropdown', Dropdown)
117
+ application.register('dropdown', DropdownController)
118
118
  application.register('enable-button', EnableButtonController)
119
119
  application.register('export-dialog', Dialog)
120
120
  application.register('filters', FiltersController)
@@ -0,0 +1,154 @@
1
+ import {
2
+ autoUpdate,
3
+ computePosition,
4
+ flip,
5
+ offset,
6
+ shift,
7
+ size,
8
+ } from "@floating-ui/dom"
9
+ import { Controller } from "@hotwired/stimulus"
10
+
11
+ export default class extends Controller {
12
+ static targets = ["menu", "toggle"]
13
+ static values = {
14
+ placement: { type: String, default: "bottom-start" },
15
+ offset: { type: Number, default: 4 },
16
+ }
17
+
18
+ connect() {
19
+ this._cleanup = null
20
+ this.boundUpdate = this.update.bind(this)
21
+ this._isOpen = false
22
+ this._toggleElement = null
23
+ }
24
+
25
+ disconnect() {
26
+ this.stopAutoUpdate()
27
+ }
28
+
29
+ toggle(event) {
30
+ event.preventDefault()
31
+ event.stopPropagation()
32
+
33
+ // Store the toggle element that triggered this action
34
+ this._toggleElement = event.currentTarget
35
+
36
+ if (this._isOpen) {
37
+ this.close()
38
+ } else {
39
+ this.open()
40
+ }
41
+ }
42
+
43
+ open() {
44
+ if (this._isOpen) return
45
+
46
+ this.menuTarget.classList.remove("hidden")
47
+ this._isOpen = true
48
+
49
+ // Start automatic positioning
50
+ this.startAutoUpdate()
51
+
52
+ // Add event listener to close on outside click
53
+ this._outsideClickHandler = this.handleOutsideClick.bind(this)
54
+ document.addEventListener("click", this._outsideClickHandler)
55
+
56
+ // Add event listener to close on escape key
57
+ this._escapeHandler = this.handleEscape.bind(this)
58
+ document.addEventListener("keydown", this._escapeHandler)
59
+ }
60
+
61
+ close() {
62
+ if (!this._isOpen) return
63
+
64
+ this.menuTarget.classList.add("hidden")
65
+ this._isOpen = false
66
+
67
+ // Stop automatic positioning
68
+ this.stopAutoUpdate()
69
+
70
+ // Remove event listeners
71
+ if (this._outsideClickHandler) {
72
+ document.removeEventListener("click", this._outsideClickHandler)
73
+ this._outsideClickHandler = null
74
+ }
75
+
76
+ if (this._escapeHandler) {
77
+ document.removeEventListener("keydown", this._escapeHandler)
78
+ this._escapeHandler = null
79
+ }
80
+ }
81
+
82
+ hide(event) {
83
+ // This method is called from the action: click@window->dropdown#hide
84
+ // Only close if clicking outside the dropdown element
85
+ if (!this.element.contains(event.target)) {
86
+ this.close()
87
+ }
88
+ }
89
+
90
+ handleOutsideClick(event) {
91
+ // Close dropdown if clicking outside
92
+ if (!this.element.contains(event.target)) {
93
+ this.close()
94
+ }
95
+ }
96
+
97
+ handleEscape(event) {
98
+ if (event.key === "Escape") {
99
+ this.close()
100
+ }
101
+ }
102
+
103
+ startAutoUpdate() {
104
+ if (!this._cleanup) {
105
+ const referenceElement = this.hasToggleTarget ? this.toggleTarget : (this._toggleElement || this.element)
106
+ this._cleanup = autoUpdate(
107
+ referenceElement,
108
+ this.menuTarget,
109
+ this.boundUpdate,
110
+ )
111
+ }
112
+ }
113
+
114
+ stopAutoUpdate() {
115
+ if (this._cleanup) {
116
+ this._cleanup()
117
+ this._cleanup = null
118
+ }
119
+ }
120
+
121
+ update() {
122
+ // Use the toggle target if available, or the stored toggle element, or fall back to the controller element
123
+ const referenceElement = this.hasToggleTarget ? this.toggleTarget : (this._toggleElement || this.element)
124
+
125
+ computePosition(referenceElement, this.menuTarget, {
126
+ placement: this.placementValue,
127
+ middleware: [
128
+ offset(this.offsetValue),
129
+ flip({
130
+ fallbackAxisSideDirection: "start",
131
+ padding: 8,
132
+ }),
133
+ shift({ padding: 8 }),
134
+ size({
135
+ apply({ availableWidth, availableHeight, elements }) {
136
+ // Ensure dropdown doesn't exceed viewport
137
+ Object.assign(elements.floating.style, {
138
+ maxWidth: `${availableWidth}px`,
139
+ maxHeight: `${availableHeight}px`,
140
+ overflow: "auto",
141
+ })
142
+ },
143
+ padding: 8,
144
+ }),
145
+ ],
146
+ }).then(({ x, y }) => {
147
+ Object.assign(this.menuTarget.style, {
148
+ left: `${x}px`,
149
+ top: `${y}px`,
150
+ position: "absolute",
151
+ })
152
+ })
153
+ }
154
+ }
@@ -37,8 +37,8 @@ module Spree
37
37
 
38
38
  JSON.parse(response.body)
39
39
  end
40
- rescue Net::OpenTimeout, Net::ReadTimeout, SocketError, Errno::ECONNREFUSED, JSON::ParserError => e
41
- Rails.logger.error("Failed to fetch Spree updates: #{e.message}")
40
+ rescue StandardError => e
41
+ Rails.error.report(e)
42
42
  {}
43
43
  end
44
44
  end
@@ -13,12 +13,10 @@
13
13
 
14
14
  <%= f.spree_rich_text_area :content,
15
15
  help_bubble: 'Add a summary of the post',
16
- style: 'height: 300px',
17
16
  data: { seo_form_target: 'sourceDescriptionInput' } %>
18
17
 
19
18
  <%= f.spree_rich_text_area :excerpt,
20
19
  help_bubble: 'Add a summary of the post',
21
- style: 'height: 100px',
22
20
  data: { seo_form_target: 'sourceExcerptInput' } %>
23
21
  </div>
24
22
  </div>
@@ -7,6 +7,7 @@
7
7
  Spree::ReimbursementType::KINDS.map do |kind|
8
8
  [kind.demodulize.titleize, kind]
9
9
  end,
10
+ f.object.type
10
11
  ),
11
12
  { include_blank: false, label: Spree.t(:type), autocomplete: true } %>
12
13
 
@@ -14,7 +14,7 @@
14
14
  <p class="text-muted">
15
15
  Customers will need to accept these terms of service during signup.
16
16
  </p>
17
- <%= f.spree_rich_text_area :customer_terms_of_service, style: 'height: 300px', label: Spree.t(:terms_of_service) %>
17
+ <%= f.spree_rich_text_area :customer_terms_of_service, label: Spree.t(:terms_of_service) %>
18
18
  </div>
19
19
  </div>
20
20
 
@@ -26,7 +26,7 @@
26
26
  <p class="text-muted">
27
27
  Customers will need to accept these privacy policy during signup.
28
28
  </p>
29
- <%= f.spree_rich_text_area :customer_privacy_policy, style: 'height: 300px', label: Spree.t(:privacy_policy) %>
29
+ <%= f.spree_rich_text_area :customer_privacy_policy, label: Spree.t(:privacy_policy) %>
30
30
  </div>
31
31
  </div>
32
32
 
@@ -38,7 +38,7 @@
38
38
  <p class="text-muted">
39
39
  Please provide your customers with a clear and transparent returns policy.
40
40
  </p>
41
- <%= f.spree_rich_text_area :customer_returns_policy, style: 'height: 300px', label: Spree.t(:returns_policy) %>
41
+ <%= f.spree_rich_text_area :customer_returns_policy, label: Spree.t(:returns_policy) %>
42
42
  </div>
43
43
  </div>
44
44
 
@@ -50,7 +50,7 @@
50
50
  <p class="text-muted">
51
51
  Please provide your customers with a clear and transparent shipping policy.
52
52
  </p>
53
- <%= f.spree_rich_text_area :customer_shipping_policy, style: 'height: 300px', label: Spree.t(:shipping_policy) %>
53
+ <%= f.spree_rich_text_area :customer_shipping_policy, label: Spree.t(:shipping_policy) %>
54
54
  </div>
55
55
  </div>
56
56
 
@@ -63,7 +63,7 @@
63
63
  <p class="text-muted">
64
64
  Vendors you invite will need to accept these terms of service during their onboarding process.
65
65
  </p>
66
- <%= f.spree_rich_text_area :partners_terms_of_service, style: 'height: 300px', label: Spree.t(:terms_of_service) %>
66
+ <%= f.spree_rich_text_area :partners_terms_of_service, label: Spree.t(:terms_of_service) %>
67
67
  </div>
68
68
  </div>
69
69
  <% end %>
@@ -2,6 +2,13 @@
2
2
  <div class="d-flex flex-column flex-lg-row gap-2">
3
3
  <%= render 'spree/admin/shared/filters_search_bar', param: :multi_search, placeholder: Spree.t('admin.users.filters.search_placeholder') %>
4
4
 
5
+ <%= render "spree/admin/shared/calendar_range_picker",
6
+ date_from_input_name: "q[created_at_gt]",
7
+ date_to_input_name: "q[created_at_lt]",
8
+ date_from_value: params.dig(:q, :created_at_gt),
9
+ date_to_value: params.dig(:q, :created_at_lt),
10
+ dropdown_direction: "right" %>
11
+
5
12
  <%= render 'spree/admin/shared/filters_button' %>
6
13
  </div>
7
14
  <div data-dropdown-target="menu" id="table-filter" class="hidden">
data/config/importmap.rb CHANGED
@@ -27,7 +27,6 @@ pin 'hotkeys-js', preload: ['application-spree-admin'] # @3.13.9
27
27
  pin 'stimulus-use', preload: ['application-spree-admin'] # @0.51.3
28
28
  pin 'stimulus-checkbox-select-all', preload: ['application-spree-admin'] # @5.3.0
29
29
  pin 'stimulus-clipboard', preload: ['application-spree-admin'] # @4.0.1
30
- pin "@stimulus-components/dropdown", to: "@stimulus-components--dropdown.js", preload: ['application-spree-admin'] # @3.0.0
31
30
  pin "@stimulus-components/dialog", to: "@stimulus-components--dialog.js", preload: ['application-spree-admin'] # @1.0.1
32
31
 
33
32
  # We can't vendor some of the javascript libraries
@@ -0,0 +1,33 @@
1
+ require 'rails/generators'
2
+
3
+ module Spree
4
+ module Admin
5
+ module Generators
6
+ class DeviseGenerator < Rails::Generators::Base
7
+ desc 'Installs Spree Admin Devise controllers'
8
+
9
+ def install
10
+ # add devise routes
11
+ insert_into_file 'config/routes.rb', after: "Rails.application.routes.draw do\n" do
12
+ <<-ROUTES.strip_heredoc.indent!(2)
13
+ Spree::Core::Engine.add_routes do
14
+ # Admin authentication
15
+ devise_for(
16
+ Spree.admin_user_class.model_name.singular_route_key,
17
+ class_name: Spree.admin_user_class.to_s,
18
+ controllers: {
19
+ sessions: 'spree/admin/user_sessions',
20
+ passwords: 'spree/admin/user_passwords'
21
+ },
22
+ skip: :registrations,
23
+ path: :admin_user,
24
+ router_name: :spree
25
+ )
26
+ end
27
+ ROUTES
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
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.2.0.rc1
4
+ version: 5.2.0.rc2
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: 2025-11-04 00:00:00.000000000 Z
11
+ date: 2025-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree_core
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.2.0.rc1
19
+ version: 5.2.0.rc2
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.2.0.rc1
26
+ version: 5.2.0.rc2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: spree_api
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 5.2.0.rc1
33
+ version: 5.2.0.rc2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 5.2.0.rc1
40
+ version: 5.2.0.rc2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: active_link_to
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -448,6 +448,7 @@ files:
448
448
  - app/javascript/spree/admin/controllers/codemirror_controller.js
449
449
  - app/javascript/spree/admin/controllers/color_palette_controller.js
450
450
  - app/javascript/spree/admin/controllers/color_picker_controller.js
451
+ - app/javascript/spree/admin/controllers/dropdown_controller.js
451
452
  - app/javascript/spree/admin/controllers/filters_controller.js
452
453
  - app/javascript/spree/admin/controllers/font_picker_controller.js
453
454
  - app/javascript/spree/admin/controllers/highlight_controller.js
@@ -1192,6 +1193,7 @@ files:
1192
1193
  - config/initializers/ransack.rb
1193
1194
  - config/locales/en.yml
1194
1195
  - config/routes.rb
1196
+ - lib/generators/spree/admin/devise/devise_generator.rb
1195
1197
  - lib/generators/spree/admin/install/install_generator.rb
1196
1198
  - lib/generators/spree/admin/install/templates/dev
1197
1199
  - lib/generators/spree/admin/scaffold/scaffold_generator.rb
@@ -1240,7 +1242,6 @@ files:
1240
1242
  - vendor/javascript/@rails--actiontext@7.2.201.js
1241
1243
  - vendor/javascript/@simonwep--pickr.js
1242
1244
  - vendor/javascript/@stimulus-components--dialog.js
1243
- - vendor/javascript/@stimulus-components--dropdown.js
1244
1245
  - vendor/javascript/@stimulus-components--rails-nested-form.js
1245
1246
  - vendor/javascript/bootstrap--dist--js--bootstrap.bundle.min.js.js
1246
1247
  - vendor/javascript/codemirror.js
@@ -1266,9 +1267,9 @@ licenses:
1266
1267
  - AGPL-3.0-or-later
1267
1268
  metadata:
1268
1269
  bug_tracker_uri: https://github.com/spree/spree/issues
1269
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.2.0.rc1
1270
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.2.0.rc2
1270
1271
  documentation_uri: https://docs.spreecommerce.org/
1271
- source_code_uri: https://github.com/spree/spree/tree/v5.2.0.rc1
1272
+ source_code_uri: https://github.com/spree/spree/tree/v5.2.0.rc2
1272
1273
  post_install_message:
1273
1274
  rdoc_options: []
1274
1275
  require_paths:
@@ -1,4 +0,0 @@
1
- // @stimulus-components/dropdown@3.0.0 downloaded from https://ga.jspm.io/npm:@stimulus-components/dropdown@3.0.0/dist/stimulus-dropdown.mjs
2
-
3
- import{Controller as t}from"@hotwired/stimulus";import{useTransition as e}from"stimulus-use";const s=class _Dropdown extends t{connect(){e(this,{element:this.menuTarget})}toggle(){this.toggleTransition()}hide(t){!this.element.contains(t.target)&&!this.menuTarget.classList.contains("hidden")&&this.leave()}};s.targets=["menu"];let i=s;export{i as default};
4
-