added confirmation when deleting a link + more spacing for dropdowns
This commit is contained in:
parent
4ac7110fb4
commit
230110e912
|
@ -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={() => {
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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={() => {
|
||||
|
|
|
@ -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={() => {
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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={() => {
|
||||
|
|
Ŝarĝante…
Reference in New Issue