Skip to content

Commit e2eda5d

Browse files
committed
feat: connect APIs
1 parent b76ecd7 commit e2eda5d

File tree

8 files changed

+602
-19
lines changed

8 files changed

+602
-19
lines changed

src/renderer/src/components/connection-wizard/wizard-modal.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,32 @@ export function ConnectionWizard(): JSX.Element {
151151
api
152152
.post('/api/user/db/create/profile', filteredPayload)
153153
.then((response) => {
154-
const id = response.data.id as number
154+
const id = response.data.id as string
155155
setConnectionDetail((prev) => ({
156156
...prev,
157157
id: id
158158
}))
159+
createAnnotation(id)
159160
})
160161
.catch(() => {
161162
toast.error('데이터베이스 연결 생성 중 오류가 발생했습니다.')
162163
})
164+
.finally(() => {
165+
// NOTE: 페이지 새로고침 -> 저장된거 불러오도록
166+
window.location.reload()
167+
onClose()
168+
})
169+
}
163170

164-
onClose()
171+
const createAnnotation = (db_profile_id: string): void => {
172+
api
173+
.post('/api/annotations/create', {
174+
db_profile_id: db_profile_id
175+
})
176+
.then(() => {})
177+
.catch(() => {
178+
toast.error('어노테이션 생성 중 오류가 발생했습니다.')
179+
})
165180
}
166181

