このコミットが含まれているのは:
@@ -1,4 +1,4 @@
|
||||
import { useRef, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet-async'
|
||||
|
||||
import FieldError from '@/components/common/FieldError'
|
||||
@@ -28,8 +28,10 @@ type ImportRow = {
|
||||
warnings: string[]
|
||||
errors: Record<string, string[]>
|
||||
provenance: Record<string, 'automatic' | 'mapped' | 'fixed' | 'manual'>
|
||||
tagSources?: Record<'automatic' | 'mapped' | 'fixed' | 'manual', string>
|
||||
status: 'ready' | 'warning' | 'error'
|
||||
existing: boolean }
|
||||
existing: boolean
|
||||
importStatus?: 'pending' | 'created' | 'skipped' | 'failed' }
|
||||
type ParsedImport = { columns: Column[], rows: { sourceRow: number, values: string[] }[] }
|
||||
type Phase = 'source' | 'mapping' | 'preview' | 'result'
|
||||
|
||||
@@ -172,18 +174,22 @@ const PostImportPage: FC<Props> = ({ user }) => {
|
||||
}
|
||||
|
||||
const submit = async () => {
|
||||
const targets = rows.filter (row => row.status !== 'error' && !(row.existing && existing === 'skip'))
|
||||
const targets = rows.filter (row => (row as ImportRow & { importStatus?: string }).importStatus !== 'created')
|
||||
if (targets.length === 0)
|
||||
return
|
||||
setLoading (true)
|
||||
try
|
||||
{
|
||||
const result = await apiPost<{ created: number, skipped: number, failed: number,
|
||||
rows: { sourceRow: number, status: string, post?: { id: number }, errors?: Record<string, string[]> }[] }> ('/posts/import', { rows: targets })
|
||||
rows: { sourceRow: number, status: string, post?: { id: number }, errors?: Record<string, string[]> }[] }> ('/posts/import', { rows: targets, existing })
|
||||
toast ({ title: `登録完了: ${result.created} 件`,
|
||||
description: `スキップ ${result.skipped} 件、失敗 ${result.failed} 件` })
|
||||
setPhase ('result')
|
||||
setResults (result.rows)
|
||||
setRows (current => current.map (row => {
|
||||
const resultRow = result.rows.find (_1 => _1.sourceRow === row.sourceRow)
|
||||
return resultRow ? { ...row, importStatus: resultRow.status } : row
|
||||
}))
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -304,14 +310,17 @@ const RowCard = ({ row, index, update, updateURL }: { row: ImportRow, index: num
|
||||
const EditableValue = ({ label, value, origin, onCommit }: { label: string, value: string, origin: string | undefined, onCommit: (value: string) => void }) => {
|
||||
const [editing, setEditing] = useState (false)
|
||||
const [draft, setDraft] = useState (value)
|
||||
const finished = useRef (false)
|
||||
useEffect (() => { if (!editing) setDraft (value) }, [editing, value])
|
||||
const originLabel = { automatic: '自動取得', mapped: '入力データ', fixed: '固定値', manual: '手修正' }[origin ?? 'automatic']
|
||||
const commit = () => { setEditing (false); if (draft !== value) onCommit (draft) }
|
||||
const cancel = () => { setDraft (value); setEditing (false) }
|
||||
const begin = () => { finished.current = false; setDraft (value); setEditing (true) }
|
||||
const commit = () => { if (finished.current) return; finished.current = true; setEditing (false); if (draft !== value) onCommit (draft) }
|
||||
const cancel = () => { if (finished.current) return; finished.current = true; setDraft (value); setEditing (false) }
|
||||
return <div className={origin === 'manual' ? 'rounded bg-amber-100 p-1 dark:bg-amber-900' : 'p-1'}>
|
||||
<span className="text-xs">{label}・{originLabel}</span>
|
||||
{editing ? <input autoFocus value={draft} onChange={ev => setDraft (ev.target.value)} onBlur={commit}
|
||||
onKeyDown={ev => { if (ev.key === 'Escape') cancel (); if (ev.key === 'Enter') commit () } } className={inputClass (false)}/>
|
||||
: <button type="button" className="block w-full text-left" onDoubleClick={() => setEditing (true)} onClick={() => setEditing (true)}>{value || '(未指定)'} 編輯</button>}
|
||||
onKeyDown={ev => { if (ev.key === 'Escape') cancel (); if (ev.key === 'Enter') { ev.preventDefault (); commit () } } } className={inputClass (false)}/>
|
||||
: <button type="button" className="block w-full text-left" onDoubleClick={begin} onClick={begin}>{value || '(未指定)'} 編輯</button>}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
新しい課題から参照
ユーザをブロックする