Get the base favourite mechanism working so the items are visible on the skills card
This commit is contained in:
parent
7d39c487dc
commit
c495f45015
14 changed files with 165 additions and 27 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
Oliver Akins:
|
Oliver Akins:
|
||||||
- geist-silhouette.v2.svg : All rights reserved.
|
- geist-silhouette.v2.svg : All rights reserved.
|
||||||
- caster-silhouette.v1.svg : All rights reserved.
|
- caster-silhouette.v1.svg : All rights reserved.
|
||||||
|
- icons/star-empty.svg : Modified from https://thenounproject.com/icon/star-7711815/ by Llisole
|
||||||
|
- icons/star.svg : Modified from https://thenounproject.com/icon/star-7711815/ by Llisole
|
||||||
|
|
||||||
Kýnan Antos (Gritsilk Games):
|
Kýnan Antos (Gritsilk Games):
|
||||||
- hero-silhouette.svg : Licensed to Distribute and Modify within the bounds of the "Foundry-RipCrypt" system.
|
- hero-silhouette.svg : Licensed to Distribute and Modify within the bounds of the "Foundry-RipCrypt" system.
|
||||||
|
|
|
||||||
1
assets/icons/star-empty.svg
Normal file
1
assets/icons/star-empty.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path d="M93.824 44.383 80.058 61.379a6.3 6.3 0 0 0-1.398 4.3l1.144 21.84c.2 3.802-3.578 6.548-7.133 5.18l-20.418-7.84a6.3 6.3 0 0 0-4.52 0L27.317 92.7c-3.551 1.364-7.332-1.382-7.133-5.18l1.145-21.84a6.3 6.3 0 0 0-1.399-4.3L6.163 44.383C3.77 41.426 5.21 36.985 8.886 36l21.125-5.66a6.3 6.3 0 0 0 3.656-2.656L45.577 9.34c2.07-3.192 6.742-3.192 8.816 0l11.91 18.344a6.3 6.3 0 0 0 3.657 2.656L91.085 36c3.675.985 5.128 5.43 2.734 8.387z" style="stroke-width: 8px; stroke: black; fill: transparent;"/></svg>
|
||||||
|
After Width: | Height: | Size: 565 B |
1
assets/icons/star.svg
Normal file
1
assets/icons/star.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path d="M93.824 44.383 80.058 61.379a6.3 6.3 0 0 0-1.398 4.3l1.144 21.84c.2 3.802-3.578 6.548-7.133 5.18l-20.418-7.84a6.3 6.3 0 0 0-4.52 0L27.317 92.7c-3.551 1.364-7.332-1.382-7.133-5.18l1.145-21.84a6.3 6.3 0 0 0-1.399-4.3L6.163 44.383C3.77 41.426 5.21 36.985 8.886 36l21.125-5.66a6.3 6.3 0 0 0 3.656-2.656L45.577 9.34c2.07-3.192 6.742-3.192 8.816 0l11.91 18.344a6.3 6.3 0 0 0 3.657 2.656L91.085 36c3.675.985 5.128 5.43 2.734 8.387z"/></svg>
|
||||||
|
After Width: | Height: | Size: 504 B |
|
|
@ -173,12 +173,17 @@
|
||||||
"rollTarget": "Target",
|
"rollTarget": "Target",
|
||||||
"difficulty": "(DC: {dc})",
|
"difficulty": "(DC: {dc})",
|
||||||
"RichEditor-no-collaborative": "Warning: This editor is not collaborative, that means that if you and someone else are editing it at the same time, you won't see that someone else is making changes until they save, and then your changes will be lost.",
|
"RichEditor-no-collaborative": "Warning: This editor is not collaborative, that means that if you and someone else are editing it at the same time, you won't see that someone else is making changes until they save, and then your changes will be lost.",
|
||||||
"no-ammo": "You don't have any ammo!"
|
"AmmoTracker": {
|
||||||
|
"no-ammo": "You don't have any ammo!",
|
||||||
|
"pin-button": "Pin {name} to your character sheet",
|
||||||
|
"pin-button-tooltip": "Pin {name}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"notifs": {
|
"notifs": {
|
||||||
"error": {
|
"error": {
|
||||||
"cannot-equip": "Cannot equip the {itemType}, see console for more details.",
|
"cannot-equip": "Cannot equip the {itemType}, see console for more details.",
|
||||||
"invalid-delta": "The delta for \"{name}\" is not a number, cannot finish processing the action."
|
"invalid-delta": "The delta for \"{name}\" is not a number, cannot finish processing the action.",
|
||||||
|
"at-favourite-limit": "Cannot favourite more than three items, unfavourite one to make space."
|
||||||
},
|
},
|
||||||
"warn": {
|
"warn": {
|
||||||
"cannot-go-negative": "\"{name}\" is unable to be a negative number."
|
"cannot-go-negative": "\"{name}\" is unable to be a negative number."
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,23 @@ export class HeroSkillsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin
|
||||||
};
|
};
|
||||||
|
|
||||||
static async prepareAmmo(ctx) {
|
static async prepareAmmo(ctx) {
|
||||||
ctx.ammo = 0;
|
let total = 0;
|
||||||
|
ctx.favouriteAmmo = [];
|
||||||
|
|
||||||
|
for (const ammo of ctx.actor.itemTypes.ammo) {
|
||||||
|
total += ammo.system.quantity;
|
||||||
|
|
||||||
|
if (ctx.favouriteAmmo.length < 3 && ammo.getFlag(game.system.id, `favourited`)) {
|
||||||
|
ctx.favouriteAmmo.push({
|
||||||
|
uuid: ammo.uuid,
|
||||||
|
name: ammo.name,
|
||||||
|
quantity: ammo.system.quantity,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ctx.favouriteAmmo.length = 3; // assert array length
|
||||||
|
|
||||||
|
ctx.ammo = total;
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,11 @@ export function GenericAppMixin(HandlebarsApp) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
* This override makes it so that if the application has any framable popovers
|
||||||
|
* within it that are currently open, they will rerender as well.
|
||||||
|
*/
|
||||||
async _onRender() {
|
async _onRender() {
|
||||||
await super._onRender();
|
await super._onRender();
|
||||||
for (const manager of this._popoverManagers.values()) {
|
for (const manager of this._popoverManagers.values()) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { filePath } from "../../consts.mjs";
|
import { filePath } from "../../consts.mjs";
|
||||||
import { GenericPopoverMixin } from "./GenericPopoverMixin.mjs";
|
import { GenericPopoverMixin } from "./GenericPopoverMixin.mjs";
|
||||||
|
import { localizer } from "../../utils/Localizer.mjs";
|
||||||
|
import { Logger } from "../../utils/Logger.mjs";
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
|
@ -15,7 +17,10 @@ export class AmmoTracker extends GenericPopoverMixin(HandlebarsApplicationMixin(
|
||||||
`ripcrypt--AmmoTracker`,
|
`ripcrypt--AmmoTracker`,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
actions: {},
|
actions: {
|
||||||
|
favourite: this.#favourite,
|
||||||
|
unfavourite: this.#unfavourite,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
|
|
@ -26,17 +31,63 @@ export class AmmoTracker extends GenericPopoverMixin(HandlebarsApplicationMixin(
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Instance Data
|
// #region Instance Data
|
||||||
|
_favouriteCount = 0;
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Lifecycle
|
// #region Lifecycle
|
||||||
async _preparePartContext(partId, data) {
|
async _preparePartContext(partId, data) {
|
||||||
const ctx = { partId };
|
const ctx = { partId };
|
||||||
ctx.canPin = false;
|
|
||||||
ctx.ammos = data.ammos;
|
let favouriteCount = 0;
|
||||||
|
ctx.ammos = data.ammos.map(ammo => {
|
||||||
|
const favourite = ammo.getFlag(game.system.id, `favourited`) ?? false;
|
||||||
|
if (favourite) { favouriteCount++ };
|
||||||
|
|
||||||
|
return {
|
||||||
|
ammo,
|
||||||
|
favourite,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this._favouriteCount = favouriteCount;
|
||||||
|
ctx.atFavouriteLimit = favouriteCount >= 3;
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Actions
|
// #region Actions
|
||||||
|
static async #favourite(_, el) {
|
||||||
|
const targetEl = el.closest(`[data-item-id]`);
|
||||||
|
if (!targetEl) {
|
||||||
|
Logger.warn(`Cannot find a parent element with data-item-id`);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// get count of favourites
|
||||||
|
if (this._favouriteCount > 3) {
|
||||||
|
ui.notifications.error(localizer(`RipCrypt.notifs.error.at-favourite-limit`));
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = targetEl.dataset;
|
||||||
|
const item = await fromUuid(data.itemId);
|
||||||
|
if (!item) { return };
|
||||||
|
|
||||||
|
item.setFlag(game.system.id, `favourited`, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
static async #unfavourite(_, el) {
|
||||||
|
const targetEl = el.closest(`[data-item-id]`);
|
||||||
|
if (!targetEl) {
|
||||||
|
Logger.warn(`Cannot find a parent element with data-item-id`);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = targetEl.dataset;
|
||||||
|
const item = await fromUuid(data.itemId);
|
||||||
|
if (!item) { return };
|
||||||
|
|
||||||
|
item.unsetFlag(game.system.id, `favourited`);
|
||||||
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export function GenericPopoverMixin(HandlebarsApp) {
|
||||||
* want it to when being created.
|
* want it to when being created.
|
||||||
*
|
*
|
||||||
* Most of this implementation is identical to the ApplicationV2
|
* Most of this implementation is identical to the ApplicationV2
|
||||||
* implementation, the biggest difference is how targetLeft and targetRight
|
* implementation, the biggest difference is how targetLeft and targetTop
|
||||||
* are calculated.
|
* are calculated.
|
||||||
*/
|
*/
|
||||||
_updatePosition(position) {
|
_updatePosition(position) {
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,24 @@
|
||||||
{{ ammo }}
|
{{ ammo }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{#each favouriteAmmo as | data |}}
|
||||||
|
{{#if data}}
|
||||||
|
<div
|
||||||
|
class="half-pill fav-ammo"
|
||||||
|
data-item-id="{{data.uuid}}"
|
||||||
|
>
|
||||||
|
<label for="{{@root.meta.idp}}-{{data.uuid}}-quantity">
|
||||||
|
{{data.name}}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value="{{data.quantity}}"
|
||||||
|
id="{{@root.meta.idp}}-{{data.uuid}}-quantity"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
{{!-- * Currencies --}}
|
{{!-- * Currencies --}}
|
||||||
<div class="currencies">
|
<div class="currencies">
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
grid-template-rows: repeat(13, minmax(0, 1fr));
|
grid-template-rows: repeat(13, minmax(0, 1fr));
|
||||||
column-gap: var(--col-gap);
|
column-gap: var(--col-gap);
|
||||||
|
row-gap: var(--row-gap);
|
||||||
|
|
||||||
background: var(--base-background);
|
background: var(--base-background);
|
||||||
color: var(--base-text);
|
color: var(--base-text);
|
||||||
|
|
@ -125,8 +126,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label, .label {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.input {
|
|
||||||
|
input, .input {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,37 @@
|
||||||
<div>
|
<div>
|
||||||
{{#if ammos}}
|
{{#if ammos}}
|
||||||
<ul>
|
<ul>
|
||||||
{{#each ammos as | ammo |}}
|
{{#each ammos as | data |}}
|
||||||
<div class="ammo" data-item-id="{{ammo.uuid}}">
|
<li class="ammo" data-item-id="{{data.ammo.uuid}}">
|
||||||
<span class="name">{{ ammo.name }}</span>
|
<span class="name">{{ data.ammo.name }}</span>
|
||||||
<span class="value">{{ ammo.system.quantity }}</span>
|
<span class="value">{{ data.ammo.system.quantity }}</span>
|
||||||
<button
|
{{#if data.favourite}}
|
||||||
type="button"
|
<button
|
||||||
{{ disabled @root.canPin }}
|
type="button"
|
||||||
data-action="pinAmmo"
|
class="icon"
|
||||||
>
|
data-action="unfavourite"
|
||||||
Pin
|
aria-label="Unpin ammo"
|
||||||
</button>
|
>
|
||||||
</div>
|
<rc-icon
|
||||||
|
name="icons/star"
|
||||||
|
var:size="1rem"
|
||||||
|
></rc-icon>
|
||||||
|
</button>
|
||||||
|
{{else}}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="icon"
|
||||||
|
{{ disabled @root.atFavouriteLimit }}
|
||||||
|
data-action="favourite"
|
||||||
|
aria-label="Pin ammo"
|
||||||
|
>
|
||||||
|
<rc-icon
|
||||||
|
name="icons/star-empty"
|
||||||
|
var:size="1rem"
|
||||||
|
></rc-icon>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
.ripcrypt--AmmoTracker.ripcrypt--AmmoTracker {
|
.ripcrypt--AmmoTracker.ripcrypt--AmmoTracker {
|
||||||
color: var(--popover-text);
|
color: var(--popover-text);
|
||||||
background: var(--popover-background);
|
background: var(--popover-background);
|
||||||
padding: 4px 8px;
|
padding: 4px;
|
||||||
|
|
||||||
|
--row-gap: 4px;
|
||||||
--button-text: var(--header-text);
|
--button-text: var(--header-text);
|
||||||
--button-background: var(--header-background);
|
--button-background: var(--header-background);
|
||||||
|
|
||||||
|
|
@ -11,11 +12,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
&:nth-child(even) {
|
display: flex;
|
||||||
color: var(--popover-alt-row-text);
|
flex-direction: column;
|
||||||
background: var(--popover-alt-row-background);
|
row-gap: var(--row-gap);
|
||||||
--button-text: unset;
|
|
||||||
--button-background: unset;
|
> li {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
color: var(--popover-alt-row-text);
|
||||||
|
background: var(--popover-alt-row-background);
|
||||||
|
--button-text: unset;
|
||||||
|
--button-background: unset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
/* height: 270px; */
|
/* height: 270px; */
|
||||||
width: 680px;
|
width: 680px;
|
||||||
--col-gap: 2px;
|
--col-gap: 2px;
|
||||||
|
--row-gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
label, input, select {
|
label, input, select {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
.ripcrypt:where(.popover.frameless, .hud) button,
|
.ripcrypt:where(.popover.frameless, .hud) button,
|
||||||
.ripcrypt > .window-content button {
|
.ripcrypt > .window-content button {
|
||||||
all: revert;
|
all: revert;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue