Skip to content

Commit d1e00a2

Browse files
committed
refactor
1 parent 4b6dd17 commit d1e00a2

16 files changed

+702
-292
lines changed

packages/db-devtools/src/BaseTanStackDbDevtoolsPanel.tsx

Lines changed: 67 additions & 291 deletions
Large diffs are not rendered by default.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { clsx as cx } from 'clsx'
2+
import { useStyles } from '../useStyles'
3+
import { CollectionStats } from './CollectionStats'
4+
import type { Accessor } from 'solid-js'
5+
import type { CollectionMetadata } from '../types'
6+
7+
interface CollectionItemProps {
8+
collection: CollectionMetadata
9+
isActive: Accessor<boolean>
10+
onSelect: (collection: CollectionMetadata) => void
11+
}
12+
13+
export function CollectionItem({
14+
collection,
15+
isActive,
16+
onSelect,
17+
}: CollectionItemProps) {
18+
const styles = useStyles()
19+
20+
return (
21+
<div
22+
class={cx(
23+
styles().collectionItem,
24+
isActive() ? styles().collectionItemActive : ''
25+
)}
26+
onClick={() => onSelect(collection)}
27+
>
28+
<div class={styles().collectionName}>{collection.id}</div>
29+
<CollectionStats collection={collection} />
30+
</div>
31+
)
32+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { clsx as cx } from 'clsx'
2+
import { useStyles } from '../useStyles'
3+
import { formatTime } from '../utils/formatTime'
4+
import type { CollectionMetadata } from '../types'
5+
6+
interface CollectionStatsProps {
7+
collection: CollectionMetadata
8+
}
9+
10+
export function CollectionStats({ collection }: CollectionStatsProps) {
11+
const styles = useStyles()
12+
13+
if (collection.type === 'collection') {
14+
// Standard collection stats
15+
return (
16+
<div class={styles().collectionStats}>
17+
<div>{collection.size}</div>
18+
<div>/</div>
19+
<div>{collection.transactionCount}</div>
20+
<div>/</div>
21+
<div>{formatTime(collection.gcTime || 0)}</div>
22+
<div>/</div>
23+
<div class={cx(
24+
styles().collectionStatus,
25+
collection.status === 'error' ? styles().collectionStatusError : ''
26+
)}>
27+
{collection.status}
28+
</div>
29+
</div>
30+
)
31+
} else {
32+
// Live query collection stats
33+
return (
34+
<div class={styles().collectionStats}>
35+
<div>{collection.size}</div>
36+
<div>/</div>
37+
<div>{formatTime(collection.gcTime || 0)}</div>
38+
<div>/</div>
39+
<div class={cx(
40+
styles().collectionStatus,
41+
collection.status === 'error' ? styles().collectionStatusError : ''
42+
)}>
43+
{collection.status}
44+
</div>
45+
</div>
46+
)
47+
}
48+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { Show, For, createMemo } from 'solid-js'
2+
import { useStyles } from '../useStyles'
3+
import { CollectionItem } from './CollectionItem'
4+
import { multiSortBy } from '../utils'
5+
import type { Accessor } from 'solid-js'
6+
import type { CollectionMetadata } from '../types'
7+
8+
interface CollectionsPanelProps {
9+
collections: Accessor<CollectionMetadata[]>
10+
activeCollectionId: Accessor<string>
11+
onSelectCollection: (collection: CollectionMetadata) => void
12+
}
13+
14+
export function CollectionsPanel({
15+
collections,
16+
activeCollectionId,
17+
onSelectCollection,
18+
}: CollectionsPanelProps) {
19+
const styles = useStyles()
20+
21+
const sortedCollections = createMemo(() => {
22+
return multiSortBy(
23+
collections(),
24+
[
25+
(c) => c.status === 'error' ? 0 : 1, // Errors first
26+
(c) => c.id.toLowerCase(), // Then alphabetically by ID
27+
]
28+
)
29+
})
30+
31+
// Group collections by type
32+
const standardCollections = createMemo(() =>
33+
sortedCollections().filter(c => c.type === 'collection')
34+
)
35+
36+
const liveCollections = createMemo(() =>
37+
sortedCollections().filter(c => c.type === 'live-query')
38+
)
39+
40+
return (
41+
<div class={styles().collectionsExplorer}>
42+
<div class={styles().collectionsList}>
43+
<Show
44+
when={sortedCollections().length > 0}
45+
fallback={
46+
<div style={{ padding: '16px', color: '#666' }}>
47+
No collections found
48+
</div>
49+
}
50+
>
51+
{/* Standard Collections */}
52+
<Show when={standardCollections().length > 0}>
53+
<div class={styles().collectionGroup}>
54+
<div class={styles().collectionGroupHeader}>
55+
<div>Standard Collections ({standardCollections().length})</div>
56+
<div class={styles().collectionGroupStats}>
57+
<span>Items</span>
58+
<span>/</span>
59+
<span>Txn</span>
60+
<span>/</span>
61+
<span>GC</span>
62+
<span>/</span>
63+
<span>Status</span>
64+
</div>
65+
</div>
66+
<For each={standardCollections()}>{(collection) =>
67+
<CollectionItem
68+
collection={collection}
69+
isActive={() => collection.id === activeCollectionId()}
70+
onSelect={onSelectCollection}
71+
/>
72+
}</For>
73+
</div>
74+
</Show>
75+
76+
{/* Live Collections */}
77+
<Show when={liveCollections().length > 0}>
78+
<div class={styles().collectionGroup}>
79+
<div class={styles().collectionGroupHeader}>
80+
<div>Live Collections ({liveCollections().length})</div>
81+
<div class={styles().collectionGroupStats}>
82+
<span>Items</span>
83+
<span>/</span>
84+
<span>GC</span>
85+
<span>/</span>
86+
<span>Status</span>
87+
</div>
88+
</div>
89+
<For each={liveCollections()}>{(collection) =>
90+
<CollectionItem
91+
collection={collection}
92+
isActive={() => collection.id === activeCollectionId()}
93+
onSelect={onSelectCollection}
94+
/>
95+
}</For>
96+
</div>
97+
</Show>
98+
</Show>
99+
</div>
100+
</div>
101+
)
102+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { Show } from 'solid-js'
2+
import { useStyles } from '../useStyles'
3+
import type { CollectionMetadata, TransactionDetails } from '../types'
4+
5+
interface DetailsPanelProps {
6+
selectedView: 'collections' | 'transactions'
7+
activeCollection?: CollectionMetadata
8+
activeTransaction?: TransactionDetails
9+
}
10+
11+
export function DetailsPanel({
12+
selectedView,
13+
activeCollection,
14+
activeTransaction,
15+
}: DetailsPanelProps) {
16+
const styles = useStyles()
17+
18+
return (
19+
<Show when={selectedView === 'collections'}>
20+
<Show
21+
when={activeCollection}
22+
fallback={
23+
<div class={styles().detailsPanel}>
24+
<div class={styles().detailsHeader}>
25+
Select a collection to view details
26+
</div>
27+
</div>
28+
}
29+
>
30+
{(collection) => (
31+
<div class={styles().detailsPanel}>
32+
<div class={styles().detailsHeader}>
33+
{collection().id}
34+
</div>
35+
<div class={styles().detailsContent}>
36+
<pre>{JSON.stringify(collection(), null, 2)}</pre>
37+
</div>
38+
</div>
39+
)}
40+
</Show>
41+
</Show>
42+
)
43+
}
44+
45+
export function TransactionDetailsPanel({
46+
selectedView,
47+
activeTransaction,
48+
}: DetailsPanelProps) {
49+
const styles = useStyles()
50+
51+
return (
52+
<Show when={selectedView === 'transactions'}>
53+
<Show
54+
when={activeTransaction}
55+
fallback={
56+
<div class={styles().detailsPanel}>
57+
<div class={styles().detailsHeader}>
58+
Select a transaction to view details
59+
</div>
60+
</div>
61+
}
62+
>
63+
{(transaction) => (
64+
<div class={styles().detailsPanel}>
65+
<div class={styles().detailsHeader}>
66+
Transaction {transaction().id}
67+
</div>
68+
<div class={styles().detailsContent}>
69+
<pre>{JSON.stringify(transaction(), null, 2)}</pre>
70+
</div>
71+
</div>
72+
)}
73+
</Show>
74+
</Show>
75+
)
76+
}
77+
78+
export function UnifiedDetailsPanel({
79+
selectedView,
80+
activeCollection,
81+
activeTransaction,
82+
}: DetailsPanelProps) {
83+
const styles = useStyles()
84+
85+
// Simple conditional rendering
86+
if (selectedView === 'collections') {
87+
if (activeCollection) {
88+
return (
89+
<div class={styles().detailsPanel}>
90+
<div class={styles().detailsHeader}>
91+
{activeCollection.id}
92+
</div>
93+
<div class={styles().detailsContent}>
94+
<pre>{JSON.stringify(activeCollection, null, 2)}</pre>
95+
</div>
96+
</div>
97+
)
98+
} else {
99+
return (
100+
<div class={styles().detailsPanel}>
101+
<div class={styles().detailsHeader}>
102+
Select a collection to view details
103+
</div>
104+
</div>
105+
)
106+
}
107+
} else if (selectedView === 'transactions') {
108+
if (activeTransaction) {
109+
return (
110+
<div class={styles().detailsPanel}>
111+
<div class={styles().detailsHeader}>
112+
Transaction {activeTransaction.id}
113+
</div>
114+
<div class={styles().detailsContent}>
115+
<pre>{JSON.stringify(activeTransaction, null, 2)}</pre>
116+
</div>
117+
</div>
118+
)
119+
} else {
120+
return (
121+
<div class={styles().detailsPanel}>
122+
<div class={styles().detailsHeader}>
123+
Select a transaction to view details
124+
</div>
125+
</div>
126+
)
127+
}
128+
}
129+
130+
// Fallback
131+
return (
132+
<div class={styles().detailsPanel}>
133+
<div class={styles().detailsHeader}>
134+
Unknown view: {selectedView}
135+
</div>
136+
</div>
137+
)
138+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { clsx as cx } from 'clsx'
2+
import { useStyles } from '../useStyles'
3+
4+
interface LogoProps {
5+
className?: () => string
6+
[key: string]: any
7+
}
8+
9+
export function Logo(props: LogoProps) {
10+
const { className, ...rest } = props
11+
const styles = useStyles()
12+
return (
13+
<button {...rest} class={cx(styles().logo, className ? className() : '')}>
14+
<div class={styles().tanstackLogo}>TANSTACK</div>
15+
<div class={styles().dbLogo}>TanStack DB v0</div>
16+
</button>
17+
)
18+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { clsx as cx } from 'clsx'
2+
import { useStyles } from '../useStyles'
3+
import type { Accessor } from 'solid-js'
4+
5+
interface TabNavigationProps {
6+
selectedView: Accessor<'collections' | 'transactions'>
7+
collectionsCount: Accessor<number>
8+
transactionsCount: Accessor<number>
9+
onSelectView: (view: 'collections' | 'transactions') => void
10+
}
11+
12+
export function TabNavigation({
13+
selectedView,
14+
collectionsCount,
15+
transactionsCount,
16+
onSelectView,
17+
}: TabNavigationProps) {
18+
const styles = useStyles()
19+
20+
return (
21+
<div class={styles().tabNav}>
22+
<button
23+
onClick={() => {
24+
onSelectView('collections')
25+
}}
26+
class={cx(
27+
styles().tabBtn,
28+
selectedView() === 'collections' && styles().tabBtnActive
29+
)}
30+
>
31+
Collections ({collectionsCount()})
32+
</button>
33+
<button
34+
onClick={() => {
35+
onSelectView('transactions')
36+
}}
37+
class={cx(
38+
styles().tabBtn,
39+
selectedView() === 'transactions' && styles().tabBtnActive
40+
)}
41+
>
42+
Transactions ({transactionsCount()})
43+
</button>
44+
</div>
45+
)
46+
}

0 commit comments

Comments
 (0)