AI: address review on PR #477

このコミットが含まれているのは:
Codex Night Worker
2026-11-14 10:55:41 +09:00
コミット c897ea8f8f
9個のファイルの変更、250行の追加、78行の削除
+56 -12
ファイルの表示
@@ -1,6 +1,6 @@
import { isAxiosError } from 'axios'
import { apiGet } from '@/lib/api'
import { apiGet, apiPost, apiPut } from '@/lib/api'
import { switchLocalePath } from '@/lib/locales'
import { fetchTag, fetchTagByName } from '@/lib/tags'
@@ -24,19 +24,54 @@ export const fetchWikiChanges = (
export const fetchWikiPages = async (
{ title, resourceType }: { title?: string, resourceType?: WikiPage['resourceType'] },
{ title, resourceType = 'tag_description' }: {
title?: string, resourceType?: WikiPage['resourceType'] },
locale: LocaleCode = 'ja',
): Promise<WikiPage[]> =>
await apiGet ('/wiki', { locale, params: { title, resource_type: resourceType } })
): Promise<WikiPage[]> => apiGet (
resourceType === 'tag_group' ? '/tag_groups' : '/tags/descriptions',
{ locale, params: { title, document: '1' } })
export const fetchWikiPage = async (
id: string,
{ version }: { version?: string },
id: string,
{ version }: { version?: string },
locale: LocaleCode = 'ja',
): Promise<WikiPage> =>
await apiGet (`/wiki/${ encodeURIComponent (id) }`, {
locale, params: version ? { version } : { } })
): Promise<WikiPage> => {
if (version != null)
return apiGet (`/wiki/${encodeURIComponent (id)}`, { locale, params: { version } })
try
{
return await apiGet (`/tags/descriptions/${encodeURIComponent (id)}`,
{ locale, params: { document: '1' } })
}
catch (error)
{
if (!isAxiosError (error) || error.response?.status !== 404)
throw error
return apiGet (`/tag_groups/${encodeURIComponent (id)}`,
{ locale, params: { document: '1' } })
}
}
export const saveTagDocument = async (
{ title, body, page }: { title: string, body: string, page?: WikiPage },
locale: LocaleCode,
): Promise<WikiPage> => {
const groupName = /^(?:タググループ:|tag_group:)(.*)$/i.exec (title.trim ())?.[1]
const options = { locale, params: { document: '1' } }
if (page?.resourceType === 'tag_group' || (page == null && groupName != null))
{
const attributes = { name: groupName ?? title.trim (), body }
return page == null
? apiPost ('/tag_groups', attributes, options)
: apiPut (`/tag_groups/${encodeURIComponent (String (page.id))}`, attributes, options)
}
if (page == null)
return apiPost ('/tags/descriptions', { title, body }, options)
return apiPut (`/tags/${encodeURIComponent (String (page.tagId))}/description`,
{ title, body }, options)
}
export const fetchWikiPageByTitle = async (
@@ -46,7 +81,14 @@ export const fetchWikiPageByTitle = async (
): Promise<WikiPage | null> => {
try
{
return await apiGet (`/wiki/title/${ encodeURIComponent (title) }`, { locale, params: { version } })
if (version != null)
return await apiGet (`/wiki/title/${encodeURIComponent (title)}`,
{ locale, params: { version } })
const groupName = /^(?:タググループ:|tag_group:)(.*)$/i.exec (title.trim ())?.[1]
const path = groupName == null
? `/tags/name/${encodeURIComponent (title)}/description`
: `/tag_groups/name/${encodeURIComponent (groupName)}`
return await apiGet (path, { locale, params: { document: '1' } })
}
catch (error)
{
@@ -72,7 +114,7 @@ export const fetchWikiPageByReference = async (
{
if (!isAxiosError (error) || error.response?.status !== 404)
throw error
const tag = await fetchWikiTag ({ wikiId: reference }, locale)
const tag = await fetchTagByName (reference, locale)
return tag == null ? null : fetchWikiPageByTitle (tag.name, params, locale)
}
}
@@ -86,7 +128,9 @@ export const fetchWikiTag = async (
return fetchTagByName (reference.name, locale)
try
{
return await apiGet (`/wiki/${encodeURIComponent (reference.wikiId)}/tag`, { locale })
const page = await fetchWikiPage (reference.wikiId, { }, locale)
return (page.resourceType === 'tag_description' && page.tagId != null)
? fetchTag (String (page.tagId), locale) : null
}
catch (error)
{
+10 -13
ファイルの表示
@@ -11,8 +11,8 @@ import FormField from '@/components/common/FormField'
import MainArea from '@/components/layout/MainArea'
import { toast } from '@/components/ui/use-toast'
import PageHead from '@/components/common/PageHead'
import { apiGet, apiPut } from '@/lib/api'
import { wikiKeys } from '@/lib/queryKeys'
import { fetchWikiPage, saveTagDocument } from '@/lib/wiki'
import { tagsKeys, wikiKeys } from '@/lib/queryKeys'
import { canEditContent } from '@/lib/users'
import { inputClass } from '@/lib/utils'
import { useValidationErrors } from '@/lib/useValidationErrors'
@@ -33,7 +33,7 @@ const FIXED_WIKI_EDITOR_VIEW = { menu: true, md: true, html: true } as const
type Props = { user: User | null }
type WikiFormField = 'title' | 'body'
type WikiFormField = 'title' | 'name' | 'body'
const WikiEditPage: FC<Props> = ({ user }) => {
@@ -50,7 +50,7 @@ const WikiEditPage: FC<Props> = ({ user }) => {
const source = `${locale}:${id}`
const { data: wiki, isPending: loading } = useQuery ({
queryKey: wikiKeys.show (id ?? '', { }, locale),
queryFn: () => apiGet<WikiPage> (`/wiki/${ encodeURIComponent (id ?? '') }`, { locale }),
queryFn: () => fetchWikiPage (id ?? '', { }, locale),
enabled: editable })
const [body, setBody] = useState (wiki?.body ?? '')
const [loadedSource, setLoadedSource] = useState (wiki == null ? '' : source)
@@ -60,22 +60,19 @@ const WikiEditPage: FC<Props> = ({ user }) => {
useValidationErrors<WikiFormField> ()
const handleSubmit = async () => {
if (pending || !editable)
if (pending || !editable || wiki == null)
return
clearValidationErrors ()
const formData = new FormData ()
formData.append ('title', title)
formData.append ('body', body)
try
{
await apiPut (`/wiki/${ id }`, formData,
{ locale, headers: { 'Content-Type': 'multipart/form-data' } })
await saveTagDocument ({ title, body, page: wiki }, locale)
qc.setQueryData (wikiKeys.show (title, { }, locale),
(prev: WikiPage | undefined) =>
prev == null ? prev : { ...prev, title, body })
qc.invalidateQueries ({ queryKey: wikiKeys.root })
await Promise.all ([
qc.invalidateQueries ({ queryKey: wikiKeys.root }),
qc.invalidateQueries ({ queryKey: tagsKeys.root })])
toast ({ title: label ('shared:messages.postSuccess') })
navigate (`/wiki/${ encodeURIComponent (title) }`)
}
@@ -110,7 +107,7 @@ const WikiEditPage: FC<Props> = ({ user }) => {
{/* タイトル */}
{/* TODO: タグ補完 */}
<FormField label={label ('shared:labels.title')} messages={fieldErrors.title}>
<FormField label={label ('shared:labels.title')} messages={fieldErrors.title ?? fieldErrors.name}>
{({ describedBy, invalid }) => (
<input type="text"
value={title}
+5 -10
ファイルの表示
@@ -12,7 +12,7 @@ import FormField from '@/components/common/FormField'
import MainArea from '@/components/layout/MainArea'
import { toast } from '@/components/ui/use-toast'
import PageHead from '@/components/common/PageHead'
import { apiPost } from '@/lib/api'
import { saveTagDocument } from '@/lib/wiki'
import { tagsKeys, wikiKeys } from '@/lib/queryKeys'
import { canEditContent } from '@/lib/users'
import { inputClass } from '@/lib/utils'
@@ -21,7 +21,7 @@ import Forbidden from '@/pages/Forbidden'
import type { FC } from 'react'
import type { User, WikiPage } from '@/types'
import type { User } from '@/types'
const mdParser = new MarkdownIt
const FIXED_WIKI_EDITOR_VIEW = { menu: true, md: true, html: true } as const
@@ -32,7 +32,7 @@ const FIXED_WIKI_EDITOR_VIEW = { menu: true, md: true, html: true } as const
type Props = { user: User | null }
type WikiFormField = 'title' | 'body'
type WikiFormField = 'title' | 'name' | 'body'
const WikiNewPage: FC<Props> = ({ user }) => {
@@ -55,14 +55,9 @@ const WikiNewPage: FC<Props> = ({ user }) => {
const handleSubmit = async () => {
clearValidationErrors ()
const formData = new FormData
formData.append ('title', title)
formData.append ('body', body)
try
{
const data = await apiPost<WikiPage> ('/wiki', formData,
{ locale, headers: { 'Content-Type': 'multipart/form-data' } })
const data = await saveTagDocument ({ title, body }, locale)
await qc.cancelQueries ({ queryKey: wikiKeys.root })
qc.setQueryData (wikiKeys.show (data.title, { }, locale), data)
await Promise.all ([
@@ -91,7 +86,7 @@ const WikiNewPage: FC<Props> = ({ user }) => {
{/* タイトル */}
{/* TODO: タグ補完 */}
<FormField label={label ('shared:labels.title')} messages={fieldErrors.title}>
<FormField label={label ('shared:labels.title')} messages={fieldErrors.title ?? fieldErrors.name}>
{({ describedBy, invalid }) => (
<input type="text"
value={title}