Skip to content

Commit 0c3c053

Browse files
committed
complete paper graph
1 parent f59ef56 commit 0c3c053

6 files changed

Lines changed: 203 additions & 169 deletions

File tree

@types/paper-graph.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ type Paper = {
66
aclId: string | null,
77
dblpId: string | null,
88

9+
tags: { name: string, color: string }[]
10+
911
title: string,
1012
year: number,
1113
authors: _Author[],

app/tools/paper-graph/Canvas.tsx

Lines changed: 0 additions & 3 deletions
This file was deleted.

app/tools/paper-graph/PaperDetail.tsx

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { LightbulbIcon, OpenIcon } from "@public/icons";
2-
import { useEffect, useRef, useState } from "react";
3-
import { fetchFromSemanticScholar, fetchNotionBlock, fetchNotionPage, getOpenUrl } from "./utils";
2+
import { useRef, useState } from "react";
3+
import { fetchFromSemanticScholar, getOpenUrl } from "./utils";
44
import { useClickOutside } from "@hooks";
55
import PaperCard from "./PaperCard";
66

@@ -13,20 +13,22 @@ export default function PaperDetail({ paper }: { paper: Paper | null }) {
1313
citations: RelatedPaper[],
1414
}
1515
}>({});
16-
const [lightbulbData, setLightbulbData] = useState<{
16+
const [suggestions, setSuggestions] = useState<{
1717
references: any[],
1818
citations: any[],
1919
open: boolean,
2020
}>({ references: [], citations: [], open: false });
21+
const [visibleReferenceCount, setVisibleReferenceCount] = useState(10);
22+
const [visibleCitationCount, setVisibleCitationCount] = useState(10);
2123
const [suggestionLoading, setSuggestionLoading] = useState(false);
2224
const suggestionRef = useRef<HTMLDivElement>(null);
23-
useClickOutside(suggestionRef, () => setLightbulbData(d => ({ ...d, open: false })))
25+
useClickOutside(suggestionRef, () => setSuggestions(d => ({ ...d, open: false })))
2426

2527
async function handleSuggest() {
2628
if (!paper) return;
2729

2830
if (cachedRelatedPapers[paper.id]) {
29-
setLightbulbData({
31+
setSuggestions({
3032
...cachedRelatedPapers[paper.id],
3133
open: true,
3234
});
@@ -47,7 +49,7 @@ export default function PaperDetail({ paper }: { paper: Paper | null }) {
4749
}));
4850

4951
// Show modal
50-
setLightbulbData({
52+
setSuggestions({
5153
...newEntry,
5254
open: true,
5355
});
@@ -59,7 +61,7 @@ export default function PaperDetail({ paper }: { paper: Paper | null }) {
5961
paper
6062
?
6163
<>
62-
<div className="paper-detail w-[30%] bg-slate-100 rounded-md p-2 h-full overflow-auto scrollbar-thin scrollbar-thumb-slate-400 scrollbar-track-slate-200">
64+
<div className="paper-detail bg-slate-100 rounded-md p-2 h-full overflow-auto scrollbar-thin scrollbar-thumb-slate-400 scrollbar-track-slate-200">
6365
<div className='flex justify-between'>
6466
<span className="font-semibold text-sm text-blue-700 truncate">
6567
{paper.title}
@@ -101,38 +103,63 @@ export default function PaperDetail({ paper }: { paper: Paper | null }) {
101103
}
102104
</div>
103105
}
104-
{lightbulbData.open && (
106+
{suggestions.open && (
105107
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
106-
<div ref={suggestionRef} className="bg-white w-[1/2] max-h-[80vh] p-6 rounded shadow overflow-y-auto">
107-
<div className="mb-4">
108-
<h3 className="font-semibold text-gray-700">References</h3>
109-
{lightbulbData.references.length === 0 ? (
110-
<p className="text-sm text-gray-500"> No references found.</p>
108+
<div ref={suggestionRef} className="bg-white w-[50vw] max-h-[80vh] p-6 rounded shadow overflow-y-auto">
109+
110+
{/* References Section */}
111+
<div className="mb-6">
112+
<h3 className="font-semibold text-gray-700 mb-2">References</h3>
113+
{suggestions.references.length === 0 ? (
114+
<p className="text-sm text-gray-500">No references found.</p>
111115
) : (
112116
<>
113-
{lightbulbData.references
117+
{suggestions.references
114118
.sort((a, b) => b.citationCount - a.citationCount)
115-
.map((paper) => <PaperCard key={paper.id} paper={paper} />)}
119+
.slice(0, visibleReferenceCount)
120+
.map((paper) => (
121+
<PaperCard key={paper.scid} paper={paper} />
122+
))}
123+
{visibleReferenceCount < suggestions.references.length && (
124+
<button
125+
className="text-blue-600 text-sm mt-2"
126+
onClick={() => setVisibleReferenceCount(c => c + 10)}
127+
>
128+
Show 10 more
129+
</button>
130+
)}
116131
</>
117132
)}
118133
</div>
119134

135+
{/* Citations Section */}
120136
<div>
121-
<h3 className="font-semibold text-gray-700">Citations</h3>
122-
{lightbulbData.citations.length === 0 ? (
137+
<h3 className="font-semibold text-gray-700 mb-2">Citations</h3>
138+
{suggestions.citations.length === 0 ? (
123139
<p className="text-sm text-gray-500">No citations found.</p>
124140
) : (
125141
<>
126-
{lightbulbData.citations
142+
{suggestions.citations
127143
.sort((a, b) => b.citationCount - a.citationCount)
128-
.map((paper) =>
129-
<PaperCard key={paper.scid} paper={paper} />)}
144+
.slice(0, visibleCitationCount)
145+
.map((paper) => (
146+
<PaperCard key={paper.scid} paper={paper} />
147+
))}
148+
{visibleCitationCount < suggestions.citations.length && (
149+
<button
150+
className="text-blue-600 text-sm mt-2"
151+
onClick={() => setVisibleCitationCount(c => c + 10)}
152+
>
153+
Show 10 more
154+
</button>
155+
)}
130156
</>
131157
)}
132158
</div>
133159
</div>
134160
</div>
135161
)}
162+
136163
</div>
137164
</>
138165
: <></>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client';
2+
import React from 'react';
3+
4+
interface Props {
5+
nodes: GraphNode[];
6+
hoveredNodeId: string | null;
7+
onHover: (id: string | null) => void;
8+
onClick: (node: GraphNode) => void;
9+
}
10+
11+
export default function PaperList({ nodes, hoveredNodeId, onHover, onClick }: Props) {
12+
return (
13+
<div className='border-gray-300'>
14+
{nodes.map((node) => (
15+
<div
16+
key={node.id}
17+
className={`p-3 border border-b-gray-300
18+
${hoveredNodeId === node.id ? 'bg-gray-100' : 'bg-white'}
19+
rounded-lg shadow-sm cursor-pointer`}
20+
onMouseOver={() => onHover(node.id)}
21+
onMouseLeave={() => onHover(null)}
22+
onClick={() => onClick(node)}
23+
>
24+
<div className="text-sm">{node.title}</div>
25+
<div>
26+
{node.tags.map((tag) =>
27+
<span key={tag.name} style={{ backgroundColor: tag.color }} className='mt-2 mr-1 p-1 text-[10px] rounded-sm text-white opacity-60'>
28+
{tag.name}
29+
</span>)}
30+
</div>
31+
</div>
32+
))}
33+
</div>
34+
);
35+
}

0 commit comments

Comments
 (0)