広場投稿追加画面の刷新 (#399) #413

マージ済み
みてるぞ が 103 個のコミットを feature/399 から main へマージ 2026-07-19 00:03:11 +09:00
2個のファイルの変更114行の追加99行の削除
コミット 2d2a9b4bd6 の変更だけを表示してゐます - すべてのコミットを表示
+4 -2
ファイルの表示
@@ -226,12 +226,14 @@ class Post < ApplicationRecord
end end
def self.sanitised_svg_bytes(bytes) def self.sanitised_svg_bytes(bytes)
parse_options =
Nokogiri::XML::ParseOptions::STRICT |
Nokogiri::XML::ParseOptions::NONET
document = Nokogiri::XML( document = Nokogiri::XML(
bytes, bytes,
nil, nil,
nil, nil,
Nokogiri::XML::ParseOptions::STRICT parse_options)
| Nokogiri::XML::ParseOptions::NONET)
root = document.root root = document.root
raise MiniMagick::Error, 'SVG が不正です.' if root == nil || root.name != 'svg' raise MiniMagick::Error, 'SVG が不正です.' if root == nil || root.name != 'svg'
raise MiniMagick::Error, 'SVG が不正です.' if document.internal_subset != nil raise MiniMagick::Error, 'SVG が不正です.' if document.internal_subset != nil
+28 -15
ファイルの表示
@@ -427,7 +427,8 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
: { duration: .2, ease: 'easeOut' as const } : { duration: .2, ease: 'easeOut' as const }
const [session, setSession] = useState<PostImportSession | null> (null) const [session, setSession] = useState<PostImportSession | null> (null)
const [loading, setLoading] = useState (false) const [metadataLoading, setMetadataLoading] = useState (false)
const [submitting, setSubmitting] = useState (false)
const [loadingRow, setLoadingRow] = useState<number | null> (null) const [loadingRow, setLoadingRow] = useState<number | null> (null)
const [editingRow, setEditingRow] = useState<PostImportRow | null> (null) const [editingRow, setEditingRow] = useState<PostImportRow | null> (null)
const [showExistingRows, setShowExistingRows] = useState (false) const [showExistingRows, setShowExistingRows] = useState (false)
@@ -490,7 +491,10 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
} }
const refreshRows = async (baseSession: PostImportSession) => { const refreshRows = async (baseSession: PostImportSession) => {
setLoading (true) if (active)
setMetadataLoading (true)
try
{
let nextIndex = 0 let nextIndex = 0
const previewErrors = new Map<number, Record<string, string[]>> () const previewErrors = new Map<number, Record<string, string[]>> ()
let workingRows = [...(sessionRef.current ?? baseSession).rows] let workingRows = [...(sessionRef.current ?? baseSession).rows]
@@ -569,10 +573,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
await Promise.all ( await Promise.all (
Array.from ({ length: Math.min (4, baseSession.rows.length) }, () => worker ())) Array.from ({ length: Math.min (4, baseSession.rows.length) }, () => worker ()))
if (!(active) || previewSequenceRef.current !== previewSequence) if (!(active) || previewSequenceRef.current !== previewSequence)
{
setLoading (false)
return return
}
const nextRows = applyDuplicateUrlErrors (workingRows.map (row => { const nextRows = applyDuplicateUrlErrors (workingRows.map (row => {
const rowErrors = previewErrors.get (row.sourceRow) const rowErrors = previewErrors.get (row.sourceRow)
@@ -584,7 +585,12 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
status: 'error' as const } status: 'error' as const }
})) }))
await persistSession (buildSession (nextRows)) await persistSession (buildSession (nextRows))
setLoading (false) }
finally
{
if (active)
setMetadataLoading (false)
}
} }
const hydrate = async () => { const hydrate = async () => {
@@ -643,7 +649,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
: rows : rows
const existingRows = sortedRows.filter (row => isExistingSkipRow (row)) const existingRows = sortedRows.filter (row => isExistingSkipRow (row))
const reviewRows = sortedRows.filter (row => !(isExistingSkipRow (row))) const reviewRows = sortedRows.filter (row => !(isExistingSkipRow (row)))
const busy = loading || loadingRow != null const busy = metadataLoading || submitting || loadingRow != null
const canSubmit = const canSubmit =
rows.every (row => isCompletedReviewRow (row)) rows.every (row => isCompletedReviewRow (row))
|| processableImportRows (rows).length > 0 || processableImportRows (rows).length > 0
@@ -856,7 +862,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
return return
} }
setLoading (true) setSubmitting (true)
try try
{ {
const processingRows = processableImportRows (currentSession.rows) const processingRows = processableImportRows (currentSession.rows)
@@ -887,7 +893,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
} }
finally finally
{ {
setLoading (false) setSubmitting (false)
} }
} }
@@ -968,26 +974,29 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
</MainArea> </MainArea>
<PostImportFooter <PostImportFooter
loading={busy} metadataLoading={metadataLoading}
submitting={submitting}
canSubmit={canSubmit} canSubmit={canSubmit}
creatableCount={counts.creatable} creatableCount={counts.creatable}
manualSkippedCount={counts.manualSkipped} manualSkippedCount={counts.manualSkipped}
existingSkippedCount={counts.existingSkipped} existingSkippedCount={counts.existingSkipped}
pendingOrErrorCount={counts.pendingOrError} pendingOrErrorCount={counts.pendingOrError}
onBack={() => navigate (-1)} onBack={() => navigate ('/posts/new')}
onSubmit={() => submit ()}/> onSubmit={() => submit ()}/>
</>) </>)
} }
const PostImportFooter = ( const PostImportFooter = (
{ loading, { metadataLoading,
submitting,
canSubmit, canSubmit,
creatableCount, creatableCount,
manualSkippedCount, manualSkippedCount,
existingSkippedCount, existingSkippedCount,
pendingOrErrorCount, pendingOrErrorCount,
onBack, onBack,
onSubmit }: { loading: boolean onSubmit }: { metadataLoading: boolean
submitting: boolean
canSubmit: boolean canSubmit: boolean
creatableCount: number creatableCount: number
manualSkippedCount: number manualSkippedCount: number
@@ -1008,13 +1017,17 @@ const PostImportFooter = (
<span> {pendingOrErrorCount}</span> <span> {pendingOrErrorCount}</span>
</div> </div>
<div className="flex flex-col gap-2 sm:flex-row"> <div className="flex flex-col gap-2 sm:flex-row">
<Button type="button" variant="outline" onClick={onBack} disabled={loading}> <Button
type="button"
variant="outline"
onClick={onBack}
disabled={submitting}>
URL URL
</Button> </Button>
<Button <Button
type="button" type="button"
onClick={onSubmit} onClick={onSubmit}
disabled={loading || !(canSubmit)}> disabled={metadataLoading || submitting || !(canSubmit)}>
{creatableCount > 1 ? '一括追加' : '追加'} {creatableCount > 1 ? '一括追加' : '追加'}
</Button> </Button>
</div> </div>