Skip to content

Commit 3143cef

Browse files
authored
SCRUM-225-웹 버전 UI 수정 (#36)
* fix: top nav 수정 * feat: 2d graph를 packages/ui에서 통합으로 관리 * chore: tree 컴포넌트를 위한 라이브러리 설치 * feat: Theme에 tree 추가 * feat: tree용 북마크 조회 API 연동 및 tree 구조 구현 * fix: 행성 UI 수정
1 parent 4ee9918 commit 3143cef

29 files changed

Lines changed: 639 additions & 77 deletions

File tree

apps/extension/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"lettercoder": "^0.1.1",
1616
"react": "^18.3.1",
1717
"react-dom": "^18.3.1",
18-
"react-force-graph-2d": "^1.27.1",
1918
"react-router-dom": "^6.28.0",
2019
"zustand": "^5.0.1"
2120
},

apps/extension/src/pages/bookmark.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { useMemo } from "react";
22

3-
import ForceGraph from "@/components/force-graph";
43
import Loading from "@/components/loading";
54
import { useCreateStar } from "@/state/mutation/star";
65
import { useStarStore } from "@/state/zustand/star";
76
import { useTabStore } from "@/state/zustand/tab";
87
import { getHtmlText } from "@/utils/chrome";
8+
import { Graph2D } from "@repo/ui";
99
import { RectangleButton } from "@repo/ui";
1010

1111
import { useNavigate } from "react-router-dom";
@@ -69,7 +69,7 @@ const Bookmark = () => {
6969
<Loading title="페이지를 요약하고 있어요!">
7070
<main className="flex h-full flex-col justify-center gap-28 overflow-x-hidden">
7171
<section>
72-
<ForceGraph graphData={graphData} />
72+
<Graph2D graphData={graphData} />
7373
<h1 className="text-notification">현재 페이지 정보</h1>
7474
</section>
7575
<section className="space-y-4">

apps/extension/src/pages/create-bookmark.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useEffect, useMemo, useState } from "react";
33
import AISummary from "@/assets/ai-summary.svg?react";
44
import Logo from "@/assets/logo.svg?react";
55
import CardWrapper from "@/components/create-bookmark/card-wrapper";
6-
import ForceGraph from "@/components/force-graph";
76
import Loading from "@/components/loading";
87
import { useCreateCategory } from "@/state/mutation/category";
98
import { useCompleteCreateStar, useUpdateStar } from "@/state/mutation/star";
@@ -13,6 +12,7 @@ import { useStarStore } from "@/state/zustand/star";
1312
import { useTabStore } from "@/state/zustand/tab";
1413
import { CategoryListProps } from "@/types/category";
1514
import { CompleteSummarizeStarProps } from "@/types/star";
15+
import { Graph2D } from "@repo/ui";
1616
import { Keyword, RectangleButton, Spinner, Textarea } from "@repo/ui";
1717

1818
import { Navigate, useLocation, useSearchParams } from "react-router-dom";
@@ -199,7 +199,7 @@ const CreateBookmark = () => {
199199
</button>
200200
</header>
201201
<section>
202-
<ForceGraph graphData={graphData} />
202+
<Graph2D graphData={graphData} />
203203
</section>
204204
<CardWrapper
205205
thumbnailUrl={bookmark.thumbnailUrl}

apps/www/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@tanstack/react-query": "^5.59.20",
1414
"next": "15.0.3",
1515
"react": "19.0.0-rc-66855b96-20241106",
16+
"react-d3-tree": "^3.6.6",
1617
"react-dom": "19.0.0-rc-66855b96-20241106",
1718
"three": "^0.175.0",
1819
"wordcloud": "^1.2.3",

apps/www/src/app/bookmarks/layout.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import Sidebar from "@/components/bookmarks/sidebar";
2+
import NavDropdown from "@/components/common/nav-dropdown";
23

34
const BookmarksLayout = ({ children }: { children: React.ReactNode }) => {
45
return (
56
<main className="flex min-h-screen overflow-hidden">
67
<Sidebar />
8+
<div className="fixed right-5 top-5 z-10">
9+
<NavDropdown />
10+
</div>
711
{children}
812
</main>
913
);

apps/www/src/app/bookmarks/page.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"use client";
22

3-
import { useState } from "react";
3+
import { useEffect, useState } from "react";
44

55
import Graph from "@/components/bookmarks/graph";
66
import GraphDetail from "@/components/bookmarks/graph/graph-detail";
77
import Planet from "@/components/bookmarks/graph/planet";
8+
import Tree from "@/components/bookmarks/tree";
89
import { GRAPH_THEME } from "@/constants/bookmark";
910
import { useGetAllStars } from "@/lib/tanstack/query/star";
1011
import { useBookmarkStore } from "@/lib/zustand/bookmark";
@@ -34,6 +35,23 @@ const BookmarkPage = () => {
3435
});
3536
};
3637

