feat: enable sorting items by clicking on item list headers

This commit is contained in:
Johannes Loher 2021-11-06 01:41:31 +01:00
parent c33bd5fb67
commit 298bbf054b
9 changed files with 150 additions and 40 deletions

View file

@ -9,6 +9,7 @@ import { DS4ActiveEffect } from "../../active-effect";
import { ModifiableDataBaseTotal } from "../../common/common-data";
import { DS4 } from "../../config";
import { getCanvas, getGame } from "../../helpers";
import type { DS4Item } from "../../item/item";
import { DS4Settings, getDS4Settings } from "../../settings";
import notifications from "../../ui/notifications";
import { enforce } from "../../utils";
@ -108,6 +109,8 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
html.find(".rollable-item").on("click", this.onRollItem.bind(this));
html.find(".rollable-check").on("click", this.onRollCheck.bind(this));
html.find(".sort-items").on("click", this.onSortItems.bind(this));
}
/**
@ -257,9 +260,9 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
enforce(element instanceof HTMLInputElement);
if (element.disabled) return;
const effectElement = element.closest(embeddedDocumentListEntryProperties[documentName].selector);
enforce(effectElement instanceof HTMLElement);
const id = effectElement.dataset[embeddedDocumentListEntryProperties[documentName].idDataAttribute];
const documentElement = element.closest(embeddedDocumentListEntryProperties[documentName].selector);
enforce(documentElement instanceof HTMLElement);
const id = documentElement.dataset[embeddedDocumentListEntryProperties[documentName].idDataAttribute];
const property = element.dataset["property"];
enforce(property !== undefined, TypeError("HTML element does not provide 'data-property' attribute"));
@ -344,6 +347,49 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
event.dataTransfer?.setData("text/plain", JSON.stringify(dragData));
}
/**
* Sort items according to the item list header that has been clicked.
* @param event - The originating click event
*/
protected onSortItems(event: JQuery.ClickEvent<unknown, unknown, HTMLElement>): void {
event.preventDefault();
const target = event.currentTarget;
const type = target.parentElement?.dataset["type"];
enforce(type !== undefined, `Could not find property 'type' in the dataset of the parent of ${target}`);
const dataPath = target.dataset["dataPath"];
enforce(dataPath !== undefined, `Could not find property 'dataPath' in the dataset of ${target}`);
const items = this.actor.items.filter((item) => item.type === type);
items.sort((a, b) => a.data.sort - b.data.sort);
const sortFunction =
(invert: boolean) =>
(a: DS4Item, b: DS4Item): number => {
const propertyA = getProperty(a.data, dataPath);
const propertyB = getProperty(b.data, dataPath);
if (typeof propertyA === "string" || typeof propertyB === "string") {
return invert
? (propertyB ?? "").localeCompare(propertyA ?? "")
: (propertyA ?? "").localeCompare(propertyB ?? "");
} else {
return invert ? propertyB - propertyA : propertyA - propertyB;
}
};
const sortedItems = [...items].sort(sortFunction(false));
const wasSortedAlready = !sortedItems.find((item, index) => item !== items[index]);
if (wasSortedAlready) {
sortedItems.sort(sortFunction(true));
}
const updates = sortedItems.map((item, i) => ({
_id: item.id,
sort: (i + 1) * CONST.SORT_INTEGER_DENSITY,
}));
this.actor.updateEmbeddedDocuments("Item", updates);
}
/** @override */
protected async _onDropItem(event: DragEvent, data: ActorSheet.DropData.Item): Promise<unknown> {
const item = await Item.fromDropData(data);
@ -362,7 +408,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
}
}
interface DS4ActorSheetData extends ActorSheet.Data<ActorSheet.Options> {
interface DS4ActorSheetData extends ActorSheet.Data {
config: typeof DS4;
itemsByType: Record<string, foundry.data.ItemData[]>;
enrichedEffects: EnrichedActiveEffectDataSource[];