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 {ActorSheetV2} = foundry.applications.sheets
const {ContextMenu} = foundry.applications.ux
export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
@ -8,17 +9,22 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
position: {width: 520, height: 480},
classes: ['dsa41', 'sheet', 'actor', 'group'],
tag: 'form',
dragDrop: [{
dropSelector: '.tab.inventory.active'
}],
form: {
submitOnChange: true,
closeOnSubmit: false,
handler: GroupSheet.#onSubmitForm
},
window: {
resizable: true,
},
actions: {
roll: GroupSheet.#dieRoll,
editImage: ActorSheetV2.DEFAULT_OPTIONS.actions.editImage,
openEmbeddedDocument: GroupSheet.#openEmbeddedDocument,
openActorDocument: GroupSheet.#openActorDocument,
removeFromParty: GroupSheet.#removeFromParty,
}
}
@ -27,7 +33,6 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
tabs: [
{id: 'members', group: 'sheet', label: 'Gruppenmitglieder'},
{id: 'inventory', group: 'sheet', label: 'Gruppeninventar'},
// settings is only added on context
],
initial: 'members'
}
@ -44,51 +49,45 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
inventory: {
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") {
const uuid = await foundry.utils.parseUuid(data.uuid);
const character = await (game.actors.get(uuid.id))
/**
* Handle form submission
* @this {AdvantageSheet}
* @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 (group.system.characters.includes(character._id)) {
ui.notifications.warn(`${character.name} befindet sich bereits in der Heldengruppe ${group.name}`)
return false;
if (formData.object.name) {
await (game.folders.get(this.document.system.groupId)).update({name: formData.object.name})
}
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)
}
// update group
let settings = {...group.system.settings}
character.items.filter((i) => i.type === "Advantage").forEach((advantage) => {
if (!settings[sheet.#stringToKeyFieldName(advantage.name)]) {
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;
}
d.callbacks = {
dragstart: this._onDragStart.bind(this),
dragover: this._onDragOver.bind(this),
drop: this._onDrop.bind(this)
}
return new DragDrop(d)
})
}
#stringToKeyFieldName(s) {
@ -110,43 +109,47 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
console.log(evt)
}
static async #removeFromParty(evt) {
const dataset = evt.srcElement.dataset;
const group = this.document;
const charactersWithoutMember = group.system.characters.filter(id => id !== dataset.id)
group.update({
system: {
characters: charactersWithoutMember
}
})
async #onUpdateCharacterSettings(data) {
if (data.type === "character") {
// 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})
}
}
/**
* Handle form submission
* @this {AdvantageSheet}
* @param {SubmitEvent} event
* @param {HTMLFormElement} form
* @param {FormDataExtended} formData
*/
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
_getTabsConfig(group) {
const tabs = foundry.utils.deepClone(super._getTabsConfig(group))
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 */
async _prepareContext(options) {
const context = await super._prepareContext(options)
// Use a safe clone of the actor data for further operations.
const groupData = context.document;
// Add the actor's data to context.data for easier access, as well as flags.
context.system = groupData.system;
context.flags = groupData.flags;
const groupData = context.document
context.system = groupData.system
context.flags = groupData.flags
context.characters = []
context.isGM = game.user.isGM;
context.isGM = game.user.isGM
context.name = groupData.name
context.img = groupData.img
context.fields = [];
@ -187,15 +190,8 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
if (!context.fields[n]) {
context.fields[n] = {}
}
const eigenschaften = Object.values(skill.system.probe);
context.fields[n][character.name] = {
taw: skill.system.taw,
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,
taw: skill.system.taw ?? "0",
name: skill.name,
actor: character._id,
}
@ -244,7 +240,7 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
}
_onRender(context, options) {
new ContextMenu(this.element, ".equipment", [
/*ContextMenu.implementation.create(this, this.element, ".equipment", [
{
name: "Aus dem Gruppeninventar entfernen",
icon: '<i class="fa-solid fa-trash"></i>',
@ -255,7 +251,42 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
}
], {
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 {
.window-content {
display: unset;
position: relative;
}
.application.sheet.dsa41.actor.group {
.sheet-header {
.sheet-name {
font-size: 24pt;
height: 48px;
}
}
display: grid;
grid-template-columns: 32px 1fr;
gap: 8px;
.sheet-tabs {
position: absolute;
left: 0;
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;
img {
height: 32px;
width: 32px;
}
}

View File

@ -1,6 +1,8 @@
<div>
<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}}"/>
</header>

View File

@ -59,18 +59,11 @@
{{#if (eq this "-")}}
{{else}}
{{#if this.taw}}
{{#if (lt this.taw 0)}}
<div class="rollable" data-actor-id="{{this.actor}}"
data-taw="{{this.taw}}"
data-name="{{this.name}}"
data-eigenschaft1="{{this.eigenschaft1}}"
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}})
data-name="{{this.name}}">
{{this.taw}}
</div>
{{else}}
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}}
<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="name">{{this.name}}</td>
<td class="quantity">{{this.quantity}}</td>