From f43398d28885742b8a3c711fcdf5b66c40f63f4a Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 16 May 2023 20:38:28 +0330 Subject: [PATCH] layout redesign for the modals --- components/Dashboard/CollectionItem.tsx | 5 +- components/InputSelect/styles.ts | 1 - components/Modal/AddCollection.tsx | 143 +++++++++++----------- components/Modal/AddLink.tsx | 94 ++++++++------- components/Modal/EditCollection.tsx | 152 ++++++++++++------------ components/Modal/EditLink.tsx | 75 ++++++------ components/Modal/UserSettings.tsx | 55 +++++++++ components/Navbar.tsx | 28 ++++- lib/api/controllers/links/updateLink.ts | 6 - lib/api/controllers/tags/getTags.ts | 23 ++-- pages/register.tsx | 2 +- pages/tags/[id].tsx | 3 - store/tags.ts | 1 + 13 files changed, 330 insertions(+), 258 deletions(-) create mode 100644 components/Modal/UserSettings.tsx diff --git a/components/Dashboard/CollectionItem.tsx b/components/Dashboard/CollectionItem.tsx index eca3e5d..5afd8a5 100644 --- a/components/Dashboard/CollectionItem.tsx +++ b/components/Dashboard/CollectionItem.tsx @@ -18,7 +18,10 @@ export default function ({ collection }: { collection: ExtendedCollection }) { }); return ( - +
diff --git a/components/InputSelect/styles.ts b/components/InputSelect/styles.ts index c24357f..c32a5de 100644 --- a/components/InputSelect/styles.ts +++ b/components/InputSelect/styles.ts @@ -26,7 +26,6 @@ export const styles: StylesConfig = { }), container: (styles) => ({ ...styles, - width: "15rem", border: "1px solid #e0f2fe", borderRadius: "0.375rem", lineHeight: "1.25rem", diff --git a/components/Modal/AddCollection.tsx b/components/Modal/AddCollection.tsx index 5459845..8b23e68 100644 --- a/components/Modal/AddCollection.tsx +++ b/components/Modal/AddCollection.tsx @@ -46,88 +46,91 @@ export default function AddCollection({ toggleCollectionModal }: Props) { return (
-

New Collection

+

New Collection

-
-

- Name - -

- - setNewCollection({ ...newCollection, name: e.target.value }) - } - type="text" - placeholder="e.g. Example Collection" - className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
+
+
+

+ Name + +

+ + setNewCollection({ ...newCollection, name: e.target.value }) + } + type="text" + placeholder="e.g. Example Collection" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +
-
-

Description

- - setNewCollection({ ...newCollection, description: e.target.value }) - } - type="text" - placeholder="Collection description" - className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> +
+

Description

+ + setNewCollection({ + ...newCollection, + description: e.target.value, + }) + } + type="text" + placeholder="Collection description" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +

-
-

Members

- { - setMemberEmail(e.target.value); - }} - onKeyDown={async (e) => { - const checkIfMemberAlreadyExists = newCollection.members.find( - (e) => e.email === memberEmail - ); +

Members

+ { + setMemberEmail(e.target.value); + }} + onKeyDown={async (e) => { + const checkIfMemberAlreadyExists = newCollection.members.find( + (e) => e.email === memberEmail + ); - const ownerEmail = session.data?.user.email; + const ownerEmail = session.data?.user.email; - if ( - e.key === "Enter" && - // no duplicate members - !checkIfMemberAlreadyExists && - // member can't be empty - memberEmail.trim() !== "" && - // member can't be the owner - memberEmail.trim() !== ownerEmail - ) { - // Lookup, get data/err, list ... - const user = await getUserByEmail(memberEmail.trim()); + if ( + e.key === "Enter" && + // no duplicate members + !checkIfMemberAlreadyExists && + // member can't be empty + memberEmail.trim() !== "" && + // member can't be the owner + memberEmail.trim() !== ownerEmail + ) { + // Lookup, get data/err, list ... + const user = await getUserByEmail(memberEmail.trim()); - if (user.email) { - const newMember = { - name: user.name, - email: user.email, - canCreate: false, - canUpdate: false, - canDelete: false, - }; + if (user.email) { + const newMember = { + name: user.name, + email: user.email, + canCreate: false, + canUpdate: false, + canDelete: false, + }; - setNewCollection({ - ...newCollection, - members: [...newCollection.members, newMember], - }); + setNewCollection({ + ...newCollection, + members: [...newCollection.members, newMember], + }); - setMemberEmail(""); - } + setMemberEmail(""); } - }} - type="text" - placeholder="Email" - className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
+ } + }} + type="text" + placeholder="Email" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> {newCollection.members[0] ? (

diff --git a/components/Modal/AddLink.tsx b/components/Modal/AddLink.tsx index ccdfc77..e5f8bbc 100644 --- a/components/Modal/AddLink.tsx +++ b/components/Modal/AddLink.tsx @@ -75,56 +75,62 @@ export default function AddLink({ toggleLinkModal }: Props) { if (response) toggleLinkModal(); }; + return ( -

+

New Link

-
-

- Name - -

- setNewLink({ ...newLink, name: e.target.value })} - type="text" - placeholder="e.g. Example Link" - className="w-60 rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
+
+
+

+ Name + +

+ setNewLink({ ...newLink, name: e.target.value })} + type="text" + placeholder="e.g. Example Link" + className="w-full rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +
-
-

- URL - -

- setNewLink({ ...newLink, url: e.target.value })} - type="text" - placeholder="e.g. http://example.com/" - className="w-60 rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
+
+

+ URL + +

+ setNewLink({ ...newLink, url: e.target.value })} + type="text" + placeholder="e.g. http://example.com/" + className="w-full rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +
-
-

