document loading working

This commit is contained in:
Youwen Wu 2024-02-12 19:42:56 -08:00
parent 3e97241cf6
commit 7dc55799b8
14 changed files with 236 additions and 136 deletions

25
package-lock.json generated
View file

@ -8,6 +8,7 @@
"name": "eexiv-2", "name": "eexiv-2",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@tanstack/react-query": "^5.20.2",
"minisearch": "^6.3.0", "minisearch": "^6.3.0",
"next": "14.1.0", "next": "14.1.0",
"react": "^18", "react": "^18",
@ -466,6 +467,30 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@tanstack/query-core": {
"version": "5.20.2",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.20.2.tgz",
"integrity": "sha512-sAILwNiyA1I52e6imOsmNDUA/PuOayOzqz5jcLiIB5wBXqVk+HIiriWouPcAkjS8RqARfHUehuoPwcZ7Uzh0GQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "5.20.2",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.20.2.tgz",
"integrity": "sha512-949myvMY77cPqwb71m3wRG2ypgwPijshO5kN9w0CDKWrFC0X8Wh1mwSqst88kIr58tWlWNsGy3U40AK23RgYQA==",
"dependencies": {
"@tanstack/query-core": "5.20.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^18.0.0"
}
},
"node_modules/@types/file-saver": { "node_modules/@types/file-saver": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz", "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz",

View file

@ -10,6 +10,7 @@
"format": "prettier --write ." "format": "prettier --write ."
}, },
"dependencies": { "dependencies": {
"@tanstack/react-query": "^5.20.2",
"minisearch": "^6.3.0", "minisearch": "^6.3.0",
"next": "14.1.0", "next": "14.1.0",
"react": "^18", "react": "^18",

View file

@ -346,22 +346,20 @@ authorName (as a slug): {
website: website url website: website url
} }
*/ */
export interface Authors { export interface Author {
[key: string]: { name: {
name: { first: string
first: string last: string
last: string nickname?: string
nickname?: string
}
affiliation: string[]
image: string
nationality: string[]
formerAffiliations?: string[]
bio?: string
website?: string
} }
affiliation: string[]
image: string
nationality: string[]
formerAffiliations?: string[]
bio?: string
website?: string
} }
export const authors: Authors = { export const authors: { [key: string]: Author } = {
shasan: { shasan: {
name: { name: {
first: 'Saim', first: 'Saim',

View file

@ -1,4 +1,4 @@
import { Document } from './data' import { Document, Author } from './data'
export const loadDocument = (id: string): Promise<Document> => { export const loadDocument = (id: string): Promise<Document> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -62,3 +62,32 @@ export const loadAllDocuments = (): Promise<{ [key: string]: Document }> => {
} }
}) })
} }
export const loadAllAuthors = (): Promise<{ [key: string]: Author }> => {
return new Promise((resolve, reject) => {
if (typeof Worker !== 'undefined') {
const worker = new Worker(
new URL('./workers/documentLoader.worker.ts', import.meta.url),
{ type: 'module' }
)
worker.onmessage = (e: MessageEvent<{ [key: string]: Author }>) => {
resolve(e.data)
worker.terminate()
}
worker.onerror = (error) => {
reject(error)
worker.terminate()
}
worker.postMessage('LOAD')
} else {
reject(
new Error(
'Web Workers are not supported in this environment. Please avoid using a prehistoric browser.'
)
)
}
})
}

View file

@ -0,0 +1,7 @@
import { affiliations } from '../data'
onmessage = (e) => {
if (e.data === 'LOAD') {
self.postMessage(affiliations)
}
}

View file

@ -0,0 +1,7 @@
import { authors } from '../data'
onmessage = (e) => {
if (e.data === 'LOAD') {
self.postMessage(authors)
}
}

View file

@ -0,0 +1,7 @@
import { nationalities } from '../data'
onmessage = (e) => {
if (e.data === 'LOAD') {
self.postMessage(nationalities)
}
}

View file

@ -0,0 +1,7 @@
import { topics } from '../data'
onmessage = (e) => {
if (e.data === 'LOAD') {
self.postMessage(topics)
}
}

View file

@ -1,4 +1,4 @@
import { DocumentType, Document } from '@/app/db/data' import { DocumentType } from '@/app/db/data'
import { Zilla_Slab } from 'next/font/google' import { Zilla_Slab } from 'next/font/google'
import { epoch2datestring } from '@/app/utils/epoch2datestring' import { epoch2datestring } from '@/app/utils/epoch2datestring'
import { import {
@ -10,14 +10,21 @@ import {
} from '@/app/components/DataDisplay' } from '@/app/components/DataDisplay'
import { ItemBadge, Status } from '@/app/components/Badges' import { ItemBadge, Status } from '@/app/components/Badges'
import Link from 'next/link' import Link from 'next/link'
import { useSuspenseQuery } from '@tanstack/react-query'
import { loadDocument } from '@/app/db/loaders'
const zillaSlab = Zilla_Slab({ subsets: ['latin'], weight: ['500', '700'] }) const zillaSlab = Zilla_Slab({ subsets: ['latin'], weight: ['500', '700'] })
export default function DocumentViewer({ export default function DocumentViewer({ slug }: Readonly<{ slug: string }>) {
doc, const { data, error } = useSuspenseQuery({
slug, queryKey: [slug],
}: Readonly<{ doc: Document; slug: string }>) { queryFn: () => {
const { manifest, abstract, file, citation } = doc const data = loadDocument(slug)
return data
},
})
const { manifest, abstract, file, citation } = data
const { const {
title, title,
authors, authors,
@ -31,6 +38,8 @@ export default function DocumentViewer({
status, status,
} = manifest } = manifest
if (error) throw error
return ( return (
<div className='max-w-4xl lg:max-w-6xl mx-auto'> <div className='max-w-4xl lg:max-w-6xl mx-auto'>
<h1 <h1

View file

@ -1,29 +1,13 @@
'use client' 'use client'
import { Zilla_Slab } from 'next/font/google'
import { DocumentType, reviewer, Document, documents } from '@/app/db/data'
import { loadDocument, loadAllDocuments } from '@/app/db/loaders'
import DocumentViewer from './DocumentViewer' import DocumentViewer from './DocumentViewer'
import createResource from '@/app/utils/createResource' import ErrorBoundary from '@/app/utils/ErrorBoundary'
import { Suspense, useEffect, useMemo } from 'react'
export default function Page({ export default function Page({
params, params,
}: Readonly<{ params: { slug: string } }>) { }: Readonly<{ params: { slug: string } }>) {
// const docResource = createResource(loadDocument(params.slug))
// const doc = docResource.read()
useEffect(() => {
const check = async () => {
const doc = await loadDocument(params.slug)
console.log(doc)
}
check()
})
return ( return (
<> <ErrorBoundary>
<div>hi</div> <DocumentViewer slug={params.slug} />
<DocumentViewer doc={documents[params.slug]} slug={params.slug} /> </ErrorBoundary>
</>
) )
} }

View file

@ -8,6 +8,7 @@ import Container from './container/Container'
import MobileMenu from './components/MobileMenu' import MobileMenu from './components/MobileMenu'
import { ToastContainer } from 'react-toastify' import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css' import 'react-toastify/dist/ReactToastify.css'
import Providers from './providers'
/* The default font is Inter. If you want to use Zilla Slab (or any other Google Font, /* The default font is Inter. If you want to use Zilla Slab (or any other Google Font,
which are pre-provided by Next.js in the 'next/font/google' module), you need to which are pre-provided by Next.js in the 'next/font/google' module), you need to
@ -31,80 +32,82 @@ export default function RootLayout({
return ( return (
<html lang='en'> <html lang='en'>
<body className={inter.className}> <body className={inter.className}>
<ToastContainer /> <Providers>
<div className={styles.header}> <ToastContainer />
<div className='max-w-[1200px] flex flex-nowrap mx-auto justify-between items-center'> <div className={styles.header}>
<Link href='/affiliation/1280-eecs'> <div className='max-w-[1200px] flex flex-nowrap mx-auto justify-between items-center'>
<img <Link href='/affiliation/1280-eecs'>
className='h-[100px] mt-4' <img
src='/img/logos/eecs-wordmark.png' className='h-[100px] mt-4'
alt='EECS' src='/img/logos/eecs-wordmark.png'
/> alt='EECS'
</Link> />
<p className={`max-w-[600px] hidden md:inline`}>
We gratefully acknowledge support from our volunteer peer
reviewers, member institutions, and all{' '}
<a
href='https://github.com/couscousdude/eeXiv-2/graphs/contributors'
target='_blank'
>
open-source contributors
</a>
.
</p>
</div>
</div>
<div className={`${styles.banner} w-full h-[100px] mb-[50px]`}>
<div className='max-w-[1200px] flex justify-between mx-auto items-center pt-3 flex-nowrap'>
<h1 className={`${styles.title} ${zillaSlab.className} mx-10`}>
<Link href='/' className='no-link-style'>
eeXiv
</Link> </Link>
</h1> <p className={`max-w-[600px] hidden md:inline`}>
<div className='hidden md:inline'> We gratefully acknowledge support from our volunteer peer
<SearchBar /> reviewers, member institutions, and all{' '}
</div> <a
<div className='md:hidden'> href='https://github.com/couscousdude/eeXiv-2/graphs/contributors'
<MobileMenu /> target='_blank'
>
open-source contributors
</a>
.
</p>
</div> </div>
</div> </div>
</div> <div className={`${styles.banner} w-full h-[100px] mb-[50px]`}>
<Container>{children}</Container> <div className='max-w-[1200px] flex justify-between mx-auto items-center pt-3 flex-nowrap'>
<footer> <h1 className={`${styles.title} ${zillaSlab.className} mx-10`}>
<div className={styles.footerContent}> <Link href='/' className='no-link-style'>
<ul> eeXiv
<li key='about'>
<Link href='/about'>About</Link>
</li>
<li key='help'>
<Link href='/help'>Help</Link>
</li>
<li key='contact'>
<Link href='/contact'>Contact</Link>
</li>
<li key='subscribe'>
<Link href='/subscribe'>Subscribe</Link>
</li>
<li key='copyright'>
<Link href='/legal/copyright'>Copyright</Link>
</li>
<li key='privacy'>
<Link href='/legal/privacy'>Privacy Policy</Link>
</li>
<li key='accessibility'>
<Link href='/help/accessibility'>Accessibility</Link>
</li>
<li key='status'>
<Link href='/status'>eeXiv status</Link>
</li>
<li key='notifications'>
<Link href='/status/notifications'>
Get status notifications
</Link> </Link>
</li> </h1>
</ul> <div className='hidden md:inline'>
<SearchBar />
</div>
<div className='md:hidden'>
<MobileMenu />
</div>
</div>
</div> </div>
</footer> <Container>{children}</Container>
<footer>
<div className={styles.footerContent}>
<ul>
<li key='about'>
<Link href='/about'>About</Link>
</li>
<li key='help'>
<Link href='/help'>Help</Link>
</li>
<li key='contact'>
<Link href='/contact'>Contact</Link>
</li>
<li key='subscribe'>
<Link href='/subscribe'>Subscribe</Link>
</li>
<li key='copyright'>
<Link href='/legal/copyright'>Copyright</Link>
</li>
<li key='privacy'>
<Link href='/legal/privacy'>Privacy Policy</Link>
</li>
<li key='accessibility'>
<Link href='/help/accessibility'>Accessibility</Link>
</li>
<li key='status'>
<Link href='/status'>eeXiv status</Link>
</li>
<li key='notifications'>
<Link href='/status/notifications'>
Get status notifications
</Link>
</li>
</ul>
</div>
</footer>
</Providers>
</body> </body>
</html> </html>
) )

20
src/app/providers.jsx Normal file
View file

@ -0,0 +1,20 @@
'use client'
import { useState } from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
export default function Providers({ children }) {
const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
},
},
})
)
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
)
}

View file

@ -0,0 +1,29 @@
import React from 'react'
import { notFound } from 'next/navigation'
export default class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false, error: null }
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true, error }
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error('Error caught by Error Boundary:', error, errorInfo)
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
if (this.state.error.message === '404') notFound()
return <h1>Something went wrong.</h1>
}
return this.props.children
}
}

View file

@ -1,26 +0,0 @@
export default function wrapPromise(promise: Promise<any>) {
let status = 'pending'
let result: any
let suspender = promise.then(
(r) => {
status = 'success'
result = r
},
(e) => {
status = 'error'
result = e
}
)
return {
read() {
if (status === 'pending') {
throw suspender
} else if (status === 'error') {
throw result
} else if (status === 'success') {
return result
}
},
}
}