このコミットが含まれているのは:
@@ -25,6 +25,31 @@ const ATTRIBUTE_KEYS = [
|
||||
const PROVENANCE_KEYS = [...ATTRIBUTE_KEYS, 'url'] as const
|
||||
const TAG_SOURCE_KEYS = ['automatic', 'manual'] as const
|
||||
const WARNING_KEYS = [...ATTRIBUTE_KEYS, 'url'] as const
|
||||
const ROW_KEYS = [
|
||||
'sourceRow',
|
||||
'url',
|
||||
'attributes',
|
||||
'fieldWarnings',
|
||||
'baseWarnings',
|
||||
'validationErrors',
|
||||
'importErrors',
|
||||
'provenance',
|
||||
'tagSources',
|
||||
'status',
|
||||
'skipReason',
|
||||
'existingPostId',
|
||||
'existingPost',
|
||||
'metadataUrl',
|
||||
'resetSnapshot',
|
||||
'createdPostId',
|
||||
'importStatus',
|
||||
'recoverable'] as const
|
||||
const SESSION_KEYS = [
|
||||
'version',
|
||||
'expiresAt',
|
||||
'source',
|
||||
'rows',
|
||||
'repairMode'] as const
|
||||
|
||||
|
||||
const isPlainObject = (value: unknown): value is Record<string, unknown> =>
|
||||
@@ -220,10 +245,110 @@ const sanitiseExistingPost = (value: unknown): PostImportExistingPost | undefine
|
||||
thumbnailUrl: value.thumbnailUrl as string | undefined }
|
||||
}
|
||||
|
||||
const recalculateThumbnailWarning = (row: PostImportRow): PostImportRow => {
|
||||
const others = (row.fieldWarnings.thumbnailBase ?? []).filter (
|
||||
key => key !== 'サムネールなし')
|
||||
const thumbnailBasePresent =
|
||||
typeof row.attributes.thumbnailBase === 'string'
|
||||
&& row.attributes.thumbnailBase.trim () !== ''
|
||||
|
||||
return {
|
||||
...row,
|
||||
fieldWarnings: {
|
||||
...row.fieldWarnings,
|
||||
thumbnailBase:
|
||||
thumbnailBasePresent
|
||||
? others
|
||||
: [...new Set ([...others, 'サムネールなし'])] } }
|
||||
}
|
||||
|
||||
const serialiseExistingPost = (value: PostImportExistingPost | undefined) =>
|
||||
value == null
|
||||
? undefined
|
||||
: {
|
||||
id: value.id,
|
||||
title: value.title,
|
||||
url: value.url,
|
||||
thumbnailUrl: value.thumbnailUrl }
|
||||
|
||||
const serialiseResetSnapshot = (value: PostImportResetSnapshot) => ({
|
||||
url: value.url,
|
||||
attributes: Object.fromEntries (
|
||||
Object.entries (value.attributes).map (([key, entry]) => [key, entry])),
|
||||
provenance: Object.fromEntries (
|
||||
Object.entries (value.provenance).map (([key, entry]) => [key, entry])),
|
||||
tagSources: {
|
||||
automatic: value.tagSources.automatic,
|
||||
manual: value.tagSources.manual },
|
||||
fieldWarnings: Object.fromEntries (
|
||||
Object.entries (value.fieldWarnings).map (([key, entry]) => [key, [...entry]])),
|
||||
baseWarnings: [...value.baseWarnings],
|
||||
metadataUrl: value.metadataUrl })
|
||||
|
||||
export const serialisePostImportRow = (row: PostImportRow) => {
|
||||
const thumbnailBaseWarnings = (() => {
|
||||
const others = (row.fieldWarnings.thumbnailBase ?? []).filter (
|
||||
message => message !== 'サムネールなし')
|
||||
const thumbnailBasePresent =
|
||||
typeof row.attributes.thumbnailBase === 'string'
|
||||
&& row.attributes.thumbnailBase.trim () !== ''
|
||||
return thumbnailBasePresent
|
||||
? others
|
||||
: [...new Set ([...others, 'サムネールなし'])]
|
||||
}) ()
|
||||
|
||||
return {
|
||||
sourceRow: row.sourceRow,
|
||||
url: row.url,
|
||||
attributes: Object.fromEntries (
|
||||
Object.entries (row.attributes).map (([key, entry]) => [key, entry])),
|
||||
fieldWarnings: Object.fromEntries (
|
||||
Object.entries ({
|
||||
...row.fieldWarnings,
|
||||
thumbnailBase: thumbnailBaseWarnings }).map (([key, entry]) => [key, [...entry]])),
|
||||
baseWarnings: [...row.baseWarnings],
|
||||
validationErrors: Object.fromEntries (
|
||||
Object.entries (row.validationErrors).map (([key, entry]) => [key, [...entry]])),
|
||||
importErrors:
|
||||
row.importErrors == null
|
||||
? undefined
|
||||
: Object.fromEntries (
|
||||
Object.entries (row.importErrors).map (([key, entry]) => [key, [...entry]])),
|
||||
provenance: Object.fromEntries (
|
||||
Object.entries (row.provenance).map (([key, entry]) => [key, entry])),
|
||||
tagSources:
|
||||
row.tagSources == null
|
||||
? undefined
|
||||
: {
|
||||
automatic: row.tagSources.automatic,
|
||||
manual: row.tagSources.manual },
|
||||
status: row.status,
|
||||
skipReason: row.skipReason,
|
||||
existingPostId: row.existingPostId,
|
||||
existingPost: serialiseExistingPost (row.existingPost),
|
||||
metadataUrl: row.metadataUrl,
|
||||
resetSnapshot: serialiseResetSnapshot (row.resetSnapshot),
|
||||
createdPostId: row.createdPostId,
|
||||
importStatus: row.importStatus,
|
||||
recoverable: row.recoverable }
|
||||
}
|
||||
|
||||
export const serialisePostImportRows = (rows: PostImportRow[]) =>
|
||||
rows.map (row => serialisePostImportRow (row))
|
||||
|
||||
export const serialisedPostImportRowsEqual = (
|
||||
left: PostImportRow[],
|
||||
right: PostImportRow[],
|
||||
): boolean =>
|
||||
JSON.stringify (serialisePostImportRows (left))
|
||||
=== JSON.stringify (serialisePostImportRows (right))
|
||||
|
||||
|
||||
const sanitiseRow = (value: unknown): PostImportRow | null => {
|
||||
if (!(isPlainObject (value)))
|
||||
return null
|
||||
if (!(hasOnlyKeys (value, ROW_KEYS)))
|
||||
return null
|
||||
if (!(Number.isInteger (value.sourceRow)) || Number (value.sourceRow) <= 0)
|
||||
return null
|
||||
if (typeof value.url !== 'string')
|
||||
@@ -321,6 +446,8 @@ const sanitiseRow = (value: unknown): PostImportRow | null => {
|
||||
const sanitiseSession = (value: unknown): PostImportSession | null => {
|
||||
if (!(isPlainObject (value)))
|
||||
return null
|
||||
if (!(hasOnlyKeys (value, SESSION_KEYS)))
|
||||
return null
|
||||
if (value.version !== SESSION_VERSION || !(Array.isArray (value.rows)))
|
||||
return null
|
||||
if (typeof value.expiresAt !== 'string' || isExpiredSession (value.expiresAt))
|
||||
@@ -334,7 +461,7 @@ const sanitiseSession = (value: unknown): PostImportSession | null => {
|
||||
version: SESSION_VERSION,
|
||||
expiresAt: value.expiresAt,
|
||||
source: typeof value.source === 'string' ? value.source : '',
|
||||
rows: rows as PostImportRow[],
|
||||
rows: (rows as PostImportRow[]).map (row => recalculateThumbnailWarning (row)),
|
||||
repairMode: value.repairMode === 'failed' ? 'failed' : 'all' }
|
||||
}
|
||||
|
||||
@@ -438,7 +565,9 @@ export const savePostImportSession = (
|
||||
return writeStorage (
|
||||
sessionKey (validatedId),
|
||||
JSON.stringify ({
|
||||
...session,
|
||||
source: session.source,
|
||||
rows: serialisePostImportRows (session.rows),
|
||||
repairMode: session.repairMode,
|
||||
version: SESSION_VERSION,
|
||||
expiresAt: new Date (Date.now () + SESSION_MAX_AGE_MS).toISOString () }),
|
||||
onError)
|
||||
|
||||
新しい課題から参照
ユーザをブロックする