33 lines
2.1 KiB
JavaScript
33 lines
2.1 KiB
JavaScript
// A single coordinator for page, module, company and unit transitions.
|
|
// Saving uses the existing form and its existing command/validation path.
|
|
export class ContextTransition {
|
|
constructor() { this.dirty = new Set(); this.pending = 0; this.saved = 0; this.failed = 0; this.versions = new WeakMap(); this.submitting = null; }
|
|
changed(form) { if (form && form.dataset?.sgfReadFilters!=='true') { this.dirty.add(form); this.versions.set(form,(this.versions.get(form)||0)+1); } }
|
|
prune() { for (const form of this.dirty) if (!form.isConnected) this.dirty.delete(form); }
|
|
async command(operation) {
|
|
this.pending++;
|
|
const form=this.submitting, version=form&&this.versions.get(form);
|
|
try { const result = await operation(); this.saved++; if(form&&version===this.versions.get(form))this.dirty.delete(form); return result; }
|
|
catch (e) { this.failed++; throw e; }
|
|
finally { this.pending--; }
|
|
}
|
|
async save() {
|
|
this.prune();
|
|
for (const form of [...this.dirty]) {
|
|
if (!form.requestSubmit) throw new Error('Este editor exige gravação explícita no próprio percurso. Cancele a mudança, guarde e tente novamente.');
|
|
if (!form.reportValidity()) throw new Error('Corrija os campos antes de mudar de contexto.');
|
|
const saved = this.saved, failed = this.failed;
|
|
const version=this.versions.get(form);
|
|
this.submitting=form;
|
|
form.requestSubmit();
|
|
// React handlers start commands synchronously or after a short validation step.
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
while (this.pending) await new Promise(resolve => setTimeout(resolve, 40));
|
|
if (this.failed !== failed || this.saved === saved) throw new Error('Não foi possível guardar. O contexto foi mantido.');
|
|
if(version!==this.versions.get(form))throw new Error('Existem alterações posteriores à gravação. O contexto foi mantido.');
|
|
this.dirty.delete(form);
|
|
}
|
|
}
|
|
discard() { this.dirty.clear(); }
|
|
}
|