added unlocked (deletion) function for aime_user_game_locks in admin panel
This commit is contained in:
parent
04edbf3df0
commit
d13e1561ae
@ -0,0 +1,69 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { artemis } from "@/lib/prisma";
|
||||||
|
import type * as Prisma from "@prisma/client";
|
||||||
|
type AimeUserGameLocks = Prisma.PrismaClient;
|
||||||
|
|
||||||
|
export async function getLockedUsers() {
|
||||||
|
try {
|
||||||
|
const lockedUsers = await artemis.aime_user_game_locks.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
user: true,
|
||||||
|
game: true,
|
||||||
|
expires_at: true,
|
||||||
|
extra: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// user = aime_user_game_locks id column
|
||||||
|
const userIds = lockedUsers.map((lockedUsers) => lockedUsers.user);
|
||||||
|
|
||||||
|
const usersWithNames = await artemis.chuni_profile_data.findMany({
|
||||||
|
where: {
|
||||||
|
user: {
|
||||||
|
in: userIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
user: true,
|
||||||
|
userName: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const LockedUsernames = lockedUsers.map((lockedUsers) => {
|
||||||
|
const user = usersWithNames.find((u) => u.user === lockedUsers.user);
|
||||||
|
return {
|
||||||
|
...lockedUsers,
|
||||||
|
userName: user?.userName || null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return LockedUsernames;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching locked users:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteUserGameLocks(userId: number) {
|
||||||
|
try {
|
||||||
|
const result = await artemis.aime_user_game_locks.deleteMany({
|
||||||
|
where: {
|
||||||
|
user: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.count > 0) {
|
||||||
|
console.log(
|
||||||
|
`Successfully deleted ${result.count} rows for user ${userId}.`,
|
||||||
|
);
|
||||||
|
return { success: true, count: result.count };
|
||||||
|
} else {
|
||||||
|
console.log(`No rows found for user ${userId}.`);
|
||||||
|
return { success: false, message: `No rows found for user ${userId}.` };
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting user game locks:", error);
|
||||||
|
return { success: false, message: "Error deleting user game locks." };
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
"use client";
|
||||||
|
import { ColumnDef } from "@tanstack/react-table";
|
||||||
|
import { aime_user_game_locks } from "@/prisma/schemas/artemis/generated/artemis";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Trash2, UnlockIcon } from "lucide-react";
|
||||||
|
import { deleteUserGameLocks } from "./action";
|
||||||
|
type chunithm = aime_user_game_locks & { userName: string | null };
|
||||||
|
|
||||||
|
const handleDelete = async (userId: number) => {
|
||||||
|
try {
|
||||||
|
const result = await deleteUserGameLocks(userId);
|
||||||
|
if (result.success) {
|
||||||
|
console.log(
|
||||||
|
`Successfully deleted ${result.count} rows for user ${userId}.`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error(result.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting user game locks:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const columns: ColumnDef<chunithm>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "Username",
|
||||||
|
header: "Username",
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="text-bold flex items-center">
|
||||||
|
<div className="ml-2 flex flex-col">
|
||||||
|
{row.original.userName || `User ID: ${row.original.user}`}{" "}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "ExpiresDate",
|
||||||
|
header: "Expiration Date",
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const expirationDate = row.original.expires_at;
|
||||||
|
const currentDate = new Date();
|
||||||
|
|
||||||
|
if (!expirationDate) {
|
||||||
|
return <div>N/A</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const expirationDateTime = new Date(expirationDate).getTime();
|
||||||
|
const currentDateTime = currentDate.getTime();
|
||||||
|
const fifteenMinuteBuffer = 15 * 60 * 1000;
|
||||||
|
|
||||||
|
if (expirationDateTime < currentDateTime - fifteenMinuteBuffer) {
|
||||||
|
return <div>Expired</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div>{new Date(expirationDate).toLocaleDateString()}</div>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "deletelock",
|
||||||
|
header: "Remove Lock",
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
className="hover:bg-red-400"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => handleDelete(row.original.user)}
|
||||||
|
>
|
||||||
|
<UnlockIcon className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
@ -0,0 +1,106 @@
|
|||||||
|
"use client";
|
||||||
|
// https://github.com/dracor-org/einakter/blob/466ca1663098a16cc1141129a6ba22628135b04c/src/components/Table.tsx#L26
|
||||||
|
// used the above for reference on how to fuzzy search
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
SortingState,
|
||||||
|
getSortedRowModel,
|
||||||
|
flexRender,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getCoreRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import DebouncedInput from "@/components/scoreplaylog/DebouncedInput";
|
||||||
|
interface DataTableProps<TData, TValue> {
|
||||||
|
columns: ColumnDef<TData, TValue>[];
|
||||||
|
data: TData[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DataTable<TData, TValue>({
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
}: DataTableProps<TData, TValue>) {
|
||||||
|
const table = useReactTable({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="rounded-md border">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<TableRow key={headerGroup.id}>
|
||||||
|
{headerGroup.headers.map((header) => (
|
||||||
|
<TableHead key={header.id}>
|
||||||
|
{header.isPlaceholder
|
||||||
|
? null
|
||||||
|
: flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext(),
|
||||||
|
)}
|
||||||
|
</TableHead>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{table.getRowModel().rows?.length ? (
|
||||||
|
table.getRowModel().rows.map((row) => (
|
||||||
|
<TableRow
|
||||||
|
key={row.id}
|
||||||
|
data-state={row.getIsSelected() && "selected"}
|
||||||
|
>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<TableCell key={cell.id} className="pb-2 pl-4 pt-2">
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={columns.length} className="h-2 text-center">
|
||||||
|
No results.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<div className="flex items-center justify-end space-x-2 p-4">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
import UnlockUser from "./unlock";
|
import { getLockedUsers } from "./action";
|
||||||
|
import { DataTable } from "./data-table";
|
||||||
|
import { columns } from "./columns";
|
||||||
|
|
||||||
const FileExtractionPage = async () => {
|
const UnlockUserPage = async () => {
|
||||||
return <UnlockUser />;
|
const songs = (await getLockedUsers()) || [];
|
||||||
|
|
||||||
|
return <DataTable columns={columns} data={songs} />;
|
||||||
};
|
};
|
||||||
export default FileExtractionPage;
|
export default UnlockUserPage;
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Label } from "@radix-ui/react-dropdown-menu";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
const GenerateKeychip = () => {
|
|
||||||
return (
|
|
||||||
<Card x-chunk="aimecard">
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="text-2xl">Link New Aime Card</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
|
|
||||||
<CardContent>
|
|
||||||
<div className="mb-4 text-lg">Current Access Code:</div>
|
|
||||||
<form className="grid gap-4">
|
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label>Access Code</Label>
|
|
||||||
<Input
|
|
||||||
name="accessCode"
|
|
||||||
type="text"
|
|
||||||
placeholder="*******************"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button type="submit" className="w-full">
|
|
||||||
Link
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GenerateKeychip;
|
|
@ -8,8 +8,8 @@ const NAV_ITEMS = [
|
|||||||
{ href: "/admin/generateKeychip", label: "Generate Keychip" },
|
{ href: "/admin/generateKeychip", label: "Generate Keychip" },
|
||||||
|
|
||||||
{ href: "/admin/unlockUser", label: "Unlock User" },
|
{ href: "/admin/unlockUser", label: "Unlock User" },
|
||||||
{ href: "/admin/extraction", label: "Extract Game Files" },
|
// { href: "/admin/extraction", label: "Extract Game Files" },
|
||||||
{ href: "/admin/gameversions", label: "Edit Game Version" },
|
// { href: "/admin/gameversions", label: "Edit Game Version" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const AdminSubNavigation = () => {
|
const AdminSubNavigation = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user