image-tagger/module/apps/Artist.mjs

145 lines
3.1 KiB
JavaScript

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 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/ArtistApp/footer.hbs`),
},
};
// #endregion Options
// #region Instance Data
static dbType = `Artist`;
static dbPath = `storage/db/artists.json`;
/**
* 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(
`TB.apps.ArtistApp.title.edit`,
{ name: this._doc.name },
);
};
return game.i18n.localize(`TB.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(
`TB.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
};