added confirmation when deleting a link + more spacing for dropdowns

This commit is contained in:
daniel31x13 2023-12-02 04:42:51 -05:00
parent 4ac7110fb4
commit 230110e912
11 changed files with 124 additions and 49 deletions

View File

@ -73,12 +73,11 @@ export default function CollectionCard({ collection, className }: Props) {
>
<FontAwesomeIcon icon={faEllipsis} title="More" className="w-5 h-5" />
</div>
<ul className="dropdown-content z-[1] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-44 mt-1">
<ul className="dropdown-content z-[1] menu shadow bg-base-200 border border-neutral-content rounded-box w-52 mt-1">
{permissions === true ? (
<li>
<div
role="button"
className="px-2 py-1 rounded-lg"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
@ -91,7 +90,6 @@ export default function CollectionCard({ collection, className }: Props) {
) : undefined}
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {
@ -104,7 +102,6 @@ export default function CollectionCard({ collection, className }: Props) {
</li>
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {

View File

@ -30,10 +30,10 @@ export default function FilterSearchDropdown({
className="w-5 h-5 text-neutral"
/>
</div>
<ul className="dropdown-content z-[30] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-52 mt-1">
<ul className="dropdown-content z-[30] menu shadow bg-base-200 border border-neutral-content rounded-box w-44 mt-1">
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -51,7 +51,7 @@ export default function FilterSearchDropdown({
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -69,7 +69,7 @@ export default function FilterSearchDropdown({
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -90,7 +90,7 @@ export default function FilterSearchDropdown({
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -111,7 +111,7 @@ export default function FilterSearchDropdown({
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>

View File

@ -21,6 +21,7 @@ import Link from "next/link";
import unescapeString from "@/lib/client/unescapeString";
import { useRouter } from "next/router";
import EditLinkModal from "./ModalContent/EditLinkModal";
import DeleteLinkModal from "./ModalContent/DeleteLinkModal";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@ -119,6 +120,7 @@ export default function LinkCard({ link, count, className }: Props) {
);
const [editLinkModal, setEditLinkModal] = useState(false);
const [deleteLinkModal, setDeleteLinkModal] = useState(false);
return (
<div
@ -129,7 +131,7 @@ export default function LinkCard({ link, count, className }: Props) {
{permissions === true ||
permissions?.canUpdate ||
permissions?.canDelete ? (
<div className="dropdown dropdown-left dropdown-start absolute top-3 right-3 z-20">
<div className="dropdown dropdown-left absolute top-3 right-3 z-20">
<div
tabIndex={0}
role="button"
@ -142,12 +144,11 @@ export default function LinkCard({ link, count, className }: Props) {
id={"expand-dropdown" + collection.id}
/>
</div>
<ul className="dropdown-content z-[1] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-40 mr-1">
<ul className="dropdown-content z-[20] menu shadow bg-base-200 border border-neutral-content rounded-box w-44 mr-1">
{permissions === true ? (
<li>
<div
role="button"
className="px-2 py-1 rounded-lg"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
@ -164,7 +165,6 @@ export default function LinkCard({ link, count, className }: Props) {
<li>
<div
role="button"
className="px-2 py-1 rounded-lg"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
@ -179,7 +179,6 @@ export default function LinkCard({ link, count, className }: Props) {
<li>
<div
role="button"
className="px-2 py-1 rounded-lg"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
@ -194,11 +193,10 @@ export default function LinkCard({ link, count, className }: Props) {
<li>
<div
role="button"
className="px-2 py-1 rounded-lg"
tabIndex={0}
onClick={() => {
onClick={(e) => {
(document?.activeElement as HTMLElement)?.blur();
deleteLink();
e.shiftKey ? deleteLink() : setDeleteLinkModal(true);
}}
>
Delete
@ -297,6 +295,12 @@ export default function LinkCard({ link, count, className }: Props) {
activeLink={link}
/>
) : undefined}
{deleteLinkModal ? (
<DeleteLinkModal
onClose={() => setDeleteLinkModal(false)}
activeLink={link}
/>
) : undefined}
</div>
);
}

View File

@ -0,0 +1,89 @@
import React, { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import CollectionSelection from "@/components/InputSelect/CollectionSelection";
import TagSelection from "@/components/InputSelect/TagSelection";
import TextInput from "@/components/TextInput";
import unescapeString from "@/lib/client/unescapeString";
import useLinkStore from "@/store/links";
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
import toast from "react-hot-toast";
import Link from "next/link";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faLink, faTrashCan } from "@fortawesome/free-solid-svg-icons";
import Modal from "../Modal";
type Props = {
onClose: Function;
activeLink: LinkIncludingShortenedCollectionAndTags;
};
export default function DeleteLinkModal({ onClose, activeLink }: Props) {
const [link, setLink] =
useState<LinkIncludingShortenedCollectionAndTags>(activeLink);
let shortendURL;
try {
shortendURL = new URL(link.url).host.toLowerCase();
} catch (error) {
console.log(error);
}
const { removeLink } = useLinkStore();
const [submitLoader, setSubmitLoader] = useState(false);
useEffect(() => {
setLink(activeLink);
}, []);
const deleteLink = async () => {
const load = toast.loading("Deleting...");
const response = await removeLink(link.id as number);
toast.dismiss(load);
response.ok && toast.success(`Link Deleted.`);
onClose();
};
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin text-red-500">Delete Link</p>
<div className="flex flex-col gap-3">
<p>Are you sure you want to delete this Link?</p>
<div role="alert" className="alert alert-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
className="stroke-current shrink-0 h-6 w-6"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</svg>
<span>Warning: This action is irreversible!</span>
</div>
<p>
Hold the <kbd className="kbd kbd-sm">Shift</kbd> key while clicking
'Delete' to bypass this confirmation in the future.
</p>
<button
className={`ml-auto btn w-fit text-white flex items-center gap-2 duration-100 bg-red-500 hover:bg-red-400 hover:dark:bg-red-600 cursor-pointer`}
onClick={deleteLink}
>
<FontAwesomeIcon icon={faTrashCan} className="h-5" />
Delete
</button>
</div>
</Modal>
);
}

View File

@ -75,10 +75,9 @@ export default function Navbar() {
/>
</div>
</div>
<ul className="dropdown-content z-[1] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-32 mt-1">
<ul className="dropdown-content z-[1] menu shadow bg-base-200 border border-neutral-content rounded-box w-40 mt-1">
<li>
<div
className="px-2 py-1 rounded-lg"
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setNewLinkModal(true);
@ -91,7 +90,6 @@ export default function Navbar() {
</li>
<li>
<div
className="px-2 py-1 rounded-lg"
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setNewCollectionModal(true);
@ -112,10 +110,9 @@ export default function Navbar() {
priority={true}
/>
</div>
<ul className="dropdown-content z-[1] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-40 mt-1">
<ul className="dropdown-content z-[1] menu shadow bg-base-200 border border-neutral-content rounded-box w-40 mt-1">
<li>
<Link
className="px-2 py-1 rounded-lg"
href="/settings/account"
onClick={() => (document?.activeElement as HTMLElement)?.blur()}
tabIndex={0}
@ -126,7 +123,6 @@ export default function Navbar() {
</li>
<li>
<div
className="px-2 py-1 rounded-lg"
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
handleToggle();
@ -139,7 +135,6 @@ export default function Navbar() {
</li>
<li>
<div
className="px-2 py-1 rounded-lg"
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
signOut();

View File

@ -22,10 +22,10 @@ export default function SortDropdown({ sortBy, setSort }: Props) {
className="w-5 h-5 text-neutral"
/>
</div>
<ul className="dropdown-content z-[30] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-52 mt-1">
<ul className="dropdown-content z-[30] menu shadow bg-base-200 border border-neutral-content rounded-xl w-52 mt-1">
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -44,7 +44,7 @@ export default function SortDropdown({ sortBy, setSort }: Props) {
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -61,7 +61,7 @@ export default function SortDropdown({ sortBy, setSort }: Props) {
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -78,7 +78,7 @@ export default function SortDropdown({ sortBy, setSort }: Props) {
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -95,7 +95,7 @@ export default function SortDropdown({ sortBy, setSort }: Props) {
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>
@ -112,7 +112,7 @@ export default function SortDropdown({ sortBy, setSort }: Props) {
</li>
<li>
<label
className="label cursor-pointer flex justify-start px-2 py-1 rounded-lg"
className="label cursor-pointer flex justify-start"
tabIndex={0}
role="button"
>

View File

@ -167,11 +167,10 @@ export default function Index() {
className="w-5 h-5"
/>
</div>
<ul className="dropdown-content z-[30] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-44 mt-1">
<ul className="dropdown-content z-[30] menu shadow bg-base-200 border border-neutral-content rounded-box w-52 mt-1">
{permissions === true ? (
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {
@ -185,7 +184,6 @@ export default function Index() {
) : undefined}
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {
@ -200,7 +198,6 @@ export default function Index() {
</li>
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {

View File

@ -57,10 +57,9 @@ export default function Collections() {
className="w-5 h-5"
/>
</div>
<ul className="dropdown-content z-[1] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-36 mt-1">
<ul className="dropdown-content z-[20] menu shadow bg-base-200 border border-neutral-content rounded-box w-40 mt-1">
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {

View File

@ -167,7 +167,7 @@ export default function Dashboard() {
{links[0] ? (
<div className="w-full">
<div
className={`grid overflow-hidden 2xl:grid-cols-3 xl:grid-cols-2 grid-cols-1 gap-5 w-full`}
className={`grid 2xl:grid-cols-3 xl:grid-cols-2 grid-cols-1 gap-5 w-full`}
>
{links.slice(0, showLinks).map((e, i) => (
<LinkCard key={i} link={e} count={i} />
@ -216,12 +216,11 @@ export default function Dashboard() {
/>
<p>Import From</p>
</div>
<ul className="shadow menu dropdown-content z-[1] p-1 bg-base-200 border border-neutral-content rounded-xl mt-1 w-60">
<ul className="shadow menu dropdown-content z-[1] bg-base-200 border border-neutral-content rounded-box mt-1 w-60">
<li>
<label
tabIndex={0}
role="button"
className="px-2 py-1 rounded-lg"
htmlFor="import-linkwarden-file"
title="JSON File"
>
@ -242,7 +241,6 @@ export default function Dashboard() {
<label
tabIndex={0}
role="button"
className="px-2 py-1 rounded-lg"
htmlFor="import-html-file"
title="HTML File"
>
@ -290,7 +288,7 @@ export default function Dashboard() {
{links.some((e) => e.pinnedBy && e.pinnedBy[0]) ? (
<div className="w-full">
<div
className={`grid overflow-hidden 2xl:grid-cols-3 xl:grid-cols-2 grid-cols-1 gap-5 w-full`}
className={`grid 2xl:grid-cols-3 xl:grid-cols-2 grid-cols-1 gap-5 w-full`}
>
{links
.filter((e) => e.pinnedBy && e.pinnedBy[0])

View File

@ -252,12 +252,11 @@ export default function Account() {
>
Import From
</div>
<ul className="shadow menu dropdown-content z-[1] p-1 bg-base-200 border border-neutral-content rounded-xl mt-1 w-60">
<ul className="shadow menu dropdown-content z-[1] bg-base-200 border border-neutral-content rounded-box mt-1 w-60">
<li>
<label
tabIndex={0}
role="button"
className="px-2 py-1 rounded-lg"
htmlFor="import-linkwarden-file"
title="JSON File"
>
@ -278,7 +277,6 @@ export default function Account() {
<label
tabIndex={0}
role="button"
className="px-2 py-1 rounded-lg"
htmlFor="import-html-file"
title="HTML File"
>

View File

@ -159,10 +159,9 @@ export default function Index() {
className="w-5 h-5"
/>
</div>
<ul className="dropdown-content z-[30] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-36 mt-1">
<ul className="dropdown-content z-[30] menu shadow bg-base-200 border border-neutral-content rounded-box w-36 mt-1">
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {
@ -175,7 +174,6 @@ export default function Index() {
</li>
<li>
<div
className="px-2 py-1 rounded-lg"
role="button"
tabIndex={0}
onClick={() => {