diff --git a/actions/publishToPublication.ts b/actions/publishToPublication.ts index db3c789e..d5fa9ce0 100644 --- a/actions/publishToPublication.ts +++ b/actions/publishToPublication.ts @@ -89,6 +89,8 @@ export async function publishToPublication({ entitiesToDelete?: string[]; publishedAt?: string; }): Promise { + // Normalize tags to lowercase for consistent storage and querying + const normalizedTags = tags?.map((tag) => tag.toLowerCase()); let identity = await getIdentityData(); if (!identity || !identity.atp_did) { return { @@ -241,7 +243,7 @@ export async function publishToPublication({ publishedAt: publishedAt || existingRecord.publishedAt || new Date().toISOString(), ...(description && { description }), - ...(tags !== undefined && { tags }), + ...(normalizedTags !== undefined && { tags: normalizedTags }), ...(coverImageBlob && { coverImage: coverImageBlob }), // Include theme for standalone documents (not for publication documents) ...(!publication_uri && theme && { theme }), @@ -259,7 +261,7 @@ export async function publishToPublication({ ...(theme && { theme }), title: title || "Untitled", description: description || "", - ...(tags !== undefined && { tags }), + ...(normalizedTags !== undefined && { tags: normalizedTags }), ...(coverImageBlob && { coverImage: coverImageBlob }), pages: pagesArray, publishedAt: diff --git a/app/(home-pages)/tag/[tag]/getDocumentsByTag.ts b/app/(home-pages)/tag/[tag]/getDocumentsByTag.ts index ebaffbe0..98b8d699 100644 --- a/app/(home-pages)/tag/[tag]/getDocumentsByTag.ts +++ b/app/(home-pages)/tag/[tag]/getDocumentsByTag.ts @@ -14,7 +14,11 @@ import { deduplicateByUriOrdered } from "src/utils/deduplicateRecords"; export async function getDocumentsByTag( tag: string, ): Promise<{ posts: Post[] }> { - // Query documents that have this tag + // Normalize tag to lowercase for case-insensitive matching + const normalizedTag = tag.toLowerCase(); + + // Query documents that have this tag (case-insensitive) + // Use ilike on the JSONB text cast to match regardless of stored case const { data: rawDocuments, error } = await supabaseServerClient .from("documents") .select( @@ -23,7 +27,7 @@ export async function getDocumentsByTag( document_mentions_in_bsky(count), documents_in_publications(publications(*))`, ) - .contains("data->tags", `["${tag}"]`) + .filter("data->>tags", "ilike", `%"${normalizedTag}"%`) .order("sort_date", { ascending: false }) .limit(50); diff --git a/components/Tags.tsx b/components/Tags.tsx index d2266e9a..984f0bb6 100644 --- a/components/Tags.tsx +++ b/components/Tags.tsx @@ -109,8 +109,10 @@ export const TagSearchInput = (props: { } function selectTag(tag: string) { - console.log("selected " + tag); - props.setSelectedTags([...props.selectedTags, tag]); + // Normalize tag to lowercase for consistent storage and querying + const normalizedTag = tag.toLowerCase(); + console.log("selected " + normalizedTag); + props.setSelectedTags([...props.selectedTags, normalizedTag]); clearTagInput(); } @@ -150,12 +152,12 @@ export const TagSearchInput = (props: { return (
{ - setTagInputValue(e.target.value); + setTagInputValue(e.target.value.toLowerCase()); setIsOpen(true); setHighlightedIndex(0); }} @@ -193,7 +195,7 @@ export const TagSearchInput = (props: { placeholder="search tags…" value={tagInputValue} onChange={(e) => { - setTagInputValue(e.target.value); + setTagInputValue(e.target.value.toLowerCase()); setIsOpen(true); setHighlightedIndex(0); }} diff --git a/src/replicache/mutations.ts b/src/replicache/mutations.ts index d8bf93c6..d61c9d11 100644 --- a/src/replicache/mutations.ts +++ b/src/replicache/mutations.ts @@ -660,6 +660,9 @@ const updatePublicationDraft: Mutation<{ cover_image?: string | null; localPublishedAt?: string | null; }> = async (args, ctx) => { + // Normalize tags to lowercase for consistent storage and querying + const normalizedTags = args.tags?.map((tag) => tag.toLowerCase()); + await ctx.runOnServer(async (serverCtx) => { console.log("updating"); const updates: { @@ -670,7 +673,7 @@ const updatePublicationDraft: Mutation<{ } = {}; if (args.description !== undefined) updates.description = args.description; if (args.title !== undefined) updates.title = args.title; - if (args.tags !== undefined) updates.tags = args.tags; + if (normalizedTags !== undefined) updates.tags = normalizedTags; if (args.cover_image !== undefined) updates.cover_image = args.cover_image; if (Object.keys(updates).length > 0) { @@ -695,7 +698,8 @@ const updatePublicationDraft: Mutation<{ if (args.title !== undefined) await tx.set("publication_title", args.title); if (args.description !== undefined) await tx.set("publication_description", args.description); - if (args.tags !== undefined) await tx.set("publication_tags", args.tags); + if (normalizedTags !== undefined) + await tx.set("publication_tags", normalizedTags); if (args.cover_image !== undefined) await tx.set("publication_cover_image", args.cover_image); if (args.localPublishedAt !== undefined)