From 96f5b177858708cc6d3ab9348d218d1fb71dc5da Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Fri, 22 Mar 2024 23:35:04 -0600 Subject: [PATCH] Implement a button to create items of a specific subtype in the player inventory (closes #120) --- langs/en-ca.2.json | 3 +- module/documents/Actor/GenericActor.mjs | 1 + module/helpers/index.mjs | 4 +- module/sheets/Actors/PC/PlayerSheetV2.mjs | 1 + module/sheets/GenericActorSheet.mjs | 5 +- module/utils/localizer.mjs | 8 ++- .../actor/char-sheet/v2/pages/inventory.scss | 50 ++++++++++++++----- .../actor/char-sheet/v2/themes/dark.scss | 3 ++ .../v2/partials/inventory/item-list.v2.pc.hbs | 19 ++++++- 9 files changed, 73 insertions(+), 21 deletions(-) diff --git a/langs/en-ca.2.json b/langs/en-ca.2.json index 3253116..460fbaf 100644 --- a/langs/en-ca.2.json +++ b/langs/en-ca.2.json @@ -49,7 +49,8 @@ "v2": { "stat-not-chosen": "Select a dice to see the {name} skills", "skill-roll-locked": "@dotdungeon.trainingLevel.locked", - "toggle-item-information": "Toggle the item's extra information visibility" + "toggle-item-information": "Toggle the item's extra information visibility", + "create-item": "Create @TYPES.Item.{type}" } }, "item": { diff --git a/module/documents/Actor/GenericActor.mjs b/module/documents/Actor/GenericActor.mjs index 64dc8b9..d52b185 100644 --- a/module/documents/Actor/GenericActor.mjs +++ b/module/documents/Actor/GenericActor.mjs @@ -1,6 +1,7 @@ export class DotDungeonActor extends Actor { async createEmbeddedItem(defaults, opts = {}) { let items = await this.createEmbeddedDocuments(`Item`, defaults); + if (!Array.isArray(items)) items = items ? [items] : []; if (items.length == 0) { throw new Error(`Failed to create any items`); }; diff --git a/module/helpers/index.mjs b/module/helpers/index.mjs index b3ad070..89c936e 100644 --- a/module/helpers/index.mjs +++ b/module/helpers/index.mjs @@ -3,7 +3,7 @@ import { createArray } from "./createArray.mjs"; import { detailsExpanded } from "./detailsExpanded.mjs"; import { objectValue } from "./objectValue.mjs"; import { toFriendlyDuration } from "./toFriendlyDuration.mjs"; -import { localizer } from "../utils/localizer.mjs"; +import { handlebarsLocalizer } from "../utils/localizer.mjs"; import { options } from "./options.mjs"; export default { @@ -14,7 +14,7 @@ export default { "dd-toFriendlyDuration": toFriendlyDuration, "dd-objectValue": objectValue, "dd-expanded": detailsExpanded, - "dd-i18n": localizer, + "dd-i18n": handlebarsLocalizer, "dd-options": options, // Simple helpers diff --git a/module/sheets/Actors/PC/PlayerSheetV2.mjs b/module/sheets/Actors/PC/PlayerSheetV2.mjs index 05de19e..64ce264 100644 --- a/module/sheets/Actors/PC/PlayerSheetV2.mjs +++ b/module/sheets/Actors/PC/PlayerSheetV2.mjs @@ -136,6 +136,7 @@ export class PlayerSheetv2 extends GenericActorSheet { filters[type] = { label: localizer(`TYPES.Item.${type}`), active: !this._itemTypesHidden.has(type), + createLabel: localizer(`dotdungeon.sheet.actor.v2.create-item`, {type}), }; }; return filters; diff --git a/module/sheets/GenericActorSheet.mjs b/module/sheets/GenericActorSheet.mjs index 9436760..6064f77 100644 --- a/module/sheets/GenericActorSheet.mjs +++ b/module/sheets/GenericActorSheet.mjs @@ -1,3 +1,4 @@ +import { localizer } from "../utils/localizer.mjs"; import DOTDUNGEON from "../config.mjs"; export class GenericActorSheet extends ActorSheet { @@ -127,11 +128,11 @@ export class GenericActorSheet extends ActorSheet { async genericEmbeddedCreate($event) { const data = $event.currentTarget.dataset; if (!this[`createCustom${data.embeddedCreate}`]) { - this.createEmbeddedItem({ + this.actor.createEmbeddedItem({ type: data.embeddedCreate, name: localizer( `dotdungeon.default.name`, - { document: `Actor`, type: data.embeddedCreate } + { document: `Item`, type: data.embeddedCreate } ), }); } else { diff --git a/module/utils/localizer.mjs b/module/utils/localizer.mjs index fc73b76..550c1cb 100644 --- a/module/utils/localizer.mjs +++ b/module/utils/localizer.mjs @@ -1,8 +1,14 @@ import { localizerConfig } from "../config.mjs"; -export function localizer(key, args = {}, depth = 0) { +export function handlebarsLocalizer(key, ...args) { + let data = args[0] + if (args.length === 1) data = args[0].hash; if (key instanceof Handlebars.SafeString) key = key.toString(); + const localized = localizer(key, data); + return localized; +}; +export function localizer(key, args = {}, depth = 0) { /** @type {string} */ let localized = game.i18n.format(key, args); const subkeys = localized.matchAll(localizerConfig.subKeyPattern); diff --git a/styles/sheets/actor/char-sheet/v2/pages/inventory.scss b/styles/sheets/actor/char-sheet/v2/pages/inventory.scss index c753e57..ae65e1b 100644 --- a/styles/sheets/actor/char-sheet/v2/pages/inventory.scss +++ b/styles/sheets/actor/char-sheet/v2/pages/inventory.scss @@ -27,6 +27,40 @@ } } + .item-group { + &__header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center + } + + &__create-item { + @include material.elevate(2); + color: var(--inventory-create-item-font-color); + &:hover { + @include material.elevate(4); + } + &:focus-visible, &:active { + @include material.elevate(8); + } + } + + &__list { + &--material { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + } + + &--untyped { + display: flex; + gap: 8px; + flex-direction: column; + } + } + } + .panel { padding: 8px; border-radius: 4px; @@ -54,7 +88,7 @@ background: hsl( from currentColor / 50% ); // probably gonna need color-mix } - &:focus-visible { + &:focus-visible, &:active { border-width: 2px; border-color: currentColor; background: var(--elevation-8dp-bg); @@ -94,18 +128,6 @@ } } - .material-list { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; - } - - .untyped-list { - display: flex; - gap: 8px; - flex-direction: column; - } - .material { @include material.elevate(1); padding: 8px; @@ -174,6 +196,7 @@ display: flex; gap: 8px; align-items: center; + justify-content: space-between; &:hover { cursor: pointer; @@ -188,6 +211,7 @@ } &__name { flex-grow: 1; + cursor: inherit; font-family: var(--inventory-item-name-font); font-size: var(--inventory-item-name-font-size); } diff --git a/styles/sheets/actor/char-sheet/v2/themes/dark.scss b/styles/sheets/actor/char-sheet/v2/themes/dark.scss index 38c3b5f..c921fbc 100644 --- a/styles/sheets/actor/char-sheet/v2/themes/dark.scss +++ b/styles/sheets/actor/char-sheet/v2/themes/dark.scss @@ -48,6 +48,9 @@ $body-font: sans-serif; --skill-training-select-text-color: #{$on-surface}; --skill-roll-button-text-color: #{$on-surface}; + /* General variables for inventory tab */ + --inventory-create-item-font-color: white; + /* Common Inventory Item Variables */ --inventory-item-name-font: #{$body-font}; --inventory-item-name-font-size: 0.875rem; diff --git a/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs index 5096c8e..b3905eb 100644 --- a/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs +++ b/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs @@ -7,9 +7,24 @@ {{#each computed.itemFilters as | filter |}} {{#if filter.active}}
-

{{filter.label}}

+
+

{{filter.label}}

+ +

-
+
{{#each (lookup @root.items @key) as | item |}} {{> (concat "dotdungeon.pc.v2." @../key) @root item=item}} {{else}}