From 1e30e7c8b0f3c96e30fa4cfce8af9b0d4ae77c23 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 28 Aug 2020 22:58:39 -0700 Subject: [PATCH] add Support mode to PosePicker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Still just read-only stuff, but now you can look at all the different poses we have for a species/color! Soon I'll make the pose/glitched stuff editable :3 Some sizable refactors here to add the ability to specify appearance ID as well as pose… most of the app still doesn't use it, it's mostly just lil extra logic to make it win if it's available! (The rationale for making it an override, rather than always tracking appearance ID, is that it gets really inconvenient in practice to //wait// on looking up the appearance ID in order to start loading various queries. Species/color/pose is a more intuitive key, and works better and faster when the canonical appearance is what you want!) --- src/app/WardrobePage/OutfitControls.js | 1 + src/app/WardrobePage/PosePicker.js | 13 +- src/app/WardrobePage/index.js | 1 + .../WardrobePage/support/ItemSupportDrawer.js | 3 +- src/app/WardrobePage/support/Metadata.js | 2 +- .../WardrobePage/support/PosePickerSupport.js | 157 +++++- src/app/WardrobePage/useOutfitState.js | 21 +- src/app/components/OutfitPreview.js | 2 + src/app/components/useOutfitAppearance.js | 36 +- src/app/util.js | 29 + src/server/index.js | 27 +- src/server/loaders.js | 4 +- src/server/query-tests/PetAppearance.test.js | 20 +- .../__snapshots__/Outfit.test.js.snap | 2 +- .../__snapshots__/PetAppearance.test.js.snap | 520 +++++++++--------- .../SpeciesColorPair.test.js.snap | 16 + 16 files changed, 552 insertions(+), 302 deletions(-) diff --git a/src/app/WardrobePage/OutfitControls.js b/src/app/WardrobePage/OutfitControls.js index 624a4c7..0bccf4c 100644 --- a/src/app/WardrobePage/OutfitControls.js +++ b/src/app/WardrobePage/OutfitControls.js @@ -174,6 +174,7 @@ function OutfitControls({ outfitState, dispatchToOutfit }) { speciesId={outfitState.speciesId} colorId={outfitState.colorId} pose={outfitState.pose} + appearanceId={outfitState.appearanceId} dispatchToOutfit={dispatchToOutfit} onLockFocus={onLockFocus} onUnlockFocus={onUnlockFocus} diff --git a/src/app/WardrobePage/PosePicker.js b/src/app/WardrobePage/PosePicker.js index 1c690a3..714e82f 100644 --- a/src/app/WardrobePage/PosePicker.js +++ b/src/app/WardrobePage/PosePicker.js @@ -23,6 +23,7 @@ import { } from "../components/useOutfitAppearance"; import { OutfitLayers } from "../components/OutfitPreview"; import SupportOnly from "./support/SupportOnly"; +import { useLocalStorage } from "../util"; // From https://twemoji.twitter.com/, thank you! import twemojiSmile from "../../images/twemoji/smile.svg"; @@ -54,6 +55,7 @@ function PosePicker({ speciesId, colorId, pose, + appearanceId, dispatchToOutfit, onLockFocus, onUnlockFocus, @@ -61,7 +63,10 @@ function PosePicker({ const theme = useTheme(); const checkedInputRef = React.useRef(); const { loading, error, poseInfos } = usePoses(speciesId, colorId, pose); - const [isInSupportMode, setIsInSupportMode] = React.useState(false); + const [isInSupportMode, setIsInSupportMode] = useLocalStorage( + "DTIPosePickerIsInSupportMode", + false + ); if (loading) { return null; @@ -136,12 +141,14 @@ function PosePicker({ - + {isInSupportMode ? ( ) : ( diff --git a/src/app/WardrobePage/support/ItemSupportDrawer.js b/src/app/WardrobePage/support/ItemSupportDrawer.js index 6821d1e..fe1bfaa 100644 --- a/src/app/WardrobePage/support/ItemSupportDrawer.js +++ b/src/app/WardrobePage/support/ItemSupportDrawer.js @@ -420,11 +420,12 @@ function ItemSupportPetCompatibilityRuleFields({ */ function ItemSupportAppearanceLayers({ item }) { const outfitState = React.useContext(OutfitStateContext); - const { speciesId, colorId, pose } = outfitState; + const { speciesId, colorId, pose, appearanceId } = outfitState; const { error, visibleLayers } = useOutfitAppearance({ speciesId, colorId, pose, + appearanceId, wornItemIds: [item.id], }); diff --git a/src/app/WardrobePage/support/Metadata.js b/src/app/WardrobePage/support/Metadata.js index 9063ed2..ac495bc 100644 --- a/src/app/WardrobePage/support/Metadata.js +++ b/src/app/WardrobePage/support/Metadata.js @@ -5,7 +5,7 @@ import { Box } from "@chakra-ui/core"; * Metadata is a UI component for showing metadata about something, as labels * and their values. */ -function Metadata({ children }) { +function Metadata({ children, ...otherProps }) { return ( id); + + if (!appearanceId) { + appearanceId = canonicalAppearanceIdsByPose[pose]; + } + + const currentPetAppearance = data.petAppearances.find( + (pa) => pa.id === appearanceId + ); + if (!currentPetAppearance) { + return ( + + Pet appearance with ID {JSON.stringify(appearanceId)} not found + + ); + } + return ( - - { + const id = e.target.value; + const petAppearance = data.petAppearances.find( + (pa) => pa.id === id + ); + dispatchToOutfit({ + type: "setPose", + pose: petAppearance.pose, + appearanceId: petAppearance.id, + }); + }} + > {data.petAppearances.map((pa) => ( - ))} + + DTI ID: + {appearanceId} + Pose: + + + + + + + Zones: + + {currentPetAppearance.layers + .map((l) => l.zone) + .map((z) => `${z.label} (${z.id})`) + .sort() + .join(", ")} + + ); } diff --git a/src/app/WardrobePage/useOutfitState.js b/src/app/WardrobePage/useOutfitState.js index 8e3b5e7..ffb8c83 100644 --- a/src/app/WardrobePage/useOutfitState.js +++ b/src/app/WardrobePage/useOutfitState.js @@ -17,7 +17,7 @@ function useOutfitState() { initialState ); - const { name, speciesId, colorId, pose } = state; + const { name, speciesId, colorId, pose, appearanceId } = state; // It's more convenient to manage these as a Set in state, but most callers // will find it more convenient to access them as arrays! e.g. for `.map()` @@ -87,6 +87,7 @@ function useOutfitState() { speciesId, colorId, pose, + appearanceId, url, }; @@ -108,6 +109,7 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => { speciesId: action.speciesId, colorId: action.colorId, pose: action.pose, + appearanceId: null, }; case "wearItem": return produce(baseState, (state) => { @@ -161,7 +163,15 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => { closetedItemIds.delete(itemId); }); case "setPose": - return { ...baseState, pose: action.pose }; + return { + ...baseState, + pose: action.pose, + + // Usually only the `pose` is specified, but `PosePickerSupport` can + // also specify a corresponding `appearanceId`, to get even more + // particular about which version of the pose to show if more than one. + appearanceId: action.appearanceId || null, + }; case "reset": return produce(baseState, (state) => { const { @@ -195,6 +205,7 @@ function parseOutfitUrl() { speciesId: urlParams.get("species"), colorId: urlParams.get("color"), pose: urlParams.get("pose") || "HAPPY_FEM", + appearanceId: urlParams.get("state") || null, wornItemIds: new Set(urlParams.getAll("objects[]")), closetedItemIds: new Set(urlParams.getAll("closet[]")), }; @@ -330,6 +341,7 @@ function buildOutfitUrl(state) { speciesId, colorId, pose, + appearanceId, wornItemIds, closetedItemIds, } = state; @@ -346,6 +358,11 @@ function buildOutfitUrl(state) { for (const itemId of closetedItemIds) { params.append("closet[]", itemId); } + if (appearanceId != null) { + // `state` is an old name for compatibility with old-style DTI URLs. It + // refers to "PetState", the database table name for pet appearances. + params.append("state", appearanceId); + } const { origin, pathname } = window.location; const url = origin + pathname + "?" + params.toString(); diff --git a/src/app/components/OutfitPreview.js b/src/app/components/OutfitPreview.js index 6a1bbd3..3a93993 100644 --- a/src/app/components/OutfitPreview.js +++ b/src/app/components/OutfitPreview.js @@ -25,6 +25,7 @@ function OutfitPreview({ speciesId, colorId, pose, + appearanceId, wornItemIds, placeholder, loadingDelay, @@ -33,6 +34,7 @@ function OutfitPreview({ speciesId, colorId, pose, + appearanceId, wornItemIds, }); diff --git a/src/app/components/useOutfitAppearance.js b/src/app/components/useOutfitAppearance.js index 95ff445..e8f3186 100644 --- a/src/app/components/useOutfitAppearance.js +++ b/src/app/components/useOutfitAppearance.js @@ -7,7 +7,7 @@ import { useQuery } from "@apollo/client"; * visibleLayers for rendering. */ export default function useOutfitAppearance(outfitState) { - const { wornItemIds, speciesId, colorId, pose } = outfitState; + const { wornItemIds, speciesId, colorId, pose, appearanceId } = outfitState; // We split this query out from the other one, so that we can HTTP cache it. // @@ -24,19 +24,37 @@ export default function useOutfitAppearance(outfitState) { // HomePage. At time of writing, Vercel isn't actually edge-caching these, I // assume because our traffic isn't enough - so let's keep an eye on this! const { loading: loading1, error: error1, data: data1 } = useQuery( - gql` - query OutfitPetAppearance($speciesId: ID!, $colorId: ID!, $pose: Pose!) { - petAppearance(speciesId: $speciesId, colorId: $colorId, pose: $pose) { - ...PetAppearanceForOutfitPreview - } - } - ${petAppearanceFragment} - `, + appearanceId == null + ? gql` + query OutfitPetAppearance( + $speciesId: ID! + $colorId: ID! + $pose: Pose! + ) { + petAppearance( + speciesId: $speciesId + colorId: $colorId + pose: $pose + ) { + ...PetAppearanceForOutfitPreview + } + } + ${petAppearanceFragment} + ` + : gql` + query OutfitPetAppearanceById($appearanceId: ID!) { + petAppearance: petAppearanceById(id: $appearanceId) { + ...PetAppearanceForOutfitPreview + } + } + ${petAppearanceFragment} + `, { variables: { speciesId, colorId, pose, + appearanceId, }, skip: speciesId == null || colorId == null || pose == null, } diff --git a/src/app/util.js b/src/app/util.js index 99e5ae5..b587051 100644 --- a/src/app/util.js +++ b/src/app/util.js @@ -159,3 +159,32 @@ export function useFetch(url, { responseType }) { return { loading, error, data }; } + +/** + * useLocalStorage is like React.useState, but it persists the value in the + * device's `localStorage`, so it comes back even after reloading the page. + * + * Adapted from https://usehooks.com/useLocalStorage/. + */ +export function useLocalStorage(key, initialValue) { + const [storedValue, setStoredValue] = React.useState(() => { + try { + const item = window.localStorage.getItem(key); + return item ? JSON.parse(item) : initialValue; + } catch (error) { + console.log(error); + return initialValue; + } + }); + + const setValue = (value) => { + try { + setStoredValue(value); + window.localStorage.setItem(key, JSON.stringify(value)); + } catch (error) { + console.log(error); + } + }; + + return [storedValue, setValue]; +} diff --git a/src/server/index.js b/src/server/index.js index b8e91c5..de1257f 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -101,6 +101,10 @@ const typeDefs = gql` layers: [AppearanceLayer!]! petStateId: ID! # Deprecated, an alias for id + # Whether this PetAppearance is known to look incorrect. This is a manual + # flag that we set, in the case where this glitchy PetAppearance really did + # appear on Neopets.com, and has since been fixed. + isGlitched: Boolean! } type ItemAppearance { @@ -210,10 +214,17 @@ const typeDefs = gql` offset: Int limit: Int ): ItemSearchResult! + + petAppearanceById(id: ID!): PetAppearance @cacheControl(maxAge: 10800) # Cache for 3 hours (Support might edit!) + # The canonical pet appearance for the given species, color, and pose. + # Null if we don't have any data for this combination. petAppearance(speciesId: ID!, colorId: ID!, pose: Pose!): PetAppearance - @cacheControl(maxAge: 604800) # Cache for 1 week (unlikely to change) + @cacheControl(maxAge: 10800) # Cache for 3 hours (we might model more!) + # All pet appearances we've ever seen for the given species and color. Note + # that this might include multiple copies for the same pose, and they might + # even be glitched data. We use this for Support tools. petAppearances(speciesId: ID!, colorId: ID!): [PetAppearance!]! - @cacheControl(maxAge: 10800) # Cache for 3 hours (we might add more!) + @cacheControl(maxAge: 10800) # Cache for 3 hours (we might model more!) outfit(id: ID!): Outfit petOnNeopetsDotCom(petName: String!): Outfit @@ -347,6 +358,10 @@ const resolvers = { return swfAssets; }, petStateId: ({ id }) => id, + isGlitched: async ({ id }, _, { petStateLoader }) => { + const petState = await petStateLoader.load(id); + return petState.glitched; + }, }, AppearanceLayer: { bodyId: async ({ id }, _, { swfAssetLoader }) => { @@ -558,6 +573,7 @@ const resolvers = { }); return { query, items }; }, + petAppearanceById: (_, { id }) => ({ id }), petAppearance: async ( _, { speciesId, colorId, pose }, @@ -568,9 +584,12 @@ const resolvers = { colorId, }); + // TODO: We could query for this more directly, instead of loading all + // appearances 🤔 const petStates = await petStatesForPetTypeLoader.load(petType.id); - // TODO: This could be optimized into the query condition 🤔 - const petState = petStates.find((ps) => getPoseFromPetState(ps) === pose); + const petState = petStates.find( + (ps) => getPoseFromPetState(ps) === pose && !ps.glitched + ); if (!petState) { return null; } diff --git a/src/server/loaders.js b/src/server/loaders.js index f75b055..8c0ee17 100644 --- a/src/server/loaders.js +++ b/src/server/loaders.js @@ -354,8 +354,8 @@ const buildPetStatesForPetTypeLoader = (db, loaders) => const qs = petTypeIds.map((_) => "?").join(","); const [rows, _] = await db.execute( `SELECT * FROM pet_states - WHERE pet_type_id IN (${qs}) AND glitched = 0 - ORDER BY (mood_id = 1) DESC, id`, + WHERE pet_type_id IN (${qs}) + ORDER BY mood_id ASC, female DESC, id DESC`, petTypeIds ); diff --git a/src/server/query-tests/PetAppearance.test.js b/src/server/query-tests/PetAppearance.test.js index 85ec4f0..82c65d8 100644 --- a/src/server/query-tests/PetAppearance.test.js +++ b/src/server/query-tests/PetAppearance.test.js @@ -46,8 +46,8 @@ describe("PetAppearance", () => { ], Array [ "SELECT * FROM pet_states - WHERE pet_type_id IN (?) AND glitched = 0 - ORDER BY (mood_id = 1) DESC", + WHERE pet_type_id IN (?) + ORDER BY mood_id ASC, female DESC, id DESC", Array [ "2", ], @@ -142,8 +142,8 @@ describe("PetAppearance", () => { ], Array [ "SELECT * FROM pet_states - WHERE pet_type_id IN (?) AND glitched = 0 - ORDER BY (mood_id = 1) DESC", + WHERE pet_type_id IN (?) + ORDER BY mood_id ASC, female DESC, id DESC", Array [ "2", ], @@ -155,14 +155,14 @@ describe("PetAppearance", () => { rel.swf_asset_id = sa.id WHERE rel.parent_id IN (?,?,?,?,?,?,?,?)", Array [ - "2", - "436", "4751", - "5991", - "10014", - "11089", + "2", "17723", "17742", + "5991", + "436", + "10014", + "11089", ], ], Array [ @@ -186,8 +186,8 @@ describe("PetAppearance", () => { "5", "37", "30", - "33", "34", + "33", ], ], ] diff --git a/src/server/query-tests/__snapshots__/Outfit.test.js.snap b/src/server/query-tests/__snapshots__/Outfit.test.js.snap index 2d31af9..d1d4888 100644 --- a/src/server/query-tests/__snapshots__/Outfit.test.js.snap +++ b/src/server/query-tests/__snapshots__/Outfit.test.js.snap @@ -44,7 +44,7 @@ Object { "id": "34", "name": "Green", }, - "id": "54-34-UNKNOWN", + "id": "3951", "pose": "UNKNOWN", "species": Object { "id": "54", diff --git a/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap b/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap index b6b728e..ef701eb 100644 --- a/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap +++ b/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap @@ -8,7 +8,7 @@ Object { "isStandard": true, "name": "Starry", }, - "id": "54-75-HAPPY_FEM", + "id": "17723", "layers": Array [ Object { "id": "5995", @@ -76,130 +76,7 @@ Object { "id": "75", "name": "Starry", }, - "id": "54-75-UNKNOWN", - "layers": Array [ - Object { - "id": "5995", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", - "zone": Object { - "depth": 18, - }, - }, - Object { - "id": "5996", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", - "zone": Object { - "depth": 7, - }, - }, - Object { - "id": "6000", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", - "zone": Object { - "depth": 40, - }, - }, - Object { - "id": "16467", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", - "zone": Object { - "depth": 34, - }, - }, - Object { - "id": "19549", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/028/28548/600x600.png?v2-1345719457000", - "zone": Object { - "depth": 37, - }, - }, - Object { - "id": "19550", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/028/28549/600x600.png?v2-0", - "zone": Object { - "depth": 38, - }, - }, - Object { - "id": "163528", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/028/28549/600x600.png?v2-1326455337000", - "zone": Object { - "depth": 38, - }, - }, - ], - "petStateId": "2", - "pose": "UNKNOWN", - "species": Object { - "id": "54", - "name": "Zafara", - }, - }, - Object { - "bodyId": "180", - "color": Object { - "id": "75", - "name": "Starry", - }, - "id": "54-75-SAD_MASC", - "layers": Array [ - Object { - "id": "5995", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", - "zone": Object { - "depth": 18, - }, - }, - Object { - "id": "5996", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", - "zone": Object { - "depth": 7, - }, - }, - Object { - "id": "6000", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", - "zone": Object { - "depth": 40, - }, - }, - Object { - "id": "14790", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21057/600x600.png?v2-0", - "zone": Object { - "depth": 38, - }, - }, - Object { - "id": "14792", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21060/600x600.png?v2-0", - "zone": Object { - "depth": 37, - }, - }, - Object { - "id": "16467", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", - "zone": Object { - "depth": 34, - }, - }, - ], - "petStateId": "436", - "pose": "SAD_MASC", - "species": Object { - "id": "54", - "name": "Zafara", - }, - }, - Object { - "bodyId": "180", - "color": Object { - "id": "75", - "name": "Starry", - }, - "id": "54-75-UNKNOWN", + "id": "4751", "layers": Array [ Object { "id": "5995", @@ -264,7 +141,7 @@ Object { "id": "75", "name": "Starry", }, - "id": "54-75-SAD_FEM", + "id": "2", "layers": Array [ Object { "id": "5995", @@ -287,20 +164,6 @@ Object { "depth": 40, }, }, - Object { - "id": "14790", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21057/600x600.png?v2-0", - "zone": Object { - "depth": 38, - }, - }, - Object { - "id": "14793", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21061/600x600.png?v2-0", - "zone": Object { - "depth": 37, - }, - }, Object { "id": "16467", "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", @@ -308,9 +171,30 @@ Object { "depth": 34, }, }, + Object { + "id": "19549", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/028/28548/600x600.png?v2-1345719457000", + "zone": Object { + "depth": 37, + }, + }, + Object { + "id": "19550", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/028/28549/600x600.png?v2-0", + "zone": Object { + "depth": 38, + }, + }, + Object { + "id": "163528", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/028/28549/600x600.png?v2-1326455337000", + "zone": Object { + "depth": 38, + }, + }, ], - "petStateId": "5991", - "pose": "SAD_FEM", + "petStateId": "2", + "pose": "UNKNOWN", "species": Object { "id": "54", "name": "Zafara", @@ -322,123 +206,7 @@ Object { "id": "75", "name": "Starry", }, - "id": "54-75-SICK_FEM", - "layers": Array [ - Object { - "id": "5995", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", - "zone": Object { - "depth": 18, - }, - }, - Object { - "id": "5996", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", - "zone": Object { - "depth": 7, - }, - }, - Object { - "id": "6000", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", - "zone": Object { - "depth": 40, - }, - }, - Object { - "id": "14791", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21059/600x600.png?v2-0", - "zone": Object { - "depth": 38, - }, - }, - Object { - "id": "14795", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21066/600x600.png?v2-0", - "zone": Object { - "depth": 37, - }, - }, - Object { - "id": "16467", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", - "zone": Object { - "depth": 34, - }, - }, - ], - "petStateId": "10014", - "pose": "SICK_FEM", - "species": Object { - "id": "54", - "name": "Zafara", - }, - }, - Object { - "bodyId": "180", - "color": Object { - "id": "75", - "name": "Starry", - }, - "id": "54-75-SICK_MASC", - "layers": Array [ - Object { - "id": "5995", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", - "zone": Object { - "depth": 18, - }, - }, - Object { - "id": "5996", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", - "zone": Object { - "depth": 7, - }, - }, - Object { - "id": "6000", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", - "zone": Object { - "depth": 40, - }, - }, - Object { - "id": "14791", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21059/600x600.png?v2-0", - "zone": Object { - "depth": 38, - }, - }, - Object { - "id": "14794", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21064/600x600.png?v2-0", - "zone": Object { - "depth": 37, - }, - }, - Object { - "id": "16467", - "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", - "zone": Object { - "depth": 34, - }, - }, - ], - "petStateId": "11089", - "pose": "SICK_MASC", - "species": Object { - "id": "54", - "name": "Zafara", - }, - }, - Object { - "bodyId": "180", - "color": Object { - "id": "75", - "name": "Starry", - }, - "id": "54-75-HAPPY_FEM", + "id": "17723", "layers": Array [ Object { "id": "5995", @@ -496,7 +264,7 @@ Object { "id": "75", "name": "Starry", }, - "id": "54-75-HAPPY_MASC", + "id": "17742", "layers": Array [ Object { "id": "5995", @@ -548,6 +316,238 @@ Object { "name": "Zafara", }, }, + Object { + "bodyId": "180", + "color": Object { + "id": "75", + "name": "Starry", + }, + "id": "5991", + "layers": Array [ + Object { + "id": "5995", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", + "zone": Object { + "depth": 18, + }, + }, + Object { + "id": "5996", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", + "zone": Object { + "depth": 7, + }, + }, + Object { + "id": "6000", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", + "zone": Object { + "depth": 40, + }, + }, + Object { + "id": "14790", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21057/600x600.png?v2-0", + "zone": Object { + "depth": 38, + }, + }, + Object { + "id": "14793", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21061/600x600.png?v2-0", + "zone": Object { + "depth": 37, + }, + }, + Object { + "id": "16467", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", + "zone": Object { + "depth": 34, + }, + }, + ], + "petStateId": "5991", + "pose": "SAD_FEM", + "species": Object { + "id": "54", + "name": "Zafara", + }, + }, + Object { + "bodyId": "180", + "color": Object { + "id": "75", + "name": "Starry", + }, + "id": "436", + "layers": Array [ + Object { + "id": "5995", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", + "zone": Object { + "depth": 18, + }, + }, + Object { + "id": "5996", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", + "zone": Object { + "depth": 7, + }, + }, + Object { + "id": "6000", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", + "zone": Object { + "depth": 40, + }, + }, + Object { + "id": "14790", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21057/600x600.png?v2-0", + "zone": Object { + "depth": 38, + }, + }, + Object { + "id": "14792", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21060/600x600.png?v2-0", + "zone": Object { + "depth": 37, + }, + }, + Object { + "id": "16467", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", + "zone": Object { + "depth": 34, + }, + }, + ], + "petStateId": "436", + "pose": "SAD_MASC", + "species": Object { + "id": "54", + "name": "Zafara", + }, + }, + Object { + "bodyId": "180", + "color": Object { + "id": "75", + "name": "Starry", + }, + "id": "10014", + "layers": Array [ + Object { + "id": "5995", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", + "zone": Object { + "depth": 18, + }, + }, + Object { + "id": "5996", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", + "zone": Object { + "depth": 7, + }, + }, + Object { + "id": "6000", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", + "zone": Object { + "depth": 40, + }, + }, + Object { + "id": "14791", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21059/600x600.png?v2-0", + "zone": Object { + "depth": 38, + }, + }, + Object { + "id": "14795", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21066/600x600.png?v2-0", + "zone": Object { + "depth": 37, + }, + }, + Object { + "id": "16467", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", + "zone": Object { + "depth": 34, + }, + }, + ], + "petStateId": "10014", + "pose": "SICK_FEM", + "species": Object { + "id": "54", + "name": "Zafara", + }, + }, + Object { + "bodyId": "180", + "color": Object { + "id": "75", + "name": "Starry", + }, + "id": "11089", + "layers": Array [ + Object { + "id": "5995", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7941/600x600.png?v2-0", + "zone": Object { + "depth": 18, + }, + }, + Object { + "id": "5996", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7942/600x600.png?v2-0", + "zone": Object { + "depth": 7, + }, + }, + Object { + "id": "6000", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/007/7946/600x600.png?v2-0", + "zone": Object { + "depth": 40, + }, + }, + Object { + "id": "14791", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21059/600x600.png?v2-0", + "zone": Object { + "depth": 38, + }, + }, + Object { + "id": "14794", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/021/21064/600x600.png?v2-0", + "zone": Object { + "depth": 37, + }, + }, + Object { + "id": "16467", + "imageUrl": "https://impress-asset-images.s3.amazonaws.com/biology/000/000/024/24008/600x600.png?v2-0", + "zone": Object { + "depth": 34, + }, + }, + ], + "petStateId": "11089", + "pose": "SICK_MASC", + "species": Object { + "id": "54", + "name": "Zafara", + }, + }, ], } `; diff --git a/src/server/query-tests/__snapshots__/SpeciesColorPair.test.js.snap b/src/server/query-tests/__snapshots__/SpeciesColorPair.test.js.snap index f14edad..103e3b4 100644 --- a/src/server/query-tests/__snapshots__/SpeciesColorPair.test.js.snap +++ b/src/server/query-tests/__snapshots__/SpeciesColorPair.test.js.snap @@ -9203,6 +9203,14 @@ Object { "id": "17", }, }, + Object { + "color": Object { + "id": "105", + }, + "species": Object { + "id": "17", + }, + }, Object { "color": Object { "id": "106", @@ -17539,6 +17547,14 @@ Object { "id": "33", }, }, + Object { + "color": Object { + "id": "112", + }, + "species": Object { + "id": "33", + }, + }, Object { "color": Object { "id": "6",