partial migration of groupsheet

feature/applicationv2
macniel 2025-10-16 16:24:36 +02:00
parent e14e4e7108
commit 6f1bad0b67
6 changed files with 134 additions and 122 deletions

View File

@ -1,5 +1,6 @@
const {HandlebarsApplicationMixin} = foundry.applications.api const {HandlebarsApplicationMixin} = foundry.applications.api
const {ActorSheetV2} = foundry.applications.sheets const {ActorSheetV2} = foundry.applications.sheets
const {ContextMenu} = foundry.applications.ux
export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) { export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
@ -8,17 +9,22 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
position: {width: 520, height: 480}, position: {width: 520, height: 480},
classes: ['dsa41', 'sheet', 'actor', 'group'], classes: ['dsa41', 'sheet', 'actor', 'group'],
tag: 'form', tag: 'form',
dragDrop: [{
dropSelector: '.tab.inventory.active'
}],
form: { form: {
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false,
handler: GroupSheet.#onSubmitForm handler: GroupSheet.#onSubmitForm
}, },
window: {
resizable: true,
},
actions: { actions: {
roll: GroupSheet.#dieRoll, roll: GroupSheet.#dieRoll,
editImage: ActorSheetV2.DEFAULT_OPTIONS.actions.editImage, editImage: ActorSheetV2.DEFAULT_OPTIONS.actions.editImage,
openEmbeddedDocument: GroupSheet.#openEmbeddedDocument, openEmbeddedDocument: GroupSheet.#openEmbeddedDocument,
openActorDocument: GroupSheet.#openActorDocument, openActorDocument: GroupSheet.#openActorDocument,
removeFromParty: GroupSheet.#removeFromParty,
} }
} }
@ -27,7 +33,6 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
tabs: [ tabs: [
{id: 'members', group: 'sheet', label: 'Gruppenmitglieder'}, {id: 'members', group: 'sheet', label: 'Gruppenmitglieder'},
{id: 'inventory', group: 'sheet', label: 'Gruppeninventar'}, {id: 'inventory', group: 'sheet', label: 'Gruppeninventar'},
// settings is only added on context
], ],
initial: 'members' initial: 'members'
} }
@ -44,51 +49,45 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
inventory: { inventory: {
template: `systems/DSA_4-1/templates/actor/group/tab-inventory.hbs` template: `systems/DSA_4-1/templates/actor/group/tab-inventory.hbs`
}, },
settings: {
template: `systems/DSA_4-1/templates/actor/group/tab-settings.hbs`
}
} }
constructor(options = {}) {
super(options);
}
static async onDroppedData(group, sheet, data) { /**
if (data.type === "Actor") { * Handle form submission
const uuid = await foundry.utils.parseUuid(data.uuid); * @this {AdvantageSheet}
const character = await (game.actors.get(uuid.id)) * @param {SubmitEvent} event
* @param {HTMLFormElement} form
* @param {FormDataExtended} formData
*/
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
// check if character already is part of the group if (formData.object.name) {
if (group.system.characters.includes(character._id)) { await (game.folders.get(this.document.system.groupId)).update({name: formData.object.name})
ui.notifications.warn(`${character.name} befindet sich bereits in der Heldengruppe ${group.name}`) }
return false;
await this.document.update(formData.object) // Note: formData.object
}
#createDragDropHandlers() {
return this.options.dragDrop.map((d) => {
d.permissions = {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this)
} }
d.callbacks = {
dragstart: this._onDragStart.bind(this),
// update group dragover: this._onDragOver.bind(this),
let settings = {...group.system.settings} drop: this._onDrop.bind(this)
character.items.filter((i) => i.type === "Advantage").forEach((advantage) => { }
if (!settings[sheet.#stringToKeyFieldName(advantage.name)]) { return new DragDrop(d)
settings[sheet.#stringToKeyFieldName(advantage.name)] = false })
}
})
character.items.filter((i) => i.type === "Skill").forEach((skill) => {
if (!settings[sheet.#stringToKeyFieldName(skill.name)]) {
settings[sheet.#stringToKeyFieldName(skill.name)] = false
}
})
await group.update({
system: {
characters: [
...group.system.characters,
character._id
],
settings: settings
}
})
ui.notifications.info(`${character.name} ist der Heldengruppe ${group.name} beigetreten`)
}
if (data.type === "Equipment") {
const uuid = await foundry.utils.parseUuid(data.uuid);
const equipment = await (game.actors.get(uuid.id))
ui.notifications.info(`${equipment.name} befindet sich nun im Inventar der Heldengruppe ${group.name}`)
return true;
}
} }
#stringToKeyFieldName(s) { #stringToKeyFieldName(s) {
@ -110,43 +109,47 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
console.log(evt) console.log(evt)
} }
static async #removeFromParty(evt) { async #onUpdateCharacterSettings(data) {
const dataset = evt.srcElement.dataset; if (data.type === "character") {
const group = this.document;
const charactersWithoutMember = group.system.characters.filter(id => id !== dataset.id)
group.update({
system: {
characters: charactersWithoutMember
}
})
// update group
let settings = {...this.document.system.settings}
data.items.filter((i) => i.type === "Advantage").forEach((advantage) => {
if (!settings[this.#stringToKeyFieldName(advantage.name)]) {
settings[this.#stringToKeyFieldName(advantage.name)] = false
}
})
data.items.filter((i) => i.type === "Skill").forEach((skill) => {
if (!settings[this.#stringToKeyFieldName(skill.name)]) {
settings[this.#stringToKeyFieldName(skill.name)] = false
}
})
await this.document.update({"system.settings": settings})
}
} }
/** _getTabsConfig(group) {
* Handle form submission const tabs = foundry.utils.deepClone(super._getTabsConfig(group))
* @this {AdvantageSheet}
* @param {SubmitEvent} event
* @param {HTMLFormElement} form
* @param {FormDataExtended} formData
*/
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
await this.document.update(formData.object) // Note: formData.object // Modify tabs based on document properties
if (game.user.isGM) {
tabs.tabs.push({id: "settings", group: "sheet", label: "Einstellungen"})
}
return tabs
} }
/** @override */ /** @override */
async _prepareContext(options) { async _prepareContext(options) {
const context = await super._prepareContext(options) const context = await super._prepareContext(options)
const groupData = context.document
// Use a safe clone of the actor data for further operations. context.system = groupData.system
const groupData = context.document; context.flags = groupData.flags
// Add the actor's data to context.data for easier access, as well as flags.
context.system = groupData.system;
context.flags = groupData.flags;
context.characters = [] context.characters = []
context.isGM = game.user.isGM; context.isGM = game.user.isGM
context.name = groupData.name
context.img = groupData.img
context.fields = []; context.fields = [];
@ -187,15 +190,8 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
if (!context.fields[n]) { if (!context.fields[n]) {
context.fields[n] = {} context.fields[n] = {}
} }
const eigenschaften = Object.values(skill.system.probe);
context.fields[n][character.name] = { context.fields[n][character.name] = {
taw: skill.system.taw, taw: skill.system.taw ?? "0",
eigenschaft1: eigenschaften[0],
eigenschaft2: eigenschaften[1],
eigenschaft3: eigenschaften[2],
rollEigenschaft1: character.system.attribute[eigenschaften[0].toLowerCase()].aktuell,
rollEigenschaft2: character.system.attribute[eigenschaften[1].toLowerCase()].aktuell,
rollEigenschaft3: character.system.attribute[eigenschaften[2].toLowerCase()].aktuell,
name: skill.name, name: skill.name,
actor: character._id, actor: character._id,
} }
@ -244,7 +240,7 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
} }
_onRender(context, options) { _onRender(context, options) {
new ContextMenu(this.element, ".equipment", [ /*ContextMenu.implementation.create(this, this.element, ".equipment", [
{ {
name: "Aus dem Gruppeninventar entfernen", name: "Aus dem Gruppeninventar entfernen",
icon: '<i class="fa-solid fa-trash"></i>', icon: '<i class="fa-solid fa-trash"></i>',
@ -255,7 +251,42 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
} }
], { ], {
jQuery: false jQuery: false
});*/
// Drag-drop
new foundry.applications.ux.DragDrop.implementation({
dropSelector: ".inventory-table",
permissions: {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this)
},
callbacks: {
dragstart: this._onDragStart.bind(this),
drop: this._onDrop.bind(this)
}
}).bind(this.element);
// Update Group Members when either an Actor was moved into the linked Folder or removed from the linked Folder
Hooks.on('updateActor', (data) => {
if (data._id !== this.document._id) { // dont update yourself when you update yourself... baka!
if (data.type === "character" && data.folder?._id === this.document.system.groupId) {
this.#onUpdateCharacterSettings(data)
this.render()
} else if (data.type === "character") {
this.render()
}
}
}); });
} }
// TODO needs to be fixed once Character Sheet is migrated to ActorSheetV2
_onDrop(event) {
const data = event.dataTransfer.getData("application/json")
if (!data) return false
console.log(data)
}
} }

