Skip to content

Commit

Permalink
feat: fetch data index, setup routing
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-aksamentov committed Aug 31, 2022
1 parent a2ed5c2 commit 299c42f
Show file tree
Hide file tree
Showing 19 changed files with 402 additions and 188 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ PLAUSIBLE_IO_DOMAIN=master.pangenome.org
FULL_DOMAIN=autodetect
NEXT_TELEMETRY_DISABLED=1

WEB_PORT_PROD=8080

DEV_ENABLE_TYPE_CHECKS=1
DEV_ENABLE_ESLINT=1
DEV_ENABLE_STYLELINT=1
Expand Down
2 changes: 2 additions & 0 deletions .env.vercel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ PLAUSIBLE_IO_DOMAIN=
FULL_DOMAIN=autodetect
NEXT_TELEMETRY_DISABLED=1

WEB_PORT_PROD=8080

DEV_ENABLE_TYPE_CHECKS=1
DEV_ENABLE_ESLINT=1
DEV_ENABLE_STYLELINT=1
Expand Down
3 changes: 1 addition & 2 deletions infra/web/lambda-at-edge/ViewerResponse.lambda.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ function generatePermissionsPolicyHeader(permissionsPolicyObject) {
.join(', ')
}
const NEW_HEADERS = {
'Content-Security-Policy':
`default-src 'self' *.pangenome.org; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.pangenome.org plausible.io maxcdn.bootstrapcdn.com; style-src 'self' 'unsafe-inline' maxcdn.bootstrapcdn.com fonts.googleapis.com; font-src 'self' maxcdn.bootstrapcdn.com fonts.googleapis.com fonts.gstatic.com;img-src 'self' data:; connect-src *; frame-src 'self' player.vimeo.com`,
'Content-Security-Policy': `default-src 'self' *.pangenome.org; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.pangenome.org plausible.io maxcdn.bootstrapcdn.com; style-src 'self' 'unsafe-inline' maxcdn.bootstrapcdn.com fonts.googleapis.com; font-src 'self' maxcdn.bootstrapcdn.com fonts.googleapis.com fonts.gstatic.com;img-src 'self' data:; connect-src *; frame-src 'self' player.vimeo.com`,
'Referrer-Policy': 'no-referrer',
'Strict-Transport-Security': 'max-age=15768000; includeSubDomains; preload',
'X-Content-Type-Options': 'nosniff',
Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"changelog": "yarn conventional-changelog -p angular -i CHANGELOG.md -s -r 1"
},
"dependencies": {
"@tanstack/react-query": "4.2.3",
"@tanstack/react-query-devtools": "4.2.3",
"animate.css": "4.1.1",
"auspice": "2.37.3",
"autoprefixer": "10.4.5",
Expand Down Expand Up @@ -157,6 +159,7 @@
"@testing-library/user-event": "14.1.1",
"@types/classnames": "2.3.0",
"@types/compare-versions": "3.3.0",
"@types/compression": "1.7.2",
"@types/compression-webpack-plugin": "9.0.0",
"@types/connect-history-api-fallback": "1.3.5",
"@types/copy-webpack-plugin": "6.4.3",
Expand All @@ -176,6 +179,7 @@
"@types/lodash-webpack-plugin": "0.11.6",
"@types/luxon": "2.3.1",
"@types/mdx-js__react": "1.5.5",
"@types/morgan": "1.9.3",
"@types/papaparse": "5.3.2",
"@types/react": "18.0.8",
"@types/react-dom": "18.0.2",
Expand Down Expand Up @@ -207,6 +211,7 @@
"allow-methods": "3.1.0",
"babel-plugin-parameter-decorator": "1.0.16",
"babel-plugin-transform-typescript-metadata": "0.3.2",
"compression": "1.7.4",
"compression-webpack-plugin": "9.2.0",
"connect-history-api-fallback": "1.6.0",
"conventional-changelog-cli": "2.2.2",
Expand Down Expand Up @@ -274,6 +279,7 @@
"json-loader": "0.5.7",
"lodash-webpack-plugin": "0.11.6",
"map.prototype.tojson": "0.1.3",
"morgan": "1.10.0",
"next-transpile-modules": "9.0.0",
"nodemon": "2.0.15",
"npm-run-all": "4.1.5",
Expand All @@ -285,7 +291,6 @@
"prettier": "2.6.2",
"raw-loader": "4.0.2",
"react-dropzone": "12.1.0",
"react-query": "3.38.0",
"remark-autolink-headings": "6.0.1",
"remark-breaks": "2.0.1",
"remark-images": "2.0.0",
Expand Down Expand Up @@ -333,6 +338,8 @@
"@babel/plugin-proposal-decorators": "7.17.9",
"@babel/preset-env": "7.16.11",
"@babel/preset-typescript": "7.16.7",
"@tanstack/react-query": "4.2.3",
"@tanstack/react-query-devtools": "4.2.3",
"@types/react": "18.0.8",
"@types/react-dom": "18.0.2",
"@typescript-eslint/eslint-plugin": "5.21.0",
Expand Down
50 changes: 0 additions & 50 deletions scripts/server.js

This file was deleted.

34 changes: 33 additions & 1 deletion src/components/Main/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
import React from 'react'
import React, { useMemo } from 'react'
import { Col, Row } from 'reactstrap'

import { Layout } from 'src/components/Layout/Layout'
import { Link } from 'src/components/Link/Link'
import MainPageContent from 'src/components/Main/MainPage.mdx'
import { useDataIndexQuery } from 'src/hooks/useDataIndexQuery'

export function MainPage() {
const indexJson = useDataIndexQuery()

const speciesLinks = useMemo(() => {
return indexJson.datasets.map(({ pathogenName }) => (
<li key={pathogenName}>
<Link href={`/species/${pathogenName}`}>{`/species/${pathogenName}`}</Link>
</li>
))
}, [indexJson.datasets])

return (
<Layout>
<MainPageContent />

<Row noGutters>
<Col>
<ul>
<li>
<Link href={'/doesnotexist'}>{'/doesnotexist'}</Link>
</li>
<li>
<Link href={'/species/doesnotexist'}>{'/species/doesnotexist'}</Link>
</li>
</ul>
</Col>
</Row>

<Row noGutters>
<Col>
<ul>{speciesLinks}</ul>
</Col>
</Row>
</Layout>
)
}
33 changes: 0 additions & 33 deletions src/helpers/useAxiosQuery.ts

This file was deleted.

54 changes: 54 additions & 0 deletions src/hooks/useAxiosQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { QueryKey, UseQueryOptions } from '@tanstack/react-query'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'

import { axiosFetch } from 'src/io/axiosFetch'

export type QueryOptions<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> = Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData'> & {
initialData?: () => undefined
}

