rails_modal_manager 1.0.41 → 1.0.43

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: 5884364bb07444f45c08e4733c5623883a775592ba853a1275f5f2bd84bb5c03
4
- data.tar.gz: 06a78be76359c81f55ec9e904488a1f3d961fdababf4bb8b31c24d0d19a8b7e1
3
+ metadata.gz: 37be545accc1417617473c793c6141fbf2ab14d6ca3bf1bf8279a0c008749bdf
4
+ data.tar.gz: dd2b26619197fedab1629888b9d07f7c9946f1639e5c824eb980b424d8850c64
5
5
  SHA512:
6
- metadata.gz: 985fca2add00de7fca1c9c5d05d66be9b8a6dbc208526de6811dad2c4b27977be9aa332dce1287d561d0fe04c3ec365768abbeeac89f582f07af8250aed843e2
7
- data.tar.gz: ab10ad1ad3a86cd5a6ad64af536d015cbfeccc030523e03c980c74cb042cab25bd70bd936cd7247980097a18140d2c0969f18c9afb6c6df8fc66301c959c4232
6
+ metadata.gz: 29970d10f36b4576572d2459f6a9dc6eeaf459242757072788b02b0af57a331b6a142039186a805cd3ce42669dd0f4c46c6546618c71cbf6e0fd9e21679e5aae
7
+ data.tar.gz: b67c38c317b8cca2b2855b9f881279e423f8bb6324b4c844dc19569ee46cafbbf8c417c93d4b71dde9291a578d3113be10f333a57c0613acd4670f652dbef8a8
@@ -16,18 +16,24 @@ export default class extends Controller {
16
16
  connect() {
17
17
  // Listen for sidebar toggled event to update icon
18
18
  this.handleSidebarToggled = this.handleSidebarToggled.bind(this)
19
+ this.handleModalClosed = this.handleModalClosed.bind(this)
20
+
19
21
  const modal = this.element.closest('.rmm-modal')
20
22
  if (modal) {
21
23
  modal.addEventListener('rmm-sidebar:toggled', this.handleSidebarToggled)
24
+ modal.addEventListener('rmm:closed', this.handleModalClosed)
22
25
  }
23
26
 
24
- // Title 더블클릭 이벤트 리스너 추가
27
+ // Title 더블클릭 이벤트 리스너 추가 및 원래 title 저장
25
28
  this.setupTitleEdit()
26
29
  }
27
30
 
28
31
  setupTitleEdit() {
29
32
  const titleEl = this.element.querySelector('.rmm-header-title')
30
33
  if (titleEl) {
34
+ // 원래 title 저장 (모달 닫힐 때 복원용)
35
+ this.originalTitle = titleEl.textContent.trim()
36
+
31
37
  titleEl.addEventListener('dblclick', (e) => this.editTitle(e))
32
38
  titleEl.style.cursor = 'default'
33
39
  }
@@ -37,6 +43,21 @@ export default class extends Controller {
37
43
  const modal = this.element.closest('.rmm-modal')
38
44
  if (modal) {
39
45
  modal.removeEventListener('rmm-sidebar:toggled', this.handleSidebarToggled)
46
+ modal.removeEventListener('rmm:closed', this.handleModalClosed)
47
+ }
48
+ }
49
+
50
+ // 모달 닫힐 때 title을 원래 값으로 복원
51
+ handleModalClosed() {
52
+ this.resetTitle()
53
+ }
54
+
55
+ resetTitle() {
56
+ if (!this.originalTitle) return
57
+
58
+ const titleEl = this.element.querySelector('.rmm-header-title')
59
+ if (titleEl) {
60
+ titleEl.textContent = this.originalTitle
40
61
  }
41
62
  }
42
63
 
@@ -44,6 +44,7 @@ export default class extends Controller {
44
44
  connect() {
45
45
  this.ajaxCache = new Map()
46
46
  this.currentItemId = null
47
+ this.currentAbortController = null
47
48
 
48
49
  // Find initial active item
49
50
  const activeItem = this.element.querySelector('.rmm-submenu-item.rmm-active')
@@ -140,6 +141,8 @@ export default class extends Controller {
140
141
 
141
142
  /**
142
143
  * AJAX mode: Load content from URL
144
+ * Uses AbortController to cancel previous pending requests and
145
+ * validates response against current active item to prevent race conditions.
143
146
  */
144
147
  async loadAjaxContent(item) {
145
148
  const url = item.dataset.url
@@ -161,12 +164,22 @@ export default class extends Controller {
161
164
  return
162
165
  }
163
166
 
167
+ // Abort previous pending request
168
+ if (this.currentAbortController) {
169
+ this.currentAbortController.abort()
170
+ }
171
+
172
+ const abortController = new AbortController()
173
+ this.currentAbortController = abortController
174
+ const requestItemId = item.dataset.itemId
175
+
164
176
  // Show loading state
165
177
  contentContainer.classList.add('rmm-tab-loading')
166
178
  contentContainer.innerHTML = '<div class="rmm-tab-loader"><div class="rmm-spinner"></div><span>로딩 중...</span></div>'
167
179
 
168
180
  try {
169
181
  const response = await fetch(url, {
182
+ signal: abortController.signal,
170
183
  headers: {
171
184
  'Accept': 'text/html',
172
185
  'X-Requested-With': 'XMLHttpRequest'
@@ -179,6 +192,11 @@ export default class extends Controller {
179
192
 
180
193
  const html = await response.text()
181
194
 
195
+ // Validate: only update if this request is still the current one
196
+ if (this.currentItemId !== requestItemId) {
197
+ return
198
+ }
199
+
182
200
  // Cache the response
183
201
  if (this.cacheAjaxValue) {
184
202
  this.ajaxCache.set(url, html)
@@ -192,6 +210,11 @@ export default class extends Controller {
192
210
  detail: { modalId: this.modalIdValue, itemId: item.dataset.itemId, fromCache: false }
193
211
  })
194
212
  } catch (error) {
213
+ // Ignore abort errors (expected when switching tabs quickly)
214
+ if (error.name === 'AbortError') {
215
+ return
216
+ }
217
+
195
218
  console.error('RMM Submenu: Failed to load content', error)
196
219
  contentContainer.innerHTML = `
197
220
  <div class="rmm-tab-error">
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsModalManager
4
- VERSION = "1.0.41"
4
+ VERSION = "1.0.43"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_modal_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.41
4
+ version: 1.0.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - reshacs