@@ -92,6 +92,7 @@ export function Component(props: TabsProps) {
9292 const [ addTabDialogOpen , setAddTabDialogOpen ] = React . useState ( false ) ;
9393 const [ name , setName ] = React . useState ( '' ) ;
9494 const [ renameModalOpen , setRenameModalOpen ] = React . useState ( false ) ;
95+ const [ copyModalOpen , setCopyModalOpen ] = React . useState ( false ) ;
9596 const [ currentTab , setCurrentTab ] = React . useState < TabItem | null > ( null ) ;
9697
9798 const onChange = ( key : string ) => {
@@ -184,7 +185,37 @@ export function Component(props: TabsProps) {
184185 }
185186 setRenameModalOpen ( false ) ;
186187 } ;
188+ const handleCopy = async ( key : string , newName : string ) => {
189+ if ( props . storage && props . project ) {
190+ try {
191+ let newPath = await commonStorage . copyModuleInProject (
192+ props . storage ,
193+ props . project ,
194+ newName ,
195+ key
196+ ) ;
197+ const newTabs = [ ...props . tabList ] ;
198+
199+ // find the original tab to copy its type
200+ const originalTab = props . tabList . find ( tab => tab . key === key ) ;
201+ if ( ! originalTab ) {
202+ console . error ( 'Original tab not found for copying:' , key ) ;
203+ props . setAlertErrorMessage ( 'Original tab not found for copying' ) ;
204+ return ;
205+ }
206+ // Add the new tab with the copied name and type
207+ newTabs . push ( { key : newPath , title : newName , type : originalTab . type } ) ;
187208
209+ props . setTabList ( newTabs ) ;
210+ setActiveKey ( newPath ) ; // Use newPath instead of key
211+ props . setProject ( { ...props . project , } ) ;
212+ } catch ( error ) {
213+ console . error ( 'Error copying module:' , error ) ;
214+ props . setAlertErrorMessage ( 'Failed to copy module' ) ;
215+ }
216+ }
217+ setCopyModalOpen ( false ) ;
218+ } ;
188219 return (
189220 < >
190221 { contextHolder }
@@ -225,7 +256,34 @@ export function Component(props: TabsProps) {
225256 />
226257 ) }
227258 </ Antd . Modal >
228-
259+ < Antd . Modal
260+ title = { `Copy ${ currentTab ? TabTypeUtils . toString ( currentTab . type ) : '' } : ${ currentTab ? currentTab . title : '' } ` }
261+ open = { copyModalOpen }
262+ onCancel = { ( ) => setCopyModalOpen ( false ) }
263+ onOk = { ( ) => {
264+ if ( currentTab ) {
265+ handleCopy ( currentTab . key , name ) ;
266+ }
267+ } }
268+ okText = { t ( "Copy" ) }
269+ cancelText = { t ( "Cancel" ) }
270+ >
271+ { currentTab && (
272+ < ModuleNameComponent
273+ tabType = { currentTab . type }
274+ newItemName = { name }
275+ setNewItemName = { setName }
276+ onAddNewItem = { ( ) => {
277+ if ( currentTab ) {
278+ handleCopy ( currentTab . key , name ) ;
279+ }
280+ } }
281+ project = { props . project }
282+ storage = { props . storage }
283+ buttonLabel = ""
284+ />
285+ ) }
286+ </ Antd . Modal >
229287 < Antd . Tabs
230288 type = "editable-card"
231289 onChange = { onChange }
@@ -293,7 +351,7 @@ export function Component(props: TabsProps) {
293351 props . setTabList ( newTabs ) ;
294352 if ( props . storage && props . project ) {
295353 commonStorage . removeModuleFromProject ( props . storage , props . project , tab . key ) ;
296- props . setProject ( { ...props . project , } ) ;
354+ props . setProject ( { ...props . project , } ) ;
297355 }
298356 setActiveKey ( props . tabList [ 0 ] . key ) ;
299357 } ,
@@ -304,7 +362,14 @@ export function Component(props: TabsProps) {
304362 key : 'copy' ,
305363 label : t ( 'Copy...' ) ,
306364 disabled : tab . type === TabType . ROBOT ,
307- icon : < CopyOutlined />
365+ icon : < CopyOutlined /> ,
366+ onClick : ( ) => {
367+ // Find the current tab to get the latest title
368+ const currentTab = props . tabList . find ( t => t . key === tab . key ) ;
369+ setName ( ( currentTab ? currentTab . title : tab . title ) + "Copy" ) ;
370+ setCurrentTab ( currentTab || tab ) ;
371+ setCopyModalOpen ( true ) ;
372+ } ,
308373 } ,
309374 ] ,
310375 } }
0 commit comments