Compare commits

...

4 commits

Author SHA1 Message Date
bb0d219508 Don't let action buttons wrap onto multiple lines in Item Getting Guide
A funny table-layout bug, where the item "Portal to the Unknown" had a
very long Owls listing ("Owls listing: Buyable - Magic Lens + Blank
Grey Tome (NP)"), and so the table layout tried to give it more room by
decreasing the width of the action cell and wrapping the "NC Trades"
action button text onto multiple lines.

The fix: don't allow that! The table layout will figure out how to
handle this being disallowed, and give the actions cell an appropriate
minimum width.
2024-05-28 17:16:41 -07:00
f84e340899 Add link to Item Getting Guide from outfit editor (behind secret link)
You can now go to `/outfits/new?features=get-these-items` to start
seeing the "Get These Items!" button in the outfit editor!

I haven't tested it a ton yet, but yeah here it is!
2024-05-28 17:06:23 -07:00
671e0becb6 Oops, fix recent bug in Item Getting Guide for most item types
Oh oops, I added an optional `subtitle` argument for the item table
list row template, but didn't realize that it would crash in cases when
not provided! Now, we add an initializer to set it to `nil` if
undefined.
2024-05-28 17:05:28 -07:00
3eb40b2a4f Preload SWF asset manifests during wardrobe item search
This doesn't matter a ton in production, where we already have most of
our manifests loaded! But it matters a lot on my relatively-fresh
development instance, at times like now when images.neopets.com is slow
to respond. A single item search was taking minutes before this change
(5 seconds of timeout per asset for 30 items!), but now takes a few
seconds the first time, as it should!
2024-05-28 17:05:04 -07:00
4 changed files with 65 additions and 2 deletions

View file

@ -39,6 +39,11 @@
padding-left: 1em
font-size: 85%
a, button
/* When item names get long, don't let the buttons wrap to give the
* item names more space. The names should wrap more instead! */
text-wrap: nowrap
tbody
tr
&:hover, &:focus-within

View file

@ -171,7 +171,13 @@ class ItemsController < ApplicationController
appearance_params[:color_id], appearance_params[:species_id])
end
target.appearances_for(@items.map(&:id), swf_asset_includes: [:zone])
target.appearances_for(@items.map(&:id), swf_asset_includes: [:zone]).
tap do |appearances|
# Preload the manifests for these SWF assets concurrently, rather than
# loading them in sequence when we generate the JSON.
swf_assets = appearances.values.map(&:swf_assets).flatten
SwfAsset.preload_manifests(swf_assets)
end
end
def search_error(e)

View file

@ -31,12 +31,20 @@ import {
CheckIcon,
DeleteIcon,
EditIcon,
ExternalLinkIcon,
QuestionIcon,
WarningTwoIcon,
} from "@chakra-ui/icons";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { useSearchParams } from "react-router-dom";
import { Delay, ErrorMessage, Heading1, Heading2 } from "../util";
import {
Delay,
ErrorMessage,
Heading1,
Heading2,
useLocalStorage,
} from "../util";
import Item, { ItemListContainer, ItemListSkeleton } from "./Item";
import { BiRename } from "react-icons/bi";
import { IoCloudUploadOutline } from "react-icons/io5";
@ -270,6 +278,45 @@ function ItemZoneGroupSkeleton({ itemCount }) {
);
}
/**
* GetTheseItemsButton shows the "Get these items!" button, to link to the
* Item Getting Guide page for the items in this outfit. If there are no items
* being worn, this is disabled.
*/
function GetTheseItemsButton({ outfitState }) {
const [searchParams] = useSearchParams();
const [isVisible, setIsVisible] = useLocalStorage("DTIShowGetTheseItems");
// Enable this feature by visiting `/outfits/new?features=get-these-items`.
React.useEffect(() => {
const features = searchParams.get("features") ?? "";
if (features.split(",").includes("get-these-items")) {
setIsVisible(true);
}
}, [searchParams, setIsVisible]);
const itemIds = [...outfitState.wornItemIds].sort();
const targetUrl = `/items/sources/${itemIds.join(",")}`;
const isDisabled = itemIds.length === 0;
if (!isVisible) {
return null;
}
return (
<Button
as={isDisabled ? "button" : "a"}
href={isDisabled ? undefined : targetUrl}
target={isDisabled ? undefined : "_blank"}
colorScheme="purple"
rightIcon={<ExternalLinkIcon />}
isDisabled={isDisabled}
>
Get these items!
</Button>
);
}
/**
* OutfitSavingIndicator shows a Save button, or the "Saved" or "Saving" state,
* if the user can save this outfit. If not, this is empty!
@ -403,6 +450,9 @@ function OutfitHeading({ outfitState, outfitSaving, dispatchToOutfit }) {
</Box>
</Box>
<Box width="4" flex="1 0 auto" />
<Box flex="0 0 auto">
<GetTheseItemsButton outfitState={outfitState} />
</Box>
<Box flex="0 0 auto">
<OutfitSavingIndicator outfitSaving={outfitSaving} />
</Box>

View file

@ -1,3 +1,5 @@
- subtitle = nil unless defined? subtitle
%tr
%td.thumbnail-cell
= link_to item_thumbnail_for(item), item, target: "_blank",