Add a placeholder to the cards for the security-hub (#19536)

1. Related issue #19249

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Shijun Sun 2023-11-15 16:23:07 +08:00 committed by GitHub
parent 7718134301
commit 30730c6716
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 157 additions and 95 deletions

View File

@ -119,43 +119,55 @@
</div>
</div>
<div class="card-block pt-1">
<div
class="clr-row row"
*ngFor="let item of securitySummary?.dangerous_artifacts">
<div class="clr-col">
<a
class="search"
href="javascript:void(0)"
appScrollAnchor="{{ vulId }}"
(click)="searchRepoClick(item)"
title="{{ item.repository_name }}">
<span class="ellipsis">
<clr-icon shape="search"></clr-icon
>{{ item.repository_name }}
</span>
</a>
</div>
<div class="clr-col" title="{{ item?.digest }}">
<a
href="javascript:void(0)"
[routerLink]="
getDigestLink(
item?.project_id,
item?.repository_name,
item.digest
)
"
><span class="ellipsis">{{
item?.digest?.slice(0, 15)
}}</span>
</a>
</div>
<div class="clr-col">
<div class="single-bar-container">
<app-single-bar
[dangerousArtifact]="item"></app-single-bar>
<ng-container *ngIf="securitySummary?.dangerous_artifacts?.length"
><div
class="clr-row row"
*ngFor="let item of securitySummary?.dangerous_artifacts">
<div class="clr-col">
<a
class="search"
href="javascript:void(0)"
appScrollAnchor="{{ vulId }}"
(click)="searchRepoClick(item)"
title="{{ item.repository_name }}">
<span class="ellipsis">
<clr-icon shape="search"></clr-icon
>{{ item.repository_name }}
</span>
</a>
</div>
</div>
<div class="clr-col" title="{{ item?.digest }}">
<a
href="javascript:void(0)"
[routerLink]="
getDigestLink(
item?.project_id,
item?.repository_name,
item.digest
)
"
><span class="ellipsis">{{
item?.digest?.slice(0, 15)
}}</span>
</a>
</div>
<div class="clr-col">
<div class="single-bar-container">
<app-single-bar
[dangerousArtifact]="item"></app-single-bar>
</div>
</div></div
></ng-container>
<div
class="datagrid-placeholder"
*ngIf="
!loadingSummary &&
!securitySummary?.dangerous_artifacts?.length
">
<div class="datagrid-placeholder-image"></div>
<span class="datagrid-placeholder-content">{{
'SECURITY_HUB.NO_VUL' | translate
}}</span>
</div>
</div>
</div>
@ -178,67 +190,91 @@
</div>
</div>
<div class="card-block pt-1">
<div
class="clr-row row"
*ngFor="let item of securitySummary?.dangerous_cves">
<div class="clr-col-4">
<a
class="search"
href="javascript:void(0)"
appScrollAnchor="{{ vulId }}"
(click)="searchCVEClick(item?.cve_id)"
title="{{ item.cve_id }}">
<span class="ellipsis">
<clr-icon shape="search"></clr-icon
>{{ item.cve_id }}
<ng-container *ngIf="securitySummary?.dangerous_cves?.length"
><div
class="clr-row row"
*ngFor="let item of securitySummary?.dangerous_cves">
<div class="clr-col-4">
<a
class="search"
href="javascript:void(0)"
appScrollAnchor="{{ vulId }}"
(click)="searchCVEClick(item?.cve_id)"
title="{{ item.cve_id }}">
<span class="ellipsis">
<clr-icon shape="search"></clr-icon
>{{ item.cve_id }}
</span>
</a>
</div>
<div class="clr-col-2">
<ng-container [ngSwitch]="item.severity">
<span
*ngSwitchCase="'Critical'"
class="label label-critical no-border"
>{{
severityText(item.severity) | translate
}}</span
>
<span
*ngSwitchCase="'High'"
class="label label-danger no-border"
>{{
severityText(item.severity) | translate
}}</span
>
<span
*ngSwitchCase="'Medium'"
class="label label-medium no-border"
>{{
severityText(item.severity) | translate
}}</span
>
<span
*ngSwitchCase="'Low'"
class="label label-low no-border"
>{{
severityText(item.severity) | translate
}}</span
>
<span
*ngSwitchCase="'None'"
class="label label-none no-border"
>{{
severityText(item.severity) | translate
}}</span
>
<span *ngSwitchDefault>{{
severityText(item.severity) | translate
}}</span>
</ng-container>
</div>
<div class="clr-col-2">
{{ item?.cvss_score_v3 }}
</div>
<div class="clr-col-4 ellipsis">
<span
*ngIf="item?.version"
title="{{ item?.package + '@' + item?.version }}">
{{ item?.package + '@' + item?.version }}
</span>
</a>
</div>
<div class="clr-col-2">
<ng-container [ngSwitch]="item.severity">
<span
*ngSwitchCase="'Critical'"
class="label label-critical no-border"
>{{ severityText(item.severity) | translate }}</span
>
<span
*ngSwitchCase="'High'"
class="label label-danger no-border"
>{{ severityText(item.severity) | translate }}</span
>
<span
*ngSwitchCase="'Medium'"
class="label label-medium no-border"
>{{ severityText(item.severity) | translate }}</span
>
<span
*ngSwitchCase="'Low'"
class="label label-low no-border"
>{{ severityText(item.severity) | translate }}</span
>
<span
*ngSwitchCase="'None'"
class="label label-none no-border"
>{{ severityText(item.severity) | translate }}</span
>
<span *ngSwitchDefault>{{
severityText(item.severity) | translate
}}</span>
</ng-container>
</div>
<div class="clr-col-2">
{{ item?.cvss_score_v3 }}
</div>
<div class="clr-col-4 ellipsis">
<span
*ngIf="item?.version"
title="{{ item?.package + '@' + item?.version }}">
{{ item?.package + '@' + item?.version }}
</span>
<span *ngIf="!item?.version" title="{{ item?.package }}">
{{ item?.package }}
</span>
</div>
*ngIf="!item?.version"
title="{{ item?.package }}">
{{ item?.package }}
</span>
</div>
</div></ng-container
>
<div
class="datagrid-placeholder"
*ngIf="
!loadingSummary && !securitySummary?.dangerous_cves?.length
">
<div class="datagrid-placeholder-image"></div>
<span class="datagrid-placeholder-content">{{
'SECURITY_HUB.NO_VUL' | translate
}}</span>
</div>
</div>
</div>

View File

@ -110,3 +110,25 @@ $row-height: 48px;
.label {
min-width: 3rem;
}
.datagrid-placeholder {
margin-top: 2.5rem;
border-top: 0;
padding: 0.6rem;
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: flex-start;
font-size: .8rem;
color: #b3b3b3;
}
.datagrid-placeholder-image {
height: 3rem;
width: 3rem;
margin-bottom: 0.6rem;
background-repeat: no-repeat;
background-size: contain;
background-position: center;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%220%200%2060%2072%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%0A%20%20%20%20%3Cdefs%3E%0A%20%20%20%20%20%20%20%20%3Cellipse%20id%3D%22path-1%22%20cx%3D%2230%22%20cy%3D%2261.7666667%22%20rx%3D%2215.4512904%22%20ry%3D%224.73333333%22%3E%3C%2Fellipse%3E%0A%20%20%20%20%20%20%20%20%3Cmask%20id%3D%22mask-2%22%20maskContentUnits%3D%22userSpaceOnUse%22%20maskUnits%3D%22objectBoundingBox%22%20x%3D%220%22%20y%3D%220%22%20width%3D%2230.9025808%22%20height%3D%229.46666667%22%20fill%3D%22white%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cuse%20xlink%3Ahref%3D%22%23path-1%22%3E%3C%2Fuse%3E%0A%20%20%20%20%20%20%20%20%3C%2Fmask%3E%0A%20%20%20%20%3C%2Fdefs%3E%0A%20%20%20%20%3Cg%20id%3D%22Page-1%22%20stroke%3D%22none%22%20stroke-width%3D%221%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%20%20%20%20%3Cg%20id%3D%22Artboard%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cuse%20id%3D%22Oval-10%22%20stroke%3D%22%23C1DFEF%22%20mask%3D%22url(%23mask-2)%22%20stroke-width%3D%222.8%22%20stroke-linecap%3D%22square%22%20stroke-dasharray%3D%223%2C6%2C3%2C5%22%20xlink%3Ahref%3D%22%23path-1%22%3E%3C%2Fuse%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M38.4613647%2C18.1642456%20L30.9890137%2C34.9141846%20L31%2C47%20L32.5977783%2C46.5167236%20L32.5977783%2C34.9141846%20L51.0673218%2C15.7560425%20C51.0673218%2C15.7560425%2048.6295166%2C16.6542969%2044.9628906%2C17.3392334%20C41.2962646%2C18.0241699%2038.4613647%2C18.1642456%2038.4613647%2C18.1642456%20Z%22%20id%3D%22Path-195%22%20fill%3D%22%23C1DFEF%22%3E%3C%2Fpath%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M4.74639226%2C12.5661855%20L4.62065726%2C12.1605348%20L5.3515414%2C11.1625044%20L5.77622385%2C11.159939%20L6.20936309%2C12.5573481%20L4.74639226%2C12.5661855%20Z%20M6.20936309%2C12.5573481%20L6.32542632%2C12.9317954%20L28.4963855%2C34.8796718%20L28.4963855%2C47.8096691%20L32.6%2C46.4836513%20L32.6%2C34.8992365%20L53.973494%2C12.7035813%20L53.973494%2C12.2688201%20L6.20936309%2C12.5573481%20Z%20M55.373494%2C10.8603376%20L55.373494%2C13.2680664%20L34%2C35.4637216%20L34%2C47.5025401%20L27.0963855%2C49.7333333%20L27.0963855%2C35.4637219%20L5.09179688%2C13.680542%20L4.31325301%2C11.1687764%20L55.373494%2C10.8603376%20Z%22%20id%3D%22Path-149%22%20fill%3D%22%237FBDDD%22%3E%3C%2Fpath%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cellipse%20id%3D%22Oval-9%22%20fill%3D%22%23FFFFFF%22%20cx%3D%2230%22%20cy%3D%2211.785654%22%20rx%3D%2226%22%20ry%3D%226.78565401%22%3E%3C%2Fellipse%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M30%2C17.171308%20C36.8772177%2C17.171308%2043.3112282%2C16.4610701%2048.0312371%2C15.2292106%20C50.2777611%2C14.6428977%2052.0507619%2C13.9579677%2053.2216231%2C13.2354973%20C54.1938565%2C12.6355886%2054.6%2C12.1175891%2054.6%2C11.785654%20C54.6%2C11.4537189%2054.1938565%2C10.9357194%2053.2216231%2C10.3358107%20C52.0507619%2C9.61334032%2050.2777611%2C8.92841034%2048.0312371%2C8.34209746%20C43.3112282%2C7.11023795%2036.8772177%2C6.4%2030%2C6.4%20C23.1227823%2C6.4%2016.6887718%2C7.11023795%2011.9687629%2C8.34209746%20C9.72223886%2C8.92841034%207.94923814%2C9.61334032%206.77837689%2C10.3358107%20C5.8061435%2C10.9357194%205.4%2C11.4537189%205.4%2C11.785654%20C5.4%2C12.1175891%205.8061435%2C12.6355886%206.77837689%2C13.2354973%20C7.94923814%2C13.9579677%209.72223886%2C14.6428977%2011.9687629%2C15.2292106%20C16.6887718%2C16.4610701%2023.1227823%2C17.171308%2030%2C17.171308%20Z%20M30%2C18.571308%20C15.6405965%2C18.571308%204%2C15.5332672%204%2C11.785654%20C4%2C8.03804078%2015.6405965%2C5%2030%2C5%20C44.3594035%2C5%2056%2C8.03804078%2056%2C11.785654%20C56%2C15.5332672%2044.3594035%2C18.571308%2030%2C18.571308%20Z%22%20id%3D%22Oval-9-Copy%22%20fill%3D%22%237FBDDD%22%3E%3C%2Fpath%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M18.2608643%2C7.14562988%20L22.727356%2C16.9047241%20C22.727356%2C16.9047241%2015.3006592%2C16.3911743%2010.276001%2C14.7511597%20C5.25134277%2C13.111145%205.38031006%2C11.8284302%205.38031006%2C11.6882935%20C5.38031006%2C10.4832831%208.16633152%2C9.41877716%2011.114563%2C8.57324219%20C14.549319%2C7.58817492%2018.2608643%2C7.14562988%2018.2608643%2C7.14562988%20Z%22%20id%3D%22Path-196%22%20fill%3D%22%23C1DFEF%22%3E%3C%2Fpath%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E");
}

View File

@ -26,6 +26,7 @@ import {
import { TranslateService } from '@ngx-translate/core';
import { DangerousArtifact } from '../../../../../../../ng-swagger-gen/models/dangerous-artifact';
import * as echarts from 'echarts/core';
import { finalize } from 'rxjs/operators';
@Component({
selector: 'app-vulnerability-summary',
@ -45,6 +46,7 @@ export class VulnerabilitySummaryComponent implements OnInit, OnDestroy {
chart: any;
@ViewChild('pieChart', { static: true })
pieChartEle: ElementRef;
loadingSummary: boolean = false;
constructor(
private securityHubService: SecurityhubService,
private messageHandler: MessageHandlerService,
@ -74,11 +76,13 @@ export class VulnerabilitySummaryComponent implements OnInit, OnDestroy {
}
getSummary() {
this.loadingSummary = true;
this.securityHubService
.getSecuritySummary({
withDangerousArtifact: true,
withDangerousCve: true,
})
.pipe(finalize(() => (this.loadingSummary = false)))
.subscribe({
next: res => {
this.securitySummary = res;