View File

@ -1,40 +1,14 @@
.dsa41.sheet.actor.group { .application.sheet.dsa41.actor.group {
.window-content {
display: unset;
position: relative;
}
.sheet-header { .sheet-header {
.sheet-name {
font-size: 24pt;
height: 48px;
}
} display: grid;
grid-template-columns: 32px 1fr;
gap: 8px;
.sheet-tabs { img {
position: absolute; height: 32px;
left: 0; width: 32px;
right: 0;
top: 76px;
height: 32px;
padding: 0 16px;
}
.sheet-body {
position: absolute;
top: 98px;
left: 0;
bottom: 0;
right: 0;
padding: 8px;
margin: 8px;
div.tab {
height: 100%;
position: relative;
} }
} }

View File

@ -1,6 +1,8 @@
<div> <div>
<header class="sheet-header"> <header class="sheet-header">
<img class="img" src="{{img}}" data-action="editImage" data-edit="img" alt="{{name}}"
title="{{name}}"/>
<input class="sheet-name" type="text" name="name" value="{{name}}"/> <input class="sheet-name" type="text" name="name" value="{{name}}"/>
</header> </header>

View File

@ -59,18 +59,11 @@
{{#if (eq this "-")}} {{#if (eq this "-")}}
{{else}} {{else}}
{{#if this.taw}} {{#if (lt this.taw 0)}}
<div class="rollable" data-actor-id="{{this.actor}}" <div class="rollable" data-actor-id="{{this.actor}}"
data-taw="{{this.taw}}" data-taw="{{this.taw}}"
data-name="{{this.name}}" data-name="{{this.name}}">
data-eigenschaft1="{{this.eigenschaft1}}" {{this.taw}}
data-eigenschaft2="{{this.eigenschaft2}}"
data-eigenschaft3="{{this.eigenschaft3}}"
data-rollEigenschaft1="{{this.rollEigenschaft1}}"
data-rollEigenschaft2="{{this.rollEigenschaft2}}"
data-rollEigenschaft3="{{this.rollEigenschaft3}}">
{{this.taw}} ({{this.eigenschaft1}}, {{this.eigenschaft2}}
, {{this.eigenschaft3}})
</div> </div>
{{else}} {{else}}
Ja Ja

View File

@ -0,0 +1,12 @@
<section class="tab {{tabs.settings.id}} {{tabs.settings.cssClass}}"
data-tab="{{tabs.settings.id}}"
data-group="{{tabs.settings.group}}">
<ul>
{{#each system.settings}}
<div>
<label><input name="system.settings.{{@key}}" type="checkbox" {{checked this}}> {{@key}}</label>
</div>
{{/each}}
</ul>
</section>

View File

@ -11,7 +11,7 @@
{{#each this}} {{#each this}}
<tr class="equipment" data-id="{{this.id}}" draggable="true"> <tr class="equipment" data-item-id="{{this.id}}" draggable="true">
<td class="icon"><img alt="" src="{{this.icon}}" width="16" height="16"></td> <td class="icon"><img alt="" src="{{this.icon}}" width="16" height="16"></td>
<td class="name">{{this.name}}</td> <td class="name">{{this.name}}</td>
<td class="quantity">{{this.quantity}}</td> <td class="quantity">{{this.quantity}}</td>