Skip to content

Commit

Permalink
feat: add loading spinner for search and limit number of reindexes pe…
Browse files Browse the repository at this point in the history
…r hour

Signed-off-by: tylerslaton <[email protected]>
  • Loading branch information
tylerslaton committed Mar 19, 2024
1 parent e5bf575 commit c2144c7
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
5 changes: 3 additions & 2 deletions src/lib/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PrismaClient, Prisma } from '@prisma/client';

const prisma = new PrismaClient();

export const getToolsForUrl = async (url: string): Promise<{ tools: Tool[], examples: ToolExample[] }> => {
export const getToolsForUrl = async (url: string): Promise<{ tools: Tool[], examples: ToolExample[], lastIndexedAt: Date }> => {
const toolEntry = await prisma.toolEntry.findFirst({
where: {
reference: url
Expand All @@ -15,11 +15,12 @@ export const getToolsForUrl = async (url: string): Promise<{ tools: Tool[], exam
});

if (!toolEntry) {
return { tools: [], examples: [] };
return { tools: [], examples: [], lastIndexedAt: new Date() };
}

return {
tools: toolEntry.content as Tool[],
lastIndexedAt: toolEntry.lastIndexedAt,
examples: toolEntry.examples.map((example) => ({
name: example.name,
url: example.url,
Expand Down
13 changes: 12 additions & 1 deletion src/pages/search.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div>
<div v-if="!error.status" class="m-10 md:m-24 mt-36 prose">
<div v-if="!error.status && !loading" class="m-10 md:m-24 mt-36 prose">
<h1 class="text-3xl font-bold mb-8">Search Results</h1>
<div v-for="(tools, url) in searchResults" :key="url" class="mb-8">
<a class="text-xl font-semibold mb-4 block" :href="`/${url}`">
Expand All @@ -10,6 +10,14 @@

</div>
</div>

<div v-else-if="loading" class="flex items-center justify-center h-screen">
<div class="flex flex-col items-center justify-center h-screen">
<div class="animate-spin rounded-full h-16 w-16 border-t-4 border-b-6 border-gray-900"></div>
<p class="mt-10 text-gray-900 text-xl font-semibold">Loading search...</p>
</div>
</div>

<Error
class="flex flex-col items-center justify-center h-screen"
v-else
Expand All @@ -26,6 +34,7 @@ import type { Tool } from '@/lib/types';
const router = useRouter();
const searchResults = ref({} as Record<string, Tool[]>);
const error = ref({status: 0, message: ''});
const loading = ref(true);
const fetchData = async (q: string) => {
// if the query is a github valid github url, we want to redirect to that tool's page
Expand All @@ -38,9 +47,11 @@ const fetchData = async (q: string) => {
const results = await fetch(`/api/search?q=${q}`, { method: 'GET' });
if (!results.ok) {
error.value = { status: results.status, message: results.statusText };
loading.value = false;
return;
}
searchResults.value = await results.json() as Record<string, Tool[]>;
loading.value = false;
};
onMounted(async () => fetchData(useRoute().query.q as string));
Expand Down
10 changes: 9 additions & 1 deletion src/server/api/[...slug].post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,17 @@ export default defineEventHandler(async (event) => {

// if the tool is already indexed and force is not true, return the tool
let entry = await db.getToolsForUrl(url);
if (entry.tools.length > 0 && !getQuery(event).force) {

// if the tool is already indexed and the last index time is less than 1 hour ago, return the tool
if (entry.tools.length > 0 && entry.lastIndexedAt && (Date.now() - Number(entry.lastIndexedAt)) < 3600000) {
// add headers to communicate that the response is cached and when it was last indexed
setResponseHeader(event, "Content-Type", "application/json");
setResponseHeader(event, "Cached-Response", "true")
setResponseHeader(event, "Last-Indexed-At", entry.lastIndexedAt.toISOString())
setResponseStatus(event, 200)
return entry;
}
setResponseHeader(event, "Cached-Response", "false")

// grab the owner, repo and subdirs from the URL if they exist
const [owner, repo, ...subdirs] = url.replace(/^(https?:\/\/)?(www\.)?github\.com\//, "").split("/");
Expand Down Expand Up @@ -80,6 +87,7 @@ export default defineEventHandler(async (event) => {

// upsert the tool into the database and return the tool
setResponseHeader(event, "Content-Type", "application/json");
setResponseStatus(event, 201)
return await db.upsertToolForUrl(url,
parsedTools,
await getExamples(owner, repo)
Expand Down

0 comments on commit c2144c7

Please sign in to comment.