add ability to setShareLinkExpiresAt value
This commit is contained in:
parent
cc4f2ad4ee
commit
ea33309b76
5 changed files with 69 additions and 50 deletions
|
|
@ -24,7 +24,7 @@ model Video {
|
||||||
userId String
|
userId String
|
||||||
sharing Boolean @default(false)
|
sharing Boolean @default(false)
|
||||||
delete_after_link_expires Boolean @default(false)
|
delete_after_link_expires Boolean @default(false)
|
||||||
shareExpiryAt DateTime?
|
shareLinkExpiresAt DateTime?
|
||||||
linkShareSeo Boolean @default(false)
|
linkShareSeo Boolean @default(false)
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,51 @@
|
||||||
import { Listbox, Transition } from "@headlessui/react";
|
import { Listbox, Transition } from "@headlessui/react";
|
||||||
import { Fragment, useState } from "react";
|
import { Fragment } from "react";
|
||||||
import { getTime } from "~/utils/getTime";
|
import { getTime } from "~/utils/getTime";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
shareExpiryAt: Date | null;
|
shareLinkExpiresAt: Date | null;
|
||||||
|
videoId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ExpireDateSelectMenu({ shareExpiryAt }: Props) {
|
export default function ExpireDateSelectMenu({
|
||||||
const handleChange = (value) => {
|
shareLinkExpiresAt,
|
||||||
|
videoId,
|
||||||
|
}: Props) {
|
||||||
|
const utils = api.useContext();
|
||||||
|
|
||||||
|
const setShareLinkExpiresAtMutation =
|
||||||
|
api.video.setShareLinkExpiresAt.useMutation({
|
||||||
|
onMutate: async ({ videoId, shareLinkExpiresAt }) => {
|
||||||
|
await utils.video.get.cancel();
|
||||||
|
const previousValue = utils.video.get.getData({ videoId });
|
||||||
|
if (previousValue) {
|
||||||
|
utils.video.get.setData(
|
||||||
|
{ videoId },
|
||||||
|
{ ...previousValue, shareLinkExpiresAt }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return { previousValue };
|
||||||
|
},
|
||||||
|
onError: (err, { videoId }, context) => {
|
||||||
|
if (context?.previousValue) {
|
||||||
|
utils.video.get.setData({ videoId }, context.previousValue);
|
||||||
|
}
|
||||||
|
console.error(err.message);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const handleChange = (value: string) => {
|
||||||
console.log("selecting value", value);
|
console.log("selecting value", value);
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
now.setHours(now.getHours() + 1);
|
||||||
|
|
||||||
|
console.log(now);
|
||||||
|
|
||||||
|
setShareLinkExpiresAtMutation.mutate({
|
||||||
|
videoId,
|
||||||
|
shareLinkExpiresAt: now,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const availableExpireDates = [
|
const availableExpireDates = [
|
||||||
|
|
@ -21,12 +58,12 @@ export default function ExpireDateSelectMenu({ shareExpiryAt }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Listbox value={shareExpiryAt} onChange={handleChange}>
|
<Listbox value={shareLinkExpiresAt} onChange={handleChange}>
|
||||||
<div>
|
<div>
|
||||||
<Listbox.Button className="h-6 rounded border border-solid border-[#d5d9df] bg-white px-[7px] font-medium">
|
<Listbox.Button className="h-6 rounded border border-solid border-[#d5d9df] bg-white px-[7px] font-medium">
|
||||||
<span className="block truncate">
|
<span className="block truncate">
|
||||||
{typeof shareExpiryAt === null
|
{shareLinkExpiresAt
|
||||||
? getTime(shareExpiryAt)
|
? getTime(shareLinkExpiresAt)
|
||||||
: "Never expire"}
|
: "Never expire"}
|
||||||
</span>
|
</span>
|
||||||
</Listbox.Button>
|
</Listbox.Button>
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,8 @@ export function ShareModal({ video }: Props) {
|
||||||
<div className="flex h-6 items-center justify-between">
|
<div className="flex h-6 items-center justify-between">
|
||||||
<span>Expire link</span>
|
<span>Expire link</span>
|
||||||
<ExpireDateSelectMenu
|
<ExpireDateSelectMenu
|
||||||
shareExpiryAt={video.shareExpiryAt}
|
videoId={video.id}
|
||||||
|
shareLinkExpiresAt={video.shareLinkExpiresAt}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3 flex h-6 items-center justify-between">
|
<div className="mt-3 flex h-6 items-center justify-between">
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,28 @@ export const videoRouter = createTRPCRouter({
|
||||||
throw new TRPCError({ code: "FORBIDDEN" });
|
throw new TRPCError({ code: "FORBIDDEN" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
updateVideo,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
setShareLinkExpiresAt: protectedProcedure
|
||||||
|
.input(z.object({ videoId: z.string(), shareLinkExpiresAt: z.date() }))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const updateVideo = await ctx.prisma.video.updateMany({
|
||||||
|
where: {
|
||||||
|
id: input.videoId,
|
||||||
|
userId: ctx.session.user.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
shareLinkExpiresAt: input.shareLinkExpiresAt,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (updateVideo.count === 0) {
|
||||||
|
throw new TRPCError({ code: "FORBIDDEN" });
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
updateVideo,
|
updateVideo,
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
import { type RefCallback, useRef, useCallback, useMemo } from "react";
|
|
||||||
import { createPopper, type Options } from "@popperjs/core";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example implementation to use Popper: https://popper.js.org/
|
|
||||||
*/
|
|
||||||
export function usePopper(
|
|
||||||
options?: Partial<Options>
|
|
||||||
): [RefCallback<Element | null>, RefCallback<HTMLElement | null>] {
|
|
||||||
let reference = useRef<Element>(null);
|
|
||||||
let popper = useRef<HTMLElement>(null);
|
|
||||||
|
|
||||||
let cleanupCallback = useRef(() => {});
|
|
||||||
|
|
||||||
let instantiatePopper = useCallback(() => {
|
|
||||||
if (!reference.current) return;
|
|
||||||
if (!popper.current) return;
|
|
||||||
|
|
||||||
if (cleanupCallback.current) cleanupCallback.current();
|
|
||||||
|
|
||||||
cleanupCallback.current = createPopper(
|
|
||||||
reference.current,
|
|
||||||
popper.current,
|
|
||||||
options
|
|
||||||
).destroy;
|
|
||||||
}, [reference, popper, cleanupCallback, options]);
|
|
||||||
|
|
||||||
return useMemo(
|
|
||||||
() => [
|
|
||||||
(referenceDomNode) => {
|
|
||||||
reference.current = referenceDomNode;
|
|
||||||
instantiatePopper();
|
|
||||||
},
|
|
||||||
(popperDomNode) => {
|
|
||||||
popper.current = popperDomNode;
|
|
||||||
instantiatePopper();
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[reference, popper, instantiatePopper]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue