このコミットが含まれているのは:
2026-06-22 08:16:29 +09:00
コミット eeefb09d0c
13個のファイルの変更59行の追加15行の削除
+11 -7
ファイルの表示
@@ -4,17 +4,18 @@ class WikiPagesController < ApplicationController
def index def index
title = params[:title].to_s.strip title = params[:title].to_s.strip
if title.blank? if title.blank?
return render json: WikiPageRepr.base(WikiPage.joins(:tag_name).includes(:tag_name)) return render json: WikiPageRepr.base(
WikiPage.joins(:tag_name).includes(tag_name: :tag))
end end
q = WikiPage.joins(:tag_name).includes(:tag_name) q = WikiPage.joins(:tag_name).includes(tag_name: :tag)
.where('tag_names.name LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%") .where('tag_names.name LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%")
render json: WikiPageRepr.base(q.limit(20)) render json: WikiPageRepr.base(q.limit(20))
end end
def show def show
page = WikiPage.joins(:tag_name) page = WikiPage.joins(:tag_name)
.includes(:tag_name) .includes(tag_name: :tag)
.find_by(id: params[:id]) .find_by(id: params[:id])
render_wiki_page_or_404 page render_wiki_page_or_404 page
end end
@@ -22,7 +23,7 @@ class WikiPagesController < ApplicationController
def show_by_title def show_by_title
title = params[:title].to_s.strip title = params[:title].to_s.strip
page = WikiPage.joins(:tag_name) page = WikiPage.joins(:tag_name)
.includes(:tag_name) .includes(tag_name: :tag)
.find_by(tag_name: { name: title }) .find_by(tag_name: { name: title })
render_wiki_page_or_404 page render_wiki_page_or_404 page
end end
@@ -51,7 +52,7 @@ class WikiPagesController < ApplicationController
from = params[:from].presence from = params[:from].presence
to = params[:to].presence to = params[:to].presence
page = WikiPage.joins(:tag_name).includes(:tag_name).find(id) page = WikiPage.joins(:tag_name).includes(tag_name: :tag).find(id)
from_rev = from && page.wiki_revisions.find(from) from_rev = from && page.wiki_revisions.find(from)
to_rev = to ? page.wiki_revisions.find(to) : page.current_revision to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
@@ -76,6 +77,7 @@ class WikiPagesController < ApplicationController
render json: { wiki_page_id: page.id, render json: { wiki_page_id: page.id,
title: page.title, title: page.title,
deprecated_at: page.deprecated_at,
older_revision_id: from_rev&.id, older_revision_id: from_rev&.id,
newer_revision_id: to_rev.id, newer_revision_id: to_rev.id,
diff: diff_json } diff: diff_json }
@@ -157,7 +159,7 @@ class WikiPagesController < ApplicationController
def changes def changes
id = params[:id].presence id = params[:id].presence
q = WikiRevision.joins(wiki_page: :tag_name) q = WikiRevision.joins(wiki_page: :tag_name)
.includes(:created_user, wiki_page: :tag_name) .includes(:created_user, wiki_page: { tag_name: :tag })
.order(id: :desc) .order(id: :desc)
q = q.where(wiki_page_id: id) if id q = q.where(wiki_page_id: id) if id
@@ -165,7 +167,9 @@ class WikiPagesController < ApplicationController
{ revision_id: rev.id, { revision_id: rev.id,
pred: rev.base_revision_id, pred: rev.base_revision_id,
succ: nil, succ: nil,
wiki_page: { id: rev.wiki_page_id, title: rev.wiki_page.title }, wiki_page: { id: rev.wiki_page_id,
title: rev.wiki_page.title,
deprecated_at: rev.wiki_page.deprecated_at },
user: rev.created_user && { id: rev.created_user.id, name: rev.created_user.name }, user: rev.created_user && { id: rev.created_user.id, name: rev.created_user.name },
kind: rev.kind, kind: rev.kind,
message: rev.message, message: rev.message,
+1
ファイルの表示
@@ -22,6 +22,7 @@ class WikiPage < ApplicationRecord
validates :body, presence: true validates :body, presence: true
def title = tag_name.name def title = tag_name.name
def deprecated_at = tag_name.tag&.deprecated_at
def title= val def title= val
(self.tag_name ||= build_tag_name).name = val (self.tag_name ||= build_tag_name).name = val
+1 -1
ファイルの表示
@@ -2,7 +2,7 @@
module WikiPageRepr module WikiPageRepr
BASE = { methods: [:title] }.freeze BASE = { methods: [:title, :deprecated_at] }.freeze
module_function module_function
+15
ファイルの表示
@@ -18,6 +18,21 @@ describe ('TagLink', () => {
expect (screen.getByText ('4')).toBeInTheDocument () expect (screen.getByText ('4')).toBeInTheDocument ()
}) })
it ('does not append deprecated state to the rendered tag name', () => {
renderWithProviders (
<TagLink
tag={buildTag ({
name: '旧タグ',
deprecatedAt: '2026-06-01T00:00:00.000Z',
})}
withWiki={false}
withCount={false}/>,
)
expect (screen.getByRole ('link', { name: '旧タグ' })).toBeInTheDocument ()
expect (screen.queryByText ('(廃止)')).not.toBeInTheDocument ()
})
it ('links wiki markers to the correct detail route', () => { it ('links wiki markers to the correct detail route', () => {
renderWithProviders ( renderWithProviders (
<TagLink tag={buildTag ({ hasWiki: true, name: 'a/b' })}/>, <TagLink tag={buildTag ({ hasWiki: true, name: 'a/b' })}/>,
+1 -1
ファイルの表示
@@ -128,4 +128,4 @@ const TagLink: FC<Props> = ({ tag,
</>) </>)
} }
export default TagLink export default TagLink
-1
ファイルの表示
@@ -66,7 +66,6 @@ export const fetchTagByName = async (name: string): Promise<Tag | null> => {
} }
} }
export const fetchTagChanges = async ( export const fetchTagChanges = async (
{ id, page, limit }: { { id, page, limit }: {
id?: string id?: string
+6 -2
ファイルの表示
@@ -39,6 +39,7 @@ const WikiDetailPage: FC = () => {
queryFn: () => fetchWikiPageByTitle (title, { version }) }) queryFn: () => fetchWikiPageByTitle (title, { version }) })
const effectiveTitle = wikiPage?.title ?? title const effectiveTitle = wikiPage?.title ?? title
const deprecated = wikiPage?.deprecatedAt != null
const { data: tag } = useQuery ({ const { data: tag } = useQuery ({
enabled: Boolean (effectiveTitle), enabled: Boolean (effectiveTitle),
@@ -88,7 +89,7 @@ const WikiDetailPage: FC = () => {
return ( return (
<MainArea> <MainArea>
<Helmet> <Helmet>
<title>{`${ title } Wiki | ${ SITE_TITLE }`}</title> <title>{`${ effectiveTitle }${ deprecated ? '(廃止)' : '' } Wiki | ${ SITE_TITLE }`}</title>
{!(wikiPage?.body) && <meta name="robots" content="noindex"/>} {!(wikiPage?.body) && <meta name="robots" content="noindex"/>}
</Helmet> </Helmet>
@@ -110,10 +111,13 @@ const WikiDetailPage: FC = () => {
<article className="prose dark:prose-invert mx-auto p-4"> <article className="prose dark:prose-invert mx-auto p-4">
<h1 className="prose-a:no-underline"> <h1 className="prose-a:no-underline">
<TagLink tag={tag ?? defaultTag} <TagLink tag={tag ?? { ...defaultTag,
name: effectiveTitle,
deprecatedAt: wikiPage?.deprecatedAt ?? null }}
withWiki={false} withWiki={false}
withCount={false} withCount={false}
{...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/> {...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/>
{deprecated && <span></span>}
</h1> </h1>
{loading ? <div>Loading...</div> : <WikiBody title={title} body={wikiPage?.body}/>} {loading ? <div>Loading...</div> : <WikiBody title={title} body={wikiPage?.body}/>}
+5 -2
ファイルの表示
@@ -23,6 +23,9 @@ const WikiDiffPage: FC = () => {
const query = new URLSearchParams (location.search) const query = new URLSearchParams (location.search)
const from = query.get ('from') const from = query.get ('from')
const to = query.get ('to') const to = query.get ('to')
const displayTitle = diff
? `${ diff.title }${ diff.deprecatedAt != null ? '(廃止)' : '' }`
: ''
useEffect (() => { useEffect (() => {
void (async () => { void (async () => {
@@ -33,9 +36,9 @@ const WikiDiffPage: FC = () => {
return ( return (
<MainArea> <MainArea>
<Helmet> <Helmet>
<title>{`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`}</title> <title>{`Wiki 差分: ${ displayTitle } | ${ SITE_TITLE }`}</title>
</Helmet> </Helmet>
<PageTitle>{diff?.title}</PageTitle> <PageTitle>{displayTitle}</PageTitle>
<div className="prose mx-auto p-4"> <div className="prose mx-auto p-4">
{diff {diff
? ( ? (
+1
ファイルの表示
@@ -59,6 +59,7 @@ const WikiHistoryPage: FC = () => {
to={`/wiki/${ encodeURIComponent (change.wikiPage.title) }?version=${ change.revisionId }`}> to={`/wiki/${ encodeURIComponent (change.wikiPage.title) }?version=${ change.revisionId }`}>
{change.wikiPage.title} {change.wikiPage.title}
</PrefetchLink> </PrefetchLink>
{change.wikiPage.deprecatedAt != null && <span></span>}
</td> </td>
<td className="p-2"> <td className="p-2">
{change.pred == null ? '新規' : '更新'} {change.pred == null ? '新規' : '更新'}
+13
ファイルの表示
@@ -42,4 +42,17 @@ describe ('WikiSearchPage', () => {
}) })
expect (await screen.findByRole ('link', { name: '検索結果' })).toBeInTheDocument () expect (await screen.findByRole ('link', { name: '検索結果' })).toBeInTheDocument ()
}) })
it ('marks deprecated wiki tags in the result title', async () => {
api.apiGet.mockResolvedValueOnce ([
buildWikiPage ({
title: '旧タグ',
deprecatedAt: '2026-06-01T00:00:00.000Z',
}),
])
renderWithProviders (<WikiSearchPage/>)
expect (await screen.findByRole ('link', { name: '旧タグ(廃止)' })).toBeInTheDocument ()
})
}) })
+1
ファイルの表示
@@ -86,6 +86,7 @@ const WikiSearchPage: FC = () => {
<PrefetchLink to={`/wiki/${ encodeURIComponent (page.title) }`}> <PrefetchLink to={`/wiki/${ encodeURIComponent (page.title) }`}>
{page.title} {page.title}
</PrefetchLink> </PrefetchLink>
{page.deprecatedAt != null && <span></span>}
</td> </td>
<td className="p-2"> <td className="p-2">
{dateString (page.updatedAt)} {dateString (page.updatedAt)}
+1
ファイルの表示
@@ -58,6 +58,7 @@ export const buildUser = (overrides: Partial<User> = {}): User => ({
export const buildWikiPage = (overrides: Partial<WikiPage> = {}): WikiPage => ({ export const buildWikiPage = (overrides: Partial<WikiPage> = {}): WikiPage => ({
id: 1, id: 1,
title: 'テストWiki', title: 'テストWiki',
deprecatedAt: null,
createdUserId: 1, createdUserId: 1,
updatedUserId: 1, updatedUserId: 1,
createdAt: '2026-01-02T03:04:05.000Z', createdAt: '2026-01-02T03:04:05.000Z',
+3 -1
ファイルの表示
@@ -299,6 +299,7 @@ export type ViewFlagBehavior = typeof ViewFlagBehavior[keyof typeof ViewFlagBeha
export type WikiPage = { export type WikiPage = {
id: number id: number
title: string title: string
deprecatedAt: string | null
createdUserId: number createdUserId: number
updatedUserId: number updatedUserId: number
createdAt: string createdAt: string
@@ -312,7 +313,7 @@ export type WikiPageChange = {
revisionId: number revisionId: number
pred: number | null pred: number | null
succ: null succ: null
wikiPage: Pick<WikiPage, 'id' | 'title'> wikiPage: Pick<WikiPage, 'id' | 'title' | 'deprecatedAt'>
user: Pick<User, 'id' | 'name'> user: Pick<User, 'id' | 'name'>
kind: 'content' | 'redirect' kind: 'content' | 'redirect'
message: string | null message: string | null
@@ -321,6 +322,7 @@ export type WikiPageChange = {
export type WikiPageDiff = { export type WikiPageDiff = {
wikiPageId: number wikiPageId: number
title: string title: string
deprecatedAt: string | null
olderRevisionId: number | null olderRevisionId: number | null
newerRevisionId: number newerRevisionId: number
diff: WikiPageDiffDiff[] } diff: WikiPageDiffDiff[] }