diff --git a/src/app/ItemPageLayout.js b/src/app/ItemPageLayout.js
index a82b0d4..9caad8c 100644
--- a/src/app/ItemPageLayout.js
+++ b/src/app/ItemPageLayout.js
@@ -10,10 +10,13 @@ import {
Portal,
Select,
Skeleton,
+ Spinner,
Tooltip,
+ useToast,
VStack,
} from "@chakra-ui/react";
import { ExternalLinkIcon, ChevronRightIcon } from "@chakra-ui/icons";
+import { gql, useMutation } from "@apollo/client";
import {
ItemBadgeList,
@@ -204,13 +207,32 @@ function ItemPageBadges({ item, isEmbedded }) {
}
function ItemKindBadgeWithSupportTools({ item }) {
- const { isSupportUser } = useSupport();
+ const { isSupportUser, supportSecret } = useSupport();
+ const toast = useToast();
const ncRef = React.useRef(null);
const isNcAutoDetectedFromRarity =
item.rarityIndex === 500 || item.rarityIndex === 0;
+ const [mutate, { loading }] = useMutation(gql`
+ mutation ItemPageSupportSetIsManuallyNc(
+ $itemId: ID!
+ $isManuallyNc: Boolean!
+ $supportSecret: String!
+ ) {
+ setItemIsManuallyNc(
+ itemId: $itemId
+ isManuallyNc: $isManuallyNc
+ supportSecret: $supportSecret
+ ) {
+ id
+ isNc
+ isManuallyNc
+ }
+ }
+ `);
+
if (isSupportUser && item.rarityIndex != null && item.isManuallyNc != null) {
// TODO: Could code-split this into a SupportOnly file...
return (
@@ -230,6 +252,31 @@ function ItemKindBadgeWithSupportTools({ item }) {
ref={ncRef}
size="xs"
value={item.isManuallyNc ? "true" : "false"}
+ onChange={(e) => {
+ const isManuallyNc = e.target.value === "true";
+ mutate({
+ variables: {
+ itemId: item.id,
+ isManuallyNc,
+ supportSecret,
+ },
+ optimisticResponse: {
+ setItemIsManuallyNc: {
+ __typename: "Item",
+ id: item.id,
+ isNc: isManuallyNc || isNcAutoDetectedFromRarity,
+ isManuallyNc,
+ },
+ },
+ }).catch((e) => {
+ console.error(e);
+ toast({
+ status: "error",
+ title:
+ "Could not set NC status for this item. Try again?",
+ });
+ });
+ }}
>
+ {loading && }
diff --git a/src/server/types/MutationsForSupport.js b/src/server/types/MutationsForSupport.js
index 6e3cbfe..03be98d 100644
--- a/src/server/types/MutationsForSupport.js
+++ b/src/server/types/MutationsForSupport.js
@@ -37,6 +37,12 @@ const typeDefs = gql`
supportSecret: String!
): Item!
+ setItemIsManuallyNc(
+ itemId: ID!
+ isManuallyNc: Boolean!
+ supportSecret: String!
+ ): Item!
+
setLayerBodyId(
layerId: ID!
bodyId: ID!
@@ -206,6 +212,69 @@ const resolvers = {
return { id: itemId };
},
+ setItemIsManuallyNc: async (
+ _,
+ { itemId, isManuallyNc, supportSecret },
+ { itemLoader, itemTranslationLoader, db }
+ ) => {
+ assertSupportSecretOrThrow(supportSecret);
+
+ const oldItem = await itemLoader.load(itemId);
+
+ const [
+ result,
+ ] = await db.execute(
+ `UPDATE items SET is_manually_nc = ? WHERE id = ? LIMIT 1`,
+ [isManuallyNc ? 1 : 0, itemId]
+ );
+
+ if (result.affectedRows !== 1) {
+ throw new Error(
+ `Expected to affect 1 item, but affected ${result.affectedRows}`
+ );
+ }
+
+ itemLoader.clear(itemId); // we changed the item, so clear it from cache
+
+ if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) {
+ try {
+ const itemTranslation = await itemTranslationLoader.load(itemId);
+ const oldRuleName = oldItem.isManuallyNc
+ ? "Manually set: Yes"
+ : "Auto-detect";
+ const newRuleName = isManuallyNc
+ ? "Manually set: Yes"
+ : "Auto-detect";
+ await logToDiscord({
+ embeds: [
+ {
+ title: `🛠${itemTranslation.name}`,
+ thumbnail: {
+ url: oldItem.thumbnailUrl,
+ height: 80,
+ width: 80,
+ },
+ fields: [
+ {
+ name: "Is NC rule",
+ value: `${oldRuleName} → **${newRuleName}**`,
+ },
+ ],
+ timestamp: new Date().toISOString(),
+ url: `https://impress.openneo.net/items/${oldItem.id}`,
+ },
+ ],
+ });
+ } catch (e) {
+ console.error("Error sending Discord support log", e);
+ }
+ } else {
+ console.warn("No Discord support webhook provided, skipping");
+ }
+
+ return { id: itemId };
+ },
+
setLayerBodyId: async (
_,
{ layerId, bodyId, supportSecret },