{#if $store.activeTab === "auctions"}
await store.claimAuctions(auctions.filter(auction => auction.user === game.user && auction.expired))}
- disabled={!auctions.filter(auction => auction.user === game.user && auction.expired).length}>
+ callback={async () => await store.claimAuctions(auctions.filter(auction => auction.user === game.user && auction.expired))}
+ disabled={!auctions.filter(auction => auction.user === game.user && auction.expired).length}>
Collect all
{:else if $store.activeTab === "bids"}
await store.claimAuctions(auctions.filter(auction => !auction.won))}
- disabled={!auctions.filter(auction => !auction.won).length}>
+ callback={async () => await store.claimAuctions(auctions.filter(auction => !auction.won))}
+ disabled={!auctions.filter(auction => !auction.won).length}>
Collect all
{:else}
await store.claimAuctions(auctions.filter(auction => auction.won))}
- disabled={!auctions.filter(auction => auction.won).length}>
+ callback={async () => await store.claimAuctions(auctions.filter(auction => auction.won))}
+ disabled={!auctions.filter(auction => auction.won).length}>
Collect all
{/if}
diff --git a/src/applications/auctioneer/Components/DropZone.svelte b/src/applications/auctioneer/Components/DropZone.svelte
index 80f9146..4cae365 100644
--- a/src/applications/auctioneer/Components/DropZone.svelte
+++ b/src/applications/auctioneer/Components/DropZone.svelte
@@ -45,13 +45,13 @@
diff --git a/src/applications/auctioneer/Components/NoAccess.svelte b/src/applications/auctioneer/Components/NoAccess.svelte
index a2a6291..581a084 100644
--- a/src/applications/auctioneer/Components/NoAccess.svelte
+++ b/src/applications/auctioneer/Components/NoAccess.svelte
@@ -37,7 +37,7 @@
diff --git a/src/applications/auctioneer/Components/ReactiveButton.svelte b/src/applications/auctioneer/Components/ReactiveButton.svelte
index 918f811..c42f999 100644
--- a/src/applications/auctioneer/Components/ReactiveButton.svelte
+++ b/src/applications/auctioneer/Components/ReactiveButton.svelte
@@ -8,10 +8,10 @@
let disabledCallback = false;
async function runCallback() {
- if(disabledCallback) return;
+ if (disabledCallback) return;
disabledCallback = true;
await callback();
- if(!completelyDisable) {
+ if (!completelyDisable) {
setTimeout(() => {
disabledCallback = false;
}, 100);
diff --git a/src/applications/auctioneer/Components/SortByTabs.svelte b/src/applications/auctioneer/Components/SortByTabs.svelte
index 6935ce4..f1fcc69 100644
--- a/src/applications/auctioneer/Components/SortByTabs.svelte
+++ b/src/applications/auctioneer/Components/SortByTabs.svelte
@@ -64,10 +64,10 @@
margin-left: 0.35rem;
}
- i.switch-tab {
+ i.switch-tab {
margin-left: 0;
margin-right: 0.35rem;
- }
+ }
}
}
diff --git a/src/applications/auctioneer/Logs/Logs.svelte b/src/applications/auctioneer/Logs/Logs.svelte
index d71b66d..a850bcf 100644
--- a/src/applications/auctioneer/Logs/Logs.svelte
+++ b/src/applications/auctioneer/Logs/Logs.svelte
@@ -7,24 +7,24 @@
import BidLog from "~/applications/auctioneer/Logs/BidLog.svelte";
import BuyoutLog from "~/applications/auctioneer/Logs/BuyoutLog.svelte";
import ClaimedAuctionLog from "~/applications/auctioneer/Logs/ClaimedAuctionLog.svelte";
- import CancelledAuctionLog from "~/applications/auctioneer/Logs/CancelledAuctionLog.svelte";
- import { getLogs } from "~/lib.js";
- import { writable } from "svelte/store";
+ import CancelledAuctionLog from "~/applications/auctioneer/Logs/CancelledAuctionLog.svelte";
+ import { getLogData } from "~/lib.js";
+ import { writable } from "svelte/store";
const store = getContext("store");
- const componentTypes = {
- AuctionLog,
- ExpiredAuctionLog,
- BidLog,
- BuyoutLog,
- ClaimedAuctionLog,
- CancelledAuctionLog,
- }
+ const componentTypes = {
+ AuctionLog,
+ ExpiredAuctionLog,
+ BidLog,
+ BuyoutLog,
+ ClaimedAuctionLog,
+ CancelledAuctionLog,
+ }
- const auctioneerDoc = store.auctioneerDoc;
+ const auctioneerDoc = store.auctioneerDoc;
let allEntries = writable([]);
- $: $allEntries = getLogs($auctioneerDoc, $store.auctionData).logs;
+ $: $allEntries = getLogData($auctioneerDoc, $store.auctionData).logs;
const searchDebounce = foundry.utils.debounce((searchText) => {
allEntries.update(entries => {
diff --git a/src/applications/auctioneer/Tabs.svelte b/src/applications/auctioneer/Tabs.svelte
index 08d4377..17c9da3 100644
--- a/src/applications/auctioneer/Tabs.svelte
+++ b/src/applications/auctioneer/Tabs.svelte
@@ -20,48 +20,48 @@
diff --git a/src/applications/auctioneer/Winnings/Winnings.svelte b/src/applications/auctioneer/Winnings/Winnings.svelte
index 43777ce..dade428 100644
--- a/src/applications/auctioneer/Winnings/Winnings.svelte
+++ b/src/applications/auctioneer/Winnings/Winnings.svelte
@@ -52,7 +52,7 @@
overflow: hidden;
}
- :global.virtual-scroll-root{
+ :global.virtual-scroll-root {
overflow-x: hidden;
}
diff --git a/src/applications/auctioneer/auctioneer-shell.svelte b/src/applications/auctioneer/auctioneer-shell.svelte
index 4414681..c9aec1c 100644
--- a/src/applications/auctioneer/auctioneer-shell.svelte
+++ b/src/applications/auctioneer/auctioneer-shell.svelte
@@ -2,7 +2,7 @@
import { ApplicationShell } from "#runtime/svelte/component/core";
import { getContext, onDestroy, setContext } from 'svelte';
- import { createStore } from "./auctioneer-store.js";
+ import { createStore } from "./auctioneer-store.js";
import Tabs from "./Tabs.svelte";
import BottomBar from "~/applications/auctioneer/Components/BottomBar.svelte";
import NoAccess from "~/applications/auctioneer/Components/NoAccess.svelte";
@@ -14,13 +14,13 @@
const { auctioneer } = application.options;
export const store = createStore(auctioneer);
- setContext("store", store);
+ setContext("store", store);
onDestroy(() => {
store.unsubscribe();
});
- $: component = $store.access ? $store.tabs[$store.activeTab].component : NoAccess;
+ $: component = $store.access ? $store.tabs[$store.activeTab].component : NoAccess;
diff --git a/src/applications/auctioneer/auctioneer-store.js b/src/applications/auctioneer/auctioneer-store.js
index bee1020..1684149 100644
--- a/src/applications/auctioneer/auctioneer-store.js
+++ b/src/applications/auctioneer/auctioneer-store.js
@@ -26,9 +26,9 @@ export function createStore(auctioneer) {
switch: "price",
sortByColumns: {
"name": { label: "Name", sort: (a, b) => a.item.name > b.item.name ? 1 : -1 },
- "time": { label: "Time Left", sort: (a, b) => b.timeLeft.value - a.timeLeft.value },
+ "time": { label: "Time", sort: (a, b) => b.timeLeft.value - a.timeLeft.value },
"seller": { label: "Seller", sort: (a, b) => a.actor.name > b.actor.name ? 1 : -1 },
- "bid-type": { label: "Bid Type", sort: (a, b) => a.bidVisibility > b.bidVisibility ? 1 : -1 },
+ "bid-type": { label: "Type", sort: (a, b) => a.bidVisibility > b.bidVisibility ? 1 : -1 },
"price": {
label: "Price / Buyout",
sort: (a, b) => b.bidPriceData.totalPrice - a.bidPriceData.totalPrice,
@@ -61,7 +61,7 @@ export function createStore(auctioneer) {
sortByInverse: false,
sortByColumns: {
"name": { label: "Name", sort: (a, b) => a.auction.item.name > b.auction.item.name ? 1 : -1 },
- "time": { label: "Time Left", sort: (a, b) => b.auction.timeLeft.value - a.auction.timeLeft.value },
+ "time": { label: "Time", sort: (a, b) => b.auction.timeLeft.value - a.auction.timeLeft.value },
"price": {
label: "Buyout Price", sort: (a, b) => {
if (!b.auction.buyoutPrice && a.auction.buyoutPrice) {
@@ -72,8 +72,8 @@ export function createStore(auctioneer) {
return b.auction.buyoutPriceData.totalPrice - a.auction.buyoutPriceData.totalPrice;
}
},
- "bid-type": { label: "Bid Type", sort: (a, b) => a.auction.bidVisibility > b.auction.bidVisibility ? 1 : -1 },
- "bid-status": { label: "Bid Status", sort: (a, b) => b.bidStatus.value - a.bidStatus.value },
+ "bid-type": { label: "Bid", sort: (a, b) => a.auction.bidVisibility > b.auction.bidVisibility ? 1 : -1 },
+ "bid-status": { label: "Status", sort: (a, b) => b.bidStatus.value - a.bidStatus.value },
"bid": {
label: "Current Bid",
sort: (a, b) => b.bidPriceData.totalPrice - a.bidPriceData.totalPrice
@@ -89,9 +89,9 @@ export function createStore(auctioneer) {
switch: "price",
sortByColumns: {
"name": { label: "Name", sort: (a, b) => a.item.name > b.item.name ? 1 : -1 },
- "time": { label: "Time Left", sort: (a, b) => b.timeLeft.value - a.timeLeft.value },
+ "time": { label: "Time", sort: (a, b) => b.timeLeft.value - a.timeLeft.value },
"high-bidder": { label: "High Bidder", sort: (a, b) => a.actor.name > b.actor.name ? 1 : -1 },
- "bid-type": { label: "Bid Type", sort: (a, b) => a.bidVisibility > b.bidVisibility ? 1 : -1 },
+ "bid-type": { label: "Type", sort: (a, b) => a.bidVisibility > b.bidVisibility ? 1 : -1 },
"price": {
label: "Bid/Reserve Price",
sort: (a, b) => {
@@ -231,15 +231,15 @@ export function createStore(auctioneer) {
Simple calendar tends to touch update world time, the date updated hook is only local, meaning other users do not get
the updated date
*/
- let lastUpdate = null;
+ let lastUpdate = null;
const calendarHookId = Hooks.on("updateWorldTime", () => {
if (Date.now() < (lastUpdate + 10000)
- || get(auctioneerFlags).timeType === CONSTANTS.AUCTION_TIME_TYPE_KEYS.REAL_TIME
- || !window?.SimpleCalendar){
- return;
- }
+ || get(auctioneerFlags).timeType === CONSTANTS.AUCTION_TIME_TYPE_KEYS.REAL_TIME
+ || !window?.SimpleCalendar) {
+ return;
+ }
debounceUpdateAuctionData();
- lastUpdate = Date.now();
+ lastUpdate = Date.now();
});
updateAuctionData();
@@ -320,8 +320,8 @@ export function createStore(auctioneer) {
let minimumBidPrice = latestBidPrice ?? auction.startPrice;
- if (auction.minBidPrice) {
- minimumBidPrice = game.itempiles.API.calculateCurrencies(minimumBidPrice, auction.minBidPrice, false);
+ if (auction.actualMininumBidPrice) {
+ minimumBidPrice = game.itempiles.API.calculateCurrencies(minimumBidPrice, auction.actualMininumBidPrice, false);
}
const latestBidPaymentData = lib.getPriceFromData(minimumBidPrice);
@@ -337,7 +337,7 @@ export function createStore(auctioneer) {
existingBids.push({
id: randomID(),
- userId: game.userId,
+ userId: game.userId,
auctionUuid: existingBids?.[existingBidForAuctionIndex]?.uuid ?? auction.uuid,
price: bidPaymentData.basePriceString,
date: lib.evaluateFoundryTime(auctioneer)
@@ -366,7 +366,7 @@ export function createStore(auctioneer) {
const existingBuyouts = lib.getUserBuyouts();
existingBuyouts.push({
id: randomID(),
- userId: game.userId,
+ userId: game.userId,
auctionUuid: auction.uuid,
actorUuid: targetActor.uuid,
price: auction.buyoutPrice,
@@ -473,7 +473,7 @@ export function createStore(auctioneer) {
}
if (!bidPriceString && !buyoutPriceString) {
- ui.notifications.error("The item cannot be free!")
+ ui.notifications.error("The item cannot be free - the auction must have a start bid price or a buyout price!");
return false;
}
@@ -506,7 +506,7 @@ export function createStore(auctioneer) {
setProperty(data.itemData, game.itempiles.API.ITEM_QUANTITY_ATTRIBUTE, data.quantityPerAuction);
const baseFlagData = {
- userId: game.userId,
+ userId: game.userId,
actorUuid: actor.uuid,
itemData: data.itemData,
startPrice: bidPriceString,
@@ -556,7 +556,7 @@ export function createStore(auctioneer) {
let successfulAuctionCurrencies = [];
let failedBidCurrencies = [];
- if(cancelled){
+ if (cancelled) {
let content = `
Are you sure you want to cancel this auction?
`;
content += flags.auctionDeposit && ownedAuctions[0].depositPrice
? `
You will lose the deposit of ${ownedAuctions[0].depositPrice} .
`
@@ -696,24 +696,26 @@ export function createStore(auctioneer) {
async function relistAuction(auction) {
const existingAuctions = lib.getUserAuctions();
const indexToRefresh = existingAuctions.findIndex(existingAuction => existingAuction.uuid === auction.uuid);
- existingAuctions[indexToRefresh].date = lib.evaluateFoundryTime(auctioneer)
- existingAuctions[indexToRefresh].expiryDate = lib.evaluateFoundryTime(auctioneer, existingAuctions[indexToRefresh].duration);
+ const duplicatedAuction = foundry.utils.duplicate(existingAuctions[indexToRefresh]);
+ existingAuctions[indexToRefresh].claimed = true;
+ duplicatedAuction.date = lib.evaluateFoundryTime(auctioneer)
+ duplicatedAuction.expiryDate = lib.evaluateFoundryTime(auctioneer, duplicatedAuction.duration);
const actor = get(actorDoc);
const flags = get(auctioneerFlags);
- if (flags.auctionDeposit && existingAuctions[indexToRefresh].depositPrice) {
- const depositPriceData = lib.getPriceFromData(existingAuctions[indexToRefresh].depositPrice, actor);
+ if (flags.auctionDeposit && duplicatedAuction.depositPrice) {
+ const depositPriceData = lib.getPriceFromData(duplicatedAuction.depositPrice, actor);
if (!depositPriceData.canBuy) {
if (game.user.isGM) {
const proceed = await Dialog.confirm({
title: "Relist Failed Auction",
- content: `
${actor.name} can't afford the deposit of ${existingAuctions[indexToRefresh].depositPrice} - are you sure you want to relist this auction?
`,
+ content: `
${actor.name} can't afford the deposit of ${duplicatedAuction.depositPrice} - are you sure you want to relist this auction?
`,
options: { classes: ["dialog", "item-piles-auctioneer"] }
});
if (!proceed) return;
} else {
return Dialog.prompt({
title: "Cannot Relist Failed Auction",
- content: `
You cannot relist this auction, as ${actor.name} cannot afford the deposit of ${existingAuctions[indexToRefresh].depositPrice} to do so.
`,
+ content: `
You cannot relist this auction, as ${actor.name} cannot afford the deposit of ${duplicatedAuction.depositPrice} to do so.
`,
options: { classes: ["dialog", "item-piles-auctioneer"] }
});
}
@@ -723,7 +725,7 @@ export function createStore(auctioneer) {
const proceed = await Dialog.confirm({
title: "Relist Failed Auction",
content: `
-
By relisting this auction, ${actor.name} must pay ${existingAuctions[indexToRefresh].depositPrice} - are you sure you want to do this?
+
By relisting this auction, ${actor.name} must pay ${duplicatedAuction.depositPrice} - are you sure you want to do this?
Ignore deposit payment
`,
yes: (html) => {
@@ -732,20 +734,21 @@ export function createStore(auctioneer) {
options: { classes: ["dialog", "item-piles-auctioneer"] }
});
if (!proceed) return;
- if(!ignoreDeposit) {
- await game.itempiles.API.removeCurrencies(actor, existingAuctions[indexToRefresh].depositPrice);
+ if (!ignoreDeposit) {
+ await game.itempiles.API.removeCurrencies(actor, duplicatedAuction.depositPrice);
}
- }else {
+ } else {
const proceed = await Dialog.confirm({
title: "Relist Failed Auction",
- content: `
By relisting this auction, ${actor.name} must pay ${existingAuctions[indexToRefresh].depositPrice} - are you sure you want to do this?
`,
+ content: `
By relisting this auction, ${actor.name} must pay ${duplicatedAuction.depositPrice} - are you sure you want to do this?
`,
options: { classes: ["dialog", "item-piles-auctioneer"] }
});
if (!proceed) return;
- await game.itempiles.API.removeCurrencies(actor, existingAuctions[indexToRefresh].depositPrice);
+ await game.itempiles.API.removeCurrencies(actor, duplicatedAuction.depositPrice);
}
}
}
+ existingAuctions.push(duplicatedAuction);
ui.notifications.notify(`The auction for ${auction.item.name} has been relisted.`);
return game.user.setFlag(CONSTANTS.MODULE_NAME, CONSTANTS.AUCTIONS_FLAG, existingAuctions);
}
@@ -837,7 +840,7 @@ export function getAuctioneerActorData(auctioneer) {
&& auctions[source.auctionUuid]
&& !auctions[source.auctionUuid].won;
}).forEach(source => {
- const bid = lib.makeBid(auctioneer, source, auctions);
+ const bid = lib.makeBid(auctioneer, source, auctions);
bids[bid.id] = bid;
});
@@ -855,10 +858,10 @@ export function getAuctioneerActorData(auctioneer) {
auction.bidPrice = auction.bids.length ? ownedBids[0].price : false;
}
- auction.minBidPrice = auction.minBidPrice
+ auction.actualMininumBidPrice = auction.minBidPrice && auction.bidPrice
? game.itempiles.API.calculateCurrencies(auction.bidPrice, auction.minBidPrice, false)
- : auction.bidPrice || auction.startPrice;
- auction.minBidPriceData = lib.getPriceFromData(auction.minBidPrice);
+ : auction.minBidPrice || auction.bidPrice;
+ auction.actualMininumBidPriceData = lib.getPriceFromData(auction.actualMininumBidPrice);
if (auction.bids.length && auction.buyoutPrice) {
if (lib.isPriceHigherThan(auction.bids[0].priceData, auction.buyoutPriceData)) {
diff --git a/src/applications/auctioneer/auctioneer.js b/src/applications/auctioneer/auctioneer.js
index e7e7835..87dc849 100644
--- a/src/applications/auctioneer/auctioneer.js
+++ b/src/applications/auctioneer/auctioneer.js
@@ -16,10 +16,6 @@ export default class Auctioneer extends SvelteApplication {
this.actor = options.auctioneer;
}
- onDropData(data){
- return this.store.onDropData(data);
- }
-
/** @inheritdoc */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
@@ -52,7 +48,9 @@ export default class Auctioneer extends SvelteApplication {
})
}
-
+ onDropData(data) {
+ return this.store.onDropData(data);
+ }
/** @override */
_getHeaderButtons() {
@@ -60,6 +58,14 @@ export default class Auctioneer extends SvelteApplication {
const canConfigure = game.user.isGM;
if (canConfigure) {
buttons = [
+ {
+ label: !game.settings.get('item-piles', 'hideActorHeaderText') ? "ITEM-PILES.Inspect.OpenSheet" : "",
+ class: "item-piles-open-actor-sheet",
+ icon: "fas fa-user",
+ onclick: () => {
+ this.actor.sheet.render(true, { focus: true, bypassItemPiles: true });
+ }
+ },
{
label: !game.settings.get("item-piles", "hideActorHeaderText") ? "ITEM-PILES.HUD.Configure" : "",
class: "item-piles-configure-pile",
diff --git a/src/constants.js b/src/constants.js
index cb7e695..3d11f89 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -38,10 +38,12 @@ const CONSTANTS = {
* @property {AuctionTimeType} timeType
* @property {string} minTimeLimit
* @property {string} maxTimeLimit
+ * @property {Item/boolean} entryItem
* @property {boolean} displayEntryItem
+ * @property {Actor/boolean} owner
*/
ACTOR_DEFAULTS: {
- auctionFee: 5,
+ auctionFee: "@finalAuctionCost * 0.05",
auctionDeposit: "@itemCost * 0.05",
allowSecondaryCurrencies: true,
enableMinimumBid: false,
@@ -53,7 +55,9 @@ const CONSTANTS = {
timeType: "realTime",
minTimeLimit: "12hours",
maxTimeLimit: "2days",
- displayEntryItem: false,
+ entryItem: false,
+ displayEntryItem: false,
+ owner: false,
},
AUCTION_TIME_LIMITS: {
@@ -75,8 +79,8 @@ const CONSTANTS = {
DEFAULTS: {
/**
* @typedef {Object} Auction
- * @property {String} id
- * @property {String} userId
+ * @property {String} id
+ * @property {String} userId
* @property {String} uuid
* @property {String} actorUuid
* @property {Object} item
@@ -92,7 +96,7 @@ const CONSTANTS = {
*/
AUCTION: {
id: "",
- userId: "",
+ userId: "",
uuid: "AUCTIONID-AUCTIONEERUUID-USERUUID",
actorUuid: "",
itemData: {},
@@ -114,14 +118,14 @@ const CONSTANTS = {
/**
* @typedef {Object} Bid
* @property {String} id
- * @property {String} userId
+ * @property {String} userId
* @property {String} auctionUuid
* @property {Number} price
* @property {Number} date
*/
BID: {
id: "",
- userId: "",
+ userId: "",
auctionUuid: "",
actorUuid: "",
price: "",
@@ -139,7 +143,7 @@ const CONSTANTS = {
*/
BUYOUT: {
id: "",
- userId: "",
+ userId: "",
auctionUuid: "",
actorUuid: "",
price: "",
@@ -195,12 +199,12 @@ CONSTANTS.AUCTIONEER_SETTINGS = {
auctionFee: {
title: "Auction Fee Formula",
label: "This is the percentage of the total sell price that the auctioneer takes as a cut from any successful auction.",
- type: Number,
+ type: String,
value: CONSTANTS.ACTOR_DEFAULTS.auctionFee
},
- auctionDeposit: {
+ auctionDeposit: {
title: "Deposit Fee Formula",
- label: "This is the formula to calculate the price that someone must pay to put up an auction.",
+ label: "This is the formula to calculate the price that someone must pay to put up an auction. This is returned to the creator of the auction if the auction is successful, but kept by the auctioneer if failed",
type: String,
value: CONSTANTS.ACTOR_DEFAULTS.auctionDeposit
},
@@ -217,7 +221,7 @@ CONSTANTS.AUCTIONEER_SETTINGS = {
type: Boolean,
value: CONSTANTS.ACTOR_DEFAULTS.allowSecondaryCurrencies
},
- visibleTimeLeft: {
+ visibleTimeLeft: {
title: "Show full time left",
label: "When enabled, instead of 'very long' or 'short' strings for auction duration, this will show an exact amount of time left before auctions expire.",
type: Boolean,
@@ -263,24 +267,30 @@ CONSTANTS.AUCTIONEER_SETTINGS = {
options: CONSTANTS.AUCTION_TIME_LIMITS,
value: CONSTANTS.ACTOR_DEFAULTS.maxTimeLimit
},
- allowBankerVaults: {
- title: "Allow banker vault impersonation",
- label: "When enabled, this allows users to impersonate the vaults connected to bankers when interacting with the auctioneer. They can buy and sell items with it.",
- type: Boolean,
- value: CONSTANTS.ACTOR_DEFAULTS.allowBankerVaults
- },
+ allowBankerVaults: {
+ title: "Allow banker vault impersonation",
+ label: "When enabled, this allows users to impersonate the vaults connected to bankers when interacting with the auctioneer. They can buy and sell items with it.",
+ type: Boolean,
+ value: CONSTANTS.ACTOR_DEFAULTS.allowBankerVaults
+ },
entryItem: {
title: "Entry Item",
label: "This configures an item that the character must possess in their inventory in order to access the auction house.",
type: Item,
value: false
},
- displayEntryItem: {
- title: "Display Entry Item",
- label: "This determines whether the auctioneer accepts secondary currencies for its auctions",
- type: Boolean,
- value: CONSTANTS.ACTOR_DEFAULTS.displayEntryItem
- },
+ displayEntryItem: {
+ title: "Display Entry Item",
+ label: "This determines whether the auctioneer accepts secondary currencies for its auctions",
+ type: Boolean,
+ value: CONSTANTS.ACTOR_DEFAULTS.displayEntryItem
+ },
+ owner: {
+ title: "Owner",
+ label: "This configures whether a character owns this auctioneer or not. All auction fees and deposit fees are sent to this character's inventory when a GM logs on.",
+ type: Actor,
+ value: false
+ },
};
export default CONSTANTS;
diff --git a/src/lib.js b/src/lib.js
index e3cdb9c..f6b917e 100644
--- a/src/lib.js
+++ b/src/lib.js
@@ -1,102 +1,103 @@
import CONSTANTS from "~/constants.js";
import Auctioneer from "~/applications/auctioneer/auctioneer.js";
import moment from "moment";
+import { getAuctioneerActorData } from "~/applications/auctioneer/auctioneer-store.js";
export function auctioneerRendered(itemPile) {
- const auctioneer = itemPile?.actor ?? itemPile;
+ const auctioneer = itemPile?.actor ?? itemPile;
- const flags = auctioneer.getFlag("item-piles", 'data');
+ const flags = auctioneer.getFlag("item-piles", 'data');
- if (flags?.type !== CONSTANTS.AUCTIONEER) return;
+ if (flags?.type !== CONSTANTS.AUCTIONEER) return;
- Auctioneer.show({ auctioneer });
+ Auctioneer.show({ auctioneer });
- return false;
+ return false;
}
export function getActiveApps(id, single = false) {
- const apps = Object.values(ui.windows).filter(app => {
- return app.id.startsWith(id) && app._state > Application.RENDER_STATES.CLOSED;
- });
- if (single) {
- return apps?.[0] ?? false;
- }
- return apps;
+ const apps = Object.values(ui.windows).filter(app => {
+ return app.id.startsWith(id) && app._state > Application.RENDER_STATES.CLOSED;
+ });
+ if (single) {
+ return apps?.[0] ?? false;
+ }
+ return apps;
}
export function abbreviateNumbers(number, decPlaces = 2) {
- // 2 decimal places => 100, 3 => 1000, etc
- decPlaces = Math.pow(10, decPlaces)
+ // 2 decimal places => 100, 3 => 1000, etc
+ decPlaces = Math.pow(10, decPlaces)
- // Enumerate number abbreviations
- let abbrev = ['k', 'm', 'b', 't']
+ // Enumerate number abbreviations
+ let abbrev = ['k', 'm', 'b', 't']
- // Go through the array backwards, so we do the largest first
- for (let i = abbrev.length - 1; i >= 0; i--) {
+ // Go through the array backwards, so we do the largest first
+ for (let i = abbrev.length - 1; i >= 0; i--) {
- // Convert array index to "1000", "1000000", etc
- let size = Math.pow(10, (i + 1) * 3)
+ // Convert array index to "1000", "1000000", etc
+ let size = Math.pow(10, (i + 1) * 3)
- // If the number is bigger or equal do the abbreviation
- if (size <= number) {
- // Here, we multiply by decPlaces, round, and then divide by decPlaces.
- // This gives us nice rounding to a particular decimal place.
- number = Math.round((number * decPlaces) / size) / decPlaces
+ // If the number is bigger or equal do the abbreviation
+ if (size <= number) {
+ // Here, we multiply by decPlaces, round, and then divide by decPlaces.
+ // This gives us nice rounding to a particular decimal place.
+ number = Math.round((number * decPlaces) / size) / decPlaces
- // Handle special case where we round up to the next abbreviation
- if (number === 1000 && i < abbrev.length - 1) {
- number = 1
- i++
- }
+ // Handle special case where we round up to the next abbreviation
+ if (number === 1000 && i < abbrev.length - 1) {
+ number = 1
+ i++
+ }
- // Add the letter for the abbreviation
- number += abbrev[i]
+ // Add the letter for the abbreviation
+ number += abbrev[i]
- // We are done... stop
- break;
- }
- }
+ // We are done... stop
+ break;
+ }
+ }
- return number
+ return number
}
const relativeDateStrings = [
- [0, "Auction Failed"],
- [0.5, "Short"],
- [2, "Medium"],
- [12, "Long"],
- [24, "Very Long"],
+ [0, "Auction Failed"],
+ [0.5, "Short"],
+ [2, "Medium"],
+ [12, "Long"],
+ [24, "Very Long"],
]
export function dateNumberToRelativeString(auctioneer, date) {
- const flags = getAuctioneerActorFlags(auctioneer);
+ const flags = getAuctioneerActorFlags(auctioneer);
- const now = evaluateFoundryTime(auctioneer);
+ const now = evaluateFoundryTime(auctioneer);
- if (flags.visibleTimeLeft) {
- const value = (date - now);
- return {
- value: value,
- label: value > 0 ? dateTimeToString(auctioneer, date, true) : "Auction Expired"
- }
- }
+ if (flags.visibleTimeLeft) {
+ const value = (date - now);
+ return {
+ value: value,
+ label: value > 0 ? dateTimeToString(auctioneer, date, true) : "Auction Expired"
+ }
+ }
- const hours = (date - now) / 1000 / 60 / 60;
+ const hours = (date - now) / 1000 / 60 / 60;
- for (const [value, label] of relativeDateStrings) {
- if (hours <= value) return { value, label };
- }
+ for (const [value, label] of relativeDateStrings) {
+ if (hours <= value) return { value, label };
+ }
- return {
- value: hours,
- label: Math.floor(hours / 24) + " day" + (Math.floor(hours / 24) > 1 ? "s" : "")
- };
+ return {
+ value: hours,
+ label: Math.floor(hours / 24) + " day" + (Math.floor(hours / 24) > 1 ? "s" : "")
+ };
}
@@ -107,66 +108,66 @@ export function dateNumberToRelativeString(auctioneer, date) {
*/
export function getPriceFromData(priceFlag, actor = false) {
- if (!priceFlag) {
- return {
- valid: false,
- canBuy: false,
- currencies: [],
- totalPrice: 0
- };
- }
-
- const paymentData = game.itempiles.API.getPaymentData(priceFlag, { target: actor });
-
- const currencies = paymentData.finalPrices.reverse();
-
- let primaryCurrency;
- for (const currency of currencies) {
- if (!currency.exchangeRate || currency.exchangeRate < 1) continue;
- if (currency.exchangeRate === 1) {
- primaryCurrency = currency;
- } else if (primaryCurrency && primaryCurrency.quantity >= (currency.exchangeRate * 1000)) {
- currency.quantity = Math.floor(primaryCurrency.quantity / currency.exchangeRate)
- primaryCurrency.quantity -= Math.floor(primaryCurrency.quantity / currency.exchangeRate) * currency.exchangeRate;
- }
- }
-
- return {
- ...paymentData,
- valid: true,
- currencies: currencies.reverse().filter(currency => currency.quantity),
- totalPrice: paymentData.totalCurrencyCost + paymentData.finalPrices
- .filter(currency => currency.secondary && currency.quantity)
- .reduce((acc, currency) => {
- return acc + currency.quantity;
- }, 0)
- };
+ if (!priceFlag) {
+ return {
+ valid: false,
+ canBuy: false,
+ currencies: [],
+ totalPrice: 0
+ };
+ }
+
+ const paymentData = game.itempiles.API.getPaymentData(priceFlag, { target: actor });
+
+ const currencies = paymentData.finalPrices.reverse();
+
+ let primaryCurrency;
+ for (const currency of currencies) {
+ if (!currency.exchangeRate || currency.exchangeRate < 1) continue;
+ if (currency.exchangeRate === 1) {
+ primaryCurrency = currency;
+ } else if (primaryCurrency && primaryCurrency.quantity >= (currency.exchangeRate * 1000)) {
+ currency.quantity = Math.floor(primaryCurrency.quantity / currency.exchangeRate)
+ primaryCurrency.quantity -= Math.floor(primaryCurrency.quantity / currency.exchangeRate) * currency.exchangeRate;
+ }
+ }
+
+ return {
+ ...paymentData,
+ valid: true,
+ currencies: currencies.reverse().filter(currency => currency.quantity),
+ totalPrice: paymentData.totalCurrencyCost + paymentData.finalPrices
+ .filter(currency => currency.secondary && currency.quantity)
+ .reduce((acc, currency) => {
+ return acc + currency.quantity;
+ }, 0)
+ };
}
export function getValidCurrenciesForPrice(currencies) {
- const defaultIncomingCurrencies = currencies.filter(currency => !currency.secondary);
+ const defaultIncomingCurrencies = currencies.filter(currency => !currency.secondary);
- const defaultCurrencies = defaultIncomingCurrencies.length > 0
- ? game.itempiles.API.CURRENCIES.map(currency => {
- currency.quantity = 0;
- currency.secondary = false;
- return currency;
- }) : [];
+ const defaultCurrencies = defaultIncomingCurrencies.length > 0
+ ? game.itempiles.API.CURRENCIES.map(currency => {
+ currency.quantity = 0;
+ currency.secondary = false;
+ return currency;
+ }) : [];
- const secondaryIncomingCurrencies = currencies.filter(currency => currency.secondary);
- const secondaryCurrencies = game.itempiles.API.SECONDARY_CURRENCIES
- .filter(currency => secondaryIncomingCurrencies.some(inCurrency =>
- (currency.data.uuid && inCurrency.data.uuid && currency.data.uuid === inCurrency.data.uuid)
- || (currency.data.path && inCurrency.data.path && currency.data.path === inCurrency.data.path))
- ).map(currency => {
- currency.quantity = 0;
- currency.secondary = true;
- return currency;
- });
+ const secondaryIncomingCurrencies = currencies.filter(currency => currency.secondary);
+ const secondaryCurrencies = game.itempiles.API.SECONDARY_CURRENCIES
+ .filter(currency => secondaryIncomingCurrencies.some(inCurrency =>
+ (currency.data.uuid && inCurrency.data.uuid && currency.data.uuid === inCurrency.data.uuid)
+ || (currency.data.path && inCurrency.data.path && currency.data.path === inCurrency.data.path))
+ ).map(currency => {
+ currency.quantity = 0;
+ currency.secondary = true;
+ return currency;
+ });
- return defaultCurrencies.concat(secondaryCurrencies)
+ return defaultCurrencies.concat(secondaryCurrencies)
}
@@ -175,410 +176,473 @@ export function getValidCurrenciesForPrice(currencies) {
* @returns {ActorFlagDefaults}
*/
export function getAuctioneerActorFlags(actor) {
- const defaults = foundry.utils.deepClone(CONSTANTS.ACTOR_DEFAULTS);
- const actorFlags = foundry.utils.deepClone(actor ? actor.getFlag(CONSTANTS.ITEM_PILES_MODULE, "data") : {});
- return foundry.utils.mergeObject(defaults, actorFlags);
+ const defaults = foundry.utils.deepClone(CONSTANTS.ACTOR_DEFAULTS);
+ const actorFlags = foundry.utils.deepClone(actor ? actor.getFlag(CONSTANTS.ITEM_PILES_MODULE, "data") : {});
+ return foundry.utils.mergeObject(defaults, actorFlags);
}
export function getCurrencies(actor) {
- const flags = getAuctioneerActorFlags(actor);
+ const flags = getAuctioneerActorFlags(actor);
- const defaultCurrencies = foundry.utils.deepClone(game.itempiles.API.CURRENCIES).map(currency => {
- currency.quantity = 0;
- currency.secondary = false;
- return currency;
- });
+ const defaultCurrencies = foundry.utils.deepClone(game.itempiles.API.CURRENCIES).map(currency => {
+ currency.quantity = 0;
+ currency.secondary = false;
+ return currency;
+ });
- const secondaryCurrencies = flags.allowSecondaryCurrencies
- ? foundry.utils.deepClone(game.itempiles.API.SECONDARY_CURRENCIES).map(currency => {
- currency.quantity = 0;
- currency.secondary = true;
- return currency;
- })
- : [];
+ const secondaryCurrencies = flags.allowSecondaryCurrencies
+ ? foundry.utils.deepClone(game.itempiles.API.SECONDARY_CURRENCIES).map(currency => {
+ currency.quantity = 0;
+ currency.secondary = true;
+ return currency;
+ })
+ : [];
- return defaultCurrencies.concat(secondaryCurrencies);
+ return defaultCurrencies.concat(secondaryCurrencies);
}
export function turnCurrenciesIntoString(currencies, abbreviate = false) {
- return currencies.filter(currencies => currencies.quantity)
- .reduce((acc, currency) => {
- const quantity = abbreviate ? abbreviateNumbers(currency.quantity) + " " : currency.quantity;
- return `${acc} ${currency.abbreviation.replace('{#}', quantity)}`;
- }, "").trim();
+ return currencies.filter(currencies => currencies.quantity)
+ .reduce((acc, currency) => {
+ const quantity = abbreviate ? abbreviateNumbers(currency.quantity) + " " : currency.quantity;
+ return `${acc} ${currency.abbreviation.replace('{#}', quantity)}`;
+ }, "").trim();
}
export function isPriceHigherThan(priceDataA, priceDataB) {
- if (priceDataA.primary) {
- return priceDataA.totalPrice >= priceDataB.totalPrice;
- }
- const mixedPrices = priceDataB.currencies.map(currencyB => {
- const currencyA = priceDataA.currencies.find(currencyA => currencyA.id === currencyB.id) ?? { quantity: -Infinity };
- return [currencyA, currencyB];
- })
- return mixedPrices.some(([currencyA, currencyB]) => currencyA.quantity >= currencyB.quantity);
+ if (priceDataA.primary) {
+ return priceDataA.totalPrice >= priceDataB.totalPrice;
+ }
+ const mixedPrices = priceDataB.currencies.map(currencyB => {
+ const currencyA = priceDataA.currencies.find(currencyA => currencyA.id === currencyB.id) ?? { quantity: -Infinity };
+ return [currencyA, currencyB];
+ })
+ return mixedPrices.some(([currencyA, currencyB]) => currencyA.quantity >= currencyB.quantity);
}
const DATE_REGEX = new RegExp("^(\\d+)(\\w+)$", "g")
export function evaluateFoundryTime(auctioneer, duration = "now") {
- const flags = getAuctioneerActorFlags(auctioneer);
-
- if (flags.timeType === CONSTANTS.AUCTION_TIME_TYPE_KEYS.REAL_TIME || !window?.SimpleCalendar?.api) {
- if (duration === "now") return Date.now();
- const parts = [...duration.matchAll(DATE_REGEX)];
- const [_, number, dateType] = parts[0];
- return moment().add(Number(number), dateType).valueOf();
- }
-
- const currentTimestamp = window?.SimpleCalendar.api.timestamp();
- if (duration === "now") return currentTimestamp;
-
- const parts = [...duration.matchAll(DATE_REGEX)];
- const [_, number, dateType] = parts[0];
-
- const newDateType = {
- "minutes": "minute",
- "hours": "hour",
- "days": "day",
- "months": "month",
- "years": "year",
- }[dateType] ?? dateType;
-
- return window?.SimpleCalendar.api.timestampPlusInterval(currentTimestamp, {
- [newDateType]: Number(number)
- });
+ const flags = getAuctioneerActorFlags(auctioneer);
+
+ if (flags.timeType === CONSTANTS.AUCTION_TIME_TYPE_KEYS.REAL_TIME || !window?.SimpleCalendar?.api) {
+ if (duration === "now") return Date.now();
+ const parts = [...duration.matchAll(DATE_REGEX)];
+ const [_, number, dateType] = parts[0];
+ return moment().add(Number(number), dateType).valueOf();
+ }
+
+ const currentTimestamp = window?.SimpleCalendar.api.timestamp();
+ if (duration === "now") return currentTimestamp;
+
+ const parts = [...duration.matchAll(DATE_REGEX)];
+ const [_, number, dateType] = parts[0];
+
+ const newDateType = {
+ "minutes": "minute",
+ "hours": "hour",
+ "days": "day",
+ "months": "month",
+ "years": "year",
+ }[dateType] ?? dateType;
+
+ return window?.SimpleCalendar.api.timestampPlusInterval(currentTimestamp, {
+ [newDateType]: Number(number)
+ });
}
export function dateTimeToString(auctioneer, datetime, relative = false) {
- const flags = getAuctioneerActorFlags(auctioneer);
+ const flags = getAuctioneerActorFlags(auctioneer);
- if (flags.timeType === CONSTANTS.AUCTION_TIME_TYPE_KEYS.REAL_TIME || !window?.SimpleCalendar?.api) {
- const diffDate = moment(datetime);
- return relative ? capitalize(moment.duration(diffDate.diff(moment())).humanize()) : diffDate.format("Y-M-D - HH:mm:ss")
- }
+ if (flags.timeType === CONSTANTS.AUCTION_TIME_TYPE_KEYS.REAL_TIME || !window?.SimpleCalendar?.api) {
+ const diffDate = moment(datetime);
+ return relative ? capitalize(moment.duration(diffDate.diff(moment())).humanize()) : diffDate.format("Y-M-D - HH:mm:ss")
+ }
- if (relative) {
- const currentTimestamp = window?.SimpleCalendar.api.timestamp();
- const interval = Object.entries(window?.SimpleCalendar.api.secondsToInterval(datetime - currentTimestamp)).filter(e => e[1])
- const biggestInterval = interval[interval.length - 1];
- let [label, value] = biggestInterval;
- label = pluralize(label, value > 1);
- return `${value} ${label}`
- }
+ if (relative) {
+ const currentTimestamp = window?.SimpleCalendar.api.timestamp();
+ const interval = Object.entries(window?.SimpleCalendar.api.secondsToInterval(datetime - currentTimestamp)).filter(e => e[1])
+ const biggestInterval = interval[interval.length - 1];
+ let [label, value] = biggestInterval;
+ label = pluralize(label, value > 1);
+ return `${value} ${label}`
+ }
- const timestamp = window?.SimpleCalendar.api.timestampToDate(datetime);
- return `${timestamp.display.year}-${timestamp.display.month}-${timestamp.display.day} - ${timestamp.display.time}`;
+ const timestamp = window?.SimpleCalendar.api.timestampToDate(datetime);
+ return `${timestamp.display.year}-${timestamp.display.month}-${timestamp.display.day} - ${timestamp.display.time}`;
}
function capitalize(str) {
- return str.slice(0, 1).toUpperCase() + str.slice(1);
+ return str.slice(0, 1).toUpperCase() + str.slice(1);
}
function pluralize(str, doPluralize = true) {
- if (doPluralize) {
- return str.endsWith("s") ? str : str + "s";
- }
- return str.endsWith("s") ? str.slice(0, -1) : str;
+ if (doPluralize) {
+ return str.endsWith("s") ? str : str + "s";
+ }
+ return str.endsWith("s") ? str.slice(0, -1) : str;
}
export function getUserAuctions(user = false) {
- if (!user) user = game.user;
- return foundry.utils.deepClone(user.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.AUCTIONS_FLAG) ?? []);
+ if (!user) user = game.user;
+ return foundry.utils.deepClone(user.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.AUCTIONS_FLAG) ?? []);
}
export function getUserBids(user = false) {
- if (!user) user = game.user;
- return foundry.utils.deepClone(user.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BIDS_FLAG) ?? []);
+ if (!user) user = game.user;
+ return foundry.utils.deepClone(user.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BIDS_FLAG) ?? []);
}
export function getUserBuyouts(user = false) {
- if (!user) user = game.user;
- return foundry.utils.deepClone(user.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BUYOUTS_FLAG) ?? []);
+ if (!user) user = game.user;
+ return foundry.utils.deepClone(user.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BUYOUTS_FLAG) ?? []);
}
export function getItemColorElement(item) {
- const color = game.modules.get("rarity-colors")?.active && game.modules.get("rarity-colors")?.api
- ? game.modules.get("rarity-colors").api.getColorFromItem(item)
- : false;
- const rarity = capitalize(CONFIG?.DND5E?.itemRarity?.[item?.system?.rarity] ?? "");
- return color ? `
` : "";
+ const color = game.modules.get("rarity-colors")?.active && game.modules.get("rarity-colors")?.api
+ ? game.modules.get("rarity-colors").api.getColorFromItem(item)
+ : false;
+ const rarity = capitalize(CONFIG?.DND5E?.itemRarity?.[item?.system?.rarity] ?? "");
+ return color ? `
` : "";
}
export function evaluateFormula(formula, data, warn = false) {
- const rollFormula = Roll.replaceFormulaData(formula, data, { warn });
- return new Roll(rollFormula).evaluate({ async: false });
+ const rollFormula = Roll.replaceFormulaData(formula, data, { warn });
+ return new Roll(rollFormula).evaluate({ async: false });
}
export function isActiveGM(user) {
- return user.active && user.isGM;
+ return user.active && user.isGM;
}
export function getActiveGMs() {
- return game.users.filter(isActiveGM);
+ return game.users.filter(isActiveGM);
}
export function isResponsibleGM() {
- if (!game.user.isGM) {
- return false;
- }
- return !getActiveGMs().some(other => other.id < game.user.id);
+ if (!game.user.isGM) {
+ return false;
+ }
+ return !getActiveGMs().some(other => other.id < game.user.id);
}
-function cleanUserFlags(acc, entry, flagPath){
- const userEntries = acc[entry.userId] ?? game.users.get(entry.userId).getFlag(CONSTANTS.MODULE_NAME, flagPath);
- if (userEntries.length) {
- const auctionIndex = userEntries.findIndex(userAuction => userAuction.uuid === entry.uuid);
- userEntries.splice(auctionIndex, 1);
- acc[entry.userId] = {
- [`flags.${CONSTANTS.MODULE_NAME}.${flagPath}`]: userEntries
- };
- }
- return acc;
+function cleanUserFlags(acc, entry, flagPath) {
+ const userEntries = acc[entry.userId] ?? game.users.get(entry.userId).getFlag(CONSTANTS.MODULE_NAME, flagPath);
+ if (userEntries.length) {
+ const auctionIndex = userEntries.findIndex(userAuction => userAuction.uuid === entry.uuid);
+ userEntries.splice(auctionIndex, 1);
+ acc[entry.userId] = {
+ [`flags.${CONSTANTS.MODULE_NAME}.${flagPath}`]: userEntries
+ };
+ }
+ return acc;
}
-export function getLogs(auctioneer, { auctions = [], bids = [], buyouts = [] } = {}) {
-
- const claimedAuctions = auctions.filter(auction => auction.claimed).length > 50
- ? auctions.filter(auction => auction.claimed).slice(0, 25).map(auction => auction._source)
- : []
- const claimedBids = bids.filter(bid => bid.claimed).length > 50
- ? bids.filter(bid => bid.claimed).slice(0, 25).map(bid => bid._source)
- : [];
- const claimedBuyouts = buyouts.filter(buyout => buyout.claimed).length > 50
- ? buyouts.filter(buyout => buyout.claimed).slice(0, 25).map(buyout => buyout._source)
- : [];
-
- const maps = {
- auctions: {},
- bids: {},
- buyouts: {}
- };
- const auctioneerAuctionsData = auctioneer.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.AUCTIONS_FLAG) ?? [];
- const auctioneerAuctions = auctioneerAuctionsData.map(source => {
- const auction = makeAuction(auctioneer, source);
- maps.auctions[auction.uuid] = auction;
- return auction;
- });
-
- const auctioneerBidsData = auctioneer.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BIDS_FLAG) ?? [];
- const auctioneerBids = auctioneerBidsData.map(source => {
- const bid = makeBid(auctioneer, source, maps.auctions);
- maps.bids[bid.id] = bid;
- return bid;
- });
-
- const auctioneerBuyoutsData = auctioneer.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BUYOUTS_FLAG) ?? [];
- const auctioneerBuyouts = auctioneerBuyoutsData.map(source => {
- const buyout = makeBuyout(auctioneer, source, maps.auctions);
- maps.buyouts[buyout.id] = buyout;
- return buyout;
- });
-
- const actorUpdates = {};
- if(claimedAuctions.length) {
- if(!actorUpdates["_id"]) actorUpdates["_id"] = auctioneer.id;
- actorUpdates[CONSTANTS.AUCTIONS_FULL_FLAG] = auctioneerAuctionsData.concat(claimedAuctions)
- }
- if(claimedBids.length) {
- if(!actorUpdates["_id"]) actorUpdates["_id"] = auctioneer.id;
- actorUpdates[CONSTANTS.BIDS_FULL_FLAG] = auctioneerBidsData.concat(claimedBids)
- }
- if(claimedBuyouts.length) {
- if(!actorUpdates["_id"]) actorUpdates["_id"] = auctioneer.id;
- actorUpdates[CONSTANTS.BUYOUTS_FULL_FLAG] = auctioneerBuyoutsData.concat(claimedBuyouts)
- }
-
- let userUpdates = {};
- const userAuctionUpdates = claimedAuctions.reduce((acc, auction) => {
- return cleanUserFlags(acc, auction, CONSTANTS.AUCTIONS_FLAG);
- }, {});
- if(!foundry.utils.isEmpty(userAuctionUpdates)) {
- userUpdates = foundry.utils.mergeObject(userUpdates, userAuctionUpdates);
- }
-
- const userBidUpdates = claimedBids.reduce((acc, bid) => {
- return cleanUserFlags(acc, bid, CONSTANTS.BIDS_FLAG);
- }, {})
- if(!foundry.utils.isEmpty(userBidUpdates)) {
- userUpdates = foundry.utils.mergeObject(userUpdates, userBidUpdates);
- }
-
- const userBuyoutUpdates = claimedBuyouts.reduce((acc, buyout) => {
- return cleanUserFlags(acc, buyout, CONSTANTS.BUYOUTS_FLAG);
- }, {})
- if(!foundry.utils.isEmpty(userBuyoutUpdates)) {
- userUpdates = foundry.utils.mergeObject(userUpdates, userBuyoutUpdates);
- }
-
- userUpdates = Object.entries(userUpdates).map(([userId, updates]) => {
- return {
- _id: userId,
- ...updates
- }
- })
-
- const currentDatetime = evaluateFoundryTime(auctioneer);
-
- const auctionLogsMap = auctions
- .concat(auctioneerAuctions)
- .reduce((acc, auction) => {
- if (!acc[auction.id]) {
- acc[auction.id] = {
- data: auction,
- type: "AuctionLog",
- id: auction.id,
- date: auction.date,
- visible: true
- };
- }
- if (auction.expired && !auction.cancelled) {
- if (!auction.won && !acc[auction.id + "-expired"]) {
- acc[auction.id + "-expired"] = {
- data: auction,
- type: "ExpiredAuctionLog",
- id: auction.id + "-expired",
- date: auction.expiryDate,
- visible: true
- };
- }
- if (auction.claimed && currentDatetime >= auction.claimedDate && !acc[auction.id + "-claimed"]) {
- acc[auction.id + "-claimed"] = {
- data: auction,
- type: "ClaimedAuctionLog",
- id: auction.id + "-claimed",
- date: auction.claimedDate,
- visible: true
- };
- }
- }
- if (auction.cancelled && auction.claimed && currentDatetime >= auction.claimedDate && !acc[auction.id + "-cancelled"]) {
- acc[auction.id + "-cancelled"] = {
- data: auction,
- type: "CancelledAuctionLog",
- id: auction.id + "-cancelled",
- date: auction.claimedDate,
- visible: true
- };
- }
- return acc;
- }, {})
-
- const auctionLogs = Object.values(auctionLogsMap);
- const bidLogs = Object.values(bids.concat(auctioneerBids).reduce((acc, bid) => {
- if(acc[bid.id]) return acc;
- acc[bid.id] = {
- data: bid,
- type: "BidLog",
- id: bid.id,
- date: bid.date,
- visible: true
- }
- return acc;
- }, {}));
- const buyoutLogs = Object.values(buyouts.concat(auctioneerBuyouts).reduce((acc, buyout) => {
- if(acc[buyout.id]) return acc;
- acc[buyout.id] = {
- data: buyout,
- type: "BuyoutLog",
- id: buyout.id,
- date: buyout.date,
- visible: true
- }
- return acc;
- }, {}));
-
- return {
- logs: auctionLogs
- .concat(bidLogs)
- .concat(buyoutLogs)
- .map((entry, index) => ({
- index, ...entry
- }))
- .sort((a, b) => {
- return b.date === a.date ? b.index - a.index : b.date - a.date;
- }),
- userUpdates,
- actorUpdates
- };
+export function getLogData(auctioneer, { auctions = [], bids = [], buyouts = [] } = {}) {
+
+ const claimedAuctions = auctions.filter(auction => auction.claimed).map(auction => auction._source);
+ const claimedBids = bids.filter(bid => bid.claimed).map(bid => bid._source);
+ const claimedBuyouts = buyouts.filter(buyout => buyout.claimed).map(buyout => buyout._source);
+
+ const maps = {
+ auctions: {},
+ bids: {},
+ buyouts: {}
+ };
+ const auctioneerAuctionsData = auctioneer.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.AUCTIONS_FLAG) ?? [];
+ const auctioneerAuctions = auctioneerAuctionsData.map(source => {
+ const auction = makeAuction(auctioneer, source);
+ maps.auctions[auction.uuid] = auction;
+ return auction;
+ });
+
+ const auctioneerBidsData = auctioneer.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BIDS_FLAG) ?? [];
+ const auctioneerBids = auctioneerBidsData.map(source => {
+ const bid = makeBid(auctioneer, source, maps.auctions);
+ maps.bids[bid.id] = bid;
+ return bid;
+ });
+
+ const auctioneerBuyoutsData = auctioneer.getFlag(CONSTANTS.MODULE_NAME, CONSTANTS.BUYOUTS_FLAG) ?? [];
+ const auctioneerBuyouts = auctioneerBuyoutsData.map(source => {
+ const buyout = makeBuyout(auctioneer, source, maps.auctions);
+ maps.buyouts[buyout.id] = buyout;
+ return buyout;
+ });
+
+ let recipientCurrencies = "";
+ const flags = getAuctioneerActorFlags(auctioneer);
+ const actorUpdates = {};
+ if (claimedAuctions.length) {
+
+ if (!actorUpdates["_id"]) actorUpdates["_id"] = auctioneer.id;
+ actorUpdates[CONSTANTS.AUCTIONS_FULL_FLAG] = auctioneerAuctionsData.concat(claimedAuctions)
+
+ for (const claimedAuction of claimedAuctions) {
+ if (!claimedAuction.won) {
+ recipientCurrencies = recipientCurrencies
+ ? game.itempiles.API.calculateCurrencies(recipientCurrencies, claimedAuction.depositPrice, false)
+ : claimedAuction.depositPrice;
+ } else if (flags.auctionFee) {
+ const auctionFee = Math.max(0, flags.auctionFee ?? 0);
+ const fee = game.itempiles.API.calculateCurrencies(price, auctionFee / 100);
+ recipientCurrencies = recipientCurrencies
+ ? game.itempiles.API.calculateCurrencies(recipientCurrencies, fee, false)
+ : fee;
+ }
+ }
+ }
+ if (claimedBids.length) {
+ if (!actorUpdates["_id"]) actorUpdates["_id"] = auctioneer.id;
+ actorUpdates[CONSTANTS.BIDS_FULL_FLAG] = auctioneerBidsData.concat(claimedBids)
+ }
+ if (claimedBuyouts.length) {
+ if (!actorUpdates["_id"]) actorUpdates["_id"] = auctioneer.id;
+ actorUpdates[CONSTANTS.BUYOUTS_FULL_FLAG] = auctioneerBuyoutsData.concat(claimedBuyouts)
+ }
+
+ let userUpdates = {};
+ const userAuctionUpdates = claimedAuctions.reduce((acc, auction) => {
+ return cleanUserFlags(acc, auction, CONSTANTS.AUCTIONS_FLAG);
+ }, {});
+ if (!foundry.utils.isEmpty(userAuctionUpdates)) {
+ userUpdates = foundry.utils.mergeObject(userUpdates, userAuctionUpdates);
+ }
+
+ const userBidUpdates = claimedBids.reduce((acc, bid) => {
+ return cleanUserFlags(acc, bid, CONSTANTS.BIDS_FLAG);
+ }, {})
+ if (!foundry.utils.isEmpty(userBidUpdates)) {
+ userUpdates = foundry.utils.mergeObject(userUpdates, userBidUpdates);
+ }
+
+ const userBuyoutUpdates = claimedBuyouts.reduce((acc, buyout) => {
+ return cleanUserFlags(acc, buyout, CONSTANTS.BUYOUTS_FLAG);
+ }, {})
+ if (!foundry.utils.isEmpty(userBuyoutUpdates)) {
+ userUpdates = foundry.utils.mergeObject(userUpdates, userBuyoutUpdates);
+ }
+
+ userUpdates = Object.entries(userUpdates).map(([userId, updates]) => {
+ return {
+ _id: userId,
+ ...updates
+ }
+ })
+
+ const currentDatetime = evaluateFoundryTime(auctioneer);
+
+ const auctionLogsMap = auctions
+ .concat(auctioneerAuctions)
+ .reduce((acc, auction) => {
+ if (!acc[auction.id]) {
+ acc[auction.id] = {
+ data: auction,
+ type: "AuctionLog",
+ id: auction.id,
+ date: auction.date,
+ visible: true
+ };
+ }
+ if (auction.expired && !auction.cancelled) {
+ if (!auction.won && !acc[auction.id + "-expired"]) {
+ acc[auction.id + "-expired"] = {
+ data: auction,
+ type: "ExpiredAuctionLog",
+ id: auction.id + "-expired",
+ date: auction.expiryDate,
+ visible: true
+ };
+ }
+ if (auction.claimed && currentDatetime >= auction.claimedDate && !acc[auction.id + "-claimed"]) {
+ acc[auction.id + "-claimed"] = {
+ data: auction,
+ type: "ClaimedAuctionLog",
+ id: auction.id + "-claimed",
+ date: auction.claimedDate,
+ visible: true
+ };
+ }
+ }
+ if (auction.cancelled && auction.claimed && currentDatetime >= auction.claimedDate && !acc[auction.id + "-cancelled"]) {
+ acc[auction.id + "-cancelled"] = {
+ data: auction,
+ type: "CancelledAuctionLog",
+ id: auction.id + "-cancelled",
+ date: auction.claimedDate,
+ visible: true
+ };
+ }
+ return acc;
+ }, {})
+
+ const auctionLogs = Object.values(auctionLogsMap);
+ const bidLogs = Object.values(bids.concat(auctioneerBids).reduce((acc, bid) => {
+ if (acc[bid.id]) return acc;
+ acc[bid.id] = {
+ data: bid,
+ type: "BidLog",
+ id: bid.id,
+ date: bid.date,
+ visible: true
+ }
+ return acc;
+ }, {}));
+ const buyoutLogs = Object.values(buyouts.concat(auctioneerBuyouts).reduce((acc, buyout) => {
+ if (acc[buyout.id]) return acc;
+ acc[buyout.id] = {
+ data: buyout,
+ type: "BuyoutLog",
+ id: buyout.id,
+ date: buyout.date,
+ visible: true
+ }
+ return acc;
+ }, {}));
+
+ return {
+ logs: auctionLogs
+ .concat(bidLogs)
+ .concat(buyoutLogs)
+ .map((entry, index) => ({
+ index, ...entry
+ }))
+ .sort((a, b) => {
+ return b.date === a.date ? b.index - a.index : b.date - a.date;
+ }),
+ userUpdates,
+ actorUpdates,
+ recipientCurrencies
+ };
}
export function makeAuction(auctioneer, source) {
- const auction = {};
- auction._source = foundry.utils.mergeObject(foundry.utils.deepClone(CONSTANTS.DEFAULTS.AUCTION), source);
- auction.type = "auction";
- auction.id = auction._source.id;
- auction.uuid = auction._source.uuid;
- auction.cancelled = auction._source.cancelled;
- auction.claimed = auction._source.claimed;
- auction.gmClaimed = auction._source.gmClaimed;
- auction.item = new Item.implementation(auction._source.itemData)
- auction.user = game.users.get(auction._source.userId);
- auction.actor = auction._source.actorUuid ? fromUuidSync(auction._source.actorUuid) : false;
- auction.date = auction._source.date;
- auction.claimedDate = auction._source.claimedDate;
- auction.expiryDate = auction._source.expiryDate;
- auction.expired = evaluateFoundryTime(auctioneer) >= auction._source.expiryDate;
- auction.timeLeft = dateNumberToRelativeString(auctioneer, auction._source.expiryDate);
- auction.quantity = auction._source.quantity;
- auction.bidVisibility = auction._source.bidVisibility;
- auction.startPrice = auction._source.startPrice;
- auction.buyoutPrice = auction._source.buyoutPrice;
- auction.reservePrice = auction._source.reservePrice;
- auction.minBidPrice = auction._source.minBidPrice;
- auction.depositPrice = auction._source.depositPrice;
-
- auction.startPriceData = getPriceFromData(auction._source.startPrice);
- auction.buyoutPriceData = getPriceFromData(auction._source.buyoutPrice);
- auction.reservePriceData = getPriceFromData(auction._source.reservePrice);
- auction.minBidPriceData = getPriceFromData(auction._source.minBidPrice);
- auction.depositPriceData = getPriceFromData(auction._source.depositPrice);
-
- auction.won = false;
- auction.bids = [];
- auction.bidPriceData = false;
- auction.highestOwnedBid = false;
- return auction;
+ const auction = {};
+ auction._source = foundry.utils.mergeObject(foundry.utils.deepClone(CONSTANTS.DEFAULTS.AUCTION), source);
+ auction.type = "auction";
+ auction.id = auction._source.id;
+ auction.uuid = auction._source.uuid;
+ auction.cancelled = auction._source.cancelled;
+ auction.claimed = auction._source.claimed;
+ auction.gmClaimed = auction._source.gmClaimed;
+ auction.item = new Item.implementation(auction._source.itemData)
+ auction.user = game.users.get(auction._source.userId);
+ auction.actor = auction._source.actorUuid ? fromUuidSync(auction._source.actorUuid) : false;
+ auction.date = auction._source.date;
+ auction.claimedDate = auction._source.claimedDate;
+ auction.expiryDate = auction._source.expiryDate;
+ auction.expired = evaluateFoundryTime(auctioneer) >= auction._source.expiryDate;
+ auction.timeLeft = dateNumberToRelativeString(auctioneer, auction._source.expiryDate);
+ auction.quantity = auction._source.quantity;
+ auction.bidVisibility = auction._source.bidVisibility;
+ auction.startPrice = auction._source.startPrice;
+ auction.buyoutPrice = auction._source.buyoutPrice;
+ auction.reservePrice = auction._source.reservePrice;
+ auction.minBidPrice = auction._source.minBidPrice;
+ auction.depositPrice = auction._source.depositPrice;
+
+ auction.startPriceData = getPriceFromData(auction._source.startPrice);
+ auction.buyoutPriceData = getPriceFromData(auction._source.buyoutPrice);
+ auction.reservePriceData = getPriceFromData(auction._source.reservePrice);
+ auction.minBidPriceData = getPriceFromData(auction._source.minBidPrice);
+ auction.depositPriceData = getPriceFromData(auction._source.depositPrice);
+
+ auction.won = false;
+ auction.bids = [];
+ auction.bidPriceData = false;
+ auction.highestOwnedBid = false;
+ return auction;
}
export function makeBuyout(auctioneer, source, auctions) {
- const buyout = {};
- buyout._source = foundry.utils.mergeObject(foundry.utils.deepClone(CONSTANTS.DEFAULTS.BUYOUT), source);
- buyout.type = "buyout";
- buyout.id = buyout._source.id;
- buyout.date = buyout._source.date;
- buyout.user = game.users.get(buyout._source.userId);
- buyout.actor = buyout._source.actorUuid ? fromUuidSync(buyout._source.actorUuid) : false;
- buyout.priceData = getPriceFromData(buyout._source.price);
- buyout.price = buyout._source.price;
- buyout.claimed = buyout._source.claimed;
- buyout.auctionUuid = buyout._source.auctionUuid;
- buyout.auction = auctions[buyout._source.auctionUuid];
- buyout.auction.won = buyout;
- return buyout;
+ const buyout = {};
+ buyout._source = foundry.utils.mergeObject(foundry.utils.deepClone(CONSTANTS.DEFAULTS.BUYOUT), source);
+ buyout.type = "buyout";
+ buyout.id = buyout._source.id;
+ buyout.date = buyout._source.date;
+ buyout.user = game.users.get(buyout._source.userId);
+ buyout.actor = buyout._source.actorUuid ? fromUuidSync(buyout._source.actorUuid) : false;
+ buyout.priceData = getPriceFromData(buyout._source.price);
+ buyout.price = buyout._source.price;
+ buyout.claimed = buyout._source.claimed;
+ buyout.auctionUuid = buyout._source.auctionUuid;
+ buyout.auction = auctions[buyout._source.auctionUuid];
+ buyout.auction.won = buyout;
+ return buyout;
}
export function makeBid(auctioneer, source, auctions) {
- const bid = {};
- bid._source = foundry.utils.mergeObject(foundry.utils.deepClone(CONSTANTS.DEFAULTS.BID), source);
- bid.type = "bid";
- bid.id = bid._source.id;
- bid.date = bid._source.date;
- bid.user = game.users.get(bid._source.userId);
- bid.actor = bid._source.actorUuid ? fromUuidSync(bid._source.actorUuid) : false;
- bid.priceData = getPriceFromData(bid._source.price);
- bid.price = bid._source.price;
- bid.claimed = bid._source.claimed;
- bid.bidStatus = { value: -Infinity, label: "Low Bid" };
- bid.auctionUuid = bid._source.auctionUuid;
- bid.auction = auctions[bid._source.auctionUuid];
- bid.auction.bids.push(bid);
- return bid;
+ const bid = {};
+ bid._source = foundry.utils.mergeObject(foundry.utils.deepClone(CONSTANTS.DEFAULTS.BID), source);
+ bid.type = "bid";
+ bid.id = bid._source.id;
+ bid.date = bid._source.date;
+ bid.user = game.users.get(bid._source.userId);
+ bid.actor = bid._source.actorUuid ? fromUuidSync(bid._source.actorUuid) : false;
+ bid.priceData = getPriceFromData(bid._source.price);
+ bid.price = bid._source.price;
+ bid.claimed = bid._source.claimed;
+ bid.bidStatus = { value: -Infinity, label: "Low Bid" };
+ bid.auctionUuid = bid._source.auctionUuid;
+ bid.auction = auctions[bid._source.auctionUuid];
+ bid.auction.bids.push(bid);
+ return bid;
+}
+
+export async function migrateData(auctioneer = false) {
+
+ if (!game.user.isGM) return;
+
+ const auctioneersActors = auctioneer ? [auctioneer] : game.actors
+ .filter(actor => {
+ return actor.getFlag("item-piles", 'data')?.type === CONSTANTS.AUCTIONEER;
+ })
+
+ const auctioneers = auctioneersActors
+ .map(auctioneer => {
+ const auctioneerData = getAuctioneerActorData(auctioneer);
+ const flags = getAuctioneerActorFlags(auctioneer);
+ const { userUpdates, actorUpdates, recipientCurrencies } = getLogData(auctioneer, auctioneerData);
+ const recipient = flags.owner?.uuid ? fromUuidSync(flags.owner?.uuid) ?? auctioneer : auctioneer;
+ return {
+ id: auctioneer.id,
+ userUpdates,
+ actorUpdates,
+ recipientCurrencies,
+ recipient
+ }
+ })
+ .filter(data => {
+ return !foundry.utils.isEmpty(data.actorUpdates) || data.userUpdates.length || data.recipientCurrencies;
+ });
+
+ if (!auctioneers.length) return;
+
+ const actorUpdates = auctioneers.map(auctioneer => auctioneer.actorUpdates);
+ const userUpdates = auctioneers.map(auctioneer => auctioneer.userUpdates)
+ .deepFlatten()
+ .reduce((acc, update) => {
+ const foundIndex = acc.findIndex(pastUpdate => pastUpdate._id === update._id);
+ if (foundIndex > -1) {
+ acc[foundIndex] = foundry.utils.mergeObject(acc[foundIndex], update);
+ } else {
+ acc.push(update);
+ }
+ return acc;
+ }, []);
+
+ await Actor.updateDocuments(actorUpdates)
+ await User.updateDocuments(userUpdates);
+ for (const auctioneer of auctioneers) {
+ if (!auctioneer.recipientCurrencies) continue;
+ await game.itempiles.API.addCurrencies(auctioneer.recipient, auctioneer.recipientCurrencies);
+ }
+
}
diff --git a/src/module.js b/src/module.js
index 8f94eab..e8cfe0f 100644
--- a/src/module.js
+++ b/src/module.js
@@ -1,48 +1,10 @@
import "./styles/styles.scss";
import CONSTANTS from "./constants.js";
import * as lib from "./lib.js";
-import { getAuctioneerActorData } from "~/applications/auctioneer/auctioneer-store.js";
Hooks.once("ready", () => {
document.documentElement.style.setProperty("--item-piles-auctioneer-ui-height", `${CONSTANTS.AUCTION_UI_HEIGHT}px`);
Hooks.on(game.itempiles.hooks.PRE_RENDER_INTERFACE, lib.auctioneerRendered);
game.itempiles.API.registerItemPileType(CONSTANTS.AUCTIONEER, "Auctioneer", CONSTANTS.AUCTIONEER_SETTINGS);
- migrateData();
+ if (lib.isResponsibleGM()) lib.migrateData();
});
-
-async function migrateData() {
- if(!lib.isResponsibleGM()) return;
- const auctioneers = game.actors
- .filter(actor => {
- return actor.getFlag("item-piles", 'data')?.type === CONSTANTS.AUCTIONEER;
- })
- .map(auctioneer => {
- const auctioneerData = getAuctioneerActorData(auctioneer);
- const { userUpdates, actorUpdates } = lib.getLogs(auctioneer, auctioneerData);
- return {
- id: auctioneer.id,
- userUpdates,
- actorUpdates
- }
- })
- .filter(auctioneer => {
- return !foundry.utils.isEmpty(auctioneer.actorUpdates) || auctioneer.userUpdates.length;
- });
- if(!auctioneers.length) return;
-
- const actorUpdates = auctioneers.map(auctioneer => auctioneer.actorUpdates);
- const userUpdates = auctioneers.map(auctioneer => auctioneer.userUpdates)
- .deepFlatten()
- .reduce((acc, update) => {
- const foundIndex = acc.findIndex(pastUpdate => pastUpdate._id === update._id);
- if(foundIndex > -1){
- acc[foundIndex] = foundry.utils.mergeObject(acc[foundIndex], update);
- }else{
- acc.push(update);
- }
- return acc;
- }, []);
-
- await Actor.updateDocuments(actorUpdates)
- await User.updateDocuments(userUpdates);
-}
diff --git a/src/styles/styles.scss b/src/styles/styles.scss
index e17ef58..18e10dc 100644
--- a/src/styles/styles.scss
+++ b/src/styles/styles.scss
@@ -10,15 +10,15 @@
display: grid;
&.browse {
- grid-template-columns: 555px 85px 110px 77px 150px;
+ grid-template-columns: 553px 85px 110px 79px 150px;
}
&.bids {
- grid-template-columns: 401px 85px 150px 77px 110px 155px;
+ grid-template-columns: 399px 85px 150px 79px 110px 155px;
}
&.auctions {
- grid-template-columns: 340px 85px 100px 77px 165px;
+ grid-template-columns: 338px 85px 100px 79px 165px;
}
&.wins {
@@ -34,6 +34,13 @@
padding: 0.15rem;
--tjs-app-overflow: visible;
+ &.sheet {
+ max-width: 1000px;
+ max-height: var(--item-piles-auctioneer-ui-height);
+ min-width: 1000px;
+ min-height: var(--item-piles-auctioneer-ui-height);
+ }
+
&.dialog .dialog-content {
text-align: center;
@@ -150,7 +157,7 @@
.item-row {
align-items: center;
- font-size: 0.8rem;
+ font-size: 0.875rem;
height: 38px;
cursor: pointer;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
@@ -199,7 +206,7 @@
.auction-entry-text {
display: flex;
justify-content: center;
- font-size: 0.75rem;
+ font-size: 0.875rem;
text-align: center;
word-break: break-word;
@@ -322,7 +329,7 @@
align-items: center;
width: 100%;
- &.small-warning{
+ &.small-warning {
font-size: 0.75rem;
color: #640000;
text-align: center;
@@ -365,7 +372,7 @@
padding: 0.15rem;
border: var(--item-piles-auctioneer-border);
border-radius: var(--item-piles-auctioneer-border-radius);
- font-size: 0.8rem;
+ font-size: 0.875rem;
width: 100%;
background-color: #cbc9bc;
@@ -423,7 +430,7 @@
grid-template-columns: 1fr 1fr;
.auction-title {
- font-size: 0.8rem;
+ font-size: 0.875rem;
i {
margin-left: 0.25rem;
@@ -504,7 +511,6 @@
}
-
.log-entry {
display: flex;