このコミットが含まれているのは:
@@ -175,13 +175,33 @@ export const mergeImportResults = (
|
||||
const resultMap = new Map (results.map (row => [row.sourceRow, row]))
|
||||
return rows.map (row => {
|
||||
const result = resultMap.get (row.sourceRow)
|
||||
return result
|
||||
? {
|
||||
if (result == null)
|
||||
return row
|
||||
|
||||
switch (result.status)
|
||||
{
|
||||
case 'created':
|
||||
return {
|
||||
...row,
|
||||
importStatus: result.status,
|
||||
importStatus: 'created',
|
||||
createdPostId: result.post?.id,
|
||||
existingPostId: undefined,
|
||||
importErrors: result.errors }
|
||||
: row
|
||||
case 'skipped':
|
||||
return {
|
||||
...row,
|
||||
importStatus: 'skipped',
|
||||
createdPostId: undefined,
|
||||
existingPostId: result.existingPostId,
|
||||
importErrors: result.errors }
|
||||
case 'failed':
|
||||
return {
|
||||
...row,
|
||||
importStatus: 'failed',
|
||||
createdPostId: undefined,
|
||||
existingPostId: undefined,
|
||||
importErrors: result.errors }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,17 @@ const SESSION_VERSION = 2
|
||||
const SESSION_PREFIX = 'post-import-session:'
|
||||
const SOURCE_DRAFT_KEY = 'post-import-source-draft'
|
||||
const SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1000
|
||||
const ATTRIBUTE_KEYS = [
|
||||
'title',
|
||||
'thumbnailBase',
|
||||
'originalCreatedFrom',
|
||||
'originalCreatedBefore',
|
||||
'duration',
|
||||
'videoMs',
|
||||
'tags',
|
||||
'parentPostIds'] as const
|
||||
const PROVENANCE_KEYS = [...ATTRIBUTE_KEYS, 'url'] as const
|
||||
const TAG_SOURCE_KEYS = ['automatic', 'manual'] as const
|
||||
|
||||
|
||||
const isPlainObject = (value: unknown): value is Record<string, unknown> =>
|
||||
@@ -120,6 +131,12 @@ const isValidSkipReason = (
|
||||
const isPositiveInteger = (value: unknown): value is number =>
|
||||
Number.isInteger (value) && Number (value) > 0
|
||||
|
||||
const hasOnlyKeys = (
|
||||
value: Record<string, unknown>,
|
||||
allowedKeys: readonly string[],
|
||||
): boolean =>
|
||||
Object.keys (value).every (key => allowedKeys.includes (key))
|
||||
|
||||
|
||||
const sanitiseRow = (value: unknown): PostImportRow | null => {
|
||||
if (!(isPlainObject (value)))
|
||||
@@ -163,6 +180,13 @@ const sanitiseRow = (value: unknown): PostImportRow | null => {
|
||||
return null
|
||||
|
||||
const provenanceEntries = Object.entries (value.provenance)
|
||||
if (!(hasOnlyKeys (value.attributes, ATTRIBUTE_KEYS)))
|
||||
return null
|
||||
if (!(Object.values (value.attributes).every (entry =>
|
||||
typeof entry === 'string' || typeof entry === 'number')))
|
||||
return null
|
||||
if (!(hasOnlyKeys (value.provenance, PROVENANCE_KEYS)))
|
||||
return null
|
||||
if (!(provenanceEntries.every (([, origin]) => isValidOrigin (origin))))
|
||||
return null
|
||||
|
||||
@@ -170,6 +194,8 @@ const sanitiseRow = (value: unknown): PostImportRow | null => {
|
||||
{
|
||||
if (!(isPlainObject (value.tagSources)))
|
||||
return null
|
||||
if (!(hasOnlyKeys (value.tagSources, TAG_SOURCE_KEYS)))
|
||||
return null
|
||||
if (!(Object.values (value.tagSources).every (_1 => typeof _1 === 'string')))
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -27,10 +27,11 @@ export type PostImportRow = {
|
||||
importStatus?: PostImportStatus }
|
||||
|
||||
export type PostImportResultRow = {
|
||||
sourceRow: number
|
||||
status: PostImportResultStatus
|
||||
post?: { id: number }
|
||||
errors?: Record<string, string[]> }
|
||||
sourceRow: number
|
||||
status: PostImportResultStatus
|
||||
post?: { id: number }
|
||||
existingPostId?: number
|
||||
errors?: Record<string, string[]> }
|
||||
|
||||
export type PostImportSession = {
|
||||
version: number
|
||||
|
||||
新しい課題から参照
ユーザをブロックする