feat: minor fixes

This commit is contained in:
Travis Fischer
2021-01-16 14:49:45 -05:00
parent b57d7651ba
commit 768d0d5378
12 changed files with 161 additions and 98 deletions

43
components/Footer.tsx Normal file
View File

@@ -0,0 +1,43 @@
import * as React from 'react'
import { FaTwitter, FaGithub, FaLinkedin } from 'react-icons/fa'
import styles from './styles.module.css'
export const Footer: React.FC<{}> = () => {
return (
<footer className={styles.footer}>
<div className={styles.copyright}>Copyright 2021 Travis Fischer</div>
<div className={styles.social}>
<a
className={styles.twitter}
href='https://twitter.com/transitive_bs'
title='Twitter @transitive_bs'
target='_blank'
rel='noopener noreferrer'
>
<FaTwitter />
</a>
<a
className={styles.github}
href='https://github.com/transitive-bullshit'
title='GitHub @transitive-bullshit'
target='_blank'
rel='noopener noreferrer'
>
<FaGithub />
</a>
<a
className={styles.linkedin}
href='https://www.linkedin.com/in/fisch2'
title='LinkedIn Travis Fischer'
target='_blank'
rel='noopener noreferrer'
>
<FaLinkedin />
</a>
</div>
</footer>
)
}

View File

