Refactor/275 actor sheets simplification (#291)

* FEAT: create isNPC geeter and add the prop on metada on actors
FEAT: create common method for documents sheets
FEAT: create BaseActorSheet and implementation

* FIX: tabs label

* REFACTOR: remove unused methods
REFACTOR: simplify CharacterSheet's click actions methods
REFACTOR: minor fix on DHActor class

* REFACTOR: remove unused methods
REFACTOR: create method on BaseActorSheet
REFACTOR: make Datamodel metadata getter

* REFACTOR: remove unused method on setting sheet
FEAT: create BaseActorSetting
FIX: add type="button" to button on actor's sheet

* FIX jsdoc

* PRETTIER

---------

Co-authored-by: Joaquin Pereyra <joaquinpereyra98@users.noreply.github.com>
This commit is contained in:
joaquinpereyra98 2025-07-07 20:27:21 -03:00 committed by GitHub
parent 7d7fb88035
commit 87b3677956
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 723 additions and 1253 deletions

View file

@ -1,39 +1,17 @@
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
import DHBaseActorSettings from '../sheets/api/actor-setting.mjs';
export default class DHEnvironmentSettings extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(actor) {
super({});
this.actor = actor;
this._dragDrop = this._createDragDropHandlers();
}
get title() {
return `${game.i18n.localize('DAGGERHEART.GENERAL.Tabs.settings')}`;
}
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
export default class DHEnvironmentSettings extends DHBaseActorSettings {
/**@inheritdoc */
static DEFAULT_OPTIONS = {
tag: 'form',
classes: ['daggerheart', 'dh-style', 'dialog', 'environment-settings'],
window: {
icon: 'fa-solid fa-wrench',
resizable: false
},
position: { width: 455, height: 'auto' },
classes: ['environment-settings'],
actions: {
addFeature: this.#addFeature,
editFeature: this.#editFeature,
removeFeature: this.#removeFeature,
addCategory: this.#addCategory,
deleteProperty: this.#deleteProperty,
addCategory: DHEnvironmentSettings.#addCategory,
removeCategory: DHEnvironmentSettings.#removeCategory,
viewAdversary: this.#viewAdversary,
deleteAdversary: this.#deleteAdversary
},
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false
},
dragDrop: [
{ dragSelector: null, dropSelector: '.category-container' },
{ dragSelector: null, dropSelector: '.tab.features' },
@ -41,6 +19,7 @@ export default class DHEnvironmentSettings extends HandlebarsApplicationMixin(Ap
]
};
/**@override */
static PARTS = {
header: {
id: 'header',
@ -61,100 +40,33 @@ export default class DHEnvironmentSettings extends HandlebarsApplicationMixin(Ap
}
};
/** @inheritdoc */
static TABS = {
details: {
active: true,
cssClass: '',
group: 'primary',
id: 'details',
icon: null,
label: 'DAGGERHEART.GENERAL.Tabs.details'
},
features: {
active: false,
cssClass: '',
group: 'primary',
id: 'features',
icon: null,
label: 'DAGGERHEART.GENERAL.Tabs.features'
},
adversaries: {
active: false,
cssClass: '',
group: 'primary',
id: 'adversaries',
icon: null,
label: 'DAGGERHEART.GENERAL.Tabs.adversaries'
primary: {
tabs: [{ id: 'details' }, { id: 'features' }, { id: 'adversaries' }],
initial: 'details',
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.document = this.actor;
context.tabs = this._getTabs(this.constructor.TABS);
context.systemFields = this.actor.system.schema.fields;
context.isNPC = true;
return context;
}
_attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options);
this._dragDrop.forEach(d => d.bind(htmlElement));
}
_createDragDropHandlers() {
return this.options.dragDrop.map(d => {
d.callbacks = {
dragstart: this._onDragStart.bind(this),
drop: this._onDrop.bind(this)
};
return new foundry.applications.ux.DragDrop.implementation(d);
});
}
_getTabs(tabs) {
for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
v.cssClass = v.active ? 'active' : '';
}
return tabs;
}
static async #addFeature(_, _button) {
await this.actor.createEmbeddedDocuments('Item', [
{
type: 'feature',
name: game.i18n.format('DOCUMENT.New', { type: game.i18n.localize('TYPES.Item.feature') }),
img: 'icons/magic/perception/orb-crystal-ball-scrying-blue.webp'
}
]);
this.render();
}
static async #editFeature(_, target) {
this.actor.items.get(target.id).sheet.render(true);
}
static async #removeFeature(_, target) {
await this.actor.deleteEmbeddedDocuments('Item', [target.id]);
this.render();
}
/**
* Adds a new category entry to the actor.
* @type {ApplicationClickAction}
*/
static async #addCategory() {
await this.actor.update({
[`system.potentialAdversaries.${foundry.utils.randomID()}.label`]: game.i18n.localize(
'DAGGERHEART.ACTORS.Environment.newAdversary'
)
});
this.render();
}
static async #deleteProperty(_, target) {
await this.actor.update({ [`${target.dataset.path}.-=${target.id}`]: null });
this.render();
/**
* Removes an category entry from the actor.
* @type {ApplicationClickAction}
*/
static async #removeCategory(_, target) {
await this.actor.update({ [`system.potentialAdversaries.-=${target.dataset.categoryId}`]: null });
}
static async #viewAdversary(_, button) {
@ -164,17 +76,17 @@ export default class DHEnvironmentSettings extends HandlebarsApplicationMixin(Ap
return;
}
adversary.sheet.render(true);
adversary.sheet.render({ force: true });
}
static async #deleteAdversary(event, target) {
const adversaryKey = target.dataset.adversary;
const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`;
console.log(target.dataset.potentialAdversar);
const newAdversaries = foundry.utils
.getProperty(this.actor, path)
.filter(x => x && (x?.uuid ?? x) !== adversaryKey);
await this.actor.update({ [path]: newAdversaries });
this.render();
}
async _onDragStart(event) {
@ -206,9 +118,4 @@ export default class DHEnvironmentSettings extends HandlebarsApplicationMixin(Ap
this.render();
}
}
static async updateForm(event, _, formData) {
await this.actor.update(formData.object);
this.render();
}
}