@@ -301,7 +301,8 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
301301 const [ isCsCTypeUpdated , setsCsCTypeUpdated ] = useState < boolean > ( false ) ;
302302 const [ isLoadingSaveButton , setisLoadingSaveButton ] = useState < boolean > ( false ) ;
303303 const [ activeFilter , setActiveFilter ] = useState < string > ( '' ) ;
304- const [ isAllCheck , setIsAllCheck ] = useState < boolean > ( false ) ;
304+ const [ isAllCheck , setIsAllCheck ] = useState < boolean > ( false ) ;
305+ const [ isResetFetch , setIsResetFetch ] = useState < boolean > ( false ) ;
305306
306307
307308 /** ALL HOOKS Here */
@@ -496,6 +497,20 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
496497 } ;
497498 } , [ ] ) ;
498499
500+ /**
501+ * Debounces a function call by delaying its execution until after the specified delay has elapsed since the last invocation.
502+ * @param fn - The function to debounce
503+ * @param delay - The delay in milliseconds to wait before executing the function
504+ * @returns A debounced version of the function
505+ */
506+ const debounce = ( fn : ( ...args : any [ ] ) => any , delay : number | undefined ) => {
507+ let timeoutId : string | number | NodeJS . Timeout | undefined ;
508+ return ( ...args : any [ ] ) => {
509+ clearTimeout ( timeoutId ) ;
510+ timeoutId = setTimeout ( ( ) => fn ( ...args ) , delay ) ;
511+ } ;
512+ } ;
513+
499514 const checkAndUpdateField = (
500515 item : any ,
501516 value : any ,
@@ -1998,11 +2013,14 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
19982013 handleDropdownState
19992014 } ) ) ;
20002015
2001- const handleResetContentType = async ( ) => {
2016+ const handleResetContentType = debounce ( async ( ) => {
2017+ // Prevent duplicate clicks
2018+ if ( isResetFetch ) return ;
2019+
20022020 const orgId = selectedOrganisation ?. value ;
20032021 const projectID = projectId ;
20042022 setIsDropDownChanged ( false ) ;
2005-
2023+ setIsResetFetch ( true ) ;
20062024 const updatedRows : FieldMapType [ ] = tableData ?. map ?.( ( row ) => {
20072025 return {
20082026 ...row ,
@@ -2056,6 +2074,7 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
20562074 } ) ;
20572075
20582076 if ( status === 200 ) {
2077+ setIsResetFetch ( false ) ;
20592078 const updatedContentMapping = { ...newMigrationData ?. content_mapping ?. content_type_mapping } ;
20602079 delete updatedContentMapping [ selectedContentType ?. contentstackUid ] ;
20612080
@@ -2089,9 +2108,10 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
20892108 notificationContent : { text : data ?. message } ,
20902109 notificationProps : {
20912110 position : 'bottom-center' ,
2092- hideProgressBar : false
2111+ hideProgressBar : true
20932112 } ,
2094- type : 'success'
2113+ type : 'success' ,
2114+ autoClose : 2
20952115 } ) ;
20962116
20972117 try {
@@ -2106,112 +2126,30 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
21062126 } catch ( error ) {
21072127 console . error ( error ) ;
21082128 return error ;
2129+ } finally {
2130+ // Re-enable icon after API completes
2131+ setIsResetFetch ( false ) ;
21092132 }
21102133 }
2111- } ;
2112-
2113- const handleCTDeleted = async ( isContentType : boolean , contentTypes : ContentTypeList [ ] ) => {
2114- const updatedContentTypeMapping = Object . fromEntries (
2115- Object . entries ( newMigrationData ?. content_mapping ?. content_type_mapping || { } ) ?. filter (
2116- ( [ key ] ) => ! selectedContentType ?. contentstackUid ?. includes ?.( key )
2117- )
2118- ) ;
2119-
2120- const orgId = selectedOrganisation ?. value ;
2121- const projectID = projectId ;
2122- setIsDropDownChanged ( false ) ;
2123-
2124- const updatedRows : FieldMapType [ ] = tableData . map ( ( row ) => {
2125- return { ...row , contentstackFieldType : row ?. backupFieldType } ;
2126- } ) ;
2127- setTableData ( updatedRows ) ;
2128- setSelectedEntries ( updatedRows ) ;
2129-
2130- const dataCs = {
2131- contentTypeData : {
2132- status : selectedContentType ?. status ,
2133- id : selectedContentType ?. id ,
2134- projectId : projectId ,
2135- otherCmsTitle : otherCmsTitle ,
2136- otherCmsUid : selectedContentType ?. otherCmsUid ,
2137- isUpdated : true ,
2138- updateAt : new Date ( ) ,
2139- contentstackTitle : selectedContentType ?. contentstackTitle ,
2140- contentstackUid : selectedContentType ?. contentstackUid ,
2141- fieldMapping : updatedRows
2142- }
2143- } ;
2144- let newstate = { } ;
2145- setContentTypeMapped ( ( prevState : ContentTypeMap ) => {
2146- const newState = { ...prevState } ;
2147-
2148- delete newState [ selectedContentType ?. contentstackUid ?? '' ] ;
2149- newstate = newState ;
2150-
2151- return newstate ;
2152- } ) ;
2153-
2154- if ( orgId && selectedContentType ) {
2155- try {
2156- const { data, status } = await resetToInitialMapping (
2157- orgId ,
2158- projectID ,
2159- selectedContentType ?. id ?? '' ,
2160- dataCs
2161- ) ;
2162-
2163- setExistingField ( { } ) ;
2164- setContentTypeSchema ( [ ] ) ;
2165- setOtherContentType ( {
2166- label : `Select ${ isContentType ? 'Content Type' : 'Global Field' } from Destination Stack` ,
2167- value : `Select ${ isContentType ? 'Content Type' : 'Global Field' } from Destination Stack`
2168- } ) ;
2169-
2170- if ( status === 200 ) {
2171- const resetCT = filteredContentTypes ?. map ?.( ct =>
2172- ct ?. id === selectedContentType ?. id ? { ...ct , status : data ?. data ?. status } : ct
2173- ) ;
2174- setFilteredContentTypes ( resetCT ) ;
2175- setContentTypes ( resetCT ) ;
2176-
2177- try {
2178- await updateContentMapper ( orgId , projectID , { ...newstate } ) ;
2179- } catch ( err ) {
2180- console . error ( err ) ;
2181- return err ;
2182- }
2183-
2184- }
2185- } catch ( error ) {
2186- console . error ( error ) ;
2187- return error ;
2188- }
2189- }
2190-
2191- const newMigrationDataObj : INewMigration = {
2192- ...newMigrationData ,
2193- content_mapping : {
2194- ...newMigrationData ?. content_mapping ,
2195- [ isContentType ? 'existingCT' : 'existingGlobal' ] : contentTypes ,
2196- content_type_mapping : updatedContentTypeMapping
2197-
2198- }
2199-
2200- }
2201- dispatch ( updateNewMigrationData ( newMigrationDataObj ) ) ;
2202-
2203- }
2134+ } , 1500 ) ;
2135+ /**
2136+ * Retrieves existing content types for a given project.
2137+ * @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.
2138+ */
2139+ const handleFetchContentType = debounce ( async ( ) => {
2140+ // Prevent duplicate clicks
2141+ if ( isResetFetch ) return ;
22042142
2205- /**
2206- * Retrieves existing content types for a given project.
2207- * @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.
2208- */
2209- const handleFetchContentType = async ( ) => {
2143+ setIsResetFetch ( true ) ;
2144+
22102145 if ( isContentType ) {
22112146 try {
2147+
2148+
22122149 const { data, status } = await getExistingContentTypes ( projectId , otherContentType ?. id ?? '' ) ;
22132150 if ( status == 201 && data ?. contentTypes ?. length > 0 ) {
22142151 ( otherContentType ?. id === data ?. selectedContentType ?. uid ) && setsCsCTypeUpdated ( false ) ;
2152+ setIsResetFetch ( false ) ;
22152153
22162154 ( otherContentType ?. id && otherContentType ?. label !== data ?. selectedContentType ?. title && data ?. selectedContentType ?. title )
22172155 && setOtherContentType ( {
@@ -2233,7 +2171,7 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
22332171 notificationContent : { text : 'Content Types fetched successfully' } ,
22342172 notificationProps : {
22352173 position : 'bottom-center' ,
2236- hideProgressBar : false
2174+ hideProgressBar : true
22372175 } ,
22382176 type : 'success'
22392177 } ) ;
@@ -2256,13 +2194,17 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
22562194 } catch ( error ) {
22572195 console . error ( error ) ;
22582196 return error ;
2197+ } finally {
2198+ // Re-enable icon after API completes
2199+ setIsResetFetch ( false ) ;
22592200 }
22602201 } else {
22612202 try {
22622203 const { data, status } = await getExistingGlobalFields ( projectId , otherContentType ?. id ?? '' ) ;
22632204
22642205 if ( status == 201 && data ?. globalFields ?. length > 0 ) {
22652206 ( otherContentType ?. id === data ?. selectedGlobalField ?. uid ) && setsCsCTypeUpdated ( false ) ;
2207+ setIsResetFetch ( false ) ;
22662208
22672209 ( otherContentType ?. id && otherContentType ?. label !== data ?. selectedGlobalField ?. title && data ?. selectedGlobalField ?. title )
22682210 && setOtherContentType ( {
@@ -2311,6 +2253,9 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
23112253 } catch ( error ) {
23122254 console . error ( error ) ;
23132255 return error ;
2256+ } finally {
2257+ // Re-enable icon after API completes
2258+ setIsResetFetch ( false ) ;
23142259 }
23152260 }
23162261
@@ -2340,6 +2285,106 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
23402285
23412286 } ) ;
23422287 }
2288+ } , 1500 ) ;
2289+
2290+ /**
2291+ * Handles the deletion of a content type or global field.
2292+ * @param isContentType - Whether the content type is a content type or global field.
2293+ * @param contentTypes - The content types to delete.
2294+ */
2295+ const handleCTDeleted = async ( isContentType : boolean , contentTypes : ContentTypeList [ ] ) => {
2296+ // Prevent duplicate clicks
2297+ if ( isResetFetch ) return ;
2298+
2299+ const updatedContentTypeMapping = Object . fromEntries (
2300+ Object . entries ( newMigrationData ?. content_mapping ?. content_type_mapping || { } ) ?. filter (
2301+ ( [ key ] ) => ! selectedContentType ?. contentstackUid ?. includes ?.( key )
2302+ )
2303+ ) ;
2304+
2305+ const orgId = selectedOrganisation ?. value ;
2306+ const projectID = projectId ;
2307+ setIsDropDownChanged ( false ) ;
2308+
2309+ const updatedRows : FieldMapType [ ] = tableData . map ( ( row ) => {
2310+ return { ...row , contentstackFieldType : row ?. backupFieldType } ;
2311+ } ) ;
2312+ setTableData ( updatedRows ) ;
2313+ setSelectedEntries ( updatedRows ) ;
2314+
2315+ const dataCs = {
2316+ contentTypeData : {
2317+ status : selectedContentType ?. status ,
2318+ id : selectedContentType ?. id ,
2319+ projectId : projectId ,
2320+ otherCmsTitle : otherCmsTitle ,
2321+ otherCmsUid : selectedContentType ?. otherCmsUid ,
2322+ isUpdated : true ,
2323+ updateAt : new Date ( ) ,
2324+ contentstackTitle : selectedContentType ?. contentstackTitle ,
2325+ contentstackUid : selectedContentType ?. contentstackUid ,
2326+ fieldMapping : updatedRows
2327+ }
2328+ } ;
2329+ let newstate = { } ;
2330+ setContentTypeMapped ( ( prevState : ContentTypeMap ) => {
2331+ const newState = { ...prevState } ;
2332+
2333+ delete newState [ selectedContentType ?. contentstackUid ?? '' ] ;
2334+ newstate = newState ;
2335+
2336+ return newstate ;
2337+ } ) ;
2338+
2339+ if ( orgId && selectedContentType ) {
2340+ try {
2341+ const { data, status } = await resetToInitialMapping (
2342+ orgId ,
2343+ projectID ,
2344+ selectedContentType ?. id ?? '' ,
2345+ dataCs
2346+ ) ;
2347+
2348+ setExistingField ( { } ) ;
2349+ setContentTypeSchema ( [ ] ) ;
2350+ setOtherContentType ( {
2351+ label : `Select ${ isContentType ? 'Content Type' : 'Global Field' } from Destination Stack` ,
2352+ value : `Select ${ isContentType ? 'Content Type' : 'Global Field' } from Destination Stack`
2353+ } ) ;
2354+
2355+ if ( status === 200 ) {
2356+ const resetCT = filteredContentTypes ?. map ?.( ct =>
2357+ ct ?. id === selectedContentType ?. id ? { ...ct , status : data ?. data ?. status } : ct
2358+ ) ;
2359+ setFilteredContentTypes ( resetCT ) ;
2360+ setContentTypes ( resetCT ) ;
2361+
2362+ try {
2363+ await updateContentMapper ( orgId , projectID , { ...newstate } ) ;
2364+ } catch ( err ) {
2365+ console . error ( err ) ;
2366+ return err ;
2367+ }
2368+
2369+ }
2370+ } catch ( error ) {
2371+ console . error ( error ) ;
2372+ return error ;
2373+ }
2374+ }
2375+
2376+ const newMigrationDataObj : INewMigration = {
2377+ ...newMigrationData ,
2378+ content_mapping : {
2379+ ...newMigrationData ?. content_mapping ,
2380+ [ isContentType ? 'existingCT' : 'existingGlobal' ] : contentTypes ,
2381+ content_type_mapping : updatedContentTypeMapping
2382+
2383+ }
2384+
2385+ }
2386+ dispatch ( updateNewMigrationData ( newMigrationDataObj ) ) ;
2387+
23432388 }
23442389
23452390 const columns = [
@@ -2621,7 +2666,7 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
26212666 < Tooltip content = { 'Fetch content types from destination stack' } position = "top" >
26222667 < Button className = 'icon-padding' buttonType = "light" icon = { onlyIcon ? "v2-FetchTemplate" : '' }
26232668 version = "v2" onlyIcon = { true } onlyIconHoverColor = { 'primary' }
2624- size = 'small' onClick = { handleFetchContentType } >
2669+ size = 'small' onClick = { handleFetchContentType } disabled = { isResetFetch } >
26252670 </ Button >
26262671 </ Tooltip >
26272672 </ >
@@ -2630,7 +2675,7 @@ const ContentMapper = forwardRef(({ handleStepChange }: contentMapperProps, ref:
26302675 < Tooltip content = { 'Reset to system mapping' } position = "top" >
26312676 < Button className = 'icon-padding' buttonType = "light" icon = { onlyIcon ? "v2-ResetReverse" : '' }
26322677 version = "v2" onlyIcon = { true } onlyIconHoverColor = { 'primary' }
2633- size = 'small' onClick = { handleResetContentType } > </ Button >
2678+ size = 'small' onClick = { handleResetContentType } disabled = { isResetFetch } > </ Button >
26342679 </ Tooltip >
26352680 </ div >
26362681 ) ,
0 commit comments