38+
const renderTheme = () => {
39+
switch (bookmarkStore.selectedTheme) {
40+
case GRAPH_THEME.GRAPH:
41+
return <Graph onOpen={onOpen} data={data!.result} />;
42+
case GRAPH_THEME.PLANET:
43+
return <Planet onOpen={onOpen} data={data!.result} />;
44+
case GRAPH_THEME.TREE:
45+
return <Tree onOpen={onOpen} />;
46+
}
47+
};
48+
49+
useEffect(() => {
50+
if (data) {
51+
bookmarkStore.setStars(data.result);
52+
}
53+
}, [data]);
54+
3755
if (isPending || !data) {
3856
return (
3957
<main className="flex h-screen w-screen items-center justify-center">
@@ -44,11 +62,7 @@ const BookmarkPage = () => {
4462

4563
return (
4664
<>
47-
{bookmarkStore.selectedTheme === GRAPH_THEME.GRAPH ? (
48-
<Graph onOpen={onOpen} data={data!.result} />
49-
) : (
50-
<Planet onOpen={onOpen} data={data!.result} />
51-
)}
65+
{renderTheme()}
5266
<GraphDetail open={detail.open} id={detail.id} onClose={onClose} />
5367
</>
5468
);

apps/www/src/app/globals.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,24 @@ input[type="checkbox"] {
5858
border-radius: 50%;
5959
}
6060
}
61+
62+
.node__root,
63+
.node__branch,
64+
.node__leaf {
65+
text {
66+
fill: #fff;
67+
}
68+
}
69+
70+
.node__leaf {
71+
stroke: #fff !important;
72+
fill: #111 !important;
73+
}
74+
75+
.rd3t-link {
76+
stroke: #fff !important;
77+
}
78+
79+
.rd3t-label__attributes tspan:nth-of-type(n + 2) {
80+
display: none;
81+
}

apps/www/src/components/bookmarks/graph/graph-detail.tsx

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useMemo, useState } from "react";
22
import Image from "next/image";
33
import Link from "next/link";
44

@@ -11,7 +11,8 @@ import trash from "@/assets/icons/trash.svg";
1111
import { useCreateCategory } from "@/lib/tanstack/mutation/category";
1212
import { useDeleteStar, useUpdateStar } from "@/lib/tanstack/mutation/star";
1313
import { useGetGraphDetail } from "@/lib/tanstack/query/graph";
14-
import { Card, cn, Keyword, Modal, RectangleButton, Spinner, Textarea } from "@repo/ui";
14+
import { useBookmarkStore } from "@/lib/zustand/bookmark";
15+
import { Card, cn, Graph2D, Keyword, Modal, RectangleButton, Spinner, Textarea } from "@repo/ui";
1516

1617
interface GraphDetailProps {
1718
open: boolean;
@@ -29,11 +30,41 @@ const GraphDetail = ({ open, id, onClose }: GraphDetailProps) => {
2930
useGetGraphDetail(id);
3031

3132
const [edit, setEdit] = useState({ activated: false, keyword: "", ...(starData?.result || {}) });
33+
const stars = useBookmarkStore((state) => state.stars);
3234

3335
const { mutateAsync: createCategory, isPending: createCategoryLoading } = useCreateCategory();
3436
const { mutateAsync: updateStar, isPending: updateStarLoading } = useUpdateStar();
3537
const { mutateAsync: deleteStar, isPending: deleteStarLoading } = useDeleteStar(onClose);
3638

39+
const graphData = useMemo(() => {
40+
if (!stars?.starListDto || !stars?.linkListDto || !id) return { nodes: [], links: [] };
41+
42+
// 현재 북마크와 연결된 링크만 필터링
43+
const relatedLinks = stars.linkListDto.filter((link) => link.linkedNodeIdList.includes(id));
44+
45+
// 관련된 노드 ID 수집
46+
const relatedNodeIds = new Set<string>();
47+
relatedLinks.forEach((link) => {
48+
link.linkedNodeIdList.forEach((nodeId) => relatedNodeIds.add(nodeId));
49+
});
50+
51+
// 관련된 노드만 필터링
52+
const relatedNodes = stars.starListDto.filter((star) => relatedNodeIds.has(star.starId));
53+
54+
return {
55+
nodes: relatedNodes.map((star) => ({
56+
id: star.starId,
57+
name: star.title,
58+
val: Math.min(star.views, 10),
59+
url: star.siteUrl,
60+
})),
61+
links: relatedLinks.map((link) => ({
62+
source: link.linkedNodeIdList[0],
63+
target: link.linkedNodeIdList[1],
64+
})),
65+
};
66+
}, [stars, id]);
67+
3768
const onSelectCategory = (categoryName: string) => {
3869
setEdit((prev) => ({ ...prev, categoryName }));
3970
};
@@ -235,6 +266,19 @@ const GraphDetail = ({ open, id, onClose }: GraphDetailProps) => {
235266
)}
236267
</div>
237268
</div>
269+
<Graph2D
270+
graphData={{
271+
nodes: graphData.nodes.map((star) => ({
272+
id: star.id,
273+
name: star.name,
274+
val: 1,
275+
})),
276+
links: graphData.links.map((link) => ({
277+
source: link.source,
278+
target: link.target,
279+
})),
280+
}}
281+
/>
238282
<Card
239283
Thumbnail={
240284
starData?.result?.thumbnailUrl ? (
@@ -327,7 +371,9 @@ const GraphDetail = ({ open, id, onClose }: GraphDetailProps) => {
327371
) : (
328372
<div className="flex h-full w-full flex-col items-center justify-center gap-4 px-2">
329373
<p>북마크를 찾을 수 없습니다.</p>
330-
<RectangleButton onClick={onCloseDetail}>상세 창 닫기</RectangleButton>
374+
<RectangleButton onClick={onCloseDetail} className="w-full flex-none">
375+
상세 창 닫기
376+
</RectangleButton>
331377
</div>
332378
)}
333379
</div>

0 commit comments

Comments
 (0)