From 97a9052050f301bf1ec2728b1c26dfb070c1f175 Mon Sep 17 00:00:00 2001 From: Steven Zou Date: Mon, 24 Jul 2017 13:39:49 +0800 Subject: [PATCH 1/2] Enhance scanning status controlling --- .../config/registry-config.component.html.ts | 2 +- .../config/registry-config.component.spec.ts | 5 +- .../src/config/registry-config.component.ts | 26 +++--- ...vulnerability-config.component.template.ts | 7 +- .../vulnerability-config.component.ts | 93 ++++++++++++++----- .../create-edit-rule.component.spec.ts | 10 +- src/ui_ng/lib/src/harbor-library.module.ts | 14 ++- .../job-log-viewer.component.spec.ts | 12 +-- .../job-log-viewer.component.template.ts | 2 +- .../job-log-viewer.component.ts | 30 +++++- .../replication/replication.component.spec.ts | 4 +- .../repository-stackview.component.spec.ts | 4 +- src/ui_ng/lib/src/service.config.ts | 8 ++ src/ui_ng/lib/src/service/index.ts | 3 +- src/ui_ng/lib/src/service/interface.ts | 1 + .../lib/src/service/job-log.service.spec.ts | 39 ++++++++ src/ui_ng/lib/src/service/job-log.service.ts | 84 +++++++++++++++++ src/ui_ng/lib/src/tag/tag.component.css.ts | 1 - src/ui_ng/lib/src/tag/tag.component.spec.ts | 5 +- .../result-bar-chart.component.spec.ts | 11 ++- .../result-bar-chart.component.ts | 14 ++- .../vulnerability-scanning/scanning.css.ts | 1 + .../vulnerability-scanning/scanning.html.ts | 7 +- src/ui_ng/package.json | 2 +- src/ui_ng/src/app/app-config.ts | 2 + .../src/app/config/config.component.html | 2 +- src/ui_ng/src/app/config/config.component.ts | 4 - .../tag-repository.component.html | 2 +- .../tag-repository.component.ts | 16 +++- src/ui_ng/src/i18n/lang/en-us-lang.json | 8 +- src/ui_ng/src/i18n/lang/es-es-lang.json | 8 +- src/ui_ng/src/i18n/lang/zh-cn-lang.json | 8 +- 32 files changed, 345 insertions(+), 90 deletions(-) create mode 100644 src/ui_ng/lib/src/service/job-log.service.spec.ts create mode 100644 src/ui_ng/lib/src/service/job-log.service.ts diff --git a/src/ui_ng/lib/src/config/registry-config.component.html.ts b/src/ui_ng/lib/src/config/registry-config.component.html.ts index b2cdccecc..a647ca0bb 100644 --- a/src/ui_ng/lib/src/config/registry-config.component.html.ts +++ b/src/ui_ng/lib/src/config/registry-config.component.html.ts @@ -2,7 +2,7 @@ export const REGISTRY_CONFIG_HTML: string = `
- +
diff --git a/src/ui_ng/lib/src/config/registry-config.component.spec.ts b/src/ui_ng/lib/src/config/registry-config.component.spec.ts index c29041130..41e9fda50 100644 --- a/src/ui_ng/lib/src/config/registry-config.component.spec.ts +++ b/src/ui_ng/lib/src/config/registry-config.component.spec.ts @@ -52,7 +52,8 @@ describe('RegistryConfigComponent (inline template)', () => { "project_creation_restriction": "everyone", "self_registration": true, "has_ca_root": true, - "harbor_version": "v1.1.1-rc1-160-g565110d" + "harbor_version": "v1.1.1-rc1-160-g565110d", + "next_scan_all": 0 }; beforeEach(async(() => { @@ -85,7 +86,7 @@ describe('RegistryConfigComponent (inline template)', () => { systemInfoService = fixture.debugElement.injector.get(SystemInfoService); spy = spyOn(cfgService, 'getConfigurations').and.returnValue(Promise.resolve(mockConfig)); saveSpy = spyOn(cfgService, 'saveConfigurations').and.returnValue(Promise.resolve(true)); - spySystemInfo = spyOn(systemInfoService, 'getSystemInfo').and.returnValues(Promise.resolve(mockSystemInfo)); + spySystemInfo = spyOn(systemInfoService, 'getSystemInfo').and.returnValue(Promise.resolve(mockSystemInfo)); fixture.detectChanges(); }); diff --git a/src/ui_ng/lib/src/config/registry-config.component.ts b/src/ui_ng/lib/src/config/registry-config.component.ts index dcfa80c03..d963d7ce4 100644 --- a/src/ui_ng/lib/src/config/registry-config.component.ts +++ b/src/ui_ng/lib/src/config/registry-config.component.ts @@ -54,17 +54,8 @@ export class RegistryConfigComponent implements OnInit { return this.systemInfo && this.systemInfo.with_clair; } - get clairDB(): ClairDBStatus { - return this.systemInfo && this.systemInfo.clair_vulnerability_status ? - this.systemInfo.clair_vulnerability_status : null; - } - ngOnInit(): void { - //Get system info - toPromise(this.systemInfoService.getSystemInfo()) - .then((info: SystemInfo) => this.systemInfo = info) - .catch(error => this.errorHandler.error(error)); - + this.loadSystemInfo(); //Initialize this.load(); } @@ -82,20 +73,25 @@ export class RegistryConfigComponent implements OnInit { return !this._isEmptyObject(this.getChanges()); } + //Get system info + loadSystemInfo(): void { + toPromise(this.systemInfoService.getSystemInfo()) + .then((info: SystemInfo) => this.systemInfo = info) + .catch(error => this.errorHandler.error(error)); + } + //Load configurations load(): void { this.onGoing = true; toPromise(this.configService.getConfigurations()) .then((config: Configuration) => { - this.onGoing = false; - this.configCopy = this._clone(config); this.config = config; + this.onGoing = false; }) .catch(error => { - this.onGoing = false; - this.errorHandler.error(error); + this.onGoing = false; }); } @@ -118,6 +114,8 @@ export class RegistryConfigComponent implements OnInit { }); //Reload to fetch all the updates this.load(); + //Reload all system info + //this.loadSystemInfo(); }) .catch(error => { this.onGoing = false; diff --git a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts index d6f750647..566a6c581 100644 --- a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts +++ b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts @@ -12,13 +12,13 @@ export const VULNERABILITY_CONFIG_HTML: string = ` @@ -38,7 +38,8 @@ export const VULNERABILITY_CONFIG_HTML: string = `
- + + {{ 'CONFIG.SCANNING.NEXT_SCAN' | translate }} {{ nextScanTimestamp | date:'HH:mm' }}
diff --git a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts index 6d30ca18a..625bffff4 100644 --- a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts +++ b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts @@ -1,9 +1,13 @@ -import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core'; +import { Component, Input, Output, EventEmitter, ViewChild, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms'; import { Configuration } from '../config'; import { VULNERABILITY_CONFIG_HTML, VULNERABILITY_CONFIG_STYLES } from './vulnerability-config.component.template'; -import { ScanningResultService } from '../../service/scanning.service'; +import { + ScanningResultService, + SystemInfo, + SystemInfoService +} from '../../service/index'; import { ErrorHandler } from '../../error-handler'; import { toPromise } from '../../utils'; import { TranslateService } from '@ngx-translate/core'; @@ -19,9 +23,10 @@ const ONE_DAY_SECONDS: number = 24 * ONE_HOUR_SECONDS; template: VULNERABILITY_CONFIG_HTML, styles: [VULNERABILITY_CONFIG_STYLES, REGISTRY_CONFIG_STYLES] }) -export class VulnerabilityConfigComponent { +export class VulnerabilityConfigComponent implements OnInit { _localTime: Date = new Date(); + onSubmitting: boolean = false; config: Configuration; openState: boolean = false; @Output() configChange: EventEmitter = new EventEmitter(); @@ -46,21 +51,37 @@ export class VulnerabilityConfigComponent { } @Input() showSubTitle: boolean = false; - @Input() clairDBStatus: ClairDBStatus; + systemInfo: SystemInfo; - get updatedTimestamp(): string { - if (this.clairDBStatus && this.clairDBStatus.overall_last_update > 0) { - return this.convertToLocalTime(this.clairDBStatus.overall_last_update*1000); + get scanAvailable(): boolean { + let dt: Date = new Date(); + return !this.onSubmitting && (this.nextScanTime <= 0 || dt.getTime() > ((this.nextScanTime + 30) * 1000)); + } + + get nextScanTimestamp(): Date { + return this.nextScanTime > 0 ? this.convertToLocalTime(this.nextScanTime) : null; + } + + get nextScanTime(): number { + return this.systemInfo && this.systemInfo.next_scan_all ? this.systemInfo.next_scan_all : 0; + } + + get updatedTimestamp(): Date { + if (this.systemInfo && + this.systemInfo.clair_vulnerability_status && + this.systemInfo.clair_vulnerability_status.overall_last_update > 0) { + return this.convertToLocalTime(this.systemInfo.clair_vulnerability_status.overall_last_update); } - return "--"; + return null; } get namespaceTimestamps(): ClairDetail[] { - if (this.clairDBStatus && - this.clairDBStatus.details && - this.clairDBStatus.details.length > 0) { - return this.clairDBStatus.details; + if (this.systemInfo && + this.systemInfo.clair_vulnerability_status && + this.systemInfo.clair_vulnerability_status.details && + this.systemInfo.clair_vulnerability_status.details.length > 0) { + return this.systemInfo.clair_vulnerability_status.details; } return []; @@ -207,31 +228,57 @@ export class VulnerabilityConfigComponent { } get isClairDBFullyReady(): boolean { - return this.clairDBStatus && this.clairDBStatus.overall_last_update > 0; + return this.systemInfo && + this.systemInfo.clair_vulnerability_status && + this.systemInfo.clair_vulnerability_status.overall_last_update > 0; } constructor( private scanningService: ScanningResultService, private errorHandler: ErrorHandler, - private translate: TranslateService) { } + private translate: TranslateService, + private systemInfoService: SystemInfoService + ) { } - convertToLocalTime(utcTime: number): string { - let offset: number = this._localTime.getTimezoneOffset() * 60; - let timeWithLocal: number = utcTime - offset; - let dt = new Date(); - dt.setTime(timeWithLocal); - return dt.toLocaleString(); + ngOnInit(): void { + this.getSystemInfo(); + } + + convertToLocalTime(utcTime: number): Date { + let dt: Date = new Date(); + dt.setTime(utcTime * 1000); + + return dt; } scanNow(): void { + if (this.onSubmitting) { + return;//Aoid duplicated submitting + } + + this.onSubmitting = true; toPromise(this.scanningService.startScanningAll()) .then(() => { this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_SUCCESS").subscribe((res: string) => { this.errorHandler.info(res); }); - //TODO: - //Change button disable status. + + //Update system info + this.getSystemInfo().then(() => { + this.onSubmitting = false; + }).catch(() => { + this.onSubmitting = false; + }); }) - .catch(error => this.errorHandler.error(error)) + .catch(error => { + this.errorHandler.error(error); + this.onSubmitting = false; + }); + } + + getSystemInfo(): Promise { + return toPromise(this.systemInfoService.getSystemInfo()) + .then((info: SystemInfo) => this.systemInfo = info) + .catch(error => this.errorHandler.error(error)); } } \ No newline at end of file diff --git a/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.spec.ts b/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.spec.ts index 0c88b2f17..58d3f66a5 100644 --- a/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.spec.ts +++ b/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.spec.ts @@ -18,7 +18,12 @@ import { ReplicationRule, ReplicationJob, Endpoint } from '../service/interface' import { ErrorHandler } from '../error-handler/error-handler'; import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; -import { ReplicationService, ReplicationDefaultService } from '../service/replication.service'; +import { + ReplicationService, + ReplicationDefaultService, + JobLogService, + JobLogDefaultService + } from '../service/index'; import { EndpointService, EndpointDefaultService } from '../service/endpoint.service'; import { JobLogViewerComponent } from '../job-log-viewer/job-log-viewer.component'; @@ -183,7 +188,8 @@ describe('CreateEditRuleComponent (inline template)', ()=>{ ErrorHandler, { provide: SERVICE_CONFIG, useValue: config }, { provide: ReplicationService, useClass: ReplicationDefaultService }, - { provide: EndpointService, useClass: EndpointDefaultService } + { provide: EndpointService, useClass: EndpointDefaultService }, + { provide: JobLogService, useClass: JobLogDefaultService } ] }); })); diff --git a/src/ui_ng/lib/src/harbor-library.module.ts b/src/ui_ng/lib/src/harbor-library.module.ts index 1af8b4a9f..4b08acc0f 100644 --- a/src/ui_ng/lib/src/harbor-library.module.ts +++ b/src/ui_ng/lib/src/harbor-library.module.ts @@ -41,7 +41,9 @@ import { ScanningResultService, ScanningResultDefaultService, ConfigurationService, - ConfigurationDefaultService + ConfigurationDefaultService, + JobLogService, + JobLogDefaultService } from './service/index'; import { ErrorHandler, @@ -74,7 +76,8 @@ export const DefaultServiceConfig: IServiceConfig = { langMessagePathForHttpLoader: "i18n/langs/", langMessageFileSuffixForHttpLoader: "-lang.json", localI18nMessageVariableMap: {}, - configurationEndpoint: "/api/configurations" + configurationEndpoint: "/api/configurations", + scanJobEndpoint: "/api/jobs/scan" }; /** @@ -112,7 +115,10 @@ export interface HarborModuleConfig { scanningService?: Provider, //Service implementation for configuration - configService?: Provider + configService?: Provider, + + //Service implementation for job log + jobLogService?: Provider } /** @@ -197,6 +203,7 @@ export class HarborLibraryModule { config.tagService || { provide: TagService, useClass: TagDefaultService }, config.scanningService || { provide: ScanningResultService, useClass: ScanningResultDefaultService }, config.configService || { provide: ConfigurationService, useClass: ConfigurationDefaultService }, + config.jobLogService || { provide: JobLogService, useClass: JobLogDefaultService }, //Do initializing TranslateServiceInitializer, { @@ -224,6 +231,7 @@ export class HarborLibraryModule { config.tagService || { provide: TagService, useClass: TagDefaultService }, config.scanningService || { provide: ScanningResultService, useClass: ScanningResultDefaultService }, config.configService || { provide: ConfigurationService, useClass: ConfigurationDefaultService }, + config.jobLogService || { provide: JobLogService, useClass: JobLogDefaultService }, ChannelService ] }; diff --git a/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.spec.ts b/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.spec.ts index 02defb2d5..2780bbc9a 100644 --- a/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.spec.ts +++ b/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.spec.ts @@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { DebugElement } from '@angular/core'; import { Observable } from 'rxjs/Observable'; -import { ReplicationService, ReplicationDefaultService } from '../service/index'; +import { JobLogService, JobLogDefaultService } from '../service/index'; import { JobLogViewerComponent } from './job-log-viewer.component'; import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; @@ -13,7 +13,7 @@ describe('JobLogViewerComponent (inline template)', () => { let component: JobLogViewerComponent; let fixture: ComponentFixture; let serviceConfig: IServiceConfig; - let replicationService: ReplicationService; + let jobLogService: JobLogDefaultService; let spy: jasmine.Spy; let testConfig: IServiceConfig = { replicationJobEndpoint: "/api/jobs/replication/testing" @@ -29,7 +29,7 @@ describe('JobLogViewerComponent (inline template)', () => { providers: [ ErrorHandler, { provide: SERVICE_CONFIG, useValue: testConfig }, - { provide: ReplicationService, useClass: ReplicationDefaultService } + { provide: JobLogService, useClass: JobLogDefaultService } ] }); })); @@ -39,9 +39,9 @@ describe('JobLogViewerComponent (inline template)', () => { component = fixture.componentInstance; serviceConfig = TestBed.get(SERVICE_CONFIG); - replicationService = fixture.debugElement.injector.get(ReplicationService); - spy = spyOn(replicationService, 'getJobLog') - .and.returnValues(Promise.resolve("job log text")); + jobLogService = fixture.debugElement.injector.get(JobLogService); + spy = spyOn(jobLogService, 'getJobLog') + .and.returnValue(Promise.resolve("job log text")); fixture.detectChanges(); }); diff --git a/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.template.ts b/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.template.ts index 5b4624edb..567ee1a94 100644 --- a/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.template.ts +++ b/src/ui_ng/lib/src/job-log-viewer/job-log-viewer.component.template.ts @@ -1,6 +1,6 @@ export const JOB_LOG_VIEWER_TEMPLATE: string = ` - + `; \ No newline at end of file diff --git a/src/ui_ng/package.json b/src/ui_ng/package.json index 0dab15a1b..d64f0a6f0 100644 --- a/src/ui_ng/package.json +++ b/src/ui_ng/package.json @@ -31,7 +31,7 @@ "clarity-icons": "^0.9.8", "clarity-ui": "^0.9.8", "core-js": "^2.4.1", - "harbor-ui": "0.3.24", + "harbor-ui": "0.3.42", "intl": "^1.2.5", "mutationobserver-shim": "^0.3.2", "ngx-cookie": "^1.0.0", diff --git a/src/ui_ng/src/app/app-config.ts b/src/ui_ng/src/app/app-config.ts index ce5ac5167..0702cba12 100644 --- a/src/ui_ng/src/app/app-config.ts +++ b/src/ui_ng/src/app/app-config.ts @@ -30,6 +30,7 @@ export class AppConfig { overall_last_update: 0, details: [] }; + this.next_scan_all = 0; } with_notary: boolean; @@ -43,4 +44,5 @@ export class AppConfig { has_ca_root: boolean; harbor_version: string; clair_vulnerability_status?: ClairDBStatus; + next_scan_all: number; } \ No newline at end of file diff --git a/src/ui_ng/src/app/config/config.component.html b/src/ui_ng/src/app/config/config.component.html index 8895e863d..cdc9f58c4 100644 --- a/src/ui_ng/src/app/config/config.component.html +++ b/src/ui_ng/src/app/config/config.component.html @@ -32,7 +32,7 @@
- +
diff --git a/src/ui_ng/src/app/config/config.component.ts b/src/ui_ng/src/app/config/config.component.ts index d1c8dcd6b..85cff6aae 100644 --- a/src/ui_ng/src/app/config/config.component.ts +++ b/src/ui_ng/src/app/config/config.component.ts @@ -85,10 +85,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy { return this.appConfigService.getConfig().with_clair; } - public get clairDB(): ClairDBStatus { - return this.appConfigService.getConfig().clair_vulnerability_status; - } - isCurrentTabLink(tabId: string): boolean { return this.currentTabId === tabId; } diff --git a/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.html b/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.html index 0ef68de50..3305a4db7 100644 --- a/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.html +++ b/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.html @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.ts b/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.ts index c2d4b1eea..4286bf6de 100644 --- a/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.ts +++ b/src/ui_ng/src/app/repository/tag-repository/tag-repository.component.ts @@ -29,8 +29,6 @@ export class TagRepositoryComponent implements OnInit { repoName: string; hasProjectAdminRole: boolean = false; registryUrl: string; - withNotary: boolean; - hasSignedIn: boolean; constructor( private route: ActivatedRoute, @@ -40,7 +38,6 @@ export class TagRepositoryComponent implements OnInit { } ngOnInit() { - this.hasSignedIn = (this.session.getCurrentUser() !== null); let resolverData = this.route.snapshot.data; if (resolverData) { this.hasProjectAdminRole = (resolverData['projectResolver']).has_project_admin_role; @@ -49,7 +46,18 @@ export class TagRepositoryComponent implements OnInit { this.repoName = this.route.snapshot.params['repo']; this.registryUrl = this.appConfigService.getConfig().registry_url; - this.withNotary = this.appConfigService.getConfig().with_notary; + } + + get withNotary(): boolean { + return this.appConfigService.getConfig().with_notary; + } + + get withClair(): boolean { + return this.appConfigService.getConfig().with_clair; + } + + get hasSignedIn(): boolean { + return this.session.getCurrentUser() !== null; } watchTagClickEvt(tagEvt: TagClickEvent): void { diff --git a/src/ui_ng/src/i18n/lang/en-us-lang.json b/src/ui_ng/src/i18n/lang/en-us-lang.json index 6745c5e56..23f8c3095 100644 --- a/src/ui_ng/src/i18n/lang/en-us-lang.json +++ b/src/ui_ng/src/i18n/lang/en-us-lang.json @@ -416,7 +416,8 @@ "DAILY_POLICY": "Daily At", "REFRESH_POLICY": "Upon Refresh", "DB_REFRESH_TIME": "Database updated on", - "DB_NOT_READY": "Vulnerability database might not be fully ready!" + "DB_NOT_READY": "Vulnerability database might not be fully ready!", + "NEXT_SCAN": "Available after" }, "TEST_MAIL_SUCCESS": "Connection to mail server is verified.", "TEST_LDAP_SUCCESS": "Connection to LDAP server is verified.", @@ -464,7 +465,7 @@ "STATE": { "STOPPED": "Not Scanned", "QUEUED": "Queued", - "ERROR": "Error", + "ERROR": "View Log", "SCANNING": "Scanning", "UNKNOWN": "Unknown" }, @@ -496,7 +497,8 @@ "PLACEHOLDER": "Filter Vulnerabilities", "PACKAGE": "Package with", "PACKAGES": "Packages with", - "SCAN_NOW": "Scan" + "SCAN_NOW": "Scan", + "JOB_LOG_VIEWER": "View Scanning Job Log" }, "PUSH_IMAGE": { "TITLE": "Push Image", diff --git a/src/ui_ng/src/i18n/lang/es-es-lang.json b/src/ui_ng/src/i18n/lang/es-es-lang.json index 84e423c4b..9be60dcbb 100644 --- a/src/ui_ng/src/i18n/lang/es-es-lang.json +++ b/src/ui_ng/src/i18n/lang/es-es-lang.json @@ -417,7 +417,8 @@ "DAILY_POLICY": "Daily At", "REFRESH_POLICY": "Upon Refresh", "DB_REFRESH_TIME": "Database updated on", - "DB_NOT_READY": "Vulnerability database might not be fully ready!" + "DB_NOT_READY": "Vulnerability database might not be fully ready!", + "NEXT_SCAN": "Available after" }, "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.", @@ -463,7 +464,7 @@ "STATE": { "STOPPED": "Not Scanned", "QUEUED": "Queued", - "ERROR": "Error", + "ERROR": "View Log", "SCANNING": "Scanning", "UNKNOWN": "Unknown" }, @@ -495,7 +496,8 @@ "PLACEHOLDER": "Filter Vulnerabilities", "PACKAGE": "Package with", "PACKAGES": "Packages with", - "SCAN_NOW": "Scan" + "SCAN_NOW": "Scan", + "JOB_LOG_VIEWER": "View Scanning Job Log" }, "PUSH_IMAGE": { "TITLE": "Push Image", diff --git a/src/ui_ng/src/i18n/lang/zh-cn-lang.json b/src/ui_ng/src/i18n/lang/zh-cn-lang.json index e7a33e58b..e979c19b6 100644 --- a/src/ui_ng/src/i18n/lang/zh-cn-lang.json +++ b/src/ui_ng/src/i18n/lang/zh-cn-lang.json @@ -420,7 +420,8 @@ "DAILY_POLICY": "每日定时", "REFRESH_POLICY": "缺陷库刷新后", "DB_REFRESH_TIME": "数据库更新于", - "DB_NOT_READY": "缺陷数据库可能没有完全准备好!" + "DB_NOT_READY": "缺陷数据库可能没有完全准备好!", + "NEXT_SCAN": "下次可用时间" }, "TEST_MAIL_SUCCESS": "邮件服务器的连通正常。", "TEST_LDAP_SUCCESS": "LDAP服务器的连通正常。", @@ -468,7 +469,7 @@ "STATE": { "STOPPED": "未扫描", "QUEUED": "已入队列", - "ERROR": "错误", + "ERROR": "查看日志", "SCANNING": "扫描中", "UNKNOWN": "未知" }, @@ -500,7 +501,8 @@ "PLACEHOLDER": "过滤缺陷", "PACKAGE": "个组件有", "PACKAGES": "个组件有", - "SCAN_NOW": "扫描" + "SCAN_NOW": "扫描", + "JOB_LOG_VIEWER": "查看扫描日志" }, "PUSH_IMAGE": { "TITLE": "推送镜像", From 598f2b43dbb0169853f3c69de0f3b1b96d12a22f Mon Sep 17 00:00:00 2001 From: Steven Zou Date: Mon, 24 Jul 2017 13:49:43 +0800 Subject: [PATCH 2/2] add missing i18n message keys --- .../list-project-ro/list-project-ro.component.html | 5 ++--- .../list-repository-ro.component.html | 5 ++--- src/ui_ng/src/i18n/lang/en-us-lang.json | 12 ++++++++---- src/ui_ng/src/i18n/lang/es-es-lang.json | 12 ++++++++---- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.html b/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.html index c8df1a62c..2d1bdc9db 100644 --- a/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.html +++ b/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.html @@ -10,9 +10,8 @@ {{p.creation_time | date: 'short'}} - {{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'PROJECT.OF' | translate}} - {{pagination.totalItems }} {{'PROJECT.ITEMS' | translate}} - + {{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'PROJECT.OF' | translate}} {{pagination.totalItems }} {{'PROJECT.ITEMS' | translate}} + diff --git a/src/ui_ng/src/app/shared/list-repository-ro/list-repository-ro.component.html b/src/ui_ng/src/app/shared/list-repository-ro/list-repository-ro.component.html index 2871d8c51..d4b622465 100644 --- a/src/ui_ng/src/app/shared/list-repository-ro/list-repository-ro.component.html +++ b/src/ui_ng/src/app/shared/list-repository-ro/list-repository-ro.component.html @@ -8,8 +8,7 @@ {{r.pull_count}} - {{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'REPOSITORY.OF' | translate}} - {{pagination.totalItems }} {{'REPOSITORY.ITEMS' | translate}} - + {{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'REPOSITORY.OF' | translate}} {{pagination.totalItems }} {{'REPOSITORY.ITEMS' | translate}} + \ No newline at end of file diff --git a/src/ui_ng/src/i18n/lang/en-us-lang.json b/src/ui_ng/src/i18n/lang/en-us-lang.json index 23f8c3095..4d9bfb203 100644 --- a/src/ui_ng/src/i18n/lang/en-us-lang.json +++ b/src/ui_ng/src/i18n/lang/en-us-lang.json @@ -117,7 +117,8 @@ "DELETION_TITLE": "Confirm user deletion", "DELETION_SUMMARY": "Do you want to delete user {{param}}?", "DELETE_SUCCESS": "User deleted successfully.", - "ITEMS": "items" + "ITEMS": "items", + "OF": "of" }, "PROJECT": { "PROJECTS": "Projects", @@ -152,7 +153,8 @@ "DELETED_SUCCESS": "Deleted project successfully.", "TOGGLED_SUCCESS": "Toggled project successfully.", "FAILED_TO_DELETE_PROJECT": "Project contains repositories or replication rules cannot be deleted.", - "INLINE_HELP_PUBLIC": "When a project is set to public, anyone has read permission to the repositories under this project, and the user does not need to run \"docker login\" before pulling images under this project." + "INLINE_HELP_PUBLIC": "When a project is set to public, anyone has read permission to the repositories under this project, and the user does not need to run \"docker login\" before pulling images under this project.", + "OF": "of" }, "PROJECT_DETAIL": { "REPOSITORIES": "Repositories", @@ -182,7 +184,8 @@ "DELETION_SUMMARY": "Do you want to delete project member {{param}}?", "ADDED_SUCCESS": "Added member successfully.", "DELETED_SUCCESS": "Deleted member successfully.", - "SWITCHED_SUCCESS": "Switched member role successfully." + "SWITCHED_SUCCESS": "Switched member role successfully.", + "OF": "of" }, "AUDIT_LOG": { "USERNAME": "Username", @@ -201,7 +204,8 @@ "SIMPLE": "Simple", "ITEMS": "items", "FILTER_PLACEHOLDER": "Filter Logs", - "INVALID_DATE": "Invalid date." + "INVALID_DATE": "Invalid date.", + "OF": "of" }, "REPLICATION": { "REPLICATION_RULE": "Replication Rule", diff --git a/src/ui_ng/src/i18n/lang/es-es-lang.json b/src/ui_ng/src/i18n/lang/es-es-lang.json index 9be60dcbb..6b79c19bb 100644 --- a/src/ui_ng/src/i18n/lang/es-es-lang.json +++ b/src/ui_ng/src/i18n/lang/es-es-lang.json @@ -117,7 +117,8 @@ "DELETION_TITLE": "Confirmar eliminación de usuario", "DELETION_SUMMARY": "¿Quiere eliminar el usuario {{param}}?", "DELETE_SUCCESS": "Usuario eliminado satisfactoriamente.", - "ITEMS": "elementos" + "ITEMS": "elementos", + "OF": "of" }, "PROJECT": { "PROJECTS": "Proyectos", @@ -152,7 +153,8 @@ "DELETED_SUCCESS": "Proyecto eliminado satisfactoriamente.", "TOGGLED_SUCCESS": "Proyecto alternado satisfactoriamente.", "FAILED_TO_DELETE_PROJECT": "Los proyectos que contienen repositorios o reglas de replicación no pueden eliminarse.", - "INLINE_HELP_PUBLIC": "Cuando un proyecto se marca como público, todo el mundo tiene permisos de lectura sobre los repositorio de dicho proyecto, y no hace falta hacer \"docker login\" antes de subir imágenes a ellos." + "INLINE_HELP_PUBLIC": "Cuando un proyecto se marca como público, todo el mundo tiene permisos de lectura sobre los repositorio de dicho proyecto, y no hace falta hacer \"docker login\" antes de subir imágenes a ellos.", + "OF": "of" }, "PROJECT_DETAIL": { "REPOSITORIES": "Repositorios", @@ -182,7 +184,8 @@ "DELETION_SUMMARY": "¿Quiere eliminar el miembro {{param}} del proyecto?", "ADDED_SUCCESS": "Miembro añadido satisfactoriamente.", "DELETED_SUCCESS": "Miembro eliminado satisfactoriamente", - "SWITCHED_SUCCESS": "Rol del miembro cambiado satisfactoriamente." + "SWITCHED_SUCCESS": "Rol del miembro cambiado satisfactoriamente.", + "OF": "of" }, "AUDIT_LOG": { "USERNAME": "Nombre de usuario", @@ -201,7 +204,8 @@ "SIMPLE": "Simple", "ITEMS": "elementos", "FILTER_PLACEHOLDER": "Filtrar logs", - "INVALID_DATE": "Fecha invalida." + "INVALID_DATE": "Fecha invalida.", + "OF": "of" }, "REPLICATION": { "REPLICATION_RULE": "Reglas de Replicación",