Skip to content

Commit efc9a8e

Browse files
committed
Change URL when changing filters in compare page
This is a regression, I missed this functionality when porting the page to TypeScript.
1 parent 665e70d commit efc9a8e

File tree

4 files changed

+110
-7
lines changed

4 files changed

+110
-7
lines changed

site/frontend/src/pages/compare/header/filters.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,25 @@ import Toggle from "../toggle.vue";
33
import {DataFilter} from "../types";
44
import Tooltip from "../tooltip.vue";
55
import {ref, toRaw, watch} from "vue";
6+
import {deepCopy} from "../../../utils/copy";
67
7-
const props = defineProps<{defaultFilter: DataFilter}>();
8+
const props = defineProps<{
9+
// When reset, set filter to this value
10+
defaultFilter: DataFilter,
11+
// Initialize the filter with this value
12+
initialFilter: DataFilter
13+
}>();
814
const emit = defineEmits<{
915
(e: "change", filter: DataFilter): void;
1016
(e: "export"): void;
1117
}>();
1218
1319
function reset() {
14-
filter.value = props.defaultFilter;
20+
// We must not change the default filter
21+
filter.value = deepCopy(props.defaultFilter);
1522
}
1623
17-
let filter = ref({...props.defaultFilter});
24+
let filter = ref(deepCopy(props.initialFilter));
1825
watch(filter, (newValue, _) => {
1926
emit("change", toRaw(newValue));
2027
}, {deep: true});

site/frontend/src/pages/compare/page.vue

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
<script setup lang="ts">
22
import {loadBenchmarkInfo} from "../../api";
33
import AsOf from "../../components/as-of.vue";
4-
import {createUrlParams, getUrlParams, navigateToUrlParams} from "../../utils/navigation";
4+
import {
5+
createUrlFromParams,
6+
createUrlParams,
7+
getUrlParams,
8+
navigateToUrlParams
9+
} from "../../utils/navigation";
510
import {computed, Ref, ref} from "vue";
611
import {withLoading} from "../../utils/loading";
712
import {postMsgpack} from "../../utils/requests";
@@ -34,6 +39,72 @@ function loadSelectorFromUrl(urlParams: Dict<string>): CompareSelector {
3439
};
3540
}
3641
42+
function loadFilterFromUrl(urlParams: Dict<string>, defaultFilter: DataFilter): DataFilter {
43+
function getBoolOrDefault(name: string, defaultValue: boolean): boolean {
44+
if (urlParams.hasOwnProperty(name)) {
45+
return urlParams[name] === "true";
46+
}
47+
return defaultValue;
48+
}
49+
50+
return {
51+
name: urlParams["name"] ?? defaultFilter.name,
52+
nonRelevant: getBoolOrDefault("nonRelevant", defaultFilter.nonRelevant),
53+
showRawData: getBoolOrDefault("showRawData", defaultFilter.showRawData),
54+
profile: {
55+
check: getBoolOrDefault("check", defaultFilter.profile.check),
56+
debug: getBoolOrDefault("debug", defaultFilter.profile.debug),
57+
opt: getBoolOrDefault("opt", defaultFilter.profile.opt),
58+
doc: getBoolOrDefault("doc", defaultFilter.profile.doc)
59+
},
60+
scenario: {
61+
full: getBoolOrDefault("full", defaultFilter.scenario.full),
62+
incrFull: getBoolOrDefault("incrFull", defaultFilter.scenario.incrFull),
63+
incrUnchanged: getBoolOrDefault("incrUnchanged", defaultFilter.scenario.incrUnchanged),
64+
incrPatched: getBoolOrDefault("incrPatched", defaultFilter.scenario.incrPatched)
65+
},
66+
category: {
67+
primary: getBoolOrDefault("primary", defaultFilter.category.primary),
68+
secondary: getBoolOrDefault("secondary", defaultFilter.category.secondary)
69+
}
70+
};
71+
}
72+
73+
/**
74+
* Stores the given filter parameters into URL, so that the current "view" can be shared with
75+
* others easily.
76+
*/
77+
function storeFilterToUrl(filter: DataFilter, defaultFilter: DataFilter, urlParams: Dict<string>) {
78+
function storeOrReset<T extends boolean | string>(name: string, value: T, defaultValue: T) {
79+
if (value === defaultValue) {
80+
if (urlParams.hasOwnProperty(name)) {
81+
delete urlParams[name];
82+
}
83+
} else {
84+
urlParams[name] = value.toString();
85+
}
86+
}
87+
88+
storeOrReset("name", filter.name || null, defaultFilter.name);
89+
storeOrReset("nonRelevant", filter.nonRelevant, defaultFilter.nonRelevant);
90+
storeOrReset("showRawData", filter.showRawData, defaultFilter.showRawData);
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(urlParams).toString());
105+
}
106+
}
107+
37108
async function loadCompareData(selector: CompareSelector, loading: Ref<boolean>) {
38109
const response: CompareResponse = await withLoading(loading, async () => {
39110
const params = {
@@ -54,10 +125,17 @@ function updateSelection(params: SelectionParams) {
54125
}));
55126
}
56127
128+
function updateFilter(newFilter: DataFilter) {
129+
filter.value = newFilter;
130+
storeFilterToUrl(newFilter, defaultFilter, getUrlParams());
131+
}
132+
57133
function exportData() {
58134
exportToMarkdown(testCases.value);
59135
}
60136
137+
const urlParams = getUrlParams();
138+
61139
const defaultFilter: DataFilter = {
62140
name: null,
63141
nonRelevant: false,
@@ -87,8 +165,8 @@ const filteredSummary = computed(() => computeSummary(testCases.value));
87165
const loading = ref(false);
88166
89167
const info = await loadBenchmarkInfo();
90-
const selector = loadSelectorFromUrl(getUrlParams());
91-
const filter = ref({...defaultFilter});
168+
const selector = loadSelectorFromUrl(urlParams);
169+
const filter = ref(loadFilterFromUrl(urlParams, defaultFilter));
92170
93171
const data: Ref<CompareResponse | null> = ref(null);
94172
loadCompareData(selector, loading);
@@ -104,7 +182,9 @@ loadCompareData(selector, loading);
104182
</div>
105183
<div v-if="data !== null">
106184
<QuickLinks :stat="selector.stat" />
107-
<Filters :defaultFilter="defaultFilter" @change="f => filter = f"
185+
<Filters :defaultFilter="defaultFilter"
186+
:initialFilter="filter"
187+
@change="updateFilter"
108188
@export="exportData" />
109189
<OverallTable :summary="filteredSummary" />
110190
<Aggregations :cases="testCases" />

site/frontend/src/utils/copy.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function deepCopy<T>(value: T): T {
2+
return JSON.parse(JSON.stringify(value));
3+
}

site/frontend/src/utils/navigation.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ export function createUrlWithParams(params: Dict<any>): URL {
1616
return url;
1717
}
1818

19+
/**
20+
* Creates a URL with the current window location and the passed parameters.
21+
*/
22+
export function createUrlFromParams(params: Dict<string>): URL {
23+
const url = new URL(window.location.toString());
24+
const searchParams = new URLSearchParams();
25+
for (const [key, value] of Object.entries(params)) {
26+
searchParams.set(key, value);
27+
}
28+
url.search = searchParams.toString();
29+
return url;
30+
}
31+
1932
export function getUrlParams(): Dict<string> {
2033
const url = new URL(window.location.toString());
2134

0 commit comments

Comments
 (0)