improvements

This commit is contained in:
daniel31x13
2024-11-07 01:12:05 -05:00
parent 7eaff332a9
commit 736e98ac7d
21 changed files with 277 additions and 281 deletions
+65 -41
View File
@@ -42,6 +42,7 @@ type Props = {
standalone?: boolean;
mode?: "view" | "edit";
setMode?: Function;
onUpdateArchive?: Function;
};
export default function LinkDetails({
@@ -50,6 +51,7 @@ export default function LinkDetails({
standalone,
mode = "view",
setMode,
onUpdateArchive,
}: Props) {
const [link, setLink] =
useState<LinkIncludingShortenedCollectionAndTags>(activeLink);
@@ -236,46 +238,50 @@ export default function LinkDetails({
<div className="duration-100 h-40 skeleton rounded-none"></div>
)}
{!standalone && (permissions === true || permissions?.canUpdate) && (
<div className="absolute top-0 bottom-0 left-0 right-0 opacity-0 group-hover:opacity-100 duration-100 flex justify-end items-end">
<label className="btn btn-xs mb-2 mr-3 opacity-50 hover:opacity-100">
{t("upload_preview_image")}
<input
type="file"
accept="image/jpg, image/jpeg, image/png"
onChange={async (e) => {
const file = e.target.files?.[0];
if (!file) return;
{!standalone &&
(permissions === true || permissions?.canUpdate) &&
!isPublicRoute && (
<div className="absolute top-0 bottom-0 left-0 right-0 opacity-0 group-hover:opacity-100 duration-100 flex justify-end items-end">
<label className="btn btn-xs mb-2 mr-3 opacity-50 hover:opacity-100">
{t("upload_preview_image")}
<input
type="file"
accept="image/jpg, image/jpeg, image/png"
onChange={async (e) => {
const file = e.target.files?.[0];
if (!file) return;
const load = toast.loading(t("updating"));
const load = toast.loading(t("updating"));
await updatePreview.mutateAsync(
{
linkId: link.id as number,
file,
},
{
onSettled: (data, error) => {
toast.dismiss(load);
if (error) {
toast.error(error.message);
} else {
toast.success(t("updated"));
setLink({ updatedAt: data.updatedAt, ...link });
}
await updatePreview.mutateAsync(
{
linkId: link.id as number,
file,
},
}
);
}}
className="hidden"
/>
</label>
</div>
)}
{
onSettled: (data, error) => {
toast.dismiss(load);
if (error) {
toast.error(error.message);
} else {
toast.success(t("updated"));
setLink({ updatedAt: data.updatedAt, ...link });
}
},
}
);
}}
className="hidden"
/>
</label>
</div>
)}
</div>
{!standalone && (permissions === true || permissions?.canUpdate) ? (
{!standalone &&
(permissions === true || permissions?.canUpdate) &&
!isPublicRoute ? (
<div className="-mt-14 ml-8 relative w-fit pb-2">
<div className="tooltip tooltip-bottom" data-tip={t("change_icon")}>
<LinkIcon
@@ -505,12 +511,30 @@ export default function LinkDetails({
<div>
<br />
<p
className="text-sm mb-2 text-neutral"
title={t("available_formats")}
>
{link.url ? t("preserved_formats") : t("file")}
</p>
<div className="flex gap-1 items-center mb-2">
<p
className="text-sm text-neutral"
title={t("available_formats")}
>
{link.url ? t("preserved_formats") : t("file")}
</p>
{onUpdateArchive &&
(permissions === true || permissions?.canUpdate) &&
!isPublicRoute && (
<div
className="tooltip tooltip-bottom"
data-tip={t("refresh_preserved_formats")}
>
<button
className="btn btn-xs btn-ghost btn-square text-neutral"
onClick={() => onUpdateArchive()}
>
<i className="bi-arrow-clockwise text-sm" />
</button>
</div>
)}
</div>
<div className={`flex flex-col rounded-md p-3 bg-base-200`}>
{monolithAvailable(link) ? (
@@ -64,7 +64,7 @@ export default function LinkActions({ link, btnStyle }: Props) {
onClick={() => setLinkModal(true)}
>
<div className={clsx("btn btn-sm btn-square text-neutral", btnStyle)}>
<i title="More" className="bi-three-dots text-xl" />
<i title="More" className="bi-info-circle text-xl" />
</div>
</div>
) : (
@@ -127,22 +127,6 @@ export default function LinkActions({ link, btnStyle }: Props) {
</div>
</li>
)}
{link.type === "url" &&
(permissions === true || permissions?.canUpdate) && (
<li>
<div
role="button"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
updateArchive();
}}
className="whitespace-nowrap"
>
{t("refresh_preserved_formats")}
</div>
</li>
)}
{(permissions === true || permissions?.canDelete) && (
<li>
<div
@@ -146,6 +146,8 @@ export default function LinkCard({ link, columns, editMode }: Props) {
editMode &&
(permissions === true || permissions?.canCreate || permissions?.canDelete);
const isPublicRoute = router.pathname.startsWith("/public") ? true : false;
return (
<div
ref={ref}
@@ -233,7 +235,7 @@ export default function LinkCard({ link, columns, editMode }: Props) {
{/* Overlay on hover */}
<div className="absolute pointer-events-none top-0 left-0 right-0 bottom-0 bg-base-100 bg-opacity-0 group-hover:bg-opacity-20 group-focus-within:opacity-20 rounded-2xl duration-100"></div>
<LinkActions link={link} collection={collection} />
<LinkPin link={link} />
{!isPublicRoute && <LinkPin link={link} />}
</div>
);
}
@@ -14,7 +14,7 @@ export default function LinkCollection({
link: LinkIncludingShortenedCollectionAndTags;
collection: CollectionIncludingMembersAndLinkCount;
}) {
return (
return collection?.name ? (
<>
<Link
href={`/collections/${link.collection.id}`}
@@ -40,5 +40,7 @@ export default function LinkCollection({
<p className="truncate capitalize">{collection?.name}</p>
</Link>
</>
) : (
<></>
);
}
@@ -20,6 +20,7 @@ import { useUser } from "@/hooks/store/user";
import { useLinks } from "@/hooks/store/links";
import useLocalSettingsStore from "@/store/localSettings";
import LinkPin from "./LinkPin";
import { useRouter } from "next/router";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@@ -91,6 +92,9 @@ export default function LinkCardCompact({ link, editMode }: Props) {
editMode &&
(permissions === true || permissions?.canCreate || permissions?.canDelete);
const router = useRouter();
let isPublic = router.pathname.startsWith("/public") ? true : undefined;
return (
<>
<div
@@ -135,7 +139,7 @@ export default function LinkCardCompact({ link, editMode }: Props) {
</div>
</div>
</div>
<LinkPin link={link} btnStyle="btn-ghost" />
{!isPublic && <LinkPin link={link} btnStyle="btn-ghost" />}
<LinkActions link={link} collection={collection} btnStyle="btn-ghost" />
</div>
<div className="last:hidden rounded-none my-0 mx-1 border-t border-base-300 h-[1px]"></div>
@@ -25,6 +25,7 @@ import { useGetLink, useLinks } from "@/hooks/store/links";
import useLocalSettingsStore from "@/store/localSettings";
import clsx from "clsx";
import LinkPin from "./LinkPin";
import { useRouter } from "next/router";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@@ -108,6 +109,10 @@ export default function LinkMasonry({ link, editMode, columns }: Props) {
const isVisible = useOnScreen(ref);
const permissions = usePermissions(collection?.id as number);
const router = useRouter();
let isPublic = router.pathname.startsWith("/public") ? true : undefined;
useEffect(() => {
let interval: NodeJS.Timeout | null = null;
@@ -241,7 +246,7 @@ export default function LinkMasonry({ link, editMode, columns }: Props) {
{/* Overlay on hover */}
<div className="absolute pointer-events-none top-0 left-0 right-0 bottom-0 bg-base-100 bg-opacity-0 group-hover:bg-opacity-20 group-focus-within:opacity-20 rounded-2xl duration-100"></div>
<LinkActions link={link} collection={collection} />
<LinkPin link={link} />
{!isPublic && <LinkPin link={link} />}
</div>
);
}
+73 -70
View File
@@ -51,7 +51,7 @@ export default function LinkModal({
onClick={() => onClose()}
></div>
{(permissions === true || permissions?.canUpdate) && (
{(permissions === true || permissions?.canUpdate) && !isPublicRoute && (
<div className="flex gap-1 h-8 rounded-full bg-neutral-content bg-opacity-50 text-base-content p-1 text-xs duration-100 select-none z-10">
<div
className={clsx(
@@ -79,87 +79,89 @@ export default function LinkModal({
)}
<div className="flex gap-2">
<div className={`dropdown dropdown-end z-20`}>
<div
tabIndex={0}
role="button"
onMouseDown={dropdownTriggerer}
className="btn btn-sm btn-circle text-base-content opacity-50 hover:opacity-100 z-10"
>
<i title="More" className="bi-three-dots text-xl" />
</div>
<ul
className={`dropdown-content z-[20] menu shadow bg-base-200 border border-neutral-content rounded-box`}
>
{
<li>
<div
role="button"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
onPin();
}}
className="whitespace-nowrap"
>
{link?.pinnedBy && link.pinnedBy[0]
? t("unpin")
: t("pin_to_dashboard")}
</div>
</li>
}
{link.type === "url" &&
(permissions === true || permissions?.canUpdate) && (
{!isPublicRoute && (
<div className={`dropdown dropdown-end z-20`}>
<div
tabIndex={0}
role="button"
onMouseDown={dropdownTriggerer}
className="btn btn-sm btn-circle text-base-content opacity-50 hover:opacity-100 z-10"
>
<i title="More" className="bi-three-dots text-xl" />
</div>
<ul
className={`dropdown-content z-[20] menu shadow bg-base-200 border border-neutral-content rounded-box`}
>
{
<li>
<div
role="button"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
onUpdateArchive();
onPin();
}}
className="whitespace-nowrap"
>
{t("refresh_preserved_formats")}
{link?.pinnedBy && link.pinnedBy[0]
? t("unpin")
: t("pin_to_dashboard")}
</div>
</li>
}
{link.type === "url" &&
(permissions === true || permissions?.canUpdate) && (
<li>
<div
role="button"
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
onUpdateArchive();
}}
className="whitespace-nowrap"
>
{t("refresh_preserved_formats")}
</div>
</li>
)}
{(permissions === true || permissions?.canDelete) && (
<li>
<div
role="button"
tabIndex={0}
onClick={async (e) => {
(document?.activeElement as HTMLElement)?.blur();
console.log(e.shiftKey);
if (e.shiftKey) {
const load = toast.loading(t("deleting"));
await deleteLink.mutateAsync(link.id as number, {
onSettled: (data, error) => {
toast.dismiss(load);
if (error) {
toast.error(error.message);
} else {
toast.success(t("deleted"));
}
},
});
onClose();
} else {
onDelete();
onClose();
}
}}
className="whitespace-nowrap"
>
{t("delete")}
</div>
</li>
)}
{(permissions === true || permissions?.canDelete) && (
<li>
<div
role="button"
tabIndex={0}
onClick={async (e) => {
(document?.activeElement as HTMLElement)?.blur();
console.log(e.shiftKey);
if (e.shiftKey) {
const load = toast.loading(t("deleting"));
await deleteLink.mutateAsync(link.id as number, {
onSettled: (data, error) => {
toast.dismiss(load);
if (error) {
toast.error(error.message);
} else {
toast.success(t("deleted"));
}
},
});
onClose();
} else {
onDelete();
onClose();
}
}}
className="whitespace-nowrap"
>
{t("delete")}
</div>
</li>
)}
</ul>
</div>
</ul>
</div>
)}
{link.url && (
<Link
href={link.url}
@@ -176,6 +178,7 @@ export default function LinkModal({
className="sm:mt-0 -mt-11"
mode={mode}
setMode={(mode: "view" | "edit") => setMode(mode)}
onUpdateArchive={onUpdateArchive}
/>
</div>
</Drawer>