Skip to content

Commit 803503a

Browse files
Merge pull request #601 from contentstack/feature/dropdown-field-choices
Feature/dropdown field choices
2 parents 2bb19cd + 101e985 commit 803503a

File tree

9 files changed

+130
-91
lines changed

9 files changed

+130
-91
lines changed

api/src/models/FieldMapper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface FieldMapper {
2828
field_mapper: {
2929
id: string;
3030
projectId: string;
31+
contentTypeId: string;
3132
uid: string;
3233
otherCmsField: string;
3334
otherCmsType: string;

api/src/services/contentMapper.service.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,21 @@ const putTestData = async (req: Request) => {
3636
const contentTypes = req.body.contentTypes;
3737

3838
try {
39-
await FieldMapperModel.read();
39+
40+
/*
41+
this code snippet is iterating over an array called contentTypes and
42+
transforming each element by adding a unique identifier (id) if it doesn't already exist.
43+
The transformed elements are then stored in the contentType variable,
44+
and the generated id values are pushed into the contentIds array.
45+
*/
46+
await ContentTypesMapperModelLowdb.read();
47+
const contentIds: any[] = [];
48+
const contentType = contentTypes.map((item: any) => {
49+
const id = item?.id?.replace(/[{}]/g, "")?.toLowerCase() || uuidv4();
50+
item.id = id;
51+
contentIds.push(id);
52+
return { ...item, id, projectId };
53+
});
4054

4155
/*
4256
this code snippet iterates over an array of contentTypes and performs
@@ -47,36 +61,24 @@ const putTestData = async (req: Request) => {
4761
It then updates the field_mapper property of a data object using the FieldMapperModel.update() function.
4862
Finally, it updates the fieldMapping property of each type in the contentTypes array with the fieldIds array.
4963
*/
64+
await FieldMapperModel.read();
65+
5066
contentTypes.map((type: any, index: any) => {
5167
const fieldIds: string[] = [];
5268
const fields = type?.fieldMapping?.filter((field: any) => field)?.map?.((field: any) => {
5369
const id = field?.id ? field?.id?.replace(/[{}]/g, "")?.toLowerCase() : uuidv4();
5470
field.id = id;
5571
fieldIds.push(id);
56-
return { id, projectId, isDeleted: false, ...field };
72+
return { id, projectId, contentTypeId: type?.id, isDeleted: false, ...field };
5773
});
5874

5975
FieldMapperModel.update((data: any) => {
6076
data.field_mapper = [...(data?.field_mapper ?? []), ...(fields ?? [])];
6177
});
62-
contentTypes[index].fieldMapping = fieldIds;
78+
contentType[index].fieldMapping = fieldIds;
6379
});
6480

65-
await ContentTypesMapperModelLowdb.read();
66-
const contentIds: any[] = [];
6781

68-
/*
69-
this code snippet is iterating over an array called contentTypes and
70-
transforming each element by adding a unique identifier (id) if it doesn't already exist.
71-
The transformed elements are then stored in the contentType variable,
72-
and the generated id values are pushed into the contentIds array.
73-
*/
74-
const contentType = contentTypes.map((item: any) => {
75-
const id = item?.id?.replace(/[{}]/g, "")?.toLowerCase() || uuidv4();
76-
item.id = id;
77-
contentIds.push(id);
78-
return { ...item, id, projectId };
79-
});
8082

8183
await ContentTypesMapperModelLowdb.update((data: any) => {
8284
data.ContentTypesMappers = [
@@ -248,7 +250,7 @@ const getFieldMapping = async (req: Request) => {
248250
const fieldData = contentType?.fieldMapping?.map?.((fields: any) => {
249251
const fieldMapper = FieldMapperModel.chain
250252
.get("field_mapper")
251-
.find({ id: fields, projectId: projectId })
253+
.find({ id: fields, projectId: projectId, contentTypeId: contentTypeId })
252254
.value();
253255

254256
return fieldMapper;
@@ -616,7 +618,7 @@ const updateContentType = async (req: Request) => {
616618
await FieldMapperModel.read();
617619
fieldMapping.forEach((field: any) => {
618620
const fieldIndex = FieldMapperModel.data.field_mapper.findIndex(
619-
(f: any) => f?.id === field?.id
621+
(f: any) => f?.id === field?.id && f?.contentTypeId === field?.contentTypeId
620622
);
621623
if (fieldIndex > -1 && field?.contentstackFieldType !== "") {
622624
FieldMapperModel.update((data: any) => {

api/src/services/wordpress.service.ts

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import axios from "axios";
55
//import _ from "lodash";
66
import { MIGRATION_DATA_CONFIG } from "../constants/index.js";
77
import jsdom from "jsdom";
8-
import { htmlToJson } from "@contentstack/json-rte-serializer";
8+
import { htmlToJson, jsonToHtml } from "@contentstack/json-rte-serializer";
99
import customLogger from "../utils/custom-logger.utils.js";
1010
import { getLogMessage } from "../utils/index.js";
1111
import { Advanced } from "../models/FieldMapper.js";
@@ -108,20 +108,28 @@ let assetData: Record<string, any> | any = {};
108108
let blog_base_url = "";
109109

110110
//helper function to convert entries with content type
111-
function mapContentTypeToEntry(contentType: any, data: any) {
112-
return contentType?.fieldMapping?.reduce((acc: { [key: string]: any }, field: FieldMapping) => {
111+
async function mapContentTypeToEntry(contentType: any, data: any) {
112+
const result: { [key: string]: any } = {};
113+
114+
for (const field of contentType?.fieldMapping || []) {
113115
const fieldValue = data?.[field?.uid];
114116
let formattedValue;
115117

116118
switch (field?.contentstackFieldType) {
117119
case "single_line_text":
118120
case "text":
119-
case 'html':
120121
formattedValue = fieldValue;
121122
break;
122-
case "json":
123-
formattedValue = convertHtmlToJson(fieldValue);
123+
case "html":
124+
formattedValue =
125+
fieldValue && typeof fieldValue === "object"
126+
? await convertJsonToHtml(fieldValue)
127+
: fieldValue;
124128
break;
129+
case "json":
130+
131+
formattedValue = await convertHtmlToJson(fieldValue);
132+
break;
125133
case "reference":
126134
formattedValue = getParent(data,data[field.uid]);
127135
break;
@@ -132,10 +140,12 @@ function mapContentTypeToEntry(contentType: any, data: any) {
132140
formattedValue = Array.isArray(formattedValue) ? formattedValue : [formattedValue];
133141
}
134142

135-
acc[field.contentstackFieldUid] = formattedValue;
136-
return acc;
137-
}, {});
143+
result[field?.contentstackFieldUid] = formattedValue;
144+
}
145+
146+
return result;
138147
}
148+
139149
// helper functions
140150
async function writeFileAsync(filePath: string, data: any, tabSpaces: number) {
141151
filePath = path.resolve(filePath);
@@ -596,7 +606,7 @@ async function getAllreference(affix: string, packagePath: string, destinationSt
596606
...processReferenceData(referenceTerms, "terms", "wp:term_slug", terms)
597607
);
598608
referenceArray.push(
599-
...processReferenceData(referenceTags, "tags", "wp:tag_slug", tag)
609+
...processReferenceData(referenceTags, "tag", "wp:tag_slug", tag)
600610
);
601611

602612
if (referenceArray.length > 0) {
@@ -776,7 +786,7 @@ async function saveAuthors(authorDetails: any[], destinationStackId: string, pro
776786
authordata[customId] = {
777787
...authordata[customId],
778788
uid: customId,
779-
...mapContentTypeToEntry(contentType, authordataEntry),
789+
...( await mapContentTypeToEntry(contentType, authordataEntry)),
780790
};
781791
authordata[customId].publish_details = [];
782792

@@ -1473,7 +1483,7 @@ async function saveTerms(termsDetails: any[], destinationStackId: string, projec
14731483
`${master_locale}.json`
14741484
);
14751485
const termsdata = termsDetails.reduce(
1476-
(acc: { [key: string]: any }, data) => {
1486+
async (acc: { [key: string]: any }, data) => {
14771487

14781488
const { id } = data;
14791489
const uid = `terms_${id}`;
@@ -1485,7 +1495,7 @@ async function saveTerms(termsDetails: any[], destinationStackId: string, projec
14851495
acc[customId] = {
14861496
...acc[customId],
14871497
uid: customId,
1488-
...mapContentTypeToEntry(contentType, data), // Pass individual term object
1498+
...(await mapContentTypeToEntry(contentType, data)), // Pass individual term object
14891499
};
14901500
acc[customId].publish_details = [];
14911501
return acc;
@@ -1598,7 +1608,7 @@ async function saveTags(tagDetails: any[], destinationStackId: string, projectId
15981608
tagsFolderPath,
15991609
`${master_locale}.json`
16001610
);
1601-
const tagdata = tagDetails.reduce((acc: { [key: string]: any }, data) => {
1611+
const tagdata = tagDetails.reduce(async (acc: { [key: string]: any }, data) => {
16021612
const { id } = data;
16031613
const uid = `tags_${id}`;
16041614
//const title = `Tags - ${id}`;
@@ -1609,7 +1619,7 @@ async function saveTags(tagDetails: any[], destinationStackId: string, projectId
16091619
acc[customId]={
16101620
...acc[customId],
16111621
uid:customId,
1612-
...mapContentTypeToEntry(contenttype,data),
1622+
...( await mapContentTypeToEntry(contenttype,data)),
16131623
};
16141624
acc[customId].publish_details = [];
16151625

@@ -1715,11 +1725,22 @@ async function startingDirCategories(affix: string, ct: string, master_locale:st
17151725
}
17161726

17171727
const convertHtmlToJson = (htmlString: any) => {
1718-
const dom = new JSDOM(htmlString?.replace(/&amp;/g, "&"));
1719-
const htmlDoc = dom.window.document.querySelector("body");
1720-
return htmlToJson(htmlDoc);
1728+
if(typeof htmlString === 'string'){
1729+
const dom = new JSDOM(htmlString?.replace(/&amp;/g, "&"));
1730+
const htmlDoc = dom.window.document.querySelector("body");
1731+
const jsonValue = htmlToJson(htmlDoc)
1732+
return jsonValue;
1733+
1734+
}
1735+
else return htmlString;
17211736
};
17221737

1738+
const convertJsonToHtml = async (json: any) => {
1739+
const htmlValue = await jsonToHtml(json);
1740+
return htmlValue;
1741+
1742+
}
1743+
17231744
function getParent(data: any,id: string) {
17241745
const parentId: any = fs.readFileSync(
17251746
path.join(referencesFolder, MIGRATION_DATA_CONFIG.REFERENCES_FILE_NAME),
@@ -1745,7 +1766,7 @@ async function saveCategories(categoryDetails: any[], destinationStackId:string,
17451766
const srcFunc = 'saveCategories';
17461767
try {
17471768
const categorydata = categoryDetails.reduce(
1748-
(acc: { [key: string]: any }, data) => {
1769+
async (acc: { [key: string]: any }, data) => {
17491770
const uid = `category_${data["id"]}`;
17501771

17511772
const customId = uid
@@ -1754,7 +1775,7 @@ async function saveCategories(categoryDetails: any[], destinationStackId:string,
17541775
acc[customId]={
17551776
...acc[customId],
17561777
uid:customId,
1757-
...mapContentTypeToEntry(contenttype,data),
1778+
...(await mapContentTypeToEntry(contenttype,data)),
17581779
}
17591780
acc[customId].publish_details = [];
17601781

@@ -2057,23 +2078,18 @@ async function processChunkData(
20572078
data,
20582079
postdata
20592080
);
2060-
const formattedPosts = Object?.entries(formatted_posts)?.reduce(
2061-
(acc: { [key: string]: any }, data:any) => {
2062-
2063-
const customId = idCorrector(data["uid"])
2064-
2065-
// Accumulate category data
2066-
acc[customId]={
2067-
...acc[customId],
2068-
uid: customId,
2069-
...mapContentTypeToEntry(contenttype,data),
2070-
};
2071-
acc[customId].publish_details = [];
2072-
2073-
return acc;
2074-
},
2075-
{}
2076-
);
2081+
const formattedPosts: any = {};
2082+
2083+
for (const [key, value] of Object.entries(formatted_posts as {[key: string]: any})) {
2084+
const customId = idCorrector(value?.uid);
2085+
2086+
formattedPosts[customId] = {
2087+
...formattedPosts[customId],
2088+
uid: customId,
2089+
...(await mapContentTypeToEntry(contenttype, value)),
2090+
};
2091+
formattedPosts[customId].publish_details = [];
2092+
}
20772093
Object.assign(postdata,formattedPosts);
20782094

20792095
// await writeFileAsync(
@@ -2095,6 +2111,7 @@ async function processChunkData(
20952111
if (isLastChunk && allSuccess) {
20962112
console.info("last data");
20972113
}
2114+
console.info("postData ---> ", postdata)
20982115
return postdata
20992116
} catch (error) {
21002117
console.error(error);
@@ -2105,8 +2122,8 @@ async function processChunkData(
21052122

21062123
async function extractPosts( packagePath: string, destinationStackId: string, projectId: string,contentTypes:any, keyMapper:any, master_locale: string) {
21072124
const srcFunc = "extractPosts";
2108-
const ct:any = keyMapper?.["categories"];
2109-
const contenttype = contentTypes?.find((item:any)=> item?.otherCmsUid === 'categories');
2125+
const ct:any = keyMapper?.["posts"];
2126+
const contenttype = contentTypes?.find((item:any)=> item?.otherCmsUid === 'posts');
21102127

21112128
try {
21122129
await startingDirPosts(ct, master_locale);

ui/src/components/AdvancePropertise/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ const AdvancePropertise = (props: SchemaProps) => {
576576
isMulti={true}
577577
onChange={(selectedOptions: ContentTypeOption[]) => {
578578
setCTValue(selectedOptions);
579-
const embedObject = selectedOptions.map((item: optionsType) => item.label); // Update the state with the selected options
579+
const embedObject = selectedOptions.map((item: optionsType) => item?.value); // Update the state with the selected options
580580
props?.updateFieldSettings(
581581
props?.rowId,
582582
{

ui/src/components/ContentMapper/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ const ContentMapper = forwardRef(({handleStepChange}: contentMapperProps, ref: R
671671
const validTableData = data?.fieldMapping?.filter((field: FieldMapType) => field?.otherCmsType !== undefined);
672672

673673
setTableData(validTableData || []);
674+
setSelectedEntries(validTableData);
674675
setTotalCounts(validTableData?.length);
675676
setInitialRowSelectedData(validTableData?.filter((item: FieldMapType) => !item?.isDeleted))
676677
setIsLoading(false);

ui/src/components/LegacyCms/Actions/LoadSelectCms.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const LoadSelectCms = (props: LoadSelectCmsProps) => {
142142
}
143143
};
144144
//await updateLegacyCMSData(selectedOrganisation.value, projectId, { legacy_cms: newSelectedCard?.cms_id });
145-
//dispatch(updateNewMigrationData(newMigrationDataObj));
145+
dispatch(updateNewMigrationData(newMigrationDataObj));
146146
props?.handleStepChange(props?.currentStep);
147147
}
148148
} catch (error) {
@@ -155,25 +155,27 @@ const LoadSelectCms = (props: LoadSelectCmsProps) => {
155155
filterCMSData(searchText);
156156
}, []);
157157

158-
// Handle Legacy cms selection for single match
159-
useEffect(() => {
160-
const isSingleMatch = cmsData?.length === 1;
161-
if (isSingleMatch) {
162-
setSelectedCard({ ...selectedCard });
163158

164-
const newMigrationDataObj: INewMigration = {
165-
...newMigrationData,
166-
legacy_cms: {
167-
...newMigrationData.legacy_cms,
168-
selectedCms: { ...selectedCard }
169-
}
170-
};
171-
dispatch(updateNewMigrationData(newMigrationDataObj));
172-
173-
// Call for Step Change
174-
props?.handleStepChange(props?.currentStep);
175-
}
176-
}, [cmsData]);
159+
// Handle Legacy cms selection for single match
160+
// useEffect(() => {
161+
// const isSingleMatch = cmsData?.length === 1;
162+
// if (isSingleMatch) {
163+
// setSelectedCard({ ...selectedCard });
164+
165+
// const newMigrationDataObj: INewMigration = {
166+
// ...newMigrationData,
167+
// legacy_cms: {
168+
// ...newMigrationDataRef?.current?.legacy_cms,
169+
// selectedCms: { ...selectedCard }
170+
// }
171+
// };
172+
// console.info("neMigObj ---> ", newMigrationDataObj, cmsData)
173+
// dispatch(updateNewMigrationData(newMigrationDataObj));
174+
175+
// // Call for Step Change
176+
// props?.handleStepChange(props?.currentStep);
177+
// }
178+
// }, [cmsData]);
177179

178180
return (
179181
<div>

ui/src/components/MigrationExecution/index.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,8 @@ div .step-component .action-component-body {
6969
border: 1px solid #dde3ee;
7070
border-radius: var(--TermCount, 5px);
7171
}
72+
.textInput-ellipse {
73+
text-overflow: ellipsis;
74+
overflow: hidden;
75+
white-space: nowrap;
76+
}

0 commit comments

Comments
 (0)