Files
ltbxd-actorle/assets/controllers/import_status_controller.js

96 lines
2.8 KiB
JavaScript

import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['item', 'importBtn'];
connect() {
this._poll();
this._interval = setInterval(() => this._poll(), 5000);
this._onImportStarted = () => this._poll();
document.addEventListener('import:started', this._onImportStarted);
}
disconnect() {
clearInterval(this._interval);
document.removeEventListener('import:started', this._onImportStarted);
}
async _poll() {
try {
const response = await fetch('/api/imports/latest');
if (!response.ok) return;
const data = await response.json();
this._update(data);
} catch (e) {
// silently ignore
}
}
_update(data) {
if (!data) {
this._showDefault();
return;
}
const isActive = data.status === 'pending' || data.status === 'processing';
if (isActive) {
this._showActive(data);
} else if (data.status === 'completed') {
this._showCompleted(data);
} else if (data.status === 'failed') {
this._showFailed();
} else {
this._showDefault();
}
}
_showDefault() {
this.importBtnTarget.disabled = false;
this.importBtnTarget.textContent = 'Importer ses films';
this._removeStatus();
}
_showActive(data) {
this.importBtnTarget.disabled = true;
this.importBtnTarget.textContent = 'Import en cours\u2026';
const progress = data.totalBatches > 0
? Math.round((data.processedBatches / data.totalBatches) * 100)
: 0;
this._setStatus(`${progress}% — ${data.totalFilms} films`, 'active');
}
_showCompleted(data) {
this.importBtnTarget.disabled = false;
this.importBtnTarget.textContent = 'Importer ses films';
const imported = data.totalFilms - data.failedFilms;
this._setStatus(`Dernier import : ${imported}/${data.totalFilms} films`, 'completed');
}
_showFailed() {
this.importBtnTarget.disabled = false;
this.importBtnTarget.textContent = 'Importer ses films';
this._setStatus('Dernier import : échoué', 'failed');
}
_setStatus(text, type) {
let statusEl = this.itemTarget.querySelector('.import-status-text');
if (!statusEl) {
statusEl = document.createElement('span');
statusEl.className = 'import-status-text';
this.itemTarget.appendChild(statusEl);
}
statusEl.textContent = text;
statusEl.className = `import-status-text import-status-${type}`;
}
_removeStatus() {
const statusEl = this.itemTarget.querySelector('.import-status-text');
if (statusEl) statusEl.remove();
}
}