From 14193cbad0a808a030bb46a517368ecb75933c14 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 26 Apr 2026 23:52:37 -0600 Subject: [PATCH] Remove references to the AttributeManager now that it is no longer required --- langs/en-ca.json | 9 - module/api.mjs | 2 - module/apps/AttributeManager.mjs | 357 ------------------ module/apps/PlayerSheet.mjs | 41 -- styles/Apps/AttributeManager.css | 50 --- styles/main.css | 1 - templates/AttributeManager/attribute-list.hbs | 43 --- templates/AttributeManager/controls.hbs | 13 - 8 files changed, 516 deletions(-) delete mode 100644 module/apps/AttributeManager.mjs delete mode 100644 styles/Apps/AttributeManager.css delete mode 100644 templates/AttributeManager/attribute-list.hbs delete mode 100644 templates/AttributeManager/controls.hbs diff --git a/langs/en-ca.json b/langs/en-ca.json index 0c99bc6..1a1eecf 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -85,16 +85,7 @@ "title": "Questions", "invalid-input-type": "Invalid input type provided: {type}" }, - "AttributeManager": { - "title": "Attributes: {name}", - "has-max": "Has Maximum?", - "name-placeholder": "Attribute Name...", - "no-attributes": "No attributes yet", - "add-new-attribute": "Add New Attribute", - "default-attribute-values": "Default Attribute Values" - }, "PlayerSheet": { - "manage-attributes": "Manage Attributes", "create-item": "Create Embedded Item", "current-value": "Current value", "max-value": "Maximum value", diff --git a/module/api.mjs b/module/api.mjs index 698f141..02fd1f4 100644 --- a/module/api.mjs +++ b/module/api.mjs @@ -1,6 +1,5 @@ // Apps import { Ask } from "./apps/Ask.mjs"; -import { AttributeManager } from "./apps/AttributeManager.mjs"; import { PlayerSheet } from "./apps/PlayerSheet.mjs"; import { QueryStatus } from "./apps/QueryStatus.mjs"; @@ -18,7 +17,6 @@ export const api = deepFreeze({ QueryManager, Apps: { Ask, - AttributeManager, PlayerSheet, QueryStatus, }, diff --git a/module/apps/AttributeManager.mjs b/module/apps/AttributeManager.mjs deleted file mode 100644 index 1f4d7f6..0000000 --- a/module/apps/AttributeManager.mjs +++ /dev/null @@ -1,357 +0,0 @@ -import { __ID__, filePath } from "../consts.mjs"; -import { ask } from "../utils/DialogManager.mjs"; -import { attributeSorter } from "../utils/attributeSort.mjs"; -import { localizer } from "../utils/localizer.mjs"; -import { toID } from "../utils/toID.mjs"; - -const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; -const { deepClone, diffObject, mergeObject, performIntegerSort, randomID, setProperty } = foundry.utils; -const { DragDrop } = foundry.applications.ux; - -export class AttributeManager extends HandlebarsApplicationMixin(ApplicationV2) { - - // #region Options - static DEFAULT_OPTIONS = { - tag: `form`, - classes: [ - __ID__, - `AttributeManager`, - ], - position: { - width: 400, - height: `auto`, - }, - window: { - resizable: true, - controls: [ - { - icon: `fa-solid fa-globe`, - label: `Save As Defaults`, - visible: () => game.user.isGM, - action: `saveAsDefault`, - }, - ], - }, - form: { - submitOnChange: false, - closeOnSubmit: true, - handler: this.#onSubmit, - }, - actions: { - addNew: this.#addNew, - removeAttribute: this.#remove, - saveAsDefault: this.#saveAsDefaults, - }, - }; - - static PARTS = { - attributes: { template: filePath(`templates/AttributeManager/attribute-list.hbs`) }, - controls: { template: filePath(`templates/AttributeManager/controls.hbs`) }, - }; - // #endregion Options - - // #region Instance Data - /** @type {string | null} */ - #doc = null; - - #attributes; - - constructor({ document , ...options } = {}) { - super(options); - this.#doc = document; - this.#attributes = deepClone(document.system.attr); - }; - - get title() { - return localizer( - `taf.Apps.AttributeManager.title`, - this.#doc, - ); - }; - // #endregion Instance Data - - // #region Lifecycle - 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)); - }; - - new DragDrop.implementation({ - dragSelector: `.attribute-drag-handle`, - dropSelector: `.attributes`, - callbacks: { - dragstart: this._onDragStart.bind(this), - drop: this._onDrop.bind(this), - }, - }).bind(this.element); - }; - - /** @this {AttributeManager} */ - static async #onSubmit() { - const entries = Object.entries(this.#attributes) - .map(([id, attr]) => { - if (attr == null) { - return [ id, attr ]; - }; - - if (attr.isNew) { - delete attr.isNew; - return [ toID(attr.name), attr ]; - }; - - return [ id, attr ]; - }); - const data = Object.fromEntries(entries); - this.#attributes = data; - - const diff = diffObject( - this.#doc.system.attr, - data, - { inner: false, deletionKeys: true }, - ); - - await this.#doc.update({ "system.attr": diff }); - }; - // #endregion Lifecycle - - // #region Data Prep - async _preparePartContext(partId) { - const ctx = {}; - - ctx.actor = this.#doc; - - switch (partId) { - case `attributes`: { - await this._prepareAttributeContext(ctx); - }; - }; - - return ctx; - }; - - async _prepareAttributeContext(ctx) { - const attrs = []; - for (const [id, data] of Object.entries(this.#attributes)) { - if (data == null) { continue }; - // Remove with issue: Foundry/taf#54 - if (game.release.generation >= 14 && data == _del) {continue} - attrs.push({ - id, - name: data.name, - sort: data.sort, - isRange: data.isRange, - isNew: data.isNew ?? false, - }); - }; - ctx.attrs = attrs.sort(attributeSorter); - }; - // #endregion Data Prep - - // #region Actions - /** - * @param {Event} event - */ - async #bindListener(event) { - const target = event.target; - const data = target.dataset; - const binding = data.bind; - - let value = target.value; - switch (target.type) { - case `checkbox`: { - value = target.checked; - }; - }; - - setProperty(this.#attributes, binding, value); - await this.render({ parts: [ `attributes` ]}); - }; - - /** @this {AttributeManager} */ - static async #addNew() { - const id = randomID(); - this.#attributes[id] = { - name: ``, - sort: Number.MAX_SAFE_INTEGER, - isRange: false, - isNew: true, - }; - await this.render({ parts: [ `attributes` ]}); - }; - - /** @this {AttributeManager} */ - static async #remove($e, element) { - const attribute = element.closest(`[data-attribute]`)?.dataset.attribute; - if (!attribute) { return }; - // Remove with issue: Foundry/taf#54 - if (game.release.generation < 14) { - delete this.#attributes[attribute]; - this.#attributes[`-=${attribute}`] = null; - } - else { - this.#attributes[attribute] = _del; - } - await this.render({ parts: [ `attributes` ] }); - }; - - /** @this {AttributeManager} */ - static async #saveAsDefaults() { - const attrs = deepClone(this.#attributes); - - // Prompt the user for what values they want to save the attributes with - const inputs = []; - for (const attr of Object.values(attrs)) { - const id = toID(attr.name); - - if (attr.isRange) { - inputs.push( - { - type: `collapse`, - summary: attr.name, - inputs: [ - { - key: `${id}.value`, - type: `input`, - inputType: `number`, - label: `Value`, - defaultValue: attr.value, - }, - { - key: `${id}.max`, - type: `input`, - inputType: `number`, - label: `Maximum`, - defaultValue: attr.max, - }, - ], - }, - { type: `divider` }, - ); - continue; - }; - - inputs.push({ - key: `${id}.value`, - type: `input`, - inputType: `number`, - label: `${attr.name}`, - defaultValue: attr.value, - }); - - inputs.push({ type: `divider` }); - }; - - const prompt = { - id: `${this.#doc.id}-global-attr-saving`, - inputs: inputs.slice(0, -1), - alwaysUseAnswerObject: true, - window: { title: `taf.Apps.AttributeManager.default-attribute-values` }, - }; - - const response = await ask(prompt); - switch (response.state) { - case `errored`: - ui.notifications.error(response.error); - // eslint-disable-next-line no-fallthrough - case `fronted`: - return; - }; - - if (!response.answers) { return }; - - const fullAttrs = mergeObject(attrs, response.answers); - game.settings.set(__ID__, `actorDefaultAttributes`, fullAttrs); - ui.notifications.success(`taf.notifs.success.saved-default-attributes`, { localize: true }); - }; - // #endregion Actions - - // #region Drag & Drop - _onDragStart(event) { - const target = event.currentTarget.closest(`[data-attribute]`); - if (`link` in event.target.dataset) { return }; - if (!target.dataset.attribute) { return }; - - const attributeID = target.dataset.attribute; - const attribute = this.#attributes[attributeID]; - const dragData = { - _id: attributeID, - sort: attribute.sort, - }; - - event.dataTransfer.setDragImage(target, 16, 23); - event.dataTransfer.setData(`taf/json`, JSON.stringify(dragData)); - - // Provide an attribute reference in a way that prose-mirror can use - if (!attribute.isNew) { - event.dataTransfer.setData( - `text/plain`, - `[[@${attributeID}]]{${attribute.name}}`, - ); - }; - }; - - _onDrop(event) { - let dropped; - try { - dropped = JSON.parse(event.dataTransfer.getData(`taf/json`)); - } catch { - return; - } - - const dropTarget = event.target.closest(`[data-attribute]`); - if (!dropTarget) { return }; - const targetID = dropTarget.dataset.attribute; - let target; - - // Not moving location, ignore drop event - if (targetID === dropped._id) { return }; - - // Determine all of the siblings and create sort data - const siblings = []; - for (const element of dropTarget.parentElement.children) { - const siblingID = element.dataset.attribute; - const attr = this.#attributes[siblingID]; - const sibling = { - _id: siblingID, - sort: attr.sort, - }; - if (siblingID && siblingID !== dropped._id) { - siblings.push(sibling); - }; - if (siblingID === targetID) { - target = sibling; - } - }; - - const sortUpdates = performIntegerSort( - dropped, - { - target, - siblings, - }, - ); - - const updateEntries = sortUpdates.map(({ target, update }) => { - return [ `${target._id}.sort`, update.sort ]; - }); - const update = Object.fromEntries(updateEntries); - - mergeObject( - this.#attributes, - update, - { - insertKeys: false, - insertValues: false, - inplace: true, - performDeletions: false, - }, - ); - - this.render({ parts: [ `attributes` ] }); - }; - // #endregion Drag & Drop -}; diff --git a/module/apps/PlayerSheet.mjs b/module/apps/PlayerSheet.mjs index 2e3da97..4677de3 100644 --- a/module/apps/PlayerSheet.mjs +++ b/module/apps/PlayerSheet.mjs @@ -1,6 +1,5 @@ import { __ID__, filePath } from "../consts.mjs"; import { deleteItemFromElement, editItemFromElement } from "./utils.mjs"; -import { AttributeManager } from "./AttributeManager.mjs"; import { config } from "../config.mjs"; import { Logger } from "../utils/Logger.mjs"; import { TAFDocumentSheetConfig } from "./TAFDocumentSheetConfig.mjs"; @@ -36,7 +35,6 @@ export class PlayerSheet extends }, actions: { createEmbeddedItem: this.#createEmbeddedItem, - manageAttributes: this.#manageAttributes, configureSheet: this.#configureSheet, toggleExpand: this.#toggleExpand, }, @@ -194,17 +192,6 @@ export class PlayerSheet extends const controls = super._getHeaderControls(); controls.push( - { - icon: `fa-solid fa-at`, - label: `taf.Apps.PlayerSheet.manage-attributes`, - action: `manageAttributes`, - visible: () => { - const isGM = game.user.isGM; - const allowPlayerEdits = game.settings.get(__ID__, `canPlayersManageAttributes`); - const editable = this.isEditable; - return isGM || (allowPlayerEdits && editable); - }, - }, { icon: `fa-solid fa-suitcase`, label: `taf.Apps.PlayerSheet.create-item`, @@ -252,12 +239,6 @@ export class PlayerSheet extends { jQuery: false, fixed: true }, ); }; - - async close() { - this.#attributeManager?.close(); - this.#attributeManager = null; - return super.close(); - }; // #endregion Lifecycle // #region Data Prep @@ -412,28 +393,6 @@ export class PlayerSheet extends // #endregion Data Prep // #region Actions - #attributeManager = null; - - /** - * This action opens an instance of the AttributeManager application - * so that the user can edit and update all of the attributes for the - * actor. This persists the application instance for the duration of - * the ActorSheet's lifespan. - * - * @this {PlayerSheet} - */ - static async #manageAttributes() { - this.#attributeManager ??= new AttributeManager({ document: this.actor }); - if (this.#attributeManager.rendered) { - await this.#attributeManager.bringToFront(); - } else { - await this.#attributeManager.render({ - force: true, - window: { windowId: this.window.windowId }, - }); - }; - }; - /** * This action overrides the default Foundry action in order to tell * it to open my custom DocumentSheetConfig application instead of diff --git a/styles/Apps/AttributeManager.css b/styles/Apps/AttributeManager.css deleted file mode 100644 index 5bb8567..0000000 --- a/styles/Apps/AttributeManager.css +++ /dev/null @@ -1,50 +0,0 @@ -.taf.AttributeManager { - .attributes { - display: flex; - flex-direction: column; - gap: 8px; - } - - .attribute { - display: grid; - grid-template-columns: min-content 1fr repeat(3, auto); - align-items: center; - gap: 8px; - padding: 8px; - border: 1px solid rebeccapurple; - border-radius: 4px; - - label { - display: flex; - flex-direction: row; - align-items: center; - - &.vertical { - flex-direction: column; - } - } - - /* Used to style the actual element as dragging */ - &:has(taf-icon:active) { - background: var(--background); - } - } - - taf-icon { - cursor: grab; - - &:active { - cursor: grabbing; - } - } - - .controls { - display: flex; - flex-direction: row; - gap: 8px; - - button { - flex-grow: 1; - } - } -} diff --git a/styles/main.css b/styles/main.css index be8ba70..627b546 100644 --- a/styles/main.css +++ b/styles/main.css @@ -27,7 +27,6 @@ @import url("./Apps/common.css") layer(apps); @import url("./Apps/Ask.css") layer(apps); @import url("./Apps/AttributeItemSheet.css") layer(apps); -@import url("./Apps/AttributeManager.css") layer(apps); @import url("./Apps/GenericItemSheet.css") layer(apps); @import url("./Apps/PlayerSheet.css") layer(apps); @import url("./Apps/QueryStatus.css") layer(apps); diff --git a/templates/AttributeManager/attribute-list.hbs b/templates/AttributeManager/attribute-list.hbs deleted file mode 100644 index 065e3f4..0000000 --- a/templates/AttributeManager/attribute-list.hbs +++ /dev/null @@ -1,43 +0,0 @@ -
- {{#each attrs as |attr|}} -
- - {{#if attr.isNew}} - - {{else}} - {{ attr.name }} - {{/if}} - - -
- {{else}} -

- {{localize "taf.Apps.AttributeManager.no-attributes"}} -

- {{/each}} -
diff --git a/templates/AttributeManager/controls.hbs b/templates/AttributeManager/controls.hbs deleted file mode 100644 index 0fd91f5..0000000 --- a/templates/AttributeManager/controls.hbs +++ /dev/null @@ -1,13 +0,0 @@ -
- - -