Permalink
Newer
100644
455 lines (399 sloc)
11.8 KB
7
Popover,
8
PopoverArrow,
9
PopoverBody,
10
PopoverCloseButton,
11
PopoverContent,
12
PopoverHeader,
13
PopoverTrigger,
21
import {
22
type MutableRefObject,
23
type ReactNode,
24
useEffect,
25
useRef,
26
useState,
27
} from "react";
28
import { useLoaderData } from "@remix-run/react";
29
import AppealBans from "../../components/AppealBans.js";
35
import NewInactivityNotice from "../../components/NewInactivityNotice.js";
36
import InactivityNoticeCard from "../../components/InactivityNoticeCard.js";
38
export async function loader({ context }: { context: RequestContext }) {
39
const { current_user: currentUser } = context.data;
57
infraction: [1 << 0, 1 << 2, 1 << 6, 1 << 7],
58
user_lookup: [1 << 5, 1 << 8],
63
game_ban: "New Game Ban",
64
inactivity: "New Inactivity Notice",
65
infraction: "New Infraction",
66
user_lookup: "User Lookup",
67
};
68
69
const typePermissions = {
70
appeal: [1 << 0, 1 << 1],
71
gma: [1 << 5],
74
};
75
76
const typeNames: { [k: string]: string } = {
77
appeal: "Discord Appeals",
78
gma: "Game Appeals",
81
};
82
83
const allowedNewItems = [];
84
const allowedTypes = [];
85
86
for (const [item, ints] of Object.entries(newItemPermissions)) {
87
if (ints.find((i) => currentUser.permissions & i))
88
allowedNewItems.push({ name: newItemNames[item], value: item });
89
}
90
91
for (const [type, ints] of Object.entries(typePermissions)) {
92
if (ints.find((i) => currentUser.permissions & i))
93
allowedTypes.push({ name: typeNames[type], value: type });
94
}
95
102
can_edit_ban_users: [
103
"165594923586945025",
104
"289372404541554689",
107
departments: Object.entries(departments)
108
.filter((d) => d[1] & currentUser.permissions)
109
.map((arr) => arr[0]),
125
const isDesktop = useBreakpointValue({ base: false, lg: true });
126
const entryTypes = [];
127
const [entries, setEntries] = useState(
128
[] as { element: ReactNode; id: string }[],
129
);
132
const messageChannel: MutableRefObject<MessageChannel | null> = useRef(null);
136
entryTypes.push(
137
<option key={type.value} value={type.value}>
138
{type.name}
143
if (messageChannel.current) {
144
messageChannel.current.port1.onmessage = function (ev) {
145
const { data }: { data: string } = ev;
146
147
setEntries([...entries].filter((entry) => entry.id !== data));
148
};
149
}
159
const searchParams = new URLSearchParams(location.search);
160
const itemId = searchParams.get("id");
161
const queueType = searchParams.get("type") ?? queue_type;
162
163
if (!pageProps.entry_types.find((type) => type.value === queueType)) {
164
toast({
165
description: "You cannot access that queue",
166
isClosable: true,
167
status: "error",
168
title: "Forbidden",
169
});
170
171
return;
172
}
173
174
if (!searchParams.get("type") && itemId) {
175
toast({
176
description: "Cannot load item by id without type",
177
isClosable: true,
178
status: "error",
179
title: "Bad link",
180
});
181
182
return;
183
}
184
185
if (queueType !== queue_type) setQueue(queueType);
186
188
`/api/mod-queue/list?before=${before}&showClosed=${show_closed}&type=${queueType}`,
190
191
if (!queueReq.ok) {
192
const errorData: { error: string } = await queueReq.json();
193
195
description: errorData.error,
196
duration: 10000,
197
isClosable: true,
198
status: "error",
213
if (specifiedItem) {
214
entryData = entryData.filter((entry) => entry.id !== specifiedItem.id);
215
entryData.unshift(specifiedItem);
216
} else {
226
});
227
} else {
228
const itemData: { [k: string]: any } = await itemReq.json();
229
230
entryData.unshift(itemData);
231
}
244
entryData.indexOf(entry) > 0 &&
245
entryData.filter((d) => d.id === entry.id).length > 1
246
)
251
newEntries.push({
252
element: (
253
<AppealCard
254
{...(entry as AppealCardProps & { port?: MessagePort })}
264
newEntries.push({
265
element: (
266
<GameAppealCard
267
{...(entry as GameAppealProps & { port?: MessagePort })}
277
newEntries.push({
278
element: (
279
<InactivityNoticeCard
280
{...(entry as InactivityNoticeProps & { port?: MessagePort })}
290
newEntries.push({
291
element: (
292
<ReportCard
293
{...(entry as ReportCardProps & { port?: MessagePort })}
308
const itemModals: {
309
[k: string]: {
310
isOpen: boolean;
311
onOpen: () => void;
312
onClose: () => void;
313
[k: string]: any;
314
};
315
} = {
319
infraction: useDisclosure(),
320
user_lookup: {
321
isOpen: false,
322
onClose: () => {},
323
onOpen: () => location.assign("/hammer"),
324
},
334
const searchParams = new URLSearchParams(location.search);
335
const modal = searchParams.get("modal");
336
337
if (!modal || !pageProps.item_types.find((m) => m.value === modal)) return;
338
339
itemModals[modal].onOpen();
340
}, []);
342
const ItemDisplay = (
343
<Select
344
onChange={async (v) => {
345
setBefore(Date.now());
346
347
const { target } = v;
348
351
await updateQueue(
352
target.options[target.selectedIndex].value,
353
Date.now(),
367
<AppealBans
368
isOpen={itemModals.appeal_bans.isOpen}
369
onClose={itemModals.appeal_bans.onClose}
370
/>
371
<NewGameBan
372
isOpen={itemModals.game_ban.isOpen}
373
onClose={itemModals.game_ban.onClose}
374
/>
375
<NewInactivityNotice
376
departments={pageProps.departments}
377
isOpen={itemModals.inactivity.isOpen}
378
onClose={itemModals.inactivity.onClose}
379
/>
381
isOpen={itemModals.infraction.isOpen}
382
onClose={itemModals.infraction.onClose}
385
<VStack w={isDesktop ? "container.md" : "container.lg"}>
386
<Box display={isDesktop ? "none" : undefined} mb="16px" w="90%">
391
) : (
392
<Container
393
left="50%"
394
maxW="container.md"
395
pos="absolute"
396
mt="64px"
397
transform="translate(-50%)"
398
>
399
<Flex>
400
<Spacer />
401
<img alt="Thonkery" src="/files/Thonkery.png" />
402
<Spacer />
403
</Flex>
404
<br />
405
<Heading textAlign="center">Nothing here</Heading>
406
</Container>
407
)}
408
</VStack>
409
<Box display={isDesktop ? undefined : "none"} ml="16px" w="248px">
415
<Button
416
borderRadius="50%"
417
bottom="10vh"
418
h="16"
419
position="absolute"
420
right="10vh"
421
w="16"
422
>
430
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
431
</svg>
432
</Button>
433
</PopoverTrigger>
434
<PopoverContent>
435
<PopoverArrow />
436
<PopoverCloseButton />
440
{pageProps.item_types.map((item) => (
441
<Button
442
key={item.value}
443
onClick={() => itemModals[item.value].onOpen()}
444
w="100%"
445
>
446
{item.name}
447
</Button>
448
))}