- Collection - -

- -
+
+

+ Collection + +

+ +
-
-

Tags

- +
+

Tags

+ +

Edit Collection

-
-

- Name - -

- - setActiveCollection({ ...activeCollection, name: e.target.value }) - } - type="text" - placeholder="e.g. Example Collection" - className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
+
+
+

+ Name + +

+ + setActiveCollection({ ...activeCollection, name: e.target.value }) + } + type="text" + placeholder="e.g. Example Collection" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +
-
-

Description

- - setActiveCollection({ - ...activeCollection, - description: e.target.value, - }) - } - type="text" - placeholder="Collection description" - className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> +
+

Description

+ + setActiveCollection({ + ...activeCollection, + description: e.target.value, + }) + } + type="text" + placeholder="Collection description" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +

-
-

Members

- { - setMemberEmail(e.target.value); - }} - onKeyDown={async (e) => { - const checkIfMemberAlreadyExists = activeCollection.members.find( - (e) => e.user.email === memberEmail - ); +

Members

+ { + setMemberEmail(e.target.value); + }} + onKeyDown={async (e) => { + const checkIfMemberAlreadyExists = activeCollection.members.find( + (e) => e.user.email === memberEmail + ); - const ownerEmail = session.data?.user.email; + const ownerEmail = session.data?.user.email; - if ( - e.key === "Enter" && - // no duplicate members - !checkIfMemberAlreadyExists && - // member can't be empty - memberEmail.trim() !== "" && - // member can't be the owner - memberEmail.trim() !== ownerEmail - ) { - // Lookup, get data/err, list ... - const user = await getPublicUserDataByEmail(memberEmail.trim()); + if ( + e.key === "Enter" && + // no duplicate members + !checkIfMemberAlreadyExists && + // member can't be empty + memberEmail.trim() !== "" && + // member can't be the owner + memberEmail.trim() !== ownerEmail + ) { + // Lookup, get data/err, list ... + const user = await getPublicUserDataByEmail(memberEmail.trim()); - if (user.email) { - const newMember = { - collectionId: activeCollection.id, - userId: user.id, - canCreate: false, - canUpdate: false, - canDelete: false, - user: { - name: user.name, - email: user.email, - }, - }; + if (user.email) { + const newMember = { + collectionId: activeCollection.id, + userId: user.id, + canCreate: false, + canUpdate: false, + canDelete: false, + user: { + name: user.name, + email: user.email, + }, + }; - setActiveCollection({ - ...activeCollection, - members: [...activeCollection.members, newMember], - }); + setActiveCollection({ + ...activeCollection, + members: [...activeCollection.members, newMember], + }); - setMemberEmail(""); - } + setMemberEmail(""); } - }} - type="text" - placeholder="Email" - className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
+ } + }} + type="text" + placeholder="Email" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> {activeCollection.members[0] ? (

diff --git a/components/Modal/EditLink.tsx b/components/Modal/EditLink.tsx index c085900..e35d42d 100644 --- a/components/Modal/EditLink.tsx +++ b/components/Modal/EditLink.tsx @@ -53,44 +53,47 @@ export default function EditLink({ toggleLinkModal, link }: Props) {

{shortendURL} | {link.title}

-
-

- Name - -

- - setCurrentLink({ ...currentLink, name: e.target.value }) - } - type="text" - placeholder="e.g. Example Link" - className="w-60 rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" - /> -
-
-

- Collection - -

- -
+
+
+

+ Name + +

+ + setCurrentLink({ ...currentLink, name: e.target.value }) + } + type="text" + placeholder="e.g. Example Link" + className="w-full rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +
-
-

Tags

- { - return { label: e.name, value: e.id }; - })} - /> +
+

+ Collection + +

+ +
+ +
+

Tags

