fix(migration): ReglesOptionnelles + DialogEncaissementTables -> ApplicationV2

V1 FormApplication déprécié depuis Foundry v13. Migration vers
HandlebarsApplicationMixin(ApplicationV2) :
- DEFAULT_OPTIONS statique remplace defaultOptions getter
- _prepareContext() async remplace getData()
- _onRender() avec DOM natif remplace activateListeners(html)
- PARTS remplace template
- form: {} sub-object remplace closeOnSubmit/submitOnChange plats
- Templates sans <form> wrapper (V2 l'injecte via tag:'form')
This commit is contained in:
fabres
2026-07-22 00:29:56 +02:00
parent afabba430a
commit 348536556a
4 changed files with 111 additions and 116 deletions
+15 -16
View File
@@ -1,3 +1,5 @@
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
const TABLE_MORTEL_DISPLAY = [
{ jet: "≤ 0", type: "—", endurance: "0", vie: "0" },
{ jet: "01-04", type: "Contusion / éraflure", endurance: "-1", vie: "—" },
@@ -29,27 +31,24 @@ const TABLE_NONMORTEL_DISPLAY = [
{ jet: "20+", type: "Blessure légère", endurance: "End. à 0", vie: "-1" },
]
export class DialogEncaissementTables extends FormApplication {
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "dialog-encaissement-tables",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/dialog-encaissement-tables.hbs",
height: 600,
width: 500,
minimizable: false,
closeOnSubmit: true,
title: "Tables d'encaissement alternatives"
}, { inplace: false })
export class DialogEncaissementTables extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
tag: "form",
id: "dialog-encaissement-tables",
classes: ["dialog-encaissement-tables"],
form: { submitOnChange: false, closeOnSubmit: true },
position: { width: 500, height: 600 },
window: { title: "Tables d'encaissement alternatives", icon: "fa-solid fa-table" }
}
getData() {
static PARTS = {
form: { template: "systems/foundryvtt-reve-de-dragon/templates/settings/dialog-encaissement-tables.hbs" }
}
async _prepareContext() {
return {
mortel: TABLE_MORTEL_DISPLAY,
nonmortel: TABLE_NONMORTEL_DISPLAY,
}
}
async _updateObject(event, formData) {
this.close()
}
}
+35 -35
View File
@@ -2,6 +2,8 @@ import { SYSTEM_RDD } from "../constants.js";
import { Misc } from "../misc.js";
import { DialogEncaissementTables } from "./dialog-encaissement-tables.js";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
const listeReglesOptionnelles = [
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
@@ -52,7 +54,7 @@ const listeReglesOptionnelles = [
const uniquementJoueur = listeReglesOptionnelles.filter(it => it.uniquementJoueur).map(it=>it.name);
export class ReglesOptionnelles extends FormApplication {
export class ReglesOptionnelles extends HandlebarsApplicationMixin(ApplicationV2) {
static initSettings() {
for (const regle of listeReglesOptionnelles) {
const name = regle.name;
@@ -69,38 +71,35 @@ export class ReglesOptionnelles extends FormApplication {
});
}
constructor(...args) {
super(...args);
static DEFAULT_OPTIONS = {
tag: "form",
id: "regles-optionnelles",
classes: ["regles-optionnelles"],
form: { submitOnChange: false, closeOnSubmit: true },
position: { width: 550, height: 650 },
window: { title: "Règles optionnelles", icon: "fa-solid fa-bars" }
}
static PARTS = {
form: { template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.hbs" }
}
static _getIdRegle(name) {
return `rdd-option-${name}`;
}
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "regles-optionnelles",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.hbs",
height: 650,
width: 550,
minimizable: false,
closeOnSubmit: true,
title: "Règles optionnelles"
}, { inplace: false })
}
getData() {
let formData = super.getData();
async _prepareContext() {
const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
it = foundry.utils.duplicate(it);
it.id = ReglesOptionnelles._getIdRegle(it.name);
it.active = ReglesOptionnelles.isSet(it.name);
return it;
});
formData.regles = regles;
formData.groups = Misc.classify(regles, it => it.group);
formData.isGM = game.user.isGM;
return formData;
return {
regles,
groups: Misc.classify(regles, it => it.group),
isGM: game.user.isGM,
}
}
static isUsing(name) {
@@ -118,20 +117,21 @@ export class ReglesOptionnelles extends FormApplication {
return game.settings.set(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name), value ? true: false);
}
activateListeners(html) {
$(html).find(".select-option").click((event) => {
if (event.currentTarget.attributes.name) {
let id = event.currentTarget.attributes.name.value;
let isChecked = event.currentTarget.checked;
game.settings.set(SYSTEM_RDD, id, isChecked);
}
async _onRender(context, options) {
this.element.querySelectorAll(".select-option").forEach(el => {
el.addEventListener("click", async event => {
const id = event.currentTarget.getAttribute("name");
if (id) {
const isChecked = event.currentTarget.checked;
await game.settings.set(SYSTEM_RDD, id, isChecked);
}
});
});
$(html).find(".btn-voir-tables-encaissement").click((event) => {
new DialogEncaissementTables().render(true);
});
}
async _updateObject(event, formData) {
this.close();
const btn = this.element.querySelector(".btn-voir-tables-encaissement");
if (btn) {
btn.addEventListener("click", () => {
new DialogEncaissementTables().render(true);
});
}
}
}
@@ -1,47 +1,45 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
<style>
.encaissement-tables { display: flex; flex-direction: column; gap: 1.5em; }
.encaissement-tables table { width: 100%; border-collapse: collapse; }
.encaissement-tables th, .encaissement-tables td { padding: 4px 8px; border: 1px solid #7a7971; text-align: center; }
.encaissement-tables th { background: rgba(0,0,0,0.1); font-weight: bold; }
.encaissement-tables .type-cell { text-align: left; }
</style>
<div class="encaissement-tables">
<section>
<h2>Table mortelle</h2>
<table>
<thead>
<tr><th>Jet</th><th>Type de blessure</th><th>Endurance</th><th>Vie</th></tr>
</thead>
<tbody>
{{#each mortel}}
<tr>
<td>{{this.jet}}</td>
<td class="type-cell">{{this.type}}</td>
<td>{{this.endurance}}</td>
<td>{{this.vie}}</td>
</tr>
{{/each}}
</tbody>
</table>
</section>
<section>
<h2>Table non-mortelle</h2>
<table>
<thead>
<tr><th>Jet</th><th>Type de blessure</th><th>Endurance</th><th>Vie</th></tr>
</thead>
<tbody>
{{#each nonmortel}}
<tr>
<td>{{this.jet}}</td>
<td class="type-cell">{{this.type}}</td>
<td>{{this.endurance}}</td>
<td>{{this.vie}}</td>
</tr>
{{/each}}
</tbody>
</table>
</section>
</div>
</form>
<style>
.encaissement-tables { display: flex; flex-direction: column; gap: 1.5em; }
.encaissement-tables table { width: 100%; border-collapse: collapse; }
.encaissement-tables th, .encaissement-tables td { padding: 4px 8px; border: 1px solid #7a7971; text-align: center; }
.encaissement-tables th { background: rgba(0,0,0,0.1); font-weight: bold; }
.encaissement-tables .type-cell { text-align: left; }
</style>
<div class="encaissement-tables">
<section>
<h2>Table mortelle</h2>
<table>
<thead>
<tr><th>Jet</th><th>Type de blessure</th><th>Endurance</th><th>Vie</th></tr>
</thead>
<tbody>
{{#each mortel}}
<tr>
<td>{{this.jet}}</td>
<td class="type-cell">{{this.type}}</td>
<td>{{this.endurance}}</td>
<td>{{this.vie}}</td>
</tr>
{{/each}}
</tbody>
</table>
</section>
<section>
<h2>Table non-mortelle</h2>
<table>
<thead>
<tr><th>Jet</th><th>Type de blessure</th><th>Endurance</th><th>Vie</th></tr>
</thead>
<tbody>
{{#each nonmortel}}
<tr>
<td>{{this.jet}}</td>
<td class="type-cell">{{this.type}}</td>
<td>{{this.endurance}}</td>
<td>{{this.vie}}</td>
</tr>
{{/each}}
</tbody>
</table>
</section>
</div>
+16 -18
View File
@@ -1,19 +1,17 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
{{#each groups as |group key|}}
<h3>{{key}}</h3>
<ul>
{{#each group as |regle r|}}
<li>
<input class="select-option" type="checkbox" name="{{regle.id}}" {{#if regle.active}}checked{{/if}}/>
<label>{{regle.descr}}</label>
</li>
{{/each}}
</ul>
{{#each groups as |group key|}}
<h3>{{key}}</h3>
<ul>
{{#each group as |regle r|}}
<li>
<input class="select-option" type="checkbox" name="{{regle.id}}" {{#if regle.active}}checked{{/if}}/>
<label>{{regle.descr}}</label>
</li>
{{/each}}
{{#if isGM}}
<hr>
<button type="button" class="btn-voir-tables-encaissement" style="width:100%">
<i class="fas fa-table"></i> Voir les tables d'encaissement
</button>
{{/if}}
</form>
</ul>
{{/each}}
{{#if isGM}}
<hr>
<button type="button" class="btn-voir-tables-encaissement" style="width:100%">
<i class="fas fa-table"></i> Voir les tables d'encaissement
</button>
{{/if}}