From 4e9805af6009789423f2097412da1437a51ff38d Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 15 Mar 2021 09:13:25 -0700 Subject: [PATCH] Bulk-add tool actually saves stuff! I fixed Dug Up Dirt foreground, hooray! Hope it sticks --- .../support/AllItemLayersSupportModal.js | 122 ++++++++++++++---- src/server/types/MutationsForSupport.js | 85 ++++++++++++ 2 files changed, 180 insertions(+), 27 deletions(-) diff --git a/src/app/WardrobePage/support/AllItemLayersSupportModal.js b/src/app/WardrobePage/support/AllItemLayersSupportModal.js index ea7b828..8b1600c 100644 --- a/src/app/WardrobePage/support/AllItemLayersSupportModal.js +++ b/src/app/WardrobePage/support/AllItemLayersSupportModal.js @@ -16,7 +16,7 @@ import { Wrap, WrapItem, } from "@chakra-ui/react"; -import { gql, useQuery } from "@apollo/client"; +import { gql, useMutation, useQuery } from "@apollo/client"; import { appearanceLayerFragment, itemAppearanceFragment, @@ -26,6 +26,7 @@ import HangerSpinner from "../../components/HangerSpinner"; import { ErrorMessage, useCommonStyles } from "../../util"; import ItemSupportAppearanceLayer from "./ItemSupportAppearanceLayer"; import { EditIcon } from "@chakra-ui/icons"; +import useSupport from "./useSupport"; function AllItemLayersSupportModal({ item, isOpen, onClose }) { const [bulkAddProposal, setBulkAddProposal] = React.useState(null); @@ -54,6 +55,7 @@ function AllItemLayersSupportModal({ item, isOpen, onClose }) { setBulkAddProposal(null)} /> @@ -149,39 +151,53 @@ function BulkAddBodySpecificAssetsForm({ bulkAddProposal, onSubmit }) { ); } -function AllItemLayersSupportModalContent({ item, bulkAddProposal }) { +const allAppearancesFragment = gql` + fragment AllAppearancesForItem on Item { + allAppearances { + id + body { + id + representsAllBodies + canonicalAppearance { + id + species { + id + name + } + color { + id + name + isStandard + } + pose + ...PetAppearanceForOutfitPreview + } + } + ...ItemAppearanceForOutfitPreview + } + } + + ${itemAppearanceFragment} + ${petAppearanceFragment} +`; + +function AllItemLayersSupportModalContent({ + item, + bulkAddProposal, + onBulkAddComplete, +}) { + const { supportSecret } = useSupport(); + const { loading, error, data } = useQuery( gql` query AllItemLayersSupportModal($itemId: ID!) { item(id: $itemId) { id - allAppearances { - id - body { - id - representsAllBodies - canonicalAppearance { - id - species { - id - name - } - color { - id - name - isStandard - } - pose - ...PetAppearanceForOutfitPreview - } - } - ...ItemAppearanceForOutfitPreview - } + ...AllAppearancesForItem } } - ${itemAppearanceFragment} - ${petAppearanceFragment} + ${allAppearancesFragment} `, { variables: { itemId: item.id } } ); @@ -236,6 +252,28 @@ function AllItemLayersSupportModalContent({ item, bulkAddProposal }) { } ); + const [ + sendBulkAddMutation, + { loading: mutationLoading, error: mutationError }, + ] = useMutation(gql` + mutation AllItemLayersSupportModal_BulkAddMutation( + $itemId: ID! + $entries: [BulkAddLayersToItemEntry!]! + $supportSecret: String! + ) { + bulkAddLayersToItem( + itemId: $itemId + entries: $entries + supportSecret: $supportSecret + ) { + id + ...AllAppearancesForItem + } + } + + ${allAppearancesFragment} + `); + if (loading || loading2) { return ( @@ -266,7 +304,37 @@ function AllItemLayersSupportModalContent({ item, bulkAddProposal }) { Previewing bulk-add changes - diff --git a/src/server/types/MutationsForSupport.js b/src/server/types/MutationsForSupport.js index 06368de..dd1c5ee 100644 --- a/src/server/types/MutationsForSupport.js +++ b/src/server/types/MutationsForSupport.js @@ -55,6 +55,12 @@ const typeDefs = gql` supportSecret: String! ): AppearanceLayer + bulkAddLayersToItem( + itemId: ID! + entries: [BulkAddLayersToItemEntry!]! + supportSecret: String! + ): Item + removeLayerFromItem( layerId: ID! itemId: ID! @@ -75,6 +81,11 @@ const typeDefs = gql` setUsername(userId: ID!, newUsername: String!, supportSecret: String!): User } + + input BulkAddLayersToItemEntry { + layerId: ID! + bodyId: ID! + } `; const resolvers = { @@ -479,6 +490,80 @@ const resolvers = { return { id: layerId }; }, + bulkAddLayersToItem: async ( + _, + { itemId, entries, supportSecret }, + { itemLoader, itemTranslationLoader, db } + ) => { + assertSupportSecretOrThrow(supportSecret); + + const item = await itemLoader.load(itemId); + if (!item) { + console.warn( + `Skipping removeLayerFromItem for unknown item ID: ${itemId}` + ); + return null; + } + + const handleEntry = async ({ layerId, bodyId }) => { + await Promise.all([ + db.execute(`UPDATE swf_assets SET body_id = ? WHERE id = ? LIMIT 1`, [ + bodyId, + layerId, + ]), + db.execute( + // Technique adapted from https://stackoverflow.com/a/3025332/107415 + ` + INSERT INTO parents_swf_assets + (parent_type, parent_id, swf_asset_id) + SELECT "Item", ?, ? FROM DUAL + WHERE NOT EXISTS ( + SELECT * FROM parents_swf_assets + WHERE parent_type = "Item" AND parent_id = ? AND + swf_asset_id = ? + ) + `, + [itemId, layerId, itemId, layerId] + ), + ]); + }; + + await Promise.all(entries.map(handleEntry)); + + if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { + try { + const itemTranslation = await itemTranslationLoader.load(itemId); + + await logToDiscord({ + embeds: [ + { + title: `🛠 ${itemTranslation.name}`, + thumbnail: { + url: item.thumbnailUrl, + height: 80, + width: 80, + }, + fields: [ + { + name: `Bulk-add body-specific layers`, + value: `✅ Added/updated ${entries.length} layers`, + }, + ], + timestamp: new Date().toISOString(), + url: `https://impress.openneo.net/items/${itemId}`, + }, + ], + }); + } catch (e) { + console.error("Error sending Discord support log", e); + } + } else { + console.warn("No Discord support webhook provided, skipping"); + } + + return { id: itemId }; + }, + removeLayerFromItem: async ( _, { layerId, itemId, supportSecret },