Skip to content

Commit 9b527d0

Browse files
committed
Refactor UID handling and improve error messaging in components
- Updated UID processing logic in AEM and Sitecore services to ensure correct field mapping. - Enhanced error handling in AdvanceProperties component to provide user feedback for validation regex input. - Cleaned up unnecessary comments and improved code readability in ContentMapper and LegacyCms components. - Added default value for affix in file validation to streamline user experience. - Updated legacy CMS description for clarity and improved user guidance.
2 parents e187724 + ad7a762 commit 9b527d0

File tree

17 files changed

+138
-100
lines changed

17 files changed

+138
-100
lines changed

api/src/services/aem.service.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,22 +932,25 @@ function processFieldsRecursive(
932932
let value = getFieldValue(items, aemFieldName);
933933
const uid = getLastKey(field?.contentstackFieldUid);
934934

935+
const actualUid = getActualFieldUid(uid, field?.uid);
935936
if (value && typeof value === 'string' && /<[^>]+>/.test(value)) {
936937
value = stripHtmlTags(value);
937938
}
938939

939-
obj[uid] = value !== null && value !== undefined ? String(value) : "";
940+
obj[actualUid] = value !== null && value !== undefined ? String(value) : "";
940941
break;
941942
}
942943

943944
case 'text': {
944945
const uid = getLastKey(field?.contentstackFieldUid);
945-
obj[uid] = title ?? '';
946+
const actualUid = getActualFieldUid(uid, field?.uid);
947+
obj[actualUid] = title ?? '';
946948
break;
947949
}
948950
case 'url': {
949951
const uid = getLastKey(field?.contentstackFieldUid);
950-
obj[uid] = `/${slugify(title)}`;
952+
const actualUid = getActualFieldUid(uid, field?.uid);
953+
obj[actualUid] = `/${slugify(title)}`;
951954
break;
952955
}
953956
case 'reference': {

api/src/services/contentMapper.service.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ const putTestData = async (req: Request) => {
6565
});
6666
});
6767

