Skip to content

Commit d4410d3

Browse files
authored
Merge pull request #146 from os-checker/feat/filetree-route-query
feat(file-tree): implement route query
2 parents 443af6c + 756cc95 commit d4410d3

File tree

2 files changed

+163
-71
lines changed

2 files changed

+163
-71
lines changed

os-checks/components/FileTree2.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ const heightCodePanel = computed(() => {
8484
const adjust = displayFilters.value ? 100 : 0;
8585
return `${height * 0.85 - adjust}px`;
8686
});
87+
88+
const lockURL = defineModel("lockURL", { default: false });
89+
const lockURLIcon = computed(() => lockURL.value ? "pi pi-lock" : "pi pi-lock-open");
8790
</script>
8891

8992
<template>
@@ -100,9 +103,13 @@ const heightCodePanel = computed(() => {
100103
<Button class="btn" :icon="displayFiltersIcon" severity="secondary" variant="text"
101104
@click="() => displayFilters = !displayFilters" />
102105
</div>
106+
<div>
107+
<Button class="btn" :icon="lockURLIcon" severity="secondary" variant="text"
108+
@click="() => lockURL = !lockURL" />
109+
</div>
103110
</div>
104111
<div v-if="count" style="padding-right: 0.6rem;">
105-
<b style="margin-right: 10px;">Total Count:</b>
112+
<b style="margin-right: 6px;">Total Count:</b>
106113
<Button class="btn" severity="danger" @click="resetSelectKey"> {{ count }} </Button>
107114
</div>
108115
</div>

os-checks/pages/file-tree.vue

Lines changed: 155 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,37 @@
1212
<div style="padding: 6px 8px 6px 8px">
1313
<span class="input">User:</span>
1414
<span class="select">
15-
<Select v-model="selectedUser" filter :options="users" :optionLabel="label" />
15+
<Select v-model="selected.user" filter :options="users" :optionLabel="label" />
1616
</span>
1717

1818
<span class="input">Repo:</span>
1919
<span class="select">
20-
<Select v-model="selectedRepo" filter :options="repos" :optionLabel="label" />
20+
<Select v-model="selected.repo" filter :options="repos" :optionLabel="label" />
2121
</span>
2222

23-
<DropDownWithCount v-model="selectedTarget" tag="Target" :all="ALL_TARGETS" :counts="targets" />
23+
<DropDownWithCount v-model="selected.target" tag="Target" :all="ALL_TARGETS" :counts="targets" />
2424

2525
</div>
2626

2727
<div style="padding: 2px 8px 10px 8px">
2828

29-
<DropDownWithCount v-model="selectedChecker" tag="Checker" :all="ALL_CHECKERS" :counts="checkers" />
30-
<DropDownWithCount v-model="selectedKind" tag="Kind" :all="ALL_KINDS" :counts="kinds" />
29+
<DropDownWithCount v-model="selected.pkg" tag="Pkg" :all="ALL_PKGS" :counts="pkgs" />
30+
<DropDownWithCount v-model="selected.features" tag="Features" :all="ALL_FEATURES_SETS" :counts="features" />
3131

32-
<DropDownWithCount v-model="selectedPkg" tag="Pkg" :all="ALL_PKGS" :counts="pkgs" />
33-
34-
<DropDownWithCount v-model="selectedFeatures" tag="Features" :all="ALL_FEATURES_SETS" :counts="features" />
35-
<!-- <span class="input">Features:</span> -->
36-
<!-- <span class="select"> -->
37-
<!-- <Select v-model="selectedFeatures" filter showClear :options="features" :optionLabel="label" -->
38-
<!-- placeholder="" /> -->
39-
<!-- </span> -->
32+
<DropDownWithCount v-model="selected.checker" tag="Checker" :all="ALL_CHECKERS" :counts="checkers" />
33+
<DropDownWithCount v-model="selected.kind" tag="Kind" :all="ALL_KINDS" :counts="kinds" />
4034

4135
</div>
4236
</div>
4337

4438
</div>
4539

46-
<FileTree2 :get="got2" :count="count" v-model:filters="displayFilters" />
40+
<FileTree2 :get="got2" :count="count" v-model:filters="displayFilters" v-model:lockURL="lockURL" />
4741
</div>
4842
</template>
4943

5044
<script lang="ts" setup>
51-
import { cloneDeep } from 'es-toolkit/compat';
45+
import { cloneDeep, includes } from 'es-toolkit/compat';
5246
import type { FetchError } from 'ofetch';
5347
import { Severity, type FileTree } from '~/shared/file-tree';
5448
import { Dropdown, gen_map, gen_targets } from '~/shared/file-tree/dropdown';
@@ -62,13 +56,25 @@ highlightRust();
6256
6357
const label = (a: string) => a;
6458
65-
const selectedUser = ref("");
66-
const selectedRepo = ref("");
67-
const selectedPkg = ref<string | null>(null);
68-
const selectedChecker = ref<string | null>(null);
69-
const selectedKind = ref<string | null>(null);
70-
const selectedTarget = ref(ALL_TARGETS);
71-
const selectedFeatures = ref<string | null>(null);
59+
const selected = reactive<{
60+
user: string,
61+
repo: string,
62+
target: string | null,
63+
pkg: string | null,
64+
features: string | null,
65+
checker: string | null,
66+
kind: string | null,
67+
}>({
68+
user: "",
69+
repo: "",
70+
target: ALL_TARGETS,
71+
pkg: null,
72+
features: null,
73+
checker: null,
74+
kind: null,
75+
});
76+
// watch(selected, val => console.log(val));
77+
7278
const displayFilters = ref(true);
7379
7480
const got = ref<Get>(getEmpty());
@@ -82,26 +88,54 @@ githubFetch<UserRepo>({ path: "ui/user_repo.json" })
8288
8389
// Init filters.
8490
const users = computed(() => Object.keys(user_repo.value).sort());
85-
watch(users, (val) => selectedUser.value = val[0] ?? "");
86-
const repos = computed(() => user_repo.value[selectedUser.value]);
87-
watch(repos, (val) => selectedRepo.value = val[0] ?? "");
91+
const repos = computed(() => user_repo.value[selected.user]);
92+
const targets = computed<DropDownOptions>(() => {
93+
const t = basic.value?.targets;
94+
return t ? gen_targets(t) : emptyOptions();
95+
});
96+
97+
const lockURL = ref(false);
98+
type Params = {
99+
user?: string,
100+
repo?: string,
101+
target?: string,
102+
pkg?: string,
103+
features?: string,
104+
checker?: string,
105+
kind?: string,
106+
lock?: string,
107+
};
108+
// given query
109+
const query_params = reactive<Params>({});
110+
111+
// init user & repo, considering route query if any
112+
watch(user_repo, val => {
113+
const { user, repo, target } = query_params;
114+
if (user && repo) {
115+
selected.user = user;
116+
selected.repo = repo;
117+
if (target && target !== ALL_TARGETS) selected.target = target;
118+
} else {
119+
const user = Object.keys(val).sort()[0] ?? "";
120+
selected.user = user;
121+
selected.repo = val[user][0] ?? "";
122+
}
123+
});
88124
89125
// Update got state.
90-
watch(() => ({ user: selectedUser.value, repo: selectedRepo.value, target: selectedTarget.value }),
126+
watch(() => ({ user: selected.user, repo: selected.repo, target: selected.target }),
91127
({ user, repo, target }) => {
92-
if (user && repo) {
93-
const target_ = target || ALL_TARGETS;
94-
get(`ui/repos/${user}/${repo}/${target_}.json`);
128+
if (user && includes(repos.value, repo)) {
129+
get(`ui/repos/${user}/${repo}/${target || ALL_TARGETS}.json`);
95130
getBasic(`ui/repos/${user}/${repo}/basic.json`);
131+
} else if (user && repos.value[0]) {
132+
// repo is not present, maybe user is selected, but not for repo
133+
selected.repo = repos.value[0];
134+
selected.target = ALL_TARGETS;
96135
}
97136
}
98137
);
99138
100-
const targets = computed<DropDownOptions>(() => {
101-
const t = basic.value?.targets;
102-
return t ? gen_targets(t) : emptyOptions();
103-
});
104-
105139
const pkgs = ref(emptyOptions());
106140
const kinds = ref(emptyOptions());
107141
const checkers = ref(emptyOptions());
@@ -128,17 +162,19 @@ function get_ck_kinds(ck: string | null): string[] | null {
128162
}
129163
return null;
130164
}
131-
// switch to another Get
132-
watch(got, g => {
165+
166+
function switch_got(g: Get) {
167+
if (lock_filters()) return;
168+
133169
// reset pkg and features since it's less likely to see the same selected pkg in another repo
134-
selectedPkg.value = null;
135-
selectedFeatures.value = null;
170+
selected.pkg = null;
171+
selected.features = null;
136172
137173
// reset kind if the diagnositc is empty
138-
selectedKind.value = Dropdown.find_kind(selectedKind.value, g);
174+
selected.kind = Dropdown.find_kind(selected.kind, g);
139175
140176
// reset checker if the diagnositc is empty
141-
const ck_kinds = get_ck_kinds(selectedChecker.value);
177+
const ck_kinds = get_ck_kinds(selected.checker);
142178
let reset_checker = true;
143179
if (ck_kinds) {
144180
for (const kind of ck_kinds) {
@@ -148,27 +184,47 @@ watch(got, g => {
148184
}
149185
}
150186
}
151-
if (reset_checker) selectedChecker.value = null;
152-
});
187+
if (reset_checker) selected.checker = null;
188+
}
189+
190+
function lock_filters(): boolean {
191+
const init = query_params.lock === "true";
192+
// should be called only once in startup
193+
if (init) {
194+
lockURL.value = true;
195+
const { pkg, features, checker, kind } = query_params;
196+
if (pkg) selected.pkg = pkg;
197+
if (features) selected.features = features;
198+
if (checker) selected.checker = checker;
199+
if (kind) selected.kind = kind;
200+
query_params.lock = undefined;
201+
}
202+
return init;
203+
}
153204
154205
// watch selection changes
155206
watch(
156207
() => ({
157-
pkg: selectedPkg.value, feat: selectedFeatures.value,
158-
kind: selectedKind.value, ck: selectedChecker.value, g: got.value
208+
pkg: selected.pkg, feat: selected.features,
209+
kind: selected.kind, ck: selected.checker,
210+
g: got.value, b: basic.value
159211
}),
160-
({ pkg, feat, kind, ck, g }) => {
161-
const target = cloneDeep(g);
212+
({ pkg, feat, kind, ck, g }, old) => {
213+
if (old.g !== g) return switch_got(g);
214+
lockURL.value = false;
162215
163-
Dropdown.update_by_features(feat, target);
164-
Dropdown.update_by_pkg(pkg, target);
216+
const val = cloneDeep(g);
165217
218+
Dropdown.update_by_features(feat, val);
219+
Dropdown.update_by_pkg(pkg, val);
220+
221+
// get_ck_kinds relies on basic: if basic is not ready, spurious null is got
166222
const ck_kinds = get_ck_kinds(ck);
167-
if (ck_kinds) Dropdown.update_by_checker(ck_kinds, target);
223+
if (ck_kinds) Dropdown.update_by_checker(ck_kinds, val);
168224
169-
Dropdown.update_by_kind(kind, target);
225+
Dropdown.update_by_kind(kind, val);
170226
171-
got2.value = target;
227+
got2.value = val;
172228
}
173229
);
174230
@@ -220,7 +276,7 @@ function get(path: string) {
220276
// kind: "Not Exists!", raw: ["该目标架构下,无原始报告数据。"],
221277
// lang: "rust", severity: Severity.Danger, disabled: false
222278
// }];
223-
// selectedTab.value = "Not Exists!";
279+
// selected.tab.value = "Not Exists!";
224280
// fileTree.value = { kinds_order: [], data: [] };
225281
});
226282
}
@@ -230,6 +286,53 @@ function getBasic(path: string) {
230286
.then(val => basic.value = val)
231287
.catch(err => console.log(err))
232288
}
289+
290+
// route query
291+
const route = useRoute();
292+
function updateFilter(query: Params) {
293+
const { user, repo, target, pkg, features, checker, kind, lock } = query;
294+
295+
if (user) { query_params.user = decodeURIComponent(user); }
296+
if (repo) { query_params.repo = decodeURIComponent(repo); }
297+
if (target) { query_params.target = decodeURIComponent(target); }
298+
if (pkg) { query_params.pkg = decodeURIComponent(pkg); }
299+
if (features !== undefined) { query_params.features = decodeURIComponent(features); }
300+
if (checker) { query_params.checker = decodeURIComponent(checker); }
301+
if (kind) { query_params.kind = decodeURIComponent(kind); }
302+
if (lock === "true") {
303+
query_params.lock = decodeURIComponent(lock);
304+
lockURL.value = false;
305+
}
306+
}
307+
updateFilter(route.query);
308+
309+
const router = useRouter();
310+
// emit query
311+
const router_params = ref<Params | null>(null);
312+
watch(router_params, query => router.push({ path: route.path, query: query || {} }));
313+
314+
watch(lockURL, lock => {
315+
if (!lock) {
316+
router_params.value = {};
317+
return;
318+
}
319+
320+
const { user, repo, target, pkg, features, checker, kind } = selected;
321+
322+
let query: any = {};
323+
324+
if (user) query.user = encodeURIComponent(user);
325+
if (repo) query.repo = encodeURIComponent(repo);
326+
if (target && target !== ALL_TARGETS) query.target = encodeURIComponent(target);
327+
if (pkg) query.pkg = encodeURIComponent(pkg);
328+
if (features !== null) query.features = encodeURIComponent(features);
329+
if (checker) query.checker = encodeURIComponent(checker);
330+
if (kind) query.kind = encodeURIComponent(kind);
331+
332+
query.lock = encodeURIComponent("true");
333+
334+
router_params.value = query;
335+
});
233336
</script>
234337

235338
<!-- FIXME: remove these -->
@@ -244,22 +347,4 @@ function getBasic(path: string) {
244347
.select {
245348
padding-right: 10px;
246349
}
247-
248-
.resolved-table {
249-
--p-datatable-header-cell-color: var(--p-button-primary-background);
250-
}
251-
252-
.sources {
253-
color: var(--p-orange-400);
254-
}
255-
256-
.sources-table {
257-
--p-datatable-header-cell-color: var(--p-orange-400);
258-
}
259-
260-
.drop-down-options {
261-
margin-right: 8px;
262-
width: 40px;
263-
justify-content: right;
264-
}
265350
</style>

0 commit comments

Comments
 (0)