@@ -22,6 +22,7 @@ import { CustomHtml } from './CustomHtml'
import { Loading } from './Loading'
import { Page404 } from './Page404'
import { PageHead } from './PageHead'
import { Footer } from './Footer'
import styles from './styles.module.css'
@@ -138,6 +139,7 @@ export const NotionPage: React.FC<types.PageProps> = ({
mapPageUrl={siteMapPageUrl}
mapImageUrl={mapNotionImageUrl}
searchNotion={searchNotion}
footer={<Footer />}
/>
<CustomHtml site={site} />

View File

@@ -42,104 +42,47 @@
width: 640px;
}
.notion {
padding-bottom: calc(max(10vh, 120px));
}
.demoFooter {
position: fixed;
z-index: 800;
bottom: 1em;
left: 10vw;
right: 10vw;
border-radius: 4px;
background: #eb625a;
padding: 16px 24px;
.footer {
width: 100%;
max-width: 1100px;
margin: 0 auto;
padding: 8px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
color: #fff;
}
.demoLhs a,
.demoLhs a:visited,
.demoLhs a:hover,
.demoLhs a:active {
text-decoration: none;
color: #fff;
.copyright {
font-size: 80%;
padding: 0.5em;
}
.demoLhs {
display: flex;
flex-direction: row;
align-items: center;
.social a {
font-size: 2em;
display: inline-block;
padding: 0.5em;
margin-right: 1vw;
transition: color 250ms ease-out;
}
.demoTitle {
font-size: 1.2em;
display: flex;
flex-direction: row;
align-items: center;
padding-right: 0.5em;
margin-right: 0.5em;
border-right: 1px solid #fff;
white-space: nowrap;
.social a:last-of-type {
margin-right: 0;
}
.demoTitle img {
height: 1.5em;
margin-right: 0.5em;
.social a:hover {
transition: color 50ms ease-out;
}
.demoDesc {
font-size: 0.9em;
.twitter:hover {
color: #2795e9;
}
.demoCta {
display: block;
margin-left: 0.5em;
font-size: 0.9em;
text-decoration: none;
color: #fff;
border-radius: 2px;
padding: 8px 12px;
background: transparent;
border: 1px solid #fff;
transition: all 300ms ease;
font-weight: 500;
white-space: nowrap;
transform: scale(1);
.github:hover {
color: #c9510c;
}
.demoCta:hover {
background: #fff;
color: #eb625a;
transition: all 200ms ease;
transform: scale(1.05);
}
.demoCta:active {
transition: all 100ms ease;
transform: scale(1.03);
}
@media only screen and (max-width: 740px) {
.demoFooter {
left: 1em;
right: 1em;
}
.demoTitle {
border: 0 none;
}
.demoDesc {
display: none;
}
.linkedin:hover {
color: #0077b5;
}

View File

@@ -17,7 +17,7 @@ export const fathomConfig = fathomId
}
: undefined
// TODO: address duplication between server-side env and client-side config
// TODO: fix duplication between server-side env and client-side config
export const apiBaseUrl = `/api`
export const api = {
createPreviewImage: `${apiBaseUrl}/create-preview-image`,

View File

@@ -1,6 +1,7 @@
import pMemoize from 'p-memoize'
import { getAllPagesInSpace, getCanonicalPageId } from 'notion-utils'
import * as types from './types'
import notion from './notion'
export const getAllPages = pMemoize(getAllPagesImpl, { maxAge: 60000 * 5 })
@@ -8,16 +9,44 @@ export const getAllPages = pMemoize(getAllPagesImpl, { maxAge: 60000 * 5 })
export async function getAllPagesImpl(
rootNotionPageId: string,
rootNotionSpaceId: string
): Promise<string[]> {
const pages = await getAllPagesInSpace(
): Promise<Partial<types.SiteMap>> {
const pageMap = await getAllPagesInSpace(
rootNotionPageId,
rootNotionSpaceId,
notion.getPage.bind(notion)
)
const canonicalPageIds = Object.keys(pages)
.map((pageId) => getCanonicalPageId(pageId, pages[pageId]))
.filter(Boolean)
const canonicalPageMap = Object.keys(pageMap).reduce(
(map, pageId: string) => {
const recordMap = pageMap[pageId]
const canonicalPageId = getCanonicalPageId(pageId, recordMap, {
uuid: false
})
return canonicalPageIds
if (map[canonicalPageId]) {
console.error(
'duplicate canonical page id',
canonicalPageId,
pageId,
map[canonicalPageId].pageId
)
return map
} else {
return {
...map,
[canonicalPageId]: {
pageId,
recordMap
}
}
}
},
{}
)
return {
pageMap,
canonicalPageMap
}
}

View File

@@ -11,14 +11,17 @@ export async function getSiteMaps(): Promise<types.SiteMap[]> {
sites,
async (site, index) => {
try {
console.log('getSiteMap', index, site)
console.log(
'getSiteMap',
`${index + 1}/${sites.length}`,
`(${(((index + 1) / sites.length) * 100) | 0}%)`,
site
)
return {
site,
pageIds: await getAllPages(
site.rootNotionPageId,
site.rootNotionSpaceId
)
}
...(await getAllPages(site.rootNotionPageId, site.rootNotionSpaceId))
} as types.SiteMap
} catch (err) {
console.warn('site build error', index, site, err)
}

View File

@@ -9,7 +9,10 @@ export const mapPageUrl = (
if (uuidToId(pageId) === site.rootNotionPageId) {
return createUrl('/', searchParams)
} else {
return createUrl(`/${getCanonicalPageId(pageId, recordMap)}`, searchParams)
return createUrl(
`/${getCanonicalPageId(pageId, recordMap, { uuid: false })}`,
searchParams
)
}
}
@@ -22,7 +25,9 @@ export const getCanonicalPageUrl = (
if (uuidToId(pageId) === site.rootNotionPageId) {
return `https://${site.domain}`
} else {
return `https://${site.domain}/${getCanonicalPageId(pageUuid, recordMap)}`
return `https://${site.domain}/${getCanonicalPageId(pageUuid, recordMap, {
uuid: false
})}`
}
}

View File

@@ -2,6 +2,7 @@ import * as acl from './acl'
import * as types from './types'
import { parsePageId } from 'notion-utils'
import { getPage } from './notion'
import { getSiteMaps } from './get-site-maps'
import { getSiteForDomain } from './get-site-for-domain'
export async function resolveNotionPage(domain: string, rawPageId?: string) {
@@ -12,6 +13,24 @@ export async function resolveNotionPage(domain: string, rawPageId?: string) {
if (rawPageId && rawPageId !== 'index') {
pageId = parsePageId(rawPageId)
// handle mapping user-friendly canonical page paths to Notion page IDs
// e.g., /developer-x-entrepreneur versus /71201624b204481f862630ea25ce62fe
if (!pageId) {
const siteMaps = await getSiteMaps()
const siteMap = siteMaps[0]
console.log(siteMap)
pageId = siteMap.canonicalPageMap[pageId]?.pageId
if (!pageId) {
return {
error: {
message: `Invalid notion page ID "${rawPageId}"`,
statusCode: 404
}
}
}
}
if (!pageId) {
return {
error: {

View File

@@ -1,4 +1,4 @@
import { Block, ExtendedRecordMap } from 'notion-types'
import { ExtendedRecordMap, PageMap } from 'notion-types'
export * from 'notion-types'
@@ -47,7 +47,15 @@ export interface Site extends Model {
export interface SiteMap {
site: Site
pageIds: string[]
pageMap: PageMap
canonicalPageMap: CanonicalPageMap
}
export interface CanonicalPageMap {
[canonicalPagePath: string]: {
pageId: string
recordMap: ExtendedRecordMap | null
}
}
export interface PreviewImage {

View File

@@ -41,6 +41,7 @@
"react": "17.0.1",
"react-body-classname": "^1.3.1",
"react-dom": "17.0.1",
"react-icons": "^4.1.0",
"react-notion-x": "^3.0.1",
"react-use": "^15.3.3"
},

View File

@@ -17,3 +17,8 @@
margin-top: 1em;
margin-bottom: 1em;
}
.notion-header {
max-width: 1100px;
margin: 0 auto;
}

View File

@@ -5071,6 +5071,11 @@ react-dom@17.0.1:
object-assign "^4.1.1"
scheduler "^0.20.1"
react-icons@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.1.0.tgz#9ca9bcbf2e3aee8e86e378bb9d465842947bbfc3"
integrity sha512-FCXBg1JbbR0vWALXIxmFAfozHdVIJmmwCD81Jk0EKOt7Ax4AdBNcaRkWhR0NaKy9ugJgoY3fFvo0PHpte55pXg==
react-image@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-image/-/react-image-4.0.3.tgz#6fa722877660b67295298a914bff1ed87ad2cf83"