export interface UseAxiosQueryOptions<TData = unknown> extends QueryOptions<TData, Error, TData, string[]> {
delay?: number
}

export function useAxiosQuery<TData = unknown>(url: string, options?: UseAxiosQueryOptions<TData>): TData {
const newOptions = useMemo(() => {
let newOptions: UseAxiosQueryOptions<TData> = {
staleTime: Number.POSITIVE_INFINITY,
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: true,
refetchInterval: Number.POSITIVE_INFINITY,
}
if (options) {
newOptions = { ...newOptions, ...options }
}
return newOptions
}, [options])

const res = useQuery<TData, Error, TData, string[]>(
[url],
async () => {
if (options?.delay) {
await new Promise((resolve) => {
setInterval(resolve, options.delay)
})
}
return axiosFetch(url)
},
newOptions,
)

return useMemo(() => {
if (!res.data) {
throw new Error('Fetch failed: index.json')
}
return res.data
}, [res.data])
}
13 changes: 13 additions & 0 deletions src/hooks/useDataIndexQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useAxiosQuery, UseAxiosQueryOptions } from 'src/hooks/useAxiosQuery'

export interface SpeciesDesc {
pathogenName: string
}

export interface DataIndex {
datasets: SpeciesDesc[]
}

export function useDataIndexQuery(options?: UseAxiosQueryOptions<DataIndex>): DataIndex {
return useAxiosQuery<DataIndex>('https://data.master.pangenome.org/index.json', options)
}
6 changes: 4 additions & 2 deletions src/hooks/useReloadPage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useCallback } from 'react'

export function useReloadPage(url?: string | URL) {
return () => {
return useCallback(() => {
window.history.replaceState(null, '', url)
window.location.reload()
// trigger React suspense forever, to display loading spinner until the page is refreshed
throw new Promise(() => {}) // eslint-disable-line @typescript-eslint/no-throw-literal
}
}, [url])
}
10 changes: 10 additions & 0 deletions src/pages/404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import { useRouter } from 'next/router'
import ErrorPage from './_error'

export default function NotFoundPage() {
const { asPath } = useRouter()
const error: Error & { statusCode?: number } = new Error(`Page not found: ${asPath}`)
error.statusCode = 404
return <ErrorPage statusCode={error.statusCode} title={error.message} error={error} showDetails={false} />
}
8 changes: 8 additions & 0 deletions src/pages/500.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'
import ErrorPage from './_error'

export default function InternalServerErrorPage() {
const error: Error & { statusCode?: number } = new Error('Internal server error')
error.statusCode = 500
return <ErrorPage statusCode={error.statusCode} title={error.message} error={error} showDetails={false} />
}
Loading

0 comments on commit 299c42f

Please sign in to comment.