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",