import { __ID__, filePath } from "../consts.mjs"; import { getFile, uploadJson } from "../utils/fs.mjs"; import { promptViaTemplate } from "../utils/dialogs.mjs"; import { DBConnectorMixin } from "./mixins/DBConnector.mjs"; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; const { randomID } = foundry.utils; export class ArtistApp extends DBConnectorMixin( HandlebarsApplicationMixin( ApplicationV2 )) { // #region Options static dbType = `Artist`; static dbPath = `storage/db/artists.json`; static DEFAULT_OPTIONS = { tag: `form`, classes: [ __ID__, `ArtistApp`, ], position: { width: 350, }, window: { contentClasses: [ `standard-form`, ], }, form: { handler: this.#onSubmit, submitOnChange: false, closeOnSubmit: true, }, actions: { addNewLink: this.#addNewLink, deleteLink: this.#deleteLink, }, }; static PARTS = { form: { template: filePath(`templates/ArtistApp/form.hbs`), }, linkList: { template: filePath(`templates/ArtistApp/linkList.hbs`), }, footer: { template: filePath(`templates/partials/footer.hbs`), }, }; // #endregion Options // #region Instance Data /** * The existing artist data that is being edited, or the default values */ _doc = { name: ``, links: [] }; get title() { if (this._docID && this._doc.name) { return game.i18n.format( `IT.apps.ArtistApp.title.edit`, { name: this._doc.name }, ); }; return game.i18n.localize(`IT.apps.ArtistApp.title.create`); }; // #endregion Instance Data // #region Lifecycle /** * Makes it so that we update the frame's title to include the Artist name if * we're editing an existing artist instead of creating a new one. */ _onFirstRender() { if (this._doc?.name) { this._updateFrame({ window: { title: this.title } }); }; }; /** @this {ArtistApp} */ static async #onSubmit(event, element, formData) { const artist = formData.object; if (artist.name.length === 0) { return }; artist.links = this._doc.links; artist.links.forEach(link => { delete link.isNew; }); // Validate the DB hasn't been updated since opening if (!(await this.isAbleToSave())) { return }; const artists = await getFile(`storage/db/artists.json`); let id = this._docID; if (!this._docID) { do { id = randomID(); } while (artists[id] != null); }; artists[id] = artist; await uploadJson(`db`, `artists.json`, artists); }; // #endregion Lifecycle // #region Data Prep async _prepareContext() { const ctx = { meta: { idp: this.id, }, artist: this._doc, }; return ctx; }; // #endregion Data Prep // #region Actions /** @this {ArtistApp} */ static async #addNewLink() { const link = await promptViaTemplate( `IT.dialogs.Link.title`, `templates/Dialogs/Link.hbs`, ); link.isNew = true; this._doc.links.push(link); this.render({ parts: [ `linkList` ] }); }; /** @this {ArtistApp} */ static async #deleteLink(event, element) { const index = element.closest(`[data-index]`)?.dataset.index; if (index == null) { return }; this._doc.links.splice(index, 1); this.render({ parts: [ `linkList` ] }); }; // #endregion Actions };