managed how LinkCards are viewed by members
This commit is contained in:
parent
fdbe2e0d9f
commit
51c5615fea
|
@ -12,7 +12,8 @@ type MenuItem =
|
||||||
name: string;
|
name: string;
|
||||||
onClick?: MouseEventHandler;
|
onClick?: MouseEventHandler;
|
||||||
href: string;
|
href: string;
|
||||||
};
|
}
|
||||||
|
| undefined;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClickOutside: Function;
|
onClickOutside: Function;
|
||||||
|
@ -27,7 +28,7 @@ export default function Dropdown({ onClickOutside, className, items }: Props) {
|
||||||
className={`${className} py-1 shadow-md border border-sky-100 bg-gray-50 rounded-md flex flex-col z-20`}
|
className={`${className} py-1 shadow-md border border-sky-100 bg-gray-50 rounded-md flex flex-col z-20`}
|
||||||
>
|
>
|
||||||
{items.map((e, i) => {
|
{items.map((e, i) => {
|
||||||
const inner = (
|
const inner = e && (
|
||||||
<div className="cursor-pointer rounded-md">
|
<div className="cursor-pointer rounded-md">
|
||||||
<div className="flex items-center gap-2 py-1 px-2 hover:bg-slate-200 duration-100">
|
<div className="flex items-center gap-2 py-1 px-2 hover:bg-slate-200 duration-100">
|
||||||
<p className="text-sky-900 select-none">{e.name}</p>
|
<p className="text-sky-900 select-none">{e.name}</p>
|
||||||
|
@ -35,14 +36,16 @@ export default function Dropdown({ onClickOutside, className, items }: Props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return e.href ? (
|
return e && e.href ? (
|
||||||
<Link key={i} href={e.href}>
|
<Link key={i} href={e.href}>
|
||||||
{inner}
|
{inner}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
|
e && (
|
||||||
<div key={i} onClick={e.onClick}>
|
<div key={i} onClick={e.onClick}>
|
||||||
{inner}
|
{inner}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ClickAwayHandler>
|
</ClickAwayHandler>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
CollectionIncludingMembersAndLinkCount,
|
CollectionIncludingMembersAndLinkCount,
|
||||||
LinkIncludingShortenedCollectionAndTags,
|
LinkIncludingShortenedCollectionAndTags,
|
||||||
|
Member,
|
||||||
} from "@/types/global";
|
} from "@/types/global";
|
||||||
import { faFolder, faEllipsis } from "@fortawesome/free-solid-svg-icons";
|
import { faFolder, faEllipsis } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
@ -12,6 +13,7 @@ import useCollectionStore from "@/store/collections";
|
||||||
import useAccountStore from "@/store/account";
|
import useAccountStore from "@/store/account";
|
||||||
import useModalStore from "@/store/modals";
|
import useModalStore from "@/store/modals";
|
||||||
import { faCalendarDays } from "@fortawesome/free-regular-svg-icons";
|
import { faCalendarDays } from "@fortawesome/free-regular-svg-icons";
|
||||||
|
import usePermissions from "@/hooks/usePermissions";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
link: LinkIncludingShortenedCollectionAndTags;
|
link: LinkIncludingShortenedCollectionAndTags;
|
||||||
|
@ -22,6 +24,8 @@ type Props = {
|
||||||
export default function LinkCard({ link, count, className }: Props) {
|
export default function LinkCard({ link, count, className }: Props) {
|
||||||
const { setModal } = useModalStore();
|
const { setModal } = useModalStore();
|
||||||
|
|
||||||
|
const permissions = usePermissions(link.collection.id as number);
|
||||||
|
|
||||||
const [expandDropdown, setExpandDropdown] = useState(false);
|
const [expandDropdown, setExpandDropdown] = useState(false);
|
||||||
|
|
||||||
const { collections } = useCollectionStore();
|
const { collections } = useCollectionStore();
|
||||||
|
@ -59,6 +63,7 @@ export default function LinkCard({ link, count, className }: Props) {
|
||||||
<div
|
<div
|
||||||
className={`bg-gradient-to-tr from-slate-200 from-10% to-gray-50 via-20% shadow hover:shadow-none cursor-pointer duration-100 p-5 rounded-2xl relative group ${className}`}
|
className={`bg-gradient-to-tr from-slate-200 from-10% to-gray-50 via-20% shadow hover:shadow-none cursor-pointer duration-100 p-5 rounded-2xl relative group ${className}`}
|
||||||
>
|
>
|
||||||
|
{permissions && (
|
||||||
<div
|
<div
|
||||||
onClick={() => setExpandDropdown(!expandDropdown)}
|
onClick={() => setExpandDropdown(!expandDropdown)}
|
||||||
id={"expand-dropdown" + link.id}
|
id={"expand-dropdown" + link.id}
|
||||||
|
@ -71,6 +76,7 @@ export default function LinkCard({ link, count, className }: Props) {
|
||||||
id={"expand-dropdown" + link.id}
|
id={"expand-dropdown" + link.id}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -126,7 +132,8 @@ export default function LinkCard({ link, count, className }: Props) {
|
||||||
{expandDropdown ? (
|
{expandDropdown ? (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
items={[
|
items={[
|
||||||
{
|
permissions === true || permissions?.canUpdate
|
||||||
|
? {
|
||||||
name:
|
name:
|
||||||
link?.pinnedBy && link.pinnedBy[0]
|
link?.pinnedBy && link.pinnedBy[0]
|
||||||
? "Unpin"
|
? "Unpin"
|
||||||
|
@ -141,8 +148,10 @@ export default function LinkCard({ link, count, className }: Props) {
|
||||||
});
|
});
|
||||||
setExpandDropdown(false);
|
setExpandDropdown(false);
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
: undefined,
|
||||||
|
permissions === true || permissions?.canUpdate
|
||||||
|
? {
|
||||||
name: "Edit",
|
name: "Edit",
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
setModal({
|
setModal({
|
||||||
|
@ -154,14 +163,17 @@ export default function LinkCard({ link, count, className }: Props) {
|
||||||
});
|
});
|
||||||
setExpandDropdown(false);
|
setExpandDropdown(false);
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
: undefined,
|
||||||
|
permissions === true || permissions?.canDelete
|
||||||
|
? {
|
||||||
name: "Delete",
|
name: "Delete",
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
removeLink(link);
|
removeLink(link);
|
||||||
setExpandDropdown(false);
|
setExpandDropdown(false);
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
|
: undefined,
|
||||||
]}
|
]}
|
||||||
onClickOutside={(e: Event) => {
|
onClickOutside={(e: Event) => {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import useAccountStore from "@/store/account";
|
||||||
|
import useCollectionStore from "@/store/collections";
|
||||||
|
import { CollectionIncludingMembersAndLinkCount, Member } from "@/types/global";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export default function usePermissions(collectionId: number) {
|
||||||
|
const { collections } = useCollectionStore();
|
||||||
|
|
||||||
|
const { account } = useAccountStore();
|
||||||
|
|
||||||
|
const [permissions, setPermissions] = useState<Member | true>();
|
||||||
|
useEffect(() => {
|
||||||
|
const collection = collections.find((e) => e.id === collectionId);
|
||||||
|
|
||||||
|
if (collection) {
|
||||||
|
let getPermission: Member | undefined = collection.members.find(
|
||||||
|
(e) => e.userId === account.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
getPermission?.canCreate === false &&
|
||||||
|
getPermission?.canUpdate === false &&
|
||||||
|
getPermission?.canDelete === false
|
||||||
|
)
|
||||||
|
getPermission = undefined;
|
||||||
|
|
||||||
|
setPermissions(account.id === collection.ownerId || getPermission);
|
||||||
|
}
|
||||||
|
}, [collections]);
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
}
|
Ŝarĝante…
Reference in New Issue