Implements Filtering

pull/65/head
macniel 2025-11-12 17:05:45 +01:00
parent c2b8a7d895
commit 29d25f8afe
8 changed files with 176 additions and 16 deletions

View File

@ -45,5 +45,8 @@
"regularFormula": "Schadensformel:",
"bonusDamage": "Zusätzlicher Schaden:",
"buttonText": "Würfeln"
},
"ITEM_BROWSER": {
"progress": "{current}/{max}: Importiere von {compendium}"
}
}

View File

@ -10,15 +10,18 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2)
static DEFAULT_OPTIONS = {
classes: ['dsa41', 'dialog', 'item-browser'],
tag: "form",
form: {
submitOnChange: true,
closeOnSubmit: false,
handler: ItemBrowserDialog.#onSubmitForm
},
position: {
width: 640,
height: 480
},
window: {
resizable: true,
},
actions: {
buy: ItemBrowserDialog.#buy
title: "Gegenstände Browser"
}
}
@ -39,16 +42,29 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2)
* @private
*/
_items = []
filter_price_lower = 0
filter_price_upper = 0
filter_weight_lower = 0
filter_weight_upper = 0
filter_name = ""
filter_category = ""
constructor(actor) {
super();
this._actor = actor
// load compendium data
this._items = []
}
static async #buy(event, target) {
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
this.filter_price_lower = formData.object.filter_price_lower
this.filter_price_upper = formData.object.filter_price_upper
this.filter_weight_lower = formData.object.filter_weight_lower
this.filter_weight_upper = formData.object.filter_weight_upper
this.filter_name = formData.object.filter_name
this.filter_category = formData.object.filter_category
this.render({parts: ["form"]})
}
_canDragDrop(event, options) {
@ -83,10 +99,51 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2)
async _prepareContext(options) {
const context = await super._prepareContext(options)
context.categories = {
"": "",
"Gegenstand": "Gegenstand",
"Nahkampfwaffe": "Nahkampfwaffe",
"Fernkampfwaffe": "Fernkampfwaffe",
"Munition": "Munition",
"Währung": "Währung"
}
context.filterName = this.filter_name
context.filterCategory = this.filter_category
context.filter_price_lower = this.filter_price_lower ?? this._minPrice
context.filter_price_upper = this.filter_price_upper ?? this._maxPrice
context.filter_weight_lower = this.filter_weight_lower ?? this._minWeight
context.filter_weight_upper = this.filter_weight_upper ?? this._maxWeight
context.price_lower = this._minPrice
context.price_upper = this._maxPrice
context.weight_lower = this._minWeight
context.weight_upper = this._maxWeight
context.items = this._items
?.filter(p => p.name.toLowerCase().indexOf(context.filterName.toLowerCase()) !== -1 || context.filterName === "")
?.filter(p => p.category.indexOf(context.filterCategory) !== -1 || context.filterCategory === "")
?.filter(p => Number(context.filter_price_lower) <= p.price && p.price <= Number(context.filter_price_upper))
?.filter(p => Number(context.filter_weight_lower) <= p.weight && p.weight <= Number(context.filter_weight_upper))
return context
}
#updateProgress(compendiumName, current, max) {
if (compendiumName && current && max) {
this.element.querySelector('.progress').style.display = 'block';
this.element.querySelector('.progress .fill').style.width = (current / max * 100) + "%";
this.element.querySelector('.progress .text').textContent = game.i18n.format("ITEM_BROWSER.progress", {
compendium: compendiumName,
current: current,
max: max
})
} else {
this.element.querySelector('.progress').style.display = 'none';
}
}
async _onRender(context, options) {
if (this._items.length === 0) {
@ -97,8 +154,13 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2)
game.packs.get('DSA_4-1.Items')
]
let totalEntries = compendia.reduce((p, c) => p + c.index.size, 0)
let parsedEntries = 0
let currentCompendiumName = ""
for (const c of compendia) {
const it = await c.getDocuments()
currentCompendiumName = c.metadata.label
it.forEach((item) => {
const uuid = item.uuid
const e = new Equipment(item)
@ -111,13 +173,23 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2)
weight: e.system.weight,
category: e.system.category.join(", ")
})
console.log("importing ", item.name)
parsedEntries += 1
this.#updateProgress(currentCompendiumName, parsedEntries, totalEntries)
})
console.log("done importing from ", c)
}
this._minPrice = Math.min(...this._items.map(item => item.price))
this._maxPrice = Math.max(...this._items.map(item => item.price))
this._minWeight = Math.min(...this._items.map(item => item.weight))
this._maxWeight = Math.max(...this._items.map(item => item.weight))
this.#updateProgress()
this.render({parts: ["form"]})
}
new foundry.applications.ux.DragDrop.implementation({
dropSelector: ".window-content",
dragSelector: ".item",

View File

@ -4,7 +4,7 @@ import {GroupSheet} from "../sheets/groupSheet.mjs";
import {SkillSheet} from "../sheets/skillSheet.mjs";
import {SpellSheet} from "../sheets/spellSheet.mjs";
import {AdvantageSheet} from "../sheets/advantageSheet.mjs";
import {EquipmentSheet} from "../sheets/equipmentSheet.mjs";
import EquipmentSheet from "../sheets/equipmentSheet.mjs";
import {LiturgySheet} from "../sheets/liturgySheet.mjs";
import {SpecialAbilitySheet} from "../sheets/specialAbilitySheet.mjs";
import {ActiveEffectSheet} from "../sheets/activeEffectSheet.mjs";

View File

@ -1,6 +1,6 @@
const {DocumentSheetV2, HandlebarsApplicationMixin} = foundry.applications.api
export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
/** @inheritDoc */
static DEFAULT_OPTIONS = {
@ -311,3 +311,5 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
}
}
export default EquipmentSheet

View File

@ -2,6 +2,46 @@
.window-content [data-application-part] {
position: relative;
.progress {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 24px;
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.3);
.fill {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: url('/systems/DSA_4-1/assets/gradient.png');
background-size: 24px 100%;
background-color: rgba(64, 192, 192, 0.8);
background-blend-mode: multiply;
}
.text {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
height: 24px;
line-height: 24px;
vertical-align: middle;
font-weight: bold;
margin-left: 8px;
text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3);
color: white;
}
}
display: grid;
grid-template-columns: 240px 1fr;
height: 100%;

