diff --git a/backend/app/controllers/wiki_pages_controller.rb b/backend/app/controllers/wiki_pages_controller.rb index 40ba9da..47a388a 100644 --- a/backend/app/controllers/wiki_pages_controller.rb +++ b/backend/app/controllers/wiki_pages_controller.rb @@ -1,25 +1,10 @@ class WikiPagesController < ApplicationController def show - wiki_page = WikiPage.find(params[:id]) - return head :not_found unless wiki_page - - render json: wiki_page.as_json.merge(body: wiki_page.body) + render_wiki_page_or_404 WikiPage.find(params[:id]) end def show_by_title - title = params[:title] - version = params[:version].presence - - wiki_page = WikiPage.find_by(title:) - return head :not_found unless wiki_page - - wiki_page.sha = version - - body = wiki_page.body - sha = wiki_page.sha - pred = wiki_page.pred - succ = wiki_page.succ - render json: wiki_page.as_json.merge(body:, sha:, pred:, succ:) + render_wiki_page_or_404 WikiPage.find_by(title: params[:title]) end def diff @@ -117,4 +102,16 @@ class WikiPagesController < ApplicationController def wiki @wiki ||= Gollum::Wiki.new(WIKI_PATH) end + + def render_wiki_page_or_404 wiki_page + return head :not_found unless wiki_page + + wiki_page.sha = params[:version].presence + + body = wiki_page.body + sha = wiki_page.sha + pred = wiki_page.pred + succ = wiki_page.succ + render json: wiki_page.as_json.merge(body:, sha:, pred:, succ:) + end end diff --git a/backend/app/models/wiki_page.rb b/backend/app/models/wiki_page.rb index efe47af..9b89049 100644 --- a/backend/app/models/wiki_page.rb +++ b/backend/app/models/wiki_page.rb @@ -20,6 +20,7 @@ class WikiPage < ApplicationRecord idx = vers.find_index { |ver| ver.id == @sha } @pred = vers[idx + 1]&.id @succ = idx.positive? ? vers[idx - 1].id : nil + @updated_at = vers[idx].authored_date @sha end @@ -35,6 +36,10 @@ class WikiPage < ApplicationRecord @succ end + def updated_at + @updated_at + end + def body sha = nil unless @page @page&.raw_data&.force_encoding('UTF-8') diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4fa83b6..97482cf 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -10,6 +10,7 @@ import PostDetailPage from '@/pages/PostDetailPage' import WikiPage from '@/pages/WikiPage' import WikiNewPage from '@/pages/WikiNewPage' import WikiEditPage from '@/pages/WikiEditPage' +import WikiDiffPage from '@/pages/WikiDiffPage' import WikiDetailPage from '@/pages/WikiDetailPage' import WikiHistoryPage from '@/pages/WikiHistoryPage' import { API_BASE_URL } from '@/config' @@ -64,9 +65,10 @@ export default () => { } /> } /> } /> - } /> + } /> } /> } /> + } /> } /> diff --git a/frontend/src/pages/WikiDetailPage.tsx b/frontend/src/pages/WikiDetailPage.tsx index 9a34762..b58a9ac 100644 --- a/frontend/src/pages/WikiDetailPage.tsx +++ b/frontend/src/pages/WikiDetailPage.tsx @@ -1,45 +1,68 @@ import { useEffect, useState } from 'react' -import { Link, useParams, useNavigate } from 'react-router-dom' +import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' import ReactMarkdown from 'react-markdown' import axios from 'axios' import { API_BASE_URL } from '@/config' import MainArea from '@/components/layout/MainArea' import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' +import type { WikiPage } from '@/types' + export default () => { - const { name } = useParams () + const { title } = useParams () + const location = useLocation () const navigate = useNavigate () - const [markdown, setMarkdown] = useState (null) + const [wikiPage, setWikiPage] = useState (undefined) + + const query = new URLSearchParams (location.search) + const version = query.get ('version') useEffect (() => { - if (/^\d+$/.test (name)) + if (/^\d+$/.test (title)) { - void (axios.get (`${ API_BASE_URL }/wiki/${ name }`) + void (axios.get (`${ API_BASE_URL }/wiki/${ title }`) .then (res => navigate (`/wiki/${ res.data.title }`, { replace: true }))) return } - void (axios.get (`${ API_BASE_URL }/wiki/title/${ encodeURIComponent (name) }`) + void (axios.get (`${ API_BASE_URL }/wiki/title/${ encodeURIComponent (title) }`, version && { params: { version } }) .then (res => { - setMarkdown (res.data.body) + setWikiPage (res.data) WikiIdBus.set (res.data.id) }) - .catch (() => setMarkdown (''))) - }, [name]) + .catch (() => setWikiPage (null))) + }, [title, location.search]) return ( + {(wikiPage && version) && ( +
+ {wikiPage.pred ? ( + + < 前 + ) : <>< 前} + + {wikiPage.updated_at} + + {wikiPage.succ ? ( + + 後 > + ) : <>後 >} +
)} +

{title}

- {markdown == null ? 'Loading...' : ( + {wikiPage === undefined ? 'Loading...' : ( <> (['/', '.'].some (e => href?.startsWith (e)) ? {children} : {children})) }}> - {markdown || `このページは存在しません。[新規作成してください](/wiki/new?title=${ name })。`} + {wikiPage?.body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ title })。`} )}
diff --git a/frontend/src/pages/WikiDiffPage.tsx b/frontend/src/pages/WikiDiffPage.tsx new file mode 100644 index 0000000..5e13c44 --- /dev/null +++ b/frontend/src/pages/WikiDiffPage.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react' +import { Link, useLocation, useParams } from 'react-router-dom' +import axios from 'axios' +import MainArea from '@/components/layout/MainArea' +import { API_BASE_URL } from '@/config' + +import type { WikiPageDiff } from '@/types' + + +export default () => { + const { id } = useParams () + + const location = useLocation () + + const [diff, setDiff] = useState (null) + + const query = new URLSearchParams (location.search) + const from = query.get ('from') + const to = query.get ('to') + + useEffect (() => { + void (axios.get (`${ API_BASE_URL }/wiki/${ id }/diff`, { params: { from, to } }) + .then (res => setDiff (res.data))) + }, []) + + return ( + +

{diff?.title}

+
+ {diff ? ( + diff.diff.map (d => ( + + {d.content == '\n' ?
: d.content} +
))) : 'Loading...'} +
+
) +} diff --git a/frontend/src/pages/WikiHistoryPage.tsx b/frontend/src/pages/WikiHistoryPage.tsx index 4a826f9..c645fd2 100644 --- a/frontend/src/pages/WikiHistoryPage.tsx +++ b/frontend/src/pages/WikiHistoryPage.tsx @@ -33,10 +33,12 @@ export default () => { {changes.map (change => ( - {change.change_type === 'update' && ( - - 差分 - )} + + {change.change_type === 'update' && ( + + 差分 + )} + diff --git a/frontend/src/types.ts b/frontend/src/types.ts index dd54a19..1cfbc18 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -25,13 +25,29 @@ export type User = { export type WikiPage = { id: number title: string + sha: string + pred?: string + succ?: string updated_at?: string } export type WikiPageChange = { sha: string + pred?: string + succ?: string wiki_page: WikiPage user: User change_type: string timestamp: string } +export type WikiPageDiff = { + wiki_page_id: number + title: string + older_sha: string + newer_sha: string + diff: WikiPageDiffDiff[] } + +export type WikiPageDiffDiff = { + type: 'context' | 'added' | 'removed' + content: string } + export type UserRole = typeof USER_ROLES[number]