From 4c05171e04db22ca858cb503dfce7f15b302a825 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 5 Apr 2026 20:14:02 -0600 Subject: [PATCH] Add the context menu for items in the player sheet --- langs/en-ca.json | 1 + module/apps/PlayerSheet.mjs | 33 ++++++++++++++++++++++++++++++++- module/apps/utils.mjs | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/langs/en-ca.json b/langs/en-ca.json index 7b7a326..8cd6796 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -58,6 +58,7 @@ "confirm-and-close": "Confirm and Close", "save-and-close": "Save and Close", "delete": "Delete", + "edit": "Edit", "resizable": "Resizable", "not-resizable": "Not Resizable", "item": { diff --git a/module/apps/PlayerSheet.mjs b/module/apps/PlayerSheet.mjs index 295fd3c..3840238 100644 --- a/module/apps/PlayerSheet.mjs +++ b/module/apps/PlayerSheet.mjs @@ -4,11 +4,12 @@ import { attributeSorter } from "../utils/attributeSort.mjs"; import { config } from "../config.mjs"; import { TAFDocumentSheetConfig } from "./TAFDocumentSheetConfig.mjs"; import { TAFDocumentSheetMixin } from "./mixins/TAFDocumentSheetMixin.mjs"; +import { deleteItemFromElement, editItemFromElement } from "./utils.mjs"; const { HandlebarsApplicationMixin } = foundry.applications.api; const { ActorSheetV2 } = foundry.applications.sheets; const { getProperty } = foundry.utils; -const { TextEditor } = foundry.applications.ux; +const { ContextMenu, TextEditor } = foundry.applications.ux; export class PlayerSheet extends TAFDocumentSheetMixin( @@ -146,6 +147,36 @@ export class PlayerSheet extends return controls; }; + async _onRender(ctx, options) { + await super._onRender(ctx, options); + + new ContextMenu.implementation( + this.element, + `li.item`, + [ + { + label: _loc(`taf.misc.edit`), + condition: (el) => { + const itemUuid = el.dataset.itemUuid; + const itemExists = itemUuid != null && itemUuid !== ""; + return this.isEditable && itemExists; + }, + onClick: editItemFromElement, + }, + { + label: _loc(`taf.misc.delete`), + condition: (el) => { + const itemUuid = el.dataset.itemUuid; + const itemExists = itemUuid != null && itemUuid !== ""; + return this.isEditable && itemExists; + }, + onClick: deleteItemFromElement, + }, + ], + { jQuery: false, fixed: true, }, + ); + }; + async close() { this.#attributeManager?.close(); this.#attributeManager = null; diff --git a/module/apps/utils.mjs b/module/apps/utils.mjs index e2af7d4..de8edcc 100644 --- a/module/apps/utils.mjs +++ b/module/apps/utils.mjs @@ -3,6 +3,32 @@ This file contains utility methods used by Applications in order to be DRYer */ +/** + * @param {Event} _event The click event + * @param {HTMLElement} target The element to operate on + */ +export async function editItemFromElement(_event, target) { + const itemEl = target.closest(`[data-item-uuid]`); + if (!itemEl) { return }; + const uuid = itemEl.dataset.itemUuid; + if (!uuid) { return }; + const item = await fromUuid(uuid); + item.sheet.render({ force: true, orBringToFront: true }); +}; + +/** + * @param {Event} _event The click event + * @param {HTMLElement} target The element to operate on + */ +export async function deleteItemFromElement(_event, target) { + const itemEl = target.closest(`[data-item-uuid]`); + if (!itemEl) { return }; + const uuid = itemEl.dataset.itemUuid; + if (!uuid) { return }; + const item = await fromUuid(uuid); + item.deleteDialog(); +}; + /** * Updates a document using the UUID, this is most useful for editing * documents from a sheet of another document (e.g. an Item embedded