From 93f359e6845c3914916a81fd5a9abf8a5642b24b Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 20 Aug 2023 20:13:47 +0200 Subject: [PATCH] feat: allow filtering with null (no) rating --- components/Card.tsx | 25 ++++++++++++++++++++++--- components/Rating.tsx | 21 +++++++++++++++++++++ islands/Search.tsx | 14 +++++--------- lib/env.ts | 2 -- lib/log.ts | 3 +-- lib/resource/articles.ts | 2 +- lib/resource/movies.ts | 1 - lib/resource/series.ts | 2 +- lib/search.ts | 22 +++++++++++++--------- lib/types.ts | 6 +----- lib/typesense.ts | 1 - routes/api/articles/create/index.ts | 4 ++-- 12 files changed, 67 insertions(+), 36 deletions(-) diff --git a/components/Card.tsx b/components/Card.tsx index f313a5e..0848322 100644 --- a/components/Card.tsx +++ b/components/Card.tsx @@ -1,15 +1,25 @@ import { isLocalImage, isYoutubeLink } from "@lib/string.ts"; import { IconBrandYoutube } from "@components/icons.tsx"; import { GenericResource } from "@lib/types.ts"; +import { Rating, SmallRating } from "@components/Rating.tsx"; export function Card( - { link, title, image, thumbnail, backgroundColor, backgroundSize = 100 }: { + { + link, + rating, + title, + image, + thumbnail, + backgroundColor, + backgroundSize = 100, + }: { backgroundSize?: number; backgroundColor?: string; thumbnail?: string; link?: string; title?: string; image?: string; + rating?: number; }, ) { const backgroundStyle = { @@ -55,13 +65,21 @@ export function Card( boxShadow: "0px -60px 40px black inset, 0px 10px 20px #fff1 inset", }} > -
+
{/* Recipe Card content */}
-
+
{isYoutubeLink(link || "") && } {title}
+ {rating !== undefined && ( +
+ +
+ )}
@@ -81,6 +99,7 @@ export function ResourceCard( { + return ( +
+ {Array.from({ length: max }).map((_, i) => { + return ( + + {(i + 1) <= rating + ? + : } + + ); + })} +
+ ); +}; + export const Rating = ( props: { max?: number; rating: number }, ) => { diff --git a/islands/Search.tsx b/islands/Search.tsx index f32f5c9..6db3605 100644 --- a/islands/Search.tsx +++ b/islands/Search.tsx @@ -18,11 +18,7 @@ export async function fetchQueryResource(url: URL, type = "") { try { url.pathname = "/api/resources"; - if (query) { - url.searchParams.set("q", encodeURIComponent(query)); - } else { - return; - } + url.searchParams.set("q", encodeURIComponent(query || "*")); if (status) { url.searchParams.set("status", "not-seen"); } @@ -45,7 +41,7 @@ export const RedirectSearchHandler = () => { e.key === "?" && window.location.search === "" ) { - window.location.href += "?q="; + window.location.href += "?q=*"; } }, IS_BROWSER ? document?.body : undefined); } @@ -127,9 +123,9 @@ const Search = ( u.searchParams.set("q", searchQuery.value); } if (showSeenStatus.value) { - u.searchParams.set("status", "not-seen"); + u.searchParams.set("rating", "0"); } else { - u.searchParams.delete("status"); + u.searchParams.delete("rating"); } window.history.replaceState({}, "", u); @@ -191,7 +187,7 @@ const Search = ( onInput={handleInputChange} />
- + {data?.value?.hits?.length && !isLoading.value diff --git a/lib/env.ts b/lib/env.ts index 0da790e..a6777f7 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -23,5 +23,3 @@ export const TYPESENSE_API_KEY = Deno.env.get("TYPESENSE_API_KEY"); export const LOG_LEVEL: string = Deno.env.get("LOG_LEVEL") || "warn"; - -console.log({ LOG_LEVEL }); diff --git a/lib/log.ts b/lib/log.ts index b47858a..c77763c 100644 --- a/lib/log.ts +++ b/lib/log.ts @@ -23,9 +23,8 @@ const logFuncs = { } as const; let longestScope = 0; -let logLevel = (_LOG_LEVEL && _LOG_LEVEL in logMap && logMap[_LOG_LEVEL]) || +let logLevel = (_LOG_LEVEL && _LOG_LEVEL in logMap && logMap[_LOG_LEVEL]) ?? LOG_LEVEL.WARN; -console.log({ logLevel, logMap }); const ee = new EventEmitter<{ log: { level: LOG_LEVEL; scope: string; args: unknown[] }; diff --git a/lib/resource/articles.ts b/lib/resource/articles.ts index 70e2b0c..25c7345 100644 --- a/lib/resource/articles.ts +++ b/lib/resource/articles.ts @@ -13,7 +13,7 @@ export type Article = { name: string; tags: string[]; meta: { - status: "finished" | "not-finished"; + done?: boolean; date: Date; link: string; thumbnail?: string; diff --git a/lib/resource/movies.ts b/lib/resource/movies.ts index 996d6c4..3ed7566 100644 --- a/lib/resource/movies.ts +++ b/lib/resource/movies.ts @@ -17,7 +17,6 @@ export type Movie = { average?: string; author: string; rating: number; - status: "not-seen" | "watch-again" | "finished"; }; }; diff --git a/lib/resource/series.ts b/lib/resource/series.ts index 575cda8..069f59a 100644 --- a/lib/resource/series.ts +++ b/lib/resource/series.ts @@ -18,7 +18,7 @@ export type Series = { rating: number; average?: string; thumbnail?: string; - status: "not-seen" | "watch-again" | "finished"; + done?: boolean; }; }; diff --git a/lib/search.ts b/lib/search.ts index ac9fea4..99d1803 100644 --- a/lib/search.ts +++ b/lib/search.ts @@ -1,6 +1,6 @@ import { BadRequestError } from "@lib/errors.ts"; import { resources } from "@lib/resources.ts"; -import { ResourceStatus, SearchResult } from "@lib/types.ts"; +import { SearchResult } from "@lib/types.ts"; import { getTypeSenseClient } from "@lib/typesense.ts"; import { extractHashTags } from "@lib/string.ts"; @@ -10,7 +10,7 @@ type SearchParams = { q: string; type?: ResourceType; tags?: string[]; - status?: ResourceStatus; + rating?: string; author?: string; query_by?: string; }; @@ -18,7 +18,7 @@ type SearchParams = { export function parseResourceUrl(_url: string): SearchParams | undefined { try { const url = new URL(_url); - let query = url.searchParams.get("q"); + let query = url.searchParams.get("q") || "*"; if (!query) { return undefined; } @@ -34,7 +34,7 @@ export function parseResourceUrl(_url: string): SearchParams | undefined { q: query, type: url.searchParams.get("type") as ResourceType || undefined, tags: hashTags, - status: url.searchParams.get("status") as ResourceStatus || undefined, + rating: url.searchParams.get("rating") || undefined, query_by: url.searchParams.get("query_by") || undefined, }; } catch (_err) { @@ -43,7 +43,7 @@ export function parseResourceUrl(_url: string): SearchParams | undefined { } export async function searchResource( - { q, query_by = "name,description,author,tags", tags = [], type, status }: + { q, query_by = "name,description,author,tags", tags = [], type, rating }: SearchParams, ): Promise { const typesenseClient = await getTypeSenseClient(); @@ -57,10 +57,6 @@ export async function searchResource( filter_by.push(`type:=${type}`); } - if (status) { - filter_by.push(`status:=${status}`); - } - if (tags?.length) { filter_by.push(`tags:[${tags.map((t) => `\`${t}\``).join(",")}]`); for (const tag of tags) { @@ -71,6 +67,14 @@ export async function searchResource( } } + if (typeof rating !== "undefined") { + if (rating === "null") { + filter_by.push(`rating: null`); + } else { + filter_by.push(`rating: ${rating}`); + } + } + return await typesenseClient.collections("resources") .documents().search({ q, diff --git a/lib/types.ts b/lib/types.ts index fea5945..9c5e2ff 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -41,6 +41,7 @@ export type GenericResource = { meta?: { image?: string; author?: string; + rating?: number; average?: string; thumbnail?: string; }; @@ -66,9 +67,4 @@ export type TypesenseDocument = { image?: string; }; -export enum ResourceStatus { - COMPLETED = "completed", - NOT_COMPLETED = "not_completed", -} - export type SearchResult = SearchResponse; diff --git a/lib/typesense.ts b/lib/typesense.ts index 454e654..a2484fd 100644 --- a/lib/typesense.ts +++ b/lib/typesense.ts @@ -77,7 +77,6 @@ async function initializeTypesense() { { name: "type", type: "string", facet: true }, { name: "date", type: "string", optional: true }, { name: "author", type: "string", facet: true, optional: true }, - { name: "status", type: "string", facet: true, optional: true }, { name: "rating", type: "int32", facet: true }, { name: "tags", type: "string[]", facet: true }, { name: "description", type: "string", optional: true }, diff --git a/routes/api/articles/create/index.ts b/routes/api/articles/create/index.ts index fd03f5f..a3dc209 100644 --- a/routes/api/articles/create/index.ts +++ b/routes/api/articles/create/index.ts @@ -130,7 +130,7 @@ async function processCreateArticle( const meta: Article["meta"] = { author: (author || "").replace("@", "twitter:"), link: fetchUrl, - status: "not-finished", + done: false, date: new Date(), }; @@ -194,7 +194,7 @@ async function processCreateYoutubeVideo( content: video.snippet.description, tags: video.snippet.tags.slice(0, 5), meta: { - status: "not-finished", + done: false, link: fetchUrl, author: video.snippet.channelTitle, date: new Date(video.snippet.publishedAt),