dh_demo

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

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


      1 import Title from '@/components/elements/Title'
      2 import Container from '@/components/layout/Container'
      3 import Hero from '@/components/layout/Hero'
      4 import Section from '@/components/layout/Section'
      5 import { Pagination } from '@/components/Pagination'
      6 import WikiBase from '@/components/wiki/WikiBase'
      7 import { withConnection } from '@/lib/model_helpers'
      8 import { getWikiAndPageACLViaPath } from '@/lib/models/wiki_acl'
      9 import { countWikiChanges, getWikiChanges, WikiChangeListItem } from '@/lib/models/wiki_change'
     10 import { getPageQuery } from '@/lib/utils/pagination'
     11 import { getSlugAndPath } from '@/lib/utils/wiki'
     12 import moment from 'moment'
     13 import { GetServerSideProps } from 'next'
     14 import Link from 'next/link'
     15 import { useRouter } from 'next/router'
     16 import { useMemo } from 'react'
     17 
     18 const PAGE_SIZE = 30
     19 
     20 export interface WikiLogsPageProps {
     21   page: number
     22   count: number
     23   changes: WikiChangeListItem[]
     24 }
     25 
     26 export const getServerSideProps: GetServerSideProps<WikiLogsPageProps> = async (context) => {
     27   const [slug, path] = getSlugAndPath(context) ?? []
     28   if (slug == null || path == null) {
     29     console.error('slug or path is null', slug, path)
     30     return { notFound: true }
     31   }
     32 
     33   const [page, offset] = getPageQuery(context.query, PAGE_SIZE)
     34 
     35   const result = await withConnection(async (conn) => {
     36     const aclInfo = await getWikiAndPageACLViaPath(conn, [slug, path])
     37     if (aclInfo == null || aclInfo.pageId == null) {
     38       return null
     39     }
     40 
     41     const count = await countWikiChanges(conn, [aclInfo.pageId])
     42     const changes = await getWikiChanges(conn, [aclInfo.pageId, PAGE_SIZE, offset])
     43 
     44     return { count, changes }
     45   })
     46   if (result == null || result.changes.length === 0) {
     47     return { notFound: true }
     48   }
     49 
     50   return {
     51     props: {
     52       page,
     53       count: result.count,
     54       changes: result.changes
     55     },
     56   }
     57 }
     58 
     59 export default function WikiLogsPage (props: WikiLogsPageProps) {
     60   const router = useRouter()
     61   const [slug, path] = useMemo(() => getSlugAndPath(router), [router])
     62   return (
     63     <>
     64       <WikiBase pageKind={'logs'} title={`편집 기록: ${path}`}>
     65         <Section>
     66           <ul>
     67             {props.changes.map((change, i, changes) => (
     68               <li key={change.id}>
     69                 <Link href={`/wiki/${slug}/${path}?rev=${change.id}`}>
     70                   {moment(change.createdAt).format('YYYY년 MM월 DD일 hh시 mm분')}
     71                 </Link>
     72                 &nbsp;&nbsp;
     73                 <AuthorLink
     74                   authorId={change.authorId}
     75                   authorIp={change.authorIp}
     76                   nickname={change.nickname}
     77                 />
     78                 &nbsp;&nbsp;
     79                 <span>{change.size} bytes</span>
     80                 &nbsp;&nbsp;
     81                 <SizeDiff
     82                   size={change.size}
     83                   prev={i + 1 === changes.length ? 0 : changes[i + 1].size}
     84                 />
     85               </li>
     86             ))}
     87           </ul>
     88 
     89           <Pagination page={props.page} totalCount={props.count} pageSize={PAGE_SIZE}/>
     90         </Section>
     91       </WikiBase>
     92     </>
     93   )
     94 }
     95 
     96 function AuthorLink (props: { authorId?: number; authorIp?: string; nickname?: string }) {
     97   if (props.authorId != null && props.nickname != null) {
     98     return (
     99       <Link href={`/users/${props.authorId}`}>
    100         {props.nickname}
    101       </Link>
    102     )
    103   }
    104 
    105   if (props.authorIp != null) {
    106     return (
    107       <span>{props.authorIp}</span>
    108     )
    109   }
    110 
    111   return (
    112     <span>unknown</span>
    113   )
    114 }
    115 
    116 function SizeDiff (props: { size: number; prev: number }) {
    117   const diff = props.size - props.prev
    118   if (diff > 0) {
    119     return (
    120       <span>(+{diff} bytes)</span>
    121     )
    122   }
    123 
    124   if (diff < 0) {
    125     return (
    126       <span>(-{diff} bytes)</span>
    127     )
    128   }
    129 
    130   return (
    131     <span>(±0 bytes)</span>
    132   )
    133 }