Skip to content
Merged

Dev #418

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/src/controllers/projects.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ const updateMigrationExecution = async (req: Request, res: Response): Promise<vo
res.status(project.status).json(project);
}

const getMigratedStacks = async (req: Request, res: Response): Promise<void> => {
const project = await projectService.getMigratedStacks(req);
res.status(project.status).json(project);
}

export const projectController = {
getAllProjects,
getProject,
Expand All @@ -187,4 +192,5 @@ export const projectController = {
revertProject,
updateStackDetails,
updateMigrationExecution,
getMigratedStacks,
};
2 changes: 2 additions & 0 deletions api/src/routes/projects.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@ router.patch("/:projectId/stack-details", asyncRouter(projectController.updateSt
//update migration execution key
router.put("/:projectId/migration-excution",asyncRouter(projectController.updateMigrationExecution));

router.get("/:projectId/get-migrated-stacks", asyncRouter(projectController.getMigratedStacks))

export default router;
17 changes: 5 additions & 12 deletions api/src/services/contentMapper.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -314,7 +307,7 @@ const getExistingContentTypes = async (req: Request) => {
} catch (error: any) {
return {
data: error.message,
status: 500,
status: error.status || 500,
};
}
};
Expand Down
48 changes: 47 additions & 1 deletion api/src/services/projects.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,51 @@ const updateMigrationExecution = async (req: Request) => {
};


/**
* get the destination_stack_id of completed projects.
*
* @param req - The request object containing the parameters and body.
* @returns An object with the status and data of the update operation.
* @throws ExceptionFunction if an error occurs during the process.
*/
const getMigratedStacks = async(req: Request) => {

const { token_payload } = req.body;
const srcFunc = "getMigratedStacks";

try {
await ProjectModelLowdb.read();
const projects = ProjectModelLowdb.data?.projects || [];

// Map through projects to extract `destinationstack` key
const destinationStacks = projects.filter((project: any) => project?.status === 5 && project.current_step === 5)
.map((project: any) => project.destination_stack_id);

return {
status: HTTP_CODES.OK,
destinationStacks
};

} catch (error:any) {
// Log error message
logger.error(
getLogMessage(
srcFunc,
"Error occurred while while getting all destinationstack id's of projects",
token_payload,
error
)
);

// Throw a custom exception with the error details
throw new ExceptionFunction(
error?.message || HTTP_TEXTS.INTERNAL_ERROR,
error?.statusCode || error?.status || HTTP_CODES.SERVER_ERROR
);

}

}

export const projectService = {
getAllProjects,
Expand All @@ -1229,5 +1274,6 @@ export const projectService = {
revertProject,
updateStackDetails,
updateContentMapper,
updateMigrationExecution
updateMigrationExecution,
getMigratedStacks
};
3 changes: 2 additions & 1 deletion api/src/utils/content-type-creator.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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': {
Expand Down
36 changes: 35 additions & 1 deletion api/src/utils/test-folder-creator.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
11 changes: 8 additions & 3 deletions ui/src/components/AdvancePropertise/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import {
// Service
import { getContentTypes } from '../../services/api/migration.service';

// Utilities
import { validateArray } from '../../utilities/functions';

// Interfaces
import { optionsType, SchemaProps } from './advanceProperties.interface';
import { ContentType } from '../ContentMapper/contentMapper.interface';
Expand Down Expand Up @@ -330,9 +333,11 @@ const AdvancePropertise = (props: SchemaProps) => {
}, [ctValue]);

// Option for content types
const option = Array.isArray(contentTypes)
? contentTypes.map((option) => ({ label: option?.contentstackTitle, value: option?.contentstackUid }))
: [{ label: contentTypes, value: contentTypes }];
const contentTypesList = contentTypes?.filter((ct: ContentType) => ct?.type === "content_type");

const option = validateArray(contentTypesList)
? contentTypesList?.map((option: ContentType) => ({ label: option?.contentstackTitle, value: option?.contentstackUid }))
: [{ label: contentTypesList, value: contentTypesList }];

return (
<>
Expand Down
2 changes: 2 additions & 0 deletions ui/src/components/Common/Card/card.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export interface ICardType {
* The file format ID of the card.
*/
fileformat_id?: string;

[key: string]: any;
}

/**
Expand Down
13 changes: 12 additions & 1 deletion ui/src/components/Common/Card/card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -148,4 +155,8 @@
p {
color: $color-stepper-title;
}
}
.Card__disabled{
cursor: not-allowed;
opacity: .5;
}
42 changes: 26 additions & 16 deletions ui/src/components/Common/Card/card.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
// 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;
selectedCard: ICardType;
cardType?: string;
disabled: boolean;
};

/**
Expand All @@ -25,35 +33,37 @@ 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, cardType, idField = 'id',disabled }: 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 = () => {
setIsHovered(false);
};

const handleClick = (event: MouseEvent<HTMLDivElement>) => {
event.preventDefault(); // Prevent the default action
onCardClick?.(data);
if (!newMigrationData?.legacy_cms?.uploadedFile?.isValidated) {
event.preventDefault(); // Prevent the default action
onCardClick?.(data);
}
};

return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
className={`connector_list ${cardType === 'legacyCMS' ? 'trigger_list' : ''}`}
className={`connector_list ${cardType === 'legacyCMS' ? 'trigger_list' : ''} ${disabled ? 'Card__disabled' : ''} `}
style={{ position: 'relative' }}
onClick={handleClick}
onClick={!disabled ? handleClick : undefined}
>
{data.description && (
<div style={{ position: 'absolute' }}>
Expand Down
Loading
Loading