Skip to content

Commit

Permalink
Add new functions for searching clinical trials and FDA treatments
Browse files Browse the repository at this point in the history
Introduced functions to search clinical trials and treatments using various APIs. Modified functions to include URL error handling, and improved user ID handling in researcher agent functions.
  • Loading branch information
mikepsinn committed Sep 14, 2024
1 parent 0ec0a21 commit 582a0fc
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 45 deletions.
40 changes: 21 additions & 19 deletions components/ArticleGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,41 @@ type ArticleGridProps = {

export default function ArticleGrid({ articles }: ArticleGridProps) {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{articles.map((article) => (
<Card key={article.id} className="flex flex-col">
<Card key={article.id} className="flex flex-col overflow-hidden hover:shadow-lg transition-shadow duration-300">
{article.featuredImage && (
<Link href={`/research/articles/${article.slug}`}>
<Image
src={article.featuredImage || '/placeholder.svg?height=200&width=300'}
alt={article.title}
width={300}
height={200}
className="w-full h-48 object-cover rounded-t-lg"
/>
<Link href={`/research/articles/${article.slug}`} className="block">
<div className="relative h-48 overflow-hidden">
<Image
src={article.featuredImage}
alt={article.title}
layout="fill"
objectFit="cover"
className="transition-transform duration-300 hover:scale-105"
/>
</div>
</Link>
)}
<CardHeader>
<CardTitle>
<Link href={`/researcher/articles/${article.slug}`}
<CardHeader className="pb-2">
<Link href={`/researcher/articles/categories/${article.category.slug}`}>
<Badge variant="secondary" className="mb-2">{article.category.name}</Badge>
</Link>
<CardTitle className="text-xl">
<Link href={`/researcher/article/${article.slug}`}
className="hover:underline">
{article.title}
</Link>
</CardTitle>
</CardHeader>
<CardContent>
<Link href={`/researcher/categories/${article.category.slug}`}>
<Badge variant="secondary">{article.category.name}</Badge>
</Link>
<p className="text-muted-foreground">{article.description}</p>
<p className="text-muted-foreground text-sm line-clamp-3">{article.description}</p>
</CardContent>
<CardFooter className="mt-auto">
<CardFooter className="mt-auto pt-4 border-t">
<div className="flex flex-wrap gap-2">
{article.tags.map((tag) => (
<Link key={tag.name} href={`/research/tags/${tag.name}`}>
<Badge variant="outline">{tag.name}</Badge>
<Badge variant="outline" className="text-xs">{tag.name}</Badge>
</Link>
))}
</div>
Expand Down
84 changes: 68 additions & 16 deletions components/ArticleRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import {
import { Separator } from "@/components/ui/separator"
import { toast } from "@/components/ui/use-toast"
import { CustomReactMarkdown } from "@/components/CustomReactMarkdown"
import { deleteArticle } from "@/app/researcher/researcherActions"
import { useRouter } from "next/navigation"

import {generateImage} from "@/app/researcher/researcherActions";
import { UrlDisplay } from "./article/UrlDisplay"

function GenerateImageButton({
onClick,
Expand All @@ -40,7 +43,14 @@ function GenerateImageButton({
)
}

export default function ArticleRenderer(article: ArticleWithRelations) {
export default function ArticleRenderer({
article,
currentUserId
}: {
article: ArticleWithRelations,
currentUserId?: string
}) {
const router = useRouter();
const [expandedResult, setExpandedResult] = useState<string | null>(null)
const [isCopied, setIsCopied] = useState(false)
const [isGeneratingImage, setIsGeneratingImage] = useState(false)
Expand All @@ -56,6 +66,7 @@ export default function ArticleRenderer(article: ArticleWithRelations) {
category,
searchResults,
featuredImage,
userId,
} = article

const readingTime = Math.ceil(content.split(' ').length / 200)
Expand Down Expand Up @@ -112,6 +123,35 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
})
}

// Add this function to handle article deletion
async function handleDeleteArticle() {
if (!currentUserId) {
toast({
title: "Please login to delete articles",
description: "You must be logged in to delete articles.",
variant: "destructive",
});
return;
}
if (confirm("Are you sure you want to delete this article?")) {
try {
await deleteArticle(title, currentUserId);
toast({
title: "Article deleted",
description: "The article has been successfully deleted.",
});
router.push("/"); // Redirect to home page after deletion
} catch (error) {
console.error("Failed to delete article:", error);
toast({
title: "Failed to delete article",
description: "An error occurred while deleting the article.",
variant: "destructive",
});
}
}
}

return (
<div className="container mx-auto max-w-6xl p-4">
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
Expand All @@ -124,6 +164,13 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
<CardContent>
<CustomReactMarkdown>{content}</CustomReactMarkdown>
</CardContent>
{currentUserId === userId && (
<CardFooter>
<Button variant="destructive" onClick={handleDeleteArticle}>
Delete Article
</Button>
</CardFooter>
)}
</Card>
<div className="space-y-4">
<Card>
Expand Down Expand Up @@ -209,21 +256,25 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
<CardTitle>Sources</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2">
<div className="space-y-4">
{sources?.map((source, index) => (
<li key={index}>
<a
href={source.url}
target="_blank"
rel="noopener noreferrer"
className="flex items-center space-x-2 text-blue-500 hover:underline"
>
<Link2 className="h-4 w-4" />
<span>{source.title}</span>
</a>
</li>
<Card key={index} className="overflow-hidden">
<CardContent className="p-4">
<div className="flex flex-col space-y-2">
<a
href={source.url}
target="_blank"
rel="noopener noreferrer"
className="text-blue-500 hover:underline font-medium break-words"
>
{source.title}
</a>
<UrlDisplay url={source.url} />
</div>
</CardContent>
</Card>
))}
</ul>
</div>
</CardContent>
</Card>
</div>
Expand All @@ -241,11 +292,12 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
href={result.url}
target="_blank"
rel="noopener noreferrer"
className="text-blue-500 hover:underline"
className="text-blue-500"
>
{result.title}
</a>
</h3>
<UrlDisplay url={result.url} />
{result.publishedDate && (
<p className="text-sm text-muted-foreground">
Published on:{" "}
Expand All @@ -263,7 +315,7 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
expandedResult === result.id ? null : result.id
)
}
className="ml-2 text-blue-500 hover:underline"
className="ml-2"
>
{expandedResult === result.id ? "Show less" : "Show more"}
</button>
Expand Down
1 change: 0 additions & 1 deletion components/SidebarMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { SidebarSimple } from "@phosphor-icons/react"
import { useTheme } from "next-themes"

import Sidebar from "./Sidebar"
import { Button } from "./ui/button"
import { Sheet, SheetContent, SheetTrigger } from "./ui/sheet"

interface SidebarMobileProps {
Expand Down
3 changes: 3 additions & 0 deletions components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
import {
FaHand,
FaMessage,
FaPencil,
FaRankingStar,
FaSquarePollVertical,
} from "react-icons/fa6"
Expand Down Expand Up @@ -122,6 +123,8 @@ const icons = {
edit: FaEdit,
eye: FaEye,
eyeOff: FaEyeSlash,
book: FaBook,
pencil: FaPencil,
}

export const Icons: IconsType = icons
20 changes: 20 additions & 0 deletions config/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ export const githubLink: NavItem = {
external: true,
}

export const researcherLink: NavItem = {
title: "Researcher",
href: "/researcher",
icon: "pencil",
tooltip: "Your very own AI researcher",
}

export const dfdaLink: NavItem = {
title: "DFDA",
href: "/dfda",
icon: "health",
tooltip: "The Decentralized Food and Drug Administration",
}

export const profileSettingsLink: NavItem = {
title: "Profile Settings",
href: "/dashboard/settings",
Expand Down Expand Up @@ -134,6 +148,8 @@ export const avatarNav: Navigation = {
//wishingWellsLink,
//globalProblemsVoteLink,
//createWish
researcherLink,
dfdaLink,
],
}

Expand All @@ -152,6 +168,8 @@ export const generalSidebarNav: Navigation = {
//globalSolutionsResultsLink,
docsLink,
githubLink,
researcherLink,
dfdaLink,
],
}

Expand All @@ -163,5 +181,7 @@ export const generalFooterNav: Navigation = {
globalProblemsResultsLink,
docsLink,
githubLink,
researcherLink,
dfdaLink,
],
}
12 changes: 7 additions & 5 deletions lib/agents/researcher/researcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function getModel(modelName: string): LanguageModelV1 {

export async function writeArticle(
topic: string,
userId: string = 'test-user',
userId: string,
options: {
numberOfSearchQueryVariations?: number,
numberOfWebResultsToInclude?: number,
Expand Down Expand Up @@ -120,7 +120,9 @@ export async function writeArticle(
if (citationStyle === 'footnote') {
citationInstructions = 'Provide citations in the text using markdown footnote notation like [^1].';
} else if (citationStyle === 'hyperlinked-text') {
citationInstructions = 'Hyperlink the relevant text in the report to the source URLs used using markdown hyperlink notation like [text](https://link-where-you-got-the-information).';
citationInstructions = `'YOU MUST HYPERLINK THE RELEVANT text in the report to the source
URLs used using markdown hyperlink notation
like [text](https://link-where-you-got-the-information).';`
}

const prompt = `
Expand Down Expand Up @@ -331,7 +333,7 @@ export async function findOrCreateArticleByPromptedTopic(promptedTopic: string,
return article;
}

export async function deleteArticleByPromptedTopic(promptedTopic: string, userId: string = 'test-user'): Promise<void> {
export async function deleteArticleByPromptedTopic(promptedTopic: string, userId: string): Promise<void> {
// Find the article(s) to delete
const articlesToDelete = await prisma.article.findMany({
where: {
Expand All @@ -355,12 +357,12 @@ export async function deleteArticleByPromptedTopic(promptedTopic: string, userId
});
}

export async function findArticleByTopic(promptedTopic: string, userId: string = 'test-user'):
export async function findArticleByTopic(promptedTopic: string, userId?: string):
Promise<ArticleWithRelations | null> {
return prisma.article.findFirst({
where: {
promptedTopic: promptedTopic,
userId: userId
...(userId ? { userId } : {})
},
include: {
user: true,
Expand Down
Loading

0 comments on commit 582a0fc

Please sign in to comment.