mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-05-10 22:01:16 +00:00
feat: manual creator editing on packages and bulk set
- Click creator cell in STL Files table to edit - Server action for updating/clearing package creator - Bulk set creator action for multiple packages
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { type ColumnDef } from "@tanstack/react-table";
|
import { type ColumnDef } from "@tanstack/react-table";
|
||||||
import { FileArchive, Eye, ImageIcon } from "lucide-react";
|
import { FileArchive, Eye, Pencil } from "lucide-react";
|
||||||
import { DataTableColumnHeader } from "@/components/shared/data-table-column-header";
|
import { DataTableColumnHeader } from "@/components/shared/data-table-column-header";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -26,6 +26,7 @@ export interface PackageRow {
|
|||||||
|
|
||||||
interface PackageColumnsProps {
|
interface PackageColumnsProps {
|
||||||
onViewFiles: (pkg: PackageRow) => void;
|
onViewFiles: (pkg: PackageRow) => void;
|
||||||
|
onSetCreator: (pkg: PackageRow) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatBytes(bytesStr: string): string {
|
function formatBytes(bytesStr: string): string {
|
||||||
@@ -57,6 +58,7 @@ function PreviewCell({ pkg }: { pkg: PackageRow }) {
|
|||||||
|
|
||||||
export function getPackageColumns({
|
export function getPackageColumns({
|
||||||
onViewFiles,
|
onViewFiles,
|
||||||
|
onSetCreator,
|
||||||
}: PackageColumnsProps): ColumnDef<PackageRow, unknown>[] {
|
}: PackageColumnsProps): ColumnDef<PackageRow, unknown>[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -113,9 +115,13 @@ export function getPackageColumns({
|
|||||||
accessorKey: "creator",
|
accessorKey: "creator",
|
||||||
header: ({ column }) => <DataTableColumnHeader column={column} title="Creator" />,
|
header: ({ column }) => <DataTableColumnHeader column={column} title="Creator" />,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="text-sm text-muted-foreground truncate max-w-[160px] block">
|
<button
|
||||||
{row.original.creator ?? "\u2014"}
|
className="text-sm text-muted-foreground truncate max-w-[160px] block hover:text-foreground hover:underline cursor-pointer text-left"
|
||||||
</span>
|
onClick={() => onSetCreator(row.original)}
|
||||||
|
title="Click to edit creator"
|
||||||
|
>
|
||||||
|
{row.original.creator || "\u2014"}
|
||||||
|
</button>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback } from "react";
|
import { useState, useCallback, useTransition } from "react";
|
||||||
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { Search, FileBox } from "lucide-react";
|
import { Search, FileBox } from "lucide-react";
|
||||||
import { useDataTable } from "@/hooks/use-data-table";
|
import { useDataTable } from "@/hooks/use-data-table";
|
||||||
import { getPackageColumns, type PackageRow } from "./package-columns";
|
import { getPackageColumns, type PackageRow } from "./package-columns";
|
||||||
@@ -13,6 +14,7 @@ import { DataTableViewOptions } from "@/components/shared/data-table-view-option
|
|||||||
import { PageHeader } from "@/components/shared/page-header";
|
import { PageHeader } from "@/components/shared/page-header";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import type { IngestionAccountStatus } from "@/lib/telegram/types";
|
import type { IngestionAccountStatus } from "@/lib/telegram/types";
|
||||||
|
import { updatePackageCreator } from "../actions";
|
||||||
|
|
||||||
interface StlTableProps {
|
interface StlTableProps {
|
||||||
data: PackageRow[];
|
data: PackageRow[];
|
||||||
@@ -33,6 +35,7 @@ export function StlTable({
|
|||||||
|
|
||||||
const [searchValue, setSearchValue] = useState(searchParams.get("search") ?? "");
|
const [searchValue, setSearchValue] = useState(searchParams.get("search") ?? "");
|
||||||
const [viewPkg, setViewPkg] = useState<PackageRow | null>(null);
|
const [viewPkg, setViewPkg] = useState<PackageRow | null>(null);
|
||||||
|
const [, startTransition] = useTransition();
|
||||||
|
|
||||||
const updateSearch = useCallback(
|
const updateSearch = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
@@ -51,6 +54,19 @@ export function StlTable({
|
|||||||
|
|
||||||
const columns = getPackageColumns({
|
const columns = getPackageColumns({
|
||||||
onViewFiles: (pkg) => setViewPkg(pkg),
|
onViewFiles: (pkg) => setViewPkg(pkg),
|
||||||
|
onSetCreator: (pkg) => {
|
||||||
|
const value = prompt("Enter creator name:", pkg.creator ?? "");
|
||||||
|
if (value === null) return;
|
||||||
|
startTransition(async () => {
|
||||||
|
const result = await updatePackageCreator(pkg.id, value || null);
|
||||||
|
if (result.success) {
|
||||||
|
toast.success(value ? `Creator set to "${value}"` : "Creator removed");
|
||||||
|
router.refresh();
|
||||||
|
} else {
|
||||||
|
toast.error(result.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { table } = useDataTable({ data, columns, pageCount });
|
const { table } = useDataTable({ data, columns, pageCount });
|
||||||
|
|||||||
44
src/app/(app)/stls/actions.ts
Normal file
44
src/app/(app)/stls/actions.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { auth } from "@/lib/auth";
|
||||||
|
import { prisma } from "@/lib/prisma";
|
||||||
|
import type { ActionResult } from "@/types/api.types";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
export async function updatePackageCreator(
|
||||||
|
packageId: string,
|
||||||
|
creator: string | null
|
||||||
|
): Promise<ActionResult> {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session?.user?.id) return { success: false, error: "Unauthorized" };
|
||||||
|
|
||||||
|
try {
|
||||||
|
await prisma.package.update({
|
||||||
|
where: { id: packageId },
|
||||||
|
data: { creator: creator?.trim() || null },
|
||||||
|
});
|
||||||
|
revalidatePath("/stls");
|
||||||
|
return { success: true, data: undefined };
|
||||||
|
} catch {
|
||||||
|
return { success: false, error: "Failed to update creator" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function bulkSetCreator(
|
||||||
|
packageIds: string[],
|
||||||
|
creator: string
|
||||||
|
): Promise<ActionResult> {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session?.user?.id) return { success: false, error: "Unauthorized" };
|
||||||
|
|
||||||
|
try {
|
||||||
|
await prisma.package.updateMany({
|
||||||
|
where: { id: { in: packageIds } },
|
||||||
|
data: { creator: creator.trim() },
|
||||||
|
});
|
||||||
|
revalidatePath("/stls");
|
||||||
|
return { success: true, data: undefined };
|
||||||
|
} catch {
|
||||||
|
return { success: false, error: "Failed to update creators" };
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user