2019-11-19 17:55:30 +01:00
|
|
|
import AutosaveController from './autosave-controller.js';
|
|
|
|
import {
|
|
|
|
debounce,
|
|
|
|
delegate,
|
|
|
|
fire,
|
|
|
|
enable,
|
|
|
|
disable,
|
|
|
|
hasClass,
|
|
|
|
addClass,
|
|
|
|
removeClass
|
|
|
|
} from '@utils';
|
|
|
|
|
2019-11-19 14:40:28 +01:00
|
|
|
const AUTOSAVE_DEBOUNCE_DELAY = gon.autosave.debounce_delay;
|
|
|
|
const AUTOSAVE_STATUS_VISIBLE_DURATION = gon.autosave.status_visible_duration;
|
2019-11-19 17:55:30 +01:00
|
|
|
|
2019-11-19 14:40:28 +01:00
|
|
|
// Create a controller responsible for queuing autosave operations.
|
2019-11-19 17:55:36 +01:00
|
|
|
const autosaveController = new AutosaveController();
|
2019-11-19 17:55:30 +01:00
|
|
|
|
|
|
|
// Whenever a 'change' event is triggered on one of the form inputs, try to autosave.
|
|
|
|
|
|
|
|
const formSelector = 'form#dossier-edit-form.autosave-enabled';
|
2019-11-27 13:53:31 +01:00
|
|
|
const formInputsSelector = `${formSelector} input:not([type=file]), ${formSelector} select, ${formSelector} textarea`;
|
2019-11-19 17:55:30 +01:00
|
|
|
|
|
|
|
delegate(
|
|
|
|
'change',
|
|
|
|
formInputsSelector,
|
|
|
|
debounce(() => {
|
|
|
|
const form = document.querySelector(formSelector);
|
|
|
|
autosaveController.enqueueAutosaveRequest(form);
|
|
|
|
}, AUTOSAVE_DEBOUNCE_DELAY)
|
|
|
|
);
|
|
|
|
|
|
|
|
delegate('click', '.autosave-retry', () => {
|
|
|
|
const form = document.querySelector(formSelector);
|
|
|
|
autosaveController.enqueueAutosaveRequest(form);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Display some UI during the autosave
|
|
|
|
|
|
|
|
addEventListener('autosave:enqueue', () => {
|
|
|
|
disable(document.querySelector('button.autosave-retry'));
|
|
|
|
});
|
|
|
|
|
|
|
|
addEventListener('autosave:end', () => {
|
|
|
|
enable(document.querySelector('button.autosave-retry'));
|
|
|
|
setState('succeeded');
|
|
|
|
hideSucceededStatusAfterDelay();
|
|
|
|
});
|
|
|
|
|
|
|
|
addEventListener('autosave:error', event => {
|
|
|
|
enable(document.querySelector('button.autosave-retry'));
|
|
|
|
setState('failed');
|
|
|
|
logError(event.detail);
|
|
|
|
});
|
|
|
|
|
|
|
|
function setState(state) {
|
|
|
|
const autosave = document.querySelector('.autosave');
|
|
|
|
if (autosave) {
|
|
|
|
// Re-apply the state even if already present, to get a nice animation
|
|
|
|
removeClass(autosave, 'autosave-state-idle');
|
|
|
|
removeClass(autosave, 'autosave-state-succeeded');
|
|
|
|
removeClass(autosave, 'autosave-state-failed');
|
|
|
|
autosave.offsetHeight; // flush animations
|
|
|
|
addClass(autosave, `autosave-state-${state}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function hideSucceededStatus() {
|
|
|
|
const autosave = document.querySelector('.autosave');
|
|
|
|
if (hasClass(autosave, 'autosave-state-succeeded')) {
|
|
|
|
setState('idle');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const hideSucceededStatusAfterDelay = debounce(
|
|
|
|
hideSucceededStatus,
|
|
|
|
AUTOSAVE_STATUS_VISIBLE_DURATION
|
|
|
|
);
|
|
|
|
|
|
|
|
function logError(error) {
|
|
|
|
if (error && error.message) {
|
|
|
|
error.message = `[Autosave] ${error.message}`;
|
|
|
|
console.error(error);
|
|
|
|
fire(document, 'sentry:capture-exception', error);
|
|
|
|
}
|
|
|
|
}
|