add GQL to know what species can wear an item

gonna use this on the item page to seed the species choice!
This commit is contained in:
Emi Matchu 2020-09-20 21:33:45 -07:00
parent 5f9b143939
commit bcf6e6d8a7
4 changed files with 295 additions and 0 deletions

View file

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

View file

@ -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();
});
});

View file

@ -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 [

View file

@ -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: {