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 1fa7cd426..f07154c89 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 @@ -8,7 +8,7 @@ import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation import { ReplicationComponent } from '../replication/replication.component'; import { ListReplicationRuleComponent } from '../list-replication-rule/list-replication-rule.component'; -import { ListReplicationJobComponent } from '../list-replication-job/list-replication-job.component'; + import { CreateEditRuleComponent } from './create-edit-rule.component'; import { DatePickerComponent } from '../datetime-picker/datetime-picker.component'; import { DateValidatorDirective } from '../datetime-picker/date-validator.directive'; @@ -88,7 +88,7 @@ describe('CreateEditRuleComponent (inline template)', ()=>{ "repository": "library/busybox", "policy_id": 2, "operation": "transfer", - "tags": null + "tags": null } ]; @@ -171,7 +171,6 @@ describe('CreateEditRuleComponent (inline template)', ()=>{ declarations: [ ReplicationComponent, ListReplicationRuleComponent, - ListReplicationJobComponent, CreateEditRuleComponent, ConfirmationDialogComponent, DatePickerComponent, @@ -188,26 +187,28 @@ describe('CreateEditRuleComponent (inline template)', ()=>{ })); beforeEach(()=>{ - fixture = TestBed.createComponent(ReplicationComponent); - fixtureCreate = TestBed.createComponent(CreateEditRuleComponent); comp = fixture.componentInstance; comp.projectId = 1; comp.search.ruleId = 1; - compCreate = fixtureCreate.componentInstance; - comp.projectId = 1; - replicationService = fixture.debugElement.injector.get(ReplicationService); - endpointService = fixtureCreate.debugElement.injector.get(EndpointService); - + spyRules = spyOn(replicationService, 'getReplicationRules').and.returnValues(Promise.resolve(mockRules)); spyOneRule = spyOn(replicationService, 'getReplicationRule').and.returnValue(Promise.resolve(mockRule)); - spyJobs = spyOn(replicationService, 'getJobs').and.returnValues(Promise.resolve(mockJobs)); - spyEndpoint = spyOn(endpointService, 'getEndpoints').and.returnValues(Promise.resolve(mockEndpoints)); + fixture.detectChanges(); + }); + beforeEach(()=>{ + fixtureCreate = TestBed.createComponent(CreateEditRuleComponent); + + compCreate = fixtureCreate.componentInstance; + compCreate.projectId = 1; + + endpointService = fixtureCreate.debugElement.injector.get(EndpointService); + spyEndpoint = spyOn(endpointService, 'getEndpoints').and.returnValues(Promise.resolve(mockEndpoints)); fixture.detectChanges(); }); diff --git a/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.ts b/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.ts index ec6477e86..0fe03bd23 100644 --- a/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.ts +++ b/src/ui_ng/lib/src/create-edit-rule/create-edit-rule.component.ts @@ -208,7 +208,7 @@ export class CreateEditRuleComponent implements AfterViewChecked { }).catch(err=>this.errorHandler.error(err)); } else { if(!this.projectId) { - console.error('Project ID cannot be unset'); + this.errorHandler.error('Project ID cannot be unset'); return; } this.actionType = ActionType.ADD_NEW; @@ -378,12 +378,12 @@ export class CreateEditRuleComponent implements AfterViewChecked { for(let key in data) { let current = data[key]; let origin: string = comparison[key]; - if(((this.actionType === ActionType.EDIT && !this.readonly && !current ) || current) && current !== origin) { - this.hasChanged = true; + if(((self.actionType === ActionType.EDIT && !self.readonly && !current ) || current) && current !== origin) { + self.hasChanged = true; break; } else { - this.hasChanged = false; - this.inlineAlert.close(); + self.hasChanged = false; + self.inlineAlert.close(); } } }); diff --git a/src/ui_ng/lib/src/harbor-library.module.ts b/src/ui_ng/lib/src/harbor-library.module.ts index d7e426dbb..98d37ca11 100644 --- a/src/ui_ng/lib/src/harbor-library.module.ts +++ b/src/ui_ng/lib/src/harbor-library.module.ts @@ -10,7 +10,6 @@ import { TAG_DIRECTIVES } from './tag/index'; import { REPLICATION_DIRECTIVES } from './replication/index'; import { CREATE_EDIT_RULE_DIRECTIVES } from './create-edit-rule/index'; import { LIST_REPLICATION_RULE_DIRECTIVES } from './list-replication-rule/index'; -import { LIST_REPLICATION_JOB_DIRECTIVES } from './list-replication-job/index'; import { CREATE_EDIT_ENDPOINT_DIRECTIVES } from './create-edit-endpoint/index'; @@ -137,7 +136,6 @@ export function initConfig(translateService: TranslateService, config: IServiceC INLINE_ALERT_DIRECTIVES, REPLICATION_DIRECTIVES, LIST_REPLICATION_RULE_DIRECTIVES, - LIST_REPLICATION_JOB_DIRECTIVES, CREATE_EDIT_RULE_DIRECTIVES, DATETIME_PICKER_DIRECTIVES ], @@ -153,7 +151,6 @@ export function initConfig(translateService: TranslateService, config: IServiceC INLINE_ALERT_DIRECTIVES, REPLICATION_DIRECTIVES, LIST_REPLICATION_RULE_DIRECTIVES, - LIST_REPLICATION_JOB_DIRECTIVES, CREATE_EDIT_RULE_DIRECTIVES, DATETIME_PICKER_DIRECTIVES ], diff --git a/src/ui_ng/lib/src/i18n/lang/en-us-lang.ts b/src/ui_ng/lib/src/i18n/lang/en-us-lang.ts index 1b4178daf..f214b3ec9 100644 --- a/src/ui_ng/lib/src/i18n/lang/en-us-lang.ts +++ b/src/ui_ng/lib/src/i18n/lang/en-us-lang.ts @@ -253,6 +253,7 @@ export const EN_US_LANG: any = { "CREATION_TIME": "Start Time", "END_TIME": "End Time", "LOGS": "Logs", + "OF": "of", "ITEMS": "item(s)", "TOGGLE_ENABLE_TITLE": "Enable Rule", "CONFIRM_TOGGLE_ENABLE_POLICY": "After enabling the replication rule, all repositories under the project will be replicated to the destination registry. \nPlease confirm to continue.", diff --git a/src/ui_ng/lib/src/i18n/lang/zh-cn-lang.ts b/src/ui_ng/lib/src/i18n/lang/zh-cn-lang.ts index f97d39931..8a3f57931 100644 --- a/src/ui_ng/lib/src/i18n/lang/zh-cn-lang.ts +++ b/src/ui_ng/lib/src/i18n/lang/zh-cn-lang.ts @@ -253,6 +253,7 @@ export const ZH_CN_LANG: any = { "CREATION_TIME": "创建时间", "END_TIME": "结束时间", "LOGS": "日志", + "OF": "共计", "ITEMS": "条记录", "TOGGLE_ENABLE_TITLE": "启用规则", "CONFIRM_TOGGLE_ENABLE_POLICY": "启用规则后,该项目下的所有镜像仓库将复制到目标实例。\n请确认继续。", diff --git a/src/ui_ng/lib/src/list-replication-job/index.ts b/src/ui_ng/lib/src/list-replication-job/index.ts deleted file mode 100644 index 5b04492b9..000000000 --- a/src/ui_ng/lib/src/list-replication-job/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Type } from '@angular/core'; -import { ListReplicationJobComponent } from './list-replication-job.component'; - -export const LIST_REPLICATION_JOB_DIRECTIVES: Type[] = [ - ListReplicationJobComponent -]; \ No newline at end of file diff --git a/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.html.ts b/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.html.ts deleted file mode 100644 index a619a3c4b..000000000 --- a/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.html.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const REPLICATION_JOB_TEMPLATE: string = ` - - {{'REPLICATION.NAME' | translate}} - {{'REPLICATION.STATUS' | translate}} - {{'REPLICATION.OPERATION' | translate}} - {{'REPLICATION.CREATION_TIME' | translate}} - {{'REPLICATION.END_TIME' | translate}} - {{'REPLICATION.LOGS' | translate}} - - {{j.repository}} - {{j.status}} - {{j.operation}} - {{j.creation_time}} - {{j.update_time}} - - - - - - - - {{ jobs ? jobs.length : 0 }} {{'REPLICATION.ITEMS' | translate}} - - -`; \ No newline at end of file diff --git a/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.spec.ts b/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.spec.ts deleted file mode 100644 index b67844500..000000000 --- a/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.spec.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { ComponentFixture, TestBed, async } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { NoopAnimationsModule } from "@angular/platform-browser/animations"; - -import { DebugElement } from '@angular/core'; - -import { SharedModule } from '../shared/shared.module'; - -import { ListReplicationJobComponent } from '../list-replication-job/list-replication-job.component'; -import { ReplicationJob } from '../service/interface'; - -import { ErrorHandler } from '../error-handler/error-handler'; -import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; -import { ReplicationService, ReplicationDefaultService } from '../service/replication.service'; - - -describe('ListReplicationJobComponent (inline template)', ()=>{ - let mockJobs: ReplicationJob[] = [ - { - "id": 1, - "status": "stopped", - "repository": "library/busybox", - "policy_id": 1, - "operation": "transfer", - "tags": null - }, - { - "id": 2, - "status": "stopped", - "repository": "library/busybox", - "policy_id": 1, - "operation": "transfer", - "tags": null - }, - { - "id": 3, - "status": "stopped", - "repository": "library/busybox", - "policy_id": 2, - "operation": "transfer", - "tags": null - } - ]; - - let fixture: ComponentFixture; - - let comp: ListReplicationJobComponent; - - let replicationService: ReplicationService; - - let spyJobs: jasmine.Spy; - - let config: IServiceConfig = { - replicationJobEndpoint: '/api/policies/replication/testing' - }; - - beforeEach(async(()=>{ - TestBed.configureTestingModule({ - imports: [ - SharedModule, - NoopAnimationsModule - ], - declarations: [ - ListReplicationJobComponent - ], - providers: [ - ErrorHandler, - { provide: SERVICE_CONFIG, useValue: config }, - { provide: ReplicationService, useClass: ReplicationDefaultService } - ] - }); - })); - - beforeEach(()=>{ - fixture = TestBed.createComponent(ListReplicationJobComponent); - comp = fixture.componentInstance; - replicationService = fixture.debugElement.injector.get(ReplicationService); - spyJobs = spyOn(replicationService, 'getJobs').and.returnValues(Promise.resolve(mockJobs)); - fixture.detectChanges(); - }); - - it('Should load and render data', async(()=>{ - fixture.detectChanges(); - fixture.whenStable().then(()=>{ - fixture.detectChanges(); - let de: DebugElement = fixture.debugElement.query(By.css('datagrid-cell')); - expect(de).toBeTruthy(); - fixture.detectChanges(); - let el: HTMLElement = de.nativeElement; - expect(el.textContent.trim()).toEqual('library/busybox'); - }); - })); - -}); \ No newline at end of file diff --git a/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.ts b/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.ts deleted file mode 100644 index 87b071967..000000000 --- a/src/ui_ng/lib/src/list-replication-job/list-replication-job.component.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2017 VMware, Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; -import { ReplicationJob } from '../service/interface'; -import { State } from 'clarity-angular'; -import { ErrorHandler } from '../error-handler/error-handler'; - -import { REPLICATION_JOB_TEMPLATE } from './list-replication-job.component.html'; - -@Component({ - selector: 'list-replication-job', - template: REPLICATION_JOB_TEMPLATE, - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class ListReplicationJobComponent { - @Input() jobs: ReplicationJob[]; - @Input() totalRecordCount: number; - @Input() totalPage: number; - @Output() paginate = new EventEmitter(); - - constructor( - private errorHandler: ErrorHandler, - private ref: ChangeDetectorRef) { - let hnd = setInterval(()=>ref.markForCheck(), 100); - setTimeout(()=>clearInterval(hnd), 1000); - } - - pageOffset: number = 1; - - refresh(state: State) { - if(this.jobs) { - this.paginate.emit(state); - } - } -} \ No newline at end of file diff --git a/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts b/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts index f61267adb..e92dc8ea6 100644 --- a/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts +++ b/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts @@ -33,5 +33,8 @@ export const LIST_REPLICATION_RULE_TEMPLATE: string = ` {{ (p.enabled === 1 ? 'REPLICATION.ENABLED' : 'REPLICATION.DISABLED') | translate}} - {{ (rules ? rules.length : 0) }} {{'REPLICATION.ITEMS' | translate}} + + {{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'REPLICATION.OF' | translate}} {{pagination.totalItems }} {{'REPLICATION.ITEMS' | translate}} + + `; \ No newline at end of file diff --git a/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.ts b/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.ts index 6ab762d24..b52ddade2 100644 --- a/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.ts +++ b/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.ts @@ -27,6 +27,8 @@ import { TranslateService } from '@ngx-translate/core'; import { ErrorHandler } from '../error-handler/error-handler'; import { toPromise } from '../utils'; +import { State } from 'clarity-angular'; + import { LIST_REPLICATION_RULE_TEMPLATE } from './list-replication-rule.component.html'; @Component({ diff --git a/src/ui_ng/lib/src/replication/replication.component.html.ts b/src/ui_ng/lib/src/replication/replication.component.html.ts index 6cc71a146..f3ef8748b 100644 --- a/src/ui_ng/lib/src/replication/replication.component.html.ts +++ b/src/ui_ng/lib/src/replication/replication.component.html.ts @@ -46,6 +46,30 @@ export const REPLICATION_TEMPLATE: string = `
- + + {{'REPLICATION.NAME' | translate}} + {{'REPLICATION.STATUS' | translate}} + {{'REPLICATION.OPERATION' | translate}} + {{'REPLICATION.CREATION_TIME' | translate}} + {{'REPLICATION.END_TIME' | translate}} + {{'REPLICATION.LOGS' | translate}} + + {{j.repository}} + {{j.status}} + {{j.operation}} + {{j.creation_time}} + {{j.update_time}} + + + + + + + + {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'REPLICATION.OF' | translate}} + {{pagination.totalItems}} {{'REPLICATION.ITEMS' | translate}} + + +
`; \ No newline at end of file diff --git a/src/ui_ng/lib/src/replication/replication.component.spec.ts b/src/ui_ng/lib/src/replication/replication.component.spec.ts index ed766fe79..ab4dd0692 100644 --- a/src/ui_ng/lib/src/replication/replication.component.spec.ts +++ b/src/ui_ng/lib/src/replication/replication.component.spec.ts @@ -7,7 +7,6 @@ import { SharedModule } from '../shared/shared.module'; import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component'; import { ReplicationComponent } from './replication.component'; import { ListReplicationRuleComponent } from '../list-replication-rule/list-replication-rule.component'; -import { ListReplicationJobComponent } from '../list-replication-job/list-replication-job.component'; import { CreateEditRuleComponent } from '../create-edit-rule/create-edit-rule.component'; import { DatePickerComponent } from '../datetime-picker/datetime-picker.component'; import { DateValidatorDirective } from '../datetime-picker/date-validator.directive'; @@ -71,6 +70,7 @@ describe('Replication Component (inline template)', ()=>{ "repository": "library/nginx", "policy_id": 1, "operation": "transfer", + "update_time": new Date("2017-05-23 12:20:33"), "tags": null }, { @@ -79,6 +79,7 @@ describe('Replication Component (inline template)', ()=>{ "repository": "library/mysql", "policy_id": 1, "operation": "transfer", + "update_time": new Date("2017-05-27 12:20:33"), "tags": null }, { @@ -87,6 +88,7 @@ describe('Replication Component (inline template)', ()=>{ "repository": "library/busybox", "policy_id": 2, "operation": "transfer", + "update_time": new Date("2017-04-23 12:20:33"), "tags": null } ]; @@ -169,7 +171,6 @@ describe('Replication Component (inline template)', ()=>{ declarations: [ ReplicationComponent, ListReplicationRuleComponent, - ListReplicationJobComponent, CreateEditRuleComponent, ConfirmationDialogComponent, DatePickerComponent, @@ -283,4 +284,17 @@ describe('Replication Component (inline template)', ()=>{ expect(el.textContent.trim()).toEqual('library/mysql'); }); })); + + it('Should filter replication jobs by date range', async(()=>{ + fixture.detectChanges(); + fixture.whenStable().then(()=>{ + fixture.detectChanges(); + comp.doJobSearchByStartTime('2017-05-01'); + comp.doJobSearchByEndTime('2015-05-25'); + let el: HTMLElement = deJobs.nativeElement; + fixture.detectChanges(); + expect(el).toBeTruthy(); + expect(el.textContent.trim()).toEqual('library/nginx'); + }); + })) }); \ No newline at end of file diff --git a/src/ui_ng/lib/src/replication/replication.component.ts b/src/ui_ng/lib/src/replication/replication.component.ts index a93708517..6a85e35a7 100644 --- a/src/ui_ng/lib/src/replication/replication.component.ts +++ b/src/ui_ng/lib/src/replication/replication.component.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. import { Component, OnInit, ViewChild, Input } from '@angular/core'; -import { ResponseOptions } from '@angular/http'; +import { ResponseOptions, RequestOptions } from '@angular/http'; import { NgModel } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -24,8 +24,6 @@ import { ReplicationService } from '../service/replication.service'; import { RequestQueryParams } from '../service/RequestQueryParams'; import { ReplicationRule, ReplicationJob, Endpoint } from '../service/interface'; -import { State } from 'clarity-angular'; - import { toPromise } from '../utils'; import { REPLICATION_TEMPLATE } from './replication.component.html'; @@ -142,13 +140,8 @@ export class ReplicationComponent implements OnInit { } } - fetchReplicationJobs(state?: State) { - if(state && state.page) { - if(!state.page.to && state.page.to !== 0) { - return; - } - this.search.page = state.page.to + 1; - } + fetchReplicationJobs() { + let params: RequestQueryParams = new RequestQueryParams(); params.set('status', this.search.status); params.set('repository', this.search.repoName);