Skip to content

Commit a23334c

Browse files
Merge pull request Ericsson#4952 from xb058t/file-path-numbers
Make file tree stat cells clickable to filter reports
2 parents 1721ac1 + 0c0954e commit a23334c

1 file changed

Lines changed: 131 additions & 13 deletions

File tree

web/server/vue-cli/src/views/Reports.vue

Lines changed: 131 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
<pane size="20" :style="{ 'min-width': '320px' }">
66
<ReportFilter
77
:report-count="totalItems"
8+
:refresh-filter="refreshFilterState"
89
@refresh="refresh"
10+
@set-refresh-filter-state="setRefreshFilterState"
911
/>
1012
</pane>
1113
<pane>
@@ -350,24 +352,64 @@
350352
class="tree-item-label clickable"
351353
@click.stop="onTreeItemClick(item)"
352354
>{{ item.name }}</span>
353-
<span class="tree-stat-cell">{{ item.findings }}</span>
354-
<span class="tree-stat-cell">{{ item.stats.style || '' }}</span>
355-
<span class="tree-stat-cell">{{ item.stats.low || '' }}</span>
356-
<span class="tree-stat-cell">{{ item.stats.medium || '' }}</span>
357-
<span class="tree-stat-cell">{{ item.stats.high || '' }}</span>
358-
<span class="tree-stat-cell">
355+
<span
356+
class="tree-stat-cell"
357+
:class="{ clickable: item.findings }"
358+
@click.stop="onTreeStatClick(item, 'all')"
359+
>{{ item.findings }}</span>
360+
<span
361+
class="tree-stat-cell"
362+
:class="{ clickable: item.stats.style }"
363+
@click.stop="onTreeStatClick(item, 'style')"
364+
>{{ item.stats.style || '' }}</span>
365+
<span
366+
class="tree-stat-cell"
367+
:class="{ clickable: item.stats.low }"
368+
@click.stop="onTreeStatClick(item, 'low')"
369+
>{{ item.stats.low || '' }}</span>
370+
<span
371+
class="tree-stat-cell"
372+
:class="{ clickable: item.stats.medium }"
373+
@click.stop="onTreeStatClick(item, 'medium')"
374+
>{{ item.stats.medium || '' }}</span>
375+
<span
376+
class="tree-stat-cell"
377+
:class="{ clickable: item.stats.high }"
378+
@click.stop="onTreeStatClick(item, 'high')"
379+
>{{ item.stats.high || '' }}</span>
380+
<span
381+
class="tree-stat-cell"
382+
:class="{ clickable: item.stats.critical }"
383+
@click.stop="onTreeStatClick(item, 'critical')"
384+
>
359385
{{ item.stats.critical || '' }}
360386
</span>
361-
<span class="tree-stat-cell">
387+
<span
388+
class="tree-stat-cell"
389+
:class="{ clickable: item.stats.unreviewed }"
390+
@click.stop="onTreeStatClick(item, 'unreviewed')"
391+
>
362392
{{ item.stats.unreviewed || '' }}
363393
</span>
364-
<span class="tree-stat-cell">
394+
<span
395+
class="tree-stat-cell"
396+
:class="{ clickable: item.stats.confirmed }"
397+
@click.stop="onTreeStatClick(item, 'confirmed')"
398+
>
365399
{{ item.stats.confirmed || '' }}
366400
</span>
367-
<span class="tree-stat-cell">
401+
<span
402+
class="tree-stat-cell"
403+
:class="{ clickable: item.stats.false_positive }"
404+
@click.stop="onTreeStatClick(item, 'false_positive')"
405+
>
368406
{{ item.stats.false_positive || '' }}
369407
</span>
370-
<span class="tree-stat-cell">
408+
<span
409+
class="tree-stat-cell"
410+
:class="{ clickable: item.stats.intentional }"
411+
@click.stop="onTreeStatClick(item, 'intentional')"
412+
>
371413
{{ item.stats.intentional || '' }}
372414
</span>
373415
</div>
@@ -388,6 +430,7 @@ import { ccService, handleThriftError } from "@cc-api";
388430
import {
389431
Checker,
390432
Order,
433+
ReviewStatus,
391434
Severity,
392435
SortMode,
393436
SortType
@@ -396,6 +439,8 @@ import { SET_REPORT_FILTER } from "@/store/mutations.type";
396439
397440
import { useGradientColor } from "@/composables/useGradientColor";
398441
import { useDetectionStatus } from "@/composables/useDetectionStatus";
442+
import { useSeverity } from "@/composables/useSeverity";
443+
import { useReviewStatus } from "@/composables/useReviewStatus";
399444
import {
400445
DetectionStatusIcon,
401446
ReviewStatusIcon,
@@ -412,6 +457,9 @@ const router = useRouter();
412457
const store = useStore();
413458
const gradientColor = useGradientColor();
414459
const detectionStatus = useDetectionStatus();
460+
const severity = useSeverity();
461+
const reviewStatus = useReviewStatus();
462+
const refreshFilterState = ref(false);
415463
416464
const itemsPerPageOptions = [
417465
{ value: 25, title: "25" },
@@ -665,13 +713,74 @@ function setReportFilter(params) {
665713
store.commit(SET_REPORT_FILTER, params);
666714
}
667715
668-
function onTreeItemClick(item) {
716+
const SEVERITY_STAT_KEYS = {
717+
style: Severity.STYLE,
718+
low: Severity.LOW,
719+
medium: Severity.MEDIUM,
720+
high: Severity.HIGH,
721+
critical: Severity.CRITICAL
722+
};
723+
724+
const REVIEW_STATUS_STAT_KEYS = {
725+
unreviewed: ReviewStatus.UNREVIEWED,
726+
confirmed: ReviewStatus.CONFIRMED,
727+
false_positive: ReviewStatus.FALSE_POSITIVE,
728+
intentional: ReviewStatus.INTENTIONAL
729+
};
730+
731+
function getTreeItemFilePattern(item) {
669732
const isDir = item.children && item.children.length > 0;
670-
const pattern = isDir ? item.fullPath + "/*" : item.fullPath;
671-
setReportFilter({ filepath: [ pattern ] });
733+
return isDir ? item.fullPath + "/*" : item.fullPath;
734+
}
735+
736+
function setRefreshFilterState(state) {
737+
refreshFilterState.value = state;
738+
}
739+
740+
// Push the given filter values into the URL and let ReportFilter's
741+
// initByUrl() (triggered via the refresh-filter prop) apply them to the
742+
// individual filter components and the store, instead of writing to the
743+
// store directly and leaving the URL/filters out of sync.
744+
async function applyTreeFilter(params) {
745+
const query = { ...route.query };
746+
747+
if (params.filepath) {
748+
query["filepath"] = params.filepath;
749+
}
750+
if (params.severity) {
751+
query["severity"] =
752+
params.severity.map(s => severity.severityFromCodeToString(s));
753+
}
754+
if (params.reviewStatus) {
755+
query["review-status"] = params.reviewStatus.map(
756+
s => reviewStatus.reviewStatusFromCodeToString(s)
757+
);
758+
}
759+
760+
await router.replace({ query }).catch(() => {});
761+
setRefreshFilterState(true);
672762
viewMode.value = "table";
673763
}
674764
765+
function onTreeItemClick(item) {
766+
applyTreeFilter({ filepath: [ getTreeItemFilePattern(item) ] });
767+
}
768+
769+
function onTreeStatClick(item, statKey) {
770+
const count = statKey === "all" ? item.findings : item.stats[statKey];
771+
if (!count) return;
772+
773+
const params = { filepath: [ getTreeItemFilePattern(item) ] };
774+
775+
if (statKey in SEVERITY_STAT_KEYS) {
776+
params.severity = [ SEVERITY_STAT_KEYS[statKey] ];
777+
} else if (statKey in REVIEW_STATUS_STAT_KEYS) {
778+
params.reviewStatus = [ REVIEW_STATUS_STAT_KEYS[statKey] ];
779+
}
780+
781+
applyTreeFilter(params);
782+
}
783+
675784
function toggleTreeSort(statKey) {
676785
if (treeSortKey.value !== statKey) {
677786
treeSortKey.value = statKey;
@@ -1055,6 +1164,15 @@ body {
10551164
text-align: center;
10561165
flex-shrink: 0;
10571166
font-size: 0.8em;
1167+
1168+
&.clickable {
1169+
cursor: pointer;
1170+
1171+
&:hover {
1172+
text-decoration: underline;
1173+
color: rgb(var(--v-theme-primary));
1174+
}
1175+
}
10581176
}
10591177
10601178
.v-data-table {

0 commit comments

Comments
 (0)