Skip to content

Commit d93a353

Browse files
committed
fixed stuff
1 parent 98626e7 commit d93a353

20 files changed

+218
-3311
lines changed

examples/react/todo/src/App.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
electricCollectionOptions,
55
queryCollectionOptions,
66
} from "@tanstack/db-collections"
7-
import { TanStackReactDbDevtools } from "@tanstack/react-db-devtools"
87
import { QueryClient } from "@tanstack/query-core"
98
import { selectConfigSchema, selectTodoSchema } from "./db/validation"
109
import type { Collection } from "@tanstack/react-db"

packages/db-devtools/src/BaseTanStackDbDevtoolsPanel.tsx

Lines changed: 143 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { clsx as cx } from 'clsx'
2-
import { Show, createMemo, createSignal, onMount } from 'solid-js'
2+
import { Show, createMemo, createSignal, onMount, For } from 'solid-js'
33
import { useDevtoolsOnClose } from './contexts'
44
import { useStyles } from './useStyles'
55
import { useLocalStorage } from './useLocalStorage'
@@ -56,7 +56,7 @@ function CollectionItem({
5656
onSelect,
5757
}: {
5858
collection: CollectionMetadata
59-
isActive: boolean
59+
isActive: Accessor<boolean>
6060
onSelect: (collection: CollectionMetadata) => void
6161
}) {
6262
const styles = useStyles()
@@ -65,7 +65,7 @@ function CollectionItem({
6565
<div
6666
class={cx(
6767
styles().collectionItem,
68-
isActive ? styles().collectionItemActive : ''
68+
isActive() ? styles().collectionItemActive : ''
6969
)}
7070
onClick={() => onSelect(collection)}
7171
>
@@ -102,27 +102,68 @@ export const BaseTanStackDbDevtoolsPanel = function BaseTanStackDbDevtoolsPanel(
102102
'',
103103
)
104104

105+
const [selectedView, setSelectedView] = createSignal<'collections' | 'transactions'>('collections')
106+
const [selectedTransaction, setSelectedTransaction] = createSignal<string | null>(null)
107+
105108
const [collections, setCollections] = createSignal<CollectionMetadata[]>([])
106109

107110
// Poll for collections data
108111
onMount(() => {
109112
const updateCollections = () => {
110113
if (typeof window === 'undefined') return
111-
112114
try {
113-
const metadata = registry().getAllCollectionMetadata()
114-
setCollections(metadata)
115+
const collections = registry().getAllCollectionMetadata()
116+
setCollections(collections)
115117
} catch (error) {
116-
console.warn('Error fetching collections metadata:', error)
118+
// Silently handle errors when fetching collections metadata
117119
}
118120
}
119-
120121
updateCollections()
121122
const intervalId = setInterval(updateCollections, POLLING_INTERVAL_MS)
122-
123123
return () => clearInterval(intervalId)
124124
})
125125

126+
// Helper function to detect if collections data actually changed
127+
const hasCollectionsChanged = (oldCollections: CollectionMetadata[], newCollections: CollectionMetadata[]): boolean => {
128+
if (oldCollections.length !== newCollections.length) return true
129+
130+
// Create maps for O(1) lookup by ID
131+
const oldMap = new Map(oldCollections.map(c => [c.id, c]))
132+
const newMap = new Map(newCollections.map(c => [c.id, c]))
133+
134+
// Check if any collection data changed by comparing by ID
135+
for (const [id, old] of oldMap) {
136+
const new_ = newMap.get(id)
137+
if (!new_) return true // Collection was removed
138+
139+
if (old.status !== new_.status) return true
140+
if (old.size !== new_.size) return true
141+
if (old.hasTransactions !== new_.hasTransactions) return true
142+
if (old.transactionCount !== new_.transactionCount) return true
143+
}
144+
145+
// Check if any new collections were added
146+
for (const [id] of newMap) {
147+
if (!oldMap.has(id)) return true
148+
}
149+
150+
return false
151+
}
152+
153+
// --- Fix: Ensure selection is always valid and highlight updates instantly ---
154+
// If the selected collection disappears, auto-select the first available one
155+
createMemo(() => {
156+
const ids = collections().map(c => c.id)
157+
if (ids.length === 0) {
158+
setActiveCollectionId('') // always a string
159+
return
160+
}
161+
if (!ids.includes(activeCollectionId())) {
162+
setActiveCollectionId(ids[0] ?? '')
163+
}
164+
})
165+
// --- End fix ---
166+
126167
const activeCollection = createMemo(() => {
127168
const active = collections().find(c => c.id === activeCollectionId())
128169
return active || collections()[0]
@@ -138,24 +179,7 @@ export const BaseTanStackDbDevtoolsPanel = function BaseTanStackDbDevtoolsPanel(
138179
)
139180
})
140181

141-
const collectionDetails = createMemo(() => {
142-
const active = activeCollection()
143-
if (!active) return null
144-
145-
try {
146-
const collection = registry().getCollection(active.id)
147-
const metadata = registry().getCollectionMetadata(active.id)
148-
149-
return {
150-
collection,
151-
metadata,
152-
transactions: registry().getTransactions(active.id),
153-
}
154-
} catch (error) {
155-
console.warn('Error getting collection details:', error)
156-
return null
157-
}
158-
})
182+
159183

160184
return (
161185
<div
@@ -203,29 +227,98 @@ export const BaseTanStackDbDevtoolsPanel = function BaseTanStackDbDevtoolsPanel(
203227
<Logo />
204228
</div>
205229
<div class={styles().collectionsExplorerContainer}>
206-
<div class={styles().collectionsExplorer}>
207-
<div class={styles().collectionsHeader}>
208-
<div>Collections ({collections().length})</div>
209-
</div>
210-
211-
<div class={styles().collectionsList}>
212-
<Show
213-
when={sortedCollections().length > 0}
214-
fallback={
215-
<div style={{ padding: '16px', color: '#666' }}>
216-
No collections found
217-
</div>
218-
}
219-
>
220-
{sortedCollections().map((collection) => (
221-
<CollectionItem
222-
collection={collection}
223-
isActive={collection.id === activeCollectionId()}
224-
onSelect={(c) => setActiveCollectionId(c.id)}
225-
/>
226-
))}
227-
</Show>
228-
</div>
230+
{/* Tab Navigation */}
231+
<div class={styles().tabNav}>
232+
<button
233+
onClick={() => setSelectedView('collections')}
234+
class={cx(
235+
styles().tabBtn,
236+
selectedView() === 'collections' && styles().tabBtnActive
237+
)}
238+
>
239+
Collections
240+
</button>
241+
<button
242+
onClick={() => setSelectedView('transactions')}
243+
class={cx(
244+
styles().tabBtn,
245+
selectedView() === 'transactions' && styles().tabBtnActive
246+
)}
247+
>
248+
Transactions ({registry().getTransactions().length})
249+
</button>
250+
</div>
251+
252+
{/* Content based on selected view */}
253+
<div class={styles().sidebarContent}>
254+
<Show when={selectedView() === 'collections'}>
255+
<div class={styles().collectionsExplorer}>
256+
<div class={styles().collectionsHeader}>
257+
<div>Collections ({collections().length})</div>
258+
</div>
259+
260+
<div class={styles().collectionsList}>
261+
<Show
262+
when={sortedCollections().length > 0}
263+
fallback={
264+
<div style={{ padding: '16px', color: '#666' }}>
265+
No collections found
266+
</div>
267+
}
268+
>
269+
<For each={sortedCollections()}>{(collection) =>
270+
<CollectionItem
271+
collection={collection}
272+
isActive={() => collection.id === activeCollectionId()}
273+
onSelect={(c) => setActiveCollectionId(c.id)}
274+
/>
275+
}</For>
276+
</Show>
277+
</div>
278+
</div>
279+
</Show>
280+
281+
<Show when={selectedView() === 'transactions'}>
282+
<div class={styles().transactionsExplorer}>
283+
<div class={styles().collectionsHeader}>
284+
<div>Transactions ({registry().getTransactions().length})</div>
285+
</div>
286+
287+
<div class={styles().collectionsList}>
288+
<Show
289+
when={registry().getTransactions().length > 0}
290+
fallback={
291+
<div style={{ padding: '16px', color: '#666' }}>
292+
No transactions found
293+
</div>
294+
}
295+
>
296+
{registry().getTransactions().map((transaction) => (
297+
<div
298+
class={cx(
299+
styles().collectionItem,
300+
selectedTransaction() === transaction.id && styles().collectionItemActive
301+
)}
302+
onClick={() => setSelectedTransaction(transaction.id)}
303+
>
304+
<div class={styles().collectionName}>
305+
Transaction {transaction.id.slice(0, 8)}...
306+
</div>
307+
<div class={styles().collectionCount}>
308+
{transaction.mutations.length} mutations
309+
</div>
310+
<div class={cx(
311+
styles().collectionStatus,
312+
transaction.state === 'error' ? styles().collectionStatusError : ''
313+
)}>
314+
{transaction.state}
315+
</div>
316+
</div>
317+
))}
318+
</Show>
319+
</div>
320+
</div>
321+
</Show>
229322
</div>
230323
</div>
231324
</div>

packages/db-devtools/src/DbDevtools.tsx

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

0 commit comments

Comments
 (0)