Refactoring the vulnerability UI to make it similar to GC.

Signed-off-by: FangyuanCheng <fangyuanc@vmware.com>
This commit is contained in:
FangyuanCheng 2018-10-16 16:31:46 +08:00
parent 002727d850
commit 0b8569371d
11 changed files with 137 additions and 44 deletions

View File

@ -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();
});

View File

@ -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>

View File

@ -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;

View File

@ -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]);
}
}
}

View File

@ -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 {

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -824,12 +824,12 @@
"NONE": "无",
"DAILY": "每天",
"WEEKLY": "每周",
"MANUAL": "手动"
"MANUAL": "手动",
"ON": " ",
"AT": " "
},
"GC": {
"CURRENT_SCHEDULE": "当前定时任务",
"ON": " ",
"AT": " ",
"GC_NOW": "立即清理垃圾",
"JOB_LIST":"任务列表",
"JOB_ID":"任务ID",