Support tool: Remove layer from item
Heck yeah, let's clean these fuckers up!
This commit is contained in:
parent
c94e94538e
commit
6821c2b734
3 changed files with 176 additions and 0 deletions
|
@ -15,6 +15,7 @@ GRANT SELECT ON openneo_impress.zone_translations TO impress2020;
|
||||||
-- Public data tables: write
|
-- Public data tables: write
|
||||||
GRANT UPDATE ON openneo_impress.items TO impress2020;
|
GRANT UPDATE ON openneo_impress.items TO impress2020;
|
||||||
GRANT UPDATE ON openneo_impress.swf_assets TO impress2020;
|
GRANT UPDATE ON openneo_impress.swf_assets TO impress2020;
|
||||||
|
GRANT DELETE ON openneo_impress.parents_swf_assets TO impress2020;
|
||||||
|
|
||||||
-- User data tables
|
-- User data tables
|
||||||
GRANT SELECT ON openneo_impress.item_outfit_relationships TO impress2020;
|
GRANT SELECT ON openneo_impress.item_outfit_relationships TO impress2020;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Spinner,
|
Spinner,
|
||||||
|
useDisclosure,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/core";
|
} from "@chakra-ui/core";
|
||||||
import { ChevronRightIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
import { ChevronRightIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
|
@ -209,10 +210,18 @@ function ItemLayerSupportModal({
|
||||||
/>
|
/>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
<ItemLayerSupportModalRemoveButton
|
||||||
|
item={item}
|
||||||
|
itemLayer={itemLayer}
|
||||||
|
outfitState={outfitState}
|
||||||
|
onRemoveSuccess={onClose}
|
||||||
|
/>
|
||||||
|
<Box flex="1 0 0" />
|
||||||
{mutationError && (
|
{mutationError && (
|
||||||
<Box
|
<Box
|
||||||
color="red.400"
|
color="red.400"
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
|
marginLeft="8"
|
||||||
marginRight="2"
|
marginRight="2"
|
||||||
textAlign="right"
|
textAlign="right"
|
||||||
>
|
>
|
||||||
|
@ -223,6 +232,7 @@ function ItemLayerSupportModal({
|
||||||
isLoading={mutationLoading}
|
isLoading={mutationLoading}
|
||||||
colorScheme="green"
|
colorScheme="green"
|
||||||
onClick={mutate}
|
onClick={mutate}
|
||||||
|
flex="0 0 auto"
|
||||||
>
|
>
|
||||||
Save changes
|
Save changes
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -344,4 +354,133 @@ function ItemLayerSupportPetCompatibilityFields({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ItemLayerSupportModalRemoveButton({
|
||||||
|
item,
|
||||||
|
itemLayer,
|
||||||
|
outfitState,
|
||||||
|
onRemoveSuccess,
|
||||||
|
}) {
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const toast = useToast();
|
||||||
|
const supportSecret = useSupportSecret();
|
||||||
|
|
||||||
|
const [mutate, { loading, error }] = useMutation(
|
||||||
|
gql`
|
||||||
|
mutation ItemLayerSupportRemoveButton(
|
||||||
|
$layerId: ID!
|
||||||
|
$itemId: ID!
|
||||||
|
$outfitSpeciesId: ID!
|
||||||
|
$outfitColorId: ID!
|
||||||
|
$supportSecret: String!
|
||||||
|
) {
|
||||||
|
removeLayerFromItem(
|
||||||
|
layerId: $layerId
|
||||||
|
itemId: $itemId
|
||||||
|
supportSecret: $supportSecret
|
||||||
|
) {
|
||||||
|
# This mutation returns the affected layer, and the affected item.
|
||||||
|
# Fetch the updated appearance for the current outfit, which should
|
||||||
|
# no longer include this layer. This means you should be able to see
|
||||||
|
# your changes immediately!
|
||||||
|
item {
|
||||||
|
id
|
||||||
|
appearanceOn(speciesId: $outfitSpeciesId, colorId: $outfitColorId) {
|
||||||
|
...ItemAppearanceForOutfitPreview
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# The layer's item should be null now, fetch to confirm and update!
|
||||||
|
layer {
|
||||||
|
id
|
||||||
|
item {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${itemAppearanceFragment}
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
variables: {
|
||||||
|
layerId: itemLayer.id,
|
||||||
|
itemId: item.id,
|
||||||
|
outfitSpeciesId: outfitState.speciesId,
|
||||||
|
outfitColorId: outfitState.colorId,
|
||||||
|
supportSecret,
|
||||||
|
},
|
||||||
|
onCompleted: () => {
|
||||||
|
onClose();
|
||||||
|
onRemoveSuccess();
|
||||||
|
toast({
|
||||||
|
status: "success",
|
||||||
|
title: `Removed layer ${itemLayer.id} from ${item.name}`,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button colorScheme="red" flex="0 0 auto" onClick={onOpen}>
|
||||||
|
Remove
|
||||||
|
</Button>
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose} size="xl" isCentered>
|
||||||
|
<ModalOverlay>
|
||||||
|
<ModalContent>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalHeader>
|
||||||
|
Remove Layer {itemLayer.id} ({itemLayer.zone.label}) from{" "}
|
||||||
|
{item.name}?
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
<Box as="p" marginBottom="4">
|
||||||
|
This will permanently-ish remove Layer {itemLayer.id} (
|
||||||
|
{itemLayer.zone.label}) from this item.
|
||||||
|
</Box>
|
||||||
|
<Box as="p" marginBottom="4">
|
||||||
|
If you remove a correct layer by mistake, re-modeling should fix
|
||||||
|
it, or Matchu can restore it if you write down the layer ID
|
||||||
|
before proceeding!
|
||||||
|
</Box>
|
||||||
|
<Box as="p" marginBottom="4">
|
||||||
|
Are you sure you want to remove Layer {itemLayer.id} from this
|
||||||
|
item?
|
||||||
|
</Box>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button flex="0 0 auto" onClick={onClose}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
<Box flex="1 0 0" />
|
||||||
|
{error && (
|
||||||
|
<Box
|
||||||
|
color="red.400"
|
||||||
|
fontSize="sm"
|
||||||
|
marginLeft="8"
|
||||||
|
marginRight="2"
|
||||||
|
textAlign="right"
|
||||||
|
>
|
||||||
|
{error.message}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
colorScheme="red"
|
||||||
|
flex="0 0 auto"
|
||||||
|
onClick={() =>
|
||||||
|
mutate().catch((e) => {
|
||||||
|
/* Discard errors here; we'll show them in the UI! */
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isLoading={loading}
|
||||||
|
>
|
||||||
|
Yes, remove permanently
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</ModalOverlay>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default ItemLayerSupportModal;
|
export default ItemLayerSupportModal;
|
||||||
|
|
|
@ -210,6 +210,11 @@ const typeDefs = gql`
|
||||||
petOnNeopetsDotCom(petName: String!): Outfit
|
petOnNeopetsDotCom(petName: String!): Outfit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RemoveLayerFromItemMutationResult {
|
||||||
|
layer: AppearanceLayer!
|
||||||
|
item: Item!
|
||||||
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
setManualSpecialColor(
|
setManualSpecialColor(
|
||||||
itemId: ID!
|
itemId: ID!
|
||||||
|
@ -228,6 +233,12 @@ const typeDefs = gql`
|
||||||
bodyId: ID!
|
bodyId: ID!
|
||||||
supportSecret: String!
|
supportSecret: String!
|
||||||
): AppearanceLayer!
|
): AppearanceLayer!
|
||||||
|
|
||||||
|
removeLayerFromItem(
|
||||||
|
layerId: ID!
|
||||||
|
itemId: ID!
|
||||||
|
supportSecret: String!
|
||||||
|
): RemoveLayerFromItemMutationResult!
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -672,6 +683,31 @@ const resolvers = {
|
||||||
|
|
||||||
return { id: layerId };
|
return { id: layerId };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeLayerFromItem: async (
|
||||||
|
_,
|
||||||
|
{ layerId, itemId, supportSecret },
|
||||||
|
{ db }
|
||||||
|
) => {
|
||||||
|
if (supportSecret !== process.env["SUPPORT_SECRET"]) {
|
||||||
|
throw new Error(`Support secret is incorrect. Try setting up again?`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [result] = await db.execute(
|
||||||
|
`DELETE FROM parents_swf_assets ` +
|
||||||
|
`WHERE swf_asset_id = ? AND parent_type = "Item" AND parent_id = ? ` +
|
||||||
|
`LIMIT 1`,
|
||||||
|
[layerId, itemId]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.affectedRows !== 1) {
|
||||||
|
throw new Error(
|
||||||
|
`Expected to affect 1 layer, but affected ${result.affectedRows}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { layer: { id: layerId }, item: { id: itemId } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue