migrates active effect to DocumentV2

feature/applicationv2
macniel 2025-10-15 21:02:56 +02:00
parent 7ea6b4a2e0
commit 626474178d
10 changed files with 323 additions and 282 deletions

View File

@ -1,44 +1,65 @@
export class ActiveEffectSheet extends foundry.appv1.sheets.ItemSheet { const {DocumentSheetV2, HandlebarsApplicationMixin} = foundry.applications.api
/**@override */
static get defaultOptions() { export class ActiveEffectSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ['dsa41', 'sheet', 'activeeffect'], /** @inheritDoc */
width: 520, static DEFAULT_OPTIONS = {
height: 480 position: {width: 520, height: 480},
}); classes: ['dsa41', 'sheet', 'item', 'activeeffect'],
tag: 'form',
form: {
submitOnChange: true,
closeOnSubmit: false,
handler: ActiveEffectSheet.#onSubmitForm
},
actions: {
openEffect: ActiveEffectSheet.#openEffect,
editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage,
}
}
/** @inheritDoc */
static PARTS = {
form: {
template: `systems/DSA_4-1/templates/item/activeeffect/main-sheet.hbs`
},
}
static async #openEffect(evt) {
evt.preventDefault()
const {id} = evt.srcElement.dataset
const effect = await this.document.effects.get(id)
effect.sheet.render(true)
}
/**
* Handle form submission
* @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
} }
/** @override */ /** @override */
get template() { async _prepareContext(options) {
return `systems/DSA_4-1/templates/item/item-activeeffect-sheet.hbs`;
}
/** @override */ const context = await super._prepareContext(options)
getData() { context.system = context.document.system
// Retrieve the data structure from the base sheet. You can inspect or log
// the context variable to see the structure, but some key properties for const effects = context.document.getEmbeddedCollection("ActiveEffect").contents
// sheets are the actor object, the data object, whether or not it's
// editable, the items array, and the effects array.
const context = super.getData();
const effects = context.document.getEmbeddedCollection("ActiveEffect").contents;
if (effects.length > 0) { if (effects.length > 0) {
context.effectId = effects[0]._id; context.effectId = effects[0]._id
} }
return context; context.name = context.document.name
context.img = context.document.img
context.notes = context.document.system.notes
return context
} }
}
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
html.on('click', '.editEffects', (evt) => {
const {id} = evt.currentTarget.dataset;
const effect = this.object.effects.get(id);
effect.sheet.render(true);
})
}
}

View File

