diff --git a/.env.sample b/.env.sample index 74e9192..0edaa4b 100644 --- a/.env.sample +++ b/.env.sample @@ -12,7 +12,12 @@ PAGINATION_TAKE_COUNT= STORAGE_FOLDER= AUTOSCROLL_TIMEOUT= NEXT_PUBLIC_DISABLE_REGISTRATION= +NEXT_PUBLIC_CREDENTIALS_ENABLED= +DISABLE_NEW_SSO_USERS= RE_ARCHIVE_LIMIT= +NEXT_PUBLIC_MAX_FILE_SIZE= +MAX_LINKS_PER_USER= +ARCHIVE_TAKE_COUNT= # AWS S3 Settings SPACES_KEY= @@ -27,8 +32,348 @@ NEXT_PUBLIC_EMAIL_PROVIDER= EMAIL_FROM= EMAIL_SERVER= + +# +# SSO Providers +# + +# 42 School +NEXT_PUBLIC_FORTYTWO_ENABLED= +FORTYTWO_CUSTOM_NAME= +FORTYTWO_CLIENT_ID= +FORTYTWO_CLIENT_SECRET= + +# Apple +NEXT_PUBLIC_APPLE_ENABLED= +APPLE_CUSTOM_NAME= +APPLE_ID= +APPLE_SECRET= + +# Atlassian +NEXT_PUBLIC_ATLASSIAN_ENABLED= +ATLASSIAN_CUSTOM_NAME= +ATLASSIAN_CLIENT_ID= +ATLASSIAN_CLIENT_SECRET= +ATLASSIAN_SCOPE= + +# Auth0 +NEXT_PUBLIC_AUTH0_ENABLED= +AUTH0_CUSTOM_NAME= +AUTH0_ISSUER= +AUTH0_CLIENT_SECRET= +AUTH0_CLIENT_ID= + +# Authentik +NEXT_PUBLIC_AUTHENTIK_ENABLED= +AUTHENTIK_CUSTOM_NAME= +AUTHENTIK_ISSUER= +AUTHENTIK_CLIENT_ID= +AUTHENTIK_CLIENT_SECRET= + +# Battle.net +NEXT_PUBLIC_BATTLENET_ENABLED= +BATTLENET_CUSTOM_NAME= +BATTLENET_CLIENT_ID= +BATTLENET_CLIENT_SECRET= +BATLLENET_ISSUER= + +# Box +NEXT_PUBLIC_BOX_ENABLED= +BOX_CUSTOM_NAME= +BOX_CLIENT_ID= +BOX_CLIENT_SECRET= + +# Bungie +NEXT_PUBLIC_BUNGIE_ENABLED= +BUNGIE_CUSTOM_NAME= +BUNGIE_CLIENT_ID= +BUNGIE_CLIENT_SECRET= +BUNGIE_API_KEY= + +# Cognito +NEXT_PUBLIC_COGNITO_ENABLED= +COGNITO_CUSTOM_NAME= +COGNITO_CLIENT_ID= +COGNITO_CLIENT_SECRET= +COGNITO_ISSUER= + +# Coinbase +NEXT_PUBLIC_COINBASE_ENABLED= +COINBASE_CUSTOM_NAME= +COINBASE_CLIENT_ID= +COINBASE_CLIENT_SECRET= + +# Discord +NEXT_PUBLIC_DISCORD_ENABLED= +DISCORD_CUSTOM_NAME= +DISCORD_CLIENT_ID= +DISCORD_CLIENT_SECRET= + +# Dropbox +NEXT_PUBLIC_DROPBOX_ENABLED= +DROPBOX_CUSTOM_NAME= +DROPBOX_CLIENT_ID= +DROPBOX_CLIENT_SECRET= + +# DuendeIndentityServer6 +NEXT_PUBLIC_DUENDE_IDS6_ENABLED= +DUENDE_IDS6_CUSTOM_NAME= +DUENDE_IDS6_CLIENT_ID= +DUENDE_IDS6_CLIENT_SECRET= +DUENDE_IDS6_ISSUER= + +# EVE Online +NEXT_PUBLIC_EVEONLINE_ENABLED= +EVEONLINE_CUSTOM_NAME= +EVEONLINE_CLIENT_ID= +EVEONLINE_CLIENT_SECRET= + +# Facebook +NEXT_PUBLIC_FACEBOOK_ENABLED= +FACEBOOK_CUSTOM_NAME= +FACEBOOK_CLIENT_ID= +FACEBOOK_CLIENT_SECRET= + +# FACEIT +NEXT_PUBLIC_FACEIT_ENABLED= +FACEIT_CUSTOM_NAME= +FACEIT_CLIENT_ID= +FACEIT_CLIENT_SECRET= + +# Foursquare +NEXT_PUBLIC_FOURSQUARE_ENABLED= +FOURSQUARE_CUSTOM_NAME= +FOURSQUARE_CLIENT_ID= +FOURSQUARE_CLIENT_SECRET= +FOURSQUARE_APIVERSION= + +# Freshbooks +NEXT_PUBLIC_FRESHBOOKS_ENABLED= +FRESHBOOKS_CUSTOM_NAME= +FRESHBOOKS_CLIENT_ID= +FRESHBOOKS_CLIENT_SECRET= + +# FusionAuth +NEXT_PUBLIC_FUSIONAUTH_ENABLED= +FUSIONAUTH_CUSTOM_NAME= +FUSIONAUTH_CLIENT_ID= +FUSIONAUTH_CLIENT_SECRET= +FUSIONAUTH_ISSUER= +FUSIONAUTH_TENANT_ID= + +# GitHub +NEXT_PUBLIC_GITHUB_ENABLED= +GITHUB_CUSTOM_NAME= +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= + +# GitLab +NEXT_PUBLIC_GITLAB_ENABLED= +GITLAB_CUSTOM_NAME= +GITLAB_CLIENT_ID= +GITLAB_CLIENT_SECRET= + +# Google +NEXT_PUBLIC_GOOGLE_ENABLED= +GOOGLE_CUSTOM_NAME= +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= + +# HubSpot +NEXT_PUBLIC_HUBSPOT_ENABLED= +HUBSPOT_CUSTOM_NAME= +HUBSPOT_CLIENT_ID= +HUBSPOT_CLIENT_SECRET= + +# IdentityServer4 +NEXT_PUBLIC_IDS4_ENABLED= +IDS4_CUSTOM_NAME= +IDS4_CLIENT_ID= +IDS4_CLIENT_SECRET= +IDS4_ISSUER= + +# Kakao +NEXT_PUBLIC_KAKAO_ENABLED= +KAKAO_CUSTOM_NAME= +KAKAO_CLIENT_ID= +KAKAO_CLIENT_SECRET= + # Keycloak NEXT_PUBLIC_KEYCLOAK_ENABLED= +KEYCLOAK_CUSTOM_NAME= KEYCLOAK_ISSUER= KEYCLOAK_CLIENT_ID= KEYCLOAK_CLIENT_SECRET= + +# LINE +NEXT_PUBLIC_LINE_ENABLED= +LINE_CUSTOM_NAME= +LINE_CLIENT_ID= +LINE_CLIENT_SECRET= + +# LinkedIn +NEXT_PUBLIC_LINKEDIN_ENABLED= +LINKEDIN_CUSTOM_NAME= +LINKEDIN_CLIENT_ID= +LINKEDIN_CLIENT_SECRET= + +# Mailchimp +NEXT_PUBLIC_MAILCHIMP_ENABLED= +MAILCHIMP_CUSTOM_NAME= +MAILCHIMP_CLIENT_ID= +MAILCHIMP_CLIENT_SECRET= + +# Mail.ru +NEXT_PUBLIC_MAILRU_ENABLED= +MAILRU_CUSTOM_NAME= +MAILRU_CLIENT_ID= +MAILRU_CLIENT_SECRET= + +# Naver +NEXT_PUBLIC_NAVER_ENABLED= +NAVER_CUSTOM_NAME= +NAVER_CLIENT_ID= +NAVER_CLIENT_SECRET= + +# Netlify +NEXT_PUBLIC_NETLIFY_ENABLED= +NETLIFY_CUSTOM_NAME= +NETLIFY_CLIENT_ID= +NETLIFY_CLIENT_SECRET= + +# Okta +NEXT_PUBLIC_OKTA_ENABLED= +OKTA_CUSTOM_NAME= +OKTA_CLIENT_ID= +OKTA_CLIENT_SECRET= +OKTA_ISSUER= + +# OneLogin +NEXT_PUBLIC_ONELOGIN_ENABLED= +ONELOGIN_CUSTOM_NAME= +ONELOGIN_CLIENT_ID= +ONELOGIN_CLIENT_SECRET= +ONELOGIN_ISSUER= + +# Osso +NEXT_PUBLIC_OSSO_ENABLED= +OSSO_CUSTOM_NAME= +OSSO_CLIENT_ID= +OSSO_CLIENT_SECRET= +OSSO_ISSUER= + +# osu! +NEXT_PUBLIC_OSU_ENABLED= +OSU_CUSTOM_NAME= +OSU_CLIENT_ID= +OSU_CLIENT_SECRET= + +# Patreon +NEXT_PUBLIC_PATREON_ENABLED= +PATREON_CUSTOM_NAME= +PATREON_CLIENT_ID= +PATREON_CLIENT_SECRET= + +# Pinterest +NEXT_PUBLIC_PINTEREST_ENABLED= +PINTEREST_CUSTOM_NAME= +PINTEREST_CLIENT_ID= +PINTEREST_CLIENT_SECRET= + +# Pipedrive +NEXT_PUBLIC_PIPEDRIVE_ENABLED= +PIPEDRIVE_CUSTOM_NAME= +PIPEDRIVE_CLIENT_ID= +PIPEDRIVE_CLIENT_SECRET= + +# Reddit +NEXT_PUBLIC_REDDIT_ENABLED= +REDDIT_CUSTOM_NAME= +REDDIT_CLIENT_ID= +REDDIT_CLIENT_SECRET= + +# Salesforce +NEXT_PUBLIC_SALESFORCE_ENABLED= +SALESFORCE_CUSTOM_NAME= +SALESFORCE_CLIENT_ID= +SALESFORCE_CLIENT_SECRET= + +# Slack +NEXT_PUBLIC_SLACK_ENABLED= +SLACK_CUSTOM_NAME= +SLACK_CLIENT_ID= +SLACK_CLIENT_SECRET= + +# Spotify +NEXT_PUBLIC_SPOTIFY_ENABLED= +SPOTIFY_CUSTOM_NAME= +SPOTIFY_CLIENT_ID= +SPOTIFY_CLIENT_SECRET= + +# Strava +NEXT_PUBLIC_STRAVA_ENABLED= +STRAVA_CUSTOM_NAME= +STRAVA_CLIENT_ID= +STRAVA_CLIENT_SECRET= + +# Todoist +NEXT_PUBLIC_TODOIST_ENABLED= +TODOIST_CUSTOM_NAME= +TODOIST_CLIENT_ID= +TODOIST_CLIENT_SECRET= + +# Twitch +NEXT_PUBLIC_TWITCH_ENABLED= +TWITCH_CUSTOM_NAME= +TWITCH_CLIENT_ID= +TWITCH_CLIENT_SECRET= + +# United Effects +NEXT_PUBLIC_UNITED_EFFECTS_ENABLED= +UNITED_EFFECTS_CUSTOM_NAME= +UNITED_EFFECTS_CLIENT_ID= +UNITED_EFFECTS_CLIENT_SECRET= +UNITED_EFFECTS_ISSUER= + +# VK +NEXT_PUBLIC_VK_ENABLED= +VK_CUSTOM_NAME= +VK_CLIENT_ID= +VK_CLIENT_SECRET= + +# Wikimedia +NEXT_PUBLIC_WIKIMEDIA_ENABLED= +WIKIMEDIA_CUSTOM_NAME= +WIKIMEDIA_CLIENT_ID= +WIKIMEDIA_CLIENT_SECRET= + +# Wordpress.com +NEXT_PUBLIC_WORDPRESS_ENABLED= +WORDPRESS_CUSTOM_NAME= +WORDPRESS_CLIENT_ID= +WORDPRESS_CLIENT_SECRET= + +# Yandex +NEXT_PUBLIC_YANDEX_ENABLED= +YANDEX_CUSTOM_NAME= +YANDEX_CLIENT_ID= +YANDEX_CLIENT_SECRET= + +# Zitadel +NEXT_PUBLIC_ZITADEL_ENABLED= +ZITADEL_CUSTOM_NAME= +ZITADEL_CLIENT_ID= +ZITADEL_CLIENT_SECRET= +ZITADEL_ISSUER= + +# Zoho +NEXT_PUBLIC_ZOHO_ENABLED= +ZOHO_CUSTOM_NAME= +ZOHO_CLIENT_ID= +ZOHO_CLIENT_SECRET= + +# Zoom +NEXT_PUBLIC_ZOOM_ENABLED= +ZOOM_CUSTOM_NAME= +ZOOM_CLIENT_ID= +ZOOM_CLIENT_SECRET= diff --git a/.eslintrc.json b/.eslintrc.json index 09937b6..6ef85ca 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,7 @@ { "extends": "next/core-web-vitals", "rules": { - "react-hooks/exhaustive-deps": "off" + "react-hooks/exhaustive-deps": "off", + "@next/next/no-img-element": "off" } } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} diff --git a/README.md b/README.md index 8f07c2d..544ce93 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,11 @@

