このコミットが含まれているのは:
2026-07-14 19:12:23 +09:00
コミット 6d037192c4
9個のファイルの変更108行の追加72行の削除
+32 -8
ファイルの表示
@@ -16,9 +16,11 @@ import { canEditContent } from '@/lib/users'
import { clearPostImportSourceDraft,
loadPostImportSession,
mergeImportResults,
mergeValidatedImportRows,
retryImportRow,
savePostImportSession,
type PostImportResultRow,
type PostImportRow,
type PostImportSession } from '@/lib/postImportSession'
import Forbidden from '@/pages/Forbidden'
@@ -92,9 +94,31 @@ const PostImportResultPage: FC<Props> = ({ user }) => {
{
const pendingRows = retryImportRow (session.rows, sourceRow)
setSession ({ ...session, rows: pendingRows })
const target = pendingRows.find (_1 => _1.sourceRow === sourceRow)
const validated = await apiPost<{ rows: PostImportRow[] }> ('/posts/import/validate', {
rows: pendingRows
.filter (row => row.importStatus !== 'created')
.map (row => ({
sourceRow: row.sourceRow,
url: row.url,
attributes: row.attributes,
provenance: row.provenance,
tagSources: row.tagSources,
metadataUrl: row.metadataUrl })),
changed_row: -1 })
const validatedRows = mergeValidatedImportRows (pendingRows, validated.rows).map (row =>
row.sourceRow === sourceRow
&& Object.keys (row.validationErrors ?? { }).length > 0
? { ...row, importStatus: 'failed' as const }
: row)
setSession (current =>
current
? { ...current, rows: validatedRows }
: current)
const target = validatedRows.find (_1 => _1.sourceRow === sourceRow)
if (target == null)
return
if (Object.keys (target.validationErrors ?? { }).length > 0)
return
const result = await apiPost<{
created: number
@@ -125,15 +149,15 @@ const PostImportResultPage: FC<Props> = ({ user }) => {
}
const openRepair = (sourceRow: number) => {
if (session == null || sessionId == null)
return
const nextSession = { ...session, repairMode: 'failed' as const }
setSession (nextSession)
if (sessionId)
{
const saved = savePostImportSession (sessionId, nextSession, message =>
toast ({ title: '取込状態を保存できませんでした', description: message }))
if (!(saved))
return
}
const saved = savePostImportSession (sessionId, nextSession, message =>
toast ({ title: '取込状態を保存できませんでした', description: message }))
if (!(saved))
return
navigate (`/posts/import/${ sessionId }/review?edit=${ sourceRow }`)
}
+13 -22
ファイルの表示
@@ -24,8 +24,7 @@ import type { User } from '@/types'
type Props = { user: User | null }
type PostFormField =
'url'
type PostFormField = 'url'
| 'title'
| 'tags'
| 'parentPostIds'
@@ -42,10 +41,8 @@ const PostNewPage: FC<Props> = ({ user }) => {
const { baseErrors, fieldErrors, clearValidationErrors, applyValidationError } =
useValidationErrors<PostFormField> ()
const [originalCreatedBefore, setOriginalCreatedBefore] =
useState<string | null> (null)
const [originalCreatedFrom, setOriginalCreatedFrom] =
useState<string | null> (null)
const [originalCreatedBefore, setOriginalCreatedBefore] = useState<string | null> (null)
const [originalCreatedFrom, setOriginalCreatedFrom] = useState<string | null> (null)
const [parentPostIds, setParentPostIds] = useState ('')
const [tags, setTags] = useState ('')
const [duration, setDuration] = useState ('')
@@ -57,11 +54,9 @@ const PostNewPage: FC<Props> = ({ user }) => {
const [url, setURL] = useState ('')
const thumbnailPreviewRef = useRef ('')
const videoFlg =
useMemo (() =>
tags.split (/\s+/).some (
tag => tag.replace (/\[.*\]$/, '') === '動画'),
[tags])
const videoFlg = useMemo (() =>
tags.split (/\s+/).some (
tag => tag.replace (/\[.*\]$/, '') === '動画'), [tags])
const handleSubmit = async () => {
clearValidationErrors ()
@@ -82,8 +77,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
try
{
await apiPost ('/posts', formData,
{ headers: { 'Content-Type': 'multipart/form-data' } })
await apiPost ('/posts', formData, { headers: { 'Content-Type': 'multipart/form-data' } })
toast ({ title: '投稿成功!' })
navigate ('/posts')
}
@@ -98,8 +92,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
setTitleLoading (true)
try
{
const data = await apiGet<{ title: string }> ('/preview/title',
{ params: { url } })
const data = await apiGet<{ title: string }> ('/preview/title', { params: { url } })
setTitle (data.title || '')
}
finally
@@ -116,13 +109,11 @@ const PostNewPage: FC<Props> = ({ user }) => {
URL.revokeObjectURL (thumbnailPreviewRef.current)
try
{
const data = await apiGet<Blob> ('/preview/thumbnail',
{ params: { url },
responseType: 'blob' })
const data = await apiGet<Blob> ('/preview/thumbnail', { params: { url },
responseType: 'blob' })
const imageURL = URL.createObjectURL (data)
setThumbnailPreview (imageURL)
setThumbnailFile (new File ([data],
'thumbnail.png',
setThumbnailFile (new File ([data], 'thumbnail.png',
{ type: data.type || 'image/png' }))
}
finally
@@ -176,7 +167,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
<Button
type="button"
variant="outline"
onClick={() => void fetchTitle()}
onClick={() => void fetchTitle ()}
disabled={!(url) || titleLoading}>
</Button>
@@ -193,7 +184,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
<Button
type="button"
variant="outline"
onClick={() => void fetchThumbnail()}
onClick={() => void fetchThumbnail ()}
disabled={!(url) || thumbnailLoading}>
</Button>