dh_demo

DreamHanks demo project
git clone git://git.lair.cx/dh_demo
Log | Files | Refs | README

[...path].tsx (3815B)


      1 import Hero from '@/components/layout/Hero'
      2 import Section from '@/components/layout/Section'
      3 import RevisionAlert from '@/components/wiki/RevisionAlert'
      4 import WikiArticle from '@/components/wiki/WikiArticle'
      5 import WikiBase from '@/components/wiki/WikiBase'
      6 import { getPageCache, hasPageCache, putPageCache, refreshPageCache } from '@/lib/pagecache'
      7 import { parse, render, Token } from '@/lib/markup'
      8 import { withConnection } from '@/lib/model_helpers'
      9 import { getWikiViaSlug } from '@/lib/models/wiki_info'
     10 import { getWikiPage, getWikiPageRevision, WikiPage } from '@/lib/models/wiki_page'
     11 import { getWikiText } from '@/lib/models/wiki_text'
     12 import { ACL_ACTION_MANAGE, ACL_ACTION_READ, resolveACL } from '@/lib/security/acl'
     13 import { authenticationFromCookies } from '@/lib/security/token'
     14 import { getSlugAndPath, getStringFromWikiText } from '@/lib/utils/wiki'
     15 import { GetServerSideProps } from 'next'
     16 import Link from 'next/link'
     17 import { useRouter } from 'next/router'
     18 
     19 export type WikiViewPageProps = {
     20   page?: WikiPage
     21   tokens?: Token[]
     22   enableManage?: boolean
     23 }
     24 
     25 export const getServerSideProps: GetServerSideProps<WikiViewPageProps> = async (context) => {
     26   const { rev } = context.query
     27   const [slug, path] = getSlugAndPath(context)
     28   if (slug == null || path == null) {
     29     return { notFound: true }
     30   }
     31 
     32   const revId = rev == null ? null : parseInt(rev as string)
     33   if (revId != null && isNaN(revId)) {
     34     return { notFound: true }
     35   }
     36 
     37   const token = await authenticationFromCookies(context.req.cookies)
     38 
     39   return await withConnection(async (conn) => {
     40     const wiki = await getWikiViaSlug(conn, [slug])
     41     if (wiki == null || !resolveACL(token, wiki.acl, ACL_ACTION_READ)) {
     42       return { notFound: true }
     43     }
     44 
     45     // 매니징 권한 체크 (메뉴 표시용)
     46     const enableManage = resolveACL(token, wiki.acl, ACL_ACTION_MANAGE)
     47 
     48     const page = revId == null
     49       ? await getWikiPage(conn, [wiki.id, path])
     50       : await getWikiPageRevision(conn, [wiki.id, path, revId])
     51     if (page == null) {
     52       return { props: {} }
     53     }
     54 
     55     if (await hasPageCache(page.textId)) {
     56       const pageTokens = await getPageCache(page.textId)
     57 
     58       if (pageTokens != null) {
     59         await refreshPageCache(page.textId)
     60         return {
     61           props: {
     62             page: page,
     63             tokens: pageTokens,
     64             enableManage: enableManage,
     65           },
     66         }
     67       }
     68     }
     69 
     70     // Cache miss
     71     const wikiText = await getWikiText(conn, [page.textId])
     72     if (wikiText == null) {
     73       return { props: {} }
     74     }
     75 
     76     const source = await getStringFromWikiText(wikiText)
     77     const pageTokens = parse(source)
     78 
     79     await putPageCache(page.textId, pageTokens)
     80     return {
     81       props: {
     82         page: page,
     83         tokens: pageTokens,
     84         enableManage: enableManage,
     85       },
     86     }
     87   })
     88 }
     89 
     90 export default function WikiViewPage (props: WikiViewPageProps) {
     91   const router = useRouter()
     92   const [slug, path] = getSlugAndPath(router)
     93   const { rev } = router.query
     94 
     95   function linkRenderer (path: string, text: string) {
     96     return <Link href={`/wiki/${slug}/${path}`}>{text}</Link>
     97   }
     98 
     99   if (props.page == null || props.tokens == null) {
    100     return (
    101       <Hero>
    102         <p>문서를 찾지 못했습니다.</p>
    103         <p><Link href={`/edit/${slug}/${path}`}>새 문서 만들기</Link></p>
    104       </Hero>
    105     )
    106   }
    107 
    108   return (
    109     <WikiBase pageKind={'wiki'} title={path ?? ''} enableManage={props.enableManage}>
    110       <Section>
    111         <WikiArticle>
    112           {rev != null && (
    113             <RevisionAlert
    114               page={props.page}
    115               recentURL={`/wiki/${slug}/${path}`}
    116             />
    117           )}
    118 
    119           {render(props.tokens, {
    120             linkRenderer: linkRenderer,
    121           })}
    122         </WikiArticle>
    123       </Section>
    124     </WikiBase>
    125   )
    126 }