stat-tracker/module/Apps/TableCreator.mjs

146 lines
3.5 KiB
JavaScript

import { BucketTypes } from "../utils/buckets.mjs";
import { createDiceTable } from "../utils/databases/utils.mjs";
import { filePath } from "../consts.mjs";
import { Logger } from "../utils/Logger.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
const diceNamespacePattern = /^Dice\/d[0-9]+$/;
export class TableCreator extends HandlebarsApplicationMixin(ApplicationV2) {
// #region Options
static DEFAULT_OPTIONS = {
classes: [
__ID__,
`TableCreator`,
],
window: {
title: `Create Table`,
frame: true,
positioned: true,
resizable: false,
minimizable: true,
},
position: {
width: 320,
height: `auto`,
},
actions: {
createTable: this.#createTable,
},
};
static PARTS = {
content: {
template: filePath(`templates/Apps/TableCreator.hbs`),
root: true,
},
};
// #endregion
async render({ userUpdated, ...opts } = {}) {
if (userUpdated && !this._selectedUsers.includes(userUpdated)) {
return;
}
await super.render(opts);
};
async _onRender(context, options) {
await super._onRender(context, options);
const elements = this.element
.querySelectorAll(`[data-bind]`);
for (const input of elements) {
input.addEventListener(`change`, this.#bindListener.bind(this));
};
};
/** @type {string} */
_name = ``;
/** @type {string} */
_type = BucketTypes.NUMBER;
#diceNamespaceAlert = null;
async _preparePartContext() {
const ctx = {};
ctx.meta = {
idp: this.id,
};
ctx.name = this._name;
ctx.type = this._type;
ctx.typeDisabled = false;
ctx.types = Object.values(BucketTypes);
// Special Case for the dice namespace
if (this._name.startsWith(`Dice`)) {
ctx.createButtonDisabled = !this._name.match(diceNamespacePattern);
ctx.typeDisabled = true;
ctx.type = BucketTypes.RANGE;
this.#diceNamespaceAlert ??= ui.notifications.info(
`Tables in the "Dice" namespace must be formatted as "Dice/dX" where X is the number of sides on the die and are restricted to be ranges 1 to X.`,
{ permanent: true },
);
} else if (this.#diceNamespaceAlert != null) {
ui.notifications.remove(this.#diceNamespaceAlert);
this.#diceNamespaceAlert = null;
};
if (import.meta.env.DEV) {
Logger.log(`Context`, ctx);
};
return ctx;
};
/**
* @param {Event} event
*/
async #bindListener(event) {
const target = event.target;
const data = target.dataset;
const binding = data.bind;
if (!binding || !Object.hasOwn(this, binding)) {
Logger.debug(`Skipping change for element with binding "${binding}"`);
return;
};
Logger.log(`updating ${binding} value to ${target.value}`);
this[binding] = target.value;
this.render();
};
static async #createTable() {
/** @type {string} */
const name = this._name;
if (name === ``) {
ui.notifications.error(`Cannot create a table without a name`);
};
const existing = await CONFIG.stats.db.getTable(name);
if (existing) {
ui.notifications.error(`A table with the name "${name}" already exists`);
return;
};
if (name.startsWith(`Dice`)) {
if (!name.match(diceNamespacePattern)) {
ui.notifications.error(`Table name doesn't conform to the "Dice/dX" format required by the Dice namespace.`);
return;
};
const size = Number(name.replace(`Dice/d`, ``));
await CONFIG.stats.db.createTable(createDiceTable(size));
return;
};
await CONFIG.stats.db.createTable({
name,
buckets: {
type: this._type,
},
graph: {
type: `bar`,
stacked: true,
},
});
};
};