1
- import React , { useState , useRef } from 'react' ;
1
+ import React , { useState , useRef , useCallback } from 'react' ;
2
2
import { useParams , useSearchParams } from 'react-router-dom' ;
3
3
import { useSelector } from 'react-redux' ;
4
4
import useFileStorage from '@hooks/useFileStorage' ;
@@ -10,7 +10,7 @@ import NewFileOrFolder from './NewFileOrFolder';
10
10
import FileList from './FileList' ;
11
11
import Pagination from '@shared/Pagination' ;
12
12
import QueryPage from '@shared/layouts/QueryPage' ;
13
-
13
+ import Dialog from '@shared/Dialog' ;
14
14
import { currentSite } from '@selectors/site' ;
15
15
16
16
function FileStoragePage ( ) {
@@ -60,49 +60,69 @@ function FileStoragePage() {
60
60
function scrollToTop ( ) {
61
61
return scrollTo . current ?. scrollIntoView ( { behavior : 'smooth' , block : 'start' } ) ;
62
62
}
63
- const handleNavigate = ( newPath ) => {
64
- const decodedPath = decodeURIComponent ( newPath ) ;
65
- // Remove trailing slash if it exists
66
- // eslint-disable-next-line sonarjs/slow-regex
67
- let normalizedPath = `${ decodedPath . replace ( / \/ + $ / , '' ) } ` ;
63
+ const handleNavigate = useCallback (
64
+ ( newPath ) => {
65
+ const decodedPath = decodeURIComponent ( newPath ) ;
66
+ // Remove trailing slash if it exists
67
+ // eslint-disable-next-line sonarjs/slow-regex
68
+ let normalizedPath = `${ decodedPath . replace ( / \/ + $ / , '' ) } ` ;
68
69
69
- if ( normalizedPath !== '/' ) {
70
- normalizedPath += '/' ; // Ensure folders always end with "/"
71
- }
72
- searchParams . delete ( 'details' ) ;
73
- searchParams . delete ( 'page' ) ;
70
+ if ( normalizedPath !== '/' ) {
71
+ normalizedPath += '/' ; // Ensure folders always end with "/"
72
+ }
73
+ searchParams . delete ( 'details' ) ;
74
+ searchParams . delete ( 'page' ) ;
74
75
75
- setSearchParams ( ( prev ) => {
76
- const newParams = new URLSearchParams ( prev ) ;
77
- newParams . set ( 'path' , normalizedPath ) ;
78
- return newParams ;
79
- } ) ;
80
- scrollToTop ( ) ;
81
- } ;
76
+ setSearchParams ( ( prev ) => {
77
+ const newParams = new URLSearchParams ( prev ) ;
78
+ newParams . set ( 'path' , normalizedPath ) ;
79
+ return newParams ;
80
+ } ) ;
81
+ scrollToTop ( ) ;
82
+ } ,
83
+ [ setSearchParams ] ,
84
+ ) ;
82
85
83
- const handlePageChange = ( newPage ) => {
84
- if ( newPage === currentPage ) return ;
85
- setSearchParams ( ( prev ) => {
86
- const newParams = new URLSearchParams ( prev ) ;
87
- newParams . set ( 'page' , newPage ) ;
88
- return newParams ;
89
- } ) ;
90
- scrollToTop ( ) ;
86
+ const INITIAL_DIALOG_PROPS = {
87
+ open : false ,
91
88
} ;
89
+ const resetModal = useCallback ( ( ) => {
90
+ setDialogProps ( INITIAL_DIALOG_PROPS ) ;
91
+ } , [ ] ) ;
92
92
93
- const handleViewDetails = ( file ) => {
94
- setHighlightItem ( file ) ;
95
- setSavedScrollPos ( window . pageYOffset ) ;
96
- setSearchParams ( {
97
- ...Object . fromEntries ( searchParams ) ,
98
- details : file ,
99
- } ) ;
93
+ const [ dialogProps , setDialogProps ] = useState ( {
94
+ closeHandler : resetModal ,
95
+ } ) ;
100
96
101
- // scroll all the way up, this view is short
102
- window . scrollTo ( { top : 0 } ) ;
103
- } ;
97
+ const handlePageChange = useCallback (
98
+ ( newPage ) => {
99
+ if ( newPage === currentPage ) return ;
100
+ setSearchParams ( ( prev ) => {
101
+ const newParams = new URLSearchParams ( prev ) ;
102
+ newParams . set ( 'page' , newPage ) ;
103
+ return newParams ;
104
+ } ) ;
105
+ scrollToTop ( ) ;
106
+ } ,
107
+ [ currentPage , setSearchParams ] ,
108
+ ) ;
109
+
110
+ const handleViewDetails = useCallback (
111
+ ( file ) => {
112
+ setHighlightItem ( file ) ;
113
+ setSavedScrollPos ( window . pageYOffset ) ;
114
+ setSearchParams ( {
115
+ ...Object . fromEntries ( searchParams ) ,
116
+ details : file ,
117
+ } ) ;
118
+
119
+ // scroll all the way up, this view is short
120
+ window . scrollTo ( { top : 0 } ) ;
121
+ } ,
122
+ [ setSearchParams , searchParams ] ,
123
+ ) ;
104
124
105
- const handleCloseDetails = ( ) => {
125
+ const handleCloseDetails = useCallback ( ( ) => {
106
126
setSearchParams ( ( prev ) => {
107
127
const newParams = new URLSearchParams ( prev ) ;
108
128
newParams . delete ( 'details' ) ;
@@ -112,41 +132,60 @@ function FileStoragePage() {
112
132
setTimeout ( ( ) => {
113
133
window . scrollTo ( { top : savedScrollPos , behavior : 'smooth' } ) ;
114
134
} , 100 ) ;
115
- } ;
135
+ } , [ setSearchParams , savedScrollPos ] ) ;
116
136
117
- const handleSort = ( sortKey ) => {
118
- const currentSortKey = searchParams . get ( 'sortKey' ) || DEFAULT_SORT_KEY ;
119
- const currentSortOrder = searchParams . get ( 'sortOrder' ) || DEFAULT_SORT_ORDER ;
137
+ const handleSort = useCallback (
138
+ ( sortKey ) => {
139
+ const currentSortKey = searchParams . get ( 'sortKey' ) || DEFAULT_SORT_KEY ;
140
+ const currentSortOrder = searchParams . get ( 'sortOrder' ) || DEFAULT_SORT_ORDER ;
120
141
121
- let newSortOrder ;
122
- if ( currentSortKey === sortKey ) {
123
- // Toggle the sort order if the same column is clicked
124
- newSortOrder =
125
- currentSortOrder === DEFAULT_SORT_ORDER ? REVERSE_SORT_ORDER : DEFAULT_SORT_ORDER ;
126
- } else {
127
- // Alpha sort is better done in ASC, not DESC
128
- newSortOrder = REVERSE_SORT_ORDER ;
129
- }
130
- setSearchParams ( {
131
- ...Object . fromEntries ( searchParams ) ,
132
- sortKey,
133
- sortOrder : newSortOrder ,
134
- page : 1 ,
135
- } ) ;
136
- } ;
142
+ let newSortOrder ;
143
+ if ( currentSortKey === sortKey ) {
144
+ // Toggle the sort order if the same column is clicked
145
+ newSortOrder =
146
+ currentSortOrder === DEFAULT_SORT_ORDER
147
+ ? REVERSE_SORT_ORDER
148
+ : DEFAULT_SORT_ORDER ;
149
+ } else {
150
+ // Alpha sort is better done in ASC, not DESC
151
+ newSortOrder = REVERSE_SORT_ORDER ;
152
+ }
153
+ setSearchParams ( {
154
+ ...Object . fromEntries ( searchParams ) ,
155
+ sortKey,
156
+ sortOrder : newSortOrder ,
157
+ page : 1 ,
158
+ } ) ;
159
+ } ,
160
+ [ setSearchParams , searchParams ] ,
161
+ ) ;
137
162
138
- const handleDelete = async ( item ) => {
139
- const isFolder = item . type === 'directory' ;
140
- const confirmMessage = isFolder
141
- ? // eslint-disable-next-line sonarjs/slow-regex
163
+ const handleDelete = useCallback (
164
+ async ( item ) => {
165
+ const isFolder = item . type === 'directory' ;
166
+ const confirmMessage = isFolder
167
+ ? // eslint-disable-next-line sonarjs/slow-regex
142
168
`Are you sure you want to delete the folder "${ item . name . replace ( / \/ + $ / , '' ) } "?
143
169
Please check that it does not contain any files.`
144
- : `Are you sure you want to delete the file "${ item . name } "?` ;
145
-
146
- if ( ! window . confirm ( confirmMessage ) ) return ;
147
-
148
- await deleteItem ( item ) ;
149
- } ;
170
+ : `Are you sure you want to delete the file "${ item . name } "?` ;
171
+ const deleteHandler = async ( ) => {
172
+ await deleteItem ( item ) ;
173
+ resetModal ( ) ;
174
+ } ;
175
+ setDialogProps ( {
176
+ ...dialogProps ,
177
+ open : true ,
178
+ header : 'Are you sure?' ,
179
+ message : confirmMessage ,
180
+ primaryButton : 'Yes, I want to delete' ,
181
+ primaryHandler : deleteHandler ,
182
+ secondaryButton : 'Cancel' ,
183
+ secondaryHandler : resetModal ,
184
+ closeHandler : resetModal ,
185
+ } ) ;
186
+ } ,
187
+ [ deleteItem , resetModal ] ,
188
+ ) ;
150
189
151
190
const handleUpload = async ( files ) => {
152
191
await Promise . all ( files . map ( ( file ) => uploadFile ( path , file ) ) ) ;
@@ -155,6 +194,7 @@ function FileStoragePage() {
155
194
const handleCreateFolder = async ( folderName ) => {
156
195
await createFolder ( path , folderName ) ;
157
196
} ;
197
+
158
198
return (
159
199
< QueryPage
160
200
data = { fetchedPublicFiles }
@@ -203,7 +243,7 @@ function FileStoragePage() {
203
243
message = { createFolderSuccess }
204
244
/>
205
245
) }
206
-
246
+ < Dialog { ... dialogProps } />
207
247
< div className = "grid-col-12" ref = { scrollTo } >
208
248
< LocationBar
209
249
path = { path }
0 commit comments