From 4132cb19028f283df9b469c0195b589b2c9c1bfa Mon Sep 17 00:00:00 2001 From: Sayali Joshi Date: Thu, 2 Jan 2025 18:52:35 +0530 Subject: [PATCH 1/7] [CMG-440] - Migration execution | when migration process is in progress and then we should not be able to create new project. and CSS added for the selected card --- .../components/Common/Card/card.interface.ts | 2 + ui/src/components/Common/Card/card.scss | 9 +- ui/src/components/Common/Card/card.tsx | 40 ++++---- ui/src/components/LogScreen/index.tsx | 6 +- ui/src/components/ProjectsHeader/index.tsx | 94 +++++++------------ ui/src/components/TestMigration/index.tsx | 21 +---- ui/src/pages/Projects/projects.interface.ts | 2 + ui/src/utilities/constants.interface.ts | 4 + ui/src/utilities/functions.ts | 13 ++- 9 files changed, 94 insertions(+), 97 deletions(-) diff --git a/ui/src/components/Common/Card/card.interface.ts b/ui/src/components/Common/Card/card.interface.ts index db2068ec0..a756ca542 100644 --- a/ui/src/components/Common/Card/card.interface.ts +++ b/ui/src/components/Common/Card/card.interface.ts @@ -26,6 +26,8 @@ export interface ICardType { * The file format ID of the card. */ fileformat_id?: string; + + [key: string]: any; } /** diff --git a/ui/src/components/Common/Card/card.scss b/ui/src/components/Common/Card/card.scss index e3dcbd605..12589a8c1 100644 --- a/ui/src/components/Common/Card/card.scss +++ b/ui/src/components/Common/Card/card.scss @@ -76,10 +76,17 @@ * @cssproperty box-shadow - The box shadow effect to apply. * @cssvalue 0 3px $px-5 $px-2 rgb(215 215 215) - The specific box shadow values. */ -.connector_list:hover { + .connector_list:hover { box-shadow: 0 3px $px-5 $px-2 rgb(215 215 215); } +.connector_list.disabled-card { + &:hover { + box-shadow: none; + cursor: not-allowed; + } +} + /** * Styles for the service icon in the card component. * diff --git a/ui/src/components/Common/Card/card.tsx b/ui/src/components/Common/Card/card.tsx index 0be5b932b..9c8d5c143 100644 --- a/ui/src/components/Common/Card/card.tsx +++ b/ui/src/components/Common/Card/card.tsx @@ -1,19 +1,25 @@ +// Libraries import { Icon, Paragraph, Radio, Tooltip } from '@contentstack/venus-components'; import { MouseEvent, useState } from 'react'; -import WordWrapper from '../WordWrapper/WordWrapper'; -import { addDomainInPath } from '../../../utilities/functions'; +import { useSelector } from 'react-redux'; +// Redux Store +import { RootState } from '../../../store'; + +// Interface +import { ICardType } from './card.interface'; + +// CSS import './card.scss'; /** * Props for the Card component. */ type CardProps = { - data: any; + data: ICardType; idField?: string; onCardClick?: (T: any) => unknown; - selectedCard: any; - cardType?: string; + selectedCard: ICardType; }; /** @@ -25,17 +31,17 @@ type CardProps = { * @param cardType - The type of the card. * @param idField - The field name for the card's ID. Defaults to 'id'. */ -const Card = ({ data, selectedCard, onCardClick, cardType, idField = 'id' }: CardProps) => { - const imgStyle = { - width: cardType === 'legacyCMS' ? '60px' : '46px', - height: cardType === 'legacyCMS' ? '60px' : '46px' - }; +const Card = ({ data, selectedCard, onCardClick, idField = 'id' }: CardProps) => { const [isHovered, setIsHovered] = useState(false); + const newMigrationData = useSelector((state:RootState)=>state?.migration?.newMigrationData); + const handleMouseEnter = () => { - if (selectedCard[idField] === data?.[idField]) { - setIsHovered(true); - } + if (!newMigrationData?.legacy_cms?.uploadedFile?.isValidated) { + if (selectedCard[idField] === data?.[idField]) { + setIsHovered(true); + } + } }; const handleMouseLeave = () => { @@ -43,15 +49,17 @@ const Card = ({ data, selectedCard, onCardClick, cardType, idField = 'id' }: Car }; const handleClick = (event: MouseEvent) => { - event.preventDefault(); // Prevent the default action - onCardClick?.(data); + if (!newMigrationData?.legacy_cms?.uploadedFile?.isValidated) { + event.preventDefault(); // Prevent the default action + onCardClick?.(data); + } }; return (
diff --git a/ui/src/components/LogScreen/index.tsx b/ui/src/components/LogScreen/index.tsx index b417ea779..af1ad0e37 100644 --- a/ui/src/components/LogScreen/index.tsx +++ b/ui/src/components/LogScreen/index.tsx @@ -15,7 +15,7 @@ import { INewMigration } from '../../context/app/app.interface'; import './index.scss'; import { MAGNIFY,DEMAGNIFY } from '../../common/assets'; -import { saveStateToLocalStorage } from '../TestMigration'; +import { saveStateToLocalStorage } from '../../utilities/functions'; // Define log styles for different levels const logStyles: { [key: string]: React.CSSProperties } = { @@ -135,10 +135,10 @@ const TestMigrationLogViewer = ({ serverPath, sendDataToParent,projectId }: Logs if (message === "Test Migration Process Completed") { // Save test migration state to local storage - saveStateToLocalStorage({ + saveStateToLocalStorage(`testmigration_${projectId}`, { isTestMigrationCompleted : true, isTestMigrationStarted : false, - }, projectId); + }); Notification({ notificationContent: { text: message }, diff --git a/ui/src/components/ProjectsHeader/index.tsx b/ui/src/components/ProjectsHeader/index.tsx index efb61e1fe..5f4432351 100644 --- a/ui/src/components/ProjectsHeader/index.tsx +++ b/ui/src/components/ProjectsHeader/index.tsx @@ -1,8 +1,10 @@ // Libraries +import { useEffect, useState } from 'react'; import { Button, Icon, PageHeader, Search } from '@contentstack/venus-components'; // Interface import { ProjectsHeaderType } from './projectsHeader.interface'; +import { ProjectsObj } from '../../pages/Projects/projects.interface'; const ProjectsHeader = ({ headingText, @@ -13,6 +15,15 @@ const ProjectsHeader = ({ allProject, handleModal }: ProjectsHeaderType) => { + + const [disableCreateProject, setDisableCreateProject] = useState(false); + + useEffect(() => { + allProject?.forEach((project: ProjectsObj) => { + setDisableCreateProject(project?.isMigrationStarted && !project?.isMigrationCompleted); + }); + },[allProject]); + let interval: ReturnType; function setFocus() { clearTimeout(interval); @@ -22,64 +33,28 @@ const ProjectsHeader = ({ } const SearchProject = ( - <> -
- { - setSearchText(search)} - } - width="large" - onClear={true} - onClick={setFocus} - value={searchText} - debounceSearch={true} - id="search-project-input" - version="v2" - //disabled={allProject && allProject?.length <= 0 } - /> -
- {/* {allProject && allProject?.length > 0 ? ( -
- - search.replace(/\s/g, '').length - ? setSearchText(search?.trim()) - : setSearchText(search) - } - width="large" - onClear={true} - onClick={setFocus} - value={searchText} - debounceSearch={true} - id="search-project-input" - /> -
- ) : ( - searchText?.length > 0 && ( -
- setSearchText(search)} - onClear={true} - onClick={setFocus} - value={searchText} - debounceSearch={true} - id="search-project-input" - /> -
- ) - )} */} - +
+ { + setSearchText(search)} + } + width="large" + onClear={true} + onClick={setFocus} + value={searchText} + debounceSearch={true} + id="search-project-input" + version="v2" + //disabled={allProject && allProject?.length <= 0 } + /> +
); - const pageActions: any = [ { - label: cta && cta?.title && ( + label: cta?.title && ( diff --git a/ui/src/context/app/app.interface.ts b/ui/src/context/app/app.interface.ts index 9d392989e..72bce29f7 100644 --- a/ui/src/context/app/app.interface.ts +++ b/ui/src/context/app/app.interface.ts @@ -171,6 +171,8 @@ export interface IDestinationStack { selectedOrg: IDropDown; selectedStack: IDropDown; stackArray: IDropDown[]; + migratedStacks: string[]; + } export interface IContentMapper { existingGlobal: ContentTypeList[] | (() => ContentTypeList[]); @@ -220,6 +222,7 @@ export interface IDropDown { locales: locales[]; created_at: string; isNewStack?: boolean; + isDisabled?:boolean; } export interface ITestMigration { stack_link: string; @@ -258,7 +261,8 @@ export const DEFAULT_DROPDOWN: IDropDown = { master_locale: '', locales: [], created_at: '', - isNewStack: false + isNewStack: false, + isDisabled: false, }; export const DEFAULT_ORGANISATION: Organization = { @@ -330,6 +334,7 @@ export const DEFAULT_DESTINATION_STACK: IDestinationStack = { selectedOrg: DEFAULT_DROPDOWN, selectedStack: DEFAULT_DROPDOWN, stackArray: [], + migratedStacks: [], }; export const DEFAULT_CONTENT_MAPPER: IContentMapper = { diff --git a/ui/src/pages/Migration/index.tsx b/ui/src/pages/Migration/index.tsx index ef463ba15..783657a10 100644 --- a/ui/src/pages/Migration/index.tsx +++ b/ui/src/pages/Migration/index.tsx @@ -37,6 +37,7 @@ import ContentMapper from '../../components/ContentMapper'; import TestMigration from '../../components/TestMigration'; import MigrationExecution from '../../components/MigrationExecution'; import SaveChangesModal from '../../components/Common/SaveChangesModal'; +import { getMigratedStacks } from '../../services/api/project.service'; type StepperComponentRef = { handleStepChange: (step: number) => void; @@ -161,6 +162,8 @@ const Migration = () => { if (isEmptyString(selectedOrganisation?.value) || isEmptyString(params?.projectId)) return; const data = await getMigrationData(selectedOrganisation?.value, params?.projectId ?? ''); + const migratedstacks = await getMigratedStacks(selectedOrganisation?.value, projectId ); + if (data) { setIsLoading(false); setProjectData(data?.data); @@ -229,7 +232,8 @@ const Migration = () => { destination_stack: { selectedOrg: selectedOrganisationData, selectedStack: selectedStackData, - stackArray:[] + stackArray:[], + migratedStacks: migratedstacks?.data?.destinationStacks, }, content_mapping: { isDropDownChanged: false, diff --git a/ui/src/services/api/project.service.ts b/ui/src/services/api/project.service.ts index 118e1b843..3d33e4f3e 100644 --- a/ui/src/services/api/project.service.ts +++ b/ui/src/services/api/project.service.ts @@ -68,3 +68,15 @@ export const deleteProject = async (orgId: string, projectId: string) => { } } }; + +export const getMigratedStacks = async (orgId: string, projectId: string) => { + try { + return await getCall(`${API_VERSION}/org/${orgId}/project/${projectId}/get-migrated-stacks`, options()); + } catch (error) { + if (error instanceof Error) { + throw new Error(`Error in userSession: ${error.message}`); + } else { + throw new Error('Unknown error in userSession'); + } + } +}; From 1c076535739bdde707c5a967645acc21e49a2a15 Mon Sep 17 00:00:00 2001 From: Sayali Joshi Date: Wed, 8 Jan 2025 19:15:59 +0530 Subject: [PATCH 5/7] [CMG-408] - Content mapper | existing content type | When select group field, then it shows 3 matches and from that one field is selected still it shows below 3 matches instead of 2 matches --- ui/src/components/ContentMapper/index.tsx | 5 +++-- ui/src/components/LogScreen/index.tsx | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ui/src/components/ContentMapper/index.tsx b/ui/src/components/ContentMapper/index.tsx index c9b36ecf0..2e871c55d 100644 --- a/ui/src/components/ContentMapper/index.tsx +++ b/ui/src/components/ContentMapper/index.tsx @@ -1006,6 +1006,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R const groupArray = nestedList.filter(item => item?.child?.some(e => e?.id) ) + if(groupArray[0].child && previousSelectedValue !== selectedValue?.label && groupArray[0]?.uid === rowIndex){ for(const item of groupArray[0].child){ deletedExstingField[item?.uid] = { @@ -1316,7 +1317,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R } } - const selectedOption = OptionsForRow.length; + const selectedOption = OptionsForRow?.filter((option) => !option?.isDisabled)?.length // Handle case where there is exactly one match and it is auto-mapped if(OptionsForRow.length === 1 && @@ -1415,7 +1416,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R isDisabled: false }; - const adjustedOptions = (OptionsForRow.length === 0 && !contentTypeSchema) ? option : + const adjustedOptions: OptionsType[] | OptionsType = (OptionsForRow.length === 0 && !contentTypeSchema) ? option : (OptionsForRow.length > 0 && OptionsForRow.every((item)=>item.isDisabled) && OptionValue.label === Fields[data?.contentstackFieldType]?.label) ? [] : OptionsForRow.map((option: OptionsType) => ({ ...option, diff --git a/ui/src/components/LogScreen/index.tsx b/ui/src/components/LogScreen/index.tsx index af1ad0e37..1370695a8 100644 --- a/ui/src/components/LogScreen/index.tsx +++ b/ui/src/components/LogScreen/index.tsx @@ -184,25 +184,25 @@ const TestMigrationLogViewer = ({ serverPath, sendDataToParent,projectId }: Logs transition: "transform 0.1s ease" }}> {logs?.map((log, index) => { - const key = `${index}-${new Date().getMilliseconds()}` + // const key = `${index}-${new Date().getMilliseconds()}` try { const logObject = JSON.parse(log); const level = logObject.level; const timestamp = logObject.timestamp; const message = logObject.message; return ( - <> +
{message === "Migration logs will appear here once the process begins." - ?
+ ?
{message}
- :
+ :
{index}
{ timestamp ? new Date(timestamp)?.toTimeString()?.split(' ')[0] : new Date()?.toTimeString()?.split(' ')[0]}
{message}
} - +
); } catch (error) { console.error('Invalid JSON string', error); From 415c8fb750884392a85add6a978f8367acfb1609 Mon Sep 17 00:00:00 2001 From: AishDani Date: Thu, 9 Jan 2025 15:13:58 +0530 Subject: [PATCH 6/7] refactor:[CMG-414],[CMG-415],[CMG-450] --- api/src/services/contentMapper.service.ts | 17 +-- ui/src/components/ContentMapper/index.tsx | 126 ++++++++++++++++-- .../HorizontalStepper/HorizontalStepper.scss | 8 ++ .../HorizontalStepper/HorizontalStepper.tsx | 15 ++- 4 files changed, 138 insertions(+), 28 deletions(-) diff --git a/api/src/services/contentMapper.service.ts b/api/src/services/contentMapper.service.ts index 8febbd8ec..7534a1930 100644 --- a/api/src/services/contentMapper.service.ts +++ b/api/src/services/contentMapper.service.ts @@ -292,19 +292,12 @@ const getExistingContentTypes = async (req: Request) => { headers, }) ); - - if (err) { - throw new Error( - `Error fetching selected content type: ${ - err.response?.data || err.message - }` - ); - } + selectedContentType = { - title: res.data.content_type?.title, - uid: res.data.content_type?.uid, - schema: res.data.content_type?.schema, + title: res?.data?.content_type?.title, + uid: res?.data?.content_type?.uid, + schema: res?.data?.content_type?.schema, }; } return { @@ -314,7 +307,7 @@ const getExistingContentTypes = async (req: Request) => { } catch (error: any) { return { data: error.message, - status: 500, + status: error.status || 500, }; } }; diff --git a/ui/src/components/ContentMapper/index.tsx b/ui/src/components/ContentMapper/index.tsx index 2e871c55d..15c1fceb5 100644 --- a/ui/src/components/ContentMapper/index.tsx +++ b/ui/src/components/ContentMapper/index.tsx @@ -266,12 +266,10 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R //Check for null if (!data) { dispatch(updateMigrationData({ contentMappingData: DEFAULT_CONTENT_MAPPING_DATA })); - setIsLoading(false); return; } dispatch(updateMigrationData({ contentMappingData: data})); - setIsLoading(false); }) .catch((err) => { console.error(err); @@ -455,6 +453,17 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R [key]: { label: `${item?.display_name} > ${schemaItem?.display_name}`, value: schemaItem }, })); } + else if(! item?.schema?.some( + (schema) => schema?.uid === existingField[key]?.value?.uid) ){ + + setExistingField((prevOptions: ExistingFieldType) => { + const { [key]: _, ...rest } = prevOptions; // Destructure to exclude the key to remove + return { + ...rest + }; + }); + + } }); } } @@ -541,6 +550,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R // Method to fetch content types const fetchContentTypes = async (searchText: string) => { try { + setIsLoading(true); const { data } = await getContentTypes(projectId || '', 0, 5000, searchContentType || ''); //org id will always present setContentTypes(data?.contentTypes); @@ -588,21 +598,19 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R setItemStatusMap(itemStatusMap); - setLoading(true); for (let index = 0; index <= 30; index++) { itemStatusMap[index] = 'loaded'; } setItemStatusMap({ ...itemStatusMap }); - setLoading(false); const newTableData = data?.fieldMapping?.filter((field: FieldMapType) => field !== null) setTableData(newTableData || []); setTotalCounts(data?.count); setInitialRowSelectedData(newTableData.filter((item: FieldMapType) => !item.isDeleted)) - + setIsLoading(false); generateSourceGroupSchema(data?.fieldMapping); } catch (error) { console.error('fetchData -> error', error); @@ -636,10 +644,10 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R } setItemStatusMap({ ...updateditemStatusMapCopy }); - setLoading(false); // eslint-disable-next-line no-unsafe-optional-chaining setTableData([...tableData, ...data?.fieldMapping ?? tableData]); setTotalCounts(data?.count); + setIsLoading(false) } catch (error) { console.log('loadMoreItems -> error', error); } @@ -1686,6 +1694,97 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R } }; + const handleCTDeleted = async(isContentType:boolean) => { + const updatedContentTypeMapping = Object.fromEntries( + Object.entries(newMigrationData?.content_mapping?.content_type_mapping || {}).filter( + ([key]) => !selectedContentType?.contentstackUid.includes(key) + ) + ); + + const orgId = selectedOrganisation?.value; + const projectID = projectId; + setIsDropDownChanged(false); + + const updatedRows: FieldMapType[] = tableData.map((row) => { + return { ...row, contentstackFieldType: row?.backupFieldType }; + }); + setTableData(updatedRows); + setSelectedEntries(updatedRows); + + const dataCs = { + contentTypeData: { + status: selectedContentType?.status, + id: selectedContentType?.id, + projectId:projectId, + otherCmsTitle: otherCmsTitle, + otherCmsUid: selectedContentType?.otherCmsUid, + isUpdated: true, + updateAt: new Date(), + contentstackTitle: selectedContentType?.contentstackTitle, + contentstackUid: selectedContentType?.contentstackUid, + fieldMapping: updatedRows + } + }; + let newstate = {} ; + setContentTypeMapped((prevState: ContentTypeMap) => { + const newState = { ...prevState }; + + delete newState[selectedContentType?.contentstackUid ?? '']; + newstate = newState; + + return newstate; + }); + + if (orgId && selectedContentType) { + try { + const { data, status } = await resetToInitialMapping( + orgId, + projectID, + selectedContentType?.id ?? '', + dataCs + ); + + setExistingField({}); + setContentTypeSchema([]); + setOtherContentType({ + label: `Select ${isContentType ? 'Content Type' : 'Global Field'} from Existing Stack`, + value: `Select ${isContentType ? 'Content Type' : 'Global Field'} from Existing Stack` + }); + + if (status === 200) { + const resetCT = filteredContentTypes?.map(ct => + ct?.id === selectedContentType?.id ? { ...ct, status: data?.data?.status } : ct + ); + setFilteredContentTypes(resetCT); + setContentTypes(resetCT); + + try { + await updateContentMapper(orgId, projectID, {...newstate} ); + } catch (err) { + console.log(err); + return err; + } + + } + } catch (error) { + console.log(error); + return error; + } + } + + const newMigrationDataObj : INewMigration = { + ...newMigrationData, + content_mapping:{ + ...newMigrationData?.content_mapping, + content_type_mapping : updatedContentTypeMapping + + } + + } + dispatch(updateNewMigrationData(newMigrationDataObj)); + + } + /** * Retrieves existing content types for a given project. * @returns An array containing the retrieved content types or global fields based on condition if itContentType true and if existing content type or global field id is passed then returns an object containing title, uid and schema of that particular content type or global field. @@ -1694,7 +1793,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R if (isContentType) { try { const { data , status} = await getExistingContentTypes(projectId, otherContentType?.id ?? ''); - if (status == 201 && data?.contentTypes?.length > 0) { + if (status == 201 && data?.contentTypes?.length > 0 && data?.selectedContentType) { (otherContentType?.id === data?.selectedContentType?.uid) && setsCsCTypeUpdated(false); (otherContentType?.id && otherContentType?.label !== data?.selectedContentType?.title) @@ -1725,6 +1824,8 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R setContentTypeSchema(data?.selectedContentType?.schema); } } else { + + await handleCTDeleted(isContentType); Notification({ notificationContent: { text: "No content found in the stack" }, notificationProps: { @@ -1742,7 +1843,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R try { const { data, status } = await getExistingGlobalFields(projectId, otherContentType?.id ?? ''); - if (status == 201 && data?.globalFields?.length > 0) { + if (status == 201 && data?.globalFields?.length > 0 && data?.selectedGlobalField) { (otherContentType?.id === data?.selectedGlobalField?.uid) && setsCsCTypeUpdated(false); (otherContentType?.id && otherContentType?.label !== data?.selectedGlobalField?.title) @@ -1772,6 +1873,9 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R type: 'success' }); } else { + + await handleCTDeleted(isContentType); + Notification({ notificationContent: { text: "No Global Fields found in the stack" }, notificationProps: { @@ -1789,7 +1893,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R const contentField = contentModels?.find((item: ContentTypeList)=>item?.title === otherContentType?.label); const contentFieldKey = Object.keys(contentTypeMapped).find(key => contentTypeMapped[key] === otherContentType?.label); - + if(! contentField && contentFieldKey) { const updatedState = { ...contentTypeMapped }; delete updatedState[contentFieldKey]; @@ -1855,7 +1959,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R isDisabled: (contentTypeMapped && Object.values(contentTypeMapped).includes(item?.uid)) }; }); - + const adjustedOption = options?.map((option) => ({ @@ -2161,7 +2265,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R testId="no-results-found-page" />} -
+
); }); diff --git a/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss b/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss index 0e950ab63..ef135821a 100644 --- a/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss +++ b/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss @@ -138,4 +138,12 @@ fill: $color-brand-white-base; } } +} +.stepper-loader{ + align-items: center; + display: flex; + flex-direction: column; + height: 100%; + justify-content: center; + width: 100%; } \ No newline at end of file diff --git a/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.tsx b/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.tsx index 7128821c9..f838a844a 100644 --- a/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.tsx +++ b/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.tsx @@ -2,7 +2,7 @@ import React, { useState, useImperativeHandle, forwardRef, useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import './HorizontalStepper.scss'; -import { cbModal, Notification,Button } from '@contentstack/venus-components'; +import { cbModal, Notification,Button, CircularLoader } from '@contentstack/venus-components'; import { useSelector } from 'react-redux'; @@ -240,10 +240,15 @@ const HorizontalStepper = forwardRef(
{steps?.length ? ( <> - {!hideTabView && } -
- {steps[showStep]?.data} -
+ {!hideTabView && } +
+ {newMigrationData?.isprojectMapped ? +
+ +
: + steps[showStep]?.data + } +
) : ( emptyStateMsg From 3b5ecdbd22ac198a52c7577231985b8b523d2bd4 Mon Sep 17 00:00:00 2001 From: umeshmore45 Date: Thu, 9 Jan 2025 16:27:25 +0530 Subject: [PATCH 7/7] reslved minor bugs --- api/src/utils/content-type-creator.utils.ts | 3 +- api/src/utils/test-folder-creator.utils.ts | 36 +++++++- upload-api/migration-sitecore/utils/index.js | 91 +++++++++++++------- 3 files changed, 95 insertions(+), 35 deletions(-) diff --git a/api/src/utils/content-type-creator.utils.ts b/api/src/utils/content-type-creator.utils.ts index d02d1ba63..2c3fa357e 100644 --- a/api/src/utils/content-type-creator.utils.ts +++ b/api/src/utils/content-type-creator.utils.ts @@ -192,7 +192,8 @@ const convertToSchemaFormate = ({ field, advanced = true }: any) => { "unique": field?.advanced?.unique ?? false, "non_localizable": field.advanced?.nonLocalizable ?? false }; - data.field_metadata.default_value = field?.advanced?.default_value ?? null; + const default_value = field?.advanced?.options?.length ? (field?.advanced?.options?.find((item: any) => (item?.key === field?.advanced?.default_value) || (item?.key === field?.advanced?.default_value))) : { value: field?.advanced?.default_value }; + data.field_metadata.default_value = default_value?.value ?? null; return data; } case 'radio': { diff --git a/api/src/utils/test-folder-creator.utils.ts b/api/src/utils/test-folder-creator.utils.ts index 8e83f670e..79e993cb9 100644 --- a/api/src/utils/test-folder-creator.utils.ts +++ b/api/src/utils/test-folder-creator.utils.ts @@ -10,7 +10,9 @@ const { ASSETS_SCHEMA_FILE, CONTENT_TYPES_DIR_NAME, CONTENT_TYPES_SCHEMA_FILE, - ENTRIES_MASTER_FILE + ENTRIES_MASTER_FILE, + GLOBAL_FIELDS_DIR_NAME, + GLOBAL_FIELDS_FILE_NAME } = MIGRATION_DATA_CONFIG; @@ -201,10 +203,41 @@ const sortAssets = async (baseDir: string) => { await fs.promises.writeFile(path.join(assetsPath, ASSETS_SCHEMA_FILE), JSON?.stringify?.(assetsMeta)); } +const writeGlobalField = async (schema: any, globalSave: string, filePath: string) => { + try { + await fs.promises.access(globalSave); + } catch (err) { + try { + await fs.promises.mkdir(globalSave, { recursive: true }); + } catch (mkdirErr) { + console.error("🚀 ~ fs.mkdir ~ err:", mkdirErr); + return; + } + } + try { + await fs.promises.writeFile(filePath, JSON.stringify(schema, null, 2)); + } catch (writeErr) { + console.error("🚀 ~ fs.writeFile ~ err:", writeErr); + } +}; + +const sortGlobalField = async (baseDir: string, finalData: any) => { + const globalSave = path.join(process.cwd(), baseDir, GLOBAL_FIELDS_DIR_NAME); + const globalPath = path.join(globalSave, GLOBAL_FIELDS_FILE_NAME); + const globalData = await JSON.parse(await fs.promises.readFile(globalPath, 'utf8')); + const globalResult = []; + for await (const ct of globalData) { + await lookForReference(ct, finalData); + globalResult?.push(ct); + } + await writeGlobalField(globalResult, globalPath, globalPath); +} + const sortContentType = async (baseDir: string, finalData: any) => { const contentTypePath: string = path.join(process.cwd(), baseDir, CONTENT_TYPES_DIR_NAME); const contentSave = path.join(baseDir, CONTENT_TYPES_DIR_NAME); const ctData = await JSON.parse(await fs.promises.readFile(path.join(contentTypePath, CONTENT_TYPES_SCHEMA_FILE), 'utf8')); + await sortGlobalField(baseDir, finalData); const contentTypes: any = []; for await (const ct of finalData) { const findCtData = ctData?.find((ele: any) => ele?.uid === ct?.contentType); @@ -218,6 +251,7 @@ const sortContentType = async (baseDir: string, finalData: any) => { } + export const testFolderCreator = async ({ destinationStackId }: any) => { const sanitizedStackId = path.basename(destinationStackId); const baseDir = path.join(MIGRATION_DATA_CONFIG.DATA, sanitizedStackId); diff --git a/upload-api/migration-sitecore/utils/index.js b/upload-api/migration-sitecore/utils/index.js index cae85bd5f..519e6ac8d 100644 --- a/upload-api/migration-sitecore/utils/index.js +++ b/upload-api/migration-sitecore/utils/index.js @@ -1,48 +1,73 @@ const restrictedUid = [ - "uid", "api_key", - "created_at", - "deleted_at", - "updated_at", - "tags_array", - "klass_id", - "applikation_id", - "*_ids", - "id", - "_id", - "ACL", - "SYS_ACL", - "DEFAULT_ACL", - "app_user_object_uid", + "built_io_application_user", + "built_io_application_user_role", + "built_io_audit_log", + "built_io_environment", + "built_io_extensions", + "built_io_installation_data", + "built_io_label", + "built_io_language", + "built_io_publish_queue", + "built_io_release", "built_io_upload", + "cs_branches", + "org_uid", + "sys_asset", + "sys_metadata", + "_exists", + "_regex", + "*_ids", // Fields cannot have UID ending with "_ids." + "__indexes", "__loc", - "tags", + "__meta", + "__v", + "_id", "_owner", + "_publish_locales", + "_shouldFilter", + "_shouldLean", "_version", - "toJSON", - "save", - "update", + "ACL", + "api_key", + "app_user_object_uid", + "applikation_id", + "built_io_upload", + "contentstackFilters", + "created_at", + "created_by", + "DEFAULT_ACL", + "deleted_at", + "dimension", "domain", - "shard_account", - "shard_app", - "shard_random", + "embedded_items", "hook", - "__indexes", - "__meta", - "created_by", - "updated_by", + "id", "inbuilt_class", - "tenant_id", - "isSystemUser", "isApplicationUser", "isNew", - "_shouldLean", - "_shouldFilter", - "options", - "_version", - "__v", + "isSystemUser", + "klass_id", "locale", - "publish_details" + "options", + "org_uid", + "publish_details", + "save", + "shard_account", + "shard_app", + "shard_random", + "SYS_ACL", + "sys_assets", + "sys_metadata", + "tags", + "tags_array", + "taxonomies", + "tenant_id", + "toJSON", + "uid", + "update", + "updated_at", + "updated_by" ]; module.exports = restrictedUid; \ No newline at end of file