[...path].tsx (3353B)
1 import { useSocket } from '@/components/contexts/SocketContext' 2 import { useToken } from '@/components/contexts/TokenContext' 3 import { SubmitButton } from '@/components/elements/Button' 4 import Fields from '@/components/form/Fields' 5 import Form from '@/components/form/Form' 6 import Section from '@/components/layout/Section' 7 import WikiBase from '@/components/wiki/WikiBase' 8 import WikiEditor from '@/components/wiki/WikiEditor' 9 import { useForm } from '@/lib/hooks/use_form' 10 import { withConnection } from '@/lib/model_helpers' 11 import { getWikiViaSlug, WikiInfo } from '@/lib/models/wiki_info' 12 import { getWikiRawPage, WikiRawPage } from '@/lib/models/wiki_page' 13 import { ACL_ACTION_WRITE, resolveACL } from '@/lib/security/acl' 14 import { authenticationFromCookies } from '@/lib/security/token' 15 import { getSlugAndPath } from '@/lib/utils/wiki' 16 import { GetServerSideProps } from 'next' 17 import { useRouter } from 'next/router' 18 import { useEffect } from 'react' 19 import toast from 'react-hot-toast' 20 21 export interface WikiEditPageProps { 22 wiki: WikiInfo 23 page?: WikiRawPage 24 } 25 26 export const getServerSideProps: GetServerSideProps<WikiEditPageProps> = async (context) => { 27 const [slug, path] = getSlugAndPath(context) 28 if (slug == null || path == null) { 29 return { notFound: true } 30 } 31 32 const token = authenticationFromCookies(context.req.cookies) 33 34 return await withConnection(async (conn) => { 35 const wiki = await getWikiViaSlug(conn, [slug]) 36 if (wiki == null || !resolveACL(token, wiki.acl, ACL_ACTION_WRITE)) { 37 return { notFound: true } 38 } 39 40 const page = await getWikiRawPage(conn, [wiki.id, path]) 41 if (page == null) { 42 return { 43 props: { 44 wiki: wiki, 45 }, 46 } 47 } 48 49 if (!resolveACL(token, page.acl, ACL_ACTION_WRITE)) { 50 return { notFound: true } 51 } 52 53 return { 54 props: { 55 wiki: wiki, 56 page: page, 57 }, 58 } 59 }) 60 } 61 62 interface WikiEditFormFields { 63 content: string 64 } 65 66 export default function WikiEditPage (props: WikiEditPageProps) { 67 const router = useRouter() 68 const socket = useSocket() 69 const token = useToken() 70 71 const [slug, path] = getSlugAndPath(router) 72 73 // 다른 사용자가 문서를 편집했을 때 74 useEffect(() => { 75 return socket.on('pageChange', ({ payload }) => { 76 if (payload !== token?.uid?.toString()) { 77 toast('다른 사용자가 이 문서를 편집했습니다.') 78 } else { 79 toast('문서가 편집되었습니다.') 80 } 81 }) 82 }, []) 83 84 const [fields, updateFields, submit, isLoading, result, error] = useForm<WikiEditFormFields>( 85 { method: 'PUT', url: `/api/wiki/${slug}/${path}` }, 86 { content: props.page?.content ?? '' }, 87 () => { 88 router.push(`/wiki/${slug}/${path}`) 89 .catch(console.error) 90 } 91 ) 92 93 return ( 94 <WikiBase title={( 95 <> 96 <span>편집: {path}</span> 97 {props.page == null && ( 98 <small> (새 문서 만들기)</small> 99 )} 100 </> 101 )} pageKind="edit"> 102 <Section> 103 <WikiEditor 104 value={fields.content} 105 onValueChange={updateFields.bind(null, 'content')} 106 /> 107 108 <Form onSubmit={submit}> 109 <Fields> 110 <SubmitButton color="primary" disabled={isLoading} value="저장"/> 111 </Fields> 112 </Form> 113 </Section> 114 </WikiBase> 115 ) 116 }