@@ -3,7 +3,7 @@ import { arrayMove, SortableContext, useSortable } from '@dnd-kit/sortable';
33import { CSS } from '@dnd-kit/utilities' ;
44import AddIcon from '@mui/icons-material/Add' ;
55import { Box , Grid2 as Grid , Typography } from '@mui/material' ;
6- import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
6+ import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
77import shortid from 'shortid' ;
88
99import { WidgetContainer } from './WidgetContainer' ;
@@ -180,6 +180,9 @@ const GroupWidget: React.FC<GroupWidgetProps> = ({
180180 const [ isDraggingOut , setIsDraggingOut ] = useState ( false ) ;
181181 const [ isCurrentDropTarget , setIsCurrentDropTarget ] = useState ( false ) ;
182182
183+ // Add a ref to prevent duplicate execution
184+ const duplicationInProgress = useRef < Set < string > > ( new Set ( ) ) ;
185+
183186 // Detect mobile devices
184187 const isMobile = useMemo ( ( ) => {
185188 return (
@@ -418,43 +421,6 @@ const GroupWidget: React.FC<GroupWidgetProps> = ({
418421 setIsCurrentDropTarget ( false ) ;
419422 } ;
420423
421- // Handle item duplicate
422- const handleItemDuplicate = useCallback ( ( itemId : string ) => {
423- // Find the item in the group
424- const itemToDuplicate = items . find ( item => item . id === itemId ) ;
425- if ( ! itemToDuplicate ) {
426- console . error ( 'Could not find item to duplicate' ) ;
427- return ;
428- }
429-
430- // Create duplicated item with new ID
431- const duplicatedItem : GroupItem = {
432- ...JSON . parse ( JSON . stringify ( itemToDuplicate ) ) , // Deep clone
433- id : shortid . generate ( ) // New unique ID
434- } ;
435-
436- // Check if we've reached maximum capacity
437- if ( items . length >= MAX_ITEMS ) {
438- // Instead of showing error, pass the duplicated item to parent for adding to dashboard
439- if ( onItemDuplicate ) {
440- onItemDuplicate ( duplicatedItem ) ;
441- }
442- return ;
443- }
444-
445- // Find the index of the original item
446- const originalIndex = items . findIndex ( item => item . id === itemId ) ;
447-
448- // Insert the duplicate after the original
449- const updatedItems = [ ...items ] ;
450- updatedItems . splice ( originalIndex + 1 , 0 , duplicatedItem ) ;
451-
452- // Update the group's items
453- if ( onItemsChange ) {
454- onItemsChange ( updatedItems ) ;
455- }
456- } , [ items , MAX_ITEMS , onItemsChange , onItemDuplicate ] ) ;
457-
458424 // Handle item edit - Convert group item to dashboard item for edit form
459425 const handleItemEdit = useCallback ( ( itemId : string ) => {
460426 // Find the item in the group
@@ -593,7 +559,7 @@ const GroupWidget: React.FC<GroupWidgetProps> = ({
593559 id = { id }
594560 onEdit = { onEdit }
595561 onDelete = { onRemove }
596- onDuplicate = { onDuplicate }
562+ onDuplicate = { undefined }
597563 isHighlighted = { isHighlighted }
598564 customHeight = { layout === '2x3' || layout === '3x2' || layout === '4x2' ? DUAL_WIDGET_CONTAINER_HEIGHT : STANDARD_WIDGET_HEIGHT }
599565 >
@@ -682,10 +648,26 @@ const GroupWidget: React.FC<GroupWidgetProps> = ({
682648 onEdit = { handleItemEdit }
683649 onDelete = { handleItemDelete }
684650 onDuplicate = { ( ) => {
685- // Create a duplicate with a new ID
651+ // Prevent double execution
652+ const duplicateKey = `${ id } -${ item . id } ` ;
653+ if ( duplicationInProgress . current . has ( duplicateKey ) ) {
654+ console . log ( 'Duplication already in progress, ignoring' ) ;
655+ return ;
656+ }
657+
658+ duplicationInProgress . current . add ( duplicateKey ) ;
659+
660+ // Clear the flag after a short delay to allow the operation to complete
661+ setTimeout ( ( ) => {
662+ duplicationInProgress . current . delete ( duplicateKey ) ;
663+ } , 1000 ) ;
664+
665+ // Create a duplicate with a new ID using timestamp for uniqueness
666+ const groupItemId = `group-${ shortid . generate ( ) } -${ Date . now ( ) } ` ;
667+
686668 const duplicatedItem : GroupItem = {
687669 ...JSON . parse ( JSON . stringify ( item ) ) , // Deep clone
688- id : shortid . generate ( ) // New unique ID
670+ id : groupItemId // Extra- unique ID for group items
689671 } ;
690672
691673 // Check if group is at capacity
@@ -695,8 +677,15 @@ const GroupWidget: React.FC<GroupWidgetProps> = ({
695677 onItemDuplicate ( duplicatedItem ) ;
696678 }
697679 } else {
698- // Add within the group
699- handleItemDuplicate ( item . id ) ;
680+ // Add within the group directly - bypass any external handlers
681+ const originalIndex = items . findIndex ( groupItem => groupItem . id === item . id ) ;
682+ const updatedItems = [ ...items ] ;
683+ updatedItems . splice ( originalIndex + 1 , 0 , duplicatedItem ) ;
684+
685+ // Use React's functional state update to ensure we have the latest state
686+ if ( onItemsChange ) {
687+ onItemsChange ( updatedItems ) ;
688+ }
700689 }
701690 } }
702691 itemSize = { gridSettings . itemSize }
0 commit comments