このコミットが含まれているのは:
2026-07-18 00:01:12 +09:00
コミット ff970f8171
11個のファイルの変更449行の追加173行の削除
+77 -68
ファイルの表示
@@ -68,6 +68,7 @@ type PreviewResponse = {
thumbnailBase?: string
originalCreatedFrom?: string
originalCreatedBefore?: string
parentPostIds?: string
duration?: string
videoMs?: number
tags?: string
@@ -137,8 +138,7 @@ const mergeDryRunRow = (
currentRow: PostImportRow,
result: PreviewResponse,
): PostImportRow =>
applyThumbnailWarning (
initialisePreviewRows ([{
applyThumbnailWarning ({
...currentRow,
url: result.url,
attributes: {
@@ -150,7 +150,7 @@ const mergeDryRunRow = (
duration: result.duration ?? '',
videoMs: result.videoMs ?? '',
tags: result.tags ?? '',
parentPostIds: String (currentRow.attributes.parentPostIds ?? '') },
parentPostIds: String (result.parentPostIds ?? currentRow.attributes.parentPostIds ?? '') },
fieldWarnings: result.fieldWarnings ?? { },
baseWarnings: result.baseWarnings ?? [],
validationErrors: { },
@@ -167,7 +167,38 @@ const mergeDryRunRow = (
currentRow.importStatus === 'created'
? 'created'
: 'pending',
recoverable: undefined }])[0])
recoverable: undefined })
const buildPreviewResetSnapshot = (
preview: PreviewResponse,
): PostImportRow['resetSnapshot'] => ({
url: preview.url,
attributes: {
title: preview.title ?? '',
thumbnailBase: preview.thumbnailBase ?? '',
originalCreatedFrom: preview.originalCreatedFrom ?? '',
originalCreatedBefore: preview.originalCreatedBefore ?? '',
duration: preview.duration ?? '',
videoMs: preview.videoMs ?? '',
tags: preview.tags ?? '',
parentPostIds: String (preview.parentPostIds ?? '') },
provenance: {
url: 'manual',
title: 'automatic',
thumbnailBase: 'automatic',
originalCreatedFrom: 'automatic',
originalCreatedBefore: 'automatic',
duration: 'automatic',
videoMs: 'automatic',
tags: 'automatic',
parentPostIds: 'automatic' },
tagSources: {
automatic: preview.tags ?? '',
manual: '' },
fieldWarnings: preview.fieldWarnings ?? { },
baseWarnings: preview.baseWarnings ?? [],
metadataUrl: preview.url })
const indexedBulkResults = (
@@ -216,6 +247,9 @@ const mergePreviewRow = (
currentRow: PostImportRow,
preview: PreviewResponse,
): PostImportRow => {
const fieldWarnings = preview.fieldWarnings ?? { }
const baseWarnings = preview.baseWarnings ?? []
const metadataChanged = currentRow.metadataUrl !== preview.url
const nextRow: PostImportRow = {
...currentRow,
attributes: { ...currentRow.attributes },
@@ -224,8 +258,8 @@ const mergePreviewRow = (
automatic: currentRow.tagSources?.automatic ?? '',
manual: currentRow.tagSources?.manual ?? '' },
url: preview.url,
fieldWarnings: preview.fieldWarnings ?? { },
baseWarnings: preview.baseWarnings ?? [],
fieldWarnings,
baseWarnings,
existingPostId: preview.existingPost?.id,
existingPost: preview.existingPost ?? undefined,
skipReason:
@@ -234,9 +268,14 @@ const mergePreviewRow = (
: currentRow.skipReason === 'manual'
? 'manual'
: undefined,
metadataUrl: preview.url,
resetSnapshot:
metadataChanged
? buildPreviewResetSnapshot (preview)
: currentRow.resetSnapshot,
status:
Object.keys (preview.fieldWarnings ?? { }).length > 0
|| (preview.baseWarnings?.length ?? 0) > 0
Object.keys (fieldWarnings).length > 0
|| baseWarnings.length > 0
? 'warning'
: 'ready' }
@@ -251,8 +290,10 @@ const mergePreviewRow = (
if (currentRow.provenance.tags !== 'manual')
{
nextRow.attributes.tags = preview.tags ?? ''
nextRow.tagSources.automatic = preview.tags ?? ''
}
nextRow.tagSources.automatic = preview.tags ?? ''
if (currentRow.provenance.parentPostIds !== 'manual')
nextRow.attributes.parentPostIds = String (preview.parentPostIds ?? '')
if (currentRow.provenance.videoMs !== 'manual')
nextRow.attributes.videoMs = preview.videoMs ?? ''
if (currentRow.provenance.duration !== 'manual')
@@ -398,6 +439,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
const refreshRows = async (baseSession: PostImportSession) => {
let nextIndex = 0
const previews = new Map<number, PreviewResponse> ()
const worker = async () => {
while (active)
{
@@ -421,15 +463,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
signal: controller.signal })
if (!(active) || previewSequenceRef.current !== previewSequence)
return
const latestSession = sessionRef.current ?? baseSession
const currentRow = latestSession.rows.find (
row => row.sourceRow === baseRow.sourceRow)
if (currentRow == null)
continue
const mergedRow = mergePreviewRow (currentRow, preview)
await persistSession (buildSession (
replaceImportRow (latestSession.rows, mergedRow)))
previews.set (baseRow.sourceRow, preview)
}
catch (requestError)
{
@@ -437,11 +471,6 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
return
if (!(active) || previewSequenceRef.current !== previewSequence)
return
const latestSession = sessionRef.current ?? baseSession
const currentRow = latestSession.rows.find (
row => row.sourceRow === baseRow.sourceRow)
if (currentRow == null)
continue
if (!(isApiError (requestError)))
continue
}
@@ -454,6 +483,21 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
await Promise.all (
Array.from ({ length: Math.min (4, baseSession.rows.length) }, () => worker ()))
if (!(active) || previewSequenceRef.current !== previewSequence)
return
const latestSession = sessionRef.current ?? baseSession
const nextRows = latestSession.rows.map (row => {
const preview = previews.get (row.sourceRow)
if (preview == null
|| row.skipReason === 'manual'
|| row.importStatus === 'created'
|| row.importStatus === 'skipped'
|| isNonRecoverableFailedRow (row))
return row
return mergePreviewRow (row, preview)
})
await persistSession (buildSession (nextRows))
}
const hydrate = async () => {
@@ -494,7 +538,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
duration: preview.duration ?? '',
videoMs: preview.videoMs ?? '',
tags: preview.tags ?? '',
parentPostIds: '' },
parentPostIds: String (preview.parentPostIds ?? '') },
fieldWarnings: preview.fieldWarnings ?? { },
baseWarnings: preview.baseWarnings ?? [],
validationErrors: { },
@@ -529,7 +573,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
duration: preview.duration ?? '',
videoMs: preview.videoMs ?? '',
tags: preview.tags ?? '',
parentPostIds: '' },
parentPostIds: String (preview.parentPostIds ?? '') },
provenance: {
url: 'manual',
title: 'automatic',
@@ -544,7 +588,8 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
automatic: preview.tags ?? '',
manual: '' },
fieldWarnings: preview.fieldWarnings ?? { },
baseWarnings: preview.baseWarnings ?? [] } }])[0])]
baseWarnings: preview.baseWarnings ?? [],
metadataUrl: preview.url } }])[0])]
const persisted = await persistSession (buildSession (rows))
if (persisted == null)
return
@@ -557,10 +602,6 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
return
}
if (loadedSession == null)
{
await persistSession (loaded)
}
void refreshRows (loaded)
}
@@ -612,8 +653,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
if (row.sourceRow !== sourceRow)
return row
if (isExistingSkipRow (row)
|| row.importStatus === 'created'
|| isNonRecoverableFailedRow (row))
|| row.importStatus === 'created')
return row
return {
...row,
@@ -779,23 +819,8 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
const indexedResults = indexedBulkResults ([target], result.results)
const latestAfterImport = sessionRef.current ?? pendingSession
const mergedRows = mergeImportResults (latestAfterImport.rows, indexedResults)
const recoverableRows = indexedResults.filter (row =>
row.status === 'failed'
&& row.recoverable
&& Object.keys (row.errors ?? { }).length > 0)
const nextRows = mergedRows.map ((row): PostImportRow => {
const recoverable = recoverableRows.find (
failedRow => failedRow.sourceRow === row.sourceRow)
if (recoverable == null)
return applyThumbnailWarning (row)
return applyThumbnailWarning ({
...row,
importStatus: 'pending',
recoverable: true,
validationErrors: recoverable.errors ?? { },
importErrors: undefined })
})
const nextRows = mergeImportResults (latestAfterImport.rows, indexedResults)
.map (row => applyThumbnailWarning (row))
const persisted = await persistSession (buildSession (nextRows))
if (persisted != null
&& persisted.rows.every (row => isCompletedReviewRow (row)))
@@ -842,23 +867,8 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
const indexedResults = indexedBulkResults (processingRows, result.results)
const latestAfterImport = sessionRef.current ?? buildSession (currentSession.rows)
const mergedResults = mergeImportResults (latestAfterImport.rows, indexedResults)
const recoverableRows = indexedResults.filter (row =>
row.status === 'failed'
&& row.recoverable
&& Object.keys (row.errors ?? { }).length > 0)
const nextRows = mergedResults.map ((row): PostImportRow => {
const recoverable = recoverableRows.find (
failedRow => failedRow.sourceRow === row.sourceRow)
if (recoverable == null)
return applyThumbnailWarning (row)
return applyThumbnailWarning ({
...row,
importStatus: 'pending',
recoverable: true,
validationErrors: recoverable.errors ?? { },
importErrors: undefined })
})
const nextRows = mergeImportResults (latestAfterImport.rows, indexedResults)
.map (row => applyThumbnailWarning (row))
const persisted = await persistSession (buildSession (nextRows))
if (persisted != null
&& persisted.rows.every (row => isCompletedReviewRow (row)))
@@ -940,8 +950,7 @@ const PostImportReviewPage: FC<Props> = ({ user }) => {
skipDisabled={
busy
|| isExistingSkipRow (row)
|| row.importStatus === 'created'
|| isNonRecoverableFailedRow (row)}
|| row.importStatus === 'created'}
onEdit={() => editRow (row)}
onToggleSkip={checked => toggleManualSkip (row.sourceRow, checked)}
onRetry={canRetryResultRow (row) ? () => retry (row.sourceRow) : undefined}