This commit is contained in:
@@ -1,16 +1,3 @@
|
||||
/**
|
||||
* Chroniques de l'Étrange — Système FoundryVTT
|
||||
*
|
||||
* Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
|
||||
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
|
||||
* affilié à Antre-Monde Éditions,
|
||||
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
|
||||
*
|
||||
* @author LeRatierBretonnien
|
||||
* @copyright 2024–2026 LeRatierBretonnien
|
||||
* @license CC BY-NC-SA 4.0 – https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
import { parseLegacyJson } from "../../migration/migrator.js"
|
||||
|
||||
const MIGRATION_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-migration-app.html"
|
||||
@@ -33,10 +20,12 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
icon: "fas fa-file-import",
|
||||
resizable: false,
|
||||
},
|
||||
position: { width: 560, height: "auto" },
|
||||
position: { width: 600, height: "auto" },
|
||||
actions: {
|
||||
clearFiles: CDEMigrationApp.#clearFiles,
|
||||
doImport: CDEMigrationApp.#doImport,
|
||||
clearFiles: CDEMigrationApp.#clearFiles,
|
||||
doImport: CDEMigrationApp.#doImport,
|
||||
confirmImport: CDEMigrationApp.#confirmImport,
|
||||
cancelImport: CDEMigrationApp.#cancelImport,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -50,13 +39,31 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
/** @type {string[]} - error messages per file */
|
||||
#errors = []
|
||||
|
||||
/** @type {"idle"|"confirm"|"importing"} */
|
||||
#importState = "idle"
|
||||
|
||||
/** @type {number} - actors created so far (during importing) */
|
||||
#progress = 0
|
||||
|
||||
async _prepareContext(options) {
|
||||
// Compute _duplicate live from the world each render, to avoid stale flags
|
||||
const enrichDuplicate = (a) => ({
|
||||
...a,
|
||||
_duplicate: game.actors?.getName(a.name) !== null,
|
||||
})
|
||||
const pending = this.#pending.map(enrichDuplicate)
|
||||
const duplicateCount = pending.filter(a => a._duplicate).length
|
||||
return {
|
||||
pending: this.#pending,
|
||||
pending,
|
||||
errors: this.#errors,
|
||||
hasPending: this.#pending.length > 0,
|
||||
hasErrors: this.#errors.length > 0,
|
||||
hasDuplicates: duplicateCount > 0,
|
||||
duplicateCount,
|
||||
count: this.#pending.length,
|
||||
importState: this.#importState,
|
||||
progress: this.#progress,
|
||||
total: this.#pending.length,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,43 +102,68 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
const actors = parseLegacyJson(text)
|
||||
for (const actor of actors) {
|
||||
actor._srcFile = file.name
|
||||
// Avoid duplicates by name
|
||||
if (!this.#pending.some(p => p.name === actor.name)) {
|
||||
this.#pending.push(actor)
|
||||
// Avoid duplicates-by-name in our pending list
|
||||
if (this.#pending.some(p => p.name === actor.name)) {
|
||||
this.#errors.push(`« ${actor.name} » ignoré (nom déjà dans la liste d'attente, fichier « ${file.name} »)`)
|
||||
continue
|
||||
}
|
||||
this.#pending.push(actor)
|
||||
}
|
||||
} catch (err) {
|
||||
this.#errors.push(game.i18n.format("CDE.MigrationErrorParse", { file: file.name, error: err.message }))
|
||||
}
|
||||
}
|
||||
this.#importState = "idle"
|
||||
this.render()
|
||||
}
|
||||
|
||||
static async #clearFiles() {
|
||||
this.#pending = []
|
||||
this.#errors = []
|
||||
this.#importState = "idle"
|
||||
this.#progress = 0
|
||||
this.render()
|
||||
}
|
||||
|
||||
/** First click: switch to confirmation state instead of importing immediately. */
|
||||
static async #doImport() {
|
||||
if (!this.#pending.length) return
|
||||
this.#importState = "confirm"
|
||||
this.render()
|
||||
}
|
||||
|
||||
/** Second click: actually perform the import. */
|
||||
static async #confirmImport() {
|
||||
if (!this.#pending.length) return
|
||||
|
||||
this.#importState = "importing"
|
||||
this.#progress = 0
|
||||
this.render()
|
||||
|
||||
const total = this.#pending.length
|
||||
const created = []
|
||||
const failed = []
|
||||
|
||||
for (const data of this.#pending) {
|
||||
for (let i = 0; i < total; i++) {
|
||||
const data = this.#pending[i]
|
||||
try {
|
||||
const { _srcFile, ...actorData } = data
|
||||
const actor = await Actor.create(actorData)
|
||||
created.push(actor.name)
|
||||
} catch (err) {
|
||||
failed.push(`${data.name}: ${err.message}`)
|
||||
console.error(`CHRONIQUESDELETRANGE | Migration failed for "${data.name}":`, err)
|
||||
console.error(`CHRONIQUESDELETRANGE | Import failed for "${data.name}":`, err)
|
||||
}
|
||||
this.#progress = i + 1
|
||||
// Live-update the progress element in the DOM without full re-render
|
||||
const progEl = this.element?.querySelector(".cde-migration-progress-count")
|
||||
if (progEl) progEl.textContent = `${this.#progress}/${total}`
|
||||
}
|
||||
|
||||
this.#pending = []
|
||||
this.#errors = failed
|
||||
this.#importState = "idle"
|
||||
this.#progress = 0
|
||||
this.render()
|
||||
|
||||
if (created.length) {
|
||||
@@ -145,4 +177,9 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
static async #cancelImport() {
|
||||
this.#importState = "idle"
|
||||
this.render()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user