Skip to content

Commit

Permalink
Improve tags creation & management
Browse files Browse the repository at this point in the history
  • Loading branch information
steven-tey committed Jul 2, 2023
1 parent 8773efd commit 0db530c
Show file tree
Hide file tree
Showing 10 changed files with 370 additions and 127 deletions.
28 changes: 5 additions & 23 deletions components/app/links/link-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useRouter } from "next/router";
import { useEffect, useMemo, useRef, useState } from "react";
import useSWR from "swr";
import { useAddEditLinkModal } from "@/components/app/modals/add-edit-link-modal";
import { useTagLinkModal } from "@/components/app/modals/tag-link-modal";
import { useArchiveLinkModal } from "@/components/app/modals/archive-link-modal";
import { useDeleteLinkModal } from "@/components/app/modals/delete-link-modal";
import { useLinkQRModal } from "@/components/app/modals/link-qr-modal";
Expand All @@ -20,6 +19,7 @@ import {
getApexDomain,
linkConstructor,
nFormatter,
setQueryString,
timeAgo,
} from "#/lib/utils";
import useIntersectionObserver from "#/lib/hooks/use-intersection-observer";
Expand Down Expand Up @@ -84,9 +84,6 @@ export default function LinkCard({ props }: { props: LinkProps }) {
},
});

