mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 01:27:49 +01:00
Refactoring the vulnerability UI to make it similar to GC.
Signed-off-by: FangyuanCheng <fangyuanc@vmware.com>
This commit is contained in:
parent
002727d850
commit
0b8569371d
@ -102,7 +102,7 @@ describe('RegistryConfigComponent (inline template)', () => {
|
||||
|
||||
|
||||
fixture.detectChanges();
|
||||
let el3: HTMLInputElement = fixture.nativeElement.querySelector('input[type="time"]');
|
||||
let el3: HTMLInputElement = fixture.nativeElement.querySelector('.btn-scan');
|
||||
expect(el3).toBeTruthy();
|
||||
expect(el3).not.toBeFalsy();
|
||||
});
|
||||
|
@ -21,25 +21,35 @@
|
||||
</div>
|
||||
</clr-dropdown-menu>
|
||||
</clr-dropdown>
|
||||
<span class="label label-blue" *ngIf="isClairDBFullyReady && !showScanningNamespaces">{{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }}</span>
|
||||
<span *ngIf="isClairDBFullyReady && !showScanningNamespaces">{{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group vertical-center normal-wrapper" *ngIf="!isEditMode">
|
||||
<span>{{ 'CONFIG.SCANNING.SCAN_ALL' | translate }}</span>
|
||||
<span>{{ (scanningType ? 'SCHEDULE.'+ scanningType.toUpperCase(): "") | translate }}</span>
|
||||
<span [hidden]="scanningType===SCHEDULE_TYPE.NONE">{{'SCHEDULE.AT' | translate}}</span>
|
||||
<span [hidden]="scanningType===SCHEDULE_TYPE.NONE">{{ dailyTime | translate }}</span>
|
||||
<button class="btn btn-outline btn-sm" (click)="editSchedule()">{{'BUTTON.EDIT' | translate}}</button>
|
||||
</div>
|
||||
<div class="form-group vertical-center" *ngIf="isEditMode">
|
||||
<label for="scanAllPolicy">{{ 'CONFIG.SCANNING.SCAN_ALL' | translate }}</label>
|
||||
<div class="select">
|
||||
<select id="scanAllPolicy" name="scanAllPolicy" [disabled]="!editable" [(ngModel)]="scanningType">
|
||||
<option value="none">{{ 'CONFIG.SCANNING.NONE_POLICY' | translate }}</option>
|
||||
<option value="daily">{{ 'CONFIG.SCANNING.DAILY_POLICY' | translate }}</option>
|
||||
<option value="none">{{ 'SCHEDULE.NONE' | translate }}</option>
|
||||
<option value="daily">{{ 'SCHEDULE.DAILY' | translate }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<span [hidden]="!showTimePicker">{{'SCHEDULE.AT' | translate}}</span>
|
||||
<input type="time" name="dailyTimePicker" required [disabled]="!editable" [hidden]="!showTimePicker" [(ngModel)]="dailyTime" />
|
||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.SCANNING_POLICY' | translate}}</span>
|
||||
</a>
|
||||
<div class="btn-scan-right">
|
||||
<button class="btn btn-primary btn-sm" (click)="scanNow()" [disabled]="!scanAvailable">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br>
|
||||
<span *ngIf="!scanAvailable">{{ 'CONFIG.SCANNING.NEXT_SCAN' | translate }} {{ nextScanTimestamp | date:'y/MM/dd HH:mm' }}</span>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm" (click)="save()">{{'BUTTON.SAVE' | translate}}</button>
|
||||
<button class="btn btn-primary btn-sm" (click)="cancel()" >{{'BUTTON.CANCEL' | translate}}</button>
|
||||
</div>
|
||||
<div class="btn-scan-right btn-scan">
|
||||
<button class="btn btn-primary btn-sm" (click)="scanNow()" [disabled]="!scanAvailable">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br>
|
||||
<span *ngIf="!scanAvailable">{{ 'CONFIG.SCANNING.NEXT_SCAN' | translate }} {{ nextScanTimestamp | date:'y/MM/dd HH:mm' }}</span>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
@ -2,6 +2,17 @@
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
|
||||
.vertical-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.normal-wrapper {
|
||||
> span:not(:first-child) {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 14px !important;
|
||||
font-weight: 600 !important;
|
||||
@ -18,9 +29,7 @@
|
||||
.clr-dropdown-override {
|
||||
margin-top: -8px;
|
||||
}
|
||||
.btn-scan-right{
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.btn-scan-right button{
|
||||
width: 160px;
|
||||
margin-bottom: 0px;
|
||||
|
@ -5,24 +5,29 @@ import { Configuration } from '../config';
|
||||
import {
|
||||
ScanningResultService,
|
||||
SystemInfo,
|
||||
SystemInfoService
|
||||
SystemInfoService,
|
||||
ConfigurationService
|
||||
} from '../../service/index';
|
||||
import { ErrorHandler } from '../../error-handler/index';
|
||||
import { toPromise } from '../../utils';
|
||||
import { toPromise, isEmptyObject } from '../../utils';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ClairDetail } from '../../service/interface';
|
||||
|
||||
const ONE_HOUR_SECONDS: number = 3600;
|
||||
const ONE_DAY_SECONDS: number = 24 * ONE_HOUR_SECONDS;
|
||||
|
||||
const SCHEDULE_TYPE = {
|
||||
NONE: "none",
|
||||
DAILY: "daily"
|
||||
};
|
||||
@Component({
|
||||
selector: 'vulnerability-config',
|
||||
templateUrl: './vulnerability-config.component.html',
|
||||
styles: ['./vulnerability-config.component.scss', '../registry-config.component.scss']
|
||||
styleUrls: ['./vulnerability-config.component.scss', '../registry-config.component.scss']
|
||||
})
|
||||
export class VulnerabilityConfigComponent implements OnInit {
|
||||
_localTime: Date = new Date();
|
||||
|
||||
isEditMode: boolean = false;
|
||||
SCHEDULE_TYPE = SCHEDULE_TYPE;
|
||||
configCopy: Configuration;
|
||||
onSubmitting: boolean = false;
|
||||
config: Configuration;
|
||||
openState: boolean = false;
|
||||
@ -101,7 +106,6 @@ export class VulnerabilityConfigComponent implements OnInit {
|
||||
timeOffset = +daily_time;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to current time
|
||||
let timezoneOffset: number = this._localTime.getTimezoneOffset();
|
||||
// Local time
|
||||
@ -184,6 +188,7 @@ export class VulnerabilityConfigComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set scanningType(v: string) {
|
||||
if (this.config &&
|
||||
this.config.scan_all_policy &&
|
||||
@ -235,13 +240,30 @@ export class VulnerabilityConfigComponent implements OnInit {
|
||||
private scanningService: ScanningResultService,
|
||||
private errorHandler: ErrorHandler,
|
||||
private translate: TranslateService,
|
||||
private systemInfoService: SystemInfoService
|
||||
private systemInfoService: SystemInfoService,
|
||||
private configService: ConfigurationService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getSystemInfo();
|
||||
this.getConfigurations();
|
||||
}
|
||||
|
||||
getConfigurations(): void {
|
||||
toPromise<Configuration>(this.configService.getConfigurations())
|
||||
.then((config: Configuration) => {
|
||||
this.configCopy = Object.assign({}, config);
|
||||
this.config = config;
|
||||
})
|
||||
.catch(error => {
|
||||
this.errorHandler.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
editSchedule() {
|
||||
this.isEditMode = true;
|
||||
}
|
||||
|
||||
convertToLocalTime(utcTime: number): Date {
|
||||
let dt: Date = new Date();
|
||||
dt.setTime(utcTime * 1000);
|
||||
@ -289,4 +311,42 @@ export class VulnerabilityConfigComponent implements OnInit {
|
||||
.then((info: SystemInfo) => this.systemInfo = info)
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
|
||||
save(): void {
|
||||
let getchanges = this.config.scan_all_policy.value;
|
||||
let changes = {"scan_all_policy": getchanges};
|
||||
|
||||
if (isEmptyObject(changes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
toPromise<any>(this.configService.saveConfigurations(changes))
|
||||
.then(() => {
|
||||
this.translate.get("CONFIG.SAVE_SUCCESS").subscribe((res: string) => {
|
||||
this.errorHandler.info(res);
|
||||
});
|
||||
this.getConfigurations();
|
||||
this.isEditMode = false;
|
||||
}, () => {
|
||||
this.reset();
|
||||
})
|
||||
.catch(error => {
|
||||
this.errorHandler.error(error);
|
||||
this.reset();
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this.reset();
|
||||
this.isEditMode = false;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
// Reset to the values of copy
|
||||
let getchanges = this.config.scan_all_policy.value;
|
||||
let changes = {"scan_all_policy": getchanges};
|
||||
for (let prop of Object.keys(changes)) {
|
||||
this.config[prop] = Object.assign({}, this.configCopy[prop]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public get hideBtn(): boolean {
|
||||
return this.currentTabId === 'config-label' || this.currentTabId === 'config-gc';
|
||||
return this.currentTabId === 'config-label' || this.currentTabId === 'config-gc' || this.currentTabId === 'config-vulnerability';
|
||||
}
|
||||
|
||||
public get hideMailTestingSpinner(): boolean {
|
||||
|
@ -1,12 +1,14 @@
|
||||
<div class="normal-wrapper flex-layout" *ngIf="!isEditMode">
|
||||
<span>{{'GC.CURRENT_SCHEDULE' | translate}}</span>
|
||||
<span class="font-style">{{'GC.CURRENT_SCHEDULE' | translate}}</span>
|
||||
<span>{{(originScheduleType ? 'SCHEDULE.'+ originScheduleType.toUpperCase(): "") | translate}}</span>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY">{{'GC.ON' | translate}} {{originWeekDay.text | translate}}</span>
|
||||
<span [hidden]="originScheduleType===SCHEDULE_TYPE.NONE">{{'GC.AT' | translate}} {{originOffTime.text}}</span>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY">{{'SCHEDULE.ON' | translate}}</span>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY">{{originWeekDay.text | translate}}</span>
|
||||
<span [hidden]="originScheduleType===SCHEDULE_TYPE.NONE">{{'SCHEDULE.AT' | translate}}</span>
|
||||
<span [hidden]="originScheduleType===SCHEDULE_TYPE.NONE">{{originOffTime.text}}</span>
|
||||
<button class="btn btn-outline btn-sm" (click)="editSchedule()">{{'BUTTON.EDIT' | translate}}</button>
|
||||
</div>
|
||||
<div class="setting-wrapper flex-layout" *ngIf="isEditMode">
|
||||
<label for="gcPolicy">{{'CONFIG.GC' | translate}}</label>
|
||||
<label for="gcPolicy" class="font-style">{{'CONFIG.GC' | translate}}</label>
|
||||
<div class="select">
|
||||
<select id="gcPolicy" name="gcPolicy" [(ngModel)]="scheduleType">
|
||||
<option [value]="SCHEDULE_TYPE.NONE">{{'SCHEDULE.NONE' | translate}}</option>
|
||||
@ -15,20 +17,20 @@
|
||||
</select>
|
||||
</div>
|
||||
<section [hidden]="scheduleType!== SCHEDULE_TYPE.WEEKLY" class="select day-selector-wrapper">
|
||||
<span>{{'GC.ON' | translate}}</span>
|
||||
<span>{{'SCHEDULE.ON' | translate}}</span>
|
||||
<select id="daySelector" name="daySelector" [(ngModel)]="weekDay">
|
||||
<option *ngFor="let d of weekDays" [ngValue]="d">{{d.text | translate}}</option>
|
||||
</select>
|
||||
</section>
|
||||
<section [hidden]="scheduleType===SCHEDULE_TYPE.NONE">
|
||||
<span>{{'GC.AT' | translate}}</span>
|
||||
<span>{{'SCHEDULE.AT' | translate}}</span>
|
||||
<input type="time" name="dailyTimePicker" required [(ngModel)]="dailyTime" />
|
||||
</section>
|
||||
<button class="btn btn-primary btn-sm" (click)="scheduleGc()">{{'BUTTON.SAVE' | translate}}</button>
|
||||
<button class="btn btn-primary btn-sm" (click)="isEditMode = false" >{{'BUTTON.CANCEL' | translate}}</button>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm gc-start-btn" (click)="gcNow()" [disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button>
|
||||
<div class="job-header">{{'GC.JOB_LIST' | translate}}</div>
|
||||
<div class="job-header font-style">{{'GC.JOB_LIST' | translate}}</div>
|
||||
<clr-datagrid>
|
||||
<clr-dg-column>{{'GC.JOB_ID' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'GC.TRIGGER_TYPE' | translate}}</clr-dg-column>
|
||||
|
@ -2,17 +2,29 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin:20px 0;
|
||||
font-size: .541667rem;
|
||||
}
|
||||
|
||||
.font-style {
|
||||
color: #000;
|
||||
font-size: .541667rem;
|
||||
}
|
||||
|
||||
.setting-wrapper {
|
||||
> * {
|
||||
margin-right:35px;
|
||||
label {
|
||||
width: 228px;
|
||||
}
|
||||
*:not(:first-child), span {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.normal-wrapper {
|
||||
> * {
|
||||
margin-right: 90px;
|
||||
> span:first-child {
|
||||
width: 228px;
|
||||
}
|
||||
> span:not(:first-child){
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,12 +828,12 @@
|
||||
"NONE": "None",
|
||||
"DAILY": "Daily",
|
||||
"WEEKLY": "Weekly",
|
||||
"MANUAL": "Manual"
|
||||
"MANUAL": "Manual",
|
||||
"ON": "on",
|
||||
"AT": "at"
|
||||
},
|
||||
"GC": {
|
||||
"CURRENT_SCHEDULE": "Current Schedule",
|
||||
"ON": "on",
|
||||
"AT": "at",
|
||||
"GC_NOW": "GC NOW",
|
||||
"JOB_LIST":"GC Jobs List",
|
||||
"JOB_ID":"Job ID",
|
||||
|
@ -825,12 +825,12 @@
|
||||
"NONE": "None",
|
||||
"DAILY": "Daily",
|
||||
"WEEKLY": "Weekly",
|
||||
"MANUAL": "Manual"
|
||||
"MANUAL": "Manual",
|
||||
"ON": "on",
|
||||
"AT": "at"
|
||||
},
|
||||
"GC": {
|
||||
"CURRENT_SCHEDULE": "Current Schedule",
|
||||
"ON": "on",
|
||||
"AT": "at",
|
||||
"GC_NOW": "GC NOW",
|
||||
"JOB_LIST":"GC Jobs List",
|
||||
"JOB_ID":"Job ID",
|
||||
|
@ -788,12 +788,12 @@
|
||||
"NONE": "None",
|
||||
"DAILY": "Daily",
|
||||
"WEEKLY": "Weekly",
|
||||
"MANUAL": "Manual"
|
||||
"MANUAL": "Manual",
|
||||
"ON": "on",
|
||||
"AT": "at"
|
||||
},
|
||||
"GC": {
|
||||
"CURRENT_SCHEDULE": "Current Schedule",
|
||||
"ON": "on",
|
||||
"AT": "at",
|
||||
"GC_NOW": "GC NOW",
|
||||
"JOB_LIST":"GC Jobs List",
|
||||
"JOB_ID":"Job ID",
|
||||
|
@ -824,12 +824,12 @@
|
||||
"NONE": "无",
|
||||
"DAILY": "每天",
|
||||
"WEEKLY": "每周",
|
||||
"MANUAL": "手动"
|
||||
"MANUAL": "手动",
|
||||
"ON": " ",
|
||||
"AT": " "
|
||||
},
|
||||
"GC": {
|
||||
"CURRENT_SCHEDULE": "当前定时任务",
|
||||
"ON": " ",
|
||||
"AT": " ",
|
||||
"GC_NOW": "立即清理垃圾",
|
||||
"JOB_LIST":"任务列表",
|
||||
"JOB_ID":"任务ID",
|
||||
|
Loading…
Reference in New Issue
Block a user