foundry-dsa41-game/src/module/sheets/merchantSheet.mjs

250 lines
7.5 KiB
JavaScript

const {HandlebarsApplicationMixin} = foundry.applications.api
const {DocumentSheetV2, ActorSheetV2} = foundry.applications.sheets
export class MerchantSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
/** @inheritDoc */
static DEFAULT_OPTIONS = {
position: {width: 520, height: 480},
classes: ['dsa41', 'sheet', 'actor', 'merchant'],
tag: 'form',
dragDrop: [{
dropSelector: '.tab.inventory.active'
}],
form: {
submitOnChange: true,
closeOnSubmit: false,
handler: MerchantSheet.#onSubmitForm
},
window: {
resizable: true,
},
actions: {
editImage: MerchantSheet.editImage,
editServiceImage: MerchantSheet.#editServiceImage,
editNewServiceImage: MerchantSheet.#editNewServiceImage,
addNewService: MerchantSheet.#addNewService,
removeService: MerchantSheet.#removeService,
}
}
static TABS = {
sheet: {
tabs: [
{id: 'goods', group: 'sheet', label: 'Waren'},
{id: 'services', group: 'sheet', label: 'Dienstleistungen'},
// Meta is added via GM permission
],
initial: 'goods'
}
}
/** @inheritDoc */
static PARTS = {
form: {
template: `systems/DSA_4-1/templates/actor/merchant/main-sheet.hbs`
},
goods: {
template: `systems/DSA_4-1/templates/actor/merchant/tab-goods.hbs`
},
services: {
template: `systems/DSA_4-1/templates/actor/merchant/tab-services.hbs`
},
meta: {
template: `systems/DSA_4-1/templates/actor/merchant/tab-meta.hbs`
}
}
constructor(options = {}) {
super(options);
}
/**
* Handle form submission
* @this {AdvantageSheet}
* @param {SubmitEvent} event
* @param {HTMLFormElement} form
* @param {FormDataExtended} formData
*/
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
console.log(formData.object)
await this.document.update(formData.object) // Note: formData.object
}
static async #removeService(event, target) {
const {rowId} = target.dataset;
const services = this.document.services
services.splice(rowId, 1)
this.document.update({"system.services": services})
}
static async #addNewService(event, target) {
event.preventDefault()
const fieldset = this.element.querySelector('details')
const image = fieldset.querySelector('img').src
const name = fieldset.querySelector('input[name="new_name"]').value
const price = fieldset.querySelector('input[name="new_price"]').value
const availability = fieldset.querySelector('input[name="new_availability"]').value
const description = fieldset.querySelector('prose-mirror').value
if (name && price) {
let services = this.document.system.services
services.push({
image,
name,
price,
availability,
description
})
this.document.update({"system.services": services}).then(e => {
this.element.reset()
})
}
return false
}
static async #editNewServiceImage(event, target) {
const field = target.dataset.field || "img"
const current = foundry.utils.getProperty(this.document, field)
const fp = new foundry.applications.apps.FilePicker({
type: "image",
current: current,
callback: (path) => {
target.src = path
}
})
fp.render(true)
}
static async #editServiceImage(event, target) {
const field = target.dataset.field || "img"
const current = foundry.utils.getProperty(this.document, field)
const fp = new foundry.applications.apps.FilePicker({
type: "image",
current: current,
callback: (path) => {
target.src = path
//foundry.utils.setProperty(this.document, field, path)
target.parentElement.querySelector(`input[name="${field}"][type="hidden"]`).value = path
this.element.submit()
}
})
fp.render(true)
}
/**
* Handle changing a Document's image.
* @param {MouseEvent} event The click event.
* @returns {Promise<FilePicker>}
* @protected
*/
/*
static _onEditImage(event) {
const attr = event.currentTarget.dataset.edit;
const current = foundry.utils.getProperty(this.object, attr);
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {};
const fp = new FilePicker.implementation({
current,
type: "image",
redirectToRoot: img ? [img] : [],
callback: path => {
event.target.src = path;
event.target.dataset.edit
this.document.update({'image': path})
},
top: this.position.top + 40,
left: this.position.left + 10
});
return fp.browse();
}*/
_getTabsConfig(group) {
const tabs = foundry.utils.deepClone(super._getTabsConfig(group))
// Modify tabs based on document properties
if (game.user.isGM) {
tabs.tabs.push({id: "meta", group: "sheet", label: "Meta"})
}
return tabs
}
/** @override */
async _prepareContext(options) {
const context = await super._prepareContext(options)
context.name = this.document.name
context.image = this.document.img
context.description = this.document.system.description
context.goods = this.document.itemTypes["Equipment"] ?? []
context.services = this.document.system.services
return context
}
/**
* Actions performed after any render of the Application.
* Post-render steps are not awaited by the render process.
* @param {ApplicationRenderContext} context Prepared context data
* @param {RenderOptions} options Provided render options
* @protected
*/
_onRender(context, options) {
new foundry.applications.ux.DragDrop.implementation({
dropSelector: ".window-content",
permissions: {
drop: this._canDragDrop.bind(this)
},
callbacks: {
drop: this._onDrop.bind(this)
}
}).bind(this.element);
}
_canDragDrop(event, options) {
return game.user.isGM
}
async _onDrop(event) {
const data = TextEditor.implementation.getDragEventData(event);
const actor = this.actor;
const allowed = Hooks.call("dropActorSheetData", actor, this, data);
if (allowed === false) return;
// Dropped Documents
const documentClass = foundry.utils.getDocumentClass(data.type);
if (documentClass) {
const document = await documentClass.fromDropData(data);
if (document.type === "Equipment") {
// No duplication by moving items from one actor to another
if (document.parent && document.parent !== this.actor) {
document.parent.items.get(document._id).delete()
}
await this._onDropDocument(event, document);
}
}
}
}