167182
return (

src/renderer/src/components/erd/table-detail-sidebar.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import {
33
Table2,
44
KeyRound,
55
Link,
6-
Square,
7-
SquareDashedBottomIcon as SquareDashed,
86
Database,
97
Calendar,
108
Hash,
119
Type,
1210
Check,
13-
LucideProps
11+
LucideProps,
12+
Diamond
1413
} from 'lucide-react'
1514
import { Button } from '@/components/ui/button'
1615
import { Badge } from '@/components/ui/badge'
@@ -29,20 +28,20 @@ interface TableDetailSidebarProps {
2928
const constraintIcons = {
3029
primary: KeyRound,
3130
foreign: Link,
32-
'not-null': Square,
33-
nullable: SquareDashed,
31+
'not-null': Diamond,
32+
nullable: Diamond,
3433
unique: Hash,
3534
index: Database
3635
} as const
3736

3837
// 제약 조건들 색상
3938
const constraintColors = {
40-
primary: 'text-yellow-400 bg-yellow-400/10',
39+
primary: 'text-purple-400 bg-purple-400/10',
4140
foreign: 'text-blue-400 bg-blue-400/10',
4241
'not-null': 'text-gray-400 bg-gray-400/10',
4342
nullable: 'text-gray-500 bg-gray-500/10',
4443
unique: 'text-green-400 bg-green-400/10',
45-
index: 'text-purple-400 bg-purple-400/10'
44+
index: 'text-yellow-400 bg-yellow-400/10'
4645
} as const
4746

4847
// 제약 조건 표시
@@ -194,7 +193,10 @@ export function TableDetailSidebar({
194193
className={`flex items-center gap-1 px-2 py-1 rounded text-xs ${colorClass}`}
195194
title={label}
196195
>
197-
<IconComponent className="w-3 h-3" />
196+
<IconComponent
197+
className="w-3 h-3"
198+
fill={constraint === 'not-null' ? 'gray' : 'black'}
199+
/>
198200
<span>{label}</span>
199201
</div>
200202
)

src/renderer/src/components/layout/side-bar.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import AppIcon from '@renderer/assets/icon.svg'
33
import { Database, Plus, Settings, Tag } from 'lucide-react'
44
import { cn } from '@/lib/utils'
55
import type { NavItem } from '../workspace/types'
6-
import { useNavigate } from 'react-router-dom'
6+
import { useLocation, useNavigate } from 'react-router-dom'
77

88
const bottomNavItems: NavItem[] = [
99
{
@@ -59,21 +59,24 @@ function NavButton({ item }: { item: NavItem }): React.JSX.Element {
5959

6060
export function Sidebar(): React.JSX.Element {
6161
const navigate = useNavigate()
62+
const location = useLocation()
6263

6364
const topNavItems: NavItem[] = [
6465
{
6566
id: 'database',
6667
icon: Database,
67-
active: true,
68+
active: location.pathname === '/',
6869
onClick: (): void | Promise<void> => navigate('/')
6970
},
7071
{
7172
id: 'tags',
7273
icon: Tag,
74+
active: location.pathname === '/erd',
7375
disabled: false,
7476
onClick: (): void | Promise<void> => navigate('/erd')
7577
} // TODO: DB 연결 후에 disabled: false
7678
]
79+
7780
return (
7881
<aside className="h-full flex flex-col bg-zinc-900 p-4 items-center gap-6">
7982
<img src={AppIcon} className="size-6" alt="QGenie" />
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { DATABASES } from '@/components/connection-wizard/wizard.type'
2+
import { AnnotationItemProps } from './annotation.types'
3+
4+
export default function AnnotationItem({
5+
db,
6+
index,
7+
hasFocus,
8+
onToggle
9+
}: AnnotationItemProps): React.JSX.Element {
10+
const handleToggle = (): void => {
11+
onToggle(index)
12+
}
13+
const dbItem = DATABASES.find((d) => d.id === db.type)
14+
15+
const text = db.view_name ? db.view_name : db.type
16+
17+
return (
18+
<div className="flex flex-col justify-start items-start w-full">
19+
<div
20+
data-state="Default"
21+
className={`w-full pl-2 pr-2 py-1 rounded inline-flex justify-start items-center gap-1 cursor-pointer ${hasFocus && 'bg-genie-600'} overflow-hidden`}
22+
onClick={handleToggle}
23+
>
24+
<div className="size-6 p-0 flex items-center justify-center shrink-0">
25+
<img src={dbItem?.icon} className="w-full h-full" />
26+
</div>
27+
<div className="flex gap-1 overflow-auto items-center truncate shrink-0">
28+
<div className="justify-start h-4 content-center text-neutral-200 text-xs font-semibold font-['Pretendard'] leading-none">
29+
{text}
30+
</div>
31+
<div className="justify-start h-4 content-center text-neutral-400 text-xs font-normal font-['Pretendard'] leading-none">
32+
{db.host}:{db.port}
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
)
38+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { useState, useRef } from 'react'
2+
import AnnotationItem from './annotation-item'
3+
import { AnnotationNode } from './annotation.types'
4+
5+
interface AnnotationSidebarProps {
6+
dbList: AnnotationNode[]
7+
selectedDB: AnnotationNode | null
8+
setSelectedDB: (selectedNode: AnnotationNode) => void
9+
}
10+
11+
export default function AnnotationSidebar({
12+
dbList,
13+
selectedDB,
14+
setSelectedDB
15+
}: AnnotationSidebarProps): React.JSX.Element {
16+
const [width, setWidth] = useState(220)
17+
const isResizing = useRef(false)
18+
const startX = useRef(0)
19+
const startWidth = useRef(0)
20+
21+
const handleMouseDown = (e: React.MouseEvent): void => {
22+
isResizing.current = true
23+
startX.current = e.clientX
24+
startWidth.current = width
25+
26+
document.addEventListener('mousemove', handleMouseMove)
27+
document.addEventListener('mouseup', handleMouseUp)
28+
}
29+
30+
const handleMouseMove = (e: MouseEvent): void => {
31+
if (!isResizing.current) return
32+
const deltaX = e.clientX - startX.current
33+
const newWidth = startWidth.current + deltaX
34+
if (newWidth > 120 && newWidth < 500) {
35+
setWidth(newWidth)
36+
}
37+
}
38+
39+
const handleMouseUp = (): void => {
40+
isResizing.current = false
41+
document.removeEventListener('mousemove', handleMouseMove)
42+
document.removeEventListener('mouseup', handleMouseUp)
43+
}
44+
45+
const handleToggle = (nodeId: number): void => {
46+
setSelectedDB(dbList[nodeId])
47+
}
48+
49+
return (
50+
<div className="flex h-full">
51+
<div
52+
style={{ width, minWidth: 200, maxWidth: 500 }}
53+
className="h-full p-3 bg-neutral-800 outline-1 flex-col justify-start items-start inline-flex select-none"
54+
>
55+
{dbList.map((db, index) => {
56+
return (
57+
<AnnotationItem
58+
db={db}
59+
hasFocus={selectedDB === db}
60+
index={index}
61+
onToggle={handleToggle}
62+
key={db.id}
63+
/>
64+
)
65+
})}
66+
</div>
67+
68+
<div onMouseDown={handleMouseDown} className="w-1 cursor-col-resize bg-genie-800" />
69+
</div>
70+
)
71+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export interface AnnotationNode {
2+
id: string
3+
type: 'mysql' | 'sqlite' | 'postgresql' | 'oracle' | 'mariadb'
4+
host: string
5+
port: number
6+
name?: string
7+
view_name?: string
8+
}
9+
10+
export interface AnnotationItemProps {
11+
db: AnnotationNode
12+
index: number
13+
hasFocus: boolean
14+
onToggle: (nodeIndex: number) => void
15+
}

0 commit comments

Comments
 (0)