Begin working on converting the list of text into an actual graph

This commit is contained in:
Oliver-Akins 2025-05-24 16:45:43 -06:00
parent c7197641b6
commit cb519ad721
4 changed files with 108 additions and 46 deletions

View file

@ -1,9 +1,13 @@
import { filePath } from "../consts.mjs"; import { filePath } from "../consts.mjs";
import { Logger } from "../utils/Logger.mjs";
import { PrivacyMode } from "../utils/privacy.mjs";
const { HandlebarsApplicationMixin } = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
const { AbstractSidebarTab } = foundry.applications.sidebar; const { AbstractSidebarTab } = foundry.applications.sidebar;
const { getType } = foundry.utils;
export class StatSidebar extends HandlebarsApplicationMixin(AbstractSidebarTab) { export class StatSidebar extends HandlebarsApplicationMixin(AbstractSidebarTab) {
// #region Options
/** @override */ /** @override */
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
classes: [ classes: [
@ -14,9 +18,7 @@ export class StatSidebar extends HandlebarsApplicationMixin(AbstractSidebarTab)
title: `SIDEBAR.TabSettings`, title: `SIDEBAR.TabSettings`,
}, },
actions: { actions: {
openStats: this.#openStats, openApp: this.#openApp,
manageTables: this.#manageTables,
createTable: this.#createTable,
}, },
}; };
@ -25,23 +27,74 @@ export class StatSidebar extends HandlebarsApplicationMixin(AbstractSidebarTab)
/** @override */ /** @override */
static PARTS = { static PARTS = {
stats: { // stats: {
template: filePath(`templates/Apps/StatSidebar/main.hbs`), // template: filePath(`templates/Apps/StatSidebar/main.hbs`),
root: true, // root: true,
// },
summaryText: {
template: filePath(`templates/Apps/StatSidebar/.hbs`),
},
summaryGraph: {
template: filePath(`templates/Apps/StatSidebar/.hbs`),
},
appControls: {
template: filePath(`templates/Apps/StatSidebar/controlSection.hbs`),
}, },
}; };
// #endregion Options
async _prepareContext(options) { // #region Lifecycle
async render(options, _options) {
const { userUpdated = null } = (getType(options) === `Object` ? options : _options) ?? {};
if (userUpdated && userUpdated !== game.user.id) {
// TODO: Update the data in the graph
return;
};
return super.render(options, _options);
};
async _onFirstRender(context, options) {
await super._onFirstRender(context, options);
CONFIG.stats.db.addApp(this);
};
// #endregion Lifecycle
// #region Data Prep
async _preparePartContext(context, options) {
const ctx = await super._prepareContext(options); const ctx = await super._prepareContext(options);
this.#prepareApps(ctx);
return ctx;
};
async #prepareSummary(ctx) {
const db = CONFIG.stats.db; const db = CONFIG.stats.db;
ctx.tableCount = (await db.getTables()).length; const tables = await db.getTables();
ctx.tableCount = tables.length;
ctx.rowCount = {
total: 0,
public: 0,
self: 0,
private: 0,
gm: 0,
};
for (const table of tables) {
const rows = await db.getRows(table.name, [game.user.id], Object.values(PrivacyMode));
for (const row of rows[game.user.id] ?? []) {
ctx.rowCount[row.privacy]++;
ctx.rowCount.total++;
};
};
};
async #prepareApps(ctx) {
const controls = { const controls = {
openStats: { label: `View Stats`, action: `openStats` }, openStats: { label: `View Stats`, action: `openApp`, appKey: `viewer` },
createTable: { label: `Create New Table`, action: `createTable` }, createTable: { label: `Create New Table`, action: `openApp`, appKey: `creator` },
manageTables: { label: `Manage Tables`, action: `manageTables` }, manageTables: { label: `Manage Tables`, action: `openApp`, appKey: `tableManager` },
// manageData: { label: `Manage Data`, action: `` }, // manageData: { label: `Manage Data`, action: `openApp`, appKey: `rowManager` },
}; };
if (!game.user.isGM) { if (!game.user.isGM) {
@ -55,27 +108,21 @@ export class StatSidebar extends HandlebarsApplicationMixin(AbstractSidebarTab)
// delete controls.manageData; // delete controls.manageData;
// }; // };
Hooks.callAll(`${__ID__}.getStatsSidebarControls`, controls); Hooks.callAll(`${__ID__}.getStatsSidebarApps`, controls);
ctx.controls = Object.values(controls); ctx.controls = Object.values(controls);
return ctx;
}; };
// #endregion Data Prep
/** @this {StatSidebar} */ // #region Actions
static async #openStats() { static async #openApp(target) {
const app = new CONFIG.stats.viewer; const { appKey } = target.dataset;
app.render({ force: true }); const cls = CONFIG.stats[appKey];
}; if (!(cls.prototype instanceof ApplicationV2)) {
Logger.error(`Cannot create an app from`, cls);
/** @this {StatSidebar} */ return;
static async #manageTables() { };
const app = new CONFIG.stats.manager; const app = new cls();
app.render({ force: true });
};
/** @this {StatSidebar} */
static async #createTable() {
const app = new CONFIG.stats.creator;
app.render({ force: true }); app.render({ force: true });
}; };
// #endregion Actions
}; };

View file

@ -38,7 +38,8 @@ Hooks.on(`init`, () => {
db: UserFlagDatabase, db: UserFlagDatabase,
viewer: StatsViewer, viewer: StatsViewer,
creator: TableCreator, creator: TableCreator,
manager: TableManager, tableManager: TableManager,
rowManager: null,
}; };
if (import.meta.env.DEV) { if (import.meta.env.DEV) {

View file

@ -0,0 +1,12 @@
<section>
<h4 class="divider">{{ sectionTitle }}</h4>
{{#each controls as | btn |}}
<button
type="button"
data-action="{{ btn.action }}"
data-app-key="{{ btn.appKey }}"
>
{{ btn.label }}
</button>
{{/each}}
</section>

View file

@ -4,28 +4,30 @@
<span>Count of Tables</span> <span>Count of Tables</span>
<span>{{ tableCount }}</span> <span>{{ tableCount }}</span>
</div> </div>
{{!-- <div class="info"> <div class="info">
<span>Your Total Rows</span> <span>Your Total Rows</span>
<span>{{ userRowCount }}</span> <span>{{ rowCount.total }}</span>
</div>
<div class="info">
<span>Your Public Rows</span>
<span>{{ rowCount.public }}</span>
</div>
<div class="info">
<span>Your Self Rows</span>
<span>{{ rowCount.self }}</span>
</div> </div>
<div class="info"> <div class="info">
<span>Your Private Rows</span> <span>Your Private Rows</span>
<span>{{ userPrivateRowCount }}</span> <span>{{ rowCount.private }}</span>
</div> </div>
<div class="info"> <div class="info">
<span>Your Blind Rows</span>
<span>{{ rowCount.gm }}</span>
</div>
{{!-- <div class="info">
<span>Global Row Count</span> <span>Global Row Count</span>
<span>{{ globalRowCount }}</span> <span>{{ globalRowCount }}</span>
</div> --}} </div> --}}
</section> </section>
<section>
<h4 class="divider">Controls</h4>
{{#each controls as | btn |}}
<button
type="button"
data-action="{{ btn.action }}"
>
{{ btn.label }}
</button>
{{/each}}
</section>