From bcf6e6d8a7b3841f49267af543c42ea9667e4154 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 20 Sep 2020 21:33:45 -0700 Subject: [PATCH] add GQL to know what species can wear an item gonna use this on the item page to seed the species choice! --- src/server/loaders.js | 26 +++ src/server/query-tests/Item.test.js | 63 ++++++ .../__snapshots__/Item.test.js.snap | 192 ++++++++++++++++++ src/server/types/Item.js | 14 ++ 4 files changed, 295 insertions(+) diff --git a/src/server/loaders.js b/src/server/loaders.js index 10c1845..679e39e 100644 --- a/src/server/loaders.js +++ b/src/server/loaders.js @@ -294,6 +294,29 @@ const buildItemsThatNeedModelsLoader = (db) => return [lastResult]; }); +const buildItemSpeciesWithAppearanceDataLoader = (db) => + new DataLoader(async (itemIds) => { + const qs = itemIds.map((_) => "?").join(","); + const [rows, _] = await db.execute( + `SELECT DISTINCT pet_types.species_id AS id, items.id AS item_id + FROM items + INNER JOIN parents_swf_assets ON + items.id = parents_swf_assets.parent_id AND + parents_swf_assets.parent_type = "Item" + INNER JOIN swf_assets ON + parents_swf_assets.swf_asset_id = swf_assets.id + INNER JOIN pet_types ON + pet_types.body_id = swf_assets.body_id OR swf_assets.body_id = 0 + WHERE items.id = ${qs} + ORDER BY id`, + itemIds + ); + + const entities = rows.map(normalizeRow); + + return itemIds.map((itemId) => entities.filter((e) => e.itemId === itemId)); + }); + const buildPetTypeLoader = (db) => new DataLoader(async (petTypeIds) => { const qs = petTypeIds.map((_) => "?").join(","); @@ -594,6 +617,9 @@ function buildLoaders(db) { loaders.itemSearchLoader = buildItemSearchLoader(db, loaders); loaders.itemSearchToFitLoader = buildItemSearchToFitLoader(db, loaders); loaders.itemsThatNeedModelsLoader = buildItemsThatNeedModelsLoader(db); + loaders.itemSpeciesWithAppearanceDataLoader = buildItemSpeciesWithAppearanceDataLoader( + db + ); loaders.petTypeLoader = buildPetTypeLoader(db); loaders.petTypeBySpeciesAndColorLoader = buildPetTypeBySpeciesAndColorLoader( db, diff --git a/src/server/query-tests/Item.test.js b/src/server/query-tests/Item.test.js index 16584f0..b8df9cf 100644 --- a/src/server/query-tests/Item.test.js +++ b/src/server/query-tests/Item.test.js @@ -430,4 +430,67 @@ describe("Item", () => { expect(res.data).toMatchSnapshot(); expect(getDbCalls()).toMatchSnapshot(); }); + + it("loads species with appearance data for single-species item", async () => { + const res = await query({ + query: gql` + query { + item( + id: "38911" # Zafara Agent Hood + ) { + speciesWithAppearanceDataForThisItem { + name + } + } + } + `, + }); + + expect(res).toHaveNoErrors(); + expect(res.data.item.speciesWithAppearanceDataForThisItem).toHaveLength(1); + expect(res.data.item.speciesWithAppearanceDataForThisItem[0].name).toEqual( + "Zafara" + ); + expect(getDbCalls()).toMatchSnapshot(); + }); + + it("loads species with appearance data for all-species item", async () => { + const res = await query({ + query: gql` + query { + item( + id: "74967" # 17th Birthday Party Hat + ) { + speciesWithAppearanceDataForThisItem { + name + } + } + } + `, + }); + + expect(res).toHaveNoErrors(); + expect(res.data.item.speciesWithAppearanceDataForThisItem).toHaveLength(55); + expect(getDbCalls()).toMatchSnapshot(); + }); + + it("loads species with appearance data for bodyId=0 item", async () => { + const res = await query({ + query: gql` + query { + item( + id: "37375" # Moon and Stars Background + ) { + speciesWithAppearanceDataForThisItem { + name + } + } + } + `, + }); + + expect(res).toHaveNoErrors(); + expect(res.data.item.speciesWithAppearanceDataForThisItem).toHaveLength(55); + expect(getDbCalls()).toMatchSnapshot(); + }); }); diff --git a/src/server/query-tests/__snapshots__/Item.test.js.snap b/src/server/query-tests/__snapshots__/Item.test.js.snap index f585ef7..7e4817b 100644 --- a/src/server/query-tests/__snapshots__/Item.test.js.snap +++ b/src/server/query-tests/__snapshots__/Item.test.js.snap @@ -11998,6 +11998,198 @@ Object { } `; +exports[`Item loads species with appearance data for all-species item 1`] = ` +Array [ + Array [ + "SELECT DISTINCT pet_types.species_id AS id, items.id AS item_id + FROM items + INNER JOIN parents_swf_assets ON + items.id = parents_swf_assets.parent_id AND + parents_swf_assets.parent_type = \\"Item\\" + INNER JOIN swf_assets ON + parents_swf_assets.swf_asset_id = swf_assets.id + INNER JOIN pet_types ON + pet_types.body_id = swf_assets.body_id OR swf_assets.body_id = 0 + WHERE items.id = ? + ORDER BY id", + Array [ + "74967", + ], + ], + Array [ + "SELECT * FROM species_translations + WHERE species_id IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND locale = \\"en\\"", + Array [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "30", + "31", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44", + "45", + "46", + "47", + "48", + "49", + "50", + "51", + "52", + "53", + "54", + "55", + ], + ], +] +`; + +exports[`Item loads species with appearance data for bodyId=0 item 1`] = ` +Array [ + Array [ + "SELECT DISTINCT pet_types.species_id AS id, items.id AS item_id + FROM items + INNER JOIN parents_swf_assets ON + items.id = parents_swf_assets.parent_id AND + parents_swf_assets.parent_type = \\"Item\\" + INNER JOIN swf_assets ON + parents_swf_assets.swf_asset_id = swf_assets.id + INNER JOIN pet_types ON + pet_types.body_id = swf_assets.body_id OR swf_assets.body_id = 0 + WHERE items.id = ? + ORDER BY id", + Array [ + "37375", + ], + ], + Array [ + "SELECT * FROM species_translations + WHERE species_id IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND locale = \\"en\\"", + Array [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "30", + "31", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44", + "45", + "46", + "47", + "48", + "49", + "50", + "51", + "52", + "53", + "54", + "55", + ], + ], +] +`; + +exports[`Item loads species with appearance data for single-species item 1`] = ` +Array [ + Array [ + "SELECT DISTINCT pet_types.species_id AS id, items.id AS item_id + FROM items + INNER JOIN parents_swf_assets ON + items.id = parents_swf_assets.parent_id AND + parents_swf_assets.parent_type = \\"Item\\" + INNER JOIN swf_assets ON + parents_swf_assets.swf_asset_id = swf_assets.id + INNER JOIN pet_types ON + pet_types.body_id = swf_assets.body_id OR swf_assets.body_id = 0 + WHERE items.id = ? + ORDER BY id", + Array [ + "38911", + ], + ], + Array [ + "SELECT * FROM species_translations + WHERE species_id IN (?) AND locale = \\"en\\"", + Array [ + "54", + ], + ], +] +`; + exports[`Item returns empty appearance for incompatible items 1`] = ` Object { "items": Array [ diff --git a/src/server/types/Item.js b/src/server/types/Item.js index 44fff76..e6c2bcc 100644 --- a/src/server/types/Item.js +++ b/src/server/types/Item.js @@ -41,6 +41,12 @@ const typeDefs = gql` # major special color like Baby (#6), or leave it blank for standard # bodies like Blue, Green, Red, etc. speciesThatNeedModels(colorId: ID): [Species!]! + + # Species that we know how they look wearing this item. Used to initialize + # the preview on the item page with a compatible species. + # TODO: This would probably make more sense as like, compatible bodies, so + # we could also encode special-color stuff in here too. + speciesWithAppearanceDataForThisItem: [Species!]! } type ItemAppearance { @@ -176,6 +182,14 @@ const resolvers = { ); return unmodeledSpeciesIds.map((id) => ({ id })); }, + speciesWithAppearanceDataForThisItem: async ( + { id }, + _, + { itemSpeciesWithAppearanceDataLoader } + ) => { + const rows = await itemSpeciesWithAppearanceDataLoader.load(id); + return rows.map((row) => ({ id: row.id })); + }, }, ItemAppearance: {