Deleting VoDs feature Closes #1765

This commit is contained in:
Kalle
2024-07-21 12:36:22 +03:00
parent 6c0bd3b5f7
commit 7c1c0544fb
5 changed files with 69 additions and 10 deletions

View File

@@ -0,0 +1,5 @@
import { db } from "~/db/sql";
export function deleteById(id: number) {
return db.deleteFrom("UnvalidatedVideo").where("id", "=", id).execute();
}

View File

@@ -0,0 +1,25 @@
import { type ActionFunctionArgs, redirect } from "@remix-run/node";
import { requireUser } from "~/features/auth/core/user.server";
import { badRequestIfFalsy, unauthorizedIfFalsy } from "~/utils/remix";
import { userVodsPage } from "~/utils/urls";
import * as VodRepository from "../VodRepository.server";
import { findVodById } from "../queries/findVodById.server";
import { canEditVideo } from "../vods-utils";
export const action = async ({ request, params }: ActionFunctionArgs) => {
const user = await requireUser(request);
const vod = badRequestIfFalsy(findVodById(Number(params.id)));
unauthorizedIfFalsy(
canEditVideo({
userId: user.id,
submitterUserId: vod.submitterUserId,
povUserId: typeof vod.pov === "string" ? undefined : vod.pov?.id,
}),
);
await VodRepository.deleteById(vod.id);
return redirect(userVodsPage(user));
};

View File

@@ -8,9 +8,12 @@ import clsx from "clsx";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Button, LinkButton } from "~/components/Button";
import { FormWithConfirm } from "~/components/FormWithConfirm";
import { Image, WeaponImage } from "~/components/Image";
import { Main } from "~/components/Main";
import { YouTubeEmbed } from "~/components/YouTubeEmbed";
import { EditIcon } from "~/components/icons/Edit";
import { TrashIcon } from "~/components/icons/Trash";
import { useUser } from "~/features/auth/core/user";
import { useIsMounted } from "~/hooks/useIsMounted";
import { useSearchParamState } from "~/hooks/useSearchParamState";
@@ -34,6 +37,9 @@ import { canEditVideo } from "../vods-utils";
import "../vods.css";
import { action } from "../actions/vods.$id.server";
export { action };
export const handle: SendouRouteHandle = {
breadcrumb: ({ match }) => {
const data = match.data as SerializeFrom<typeof loader> | undefined;
@@ -79,7 +85,7 @@ export default function VodPage() {
const isMounted = useIsMounted();
const [autoplay, setAutoplay] = React.useState(false);
const data = useLoaderData<typeof loader>();
const { t } = useTranslation(["common"]);
const { t } = useTranslation(["common", "vods"]);
const user = useUser();
return (
@@ -118,13 +124,30 @@ export default function VodPage() {
povUserId:
typeof data.vod.pov === "string" ? undefined : data.vod.pov?.id,
}) ? (
<LinkButton
to={newVodPage(data.vod.id)}
size="tiny"
testId="edit-vod-button"
>
{t("common:actions.edit")}
</LinkButton>
<div className="stack horizontal md">
<LinkButton
to={newVodPage(data.vod.id)}
size="tiny"
testId="edit-vod-button"
icon={<EditIcon />}
>
{t("common:actions.edit")}
</LinkButton>
<FormWithConfirm
dialogHeading={t("vods:deleteConfirm", {
title: data.vod.title,
})}
>
<Button
variant="minimal-destructive"
size="tiny"
type="submit"
icon={<TrashIcon />}
>
{t("common:actions.delete")}
</Button>
</FormWithConfirm>
</div>
) : null}
</div>
</div>

View File

@@ -28,13 +28,18 @@ export function notFoundIfNullLike<T>(value: T | null | undefined): T {
export function badRequestIfFalsy<T>(value: T | null | undefined): T {
if (!value) {
noticeError(new Error("Value is falsy"));
throw new Response(null, { status: 400 });
}
return value;
}
export function unauthorizedIfFalsy<T>(value: T | null | undefined): T {
if (!value) throw new Response(null, { status: 401 });
return value;
}
export function parseSearchParams<T extends z.ZodTypeAny>({
request,
schema,

View File

@@ -22,5 +22,6 @@
"forms.action.deleteMatch": "Delete match",
"noVods": "No videos found matching this filter. Are we missing something? Message Sendou on Discord to get YouTube video submission permissions.",
"addVod": "Add video",
"gainPerms": "Please post on the helpdesk of our Discord to gain permissions to upload videos."
"gainPerms": "Please post on the helpdesk of our Discord to gain permissions to upload videos.",
"deleteConfirm": "Delete video with the title '{{title}}'?"
}