Linkwarden

-Discord -GitHub commits since latest release (by SemVer including pre-releases) -Top Language -Github Stars +Discord +Twitter + +GitHub commits since latest release @@ -62,10 +63,24 @@ We've forked the old version from the current repository into [this repo](https: - 📱 Responsive design and supports most modern browsers. - 🌓 Dark/Light mode support. - 🧩 Browser extension, managed by the community. [Star it here!](https://github.com/linkwarden/browser-extension) -- ⬇️ Import your bookmarks from other browsers. -- ⚡️ Powerful API. -- 🔐 SSO and Keycloak integration. (Enterprise and Self-hosted users only) -- ✅ And many more features! +- ⬇️ Import and export your bookmarks. +- 🔐 SSO integration. (Enterprise and Self-hosted users only) +- ✨ And so many more features! + +## Like what we're doing? Give us a Star ⭐ + +![Star Us](https://raw.githubusercontent.com/linkwarden/linkwarden/main/assets/star_repo.gif) + +## We're building our Community 🌐 + +Join and follow us in the following platforms to stay up to date about the most recent features and for support: + +Discord + +Mastodon + +Twitter ## Suggestions @@ -79,17 +94,9 @@ Make sure to check out our [public roadmap](https://github.com/orgs/linkwarden/p For information on how to get started or to set up your own instance, please visit the [documentation](https://docs.linkwarden.app). -## Main Tech Stack - -- NextJS -- TypeScript -- Tailwind -- Prisma -- Zustand - ## Development -If you want to contribute, Thanks! Start by checking our [public roadmap](https://github.com/orgs/linkwarden/projects/1), there you'll see a [README for contributers](https://github.com/orgs/linkwarden/projects/1?pane=issue&itemId=34708277) for the rest of the info on how to contribute to this repo. +If you want to contribute, Thanks! Start by checking our [public roadmap](https://github.com/orgs/linkwarden/projects/1), there you'll see a [README for contributers](https://github.com/orgs/linkwarden/projects/1?pane=issue&itemId=34708277) for the rest of the info on how to contribute and the main tech stack. ## Security @@ -106,3 +113,9 @@ Here are the other ways to support/cheer this project: - Referring Linkwarden to a friend. If you did any of the above, Thanksss! Otherwise thanks. + +## Thanks to All the Contributors 💪 + +Huge thanks to these guys for spending their time helping Linkwarden grow. They rock! ⚡️ + +Contributors diff --git a/assets/star_repo.gif b/assets/star_repo.gif new file mode 100644 index 0000000..87e5497 Binary files /dev/null and b/assets/star_repo.gif differ diff --git a/components/AccentSubmitButton.tsx b/components/AccentSubmitButton.tsx new file mode 100644 index 0000000..1d87787 --- /dev/null +++ b/components/AccentSubmitButton.tsx @@ -0,0 +1,29 @@ +type Props = { + onClick?: Function; + label: string; + loading?: boolean; + className?: string; + type?: "button" | "submit" | "reset" | undefined; +}; + +export default function AccentSubmitButton({ + onClick, + label, + loading, + className, + type, +}: Props) { + return ( + + ); +} diff --git a/components/AnnouncementBar.tsx b/components/AnnouncementBar.tsx index 6e46eea..032ded1 100644 --- a/components/AnnouncementBar.tsx +++ b/components/AnnouncementBar.tsx @@ -1,5 +1,3 @@ -import { faClose } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Link from "next/link"; import React, { MouseEventHandler } from "react"; @@ -9,25 +7,25 @@ type Props = { export default function AnnouncementBar({ toggleAnnouncementBar }: Props) { return ( -
+
- 🎉️{" "} + 🎉️ See what's new in{" "} - Linkwarden v2.0 - {" "} - is now out! 🥳️ + Linkwarden v2.4 + + ! 🥳️
diff --git a/components/Checkbox.tsx b/components/Checkbox.tsx index feb351c..cd69f93 100644 --- a/components/Checkbox.tsx +++ b/components/Checkbox.tsx @@ -1,5 +1,3 @@ -import { faSquare, faSquareCheck } from "@fortawesome/free-regular-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { ChangeEventHandler } from "react"; type Props = { @@ -12,23 +10,17 @@ type Props = { export default function Checkbox({ label, state, className, onClick }: Props) { return ( ); } diff --git a/components/CollectionCard.tsx b/components/CollectionCard.tsx index c382f6e..d4c2571 100644 --- a/components/CollectionCard.tsx +++ b/components/CollectionCard.tsx @@ -1,31 +1,23 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faEllipsis, faGlobe, faLink } from "@fortawesome/free-solid-svg-icons"; import Link from "next/link"; import { CollectionIncludingMembersAndLinkCount } from "@/types/global"; -import Dropdown from "./Dropdown"; -import { useState } from "react"; +import React, { useEffect, useState } from "react"; import ProfilePhoto from "./ProfilePhoto"; -import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; -import useModalStore from "@/store/modals"; import usePermissions from "@/hooks/usePermissions"; -import { useTheme } from "next-themes"; +import useLocalSettingsStore from "@/store/localSettings"; +import getPublicUserData from "@/lib/client/getPublicUserData"; +import useAccountStore from "@/store/account"; +import EditCollectionModal from "./ModalContent/EditCollectionModal"; +import EditCollectionSharingModal from "./ModalContent/EditCollectionSharingModal"; +import DeleteCollectionModal from "./ModalContent/DeleteCollectionModal"; type Props = { collection: CollectionIncludingMembersAndLinkCount; className?: string; }; -type DropdownTrigger = - | { - x: number; - y: number; - } - | false; - export default function CollectionCard({ collection, className }: Props) { - const { setModal } = useModalStore(); - - const { theme } = useTheme(); + const { settings } = useLocalSettingsStore(); + const { account } = useAccountStore(); const formattedDate = new Date(collection.createdAt as string).toLocaleString( "en-US", @@ -36,144 +28,189 @@ export default function CollectionCard({ collection, className }: Props) { } ); - const [expandDropdown, setExpandDropdown] = useState(false); - const permissions = usePermissions(collection.id as number); + const [collectionOwner, setCollectionOwner] = useState({ + id: null as unknown as number, + name: "", + username: "", + image: "", + archiveAsScreenshot: undefined as unknown as boolean, + archiveAsPDF: undefined as unknown as boolean, + }); + + useEffect(() => { + const fetchOwner = async () => { + if (collection && collection.ownerId !== account.id) { + const owner = await getPublicUserData(collection.ownerId as number); + setCollectionOwner(owner); + } else if (collection && collection.ownerId === account.id) { + setCollectionOwner({ + id: account.id as number, + name: account.name, + username: account.username as string, + image: account.image as string, + archiveAsScreenshot: account.archiveAsScreenshot as boolean, + archiveAsPDF: account.archiveAsPDF as boolean, + }); + } + }; + + fetchOwner(); + }, [collection]); + + const [editCollectionModal, setEditCollectionModal] = useState(false); + const [editCollectionSharingModal, setEditCollectionSharingModal] = + useState(false); + const [deleteCollectionModal, setDeleteCollectionModal] = useState(false); + return ( - <> +
+
+
+ +
+
    + {permissions === true ? ( +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setEditCollectionModal(true); + }} + > + Edit Collection Info +
    +
  • + ) : undefined} +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setEditCollectionSharingModal(true); + }} + > + {permissions === true ? "Share and Collaborate" : "View Team"} +
    +
  • +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setDeleteCollectionModal(true); + }} + > + {permissions === true ? "Delete Collection" : "Leave Collection"} +
    +
  • +
