| @@ -65,30 +65,30 @@ export default () => { | |||
| switch (status) | |||
| { | |||
| case 503: | |||
| return <ServiceUnavailable /> | |||
| return <ServiceUnavailable/> | |||
| } | |||
| return ( | |||
| <BrowserRouter> | |||
| <div className="flex flex-col h-screen w-screen"> | |||
| <TopNav user={user} /> | |||
| <TopNav user={user}/> | |||
| <Routes> | |||
| <Route path="/" element={<Navigate to="/posts" replace />} /> | |||
| <Route path="/posts" element={<PostListPage />} /> | |||
| <Route path="/posts/new" element={<PostNewPage user={user} />} /> | |||
| <Route path="/posts/:id" element={<PostDetailPage user={user} />} /> | |||
| <Route path="/tags/nico" element={<NicoTagListPage user={user} />} /> | |||
| <Route path="/wiki" element={<WikiSearchPage />} /> | |||
| <Route path="/wiki/:title" element={<WikiDetailPage />} /> | |||
| <Route path="/wiki/new" element={<WikiNewPage user={user} />} /> | |||
| <Route path="/wiki/:id/edit" element={<WikiEditPage user={user} />} /> | |||
| <Route path="/wiki/:id/diff" element={<WikiDiffPage />} /> | |||
| <Route path="/wiki/changes" element={<WikiHistoryPage />} /> | |||
| <Route path="/users/settings" element={<SettingPage user={user} setUser={setUser} />} /> | |||
| <Route path="/settings" element={<Navigate to="/users/settings" replace />} /> | |||
| <Route path="*" element={<NotFound />} /> | |||
| <Route path="/" element={<Navigate to="/posts" replace/>}/> | |||
| <Route path="/posts" element={<PostListPage/>}/> | |||
| <Route path="/posts/new" element={<PostNewPage user={user}/>}/> | |||
| <Route path="/posts/:id" element={<PostDetailPage user={user}/>}/> | |||
| <Route path="/tags/nico" element={<NicoTagListPage user={user}/>}/> | |||
| <Route path="/wiki" element={<WikiSearchPage/>}/> | |||
| <Route path="/wiki/:title" element={<WikiDetailPage/>}/> | |||
| <Route path="/wiki/new" element={<WikiNewPage user={user}/>}/> | |||
| <Route path="/wiki/:id/edit" element={<WikiEditPage user={user}/>}/> | |||
| <Route path="/wiki/:id/diff" element={<WikiDiffPage/>}/> | |||
| <Route path="/wiki/changes" element={<WikiHistoryPage/>}/> | |||
| <Route path="/users/settings" element={<SettingPage user={user} setUser={setUser}/>}/> | |||
| <Route path="/settings" element={<Navigate to="/users/settings" replace/>}/> | |||
| <Route path="*" element={<NotFound/>}/> | |||
| </Routes> | |||
| </div> | |||
| <Toaster /> | |||
| <Toaster/> | |||
| </BrowserRouter>) | |||
| } | |||
| @@ -39,7 +39,7 @@ export default ({ status }: Props) => { | |||
| return ( | |||
| <MainArea> | |||
| <Helmet> | |||
| <meta name="robots" content="noindex" /> | |||
| <meta name="robots" content="noindex"/> | |||
| <title>{title} | {SITE_TITLE}</title> | |||
| </Helmet> | |||
| <div className="text-6xl font-bold text-transparent | |||
| @@ -50,7 +50,7 @@ export default ({ status }: Props) => { | |||
| <p>{status}</p> | |||
| <div className="flex flex-row space-x-1 sm:space-x-2 md:space-x-4"> | |||
| <p style={{ writingMode: 'vertical-rl' }}>{leftMsg}</p> | |||
| <img className="max-w-[70vw]" src={errorImg} alt="逃げたギター" /> | |||
| <img className="max-w-[70vw]" src={errorImg} alt="逃げたギター"/> | |||
| <p style={{ writingMode: 'vertical-rl' }}>{rightMsg}</p> | |||
| </div> | |||
| <p className="mr-[-.5em]">{message}</p> | |||
| @@ -2,5 +2,5 @@ export default () => ( | |||
| <> | |||
| <span className="hidden md:inline flex items-center px-2">|</span> | |||
| <hr className="block md:hidden w-full opacity-25 | |||
| border-t border-black dark:border-white" /> | |||
| border-t border-black dark:border-white"/> | |||
| </>) | |||
| @@ -107,5 +107,5 @@ export default (props: Props) => { | |||
| height={height} | |||
| style={margedStyle} | |||
| allowFullScreen | |||
| allow="autoplay" />) | |||
| allow="autoplay"/>) | |||
| } | |||
| @@ -39,14 +39,14 @@ export default ({ post, onSave }: Props) => { | |||
| <input type="text" | |||
| className="w-full border rounded p-2" | |||
| value={title} | |||
| onChange={e => setTitle (e.target.value)} /> | |||
| onChange={e => setTitle (e.target.value)}/> | |||
| </div> | |||
| {/* タグ */} | |||
| <div> | |||
| <label className="block font-semibold">タグ</label> | |||
| <TextArea value={tags} | |||
| onChange={ev => setTags (ev.target.value)} /> | |||
| onChange={ev => setTags (ev.target.value)}/> | |||
| </div> | |||
| {/* 送信 */} | |||
| @@ -46,14 +46,14 @@ export default ({ post }: Props) => { | |||
| return ( | |||
| <SidebarComponent> | |||
| <TagSearch /> | |||
| <TagSearch/> | |||
| {CATEGORIES.map ((cat: Category) => cat in tags && ( | |||
| <div className="my-3" key={cat}> | |||
| <SubsectionTitle>{categoryNames[cat]}</SubsectionTitle> | |||
| <ul> | |||
| {tags[cat].map ((tag, i) => ( | |||
| <li key={i} className="mb-1"> | |||
| <TagLink tag={tag} /> | |||
| <TagLink tag={tag}/> | |||
| </li>))} | |||
| </ul> | |||
| </div>))} | |||
| @@ -93,10 +93,10 @@ const TagSearch: React.FC = () => { | |||
| onFocus={() => setSuggestionsVsbl (true)} | |||
| onBlur={() => setSuggestionsVsbl (false)} | |||
| onKeyDown={handleKeyDown} | |||
| className="w-full px-3 py-2 border rounded dark:border-gray-600 dark:bg-gray-800 dark:text-white" /> | |||
| className="w-full px-3 py-2 border rounded dark:border-gray-600 dark:bg-gray-800 dark:text-white"/> | |||
| <TagSearchBox suggestions={suggestionsVsbl && suggestions.length ? suggestions : [] as Tag[]} | |||
| activeIndex={activeIndex} | |||
| onSelect={handleTagSelect} /> | |||
| onSelect={handleTagSelect}/> | |||
| </div>) | |||
| } | |||
| @@ -58,14 +58,14 @@ export default ({ posts }: Props) => { | |||
| return ( | |||
| <SidebarComponent> | |||
| <TagSearch /> | |||
| <TagSearch/> | |||
| <div className={cn (!(tagsVsbl) && 'hidden', 'md:block mt-4')}> | |||
| <SectionTitle>タグ</SectionTitle> | |||
| <ul> | |||
| {CATEGORIES.flatMap (cat => cat in tags ? ( | |||
| tags[cat].map (tag => ( | |||
| <li key={tag.id} className="mb-1"> | |||
| <TagLink tag={tag} /> | |||
| <TagLink tag={tag}/> | |||
| </li>))) : [])} | |||
| </ul> | |||
| <SectionTitle>関聯</SectionTitle> | |||
| @@ -41,7 +41,7 @@ export default ({ user }: Props) => { | |||
| { name: '新規', to: '/wiki/new' }, | |||
| { name: '全体履歴', to: '/wiki/changes' }, | |||
| { name: 'ヘルプ', to: '/wiki/ヘルプ:Wiki' }, | |||
| { component: <Separator />, visible: wikiPageFlg }, | |||
| { component: <Separator/>, visible: wikiPageFlg }, | |||
| { name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`, | |||
| visible: wikiPageFlg }, | |||
| { name: '履歴', to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg }, | |||
| @@ -108,7 +108,7 @@ export default ({ user }: Props) => { | |||
| ))} | |||
| </div> | |||
| <TopNavUser user={user} /> | |||
| <TopNavUser user={user}/> | |||
| <a href="#" | |||
| className="md:hidden ml-auto pr-4 | |||
| @@ -136,7 +136,7 @@ export default ({ user }: Props) => { | |||
| <div className={cn (menuOpen ? 'flex flex-col md:hidden' : 'hidden', | |||
| 'bg-yellow-200 dark:bg-red-975 items-start')}> | |||
| <Separator /> | |||
| <Separator/> | |||
| {menu.map ((item, i) => ( | |||
| <Fragment key={i}> | |||
| <Link to={i === openItemIdx ? item.to : '#'} | |||
| @@ -163,8 +163,8 @@ export default ({ user }: Props) => { | |||
| {subItem.name} | |||
| </Link>)))} | |||
| </Fragment>))} | |||
| <TopNavUser user={user} sp /> | |||
| <Separator /> | |||
| <TopNavUser user={user} sp/> | |||
| <Separator/> | |||
| </div> | |||
| </>) | |||
| } | |||
| @@ -21,7 +21,7 @@ export default ({ user, sp }: Props) => { | |||
| return ( | |||
| <> | |||
| {sp && <Separator />} | |||
| {sp && <Separator/>} | |||
| <Link to="/users/settings" | |||
| className={className}> | |||
| {user.name || '名もなきニジラー'} | |||
| @@ -21,7 +21,7 @@ export default ({ children, checkBox }: Props) => { | |||
| <label className="flex items-center block gap-1"> | |||
| <input type="checkbox" | |||
| checked={checkBox.checked} | |||
| onChange={checkBox.onChange} /> | |||
| onChange={checkBox.onChange}/> | |||
| {checkBox.label} | |||
| </label> | |||
| </div>) | |||
| @@ -7,4 +7,4 @@ type Props = { value?: string | |||
| export default ({ value, onChange }: Props) => ( | |||
| <textarea className="rounded border w-full p-2 h-32" | |||
| value={value} | |||
| onChange={onChange} />) | |||
| onChange={onChange}/>) | |||
| @@ -51,7 +51,7 @@ export default ({ visible, onVisibleChange, setUser }: Props) => { | |||
| <div className="flex gap-2"> | |||
| <Input placeholder="引継ぎコードを入力" | |||
| value={inputCode} | |||
| onChange={ev => setInputCode (ev.target.value)} /> | |||
| onChange={ev => setInputCode (ev.target.value)}/> | |||
| <Button onClick={handleTransfer}>引継ぐ</Button> | |||
| </div> | |||
| </DialogContent> | |||
| @@ -8,5 +8,5 @@ const helmetContext = { } | |||
| createRoot (document.getElementById ('root')!).render ( | |||
| <HelmetProvider context={helmetContext}> | |||
| <App /> | |||
| <App/> | |||
| </HelmetProvider>) | |||
| @@ -1,4 +1,4 @@ | |||
| import ErrorScreen from '@/components/ErrorScreen' | |||
| export default () => <ErrorScreen status={403} /> | |||
| export default () => <ErrorScreen status={403}/> | |||
| @@ -1,4 +1,4 @@ | |||
| import ErrorScreen from '@/components/ErrorScreen' | |||
| export default () => <ErrorScreen status={404} /> | |||
| export default () => <ErrorScreen status={404}/> | |||
| @@ -1,4 +1,4 @@ | |||
| import ErrorScreen from '@/components/ErrorScreen' | |||
| export default () => <ErrorScreen status={503} /> | |||
| export default () => <ErrorScreen status={503}/> | |||
| @@ -72,9 +72,9 @@ export default ({ user }: Props) => { | |||
| switch (status) | |||
| { | |||
| case 404: | |||
| return <NotFound /> | |||
| return <NotFound/> | |||
| case 503: | |||
| return <ServiceUnavailable /> | |||
| return <ServiceUnavailable/> | |||
| } | |||
| const url = post ? new URL (post.url) : null | |||
| @@ -89,11 +89,11 @@ export default ({ user }: Props) => { | |||
| <div className="md:flex md:flex-1"> | |||
| <Helmet> | |||
| {(post?.thumbnail || post?.thumbnailBase) && ( | |||
| <meta name="thumbnail" content={post.thumbnail || post.thumbnailBase} />)} | |||
| <meta name="thumbnail" content={post.thumbnail || post.thumbnailBase}/>)} | |||
| {post && <title>{`${ post.title || post.url } | ${ SITE_TITLE }`}</title>} | |||
| </Helmet> | |||
| <div className="hidden md:block"> | |||
| <TagDetailSidebar post={post} /> | |||
| <TagDetailSidebar post={post}/> | |||
| </div> | |||
| <MainArea> | |||
| {post | |||
| @@ -103,8 +103,8 @@ export default ({ user }: Props) => { | |||
| ? ( | |||
| <NicoViewer id={videoId} | |||
| width={640} | |||
| height={360} />) | |||
| : <img src={post.thumbnail} alt={post.url} className="mb-4 w-full" />} | |||
| height={360}/>) | |||
| : <img src={post.thumbnail} alt={post.url} className="mb-4 w-full"/>} | |||
| <Button onClick={changeViewedFlg} | |||
| className={cn ('text-white', viewedClass)}> | |||
| {post.viewed ? '閲覧済' : '未閲覧'} | |||
| @@ -121,14 +121,14 @@ export default ({ user }: Props) => { | |||
| onSave={newPost => { | |||
| setPost (newPost) | |||
| toast ({ description: '更新しました.' }) | |||
| }} /> | |||
| }}/> | |||
| </Tab>)} | |||
| </TabGroup> | |||
| </>) | |||
| : 'Loading...'} | |||
| </MainArea> | |||
| <div className="md:hidden"> | |||
| <TagDetailSidebar post={post} /> | |||
| <TagDetailSidebar post={post}/> | |||
| </div> | |||
| </div>) | |||
| } | |||
| @@ -111,7 +111,7 @@ export default () => { | |||
| </title> | |||
| </Helmet> | |||
| <TagSidebar posts={posts.slice (0, 20)} /> | |||
| <TagSidebar posts={posts.slice (0, 20)}/> | |||
| <MainArea> | |||
| <TabGroup> | |||
| @@ -124,14 +124,14 @@ export default () => { | |||
| scroll: containerRef.current?.scrollTop ?? 0 } | |||
| sessionStorage.setItem (`posts:${ tagsQuery }`, | |||
| JSON.stringify (statesToSave)) | |||
| }} />) | |||
| }}/>) | |||
| : !(loading) && '広場には何もありませんよ.'} | |||
| {loading && 'Loading...'} | |||
| <div ref={loaderRef} className="h-12"></div> | |||
| </Tab> | |||
| {tags.length === 1 && ( | |||
| <Tab name="Wiki"> | |||
| <WikiBody title={tags[0]} body={wikiPage?.body} /> | |||
| <WikiBody title={tags[0]} body={wikiPage?.body}/> | |||
| <div className="my-2"> | |||
| <Link to={`/wiki/${ encodeURIComponent (tags[0]) }`}> | |||
| Wiki を見る | |||
| @@ -20,7 +20,7 @@ type Props = { user: User | null } | |||
| export default ({ user }: Props) => { | |||
| if (!(['admin', 'member'].some (r => user?.role === r))) | |||
| return <Forbidden /> | |||
| return <Forbidden/> | |||
| const navigate = useNavigate () | |||
| @@ -125,7 +125,7 @@ export default ({ user }: Props) => { | |||
| value={url} | |||
| onChange={e => setURL (e.target.value)} | |||
| className="w-full border p-2 rounded" | |||
| onBlur={handleURLBlur} /> | |||
| onBlur={handleURLBlur}/> | |||
| </div> | |||
| {/* タイトル */} | |||
| @@ -141,7 +141,7 @@ export default ({ user }: Props) => { | |||
| value={title} | |||
| placeholder={titleLoading ? 'Loading...' : ''} | |||
| onChange={ev => setTitle (ev.target.value)} | |||
| disabled={titleAutoFlg} /> | |||
| disabled={titleAutoFlg}/> | |||
| </div> | |||
| {/* サムネール */} | |||
| @@ -169,11 +169,11 @@ export default ({ user }: Props) => { | |||
| setThumbnailFile (file) | |||
| setThumbnailPreview (URL.createObjectURL (file)) | |||
| } | |||
| }} />)} | |||
| }}/>)} | |||
| {thumbnailPreview && ( | |||
| <img src={thumbnailPreview} | |||
| alt="preview" | |||
| className="mt-2 max-h-48 rounded border" />)} | |||
| className="mt-2 max-h-48 rounded border"/>)} | |||
| </div> | |||
| {/* タグ */} | |||
| @@ -181,7 +181,7 @@ export default ({ user }: Props) => { | |||
| <div> | |||
| <Label>タグ</Label> | |||
| <TextArea value={tags} | |||
| onChange={ev => setTags (ev.target.value)} /> | |||
| onChange={ev => setTags (ev.target.value)}/> | |||
| </div> | |||
| {/* 送信 */} | |||
| @@ -114,19 +114,19 @@ export default ({ user }: Props) => { | |||
| {nicoTags.map ((tag, i) => ( | |||
| <tr key={i}> | |||
| <td className="p-2"> | |||
| <TagLink tag={tag} withWiki={false} withCount={false} /> | |||
| <TagLink tag={tag} withWiki={false} withCount={false}/> | |||
| </td> | |||
| <td className="p-2"> | |||
| {editing[tag.id] | |||
| ? ( | |||
| <TextArea value={rawTags[tag.id]} onChange={ev => { | |||
| setRawTags (rawTags => ({ ...rawTags, [tag.id]: ev.target.value })) | |||
| }} />) | |||
| }}/>) | |||
| : tag.linkedTags.map((lt, j) => ( | |||
| <span key={j} className="mr-2"> | |||
| <TagLink tag={lt} | |||
| linkFlg={false} | |||
| withCount={false} /> | |||
| withCount={false}/> | |||
| </span>))} | |||
| </td> | |||
| {memberFlg && ( | |||
| @@ -55,7 +55,7 @@ export default ({ user, setUser }: Props) => { | |||
| return ( | |||
| <MainArea> | |||
| <Helmet> | |||
| <meta name="robots" content="noindex" /> | |||
| <meta name="robots" content="noindex"/> | |||
| <title>設定 | {SITE_TITLE}</title> | |||
| </Helmet> | |||
| @@ -71,7 +71,7 @@ export default ({ user, setUser }: Props) => { | |||
| className="w-full border rounded p-2" | |||
| value={name} | |||
| placeholder="名もなきニジラー" | |||
| onChange={ev => setName (ev.target.value)} /> | |||
| onChange={ev => setName (ev.target.value)}/> | |||
| {(user && !(user.name)) && ( | |||
| <p className="mt-1 text-sm text-red-500"> | |||
| 名前が未設定のアカウントは 30 日間アクセスしないと削除されます!!!! | |||
| @@ -104,10 +104,10 @@ export default ({ user, setUser }: Props) => { | |||
| <UserCodeDialogue visible={userCodeVsbl} | |||
| onVisibleChange={setUserCodeVsbl} | |||
| user={user} | |||
| setUser={setUser} /> | |||
| setUser={setUser}/> | |||
| <InheritDialogue visible={inheritVsbl} | |||
| onVisibleChange={setInheritVsbl} | |||
| setUser={setUser} /> | |||
| setUser={setUser}/> | |||
| </MainArea>) | |||
| } | |||
| @@ -98,7 +98,7 @@ export default () => { | |||
| <MainArea> | |||
| <Helmet> | |||
| <title>{`${ title } Wiki | ${ SITE_TITLE }`}</title> | |||
| {!(wikiPage?.body) && <meta name="robots" content="noindex" />} | |||
| {!(wikiPage?.body) && <meta name="robots" content="noindex"/>} | |||
| </Helmet> | |||
| {(wikiPage && version) && ( | |||
| @@ -120,18 +120,18 @@ export default () => { | |||
| <TagLink tag={tag} | |||
| withWiki={false} | |||
| withCount={false} | |||
| {...(version && { to: `/wiki/${ encodeURIComponent (title) }` })} /> | |||
| {...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/> | |||
| </PageTitle> | |||
| <div className="prose mx-auto p-4"> | |||
| {wikiPage === undefined | |||
| ? 'Loading...' | |||
| : <WikiBody title={title} body={wikiPage?.body} />} | |||
| : <WikiBody title={title} body={wikiPage?.body}/>} | |||
| </div> | |||
| {(!(version) && posts.length > 0) && ( | |||
| <TabGroup> | |||
| <Tab name="広場"> | |||
| <PostList posts={posts} /> | |||
| <PostList posts={posts}/> | |||
| </Tab> | |||
| </TabGroup>)} | |||
| </MainArea>) | |||
| @@ -42,7 +42,7 @@ export default () => { | |||
| diff.diff.map (d => ( | |||
| <span className={cn (d.type === 'added' && 'bg-green-200 dark:bg-green-800', | |||
| d.type === 'removed' && 'bg-red-200 dark:bg-red-800')}> | |||
| {d.content == '\n' ? <br /> : d.content} | |||
| {d.content == '\n' ? <br/> : d.content} | |||
| </span>))) | |||
| : 'Loading...'} | |||
| </div> | |||
| @@ -21,7 +21,7 @@ type Props = { user: User | null } | |||
| export default ({ user }: Props) => { | |||
| if (!(['admin', 'member'].some (r => user?.role === r))) | |||
| return <Forbidden /> | |||
| return <Forbidden/> | |||
| const { id } = useParams () | |||
| @@ -73,7 +73,7 @@ export default ({ user }: Props) => { | |||
| <input type="text" | |||
| value={title} | |||
| onChange={e => setTitle (e.target.value)} | |||
| className="w-full border p-2 rounded" /> | |||
| className="w-full border p-2 rounded"/> | |||
| </div> | |||
| {/* 本文 */} | |||
| @@ -82,7 +82,7 @@ export default ({ user }: Props) => { | |||
| <MdEditor value={body} | |||
| style={{ height: '500px' }} | |||
| renderHTML={text => mdParser.render (text)} | |||
| onChange={({ text }) => setBody (text)} /> | |||
| onChange={({ text }) => setBody (text)}/> | |||
| </div> | |||
| {/* 送信 */} | |||
| @@ -27,54 +27,54 @@ export default () => { | |||
| return ( | |||
| <MainArea> | |||
| <Helmet> | |||
| <title>{`Wiki 変更履歴 | ${ SITE_TITLE }`}</title> | |||
| </Helmet> | |||
| <table className="table-auto w-full border-collapse"> | |||
| <thead> | |||
| <tr> | |||
| <th></th> | |||
| <th className="p-2 text-left">タイトル</th> | |||
| <th className="p-2 text-left">変更</th> | |||
| <th className="p-2 text-left">日時</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| {changes.map (change => ( | |||
| <tr key={change.sha}> | |||
| <td> | |||
| {change.changeType === 'update' && ( | |||
| <Link to={`/wiki/${ change.wikiPage.id }/diff?from=${ change.pred }&to=${ change.sha }`}> | |||
| 差分 | |||
| </Link>)} | |||
| </td> | |||
| <td className="p-2"> | |||
| <Link to={`/wiki/${ encodeURIComponent (change.wikiPage.title) }?version=${ change.sha }`}> | |||
| {change.wikiPage.title} | |||
| </Link> | |||
| </td> | |||
| <td className="p-2"> | |||
| {(() => { | |||
| switch (change.changeType) | |||
| { | |||
| case 'create': | |||
| return '新規' | |||
| case 'update': | |||
| return '更新' | |||
| case 'delete': | |||
| return '削除' | |||
| } | |||
| }) ()} | |||
| </td> | |||
| <td className="p-2"> | |||
| <Link to={`/users/${ change.user.id }`}> | |||
| {change.user.name} | |||
| </Link> | |||
| <br /> | |||
| {change.timestamp} | |||
| </td> | |||
| </tr>))} | |||
| </tbody> | |||
| </table> | |||
| <Helmet> | |||
| <title>{`Wiki 変更履歴 | ${ SITE_TITLE }`}</title> | |||
| </Helmet> | |||
| <table className="table-auto w-full border-collapse"> | |||
| <thead> | |||
| <tr> | |||
| <th></th> | |||
| <th className="p-2 text-left">タイトル</th> | |||
| <th className="p-2 text-left">変更</th> | |||
| <th className="p-2 text-left">日時</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| {changes.map (change => ( | |||
| <tr key={change.sha}> | |||
| <td> | |||
| {change.changeType === 'update' && ( | |||
| <Link to={`/wiki/${ change.wikiPage.id }/diff?from=${ change.pred }&to=${ change.sha }`}> | |||
| 差分 | |||
| </Link>)} | |||
| </td> | |||
| <td className="p-2"> | |||
| <Link to={`/wiki/${ encodeURIComponent (change.wikiPage.title) }?version=${ change.sha }`}> | |||
| {change.wikiPage.title} | |||
| </Link> | |||
| </td> | |||
| <td className="p-2"> | |||
| {(() => { | |||
| switch (change.changeType) | |||
| { | |||
| case 'create': | |||
| return '新規' | |||
| case 'update': | |||
| return '更新' | |||
| case 'delete': | |||
| return '削除' | |||
| } | |||
| }) ()} | |||
| </td> | |||
| <td className="p-2"> | |||
| <Link to={`/users/${ change.user.id }`}> | |||
| {change.user.name} | |||
| </Link> | |||
| <br/> | |||
| {change.timestamp} | |||
| </td> | |||
| </tr>))} | |||
| </tbody> | |||
| </table> | |||
| </MainArea>) | |||
| } | |||
| @@ -21,7 +21,7 @@ type Props = { user: User | null } | |||
| export default ({ user }: Props) => { | |||
| if (!(['admin', 'member'].some (r => user?.role === r))) | |||
| return <Forbidden /> | |||
| return <Forbidden/> | |||
| const location = useLocation () | |||
| const navigate = useNavigate () | |||
| @@ -67,7 +67,7 @@ export default ({ user }: Props) => { | |||
| <input type="text" | |||
| value={title} | |||
| onChange={e => setTitle (e.target.value)} | |||
| className="w-full border p-2 rounded" /> | |||
| className="w-full border p-2 rounded"/> | |||
| </div> | |||
| {/* 本文 */} | |||
| @@ -76,7 +76,7 @@ export default ({ user }: Props) => { | |||
| <MdEditor value={body} | |||
| style={{ height: '500px' }} | |||
| renderHTML={text => mdParser.render (text)} | |||
| onChange={({ text }) => setBody (text)} /> | |||
| onChange={({ text }) => setBody (text)}/> | |||
| </div> | |||
| {/* 送信 */} | |||
| @@ -1,5 +0,0 @@ | |||
| // import { Route, | |||
| // createBrowserRouter, | |||
| // createRoutesFromElements } from 'react-router-dom' | |||
| // | |||
| // import App from '@/App' | |||