Merge pull request #492 from IsaacWise06/issue/442

feat(links): Allow the user to enable/disable merging duplicates
This commit is contained in:
Daniel 2024-03-05 17:33:32 +03:30 committed by GitHub
commit d2b867c438
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 42 additions and 5 deletions

View File

@ -226,8 +226,7 @@ const renderItem = (
return ( return (
<div ref={provided.innerRef} {...provided.draggableProps} className="mb-1"> <div ref={provided.innerRef} {...provided.draggableProps} className="mb-1">
<div <div
className={`${ className={`${currentPath === `/collections/${collection.id}`
currentPath === `/collections/${collection.id}`
? "bg-primary/20 is-active" ? "bg-primary/20 is-active"
: "hover:bg-neutral/20" : "hover:bg-neutral/20"
} duration-100 flex gap-1 items-center pr-2 pl-1 rounded-md`} } duration-100 flex gap-1 items-center pr-2 pl-1 rounded-md`}

View File

@ -109,7 +109,6 @@ export default function NewLinkModal({ onClose }: Props) {
toast.success(`Created!`); toast.success(`Created!`);
onClose(); onClose();
} else toast.error(response.data as string); } else toast.error(response.data as string);
setSubmitLoader(false); setSubmitLoader(false);
return response; return response;

View File

@ -87,6 +87,29 @@ export default async function postLink(
return { response: "Uncaught error.", status: 500 }; return { response: "Uncaught error.", status: 500 };
} }
const user = await prisma.user.findUnique({
where: {
id: userId,
},
});
if (user?.preventDuplicateLinks) {
const existingLink = await prisma.link.findFirst({
where: {
url: link.url?.trim(),
collection: {
ownerId: userId,
},
},
});
if (existingLink)
return {
response: "Link already exists",
status: 409,
};
}
const numberOfLinksTheUserHas = await prisma.link.count({ const numberOfLinksTheUserHas = await prisma.link.count({
where: { where: {
collection: { collection: {
@ -126,7 +149,7 @@ export default async function postLink(
const newLink = await prisma.link.create({ const newLink = await prisma.link.create({
data: { data: {
url: link.url, url: link.url?.trim(),
name: link.name, name: link.name,
description, description,
type: linkType, type: linkType,

View File

@ -190,6 +190,7 @@ export default async function updateUserById(
archiveAsPDF: data.archiveAsPDF, archiveAsPDF: data.archiveAsPDF,
archiveAsWaybackMachine: data.archiveAsWaybackMachine, archiveAsWaybackMachine: data.archiveAsWaybackMachine,
linksRouteTo: data.linksRouteTo, linksRouteTo: data.linksRouteTo,
preventDuplicateLinks: data.preventDuplicateLinks,
password: password:
data.newPassword && data.newPassword !== "" data.newPassword && data.newPassword !== ""
? newHashedPassword ? newHashedPassword

View File

@ -16,6 +16,8 @@ export default function Appearance() {
const { account, updateAccount } = useAccountStore(); const { account, updateAccount } = useAccountStore();
const [user, setUser] = useState<AccountSettings>(account); const [user, setUser] = useState<AccountSettings>(account);
const [preventDuplicateLinks, setPreventDuplicateLinks] =
useState<boolean>(false);
const [archiveAsScreenshot, setArchiveAsScreenshot] = const [archiveAsScreenshot, setArchiveAsScreenshot] =
useState<boolean>(false); useState<boolean>(false);
const [archiveAsPDF, setArchiveAsPDF] = useState<boolean>(false); const [archiveAsPDF, setArchiveAsPDF] = useState<boolean>(false);
@ -32,6 +34,7 @@ export default function Appearance() {
archiveAsPDF, archiveAsPDF,
archiveAsWaybackMachine, archiveAsWaybackMachine,
linksRouteTo, linksRouteTo,
preventDuplicateLinks,
}); });
}, [ }, [
account, account,
@ -39,6 +42,7 @@ export default function Appearance() {
archiveAsPDF, archiveAsPDF,
archiveAsWaybackMachine, archiveAsWaybackMachine,
linksRouteTo, linksRouteTo,
preventDuplicateLinks,
]); ]);
function objectIsEmpty(obj: object) { function objectIsEmpty(obj: object) {
@ -51,6 +55,7 @@ export default function Appearance() {
setArchiveAsPDF(account.archiveAsPDF); setArchiveAsPDF(account.archiveAsPDF);
setArchiveAsWaybackMachine(account.archiveAsWaybackMachine); setArchiveAsWaybackMachine(account.archiveAsWaybackMachine);
setLinksRouteTo(account.linksRouteTo); setLinksRouteTo(account.linksRouteTo);
setPreventDuplicateLinks(account.preventDuplicateLinks);
} }
}, [account]); }, [account]);
@ -144,6 +149,13 @@ export default function Appearance() {
<p className="capitalize text-3xl font-thin inline">Link Settings</p> <p className="capitalize text-3xl font-thin inline">Link Settings</p>
<div className="divider my-3"></div> <div className="divider my-3"></div>
<div className="mb-3">
<Checkbox
label="Prevent duplicate links"
state={preventDuplicateLinks}
onClick={() => setPreventDuplicateLinks(!preventDuplicateLinks)}
/>
</div>
<p>Clicking on Links should:</p> <p>Clicking on Links should:</p>
<div className="p-3"> <div className="p-3">

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "User" ADD COLUMN "preventDuplicateLinks" BOOLEAN NOT NULL DEFAULT false;

View File

@ -43,6 +43,7 @@ model User {
accessTokens AccessToken[] accessTokens AccessToken[]
subscriptions Subscription? subscriptions Subscription?
linksRouteTo LinksRouteTo @default(ORIGINAL) linksRouteTo LinksRouteTo @default(ORIGINAL)
preventDuplicateLinks Boolean @default(false)
archiveAsScreenshot Boolean @default(true) archiveAsScreenshot Boolean @default(true)
archiveAsPDF Boolean @default(true) archiveAsPDF Boolean @default(true)
archiveAsWaybackMachine Boolean @default(false) archiveAsWaybackMachine Boolean @default(false)