このコミットが含まれているのは:
@@ -1,16 +1,16 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet-async'
|
||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
||||
|
||||
import CommonDialogue from '@/components/dialogues/CommonDialogue'
|
||||
import PageTitle from '@/components/common/PageTitle'
|
||||
import MainArea from '@/components/layout/MainArea'
|
||||
import PostImportRowForm from '@/components/posts/import/PostImportRowForm'
|
||||
import PostImportRowForm, { buildDraft } from '@/components/posts/import/PostImportRowForm'
|
||||
import PostImportRowSummary from '@/components/posts/import/PostImportRowSummary'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { toast } from '@/components/ui/use-toast'
|
||||
import { SITE_TITLE } from '@/config'
|
||||
import { apiPost } from '@/lib/api'
|
||||
import useDialogue from '@/lib/dialogues/useDialogue'
|
||||
import { canEditContent } from '@/lib/users'
|
||||
import { loadPostImportSession,
|
||||
creatableImportRows,
|
||||
@@ -35,6 +35,7 @@ type Props = { user: User | null }
|
||||
|
||||
const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
const editable = canEditContent (user)
|
||||
const dialogue = useDialogue ()
|
||||
const navigate = useNavigate ()
|
||||
const { sessionId } = useParams ()
|
||||
const [searchParams, setSearchParams] = useSearchParams ()
|
||||
@@ -44,6 +45,10 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
const [missing, setMissing] = useState (false)
|
||||
const [savingRow, setSavingRow] = useState<number | null> (null)
|
||||
const [dialogueMessageRow, setDialogueMessageRow] = useState<PostImportRow | null> (null)
|
||||
const [dialogueDraft, setDialogueDraft] = useState<PostImportRowDraft | null> (null)
|
||||
const [dialogueResetRequested, setDialogueResetRequested] = useState (false)
|
||||
const dialogueDraftRef = useRef<PostImportRowDraft | null> (null)
|
||||
const dialogueResetRequestedRef = useRef (false)
|
||||
|
||||
useEffect (() => {
|
||||
if (sessionId == null)
|
||||
@@ -63,6 +68,14 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
toast ({ title: '取込状態を保存できませんでした', description: message }))
|
||||
}, [session, sessionId])
|
||||
|
||||
useEffect (() => {
|
||||
dialogueDraftRef.current = dialogueDraft
|
||||
}, [dialogueDraft])
|
||||
|
||||
useEffect (() => {
|
||||
dialogueResetRequestedRef.current = dialogueResetRequested
|
||||
}, [dialogueResetRequested])
|
||||
|
||||
const rows = session?.rows ?? []
|
||||
const editingSourceRow = Number (searchParams.get ('edit') ?? '')
|
||||
const editingRow =
|
||||
@@ -98,10 +111,15 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
if (editingRow == null)
|
||||
{
|
||||
setDialogueMessageRow (null)
|
||||
setDialogueDraft (null)
|
||||
setDialogueResetRequested (false)
|
||||
return
|
||||
}
|
||||
if (dialogueMessageRow?.sourceRow !== editingRow.sourceRow)
|
||||
setDialogueMessageRow (null)
|
||||
setDialogueDraft (current =>
|
||||
current != null ? current : buildDraft (editingRow))
|
||||
setDialogueResetRequested (false)
|
||||
}, [editingRow, dialogueMessageRow])
|
||||
|
||||
const updateSessionRows = (nextRows: PostImportRow[]) =>
|
||||
@@ -113,12 +131,13 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
draft: PostImportRowDraft
|
||||
resetRequested: boolean
|
||||
resetSnapshot: PostImportRow['resetSnapshot'] },
|
||||
): Promise<boolean> => {
|
||||
): Promise<{ saved: boolean
|
||||
row: PostImportRow | null }> => {
|
||||
if (session == null)
|
||||
return false
|
||||
return { saved: false, row: null }
|
||||
|
||||
if (editingRow == null)
|
||||
return false
|
||||
return { saved: false, row: null }
|
||||
|
||||
const baseRow =
|
||||
resetRequested
|
||||
@@ -159,17 +178,17 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
if (target != null && Object.keys (target.validationErrors).length > 0)
|
||||
{
|
||||
setDialogueMessageRow (target)
|
||||
return false
|
||||
return { saved: false, row: target }
|
||||
}
|
||||
updateSessionRows (mergeValidatedImportRows (nextRows, validatedRows))
|
||||
setDialogueMessageRow (null)
|
||||
setSearchParams ({ })
|
||||
return true
|
||||
return { saved: true, row: null }
|
||||
}
|
||||
catch
|
||||
{
|
||||
toast ({ title: '行の再検証に失敗しました' })
|
||||
return false
|
||||
return { saved: false, row: null }
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -177,6 +196,53 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const openEditingDialogue = async (row: PostImportRow) => {
|
||||
let currentRow = row
|
||||
|
||||
while (true)
|
||||
{
|
||||
const initialDraft = buildDraft (currentRow)
|
||||
setDialogueDraft (current => current != null ? current : initialDraft)
|
||||
setDialogueResetRequested (false)
|
||||
|
||||
const action = await dialogue.choice ({
|
||||
title: '投稿を編輯',
|
||||
description: <PostImportRowForm
|
||||
row={currentRow}
|
||||
messageRow={dialogueMessageRow?.sourceRow === currentRow.sourceRow
|
||||
? dialogueMessageRow
|
||||
: null}
|
||||
saving={savingRow === currentRow.sourceRow}
|
||||
onDraftChange={setDialogueDraft}
|
||||
onResetRequestedChange={setDialogueResetRequested}/>,
|
||||
cancelText: '取消',
|
||||
choices: [{ value: 'save', label: '編輯内容を保存' }] as const })
|
||||
|
||||
if (action !== 'save')
|
||||
{
|
||||
setSearchParams ({ })
|
||||
return
|
||||
}
|
||||
|
||||
const draft = dialogueDraftRef.current ?? initialDraft
|
||||
const result = await saveDraft ({
|
||||
draft,
|
||||
resetRequested: dialogueResetRequestedRef.current,
|
||||
resetSnapshot: currentRow.resetSnapshot })
|
||||
if (result.saved)
|
||||
return
|
||||
|
||||
currentRow = result.row ?? currentRow
|
||||
}
|
||||
}
|
||||
|
||||
useEffect (() => {
|
||||
if (editingRow == null)
|
||||
return
|
||||
|
||||
void openEditingDialogue (editingRow)
|
||||
}, [editingRow])
|
||||
|
||||
const submit = async () => {
|
||||
if (sessionId == null || session == null || processable.length === 0)
|
||||
return
|
||||
@@ -315,25 +381,6 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
|
||||
onBack={() => navigate ('/posts/import')}
|
||||
onSubmit={submit}/>
|
||||
|
||||
{editingRow != null && (
|
||||
<CommonDialogue
|
||||
open={true}
|
||||
onOpenChange={open => {
|
||||
if (!open)
|
||||
setSearchParams ({ })
|
||||
}}
|
||||
title="投稿を編輯"
|
||||
description={`投稿 ${ editingRow.sourceRow } の内容を確認し、必要な項目を編輯してください.`}
|
||||
className="flex max-h-[calc(100dvh-1rem)] max-w-3xl flex-col overflow-hidden p-0"
|
||||
bodyClassName="contents">
|
||||
<PostImportRowForm
|
||||
key={editingRow.sourceRow}
|
||||
row={editingRow}
|
||||
messageRow={dialogueMessageRow}
|
||||
saving={savingRow != null}
|
||||
onCancel={() => setSearchParams ({ })}
|
||||
onSave={saveDraft}/>
|
||||
</CommonDialogue>)}
|
||||
</>)
|
||||
}
|
||||
|
||||
|
||||
新しい課題から参照
ユーザをブロックする