+
setEditCollectionSharingModal(true)} + > + {collectionOwner.id ? ( + + ) : undefined} + {collection.members + .sort((a, b) => (a.userId as number) - (b.userId as number)) + .map((e, i) => { + return ( + + ); + }) + .slice(0, 3)} + {collection.members.length - 3 > 0 ? ( +
+
+ +{collection.members.length - 3} +
+
+ ) : null} +
+ -
setExpandDropdown({ x: e.clientX, y: e.clientY })} - id={"expand-dropdown" + collection.id} - className="inline-flex absolute top-5 right-5 rounded-md cursor-pointer hover:bg-slate-200 hover:dark:bg-neutral-700 duration-100 p-1" - > - -
- -

- {collection.name} -

-
-
- {collection.members - .sort((a, b) => (a.userId as number) - (b.userId as number)) - .map((e, i) => { - return ( - - ); - }) - .slice(0, 4)} - {collection.members.length - 4 > 0 ? ( -
- +{collection.members.length - 4} -
- ) : null} -
-
-
+
+
+

+ {collection.name} +

+
+
+ +
+
+
{collection.isPublic ? ( - + > ) : undefined} - + {collection._count && collection._count.links}
-
- -

{formattedDate}

+
+

+ + {formattedDate} +

- -
- {expandDropdown ? ( - { - collection && - setModal({ - modal: "COLLECTION", - state: true, - method: "UPDATE", - isOwner: permissions === true, - active: collection, - }); - setExpandDropdown(false); - }, - } - : undefined, - { - name: permissions === true ? "Share/Collaborate" : "View Team", - onClick: () => { - collection && - setModal({ - modal: "COLLECTION", - state: true, - method: "UPDATE", - isOwner: permissions === true, - active: collection, - defaultIndex: permissions === true ? 1 : 0, - }); - setExpandDropdown(false); - }, - }, - - { - name: - permissions === true ? "Delete Collection" : "Leave Collection", - onClick: () => { - collection && - setModal({ - modal: "COLLECTION", - state: true, - method: "UPDATE", - isOwner: permissions === true, - active: collection, - defaultIndex: permissions === true ? 2 : 1, - }); - setExpandDropdown(false); - }, - }, - ]} - onClickOutside={(e: Event) => { - const target = e.target as HTMLInputElement; - if (target.id !== "expand-dropdown" + collection.id) - setExpandDropdown(false); - }} - className="w-fit" +
+ + {editCollectionModal ? ( + setEditCollectionModal(false)} + activeCollection={collection} /> - ) : null} - + ) : undefined} + {editCollectionSharingModal ? ( + setEditCollectionSharingModal(false)} + activeCollection={collection} + /> + ) : undefined} + {deleteCollectionModal ? ( + setDeleteCollectionModal(false)} + activeCollection={collection} + /> + ) : undefined} +
); } diff --git a/components/DashboardItem.tsx b/components/DashboardItem.tsx index 3de882e..60a5fe4 100644 --- a/components/DashboardItem.tsx +++ b/components/DashboardItem.tsx @@ -1,28 +1,20 @@ -import { IconProp } from "@fortawesome/fontawesome-svg-core"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -type Props = { +export default function dashboardItem({ + name, + value, + icon, +}: { name: string; value: number; - icon: IconProp; -}; - -export default function dashboardItem({ name, value, icon }: Props) { + icon: string; +}) { return ( -
-
- +
+
+
-
-

- {name} -

-

- {value} -

+
+

{name}

+

{value}

); diff --git a/components/Dropdown.tsx b/components/Dropdown.tsx index ac1ee59..4a48ab7 100644 --- a/components/Dropdown.tsx +++ b/components/Dropdown.tsx @@ -78,13 +78,13 @@ export default function Dropdown({ onClickOutside={onClickOutside} className={`${ className || "" - } py-1 shadow-md border border-sky-100 dark:border-neutral-700 bg-gray-50 dark:bg-neutral-800 rounded-md flex flex-col z-20`} + } py-1 shadow-md border border-neutral-content bg-base-200 rounded-md flex flex-col z-20`} > {items.map((e, i) => { const inner = e && (
-
-

{e.name}

+
+

{e.name}

); diff --git a/components/FilterSearchDropdown.tsx b/components/FilterSearchDropdown.tsx index 90648e0..1fa2634 100644 --- a/components/FilterSearchDropdown.tsx +++ b/components/FilterSearchDropdown.tsx @@ -1,9 +1,6 @@ -import React, { SetStateAction } from "react"; -import ClickAwayHandler from "./ClickAwayHandler"; -import Checkbox from "./Checkbox"; +import React from "react"; type Props = { - setFilterDropdown: (value: SetStateAction) => void; setSearchFilter: Function; searchFilter: { name: boolean; @@ -15,64 +12,121 @@ type Props = { }; export default function FilterSearchDropdown({ - setFilterDropdown, setSearchFilter, searchFilter, }: Props) { return ( - { - const target = e.target as HTMLInputElement; - if (target.id !== "filter-dropdown") setFilterDropdown(false); - }} - className="absolute top-8 right-0 border border-sky-100 dark:border-neutral-700 shadow-md bg-gray-50 dark:bg-neutral-800 rounded-md p-2 z-20 w-40" - > -

- Filter by -

-
- - setSearchFilter({ ...searchFilter, name: !searchFilter.name }) - } - /> - - setSearchFilter({ ...searchFilter, url: !searchFilter.url }) - } - /> - - setSearchFilter({ - ...searchFilter, - description: !searchFilter.description, - }) - } - /> - - setSearchFilter({ - ...searchFilter, - textContent: !searchFilter.textContent, - }) - } - /> - - setSearchFilter({ ...searchFilter, tags: !searchFilter.tags }) - } - /> +
+
+
- +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
); } diff --git a/components/InputSelect/CollectionSelection.tsx b/components/InputSelect/CollectionSelection.tsx index 991557f..71dc075 100644 --- a/components/InputSelect/CollectionSelection.tsx +++ b/components/InputSelect/CollectionSelection.tsx @@ -1,9 +1,9 @@ import useCollectionStore from "@/store/collections"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; -import Select from "react-select"; import { styles } from "./styles"; import { Options } from "./types"; +import CreatableSelect from "react-select/creatable"; type Props = { onChange: any; @@ -43,8 +43,8 @@ export default function CollectionSelection({ onChange, defaultValue }: Props) { }, [collections]); return ( -