-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathApp.tsx
More file actions
66 lines (56 loc) · 2.33 KB
/
Copy pathApp.tsx
File metadata and controls
66 lines (56 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { ReactNode } from 'react'
import Page, { PageProps } from './Page.js'
import Welcome from './Welcome.js'
import { sortableDataFrame } from 'hightable'
import { byteLengthFromUrl, parquetMetadataAsync } from 'hyparquet'
import { AsyncBufferFrom, asyncBufferFrom, parquetDataFrame } from 'hyperparam'
import { useCallback, useEffect, useState } from 'react'
import Dropzone from './Dropzone.js'
import { setCurrentFile, setLoadUrlFn } from './webmcp.js'
import Layout from './Layout.js'
export default function App(): ReactNode {
const params = new URLSearchParams(location.search)
const url = params.get('key') ?? undefined
const [error, setError] = useState<Error>()
const [pageProps, setPageProps] = useState<PageProps>()
// Register the URL loader with WebMCP
setLoadUrlFn(onUrlDrop)
const setUnknownError = useCallback((e: unknown) => {
setError(e instanceof Error ? e : new Error(String(e)))
}, [])
const setAsyncBuffer = useCallback(async function setAsyncBuffer(name: string, from: AsyncBufferFrom) {
const asyncBuffer = await asyncBufferFrom(from)
const metadata = await parquetMetadataAsync(asyncBuffer)
const df = sortableDataFrame(parquetDataFrame(from, metadata))
setPageProps({ metadata, df, name, byteLength: from.byteLength, setError: setUnknownError })
setCurrentFile(name, 'url' in from ? from.url : undefined)
}, [setUnknownError])
const onUrlDrop = useCallback(
(url: string) => {
// Add key=url to query string
const params = new URLSearchParams(location.search)
params.set('key', url)
history.pushState({}, '', `${location.pathname}?${params}`)
byteLengthFromUrl(url).then(byteLength => setAsyncBuffer(url, { url, byteLength })).catch(setUnknownError)
},
[setUnknownError, setAsyncBuffer],
)
useEffect(() => {
if (!pageProps && url) {
onUrlDrop(url)
}
}, [ url, pageProps, onUrlDrop])
function onFileDrop(file: File) {
// Clear query string
history.pushState({}, '', location.pathname)
setAsyncBuffer(file.name, { file, byteLength: file.size }).catch(setUnknownError)
}
return <Layout error={error}>
<Dropzone
onError={(e) => { setError(e) }}
onFileDrop={onFileDrop}
onUrlDrop={onUrlDrop}>
{pageProps ? <Page {...pageProps} /> : <Welcome setUrl={onUrlDrop} />}
</Dropzone>
</Layout>
}