diff --git a/api/src/constants/index.ts b/api/src/constants/index.ts index f7d0377e2..09806a3b2 100644 --- a/api/src/constants/index.ts +++ b/api/src/constants/index.ts @@ -326,3 +326,6 @@ export const RESERVED_FIELD_MAPPINGS: Record = { locale: 'cm_locale', // Add other reserved fields if needed }; + +export const MEDIA_BLOCK_NAMES = ['core/image', 'core/video', 'core/audio', 'core/file']; +export const WORDPRESS_MISSSING_BLOCKS = 'core/missing'; \ No newline at end of file diff --git a/api/src/services/contentful.service.ts b/api/src/services/contentful.service.ts index 611efd67d..37af61b8b 100644 --- a/api/src/services/contentful.service.ts +++ b/api/src/services/contentful.service.ts @@ -99,6 +99,36 @@ const mapLocales = ({ masterLocale, locale, locales, isNull = false }: any) => { } } +function resolveEntryFieldKey(entry: Record, baseKey: string): string | undefined { + if (baseKey in entry) return baseKey; + const snake = baseKey.replace(/([A-Z])/g, (m) => `_${m.toLowerCase()}`); + if (snake in entry) return snake; + return undefined; +} + +/** + * Maps Contentful content type id → field id → whether that field is localized in the export schema. + * Used so we only fan out values for fields with `localized: false`, not for localized fields that + * happen to have a single locale in the entry (missing translations). + */ +function buildContentfulFieldLocalizedByContentType( + contentTypesFromPackage: any[] +): Map> { + const byCt = new Map>(); + for (const ct of contentTypesFromPackage ?? []) { + const ctId = ct?.sys?.id; + if (!ctId) continue; + const byField = new Map(); + for (const f of ct?.fields ?? []) { + if (f?.id != null) { + byField.set(f.id, f.localized === true); + } + } + byCt.set(ctId, byField); + } + return byCt; +} + const transformCloudinaryObject = (input: any) => { const result: any = []; if (!Array.isArray(input)) { @@ -777,6 +807,7 @@ const createEntry = async (packagePath: any, destination_stack_id: string, proje const data = await fs.promises.readFile(packagePath, "utf8"); const entries = JSON.parse(data)?.entries; const content = JSON.parse(data)?.contentTypes; + const cfFieldLocalizedByCt = buildContentfulFieldLocalizedByContentType(content); const LocaleMapper = { masterLocale: project?.master_locale ?? LOCALE_MAPPER?.masterLocale, ...project?.locales ?? {} }; if (entries && entries.length > 0) { const assetId = await readFile(assetsSave, ASSETS_SCHEMA_FILE) ?? []; @@ -814,7 +845,7 @@ const createEntry = async (packagePath: any, destination_stack_id: string, proje entryData[name][lang] ??= {}; entryData[name][lang][id] ??= {}; locales.push(lang); - const fieldData = currentCT?.fieldMapping?.find?.((item: any) => (key === item?.uid) && (!["text", "url"]?.includes?.(item?.backupFieldType))); + const fieldData = currentCT?.fieldMapping?.find?.((item: any) => key === item?.uid); const newId = fieldData?.contentstackFieldUid ?? `${key}`?.replace?.(/[^a-zA-Z0-9]+/g, "_"); entryData[name][lang][id][newId] = processField( langValue, @@ -860,6 +891,44 @@ const createEntry = async (packagePath: any, destination_stack_id: string, proje ); }); }); + + // Non-localized Contentful fields (`localized: false` in the content type) only appear under + // one locale in exports. Copy them to every other locale branch so each slice is complete. + // Do not infer non-localized-ness from a single locale key — localized fields can legitimately + // have only one locale when translations are missing. + const entryLocaleKeys = new Set(); + for (const [, v] of Object?.entries?.(fields)) { + for (const lang of Object.keys(v as object)) { + entryLocaleKeys.add(lang); + } + } + const ct = contentTypes?.find((c: any) => c?.otherCmsUid === name); + for (const [key, value] of Object?.entries?.(fields)) { + const langs = Object?.keys(value as object); + if (langs?.length !== 1) continue; + const fd = ct?.fieldMapping?.find?.((item: any) => key === item?.uid); + const localizedInCf = cfFieldLocalizedByCt.get(name)?.get(key); + const explicitlyNonLocalized = + localizedInCf === false || + (localizedInCf === undefined && fd?.advanced?.nonLocalizable === true); + if (!explicitlyNonLocalized) continue; + const srcLang = langs[0]; + const newId = fd?.contentstackFieldUid ?? `${key}`?.replace?.(/[^a-zA-Z0-9]+/g, "_"); + const srcEntry = entryData[name][srcLang]?.[id] as Record | undefined; + if (!srcEntry) continue; + const fk = resolveEntryFieldKey(srcEntry, newId); + if (fk === undefined) continue; + for (const tgtLang of entryLocaleKeys) { + if (tgtLang === srcLang) continue; + entryData[name][tgtLang] ??= {}; + entryData[name][tgtLang][id] ??= {}; + const tgt = entryData[name][tgtLang][id] as Record; + if (tgt[fk] === undefined) { + tgt[fk] = srcEntry[fk]; + } + } + } + return entryData; }, {} @@ -867,11 +936,28 @@ const createEntry = async (packagePath: any, destination_stack_id: string, proje for await (const [newKey, values] of Object.entries(result)) { const currentCT = contentTypes?.find((ct: any) => ct?.otherCmsUid === newKey); const ctName = currentCT?.contentstackUid in mapperKeys ? - mapperKeys?.[currentCT?.contentstackUid] : (currentCT?.contentstackUid ?? newKey.replace(/([A-Z])/g, "_$1").toLowerCase()); - for await (const [localeKey, localeValues] of Object.entries( - values as { [key: string]: any } - )) { - const localeCode = mapLocales({ masterLocale: master_locale, locale: localeKey, locales: LocaleMapper, isNull: true }); + mapperKeys?.[currentCT?.contentstackUid] : (currentCT?.contentstackUid ?? newKey?.replace?.(/([A-Z])/g, "_$1")?.toLowerCase?.()); + const valuesByCfLocale = values as { [key: string]: { [uid: string]: Record } }; + const mergedByDestinationLocale: { [localeCode: string]: { [uid: string]: Record } } = {}; + for (const localeKey of Object.keys(valuesByCfLocale)) { + const localeValues = valuesByCfLocale[localeKey]; + if (!localeValues) continue; + const localeCode = mapLocales({ + masterLocale: master_locale, + locale: localeKey, + locales: LocaleMapper, + isNull: true, + }); + if (!localeCode) continue; + mergedByDestinationLocale[localeCode] ??= {}; + for (const [uid, entry] of Object.entries(localeValues)) { + mergedByDestinationLocale[localeCode][uid] = { + ...(mergedByDestinationLocale[localeCode][uid] ?? {}), + ...(entry ?? {}), + }; + } + } + for await (const [localeCode, localeValues] of Object.entries(mergedByDestinationLocale)) { const chunks = makeChunks(localeValues); for (const [entryKey, entryValue] of Object.entries(localeValues)) { const message = getLogMessage( @@ -883,18 +969,12 @@ const createEntry = async (packagePath: any, destination_stack_id: string, proje } const refs: { [key: string]: any } = {}; let chunkIndex = 1; - if (localeCode) { - const filePath = path.join( - entriesSave, - ctName, - localeCode - ); - for await (const [chunkId, chunkData] of Object.entries(chunks)) { - refs[chunkIndex++] = `${chunkId}-entries.json`; - await writeFile(filePath, `${chunkId}-entries.json`, chunkData); - } - await writeFile(filePath, ENTRIES_MASTER_FILE, refs); + const filePath = path.join(entriesSave, ctName, localeCode); + for await (const [chunkId, chunkData] of Object.entries(chunks)) { + refs[chunkIndex++] = `${chunkId}-entries.json`; + await writeFile(filePath, `${chunkId}-entries.json`, chunkData); } + await writeFile(filePath, ENTRIES_MASTER_FILE, refs); } } } else { diff --git a/api/src/services/wordpress.service.ts b/api/src/services/wordpress.service.ts index 5bd6058d2..bfaac3f37 100644 --- a/api/src/services/wordpress.service.ts +++ b/api/src/services/wordpress.service.ts @@ -14,6 +14,7 @@ import { orgService } from "./org.service.js"; import * as cheerio from 'cheerio'; import { setupWordPressBlocks, stripHtmlTags } from "../utils/wordpressParseUtil.js"; import { getMimeTypeFromExtension } from "../utils/mimeTypes.js"; +import { MEDIA_BLOCK_NAMES, WORDPRESS_MISSSING_BLOCKS } from "../constants/index.js"; const { JSDOM } = jsdom; @@ -124,6 +125,16 @@ function getLastUid(uid : string) { return uid?.split?.('.')?.[uid?.split?.('.')?.length - 1]; } + +const resolvedBlockName = (block: any) => { + if (block?.attrs?.metadata?.name) return block?.attrs?.metadata?.name; + if (block?.blockName === WORDPRESS_MISSSING_BLOCKS) { + return block?.attrs?.originalName || 'body'; + } + if (MEDIA_BLOCK_NAMES?.includes?.(block?.blockName)) return 'media'; + return block?.blockName; +} + async function createSchema(fields: any, blockJson : any, title: string, uid: string, assetData: any, duplicateBlockMappings?: Record) { const schema : any = { title: title, @@ -159,13 +170,13 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st // Process each block in blockJson to see if it matches any modular block child for (const block of blockJson) { try { - const blockName = (block?.attrs?.metadata?.name?.toLowerCase() || getFieldName(block?.blockName?.toLowerCase())); + const blockName = getFieldName(resolvedBlockName(block)); // Find which modular block child this block matches let matchingChildField = fields.find((childField: any) => { - const fieldName = childField?.otherCmsField?.toLowerCase() ; - - return (childField?.contentstackFieldType !== 'modular_blocks_child') && (blockName === fieldName) + const fieldName = childField?.otherCmsField?.toLowerCase(); + const fieldType = childField?.otherCmsType?.toLowerCase(); + return (childField?.contentstackFieldType !== 'modular_blocks_child') && (blockName === fieldName || blockName === fieldType) }); let matchingModularBlockChild = modularBlockChildren.find((childField: any) => { @@ -187,7 +198,8 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st //if (!matchingChildField) { matchingChildField = fields.find((childField: any) => { const fieldName = childField?.otherCmsField?.toLowerCase(); - return (childField?.contentstackFieldType !== 'modular_blocks_child') && (mappedName === fieldName); + const fieldType = childField?.otherCmsType?.toLowerCase(); + return (childField?.contentstackFieldType !== 'modular_blocks_child') && (mappedName === fieldName || mappedName === fieldType); }); // } @@ -206,12 +218,13 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st const childFieldUid = matchingModularBlockChild?.contentstackFieldUid || getLastUid(matchingModularBlockChild?.contentstackUid); const childField = fields.find((f: any) => { const fUid = f?.contentstackFieldUid || ''; - const fOtherCmsField = f?.otherCmsType?.toLowerCase(); - const childBlockName = matchingChildField ? matchingChildField?.otherCmsField?.toLowerCase() : (child?.attrs?.metadata?.name?.toLowerCase() || getFieldName(child?.blockName?.toLowerCase())); + const fOtherCmsType = f?.otherCmsType?.toLowerCase(); + const fOtherCmsField = f?.otherCmsField?.toLowerCase(); + const childBlockName = matchingChildField ? matchingChildField?.otherCmsField?.toLowerCase() : (getFieldName(resolvedBlockName(child))?.toLowerCase() || getFieldName(resolvedBlockName(child)?.toLowerCase())); const childKey = getLastUid(f?.contentstackFieldUid); const alreadyPopulated = childrenObject[childKey] !== undefined && childrenObject[childKey] !== null; return fUid.startsWith(childFieldUid + '.') && - (fOtherCmsField === childBlockName) && (!alreadyPopulated || f?.advanced?.multiple === true); + (fOtherCmsType === childBlockName || fOtherCmsField === childBlockName) && (!alreadyPopulated || f?.advanced?.multiple === true); }); if (childField) { @@ -313,8 +326,9 @@ function processNestedGroup(child: any, childField: any, allFields: any[]): Reco child?.innerBlocks?.forEach((nestedChild: any, nestedIndex: number) => { try { + const nestedBlockName = (getFieldName(resolvedBlockName(nestedChild))?.toLowerCase() ?? getFieldName(resolvedBlockName(nestedChild)?.toLowerCase()))?.toLowerCase(); const nestedChildField = nestedFields?.find((field: any) => - field?.otherCmsType?.toLowerCase() === (nestedChild?.attrs?.metadata?.name?.toLowerCase() ?? getFieldName(nestedChild?.blockName?.toLowerCase()))?.toLowerCase() && !nestedChildrenObject[getLastUid(field?.contentstackFieldUid)]?.length + (field?.otherCmsType?.toLowerCase() === nestedBlockName || field?.otherCmsField?.toLowerCase() === nestedBlockName) && !nestedChildrenObject[getLastUid(field?.contentstackFieldUid)]?.length ); if (!nestedChildField) { @@ -387,7 +401,7 @@ function formatChildByType(child: any, field: any, assetData: any) { // Process attributes based on field type configuration //if (child?.attributes && typeof child.attributes === 'object') { - const attrKey = getFieldName(child?.attr?.metadata?.name?.toLowerCase() || child?.blockName?.toLowerCase()); + const attrKey = getFieldName(getFieldName(resolvedBlockName(child))?.toLowerCase() || getFieldName(resolvedBlockName(child)?.toLowerCase())); try { const attrValue = child?.attrs?.innerHTML; @@ -477,6 +491,10 @@ function formatChildByType(child: any, field: any, assetData: any) { formatted = asset; break; } + + case 'markdown': + formatted = stripHtmlTags(child?.innerHTML); + break; default: // Default formatting - preserve original structure with null check formatted = attrValue; @@ -580,6 +598,7 @@ async function saveEntry(fields: any, entry: any, file_path: string, assetData // Extract individual content encoded for this specific item const contentEncoded = $(xmlItem)?.find("content\\:encoded")?.text() || ''; const blocksJson = await setupWordPressBlocks(contentEncoded); + customLogger(project?.id, destinationStackId,'info', `Processed blocks for entry ${uid}`); diff --git a/ui/package-lock.json b/ui/package-lock.json index e6f6b801a..5a7bd8081 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -29,7 +29,7 @@ "sass": "^1.68.0", "socket.io-client": "^4.7.5", "typescript": "^4.9.5", - "vite": "^7.3.1", + "vite": "^7.3.2", "vite-tsconfig-paths": "^6.1.1" }, "devDependencies": { @@ -9094,9 +9094,10 @@ } }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "license": "MIT", "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", diff --git a/ui/package.json b/ui/package.json index 5339c3e1f..52f916eea 100644 --- a/ui/package.json +++ b/ui/package.json @@ -24,7 +24,7 @@ "sass": "^1.68.0", "socket.io-client": "^4.7.5", "typescript": "^4.9.5", - "vite": "^7.3.1", + "vite": "^7.3.2", "vite-tsconfig-paths": "^6.1.1" }, "scripts": { diff --git a/ui/src/components/Common/AddStack/addStack.tsx b/ui/src/components/Common/AddStack/addStack.tsx index 2d206bd90..99798ea50 100644 --- a/ui/src/components/Common/AddStack/addStack.tsx +++ b/ui/src/components/Common/AddStack/addStack.tsx @@ -56,7 +56,7 @@ const AddStack = (props: any): JSX.Element => { locale: formData?.locale?.value || props?.defaultValues?.locale }); - if (resp) { + if (resp === true) { Notification({ notificationContent: { text: 'Stack created successfully' }, notificationProps: { @@ -67,8 +67,9 @@ const AddStack = (props: any): JSX.Element => { }); props?.closeModal(); } else { + Notification({ - notificationContent: { text: 'Stack creation failed. Please try again.' }, + notificationContent: { text: resp }, notificationProps: { position: 'bottom-center', hideProgressBar: true diff --git a/ui/src/components/ContentMapper/index.tsx b/ui/src/components/ContentMapper/index.tsx index 4b22641ce..0798e395f 100644 --- a/ui/src/components/ContentMapper/index.tsx +++ b/ui/src/components/ContentMapper/index.tsx @@ -230,7 +230,7 @@ const Fields: MappingFields = { 'taxonomy':{ label: 'Taxonomy', options: {'Taxonomy':'taxonomy'}, - type:'taxonomy' + type:'' } } type contentMapperProps = { diff --git a/ui/src/components/DestinationStack/Actions/LoadStacks.tsx b/ui/src/components/DestinationStack/Actions/LoadStacks.tsx index 89dc581e3..e52284c24 100644 --- a/ui/src/components/DestinationStack/Actions/LoadStacks.tsx +++ b/ui/src/components/DestinationStack/Actions/LoadStacks.tsx @@ -35,6 +35,15 @@ interface LoadFileFormatProps { handleStepChange: (stepIndex: number, closeStep?: boolean) => void; } +interface ErrorObject { + error_message?: string; + errors?: Errors; +} +interface Errors { + org_uid?: string[]; +} + + const defaultStack = { description: 'Created from Migration Destination Stack Step', locale: '', @@ -108,6 +117,21 @@ const LoadStacks = (props: LoadFileFormatProps) => { // setAllStack(newMigrationData?.destination_stack?.stackArray) }, [newMigrationData?.destination_stack?.selectedStack]); + /** + * Function to format the error message + */ + const formatErrorMessage = (errorData: ErrorObject) => { + let message = errorData.error_message; + + if (errorData.errors) { + Object.entries(errorData.errors).forEach(([key, value]) => { + message += `\n${key}: ${(value as string[]).join(", ")}`; + }); + } + + return message; + } + //Handle new stack details const handleOnSave = async (data: Stack) => { try { @@ -159,8 +183,12 @@ const LoadStacks = (props: LoadFileFormatProps) => { setIsStackLoading(false); return true; } - } catch (error) { - return error; + else { + const errorMessage = formatErrorMessage(resp?.data?.data); + return errorMessage; + } + } catch (error: any) { + return error?.response?.data; } }; diff --git a/ui/src/components/LegacyCms/Actions/LoadPrefix.tsx b/ui/src/components/LegacyCms/Actions/LoadPrefix.tsx index 29369aac5..d9e4e9eee 100644 --- a/ui/src/components/LegacyCms/Actions/LoadPrefix.tsx +++ b/ui/src/components/LegacyCms/Actions/LoadPrefix.tsx @@ -106,23 +106,7 @@ const LoadPreFix = (props: LoadSelectCmsProps) => { } }); - const handleOnBlur = (value: string) => { - if (isEmptyString(value?.trim())) { - setIsError(false); - setErrorMessage(''); - setIsRestrictedKey(false); - setPrefix('cs'); - const newMigrationDataObj: INewMigration = { - ...newMigrationData, - legacy_cms: { - ...newMigrationData?.legacy_cms, - affix: 'cs', - isRestictedKeywordCheckboxChecked: isCheckedBoxChecked - } - }; - dispatch(updateNewMigrationData(newMigrationDataObj)); - } - }; + /**** ALL USEEffects HERE ****/ @@ -144,9 +128,7 @@ const LoadPreFix = (props: LoadSelectCmsProps) => { aria-label="affix" disabled={newMigrationData?.legacy_cms?.uploadedFile?.isValidated} isReadOnly={newMigrationData?.legacy_cms?.uploadedFile?.isValidated} - onBlur={(e: React.FocusEvent) => { - handleOnBlur(e.target.value); - }} + /> {isError &&

{errorMessage}

} diff --git a/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx b/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx index 6008eba64..f6a1ef67f 100644 --- a/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx +++ b/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx @@ -536,7 +536,7 @@ const LoadUploadFile = ( props: LoadUploadFileProps ) => { setValidationMessage( '' ); } - if ( !newMigrationData?.legacy_cms?.uploadedFile?.isValidated && !newMigrationData?.legacy_cms?.uploadedFile?.reValidate ) + if (!isEmptyString(newMigrationData?.legacy_cms?.affix) && !newMigrationData?.legacy_cms?.uploadedFile?.isValidated && !newMigrationData?.legacy_cms?.uploadedFile?.reValidate ) { setIsDisabled( false ); } @@ -630,7 +630,7 @@ const LoadUploadFile = ( props: LoadUploadFileProps ) => isLoading={ isLoading } loadingColor="#6c5ce7" version="v2" - disabled={ !( reValidate || ( !isDisabled ) ) } + disabled={!(reValidate || (!isDisabled && !isEmptyString(newMigrationData?.legacy_cms?.affix)))} > { fileFormat?.toLowerCase() === 'sql' ? 'Check Connection' : 'File Validate' } diff --git a/ui/src/components/LegacyCms/index.tsx b/ui/src/components/LegacyCms/index.tsx index 0e3a1b202..35275e0b8 100644 --- a/ui/src/components/LegacyCms/index.tsx +++ b/ui/src/components/LegacyCms/index.tsx @@ -198,11 +198,12 @@ const LegacyCMSComponent = forwardRef(({ legacyCMSData, isCompleted, handleOnAll //Make Step 2 complete if ( !isEmptyString(newMigrationData?.legacy_cms?.selectedCms?.cms_id) + && !isEmptyString(newMigrationData?.legacy_cms?.affix) ) { setInternalActiveStepIndex(1); } - if(!isEmptyString(newMigrationData?.legacy_cms?.selectedCms?.cms_id) && newMigrationData?.legacy_cms?.uploadedFile?.isValidated){ + if(!isEmptyString(newMigrationData?.legacy_cms?.selectedCms?.cms_id) && newMigrationData?.legacy_cms?.uploadedFile?.isValidated && !isEmptyString(newMigrationData?.legacy_cms?.affix)){ setInternalActiveStepIndex(3); } setisProjectMapped(newMigrationData?.isprojectMapped) @@ -212,7 +213,7 @@ const LegacyCMSComponent = forwardRef(({ legacyCMSData, isCompleted, handleOnAll useEffect(()=>{ if( !isEmptyString(newMigrationData?.legacy_cms?.selectedFileFormat?.title) && ! isEmptyString(newMigrationData?.legacy_cms?.selectedCms?.title) && - newMigrationData?.legacy_cms?.uploadedFile?.isValidated){ + newMigrationData?.legacy_cms?.uploadedFile?.isValidated && !isEmptyString(newMigrationData?.legacy_cms?.affix) && !isEmptyString(newMigrationData?.legacy_cms?.selectedFileFormat?.fileformat_id)){ setIsAllStepsCompleted(true); handleAllStepsComplete(true); } diff --git a/upload-api/migration-wordpress/libs/extractItems.ts b/upload-api/migration-wordpress/libs/extractItems.ts index e368720ee..da0948bfc 100644 --- a/upload-api/migration-wordpress/libs/extractItems.ts +++ b/upload-api/migration-wordpress/libs/extractItems.ts @@ -15,7 +15,9 @@ const MEDIA_BLOCK_NAMES = ['core/image', 'core/video', 'core/audio', 'core/file' function resolveBlockName(field: any): string { if (field?.attributes?.metadata?.name) return field.attributes.metadata.name; - if (field?.name === 'core/missing') return 'body'; + if (field?.name === 'core/missing') { + return field?.attributes?.originalName || 'body'; + } if (MEDIA_BLOCK_NAMES.includes(field?.name)) return 'media'; return field?.name; } @@ -73,6 +75,12 @@ function isSameStructure(obj1: any, obj2: any): boolean { return false; } + if (obj1?.name === 'core/missing' && obj2?.name === 'core/missing') { + if (obj1?.attributes?.originalName !== obj2?.attributes?.originalName) { + return false; + } + } + if (Array?.isArray(obj1?.innerBlocks) || Array.isArray(obj2?.innerBlocks)) { if (!Array.isArray(obj1?.innerBlocks) || !Array.isArray(obj2?.innerBlocks)) { diff --git a/upload-api/migration-wordpress/libs/schemaMapper.ts b/upload-api/migration-wordpress/libs/schemaMapper.ts index 6fe013001..25328fad0 100644 --- a/upload-api/migration-wordpress/libs/schemaMapper.ts +++ b/upload-api/migration-wordpress/libs/schemaMapper.ts @@ -6,7 +6,9 @@ const MEDIA_BLOCK_NAMES = ['core/image', 'core/video', 'core/audio', 'core/file' function resolveBlockName(key: any): string { if (key?.attributes?.metadata?.name) return key.attributes.metadata.name; - if (key?.name === 'core/missing') return 'body'; + if (key?.name === 'core/missing') { + return key?.attributes?.originalName || 'body'; + } if (MEDIA_BLOCK_NAMES.includes(key?.name)) return 'media'; return key?.name; } @@ -195,7 +197,7 @@ async function schemaMapper (key: WordPressBlock | WordPressBlock[], parentUid: case 'core/pullquote': case 'core/table': case 'core/columns': - case 'core/missing': + case 'core/verse': case 'core/code': { const rteUid = parentUid ? @@ -213,6 +215,35 @@ async function schemaMapper (key: WordPressBlock | WordPressBlock[], parentUid: advanced: {} }; } + case 'core/missing': + const rteUid = parentUid ? + `${parentUid}.${getFieldUid(`${key?.name}_${key?.clientId}`, affix)}` + : getFieldUid(`${key?.name}_${key?.clientId}`, affix); + if(key?.attributes?.originalName === 'jetpack/markdown'){ + return { + uid: rteUid, + otherCmsField: getFieldName(resolveBlockName(key)), + otherCmsType: getFieldName(resolveBlockName(key)), + contentstackField: fieldName , + contentstackFieldUid: rteUid, + contentstackFieldType: 'markdown', + backupFieldType: 'markdown', + backupFieldUid: rteUid, + advanced: {} + }; + }else{ + return { + uid: rteUid, + otherCmsField: getFieldName(resolveBlockName(key)), + otherCmsType:getFieldName( resolveBlockName(key) ?? resolveBlockName(key)), + contentstackField: fieldName , + contentstackFieldUid: rteUid, + contentstackFieldType: 'json', + backupFieldType: 'json', + backupFieldUid: rteUid, + advanced: {} + }; + } case 'core/image': case 'core/audio': case 'core/video': @@ -297,7 +328,7 @@ async function schemaMapper (key: WordPressBlock | WordPressBlock[], parentUid: }); if(innerBlocks?.length > 0 ){ - innerBlocks.forEach(schemaObj => { + innerBlocks?.forEach(schemaObj => { if (schemaObj) { if (Array.isArray(schemaObj)) { groupSchema.push(...schemaObj); @@ -310,13 +341,15 @@ async function schemaMapper (key: WordPressBlock | WordPressBlock[], parentUid: return groupSchema; } + break; } case 'core/search': { const searchEleUid = parentUid ? `${parentUid}.${getFieldUid(`${key?.name}_${key?.clientId}`, affix)}` : getFieldUid(`${key?.name}_${key?.clientId}`, affix); const searchEle = await processAttributes(key, searchEleUid,fieldName, affix); - searchEle.push({ + const groupSchema: Field[] = []; + searchEle?.length > 0 && groupSchema?.push({ uid: searchEleUid, otherCmsField: getFieldName(key?.name), otherCmsType: getFieldName(key?.attributes?.metadata?.name ?? key?.name), @@ -326,7 +359,16 @@ async function schemaMapper (key: WordPressBlock | WordPressBlock[], parentUid: backupFieldType: 'group', backupFieldUid: searchEleUid, }); - return searchEle; + searchEle?.length > 0 && searchEle?.forEach(schemaObj => { + if (schemaObj) { + if (Array.isArray(schemaObj)) { + groupSchema?.push?.(...schemaObj); + } else { + groupSchema?.push?.({...schemaObj}); + } + } + }); + return groupSchema; }