1
1
function findQueryParam ( name ) {
2
- let params = new URLSearchParams ( window . location . search . slice ( 1 ) ) ;
2
+ const params = new URLSearchParams ( window . location . search . slice ( 1 ) ) ;
3
3
return params . get ( name ) ;
4
4
}
5
5
@@ -28,10 +28,11 @@ function createDefaultFilter() {
28
28
29
29
/**
30
30
* Loads the initial state of UI filters from URL parameters.
31
+ * Keep in sync with `storeFilterToUrl` and `createDefaultFilter`!
31
32
*/
32
33
function initializeFilterFromUrl ( ) {
33
34
const defaultFilter = createDefaultFilter ( ) ;
34
- let params = new URLSearchParams ( window . location . search . slice ( 1 ) ) ;
35
+ const params = new URLSearchParams ( window . location . search . slice ( 1 ) ) ;
35
36
36
37
function getBoolOrDefault ( name , defaultValue ) {
37
38
const urlValue = params . get ( name ) ;
@@ -63,6 +64,43 @@ function initializeFilterFromUrl() {
63
64
} ;
64
65
}
65
66
67
+ /**
68
+ * Stores the given filter parameters into URL, so that the current "view" can be shared with
69
+ * others easily.
70
+ */
71
+ function storeFilterToUrl ( filter ) {
72
+ const defaultFilter = createDefaultFilter ( ) ;
73
+ const params = new URLSearchParams ( window . location . search ) ;
74
+
75
+ function storeOrReset ( name , value , defaultValue ) {
76
+ if ( value === defaultValue ) {
77
+ if ( params . has ( name ) ) {
78
+ params . delete ( name ) ;
79
+ }
80
+ } else {
81
+ params . set ( name , value ) ;
82
+ }
83
+ }
84
+
85
+ storeOrReset ( "name" , filter . name || null , defaultFilter . name ) ;
86
+ storeOrReset ( "nonRelevant" , filter . nonRelevant , defaultFilter . nonRelevant ) ;
87
+ storeOrReset ( "check" , filter . profile . check , defaultFilter . profile . check ) ;
88
+ storeOrReset ( "debug" , filter . profile . debug , defaultFilter . profile . debug ) ;
89
+ storeOrReset ( "opt" , filter . profile . opt , defaultFilter . profile . opt ) ;
90
+ storeOrReset ( "doc" , filter . profile . doc , defaultFilter . profile . doc ) ;
91
+ storeOrReset ( "full" , filter . scenario . full , defaultFilter . scenario . full ) ;
92
+ storeOrReset ( "incrFull" , filter . scenario . incrFull , defaultFilter . scenario . incrFull ) ;
93
+ storeOrReset ( "incrUnchanged" , filter . scenario . incrUnchanged , defaultFilter . scenario . incrUnchanged ) ;
94
+ storeOrReset ( "incrPatched" , filter . scenario . incrPatched , defaultFilter . scenario . incrPatched ) ;
95
+ storeOrReset ( "primary" , filter . category . primary , defaultFilter . category . primary ) ;
96
+ storeOrReset ( "secondary" , filter . category . secondary , defaultFilter . category . secondary ) ;
97
+
98
+ // Change URL without creating a history entry
99
+ if ( history . replaceState ) {
100
+ history . replaceState ( { } , null , createUrlFromParams ( params ) ) ;
101
+ }
102
+ }
103
+
66
104
const app = Vue . createApp ( {
67
105
mounted ( ) {
68
106
const app = this ;
@@ -86,6 +124,15 @@ const app = Vue.createApp({
86
124
dataLoading : false
87
125
}
88
126
} ,
127
+ watch : {
128
+ // Every time the filter changes, update URL
129
+ filter : {
130
+ handler ( newValue , oldValue ) {
131
+ storeFilterToUrl ( newValue ) ;
132
+ } ,
133
+ deep : true
134
+ }
135
+ } ,
89
136
computed : {
90
137
notContinuous ( ) {
91
138
return ! this . data . is_contiguous ;
@@ -735,7 +782,9 @@ function createSearchParamsForMetric(stat, start, end) {
735
782
}
736
783
737
784
function createUrlFromParams ( params ) {
738
- return window . location . protocol + "//" + window . location . host + window . location . pathname + "?" + params ;
785
+ const url = new URL ( window . location ) ;
786
+ url . search = params ;
787
+ return url . toString ( ) ;
739
788
}
740
789
741
790
function submitSettings ( ) {
0 commit comments