const { setShowTagLinkModal, TagLinkModal } = useTagLinkModal({
props,
});
const { setShowArchiveLinkModal, ArchiveLinkModal } = useArchiveLinkModal({
props,
archived: !archived,
Expand Down Expand Up @@ -143,9 +140,6 @@ export default function LinkCard({ props }: { props: LinkProps }) {
case "d":
setShowDuplicateLinkModal(true);
break;
case "t":
setShowTagLinkModal(true);
break;
case "a":
setShowArchiveLinkModal(true);
break;
Expand Down Expand Up @@ -173,7 +167,6 @@ export default function LinkCard({ props }: { props: LinkProps }) {
<LinkQRModal />
<AddEditLinkModal />
<DuplicateLinkModal />
{slug && <TagLinkModal />}
<ArchiveLinkModal />
<DeleteLinkModal />
<li className="relative flex items-center justify-between">
Expand Down Expand Up @@ -265,7 +258,10 @@ export default function LinkCard({ props }: { props: LinkProps }) {
</Link>
{tag?.color && (
<button
onClick={() => setShowTagLinkModal(true)}
onClick={(e) => {
e.stopPropagation();
setQueryString(router, "tagId", tag.id);
}}
className="hidden transition-all duration-75 hover:scale-105 active:scale-100 sm:block"
>
<TagBadge {...tag} withIcon />
Expand Down Expand Up @@ -362,20 +358,6 @@ export default function LinkCard({ props }: { props: LinkProps }) {
</kbd>
</button>
)}
{slug && (
<button
onClick={() => {
setOpenPopover(false);
setShowTagLinkModal(true);
}}
className="group flex w-full items-center justify-between rounded-md p-2 text-left text-sm font-medium text-gray-500 transition-all duration-75 hover:bg-gray-100"
>
<IconMenu text="Tag" icon={<Tag className="h-4 w-4" />} />
<kbd className="hidden rounded bg-gray-100 px-2 py-0.5 text-xs font-light text-gray-500 transition-all duration-75 group-hover:bg-gray-200 sm:inline-block">
T
</kbd>
</button>
)}
<button
onClick={() => {
setOpenPopover(false);
Expand Down
61 changes: 20 additions & 41 deletions components/app/links/link-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { ModalContext } from "#/ui/modal-provider";
import useTags from "#/lib/swr/use-tags";
import TagBadge from "@/components/app/links/tag-badge";
import { TagProps } from "#/lib/types";
import Badge from "#/ui/badge";

export default function LinkFilters() {
const { primaryDomain } = useDomains();
Expand All @@ -34,22 +33,30 @@ export default function LinkFilters() {
const { data: tagsCount } = useLinksCount({ groupBy: "tagId" });

const router = useRouter();
const { slug, sort, search, domain, userId, tagId } = router.query as {
slug: string;
sort?: string;
search?: string;
domain?: string;
userId?: string;
tagId?: string;
};
const { slug, sort, search, domain, userId, tagId, showArchived } =
router.query as {
slug: string;
sort?: string;
search?: string;
domain?: string;
userId?: string;
tagId?: string;
showArchived?: string;
};
const searchInputRef = useRef(); // this is a hack to clear the search input when the clear button is clicked

useEffect(() => {
if (search) {
setQueryString(router, "showArchived", "true");
}
}, [search]);

return domains && tags && tagsCount ? (
<div className="grid w-full rounded-md bg-white px-5 lg:divide-y lg:divide-gray-300">
<div className="grid gap-3 py-6">
<div className="flex items-center justify-between">
<h3 className="ml-1 mt-2 font-semibold">Filter Links</h3>
{(sort || search || domain || userId || tagId) && (
{(sort || search || domain || userId || tagId || showArchived) && (
<ClearButton searchInputRef={searchInputRef} />
)}
</div>
Expand Down Expand Up @@ -186,7 +193,7 @@ const DomainsFilter = ({ domains, primaryDomain }) => {
);
}
}}
className="mr-2 rounded-md border border-gray-200 px-3 py-1 transition-all hover:border-gray-600 active:bg-gray-100"
className="rounded-md border border-gray-200 px-3 py-1 transition-all hover:border-gray-600 active:bg-gray-100"
>
<p className="text-sm text-gray-500">Add</p>
</button>
Expand Down Expand Up @@ -237,7 +244,7 @@ const TagsFilter = ({
}) => {
const router = useRouter();
const { slug } = router.query as { slug?: string };
const [collapsed, setCollapsed] = useState(tags.length === 0 ? true : false);
const [collapsed, setCollapsed] = useState(true);
const [search, setSearch] = useState("");
const [showMore, setShowMore] = useState(false);

Expand All @@ -256,20 +263,6 @@ const TagsFilter = ({
: initialOptions;
}, [tagsCount, tags, search]);

const { setShowTagLinkModal, setShowAddProjectModal } =
useContext(ModalContext);

const addTag = useCallback(() => {
if (slug) {
setShowTagLinkModal(true);
} else {
setShowAddProjectModal(true);
toast.error(
"You can only add a tag to a custom project. Please create a new project or navigate to an existing one.",
);
}
}, [setShowTagLinkModal, setShowAddProjectModal, slug]);

return (
<fieldset className="overflow-hidden py-6">
<div className="flex h-8 items-center justify-between">
Expand All @@ -284,12 +277,6 @@ const TagsFilter = ({
/>
<h4 className="font-medium text-gray-900">Tags</h4>
</button>
<button
onClick={addTag}
className="mr-2 rounded-md border border-gray-200 px-3 py-1 transition-all hover:border-gray-600 active:bg-gray-100"
>
<p className="text-sm text-gray-500">Add</p>
</button>
</div>
<AnimatePresence initial={false}>
{!collapsed && (
Expand All @@ -298,15 +285,7 @@ const TagsFilter = ({
{...SWIPE_REVEAL_ANIMATION_SETTINGS}
>
{tags?.length === 0 ? ( // if the project has no tags
<p className="text-center text-sm text-gray-500">
No tags yet.{" "}
<button
className="font-medium underline underline-offset-4 transition-colors hover:text-black"
onClick={addTag}
>
Add one.
</button>
</p>
<p className="text-center text-sm text-gray-500">No tags yet. </p>
) : (
<>
<div className="relative mb-1">
Expand Down
2 changes: 1 addition & 1 deletion components/app/links/tag-badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function TagBadge({
return (
<span
className={clsx(
"whitespace-nowrap rounded-md px-2 py-0.5 text-sm",
"my-auto whitespace-nowrap rounded-md px-2 py-0.5 text-sm",
withIcon && "flex items-center space-x-1.5",
color === "red" && "bg-red-100 text-red-600",
color === "yellow" && "bg-yellow-100 text-yellow-600",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function ExpirationSection({
<Switch fn={() => setEnabled(!enabled)} checked={enabled} />
</div>
{enabled && (
<motion.div className="mt-3">
<motion.div className="mt-3" {...FADE_IN_ANIMATION_SETTINGS}>
<input
type="datetime-local"
id="expiresAt"
Expand Down
8 changes: 5 additions & 3 deletions components/app/modals/add-edit-link-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ import {
linkConstructor,
truncate,
} from "#/lib/utils";
import ExpirationSection from "./expiration-section";
import TagsSection from "./tags-section";
import OGSection from "./og-section";
import PasswordSection from "./password-section";
import UTMSection from "./utm-section";
import PasswordSection from "./password-section";
import ExpirationSection from "./expiration-section";
import IOSSection from "./ios-section";
import Preview from "./preview";
import AndroidSection from "./android-section";
import Preview from "./preview";
import { DEFAULT_LINK_PROPS, GOOGLE_FAVICON_URL } from "#/lib/constants";
import useDomains from "#/lib/swr/use-domains";
import { toast } from "sonner";
Expand Down Expand Up @@ -527,6 +528,7 @@ function AddEditLinkModal({
</div>

<div className="grid gap-5 px-4 md:px-16">
<TagsSection {...{ props, data, setData }} />
<OGSection
{...{ props, data, setData }}
generatingMetatags={generatingMetatags}
Expand Down
Loading

0 comments on commit 0db530c

Please sign in to comment.