From be816d89c97ea7618c55394706b106c79ee0fb6e Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 16:48:41 -0700
Subject: [PATCH 1/7] Waka item page UI!
---
src/app/ItemPage.js | 1 +
src/app/ItemPageLayout.js | 127 +++++++++++++++++++++++++++++++-------
src/app/ItemTradesPage.js | 1 +
3 files changed, 107 insertions(+), 22 deletions(-)
diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js
index 6b4c165..7384e12 100644
--- a/src/app/ItemPage.js
+++ b/src/app/ItemPage.js
@@ -74,6 +74,7 @@ export function ItemPageContent({ itemId, isEmbedded }) {
thumbnailUrl
description
createdAt
+ wakaValueText
# For Support users.
rarityIndex
diff --git a/src/app/ItemPageLayout.js b/src/app/ItemPageLayout.js
index 9caad8c..d8c9ee2 100644
--- a/src/app/ItemPageLayout.js
+++ b/src/app/ItemPageLayout.js
@@ -5,6 +5,7 @@ import {
Flex,
Popover,
PopoverArrow,
+ PopoverBody,
PopoverContent,
PopoverTrigger,
Portal,
@@ -12,10 +13,15 @@ import {
Skeleton,
Spinner,
Tooltip,
+ useBreakpointValue,
useToast,
VStack,
} from "@chakra-ui/react";
-import { ExternalLinkIcon, ChevronRightIcon } from "@chakra-ui/icons";
+import {
+ ExternalLinkIcon,
+ ChevronRightIcon,
+ QuestionIcon,
+} from "@chakra-ui/icons";
import { gql, useMutation } from "@apollo/client";
import {
@@ -150,6 +156,42 @@ function ItemPageBadges({ item, isEmbedded }) {
Jellyneo
+ {item.isNc && (
+
+ {item.wakaValueText && (
+ <>
+ {/* For hover-y devices, use a hover popover over the badge. */}
+
+
+
+ Waka: {item.wakaValueText}
+
+
+
+ {/* For touch-y devices, use a tappable help icon. */}
+
+
+ Waka: {item.wakaValueText}
+
+
+
+
+
+
+
+ >
+ )}
+
+ )}
{!item?.isNc && !item?.isPb && (
;
}
-function LinkBadge({ children, href, isEmbedded }) {
- return (
-
- {children}
- {
- // We also change the icon to signal whether this will launch in a new
- // window or not!
- isEmbedded ? :
- }
-
- );
-}
+const LinkBadge = React.forwardRef(
+ ({ children, href, isEmbedded, ...props }, ref) => {
+ return (
+
+ {children}
+ {
+ // We also change the icon to signal whether this will launch in a new
+ // window or not!
+ isEmbedded ? (
+
+ ) : (
+
+ )
+ }
+
+ );
+ }
+);
const fullDateFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "long",
@@ -380,4 +431,36 @@ function ShortTimestamp({ when }) {
);
}
+function WakaPopover({ children, ...props }) {
+ const placement = useBreakpointValue({ base: "bottom", md: "right" });
+
+ return (
+
+ {children}
+
+
+
+
+
+ Waka is a community resource that tracks the approximate value of
+ NC items, based on real-world trades.
+
+
+
+ Other factors, like rarity and popularity, can affect the trade
+ economy too—and it can change quickly!
+
+
+
+ Be sure to take all factors into account for your trades! And
+ consider asking for a "value check" on the Neoboards if you're not
+ sure.
+
+
+
+
+
+ );
+}
+
export default ItemPageLayout;
diff --git a/src/app/ItemTradesPage.js b/src/app/ItemTradesPage.js
index 75c4e5c..5120f98 100644
--- a/src/app/ItemTradesPage.js
+++ b/src/app/ItemTradesPage.js
@@ -102,6 +102,7 @@ function ItemTradesPage({
thumbnailUrl
description
createdAt
+ wakaValueText
}
}
`,
From 61e7a38b33b425bba3af969a60116e7a0cf61dbc Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 17:25:58 -0700
Subject: [PATCH 2/7] Normalize names for Waka, and log mismatches
By printing out this logging data, of item names we have that Waka doesn't, vs item names Waka has that we don't, I was able to solve a lot of them with new code in `normalizeItemName`!
Here's the mismatches that are left at time of writing:
```
[Item: Y, Waka: N] No Waka value for NC DTI item "goldenlulumedallion" (43034)
[Item: Y, Waka: N] No Waka value for NC DTI item "faelliebirthdaybagsurprise" (51350)
[Item: Y, Waka: N] No Waka value for NC DTI item "neopets11thbirthdaycommemorativemysterycapsule" (53448)
[Item: Y, Waka: N] No Waka value for NC DTI item "dyeworksblue:iscawig-blue" (70896)
[Item: Y, Waka: N] No Waka value for NC DTI item "mysteriousdoorwithlocks" (75601)
[Item: Y, Waka: N] No Waka value for NC DTI item "grapefruitnecklace" (77779)
[Item: Y, Waka: N] No Waka value for NC DTI item "discofeverbackground" (79250)
[Item: Y, Waka: N] No Waka value for NC DTI item "featherflaredshoes" (80047)
[Item: Y, Waka: N] No Waka value for NC DTI item "dyeworksredradioactivemutantmarkings" (80441)
[Item: N, Waka: Y] No NC DTI data for Waka item "7thbirthdaycakeslice#1"
[Item: N, Waka: Y] No NC DTI data for Waka item "7thbirthdaycakeslice#2"
[Item: N, Waka: Y] No NC DTI data for Waka item "7thbirthdaycakeslice#3"
[Item: N, Waka: Y] No NC DTI data for Waka item "8thbirthdayrainbowcupcake"
[Item: N, Waka: Y] No NC DTI data for Waka item "8thbirthdaysparklercupcake"
[Item: N, Waka: Y] No NC DTI data for Waka item "8thbirthdaytiedwithabowcupcake"
[Item: N, Waka: Y] No NC DTI data for Waka item "babyspringdress"
[Item: N, Waka: Y] No NC DTI data for Waka item "butterflydress(fromfaeriefestivalevent)"
[Item: N, Waka: Y] No NC DTI data for Waka item "discofever"
[Item: N, Waka: Y] No NC DTI data for Waka item "dyeworksblue:iscawig"
[Item: N, Waka: Y] No NC DTI data for Waka item "dyeworksred:radioactivemutantmarkings"
[Item: N, Waka: Y] No NC DTI data for Waka item "featherflairedshoes"
[Item: N, Waka: Y] No NC DTI data for Waka item "festivebooktree"
[Item: N, Waka: Y] No NC DTI data for Waka item "floralblackcardigan"
[Item: N, Waka: Y] No NC DTI data for Waka item "grapefruitneckace"
[Item: N, Waka: Y] No NC DTI data for Waka item "mysteriousdoorwithlocksbackground"
[Item: N, Waka: Y] No NC DTI data for Waka item "valiantchampionwings"
[Item: N, Waka: Y] No NC DTI data for Waka item "waxcrayonwig"
[Item: N, Waka: Y] No NC DTI data for Waka item "youngsophiesdress"
```
---
api/allWakaValues.js | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/api/allWakaValues.js b/api/allWakaValues.js
index 5cb9f15..1c50b04 100644
--- a/api/allWakaValues.js
+++ b/api/allWakaValues.js
@@ -30,6 +30,23 @@ async function handle(req, res) {
for (const { name, id } of allNcItemNamesAndIds) {
if (name in itemValuesByName) {
itemValues[id] = itemValuesByName[name];
+ } else {
+ console.warn(
+ `[Item: Y, Waka: N] No Waka value for NC DTI item ${JSON.stringify(
+ name
+ )} (${id})`
+ );
+ }
+ }
+
+ const allNcItemNames = new Set(allNcItemNamesAndIds.map(({ name }) => name));
+ for (const name of Object.keys(itemValuesByName)) {
+ if (!allNcItemNames.has(name)) {
+ console.warn(
+ `[Item: N, Waka: Y] No NC DTI data for Waka item ${JSON.stringify(
+ name
+ )}`
+ );
}
}
@@ -56,7 +73,7 @@ async function loadAllNcItemNamesAndIds() {
AND item_translations.locale = "en"
`);
- return rows;
+ return rows.map(({ id, name }) => ({ id, name: normalizeItemName(name) }));
}
async function loadWakaValuesByName() {
@@ -96,12 +113,27 @@ async function loadWakaValuesByName() {
// That's why we set `""` as the default `value`.
const itemValuesByName = {};
for (const [itemName, value = ""] of rows) {
- itemValuesByName[itemName] = { value };
+ const normalizedItemName = normalizeItemName(itemName);
+ itemValuesByName[normalizedItemName] = { value };
}
return itemValuesByName;
}
+function normalizeItemName(name) {
+ return (
+ name
+ // Remove all spaces, they're a common source of inconsistency
+ .replace(/\s+/g, "")
+ // Lower case, because capitalization is another common source
+ .toLowerCase()
+ // Remove diacritics: https://stackoverflow.com/a/37511463/107415
+ // Waka has some stray ones in item names, not sure why!
+ .normalize("NFD")
+ .replace(/[\u0300-\u036f]/g, "")
+ );
+}
+
export default async (req, res) => {
beeline.withTrace({ name: "allWakaValues" }, () => handle(req, res));
};
From 2b93e5cca79c5222c715dec459003bb87e0732be Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 17:37:38 -0700
Subject: [PATCH 3/7] Waka tooltip copy edits
---
src/app/ItemPageLayout.js | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/app/ItemPageLayout.js b/src/app/ItemPageLayout.js
index d8c9ee2..a8383f6 100644
--- a/src/app/ItemPageLayout.js
+++ b/src/app/ItemPageLayout.js
@@ -432,10 +432,8 @@ function ShortTimestamp({ when }) {
}
function WakaPopover({ children, ...props }) {
- const placement = useBreakpointValue({ base: "bottom", md: "right" });
-
return (
-
+
{children}
@@ -447,14 +445,15 @@ function WakaPopover({ children, ...props }) {
- Other factors, like rarity and popularity, can affect the trade
- economy too—and it can change quickly!
+ It's a super helpful starting point, but it's not the only factor!
+ Rarity and popularity can affect trade values too, and the trade
+ economy can change quickly.
- Be sure to take all factors into account for your trades! And
- consider asking for a "value check" on the Neoboards if you're not
- sure.
+ Be sure to take all factors into account for your trades, rather
+ than sticking to just this number! And consider asking for a
+ "value check" on the Neoboards if you're not sure.
From 45cf9a6f1ffd06fa6220f32044dc909097e3212b Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 20:41:53 -0700
Subject: [PATCH 4/7] Use the new Waka item ID field
This will help us disambiguate items like Butterfly Dress with a non-unique name, and also some where the real item name is glitchy so using it as a key is not wise lol
---
api/allWakaValues.js | 52 ++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 28 deletions(-)
diff --git a/api/allWakaValues.js b/api/allWakaValues.js
index 1c50b04..06e1563 100644
--- a/api/allWakaValues.js
+++ b/api/allWakaValues.js
@@ -14,9 +14,9 @@ import connectToDb from "../src/server/db";
async function handle(req, res) {
const allNcItemNamesAndIdsPromise = loadAllNcItemNamesAndIds();
- let itemValuesByName;
+ let itemValuesByIdOrName;
try {
- itemValuesByName = await loadWakaValuesByName();
+ itemValuesByIdOrName = await loadWakaValuesByIdOrName();
} catch (e) {
console.error(e);
res.setHeader("Content-Type", "text/plain");
@@ -28,25 +28,10 @@ async function handle(req, res) {
const allNcItemNamesAndIds = await allNcItemNamesAndIdsPromise;
const itemValues = {};
for (const { name, id } of allNcItemNamesAndIds) {
- if (name in itemValuesByName) {
- itemValues[id] = itemValuesByName[name];
- } else {
- console.warn(
- `[Item: Y, Waka: N] No Waka value for NC DTI item ${JSON.stringify(
- name
- )} (${id})`
- );
- }
- }
-
- const allNcItemNames = new Set(allNcItemNamesAndIds.map(({ name }) => name));
- for (const name of Object.keys(itemValuesByName)) {
- if (!allNcItemNames.has(name)) {
- console.warn(
- `[Item: N, Waka: Y] No NC DTI data for Waka item ${JSON.stringify(
- name
- )}`
- );
+ if (id in itemValuesByIdOrName) {
+ itemValues[id] = itemValuesByIdOrName[id];
+ } else if (name in itemValuesByIdOrName) {
+ itemValues[id] = itemValuesByIdOrName[name];
}
}
@@ -76,7 +61,12 @@ async function loadAllNcItemNamesAndIds() {
return rows.map(({ id, name }) => ({ id, name: normalizeItemName(name) }));
}
-async function loadWakaValuesByName() {
+/**
+ * Load all Waka values from the spreadsheet. Returns an object keyed by ID or
+ * name - that is, if the item ID is provided in the sheet, we use that as the
+ * key; or if not, we use the name as the key.
+ */
+async function loadWakaValuesByIdOrName() {
if (!process.env["GOOGLE_API_KEY"]) {
throw new Error(`GOOGLE_API_KEY environment variable must be provided`);
}
@@ -109,15 +99,21 @@ async function loadWakaValuesByName() {
// the spreadsheet columns that we don't use on DTI, like Notes.
//
// NOTE: The Sheets API only returns the first non-empty cells of the row.
- // So, when there's no value specified, it only returns one cell.
- // That's why we set `""` as the default `value`.
- const itemValuesByName = {};
- for (const [itemName, value = ""] of rows) {
+ // That's why we set `""` as the defaults, in case the value/notes/etc
+ // aren't provided.
+ const itemValuesByIdOrName = {};
+ for (const [
+ itemName,
+ value = "",
+ notes = "",
+ marks = "",
+ itemId = "",
+ ] of rows) {
const normalizedItemName = normalizeItemName(itemName);
- itemValuesByName[normalizedItemName] = { value };
+ itemValuesByIdOrName[itemId || normalizedItemName] = { value };
}
- return itemValuesByName;
+ return itemValuesByIdOrName;
}
function normalizeItemName(name) {
From a32bc34171f5629f403eefc3a21b47beca474c47 Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 21:46:03 -0700
Subject: [PATCH 5/7] Tweak Waka tooltip copy
---
src/app/ItemPageLayout.js | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/src/app/ItemPageLayout.js b/src/app/ItemPageLayout.js
index a8383f6..3a107be 100644
--- a/src/app/ItemPageLayout.js
+++ b/src/app/ItemPageLayout.js
@@ -445,15 +445,10 @@ function WakaPopover({ children, ...props }) {
- It's a super helpful starting point, but it's not the only factor!
- Rarity and popularity can affect trade values too, and the trade
- economy can change quickly.
-
-
-
- Be sure to take all factors into account for your trades, rather
- than sticking to just this number! And consider asking for a
- "value check" on the Neoboards if you're not sure.
+ The Waka Team aims to maintain the accuracy of the guide as fully
+ as possible, but please remember values are often changing and
+ with certain difficult-to-find or popular items it doesn't hurt to
+ make a value check!
From 089654e092638182aa45b11c9b437c4257c2a28e Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 22:02:10 -0700
Subject: [PATCH 6/7] Use VERCEL_URL for waka loader if given
Oh right, our preview deploy was loading the prod allWakaValues data! Now it uses the VERCEL_URL env variable to request from the current deployment instead.
---
src/server/loaders.js | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/server/loaders.js b/src/server/loaders.js
index 0f1b734..88a811f 100644
--- a/src/server/loaders.js
+++ b/src/server/loaders.js
@@ -608,10 +608,11 @@ const buildItemWakaValueLoader = () =>
// API would, and avoid putting pressure on our Google Sheets API quotas.
// (Some kind of internal memcache or process-level cache would be a more
// idiomatic solution in a monolith server environment!)
- const url =
- process.env.NODE_ENV === "production"
- ? "https://impress-2020.openneo.net/api/allWakaValues"
- : "http://localhost:3000/api/allWakaValues";
+ const url = process.env.VERCEL_URL
+ ? `https://${process.env.VERCEL_URL}/api/allWakaValues`
+ : process.env.NODE_ENV === "production"
+ ? "https://impress-2020.openneo.net/api/allWakaValues"
+ : "http://localhost:3000/api/allWakaValues";
const res = await fetch(url);
if (!res.ok) {
throw new Error(
From b92b5696b4651a7a95d3b63a5e8f79eb8af56407 Mon Sep 17 00:00:00 2001
From: Matchu
Date: Wed, 7 Apr 2021 22:12:03 -0700
Subject: [PATCH 7/7] Remove unused import
---
src/app/ItemPageLayout.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/app/ItemPageLayout.js b/src/app/ItemPageLayout.js
index 3a107be..c0f1068 100644
--- a/src/app/ItemPageLayout.js
+++ b/src/app/ItemPageLayout.js
@@ -13,7 +13,6 @@ import {
Skeleton,
Spinner,
Tooltip,
- useBreakpointValue,
useToast,
VStack,
} from "@chakra-ui/react";