@@ -38,11 +38,86 @@ import subscribeTo from 'lib/subscribeTo';
38
38
import * as ColumnPreferences from 'lib/ColumnPreferences' ;
39
39
import * as ClassPreferences from 'lib/ClassPreferences' ;
40
40
import { Helmet } from 'react-helmet' ;
41
+ import { useBeforeUnload } from 'react-router-dom' ;
41
42
import generatePath from 'lib/generatePath' ;
42
43
import { withRouter } from 'lib/withRouter' ;
43
44
import { get } from 'lib/AJAX' ;
44
45
import BrowserFooter from './BrowserFooter.react' ;
45
46
47
+ const SELECTED_ROWS_MESSAGE =
48
+ 'There are selected rows. Are you sure you want to leave this page?' ;
49
+
50
+ function SelectedRowsNavigationPrompt ( { when } ) {
51
+ const message = SELECTED_ROWS_MESSAGE ;
52
+
53
+ React . useEffect ( ( ) => {
54
+ if ( ! when ) {
55
+ return ;
56
+ }
57
+
58
+ const handleBeforeUnload = event => {
59
+ event . preventDefault ( ) ;
60
+ event . returnValue = message ;
61
+ return message ;
62
+ } ;
63
+
64
+ const handleLinkClick = event => {
65
+ if ( event . defaultPrevented ) {
66
+ return ;
67
+ }
68
+ if ( event . button !== 0 ) {
69
+ return ;
70
+ }
71
+ if ( event . metaKey || event . altKey || event . ctrlKey || event . shiftKey ) {
72
+ return ;
73
+ }
74
+ const anchor = event . target . closest ( 'a[href]' ) ;
75
+ if ( ! anchor || anchor . target === '_blank' ) {
76
+ return ;
77
+ }
78
+ const href = anchor . getAttribute ( 'href' ) ;
79
+ if ( ! href || href === '#' ) {
80
+ return ;
81
+ }
82
+ if ( ! window . confirm ( message ) ) {
83
+ event . preventDefault ( ) ;
84
+ event . stopPropagation ( ) ;
85
+ }
86
+ } ;
87
+
88
+ const handlePopState = ( ) => {
89
+ if ( ! window . confirm ( message ) ) {
90
+ window . history . go ( 1 ) ;
91
+ }
92
+ } ;
93
+
94
+ window . addEventListener ( 'beforeunload' , handleBeforeUnload ) ;
95
+ document . addEventListener ( 'click' , handleLinkClick , true ) ;
96
+ window . addEventListener ( 'popstate' , handlePopState ) ;
97
+
98
+ return ( ) => {
99
+ window . removeEventListener ( 'beforeunload' , handleBeforeUnload ) ;
100
+ document . removeEventListener ( 'click' , handleLinkClick , true ) ;
101
+ window . removeEventListener ( 'popstate' , handlePopState ) ;
102
+ } ;
103
+ } , [ when , message ] ) ;
104
+
105
+ useBeforeUnload (
106
+ React . useCallback (
107
+ event => {
108
+ if ( when ) {
109
+ event . preventDefault ( ) ;
110
+ event . returnValue = message ;
111
+ return message ;
112
+ }
113
+ } ,
114
+ [ when , message ]
115
+ )
116
+ ) ;
117
+
118
+ return null ;
119
+ }
120
+
46
121
// The initial and max amount of rows fetched by lazy loading
47
122
const BROWSER_LAST_LOCATION = 'brower_last_location' ;
48
123
@@ -879,6 +954,11 @@ class Browser extends DashboardView {
879
954
}
880
955
881
956
async refresh ( ) {
957
+ if ( Object . keys ( this . state . selection ) . length > 0 ) {
958
+ if ( ! window . confirm ( SELECTED_ROWS_MESSAGE ) ) {
959
+ return ;
960
+ }
961
+ }
882
962
const relation = this . state . relation ;
883
963
const prevFilters = this . state . filters || new List ( ) ;
884
964
const initialState = {
@@ -2446,6 +2526,9 @@ class Browser extends DashboardView {
2446
2526
< Helmet >
2447
2527
< title > { pageTitle } </ title >
2448
2528
</ Helmet >
2529
+ < SelectedRowsNavigationPrompt
2530
+ when = { Object . keys ( this . state . selection ) . length > 0 }
2531
+ />
2449
2532
{ browser }
2450
2533
{ notification }
2451
2534
{ extras }
0 commit comments