@ -110,12 +110,12 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
} }
#prepareMetaContext(context) { #prepareMetaContext(context) {
const equipmentData = context.document.system; const equipmentData = context.document.system
context.system = equipmentData; context.system = equipmentData
context.quantity = equipmentData.quantity; context.quantity = equipmentData.quantity
context.description = equipmentData.description; context.description = equipmentData.description
context.name = context.document.name; context.name = context.document.name
context.img = context.document.img; context.img = context.document.img
context.categoryAndOptions = { context.categoryAndOptions = {
options: { options: {
@ -131,8 +131,8 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
} }
#prepareMeleeContext(context) { #prepareMeleeContext(context) {
const equipmentData = context.document.system; const equipmentData = context.document.system
context.system = equipmentData; context.system = equipmentData
context.meleeSkillsAndOptions = { context.meleeSkillsAndOptions = {
options: { options: {
"": "", "": "",
@ -156,7 +156,7 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
} }
#prepareRangedContext(context) { #prepareRangedContext(context) {
const equipmentData = context.document.system; const equipmentData = context.document.system
context.rangedSkillsAndOptions = { context.rangedSkillsAndOptions = {
options: { options: {
"": "", "": "",
@ -187,14 +187,14 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
*/ */
_prepareTabs(tabGroup) { _prepareTabs(tabGroup) {
const currentTabs = super._prepareTabs(tabGroup); const currentTabs = super._prepareTabs(tabGroup)
const category = this.document.system.category const category = this.document.system.category
/** /**
* *
* @type {[{ApplicationTab}]} * @type {[{ApplicationTab}]}
*/ */
let tabs = currentTabs; let tabs = currentTabs
if (category.includes("Nahkampfwaffe")) { if (category.includes("Nahkampfwaffe")) {
tabs.melee = { tabs.melee = {
@ -223,7 +223,7 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
/** @override */ /** @override */
async _prepareContext(options) { async _prepareContext(options) {
const context = await super._prepareContext(options); const context = await super._prepareContext(options)
context.price = context.document.system.price context.price = context.document.system.price
context.weight = context.document.system.weight context.weight = context.document.system.weight
@ -239,12 +239,12 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
*/ */
_onRender(context, options) { _onRender(context, options) {
this.element.querySelector('.array-editor select').addEventListener('change', (evt) => { this.element.querySelector('.array-editor select').addEventListener('change', (evt) => {
const addingValue = evt.currentTarget.value; const addingValue = evt.currentTarget.value
const fieldToTarget = evt.currentTarget.dataset.targetField; const fieldToTarget = evt.currentTarget.dataset.targetField
const newSkills = [...this.document.system[fieldToTarget], addingValue]; const newSkills = [...this.document.system[fieldToTarget], addingValue]
this.document.update({system: {[fieldToTarget]: newSkills}}); this.document.update({system: {[fieldToTarget]: newSkills}})
evt.currentTarget.value = ""; evt.currentTarget.value = ""
}) })
} }

View File

@ -14,6 +14,11 @@
height: 48px; height: 48px;
line-height: 48px; line-height: 48px;
} }
button {
height: 48px;
width: 48px;
}
} }
.meta { .meta {

View File

@ -72,176 +72,180 @@ $deity_colours_tint: (
} }
} }
.tab.liturgies { .dsa41.sheet {
table {
@include coloring('Praios'); .tab.liturgies {
@include coloring('Rondra'); table {
@include coloring('Efferd');
@include coloring('Travia');
@include coloring('Boron');
@include coloring('Hesinde');
@include coloring('Firun');
@include coloring('Tsa');
@include coloring('Phex');
@include coloring('Peraine');
@include coloring('Ingerimm');
@include coloring('Rahja');
tr { @include coloring('Praios');
th.background { @include coloring('Rondra');
@include coloring('Efferd');
@include coloring('Travia');
@include coloring('Boron');
@include coloring('Hesinde');
@include coloring('Firun');
@include coloring('Tsa');
@include coloring('Phex');
@include coloring('Peraine');
@include coloring('Ingerimm');
@include coloring('Rahja');
tr {
th.background {
&::before {
position: absolute;
content: '';
background-image: url("../assets/velvet_strip.png");
background-repeat: repeat-y;
background-size: cover;
width: 86px;
height: 100%;
top: 45px;
left: 12px;
}
&::after { /* for tinting the texture */
content: "";
position: absolute;
width: 86px;
height: 100%;
top: 45px;
left: 12px;
}
}
}
.banner-top {
position: relative;
width: 90px;
img {
position: absolute;
top: 2px;
left: 1px;
width: 90px;
height: 90px;
border: 0;
z-index: 1;
}
&::after {
z-index: 0;
border-width: 0 4px 0 4px;
//background-color: #64b;
border-style: solid;
position: absolute;
content: "";
left: -2px;
top: 45px;
bottom: 0;
width: 94px;
}
&::before { &::before {
position: absolute; position: absolute;
border-radius: 45px;
height: 94px;
width: 94px;
content: ''; content: '';
background-image: url("../assets/velvet_strip.png"); left: -2px;
background-repeat: repeat-y; right: -2px;
background-size: cover; top: 0;
width: 86px; border-width: 4px;
height: 100%; border-style: solid;
z-index: 2;
top: 45px;
left: 12px;
}
&::after { /* for tinting the texture */
content: "";
position: absolute;
width: 86px;
height: 100%;
top: 45px;
left: 12px;
} }
} }
}
.banner-top { .banner-mid {
position: relative; position: relative;
width: 90px;
img {
position: absolute;
top: 2px;
left: 1px;
width: 90px;
height: 90px;
border: 0;
z-index: 1;
}
&::after {
z-index: 0;
border-width: 0 4px 0 4px; border-width: 0 4px 0 4px;
//background-color: #64b; //background-color: #64b;
border-style: solid; border-style: solid;
position: absolute; width: 90px;
content: "";
left: -2px; div {
top: 45px; position: absolute;
bottom: 0; top: 0;
width: 94px; left: 0;
bottom: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
div.rank-label {
position: absolute;
left: 2px;
right: 2px;
top: 0;
bottom: 0;
border-bottom: 2px solid black;
color: gold;
text-shadow: 2px 2px 1px black;
}
}
} }
&::before { .banner-bot {
position: absolute; position: relative;
border-radius: 45px;
height: 94px;
width: 94px;
content: '';
left: -2px;
right: -2px;
top: 0;
border-width: 4px; border-width: 4px;
border-style: solid; border-style: solid;
z-index: 2; width: 90px;
height: 12px;
} }
} }
.banner-mid { .liturgy.rollable {
position: relative; width: 24px;
border-width: 0 4px 0 4px;
//background-color: #64b;
border-style: solid;
width: 90px;
div { svg {
position: absolute; $color: #e4de61;
top: 0; width: 24px;
left: 0; height: 24px;
bottom: 0; top: 1px;
right: 0; z-index: 1;
display: flex; position: relative;
justify-content: center;
align-items: center;
div.rank-label { .border {
position: absolute; fill: #0000;
left: 2px; }
right: 2px;
top: 0; .center {
bottom: 0; fill: $color;
border-bottom: 2px solid black; stroke: colour.$rollable-die-border-color;
color: gold; }
text-shadow: 2px 2px 1px black;
.topleft {
fill: color.adjust($color, $lightness: numbers.$lighter_factor);
stroke: colour.$rollable-die-border-color;
}
.bottomleft {
fill: color.adjust($color, $lightness: numbers.$lightest_factor);
stroke: colour.$rollable-die-border-color;
}
.topright {
fill: color.adjust($color, $lightness: numbers.$darken_factor);
stroke: colour.$rollable-die-border-color;
}
.bottomright, .bottom {
fill: color.adjust($color, $lightness: numbers.$darkest_factor);
stroke: colour.$rollable-die-border-color;
} }
} }
} }
.banner-bot { .clickable:hover {
position: relative; text-shadow: 0 0 10px rgb(255 0 0);
border-width: 4px;
border-style: solid;
width: 90px;
height: 12px;
} }
} }
.liturgy.rollable { }
width: 24px;
svg {
$color: #e4de61;
width: 24px;
height: 24px;
top: 1px;
z-index: 1;
position: relative;
.border {
fill: #0000;
}
.center {
fill: $color;
stroke: colour.$rollable-die-border-color;
}
.topleft {
fill: color.adjust($color, $lightness: numbers.$lighter_factor);
stroke: colour.$rollable-die-border-color;
}
.bottomleft {
fill: color.adjust($color, $lightness: numbers.$lightest_factor);
stroke: colour.$rollable-die-border-color;
}
.topright {
fill: color.adjust($color, $lightness: numbers.$darken_factor);
stroke: colour.$rollable-die-border-color;
}
.bottomright, .bottom {
fill: color.adjust($color, $lightness: numbers.$darkest_factor);
stroke: colour.$rollable-die-border-color;
}
}
}
.clickable:hover {
text-shadow: 0 0 10px rgb(255 0 0);
}
}

View File

@ -2,25 +2,27 @@
@use "./_numbers"; @use "./_numbers";
@use "sass:color"; @use "sass:color";
.player-action { .dsa41.sheet {
.player-action {
display: inline-block; display: inline-block;
width: 120px; width: 120px;
height: 80px; height: 80px;
float: left; float: left;
margin: 0 8px 8px 0; margin: 0 8px 8px 0;
border: 1px solid #333; border: 1px solid #333;
background-color: color.scale(colours.$default-action, $alpha: 20%); background-color: color.scale(colours.$default-action, $alpha: 20%);
color: colours.$default-action-color; color: colours.$default-action-color;
border-radius: 4px; border-radius: 4px;
box-shadow: numbers.$pill-box-inset numbers.$pill-box-inset numbers.$pill-box-blur-radius colours.$pill-box-shadow; box-shadow: numbers.$pill-box-inset numbers.$pill-box-inset numbers.$pill-box-blur-radius colours.$pill-box-shadow;
&.special-ability { &.special-ability {
background-color: color.scale(colours.$special-action, $alpha: 20%); background-color: color.scale(colours.$special-action, $alpha: 20%);
color: colours.$special-action-color; color: colours.$special-action-color;
}
} }
} }

View File

@ -1,3 +1,7 @@
.editor.prosemirror.active, .editor.prosemirror.inactive { .dsa41.sheet {
flex: 1;
} .editor.prosemirror.active, .editor.prosemirror.inactive {
flex: 1;
}
}

View File

@ -1,4 +1,4 @@
.sheet.item.skill { .dsa41.sheet.item.skill {
.meta-details { .meta-details {

View File

@ -44,61 +44,62 @@
} }
}
// Tabs v2 // Tabs v2
.sheet-tabs { .sheet-tabs {
position: relative; position: relative;
display: flow; display: flow;
border-top: unset; border-top: unset;
border-bottom: unset; border-bottom: unset;
margin-bottom: 0; margin-bottom: 0;
a[data-action="tab"] { a[data-action="tab"] {
background-color: colours.$tab-inactive-background-color; background-color: colours.$tab-inactive-background-color;
display: inline-block; display: inline-block;
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;
vertical-align: middle; vertical-align: middle;
padding: 0 16px; padding: 0 16px;
span {
}
&.active {
border-left: numbers.$tab-border-width solid colours.$tab-border-color;
border-top: numbers.$tab-border-width solid colours.$tab-border-color;
border-right: numbers.$tab-border-width solid colours.$tab-border-color;
border-bottom: 0;
top: numbers.$tab-border-width*2;
background: assets.$tab-background;
position: relative;
z-index: 2;
span { span {
} }
&.active {
border-left: numbers.$tab-border-width solid colours.$tab-border-color;
border-top: numbers.$tab-border-width solid colours.$tab-border-color;
border-right: numbers.$tab-border-width solid colours.$tab-border-color;
border-bottom: 0;
top: numbers.$tab-border-width*2;
background: assets.$tab-background;
position: relative;
z-index: 2;
span {
}
}
} }
} }
section.tab {
border: numbers.$tab-border-width solid colours.$tab-border-color;
background: assets.$tab-pane-background;
flex: 1;
& > div {
display: flex;
flex-direction: column;
height: 100%;
gap: 8px;
padding: 8px;
}
}
} }
section.tab {
border: numbers.$tab-border-width solid colours.$tab-border-color;
background: assets.$tab-pane-background;
flex: 1;
& > div {
display: flex;
flex-direction: column;
height: 100%;
gap: 8px;
padding: 8px;
}
}

View File

@ -0,0 +1,24 @@
<div class="active-effect">
<div class="header">
<img class="img" src="{{img}}" data-action="editImage" data-edit="img" alt="{{name}}" title="{{name}}"/>
<input type="text" name="name" value="{{name}}"/>
<button class="editEffects" data-id="{{this.effectId}}" data-action="openEffect">
<i class="fas fa-pencil-alt"></i>
</button>
</div>
<div class="meta">
<label>Spielleiter Hinweise</label>
<prose-mirror
name="system.notes"
button="false"
editable="{{editable}}"
toggled="true"
value="{{system.notes}}">
{{{notes}}}
</prose-mirror>
</div>
</div>

View File

@ -1,20 +0,0 @@
<form class="{{cssClass}} {{item.type}} flexcol" autocomplete="off">
<div class="active-effect">
<div class="header">
<img src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<input type="text" name="actor.name" value="{{item.name}}"/>
<button class="editEffects" data-id="{{this.effectId}}" data-operation="editActiveEffect">
<i class="fas fa-pencil-alt"></i>
</button>
</div>
<div class="meta">
<label>Spielleiter Hinweise</label>
{{editor item.system.notes target="system.notes" button=true owner=owner editable=editable}}
</div>
</div>
</form>