1
- import { Box , Button , Divider , FileInput , Modal , Stack , Text } from '@mantine/core' ;
1
+ import { Box , Button , Divider , FileInput , Modal , Stack , Text , TextInput } from '@mantine/core' ;
2
2
import Toolbar from './Toolbar' ;
3
3
import 'react-grid-layout/css/styles.css' ;
4
4
import 'react-resizable/css/styles.css' ;
@@ -20,10 +20,10 @@ import { useDashboardsQuery } from '@/hooks/useDashboards';
20
20
import Tile from './Tile' ;
21
21
import { Layout } from 'react-grid-layout' ;
22
22
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider' ;
23
- import { ImportDashboardType } from '@/@types/parseable/api/dashboards' ;
23
+ import { EditTileType , ImportDashboardType , Tile as TileType } from '@/@types/parseable/api/dashboards' ;
24
24
import { templates } from './assets/templates' ;
25
25
26
- const { toggleCreateDashboardModal, toggleCreateTileModal, toggleDeleteTileModal, handlePaging, toggleImportDashboardModal } =
26
+ const { toggleCreateDashboardModal, toggleCreateTileModal, toggleDuplicateTileModal , toggleDeleteTileModal, handlePaging, toggleImportDashboardModal } =
27
27
dashboardsStoreReducers ;
28
28
29
29
const TilesView = ( props : { onLayoutChange : ( layout : Layout [ ] ) => void } ) => {
@@ -319,6 +319,78 @@ const NoTilesView = () => {
319
319
) ;
320
320
} ;
321
321
322
+ const findTileByTileId = ( tiles : TileType [ ] , tileId : string | null ) => {
323
+ return _ . find ( tiles , tile => tile . tile_id === tileId )
324
+ }
325
+
326
+ const DuplicateTileModal = ( ) => {
327
+ const [ duplicateTileModalOpen , setDashboardsStore ] = useDashboardsStore ( store => store . duplicateTileModalOpen )
328
+ const [ editTileId ] = useDashboardsStore ( store => store . editTileId ) ;
329
+ const [ activeDashboard ] = useDashboardsStore ( store => store . activeDashboard )
330
+ const [ inputValue , setInputValue ] = useState < string > ( '' ) ;
331
+ const onClose = useCallback ( ( ) => {
332
+ setDashboardsStore ( ( store ) => toggleDuplicateTileModal ( store , false , null ) ) ;
333
+ } , [ ] ) ;
334
+
335
+ const handleInputChange = useCallback ( ( e : React . ChangeEvent < HTMLInputElement > ) => {
336
+ setInputValue ( e . target . value ) ;
337
+ } , [ ] ) ;
338
+ const { updateDashboard, isUpdatingDashboard } = useDashboardsQuery ( { } ) ;
339
+
340
+ const handleSubmit = useCallback ( ( ) => {
341
+ const currentTile = findTileByTileId ( activeDashboard ?. tiles || [ ] , editTileId ) ;
342
+ if ( currentTile && activeDashboard ) {
343
+ const currentOrder = currentTile . order ;
344
+ const tempTiles = [ ...activeDashboard . tiles ] as EditTileType [ ] ;
345
+ const duplicatedTile = _ . omit ( { ...currentTile , name : inputValue } , 'tile_id' ) ;
346
+ tempTiles . splice ( currentOrder , 0 , duplicatedTile ) ;
347
+ const updatedTilesWithOrder = assignOrderToTiles ( tempTiles ) ;
348
+ return updateDashboard ( {
349
+ dashboard : { ...activeDashboard , tiles : updatedTilesWithOrder } ,
350
+ onSuccess : ( ) => {
351
+ onClose ( ) ;
352
+ } ,
353
+ } ) ;
354
+ }
355
+ } , [ inputValue , editTileId , activeDashboard ] ) ;
356
+
357
+ useEffect ( ( ) => {
358
+ const currentTile = findTileByTileId ( activeDashboard ?. tiles || [ ] , editTileId ) ;
359
+ if ( currentTile ) {
360
+ setInputValue ( currentTile ?. name ) ;
361
+ }
362
+ } , [ editTileId ] ) ;
363
+
364
+ return (
365
+ < Modal
366
+ opened = { duplicateTileModalOpen }
367
+ onClose = { onClose }
368
+ size = "auto"
369
+ centered
370
+ styles = { {
371
+ body : { padding : '0 1rem 1rem 1rem' , width : 400 } ,
372
+ header : { padding : '1rem' , paddingBottom : '0.4rem' } ,
373
+ } }
374
+ title = { < Text style = { { fontSize : '0.9rem' , fontWeight : 600 } } > Duplicate Tile</ Text > } >
375
+ < Stack >
376
+ < Stack gap = { 12 } >
377
+ < TextInput value = { inputValue } onChange = { handleInputChange } />
378
+ </ Stack >
379
+ < Stack style = { { flexDirection : 'row' , alignItems : 'center' , justifyContent : 'flex-end' } } >
380
+ < Box >
381
+ < Button onClick = { onClose } variant = "outline" >
382
+ Cancel
383
+ </ Button >
384
+ </ Box >
385
+ < Box >
386
+ < Button onClick = { handleSubmit } loading = { isUpdatingDashboard } disabled = { _ . isEmpty ( inputValue ) } > Done</ Button >
387
+ </ Box >
388
+ </ Stack >
389
+ </ Stack >
390
+ </ Modal >
391
+ ) ;
392
+ } ;
393
+
322
394
const Dashboard = ( ) => {
323
395
const [ dashboards ] = useDashboardsStore ( ( store ) => store . dashboards ) ;
324
396
const layoutRef = useRef < Layout [ ] > ( [ ] ) ;
@@ -333,6 +405,7 @@ const Dashboard = () => {
333
405
return (
334
406
< Stack style = { { flex : 1 } } gap = { 0 } >
335
407
< DeleteTileModal />
408
+ < DuplicateTileModal />
336
409
< Toolbar layoutRef = { layoutRef } />
337
410
< ImportDashboardModal />
338
411
< TilesView onLayoutChange = { onLayoutChange } />
0 commit comments