diff --git a/assets/controllers/bo/question_list_controller.js b/assets/controllers/bo/question_list_controller.js index 3121894..b611253 100644 --- a/assets/controllers/bo/question_list_controller.js +++ b/assets/controllers/bo/question_list_controller.js @@ -1,7 +1,10 @@ import {Controller} from '@hotwired/stimulus'; +import {Modal} from 'bootstrap'; + +const RETRY_DELAY_MS = 1000; export default class extends Controller { - static targets = ['list', 'item', 'status']; + static targets = ['list', 'item', 'status', 'noticeModal']; static values = { reorderUrl: String, csrf: String, @@ -24,6 +27,10 @@ export default class extends Controller { handle.setAttribute('draggable', 'true'); handle.addEventListener('dragstart', (e) => { + if (this._locked) { + e.preventDefault(); + return; + } this._dragging = el; e.dataTransfer.effectAllowed = 'move'; setTimeout(() => el.classList.add('opacity-50'), 0); @@ -107,15 +114,40 @@ export default class extends Controller { if (numberEl) numberEl.textContent = String(i + 1); }); - try { + const attempt = async () => { const res = await fetch(this.reorderUrlValue, {method: 'POST', body: params}); - if (res.ok) { - this._setStatus('saved'); - } else { - this._setStatus('error'); + if (!res.ok) { + throw new Error(`Unexpected response status: ${res.status}`); } + }; + + try { + await attempt(); } catch { - this._setStatus('error'); + await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS)); + try { + await attempt(); + } catch { + this._setStatus('error'); + this._lockReordering(); + return; + } + } + + this._setStatus('saved'); + } + + _lockReordering() { + this._locked = true; + this.itemTargets.forEach(el => { + const handle = el.querySelector('[data-drag-handle]'); + if (handle) { + handle.removeAttribute('draggable'); + handle.classList.add('opacity-25', 'pe-none'); + } + }); + if (this.hasNoticeModalTarget) { + Modal.getOrCreateInstance(this.noticeModalTarget).show(); } } } diff --git a/templates/backoffice/quiz/tab_overview.html.twig b/templates/backoffice/quiz/tab_overview.html.twig index 885809f..3676252 100644 --- a/templates/backoffice/quiz/tab_overview.html.twig +++ b/templates/backoffice/quiz/tab_overview.html.twig @@ -152,6 +152,25 @@ + + {{ _self.confirm_modal( diff --git a/translations/messages+intl-icu.nl.xliff b/translations/messages+intl-icu.nl.xliff index 85dc0f7..be486ef 100644 --- a/translations/messages+intl-icu.nl.xliff +++ b/translations/messages+intl-icu.nl.xliff @@ -181,6 +181,10 @@ Could not find candidate with name {name} in elimination. Kon geen kandidaat vinden met de naam {name} in de eliminatie + + Could not save order + Kon volgorde niet opslaan + Create a season Maak een seizoen aan @@ -649,6 +653,10 @@ Sync latest changes to this quiz Laatste wijzigingen synchroniseren naar deze quiz + + The new question order could not be saved. Reordering has been disabled until you refresh the page. + De nieuwe volgorde van de vragen kon niet worden opgeslagen. Herordenen is uitgeschakeld totdat u de pagina vernieuwt. + The password fields must match. De wachtwoorden moeten overeen komen.