View File

@ -56,11 +56,29 @@
}
}
h3.inventory-header {
.inventory-header {
line-height: 32px;
grid-area: inventory-header;
margin: 0;
padding: 0;
display: flex;
h3 {
flex: 1;
line-height: 32px;
}
.buttons {
flex: 0;
display: flex;
gap: 4px;
button {
}
}
}

View File

@ -15,9 +15,13 @@
</div>
<h3 class="inventory-header">Inventar </h3>
<div class="inventory-header">
<h3>Inventar</h3>
<div class="buttons">
<button data-action="newItem"><i class="fa-solid fa-sack" data-tooltip="Neuer Gegenstand"></i></button>
<button data-action="openItemBrowser"><i class="fa-solid fa-store" data-tooltip="Einkaufen"></i></button>
</div>
</div>
<div class="inventory">
{{> "systems/DSA_4-1/templates/ui/partial-equipment-button.hbs" equipments}}
</div>

View File

@ -1,23 +1,44 @@
<div>
<div class="progress" style="display: none">
<span class="fill"></span>
<span class="text"></span>
</div>
<aside>
<fieldset>
<legend>Name</legend>
<input name="filter_name" type="text">
<input name="filter_name" type="text" value="{{filterName}}">
</fieldset>
<fieldset>
<legend>Kategorie</legend>
<select name="filter_category">
{{selectOptions categories selected=filterCategory inverted=true}}
</select>
</fieldset>
<fieldset>
<legend>Preis</legend>
<input name="filter_price" type="range" min="{{minimumPrice}}" max="{{maximumPrice}}"/>
<label>
<span>von {{currency filter_price_lower}}</span>
<input name="filter_price_lower" type="range" min="{{price_lower}}" value="{{filter_price_lower}}"
max="{{price_upper}}" step="0.01"/></label>
<label>
<span>bis {{currency filter_price_upper}}</span>
<input name="filter_price_upper" type="range" min="{{price_lower}}" value="{{filter_price_upper}}"
max="{{price_upper}}" step="0.01"/>
</label>
</fieldset>
<fieldset>
<legend>Gewicht</legend>
<input name="filter_weight" type="range" min="{{minimumWeight}}" max="{{maximumWeight}}"/>
<label>von {{weight filter_weight_lower}}
<input name="filter_weight_lower" type="range" min="{{weight_lower}}" value="{{filter_weight_lower}}"
max="{{weight_upper}}" step="0.025"/>
</label>
<label>bis {{weight filter_weight_upper}}
<input name="filter_weight_upper" type="range" min="{{weight_lower}}" value="{{filter_weight_upper}}"
max="{{weight_upper}}" step="0.025"/>
</label>
</fieldset>
</aside>