+ { + return { label: e.name, value: e.id }; + })} + /> +
diff --git a/components/Modal/UserSettings.tsx b/components/Modal/UserSettings.tsx new file mode 100644 index 0000000..b61055b --- /dev/null +++ b/components/Modal/UserSettings.tsx @@ -0,0 +1,55 @@ +// Copyright (C) 2022-present Daniel31x13 +// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3. +// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// You should have received a copy of the GNU General Public License along with this program. If not, see . + +import { useState } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { NewLink } from "@/types/global"; +import useLinkStore from "@/store/links"; +import RequiredBadge from "../RequiredBadge"; + +type Props = { + toggleSettingsModal: Function; +}; + +export default function UserSettings({ toggleSettingsModal }: Props) { + const [newLink, setNewLink] = useState(); + + const { addLink } = useLinkStore(); + + const submit = async () => { + console.log(newLink); + + const response = await addLink(newLink as NewLink); + + if (response) toggleSettingsModal(); + }; + + return ( +
+

Settings

+ +
+

+ Name + +

+ +
+ +
+ + Apply Settings +
+
+ ); +} diff --git a/components/Navbar.tsx b/components/Navbar.tsx index c04858e..0049278 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -22,6 +22,7 @@ import ClickAwayHandler from "@/components/ClickAwayHandler"; import Sidebar from "@/components/Sidebar"; import { useRouter } from "next/router"; import Search from "@/components/Search"; +import UserSettings from "./Modal/UserSettings"; export default function () { const { data: session } = useSession(); @@ -31,6 +32,7 @@ export default function () { const user = session?.user; const [linkModal, setLinkModal] = useState(false); + const [settingsModal, setSettingsModal] = useState(false); const [sidebar, setSidebar] = useState(false); const router = useRouter(); @@ -49,6 +51,10 @@ export default function () { setLinkModal(!linkModal); }; + const toggleSettingsModal = () => { + setSettingsModal(!settingsModal); + }; + return (
- {linkModal ? ( - - - - ) : null} -
, + onClick: () => { + toggleSettingsModal(); + setProfileDropdown(!profileDropdown); + }, }, { name: "Logout", @@ -114,6 +118,18 @@ export default function () { /> ) : null} + {linkModal ? ( + + + + ) : null} + + {settingsModal ? ( + + + + ) : null} + {sidebar ? (
diff --git a/lib/api/controllers/links/updateLink.ts b/lib/api/controllers/links/updateLink.ts index f30860b..2854ed2 100644 --- a/lib/api/controllers/links/updateLink.ts +++ b/lib/api/controllers/links/updateLink.ts @@ -11,12 +11,6 @@ import getPermission from "@/lib/api/getPermission"; export default async function (link: ExtendedLink, userId: number) { if (!link) return { response: "Please choose a valid link.", status: 401 }; - const collectionIsAccessible = await getPermission(userId, link.collectionId); - - const memberHasAccess = collectionIsAccessible?.members.some( - (e: UsersAndCollections) => e.userId === userId && e.canUpdate - ); - if (link.collection.ownerId) { const collectionIsAccessible = await getPermission( userId, diff --git a/lib/api/controllers/tags/getTags.ts b/lib/api/controllers/tags/getTags.ts index 07bf3bb..92dd3b2 100644 --- a/lib/api/controllers/tags/getTags.ts +++ b/lib/api/controllers/tags/getTags.ts @@ -17,27 +17,22 @@ export default async function (userId: number) { const tags = await prisma.tag.findMany({ where: { - ownerId: userId, - owner: { - OR: [ - { - id: userId, - }, - { - collections: { - some: { + OR: [ + { ownerId: userId }, // Tags owned by the user + { + links: { + some: { + collection: { members: { some: { - user: { - id: userId, - }, + userId, // Tags from collections where the user is a member }, }, }, }, }, - ], - }, + }, + ], }, orderBy: { links: { diff --git a/pages/register.tsx b/pages/register.tsx index e9fae86..29e939b 100644 --- a/pages/register.tsx +++ b/pages/register.tsx @@ -58,7 +58,7 @@ export default function () {

Linkwarden

setForm({ ...form, name: e.target.value })} className="border border-gray-700 rounded-md block m-2 mx-auto p-2" diff --git a/pages/tags/[id].tsx b/pages/tags/[id].tsx index f1e14af..c9c8a89 100644 --- a/pages/tags/[id].tsx +++ b/pages/tags/[id].tsx @@ -21,9 +21,6 @@ export default function () { const { links } = useLinkStore(); const { tags } = useTagStore(); - const [linkModal, setLinkModal] = useState(false); - const [editCollectionModal, setEditCollectionModal] = useState(false); - const [deleteCollectionModal, setDeleteCollectionModal] = useState(false); const [sortDropdown, setSortDropdown] = useState(false); const [sortBy, setSortBy] = useState("Name (A-Z)"); diff --git a/store/tags.ts b/store/tags.ts index e4d364f..b2a22c4 100644 --- a/store/tags.ts +++ b/store/tags.ts @@ -5,6 +5,7 @@ import { create } from "zustand"; import { Tag } from "@prisma/client"; +import tags from "@/pages/api/routes/tags"; type TagStore = { tags: Tag[];