68-
69-
7068
/*
7169
this code snippet iterates over an array of contentTypes and performs
7270
some operations on each element.
@@ -742,10 +740,8 @@ const updateContentType = async (req: Request) => {
742740
FieldMapperModel.update((data: any) => {
743741
const existingField = data?.field_mapper?.[fieldIndex];
744742
const preservedInitial = existingField?.advanced?.initial;
745-
746743

747744
data.field_mapper[fieldIndex] = field;
748-
749745

750746
if (preservedInitial && field?.advanced) {
751747
data.field_mapper[fieldIndex].advanced.initial = preservedInitial;
@@ -841,7 +837,7 @@ const resetToInitialMapping = async (req: Request) => {
841837
const fieldMappingData = contentTypeData.fieldMapping.map((itemId: any) => {
842838
const fieldData = FieldMapperModel.chain
843839
.get('field_mapper')
844-
.find({ id: itemId, projectId: projectId })
840+
.find({ id: itemId, projectId: projectId, contentTypeId: contentTypeId })
845841
.value();
846842
return fieldData;
847843
});
@@ -861,21 +857,23 @@ const resetToInitialMapping = async (req: Request) => {
861857
//await FieldMapperModel.read();
862858
(fieldMappingData || []).forEach((field: any) => {
863859
const fieldIndex = FieldMapperModel.data.field_mapper.findIndex(
864-
(f: any) => f?.id === field?.id
860+
(f: any) =>
861+
f?.id === field?.id &&
862+
f?.projectId === projectId &&
863+
f?.contentTypeId === contentTypeId
865864
);
866865
if (fieldIndex > -1) {
867866
FieldMapperModel.update((data: any) => {
868-
869-
data.field_mapper[fieldIndex] = {
870-
...field,
871-
contentstackField: field?.otherCmsField,
872-
contentstackFieldUid: field?.backupFieldUid,
873-
contentstackFieldType: field?.backupFieldType,
874-
advanced: {
875-
...field?.advanced?.initial,
876-
initial: field?.advanced?.initial,
877-
}
878-
}
867+
data.field_mapper[fieldIndex] = {
868+
...field,
869+
contentstackField: field?.otherCmsField,
870+
contentstackFieldUid: field?.backupFieldUid,
871+
contentstackFieldType: field?.backupFieldType,
872+
advanced: {
873+
...field?.advanced?.initial,
874+
initial: field?.advanced?.initial,
875+
},
876+
};
879877
});
880878
}
881879
});

api/src/services/sitecore.service.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,31 @@ async function writeFiles(
105105
console.error('Error writing files:', error);
106106
}
107107
}
108+
const uidCorrector = ({ uid } :{uid : string}) => {
109+
if (!uid || typeof uid !== 'string') {
110+
return '';
111+
}
112+
113+
let newUid = uid;
114+
115+
// Note: UIDs starting with numbers and restricted keywords are handled externally in Sitecore
116+
// The prefix is applied in contentTypeMaker function when needed
108117

109-
const uidCorrector = ({ uid }: any) => {
110-
if (startsWithNumber(uid)) {
111-
return `${append}_${_.replace(
112-
uid,
113-
new RegExp('[ -]', 'g'),
114-
'_'
115-
)?.toLowerCase()}`;
118+
// Clean up the UID
119+
newUid = newUid
120+
.replace(/[ -]/g, '_') // Replace spaces and hyphens with underscores
121+
.replace(/[^a-zA-Z0-9_]+/g, '_') // Replace non-alphanumeric characters (except underscore)
122+
.replace(/([A-Z])/g, (match) => `_${match.toLowerCase()}`) // Handle camelCase
123+
.toLowerCase() // Convert to lowercase
124+
.replace(/_+/g, '_') // Replace multiple underscores with single
125+
.replace(/^_|_$/g, ''); // Remove leading/trailing underscores
126+
127+
// Ensure UID doesn't start with underscore (Contentstack requirement)
128+
if (newUid.startsWith('_')) {
129+
newUid = newUid.substring(1);
116130
}
117-
return _.replace(uid, new RegExp('[ -]', 'g'), '_')?.toLowerCase();
131+
132+
return newUid;
118133
};
119134

120135
const createAssets = async ({

api/src/utils/content-type-creator.utils.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,32 @@ function startsWithNumber(str: string) {
7474
return /^\d/.test(str);
7575
}
7676

77-
const uidCorrector = ({ uid }: any) => {
78-
if (startsWithNumber(uid)) {
79-
return `a_${_.replace(uid, new RegExp("[ -]", "g"), '_')?.toLowerCase()}`
77+
const uidCorrector = ({ uid } : {uid : string}) => {
78+
if (!uid || typeof uid !== 'string') {
79+
return '';
8080
}
81-
return _.replace(uid, new RegExp("[ -]", "g"), '_')?.toLowerCase()
82-
}
81+
82+
let newUid = uid;
83+
84+
// Note: UIDs starting with numbers and restricted keywords are handled externally in Sitecore
85+
// The prefix is applied in contentTypeMaker function when needed
86+
87+
// Clean up the UID
88+
newUid = newUid
89+
.replace(/[ -]/g, '_') // Replace spaces and hyphens with underscores
90+
.replace(/[^a-zA-Z0-9_]+/g, '_') // Replace non-alphanumeric characters (except underscore)
91+
.replace(/([A-Z])/g, (match) => `_${match.toLowerCase()}`) // Handle camelCase
92+
.toLowerCase() // Convert to lowercase
93+
.replace(/_+/g, '_') // Replace multiple underscores with single
94+
.replace(/^_|_$/g, ''); // Remove leading/trailing underscores
95+
96+
// Ensure UID doesn't start with underscore (Contentstack requirement)
97+
if (newUid.startsWith('_')) {
98+
newUid = newUid.substring(1);
99+
}
100+
101+
return newUid;
102+
};
83103

84104

85105
function buildFieldSchema(item: any, marketPlacePath: string, parentUid = ''): any {
@@ -627,8 +647,8 @@ export const convertToSchemaFormate = ({ field, advanced = true, marketPlacePath
627647
"field_metadata": {
628648
description: "",
629649
"default_value": {
630-
"title": "",
631-
"url": '',
650+
"title": field?.advanced?.title ?? '',
651+
"url": field?.advanced?.url ?? '',
632652
}
633653
},
634654
"format": field?.advanced?.validationRegex ?? '',

ui/src/cmsData/legacyCms.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@
284284
"uid": "cs6c761d71844ac800"
285285
},
286286
"title": "Add Source Affix",
287-
"description": "Add a 2–5 character affix for the source name. Use only letters, no numbers or special characters",
287+
"description": "Add a 2–5 letter-only affix for the source name. The affix will function as a prefix if the content type UID matches with <a href=\"https://www.contentstack.com/docs/developers/create-content-types/restricted-keywords-for-uids\" target=\"_blank\">restricted UIDs</a>. The affix will function as a suffix for field UIDs. If left blank, \"cs\" will be used by default. Avoid numbers, special characters, and restricted keywords",
288288
"step_lock_text": "Editing this step is currently disabled. To make changes in Draft mode, please deactivate the migration",
289289
"lock": false,
290290
"active": false,

ui/src/components/AdvancePropertise/index.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,8 @@
184184
}
185185
}
186186
}
187+
188+
.errorMessage {
189+
color: $color-brand-warning-medium;
190+
font-size: 12px;
191+
}

ui/src/components/AdvancePropertise/index.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ const AdvancePropertise = (props: SchemaProps) => {
9797
const [options, setOptions] = useState(props?.value?.options || []);
9898
const [draggedIndex, setDraggedIndex] = useState<number | null>(null);
9999

100+
const [isError, setIsError] = useState(false);
101+
const [errorMessage, setErrorMessage] = useState('');
102+
100103
useEffect(() => {
101104
if (props?.data?.referenceTo && Array.isArray(props?.data?.referenceTo)) {
102105
const updatedReferencedItems = props?.data?.referenceTo.map((item: string) => ({
@@ -234,6 +237,16 @@ const AdvancePropertise = (props: SchemaProps) => {
234237
[field]: (event.target as HTMLInputElement)?.value
235238
}));
236239

240+
if(field === 'validationRegex') {
241+
if(event.target.value?.trim()?.length > 0) {
242+
setIsError(true);
243+
setErrorMessage('Adding a regex could impact entry creation.');
244+
}
245+
else {
246+
setIsError(false);
247+
setErrorMessage('');
248+
}
249+
}
237250
const currentToggleStates = {
238251
...toggleStates,
239252
[field]: (event.target as HTMLInputElement)?.value
@@ -582,6 +595,7 @@ const AdvancePropertise = (props: SchemaProps) => {
582595
handleOnChange('validationRegex', e, true))
583596
}
584597
/>
598+
{isError && <p className="errorMessage">{errorMessage}</p>}
585599
</Field>
586600
</>
587601
)}

ui/src/components/ContentMapper/index.scss

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,7 @@
152152
.Table {
153153
border-left: 0 none;
154154
min-height: 26.25rem;
155-
// &__rowgroup {
156-
// display: flex;
157-
// flex: 1;
158-
// flex-direction: column;
159-
// }
160155
.Table__body__row {
161-
// height: auto!important;
162-
// min-height: 80px;
163156
.Table-select-body {
164157
>.checkbox-wrapper {
165158
align-items: flex-start;

ui/src/components/ContentMapper/index.tsx

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -769,12 +769,8 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
769769
setItemStatusMap(itemStatusMap);
770770
setLoading(true);
771771

772-
773-
// console.info('loading', loading);
774-
775772
const { data } = await getFieldMapping(contentTypeId || '', 0, 1000, searchText || '', projectId);
776773

777-
778774
for (let index = 0; index <= 1000; index++) {
779775
itemStatusMap[index] = 'loaded';
780776
}
@@ -789,7 +785,6 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
789785
setSelectedEntries(validTableData ?? []);
790786
setTotalCounts(validTableData?.length);
791787
setInitialRowSelectedData(validTableData?.filter((item: FieldMapType) => !item?.isDeleted))
792-
// setIsLoading(false);
793788
generateSourceGroupSchema(validTableData);
794789
} catch (error) {
795790
console.error('fetchData -> error', error);
@@ -812,7 +807,7 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
812807
}
813808

814809
setItemStatusMap({ ...itemStatusMapCopy });
815-
// setLoading(true);
810+
setLoading(true);
816811

817812
const { data } = await getFieldMapping(contentTypeUid || '', skip, limit, searchText || '', projectId);
818813

@@ -823,15 +818,15 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
823818
}
824819

825820
setItemStatusMap({ ...updateditemStatusMapCopy });
821+
setLoading(false);
826822

827823
const validTableData = data?.fieldMapping?.filter((field: FieldMapType) => field?.otherCmsType !== undefined);
828824

829825
// eslint-disable-next-line no-unsafe-optional-chaining
830-
setTableData([...tableData, ...validTableData ?? tableData]);
831-
setTotalCounts([...tableData, ...validTableData ?? tableData]?.length);
832-
setIsLoading(false);
826+
setTableData(validTableData ?? []);
827+
setSelectedEntries(validTableData ?? []);
828+
setTotalCounts(validTableData?.length);
833829
setIsAllCheck(true);
834-
835830
} catch (error) {
836831
console.error('loadMoreItems -> error', error);
837832
}
@@ -2680,20 +2675,6 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
26802675
initialRowSelectedData={initialRowSelectedData}
26812676
initialSelectedRowIds={rowIds}
26822677
itemSize={80}
2683-
// v2Features={{
2684-
// isNewEmptyState: true
2685-
// }}
2686-
// customEmptyState={
2687-
// <EmptyState
2688-
// forPage="list"
2689-
// heading={<div className="empty_search_heading">No Fields available</div>}
2690-
// moduleIcon="NoSearchResult"
2691-
// description="Try changing the search query to find what you are looking for."
2692-
// version="v2"
2693-
// testId="no-results-found-page"
2694-
// className="custom-empty-state"
2695-
// />
2696-
// }
26972678
withExportCta={{
26982679
component: (
26992680
<div className='d-flex align-items-center'>

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

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const LoadPreFix = (props: LoadSelectCmsProps) => {
2929

3030
const dispatch = useDispatch();
3131

32-
const [prefix, setPrefix] = useState<string>(newMigrationData?.legacy_cms?.affix || '');
32+
const [prefix, setPrefix] = useState<string>(newMigrationData?.legacy_cms?.affix || 'cs');
3333

3434
const [isError, setIsError] = useState<boolean>(false);
3535
const [errorMessage, setErrorMessage] = useState<string>('');
@@ -76,7 +76,6 @@ const LoadPreFix = (props: LoadSelectCmsProps) => {
7676
isRestictedKeywordCheckboxChecked: isCheckedBoxChecked
7777
}
7878
};
79-
8079
dispatch(updateNewMigrationData(newMigrationDataObj));
8180
} else {
8281
setPrefix(value);
@@ -93,28 +92,37 @@ const LoadPreFix = (props: LoadSelectCmsProps) => {
9392
};
9493

9594
dispatch(updateNewMigrationData(newMigrationDataObj));
96-
9795
setIsError(false);
9896

9997
//call for Step Change
10098
props?.handleStepChange(props?.currentStep);
10199
return;
102100
}
103101
} else {
104-
setIsError(true);
105-
setErrorMessage('Please enter Affix');
102+
setIsError(false);
103+
setErrorMessage('');
104+
setIsRestrictedKey(false);
105+
setPrefix('');
106+
}
107+
});
108+
109+
const handleOnBlur = (value: string) => {
110+
if (isEmptyString(value?.trim())) {
111+
setIsError(false);
112+
setErrorMessage('');
113+
setIsRestrictedKey(false);
114+
setPrefix('cs');
106115
const newMigrationDataObj: INewMigration = {
107116
...newMigrationData,
108117
legacy_cms: {
109118
...newMigrationData?.legacy_cms,
110-
affix: value,
119+
affix: 'cs',
111120
isRestictedKeywordCheckboxChecked: isCheckedBoxChecked
112121
}
113122
};
114-
115123
dispatch(updateNewMigrationData(newMigrationDataObj));
116124
}
117-
});
125+
};
118126

119127
/**** ALL USEEffects HERE ****/
120128

@@ -136,6 +144,9 @@ const LoadPreFix = (props: LoadSelectCmsProps) => {
136144
aria-label="affix"
137145
disabled={newMigrationData?.legacy_cms?.uploadedFile?.isValidated}
138146
isReadOnly={newMigrationData?.legacy_cms?.uploadedFile?.isValidated}
147+
onBlur={(e: React.FocusEvent<HTMLInputElement>) => {
148+
handleOnBlur(e.target.value);
149+
}}
139150
/>
140151
{isError && <p className="errorMessage">{errorMessage}</p>}
141152
</div>

0 commit comments

Comments
 (0)