diff --git a/module/documents/Actor.mjs b/module/documents/Actor.mjs index 0c97cea..13fc3bb 100644 --- a/module/documents/Actor.mjs +++ b/module/documents/Actor.mjs @@ -1,7 +1,7 @@ import { __ID__ } from "../consts.mjs"; const { Actor } = foundry.documents; -const { hasProperty, setProperty } = foundry.utils; +const { deepClone, hasProperty, setProperty } = foundry.utils; export class TAFActor extends Actor { @@ -33,16 +33,6 @@ export class TAFActor extends Actor { super._onEmbeddedDocumentChange(...args); this.#sortedTypes = null; }; - - static migrateData(data, options) { - if (options.partial) { return } - console.log(`Actor#migrateData`, foundry.utils.deepClone(data), options); - if (Object.keys(data.system?.attr ?? {}).length > 0) { - console.log(`attributes exist`) - setProperty(data, `flags.${__ID__}.convertAttributesIntoItems`, true); - }; - return data; - }; // #endregion Lifecycle // #region Token Attributes @@ -116,4 +106,35 @@ export class TAFActor extends Actor { return this.#sortedTypes = types; }; // #endregion Getters + + // #region Data Migration + /** + * This checks and performs all data migrations that the system requires, some + * of these are one-time only migrations, others of them will happen every time + * an Actor is updated. + */ + static migrateData(data, options) { + this.#migrateToAttributeItems(data, options); + return super.migrateData(data, options); + }; + + /** + * This method handles checking if the Actor has attributes within it's raw + * system data model, which was where attributes were stored originally, if + * it detects the need for a migration, it stores the existing attribute data + * into a flag so that the v3.0.0 migration script can handle creating the + * data and removing the property from the Actor. + */ + static #migrateToAttributeItems(data, options) { + if (options.partial) { return } + const attr = data.system?.attr ?? {}; + if (Object.keys(attr).length > 0) { + setProperty( + data, + `flags.${__ID__}.convertAttributesIntoItems`, + deepClone(attr), + ); + }; + }; + // #endregion Data Migration }; diff --git a/module/migrations/utils.mjs b/module/migrations/utils.mjs index 6950cc2..95f4c0f 100644 --- a/module/migrations/utils.mjs +++ b/module/migrations/utils.mjs @@ -25,7 +25,7 @@ export async function migrateCollection( const toMigrate = collection .filter(doc => doc.getFlag(__ID__, flag)) .map(doc => { - const update = convertor(doc) ?? {}; + const update = convertor(doc, options) ?? {}; update[`_id`] = doc._id; // v13/v14+ compatibility shim @@ -85,4 +85,21 @@ export function shouldMigrateCompendium(pack, types = [`Actor`, `Item`]) { // Module compendiums should only be migrated if they don't have a download or manifest URL const module = game.modules.get(pack.metadata.packageName); return !module.download && !module.manifest; -} +}; + +export function finishMigrationWarning(warning, version) { + warning.update({ pct: 1 }); + setTimeout( + () => { + warning.remove(); + ui.notifications.success( + `taf.notifs.success.migration-successful`, + { + localize: true, + format: { version }, + }, + ); + }, + 3_000, + ); +}; diff --git a/module/migrations/v3.0.0.mjs b/module/migrations/v3.0.0.mjs index 0aa7f35..50ff931 100644 --- a/module/migrations/v3.0.0.mjs +++ b/module/migrations/v3.0.0.mjs @@ -1,5 +1,6 @@ +import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; -import { migrateCollection, shouldMigrateCompendium } from "./utils.mjs"; +import { finishMigrationWarning, migrateCollection, shouldMigrateCompendium } from "./utils.mjs"; const flag = `convertAttributesIntoItems`; const operations = []; @@ -10,15 +11,14 @@ export async function migrateTo3_0_0() { const packsToMigrate = game.packs.filter( (pack) => shouldMigrateCompendium(pack, [`Actor`]), ); - const intervalSize = 1 / (packsToMigrate.length + 1); const warning = ui.notifications.warn( "taf.notifs.warn.migration-in-progress", { - format: { version: `v3.0.0` }, + localize: true, + format: { version: `3.0.0` }, progress: true, permanent: true, - console: false, }, ); @@ -30,55 +30,49 @@ export async function migrateTo3_0_0() { { update: false, }, ), ); - warning.update({ pct: warning.pct + intervalSize }); + warning.update({ pct: 0.25, }); for (const pack of packsToMigrate) { await pack.getDocuments(); const wasLocked = pack.config.locked; - if (wasLocked) pack.configure({ locked: false }); + if (wasLocked) await pack.configure({ locked: false }); compendiumOperations.push( ...await migrateCollection( pack, flag, handleMigratingActor, - { pack, update: false, }, + { pack: pack.collection, update: false, }, ), ); - // foundry.documents.modifyBatch(compendiumOperations); - console.log(`compendiumOperations`, compendiumOperations); + await foundry.documents.modifyBatch(compendiumOperations); if (wasLocked) await pack.configure({ locked: true }); compendiumOperations = []; - warning.update({ pct: warning.pct + intervalSize }); }; - // TODO: re-lock packs here? + warning.update({ pct: 0.8 }); - warning.update({ pct: 1 }); + await foundry.documents.modifyBatch(operations); - // TODO: create the item documents (batch them if possible) - Logger.debug(`Finished v3.0.0 migration, resulting operations:`); - console.log(operations); - // Use: foundry.documents.modifyBatch - // await foundry.documents.modifyBatch(operations); + finishMigrationWarning(warning, `3.0.0`); }; -function handleMigratingActor(actor) { - console.log(actor); - +function handleMigratingActor(actor, options) { const operation = { action: `create`, + broadcast: true, documentName: `Item`, parent: actor, + pack: options.pack, noHook: true, data: [], }; - const attrs = actor.system?.attr ?? {}; + const attrs = actor.getFlag(__ID__, flag) ?? {}; for (const [ key, attr ] of Object.entries(attrs)) { operation.data.push(convertToItem(key, attr)); };