From 2225417e1fda6b552f5615f16d2da248ca2e99fd Mon Sep 17 00:00:00 2001 From: sshijun Date: Wed, 6 Nov 2019 16:38:54 +0800 Subject: [PATCH] Refactor scan all page Signed-off-by: sshijun --- src/portal/lib/src/config/config.ts | 11 + .../src/config/registry-config.component.html | 2 +- .../src/config/registry-config.component.ts | 5 +- .../config/vulnerability/scanAll.service.ts | 16 +- .../vulnerability-config.component.html | 45 +++- .../vulnerability-config.component.scss | 49 ++++ .../vulnerability-config.component.spec.ts | 102 +++++++++ .../vulnerability-config.component.ts | 216 +++++++++++++----- .../lib/src/log/recent-log.component.ts | 2 +- src/portal/src/i18n/lang/en-us-lang.json | 16 +- src/portal/src/i18n/lang/es-es-lang.json | 16 +- src/portal/src/i18n/lang/fr-fr-lang.json | 16 +- src/portal/src/i18n/lang/pt-br-lang.json | 16 +- src/portal/src/i18n/lang/tr-tr-lang.json | 16 +- src/portal/src/i18n/lang/zh-cn-lang.json | 16 +- 15 files changed, 456 insertions(+), 88 deletions(-) create mode 100644 src/portal/lib/src/config/vulnerability/vulnerability-config.component.spec.ts diff --git a/src/portal/lib/src/config/config.ts b/src/portal/lib/src/config/config.ts index 5d4893fcc..921cbd2ca 100644 --- a/src/portal/lib/src/config/config.ts +++ b/src/portal/lib/src/config/config.ts @@ -159,3 +159,14 @@ export class Configuration { this.storage_per_project = new NumberValueItem(-1, true); } } + +export class ScanningMetrics { + total?: number; + completed?: number; + metrics: { + [key: string]: number; + }; + requester?: string; + isScheduled?: boolean; + ongoing: boolean; +} diff --git a/src/portal/lib/src/config/registry-config.component.html b/src/portal/lib/src/config/registry-config.component.html index a36fcb4ac..6716e8500 100644 --- a/src/portal/lib/src/config/registry-config.component.html +++ b/src/portal/lib/src/config/registry-config.component.html @@ -10,7 +10,7 @@ - + diff --git a/src/portal/lib/src/config/registry-config.component.ts b/src/portal/lib/src/config/registry-config.component.ts index 44447fede..7ef9256a5 100644 --- a/src/portal/lib/src/config/registry-config.component.ts +++ b/src/portal/lib/src/config/registry-config.component.ts @@ -59,10 +59,9 @@ export class RegistryConfigComponent implements OnInit { } isValid(): boolean { - return this.systemSettings && + return !!(this.systemSettings && this.systemSettings.isValid && - this.vulnerabilityCfg && - this.vulnerabilityCfg.isValid; + this.vulnerabilityCfg); } hasChanges(): boolean { diff --git a/src/portal/lib/src/config/vulnerability/scanAll.service.ts b/src/portal/lib/src/config/vulnerability/scanAll.service.ts index 66da5db29..587fad9c3 100644 --- a/src/portal/lib/src/config/vulnerability/scanAll.service.ts +++ b/src/portal/lib/src/config/vulnerability/scanAll.service.ts @@ -1,13 +1,17 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; +import {Observable, throwError as observableThrowError} from 'rxjs'; import { ScanApiRepository } from './scanAll.api.repository'; import { ErrorHandler } from '../../error-handler/index'; +import {HttpClient} from "@angular/common/http"; +import {ScanningMetrics} from "../config"; +import {catchError, map} from "rxjs/operators"; @Injectable() export class ScanAllRepoService { constructor( + private http: HttpClient, private scanApiRepository: ScanApiRepository, private errorHandler: ErrorHandler) { } @@ -46,4 +50,14 @@ export class ScanAllRepoService { return this.scanApiRepository.putSchedule(param); } + getScheduleMetrics(): Observable { + return this.http.get('/api/scans/schedule/metrics') + .pipe(catchError(error => observableThrowError(error))) + .pipe(map(response => response as ScanningMetrics)); + } + getManualMetrics(): Observable { + return this.http.get('/api/scans/all/metrics') + .pipe(catchError(error => observableThrowError(error))) + .pipe(map(response => response as ScanningMetrics)); + } } diff --git a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html index f5e2a2988..11c864722 100644 --- a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html +++ b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html @@ -1,10 +1,37 @@ -
-
-
- -
-
-
+
+
+ +
+
+
+
+
+ +
-
-
+ +
+
+ {{ 'CONFIG.SCANNING.MANUAL' | translate }} + {{ 'CONFIG.SCANNING.SCHEDULED' | translate }} + {{ 'SCANNER.TOTAL' | translate }} + {{scanningMetrics?.total}} +
+
+
+
+
+
+
+
+
{{getI18nKey(item?.key)|translate}}
+
{{item?.value}}
+
+
+
+ diff --git a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.scss b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.scss index 42330084e..b33538467 100644 --- a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.scss +++ b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.scss @@ -48,4 +48,53 @@ font-size: .541667rem; width: 200px; padding-right: 1rem; +} +.margin-left-5 { + margin-left: 5px; +} +.margin-top-16px { + margin-top: 16px; +} +.v-mid { + vertical-align: middle; +} +.flex-200 { + flex: 0 0 200px; +} +.total { + text-align: right; + line-height: 15px; + height: 15px; + font-size: 10px; + margin-top: 7px; + margin-bottom: 3px; +} +.info { + height: 18px; + line-height: 18px; + font-size: 14px; +} +.container { + height: 18px; + display: flex; + background-color:#eee; + .error { + background-color: #e62700; + } + .finished { + background-color: #62a420; + } + .in-progress { + background-color: #0079b8; + } +} +.state { + flex: 2; + padding-left: 3px; +} +.value { + flex: 3; +} +.float-left { + float: left; } \ No newline at end of file diff --git a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.spec.ts b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.spec.ts new file mode 100644 index 000000000..9f2517ee9 --- /dev/null +++ b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.spec.ts @@ -0,0 +1,102 @@ +import { ComponentFixture, TestBed, async, fakeAsync, tick, ComponentFixtureAutoDetect } from '@angular/core/testing'; +import { VulnerabilityConfigComponent } from "./vulnerability-config.component"; +import { ErrorHandler, IServiceConfig, ScanningMetrics, SERVICE_CONFIG, SharedModule } from "../.."; +import { ScanAllRepoService } from "./scanAll.service"; +import { of } from "rxjs"; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; + +let component: VulnerabilityConfigComponent; +let fixture: ComponentFixture; +let config: IServiceConfig = { + configurationEndpoint: '/api/configurations/testing' +}; +let mockedSchedule = {"schedule": null}; +let mockedScheduledMetrics: ScanningMetrics = { + total: 50, + completed: 50, + metrics: { + "Success": 20, + "Error": 30, + }, + ongoing: false +}; +let mockedManualMetrics: ScanningMetrics = { + total: 100, + completed: 20, + metrics: { + "Error": 10, + "Success": 20, + "Running": 70 + }, + ongoing: true +}; +let fakedScanAllRepoService = { + getSchedule() { + return of(mockedSchedule); + }, + getScheduleMetrics() { + return of(mockedScheduledMetrics); + }, + getManualMetrics() { + return of(mockedManualMetrics); + }, + manualScan() { + return of(true); + } +}; +let fakedErrorHandler = { + info() { + return null; + } +}; + +describe('VulnerabilityConfigComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + SharedModule, + ], + schemas: [ + CUSTOM_ELEMENTS_SCHEMA + ], + declarations: [ + VulnerabilityConfigComponent + ], + providers: [ + {provide: ErrorHandler, useValue: fakedErrorHandler}, + {provide: ScanAllRepoService, useValue: fakedScanAllRepoService}, + { provide: SERVICE_CONFIG, useValue: config }, + // open auto detect + { provide: ComponentFixtureAutoDetect, useValue: true } + ] + }); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VulnerabilityConfigComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + const ele = fixture.nativeElement.querySelector('.finished'); + expect(ele.style.width).toEqual('40px'); + }); + it('should loop scheduled metrics if scheduled scanning is on going', () => { + component.scanningMetrics.isScheduled = true; + component.scanningMetrics.ongoing = true; + expect(component.scanAvailable).toBeFalsy(); + }); + it('will trigger scan now and get manual metrics', () => { + const button = fixture.nativeElement.querySelector('#scan-now'); + button.click(); + const ele = fixture.nativeElement.querySelector('.finished'); + expect(ele.style.width).toEqual('40px'); + }); + it('should stop looping manual metrics if manual scanning is finished', () => { + component.scanningMetrics.isScheduled = false; + component.scanningMetrics.ongoing = false; + expect(component.scanAvailable).toBeTruthy(); + }); +}); diff --git a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts index 2732d491a..a488d13c6 100644 --- a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts +++ b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts @@ -1,64 +1,93 @@ -import { Component, Input, Output, EventEmitter, ViewChild, OnInit } from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { map, catchError, finalize } from "rxjs/operators"; -import { Observable, throwError as observableThrowError, of } from "rxjs"; -import { Configuration } from '../config'; -import { - ScanningResultService, - SystemInfo, - SystemInfoService, - ConfigurationService -} from '../../service/index'; +import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core'; +import { finalize } from "rxjs/operators"; +import { ScanningMetrics } from '../config'; import { ErrorHandler } from '../../error-handler/index'; -import { isEmptyObject, clone} from '../../utils'; import { TranslateService } from '@ngx-translate/core'; -import { ClairDetail } from '../../service/interface'; import { ScanAllRepoService } from './scanAll.service'; import { OriginCron } from '../../service/interface'; import { CronScheduleComponent } from "../../cron-schedule/cron-schedule.component"; -const ONE_HOUR_SECONDS: number = 3600; -const ONE_DAY_SECONDS: number = 24 * ONE_HOUR_SECONDS; +import { VULNERABILITY_SCAN_STATUS } from "../../utils"; +import { errorHandler as errorHandFn} from "../../shared/shared.utils"; + const SCHEDULE_TYPE_NONE = "None"; @Component({ selector: 'vulnerability-config', templateUrl: './vulnerability-config.component.html', styleUrls: ['./vulnerability-config.component.scss', '../registry-config.component.scss'] }) -export class VulnerabilityConfigComponent implements OnInit { +export class VulnerabilityConfigComponent implements OnInit, OnDestroy { onGoing: boolean; - _localTime: Date = new Date(); originCron: OriginCron; schedule: any; onSubmitting: boolean = false; - config: Configuration; openState: boolean = false; getLabelCurrent: string; @ViewChild(CronScheduleComponent, {static: false}) CronScheduleComponent: CronScheduleComponent; - - @Input() - - @Input() showSubTitle: boolean = false; - @Input() showScanningNamespaces: boolean = false; - @Output() loadingStatus = new EventEmitter(); - systemInfo: SystemInfo; - + gettingMetrics: boolean; + private _scanningMetrics: ScanningMetrics; + totalWidth: number = 200; + i18nKeyMap = { + "Pending": "CONFIG.SCANNING.STATUS.PENDING", + "Running": "CONFIG.SCANNING.STATUS.RUNNING", + "Stopped": "CONFIG.SCANNING.STATUS.STOPPED", + "Error": "CONFIG.SCANNING.STATUS.ERROR", + "Success": "CONFIG.SCANNING.STATUS.SUCCESS", + "Scheduled": "CONFIG.SCANNING.STATUS.SCHEDULED" + }; + private _loopScheduleInterval; + private _loopManualInterval; constructor( - // private scanningService: ScanningResultService, private scanningService: ScanAllRepoService, private errorHandler: ErrorHandler, private translate: TranslateService, - private systemInfoService: SystemInfoService, - private configService: ConfigurationService ) { } + get scanningMetrics(): ScanningMetrics { + return this._scanningMetrics; + } + set scanningMetrics(metrics: ScanningMetrics) { + // start looping scheduled metrics + if (metrics && metrics.ongoing && metrics.isScheduled) { + if (!this._loopScheduleInterval) { + this._loopScheduleInterval = setInterval(() => { + this.getScheduleMetrics(); + }, 5000); + } + } + // stop looping scheduled metrics + if (metrics && !metrics.ongoing && metrics.isScheduled) { + if (this._loopScheduleInterval) { + clearInterval(this._loopScheduleInterval); + this._loopScheduleInterval = null; + } + } + // start looping manual metrics + if (metrics && metrics.ongoing && !metrics.isScheduled) { + if (!this._loopManualInterval) { + this._loopManualInterval = setInterval(() => { + this.getManualMetrics(); + }, 5000); + } + } + // stop looping manual metrics + if (metrics && !metrics.ongoing && !metrics.isScheduled) { + if (this._loopManualInterval) { + clearInterval(this._loopManualInterval); + this._loopManualInterval = null; + } + } + this._scanningMetrics = metrics; + } get scanAvailable(): boolean { - return !this.onSubmitting; + return !this.onSubmitting + && !this.gettingMetrics + && !this.isOnScanning(); } getScanText() { - this.translate.get('CONFIG.SCANNING.SCAN_ALL').subscribe((res: string) => { + this.translate.get('CONFIG.SCANNING.SCHEDULE_TO_SCAN_ALL').subscribe((res: string) => { this.getLabelCurrent = res; }); } @@ -67,7 +96,6 @@ export class VulnerabilityConfigComponent implements OnInit { this.scanningService.getSchedule() .pipe(finalize(() => { this.onGoing = false; - this.loadingStatus.emit(this.onGoing); })) .subscribe(schedule => { this.initSchedule(schedule); @@ -87,31 +115,103 @@ export class VulnerabilityConfigComponent implements OnInit { }; } } - @ViewChild("systemConfigFrom", {static: false}) systemSettingsForm: NgForm; - - get isValid(): boolean { - return this.systemSettingsForm && this.systemSettingsForm.valid; - } - ngOnInit(): void { - this.getSystemInfo(); this.getScanText(); this.getSchedule(); + this.initMetrics(); } - getSystemInfo(): void { - this.systemInfoService.getSystemInfo() - .subscribe((info: SystemInfo) => (this.systemInfo = info) - , error => this.errorHandler.error(error)); + ngOnDestroy() { + if (this._loopScheduleInterval) { + clearInterval(this._loopScheduleInterval); + this._loopScheduleInterval = null; + } + if (this._loopManualInterval) { + clearInterval(this._loopManualInterval); + this._loopManualInterval = null; + } } - - convertToLocalTime(utcTime: number): Date { - let dt: Date = new Date(); - dt.setTime(utcTime * 1000); - - return dt; + isOnScanning(): boolean { + return this.scanningMetrics + && this.scanningMetrics.ongoing; + } + getScheduleMetrics() { + this.gettingMetrics = true; + this.scanningService.getScheduleMetrics() + .pipe(finalize(() => this.gettingMetrics = false)) + .subscribe(response => { + if (response) { + response.isScheduled = true; + this.scanningMetrics = response; + } + }); + } + getManualMetrics() { + this.gettingMetrics = true; + this.scanningService.getManualMetrics() + .pipe(finalize(() => this.gettingMetrics = false)) + .subscribe(response => { + if (response) { + response.isScheduled = false; + this.scanningMetrics = response; + } + }); + } + initMetrics() { + // get scheduled metrics first + this.scanningService.getScheduleMetrics() + .pipe(finalize(() => this.gettingMetrics = false)) + .subscribe(response => { + // if scheduled scanning is on going + if (response && response.ongoing) { + response.isScheduled = true; + this.scanningMetrics = response; + } else { + this.getManualMetrics(); + } + }, + error => { + this.errorHandler.error(error); + // if error, get manual metrics + this.getManualMetrics(); + }); + } + getI18nKey(str: string): string { + if (str && this.i18nKeyMap[str]) { + return this.i18nKeyMap[str]; + } + return str; + } + errorWidth() { + if (this.scanningMetrics + && this.scanningMetrics.metrics + && this.scanningMetrics.total + && this.scanningMetrics.metrics[VULNERABILITY_SCAN_STATUS.ERROR]) { + return this.scanningMetrics.metrics[VULNERABILITY_SCAN_STATUS.ERROR] / + this.scanningMetrics.total * this.totalWidth + 'px'; + } + return '0'; + } + finishedWidth() { + if (this.scanningMetrics + && this.scanningMetrics.metrics + && this.scanningMetrics.total + && this.scanningMetrics.metrics[VULNERABILITY_SCAN_STATUS.SUCCESS]) { + return this.scanningMetrics.metrics[VULNERABILITY_SCAN_STATUS.SUCCESS] / + this.scanningMetrics.total * this.totalWidth + 'px'; + } + return '0'; + } + runningWidth() { + if (this.scanningMetrics + && this.scanningMetrics.metrics + && this.scanningMetrics.total + && this.scanningMetrics.metrics[VULNERABILITY_SCAN_STATUS.RUNNING]) { + return this.scanningMetrics.metrics[VULNERABILITY_SCAN_STATUS.RUNNING] / + this.scanningMetrics.total * this.totalWidth + 'px'; + } + return '0'; } - scanNow(): void { if (this.onSubmitting) { return; // Aoid duplicated submitting @@ -123,28 +223,22 @@ export class VulnerabilityConfigComponent implements OnInit { this.onSubmitting = true; this.scanningService.manualScan() + .pipe(finalize(() => this.onSubmitting = false)) .subscribe(() => { this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_SUCCESS").subscribe((res: string) => { this.errorHandler.info(res); }); - - // Update system info - this.systemInfoService.getSystemInfo() - .subscribe(() => { - this.onSubmitting = false; - }, error => { - this.onSubmitting = false; - }); + this.getManualMetrics(); } , error => { if (error && error.status && error.status === 412) { - this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_FAIL", { error: '' + error }).subscribe((res: string) => { + this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_FAIL", + { error: '' + errorHandFn(error) }).subscribe((res: string) => { this.errorHandler.error(res); }); } else { this.errorHandler.error(error); } - this.onSubmitting = false; }); } @@ -157,7 +251,7 @@ export class VulnerabilityConfigComponent implements OnInit { }; } - scanAll(cron: string): void { + saveSchedule(cron: string): void { let schedule = this.schedule; if (schedule && schedule.schedule && schedule.schedule.type !== SCHEDULE_TYPE_NONE) { this.scanningService.putSchedule(this.CronScheduleComponent.scheduleType, cron) diff --git a/src/portal/lib/src/log/recent-log.component.ts b/src/portal/lib/src/log/recent-log.component.ts index adefad63e..08b2b7443 100644 --- a/src/portal/lib/src/log/recent-log.component.ts +++ b/src/portal/lib/src/log/recent-log.component.ts @@ -41,7 +41,7 @@ export class RecentLogComponent implements OnInit { defaultFilter = "username"; isOpenFilterTag: boolean; @Input() withTitle: boolean = false; - pageSize: number = 3; + pageSize: number = 15; currentPage: number = 1; // Double bound to pagination component constructor( private logService: AccessLogService, diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index 5506f1ebc..e4cbe4e9e 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -876,16 +876,28 @@ }, "SCANNING": { "TRIGGER_SCAN_ALL_SUCCESS": "Trigger scan all successfully!", - "TRIGGER_SCAN_ALL_FAIL": "Failed to trigger scan all with error: {{error}", + "TRIGGER_SCAN_ALL_FAIL": "Failed to trigger scan all with error: {{error}}", "TITLE": "Vulnerability Scanning", "SCAN_ALL": "Scan All", + "SCHEDULE_TO_SCAN_ALL": "Schedule to scan all", "SCAN_NOW": "SCAN NOW", + "SCAN": "SCAN", "NONE_POLICY": "None", "DAILY_POLICY": "Daily At", "REFRESH_POLICY": "Upon Refresh", "DB_REFRESH_TIME": "Database updated on", "DB_NOT_READY": "Vulnerability database might not be fully ready!", - "NEXT_SCAN": "Available after" + "NEXT_SCAN": "Available after", + "STATUS": { + "PENDING": "Pending", + "RUNNING": "Running", + "STOPPED": "Stopped", + "ERROR": "Error", + "SUCCESS": "Success", + "SCHEDULED": "Scheduled" + }, + "MANUAL": "Manual", + "SCHEDULED": "Scheduled" }, "TEST_MAIL_SUCCESS": "Connection to mail server is verified.", "TEST_LDAP_SUCCESS": "Connection to LDAP server is verified.", diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index 1244e4d91..260c3f7e1 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -875,16 +875,28 @@ }, "SCANNING": { "TRIGGER_SCAN_ALL_SUCCESS": "Trigger scan all successfully!", - "TRIGGER_SCAN_ALL_FAIL": "Failed to trigger scan all with error: {{error}", + "TRIGGER_SCAN_ALL_FAIL": "Failed to trigger scan all with error: {{error}}", "TITLE": "Vulnerability Scanning", "SCAN_ALL": "Scan All", + "SCHEDULE_TO_SCAN_ALL": "Schedule to scan all", "SCAN_NOW": "SCAN NOW", + "SCAN": "SCAN", "NONE_POLICY": "None", "DAILY_POLICY": "Daily At", "REFRESH_POLICY": "Upon Refresh", "DB_REFRESH_TIME": "Database updated on", "DB_NOT_READY": "Vulnerability database might not be fully ready!", - "NEXT_SCAN": "Available after" + "NEXT_SCAN": "Available after", + "STATUS": { + "PENDING": "Pending", + "RUNNING": "Running", + "STOPPED": "Stopped", + "ERROR": "Error", + "SUCCESS": "Success", + "SCHEDULED": "Scheduled" + }, + "MANUAL": "Manual", + "SCHEDULED": "Scheduled" }, "TEST_MAIL_SUCCESS": "La conexión al servidor de correo ha sido verificada.", "TEST_LDAP_SUCCESS": "La conexión al servidor LDAP ha sido verificada.", diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index c426f911b..fb2064308 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -849,16 +849,28 @@ }, "SCANNING": { "TRIGGER_SCAN_ALL_SUCCESS": "Déclenchement d'analyse globale avec succès !", - "TRIGGER_SCAN_ALL_FAIL": "Echec du déclenchement d'analyse globale avec des erreurs : {{error}", + "TRIGGER_SCAN_ALL_FAIL": "Echec du déclenchement d'analyse globale avec des erreurs : {{error}}", "TITLE": "Analyse de vulnérabilité", "SCAN_ALL": "Analyser tout", + "SCHEDULE_TO_SCAN_ALL": "Schedule to scan all", "SCAN_NOW": "ANALYSER MAINTENANT", + "SCAN": "SCAN", "NONE_POLICY": "Aucune", "DAILY_POLICY": "Tous les jours à", "REFRESH_POLICY": "Lors de la mise à jour", "DB_REFRESH_TIME": "Base de données mise à jour le", "DB_NOT_READY": "La base de données sur les vulnérabilités pourrait ne pas être entièrement prête !", - "NEXT_SCAN": "Disponible à partir de" + "NEXT_SCAN": "Disponible à partir de", + "STATUS": { + "PENDING": "Pending", + "RUNNING": "Running", + "STOPPED": "Stopped", + "ERROR": "Error", + "SUCCESS": "Success", + "SCHEDULED": "Scheduled" + }, + "MANUAL": "Manual", + "SCHEDULED": "Scheduled" }, "TEST_MAIL_SUCCESS": "La connexion au serveur de mail est vérifiée.", "TEST_LDAP_SUCCESS": "La connexion au serveur LDAP est vérifiée.", diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json index ffb712303..789f11b23 100644 --- a/src/portal/src/i18n/lang/pt-br-lang.json +++ b/src/portal/src/i18n/lang/pt-br-lang.json @@ -870,16 +870,28 @@ }, "SCANNING": { "TRIGGER_SCAN_ALL_SUCCESS": "Disparo de análise geral efetuado com sucesso!", - "TRIGGER_SCAN_ALL_FAIL": "Falha ao disparar análise geral com erro: {{error}", + "TRIGGER_SCAN_ALL_FAIL": "Falha ao disparar análise geral com erro: {{error}}", "TITLE": "Análise de vulnerabilidades", "SCAN_ALL": "Analisar todos", + "SCHEDULE_TO_SCAN_ALL": "Schedule to scan all", "SCAN_NOW": "ANALISAR AGORA", + "SCAN": "SCAN", "NONE_POLICY": "Nenhum", "DAILY_POLICY": "Diário em", "REFRESH_POLICY": "na atualização", "DB_REFRESH_TIME": "Banco de dados atualizado em", "DB_NOT_READY": "Banco de dados de vulnerabilidade pode não estar totalmente preparado!", - "NEXT_SCAN": "Disponível após" + "NEXT_SCAN": "Disponível após", + "STATUS": { + "PENDING": "Pending", + "RUNNING": "Running", + "STOPPED": "Stopped", + "ERROR": "Error", + "SUCCESS": "Success", + "SCHEDULED": "Scheduled" + }, + "MANUAL": "Manual", + "SCHEDULED": "Scheduled" }, "TEST_MAIL_SUCCESS": "Conexão ao servidor de Email foi verificada.", "TEST_LDAP_SUCCESS": "Conexão ao servidor de LDAP foi verificada.", diff --git a/src/portal/src/i18n/lang/tr-tr-lang.json b/src/portal/src/i18n/lang/tr-tr-lang.json index dd050b5ec..7a9a772fc 100644 --- a/src/portal/src/i18n/lang/tr-tr-lang.json +++ b/src/portal/src/i18n/lang/tr-tr-lang.json @@ -875,16 +875,28 @@ }, "SCANNING": { "TRIGGER_SCAN_ALL_SUCCESS": "Tümünü başarılı bir şekilde tara!", - "TRIGGER_SCAN_ALL_FAIL": "Tüm taramayı hatayla tetikleyemedi:{{error}", + "TRIGGER_SCAN_ALL_FAIL": "Tüm taramayı hatayla tetikleyemedi:{{error}}", "TITLE": "Güvenlik açığı taraması", "SCAN_ALL": "Hepsini Tara", + "SCHEDULE_TO_SCAN_ALL": "Schedule to scan all", "SCAN_NOW": "ŞİMDİ TARA", + "SCAN": "SCAN", "NONE_POLICY": "Hiçbiri", "DAILY_POLICY": "Günlük", "REFRESH_POLICY": "Yenileme üzerine", "DB_REFRESH_TIME": "Veri tabanı güncellendi", "DB_NOT_READY": "Güvenlik açığı veritabanı tam olarak hazır olmayabilir!", - "NEXT_SCAN": "Sonra kullanılabilir" + "NEXT_SCAN": "Sonra kullanılabilir", + "STATUS": { + "PENDING": "Pending", + "RUNNING": "Running", + "STOPPED": "Stopped", + "ERROR": "Error", + "SUCCESS": "Success", + "SCHEDULED": "Scheduled" + }, + "MANUAL": "Manual", + "SCHEDULED": "Scheduled" }, "TEST_MAIL_SUCCESS": "Posta sunucusuyla bağlantı doğrulandı.", "TEST_LDAP_SUCCESS": "LDAP sunucusuna bağlantı doğrulandı.", diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index ef18da169..b4c4a3836 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -875,16 +875,28 @@ }, "SCANNING": { "TRIGGER_SCAN_ALL_SUCCESS": "启动扫描所有镜像任务成功!", - "TRIGGER_SCAN_ALL_FAIL": "启动扫描所有镜像任务失败:{{error}", + "TRIGGER_SCAN_ALL_FAIL": "启动扫描所有镜像任务失败:{{error}}", "TITLE": "缺陷扫描", "SCAN_ALL": "扫描所有", + "SCHEDULE_TO_SCAN_ALL": "定时扫描所有", "SCAN_NOW": "开始扫描", + "SCAN": "扫描", "NONE_POLICY": "无", "DAILY_POLICY": "每日定时", "REFRESH_POLICY": "缺陷库刷新后", "DB_REFRESH_TIME": "数据库更新于", "DB_NOT_READY": "缺陷数据库可能没有完全准备好!", - "NEXT_SCAN": "下次可用时间" + "NEXT_SCAN": "下次可用时间", + "STATUS": { + "PENDING": "等待", + "RUNNING": "扫描中", + "STOPPED": "中止", + "ERROR": "出错", + "SUCCESS": "成功", + "SCHEDULED": "已入计划" + }, + "MANUAL": "手动触发", + "SCHEDULED": "定时触发" }, "TEST_MAIL_SUCCESS": "邮件服务器的连通正常。", "TEST_LDAP_SUCCESS": "LDAP服务器的连通正常。",