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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 37be545accc1417617473c793c6141fbf2ab14d6ca3bf1bf8279a0c008749bdf
|
|
4
|
+
data.tar.gz: dd2b26619197fedab1629888b9d07f7c9946f1639e5c824eb980b424d8850c64
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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">
|