1
+ function getQueryParams ( ) {
2
+ return new URLSearchParams ( window . location . search ) ;
3
+ }
4
+
1
5
function findQueryParam ( name ) {
2
- let urlParams = window . location . search ?. substring ( 1 ) . split ( "&" ) . map ( x => x . split ( "=" ) ) ;
3
- let pair = urlParams ?. find ( x => x [ 0 ] === name )
4
- if ( pair ) {
5
- return unescape ( pair [ 1 ] ) ;
6
- }
6
+ const params = getQueryParams ( ) ;
7
+ return params . get ( name ) ;
7
8
}
8
9
9
10
function createDefaultFilter ( ) {
@@ -29,6 +30,81 @@ function createDefaultFilter() {
29
30
} ;
30
31
}
31
32
33
+ /**
34
+ * Loads the initial state of UI filters from URL parameters.
35
+ * Keep in sync with `storeFilterToUrl` and `createDefaultFilter`!
36
+ */
37
+ function initializeFilterFromUrl ( ) {
38
+ const defaultFilter = createDefaultFilter ( ) ;
39
+ const params = getQueryParams ( ) ;
40
+
41
+ function getBoolOrDefault ( name , defaultValue ) {
42
+ const urlValue = params . get ( name ) ;
43
+ if ( urlValue !== null ) {
44
+ return urlValue === "true" ;
45
+ }
46
+ return defaultValue ;
47
+ }
48
+
49
+ return {
50
+ name : params . get ( "name" ) ,
51
+ nonRelevant : getBoolOrDefault ( "nonRelevant" , defaultFilter . nonRelevant ) ,
52
+ profile : {
53
+ check : getBoolOrDefault ( "check" , defaultFilter . profile . check ) ,
54
+ debug : getBoolOrDefault ( "debug" , defaultFilter . profile . debug ) ,
55
+ opt : getBoolOrDefault ( "opt" , defaultFilter . profile . opt ) ,
56
+ doc : getBoolOrDefault ( "doc" , defaultFilter . profile . doc )
57
+ } ,
58
+ scenario : {
59
+ full : getBoolOrDefault ( "full" , defaultFilter . scenario . full ) ,
60
+ incrFull : getBoolOrDefault ( "incrFull" , defaultFilter . scenario . incrFull ) ,
61
+ incrUnchanged : getBoolOrDefault ( "incrUnchanged" , defaultFilter . scenario . incrUnchanged ) ,
62
+ incrPatched : getBoolOrDefault ( "incrPatched" , defaultFilter . scenario . incrPatched )
63
+ } ,
64
+ category : {
65
+ primary : getBoolOrDefault ( "primary" , defaultFilter . category . primary ) ,
66
+ secondary : getBoolOrDefault ( "secondary" , defaultFilter . category . secondary )
67
+ }
68
+ } ;
69
+ }
70
+
71
+ /**
72
+ * Stores the given filter parameters into URL, so that the current "view" can be shared with
73
+ * others easily.
74
+ */
75
+ function storeFilterToUrl ( filter ) {
76
+ const defaultFilter = createDefaultFilter ( ) ;
77
+ const params = getQueryParams ( ) ;
78
+
79
+ function storeOrReset ( name , value , defaultValue ) {
80
+ if ( value === defaultValue ) {
81
+ if ( params . has ( name ) ) {
82
+ params . delete ( name ) ;
83
+ }
84
+ } else {
85
+ params . set ( name , value ) ;
86
+ }
87
+ }
88
+
89
+ storeOrReset ( "name" , filter . name || null , defaultFilter . name ) ;
90
+ storeOrReset ( "nonRelevant" , filter . nonRelevant , defaultFilter . nonRelevant ) ;
91
+ storeOrReset ( "check" , filter . profile . check , defaultFilter . profile . check ) ;
92
+ storeOrReset ( "debug" , filter . profile . debug , defaultFilter . profile . debug ) ;
93
+ storeOrReset ( "opt" , filter . profile . opt , defaultFilter . profile . opt ) ;
94
+ storeOrReset ( "doc" , filter . profile . doc , defaultFilter . profile . doc ) ;
95
+ storeOrReset ( "full" , filter . scenario . full , defaultFilter . scenario . full ) ;
96
+ storeOrReset ( "incrFull" , filter . scenario . incrFull , defaultFilter . scenario . incrFull ) ;
97
+ storeOrReset ( "incrUnchanged" , filter . scenario . incrUnchanged , defaultFilter . scenario . incrUnchanged ) ;
98
+ storeOrReset ( "incrPatched" , filter . scenario . incrPatched , defaultFilter . scenario . incrPatched ) ;
99
+ storeOrReset ( "primary" , filter . category . primary , defaultFilter . category . primary ) ;
100
+ storeOrReset ( "secondary" , filter . category . secondary , defaultFilter . category . secondary ) ;
101
+
102
+ // Change URL without creating a history entry
103
+ if ( history . replaceState ) {
104
+ history . replaceState ( { } , null , createUrlFromParams ( params ) ) ;
105
+ }
106
+ }
107
+
32
108
const app = Vue . createApp ( {
33
109
mounted ( ) {
34
110
const app = this ;
@@ -46,12 +122,21 @@ const app = Vue.createApp({
46
122
} ,
47
123
data ( ) {
48
124
return {
49
- filter : createDefaultFilter ( ) ,
125
+ filter : initializeFilterFromUrl ( ) ,
50
126
showRawData : false ,
51
127
data : null ,
52
128
dataLoading : false
53
129
}
54
130
} ,
131
+ watch : {
132
+ // Every time the filter changes, update URL
133
+ filter : {
134
+ handler ( newValue , oldValue ) {
135
+ storeFilterToUrl ( newValue ) ;
136
+ } ,
137
+ deep : true
138
+ }
139
+ } ,
55
140
computed : {
56
141
notContinuous ( ) {
57
142
return ! this . data . is_contiguous ;
@@ -281,10 +366,9 @@ const app = Vue.createApp({
281
366
return result ;
282
367
} ,
283
368
createUrlForMetric ( metric ) {
284
- let start = findQueryParam ( "start" ) ;
285
- let end = findQueryParam ( "end" ) ;
286
-
287
- return createUrlFromParams ( createSearchParamsForMetric ( metric , start , end ) ) ;
369
+ const params = getQueryParams ( ) ;
370
+ params . set ( "stat" , metric ) ;
371
+ return createUrlFromParams ( params ) ;
288
372
} ,
289
373
resetFilter ( ) {
290
374
this . filter = createDefaultFilter ( ) ;
@@ -696,29 +780,22 @@ function makeData(state, app) {
696
780
} ) ;
697
781
}
698
782
699
- function createSearchParamsForMetric ( stat , start , end ) {
700
- let params = new URLSearchParams ( ) ;
701
- if ( start !== undefined ) {
702
- params . append ( "start" , start ) ;
703
- }
704
- if ( end !== undefined ) {
705
- params . append ( "end" , end ) ;
706
- }
707
- if ( stat !== undefined ) {
708
- params . append ( "stat" , stat ) ;
709
- }
710
- return params . toString ( ) ;
711
- }
712
-
713
783
function createUrlFromParams ( params ) {
714
- return window . location . protocol + "//" + window . location . host + window . location . pathname + "?" + params ;
784
+ const url = new URL ( window . location ) ;
785
+ url . search = params ;
786
+ return url . toString ( ) ;
715
787
}
716
788
717
789
function submitSettings ( ) {
718
790
let stat = getSelected ( "stats" ) ;
719
791
let start = document . getElementById ( "start-bound" ) . value ;
720
792
let end = document . getElementById ( "end-bound" ) . value ;
721
- let params = createSearchParamsForMetric ( stat , start , end ) ;
793
+
794
+ const params = getQueryParams ( ) ;
795
+ params . set ( "stat" , stat ) ;
796
+ params . set ( "start" , start ) ;
797
+ params . set ( "end" , end ) ;
798
+
722
799
window . location . search = params . toString ( ) ;
723
800
}
724
801
0 commit comments