Use MessageChannels to self-delete queue items
Previous method would cause site to die
This commit is contained in:
parent
912cd0581a
commit
5d38bae59c
@ -18,7 +18,7 @@ import {
|
|||||||
useToast,
|
useToast,
|
||||||
VStack,
|
VStack,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { type ReactElement, useEffect, useState } from "react";
|
import { type ReactNode, useEffect, useState } from "react";
|
||||||
import AppealCard from "../../components/AppealCard.js";
|
import AppealCard from "../../components/AppealCard.js";
|
||||||
import GameAppealCard from "../../components/GameAppealCard.js";
|
import GameAppealCard from "../../components/GameAppealCard.js";
|
||||||
import NewGameBan from "../../components/NewGameBan.js";
|
import NewGameBan from "../../components/NewGameBan.js";
|
||||||
@ -115,8 +115,11 @@ export default function () {
|
|||||||
const pageProps = useLoaderData<typeof loader>();
|
const pageProps = useLoaderData<typeof loader>();
|
||||||
const isDesktop = useBreakpointValue({ base: false, lg: true });
|
const isDesktop = useBreakpointValue({ base: false, lg: true });
|
||||||
const entryTypes = [];
|
const entryTypes = [];
|
||||||
const [entries, setEntries] = useState([] as ReactElement[]);
|
const [entries, setEntries] = useState(
|
||||||
|
[] as { element: ReactNode; id: string }[],
|
||||||
|
);
|
||||||
const [before, setBefore] = useState(Date.now());
|
const [before, setBefore] = useState(Date.now());
|
||||||
|
const [messageChannel] = useState(null as MessageChannel | null);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
for (const type of pageProps.entry_types)
|
for (const type of pageProps.entry_types)
|
||||||
@ -126,6 +129,16 @@ export default function () {
|
|||||||
</option>,
|
</option>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!messageChannel) return;
|
||||||
|
|
||||||
|
messageChannel.port1.onmessage = function (ev) {
|
||||||
|
const { data }: { data: string } = ev;
|
||||||
|
|
||||||
|
setEntries([...entries].filter((entry) => entry.id !== data));
|
||||||
|
};
|
||||||
|
}, [messageChannel]);
|
||||||
|
|
||||||
async function updateQueue(
|
async function updateQueue(
|
||||||
queue_type: string,
|
queue_type: string,
|
||||||
before: number,
|
before: number,
|
||||||
@ -212,24 +225,54 @@ export default function () {
|
|||||||
|
|
||||||
switch (cardType) {
|
switch (cardType) {
|
||||||
case "appeal":
|
case "appeal":
|
||||||
newEntries.push(<AppealCard {...(entry as AppealCardProps)} />);
|
newEntries.push({
|
||||||
|
element: (
|
||||||
|
<AppealCard
|
||||||
|
{...(entry as AppealCardProps & { port?: MessagePort })}
|
||||||
|
port={messageChannel?.port2}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
id: `appeal_${entry.id}`,
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "gma":
|
case "gma":
|
||||||
newEntries.push(<GameAppealCard {...(entry as GameAppealProps)} />);
|
newEntries.push({
|
||||||
|
element: (
|
||||||
|
<GameAppealCard
|
||||||
|
{...(entry as GameAppealProps & { port?: MessagePort })}
|
||||||
|
port={messageChannel?.port2}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
id: `gma_${entry.id}`,
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "inactivity":
|
case "inactivity":
|
||||||
newEntries.push(
|
newEntries.push({
|
||||||
<InactivityNoticeCard {...(entry as InactivityNoticeProps)} />,
|
element: (
|
||||||
);
|
<InactivityNoticeCard
|
||||||
|
{...(entry as InactivityNoticeProps & { port?: MessagePort })}
|
||||||
|
port={messageChannel?.port2}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
id: `inactivity_${entry.id}`,
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "report":
|
case "report":
|
||||||
newEntries.push(<ReportCard {...(entry as ReportCardProps)} />);
|
newEntries.push({
|
||||||
|
element: (
|
||||||
|
<ReportCard
|
||||||
|
{...(entry as ReportCardProps & { port?: MessagePort })}
|
||||||
|
port={messageChannel?.port2}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
id: `report_${entry.id}`,
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -311,7 +354,7 @@ export default function () {
|
|||||||
{ItemDisplay}
|
{ItemDisplay}
|
||||||
</Box>
|
</Box>
|
||||||
{entries.length ? (
|
{entries.length ? (
|
||||||
entries
|
entries.map((entry) => entry.element)
|
||||||
) : (
|
) : (
|
||||||
<Container
|
<Container
|
||||||
left="50%"
|
left="50%"
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function(props: AppealCardProps) {
|
export default function(props: AppealCardProps & { port?: MessagePort }) {
|
||||||
const [dateString, setDateString] = useState(
|
const [dateString, setDateString] = useState(
|
||||||
new Date(props.created_at).toUTCString()
|
new Date(props.created_at).toUTCString()
|
||||||
);
|
);
|
||||||
@ -80,7 +80,7 @@ export default function(props: AppealCardProps) {
|
|||||||
|
|
||||||
onClose();
|
onClose();
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
document.getElementById(`appeal_${props.id}`)?.remove();
|
props.port?.postMessage(`appeal_${props.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function (props: GameAppealProps) {
|
export default function (props: GameAppealProps & { port?: MessagePort }) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [percentage, setPercentage] = useState(0);
|
const [percentage, setPercentage] = useState(0);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
@ -59,9 +59,7 @@ export default function (props: GameAppealProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
document
|
props.port?.postMessage(`gma_${props.id}`);
|
||||||
.getElementById(`gma_${props.roblox_id}${props.created_at}`)
|
|
||||||
?.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||||
|
@ -11,11 +11,11 @@ import {
|
|||||||
StackDivider,
|
StackDivider,
|
||||||
Text,
|
Text,
|
||||||
UnorderedList,
|
UnorderedList,
|
||||||
useToast
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function(props: InactivityNoticeProps) {
|
export default function (props: InactivityNoticeProps & { port?: MessagePort }) {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ export default function(props: InactivityNoticeProps) {
|
|||||||
const decisionReq = await fetch(`/api/inactivity/${props.id}`, {
|
const decisionReq = await fetch(`/api/inactivity/${props.id}`, {
|
||||||
body: JSON.stringify({ accepted }),
|
body: JSON.stringify({ accepted }),
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "application/json"
|
"content-type": "application/json",
|
||||||
},
|
},
|
||||||
method: "POST"
|
method: "POST",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!decisionReq.ok) {
|
if (!decisionReq.ok) {
|
||||||
@ -35,7 +35,7 @@ export default function(props: InactivityNoticeProps) {
|
|||||||
description: ((await decisionReq.json()) as { error: string }).error,
|
description: ((await decisionReq.json()) as { error: string }).error,
|
||||||
isClosable: true,
|
isClosable: true,
|
||||||
status: "error",
|
status: "error",
|
||||||
title: "Oops"
|
title: "Oops",
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -45,24 +45,22 @@ export default function(props: InactivityNoticeProps) {
|
|||||||
description: `Inactivity notice ${accepted ? "accepted" : "denied"}.`,
|
description: `Inactivity notice ${accepted ? "accepted" : "denied"}.`,
|
||||||
isClosable: true,
|
isClosable: true,
|
||||||
status: "success",
|
status: "success",
|
||||||
title: "Success"
|
title: "Success",
|
||||||
});
|
});
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
location.reload();
|
props.port?.postMessage(`inactivity_${props.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Approved = () => (
|
const Approved = () => (
|
||||||
<svg fill="currentColor" height="16" viewBox="0 0 16 16" width="16">
|
<svg fill="currentColor" height="16" viewBox="0 0 16 16" width="16">
|
||||||
<path
|
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" />
|
||||||
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" />
|
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
const Denied = () => (
|
const Denied = () => (
|
||||||
<svg fill="currentColor" height="16" viewBox="0 0 16 16" width="16">
|
<svg fill="currentColor" height="16" viewBox="0 0 16 16" width="16">
|
||||||
<path
|
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z" />
|
||||||
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z" />
|
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
useToast,
|
useToast,
|
||||||
VStack
|
VStack,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function(props: ReportCardProps) {
|
export default function (props: ReportCardProps & { port?: MessagePort }) {
|
||||||
const [attachmentIdx, setAttachmentIdx] = useState(0);
|
const [attachmentIdx, setAttachmentIdx] = useState(0);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
@ -26,7 +26,7 @@ export default function(props: ReportCardProps) {
|
|||||||
|
|
||||||
for (let i = 0; i < props.target_ids.length; i++)
|
for (let i = 0; i < props.target_ids.length; i++)
|
||||||
Object.defineProperty(targetMap, props.target_ids[i], {
|
Object.defineProperty(targetMap, props.target_ids[i], {
|
||||||
value: props.target_usernames[i]
|
value: props.target_usernames[i],
|
||||||
});
|
});
|
||||||
|
|
||||||
async function submitActions() {
|
async function submitActions() {
|
||||||
@ -34,9 +34,9 @@ export default function(props: ReportCardProps) {
|
|||||||
const submitReq = await fetch(`/api/reports/${props.id}/action`, {
|
const submitReq = await fetch(`/api/reports/${props.id}/action`, {
|
||||||
body: JSON.stringify(actionMap),
|
body: JSON.stringify(actionMap),
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "application/json"
|
"content-type": "application/json",
|
||||||
},
|
},
|
||||||
method: "POST"
|
method: "POST",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!submitReq.ok) {
|
if (!submitReq.ok) {
|
||||||
@ -44,7 +44,7 @@ export default function(props: ReportCardProps) {
|
|||||||
toast({
|
toast({
|
||||||
description: ((await submitReq.json()) as { error: string }).error,
|
description: ((await submitReq.json()) as { error: string }).error,
|
||||||
status: "error",
|
status: "error",
|
||||||
title: "S̸̯̜̈́o̴̳̅̾̏̽m̴͔͕̈́̋ē̴̙͓̯̍̃ț̸͖̘̀h̶̛̳̝̐i̵̋͘͜ņ̷̙̤͌g̴̭̻̓̈́ ̴̘͍̦̪̆w̸̡̏̑̊é̸̠̖̹̂͜n̴̖̳̤̕t̴͚̊̊̕ ̸̛͙̺̬̎́w̴͈͑̋͊r̷̢̛o̵̱̩̍͋ͅṇ̸̝̰̮́g̵̡̢̦͕͂"
|
title: "S̸̯̜̈́o̴̳̅̾̏̽m̴͔͕̈́̋ē̴̙͓̯̍̃ț̸͖̘̀h̶̛̳̝̐i̵̋͘͜ņ̷̙̤͌g̴̭̻̓̈́ ̴̘͍̦̪̆w̸̡̏̑̊é̸̠̖̹̂͜n̴̖̳̤̕t̴͚̊̊̕ ̸̛͙̺̬̎́w̴͈͑̋͊r̷̢̛o̵̱̩̍͋ͅṇ̸̝̰̮́g̵̡̢̦͕͂",
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -53,10 +53,10 @@ export default function(props: ReportCardProps) {
|
|||||||
toast({
|
toast({
|
||||||
description: "Actions were successfully applied",
|
description: "Actions were successfully applied",
|
||||||
status: "success",
|
status: "success",
|
||||||
title: "Success"
|
title: "Success",
|
||||||
});
|
});
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
location.reload();
|
props.port?.postMessage(`report_${props.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -132,7 +132,7 @@ export default function(props: ReportCardProps) {
|
|||||||
</CardBody>
|
</CardBody>
|
||||||
<CardFooter display={props.open ? undefined : "none"}>
|
<CardFooter display={props.open ? undefined : "none"}>
|
||||||
<Stack direction="column" gap="16px">
|
<Stack direction="column" gap="16px">
|
||||||
{(function() {
|
{(function () {
|
||||||
const radioGroups = [];
|
const radioGroups = [];
|
||||||
for (let i = 0; i < props.target_ids.length; i++) {
|
for (let i = 0; i < props.target_ids.length; i++) {
|
||||||
radioGroups.push(
|
radioGroups.push(
|
||||||
@ -154,7 +154,7 @@ export default function(props: ReportCardProps) {
|
|||||||
Ban
|
Ban
|
||||||
</Radio>
|
</Radio>
|
||||||
</VStack>
|
</VStack>
|
||||||
</RadioGroup>
|
</RadioGroup>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user