Add pagination support to label list (#14714)

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Will Sun 2021-04-26 10:32:38 +08:00 committed by GitHub
parent 705cb5b55d
commit 0c724d3a44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 256 additions and 84 deletions

View File

@ -11,6 +11,7 @@ import { LabelService, SystemInfoService, UserPermissionService } from "../../..
import { ErrorHandler } from "../../../../../../shared/units/error-handler"; import { ErrorHandler } from "../../../../../../shared/units/error-handler";
import { OperationService } from "../../../../../../shared/components/operation/operation.service"; import { OperationService } from "../../../../../../shared/components/operation/operation.service";
import { delay } from "rxjs/operators"; import { delay } from "rxjs/operators";
import { SharedTestingModule } from "../../../../../../shared/shared.module";
describe('ChartVersionComponent', () => { describe('ChartVersionComponent', () => {
let component: ChartVersionComponent; let component: ChartVersionComponent;
@ -85,13 +86,10 @@ describe('ChartVersionComponent', () => {
CUSTOM_ELEMENTS_SCHEMA CUSTOM_ELEMENTS_SCHEMA
], ],
imports: [ imports: [
ClarityModule, SharedTestingModule
TranslateModule.forRoot(),
FormsModule
], ],
declarations: [ChartVersionComponent, LabelFilterComponent], declarations: [ChartVersionComponent, LabelFilterComponent],
providers: [ providers: [
TranslateService,
{ provide: SystemInfoService, useValue: mockSystemInfoService }, { provide: SystemInfoService, useValue: mockSystemInfoService },
{ provide: LabelService, useValue: mockLabelService }, { provide: LabelService, useValue: mockLabelService },
{ provide: UserPermissionService, useValue: mockUserPermissionService }, { provide: UserPermissionService, useValue: mockUserPermissionService },

View File

@ -12,8 +12,7 @@ import { TranslateService } from "@ngx-translate/core";
import { HelmChartVersion, HelmChartMaintainer } from "../../helm-chart.interface.service"; import { HelmChartVersion, HelmChartMaintainer } from "../../helm-chart.interface.service";
import { HelmChartService } from "../../helm-chart.service"; import { HelmChartService } from "../../helm-chart.service";
import { import {
Label, LabelService as OldLabelService,
LabelService,
State, State,
SystemInfo, SystemInfo,
SystemInfoService, SystemInfoService,
@ -33,7 +32,9 @@ import { errorHandler } from "../../../../../../shared/units/shared.utils";
import { ConfirmationDialogComponent } from "../../../../../../shared/components/confirmation-dialog"; import { ConfirmationDialogComponent } from "../../../../../../shared/components/confirmation-dialog";
import { ConfirmationMessage } from "../../../../../global-confirmation-dialog/confirmation-message"; import { ConfirmationMessage } from "../../../../../global-confirmation-dialog/confirmation-message";
import { ConfirmationAcknowledgement } from "../../../../../global-confirmation-dialog/confirmation-state-message"; import { ConfirmationAcknowledgement } from "../../../../../global-confirmation-dialog/confirmation-state-message";
import { Label } from "../../../../../../../../ng-swagger-gen/models/label";
import { LabelService } from "../../../../../../../../ng-swagger-gen/services/label.service";
const PAGE_SIZE: number = 100;
@Component({ @Component({
selector: "hbr-helm-chart-version", selector: "hbr-helm-chart-version",
templateUrl: "./helm-chart-version.component.html", templateUrl: "./helm-chart-version.component.html",
@ -82,7 +83,8 @@ export class ChartVersionComponent implements OnInit {
private errorHandlerEntity: ErrorHandler, private errorHandlerEntity: ErrorHandler,
private systemInfoService: SystemInfoService, private systemInfoService: SystemInfoService,
private helmChartService: HelmChartService, private helmChartService: HelmChartService,
private resrouceLabelService: LabelService, private labelService: LabelService,
private resrouceLabelService: OldLabelService,
public userPermissionService: UserPermissionService, public userPermissionService: UserPermissionService,
private operationService: OperationService, private operationService: OperationService,
private translateService: TranslateService, private translateService: TranslateService,
@ -109,11 +111,78 @@ export class ChartVersionComponent implements OnInit {
} }
getLabels() { getLabels() {
forkJoin(this.resrouceLabelService.getLabels("g"), this.resrouceLabelService.getProjectLabels(this.projectId)) // get all project labels
.subscribe( this.labelService.ListLabelsResponse({
(labels) => { pageSize: PAGE_SIZE,
this.labels = [].concat(...labels); page: 1,
}); scope: 'p',
projectId: this.projectId
}).subscribe(res => {
if (res.headers) {
const xHeader: string = res.headers.get("X-Total-Count");
const totalCount = parseInt(xHeader, 0);
let arr = res.body || [];
if (totalCount <= PAGE_SIZE) { // already gotten all project labels
if (arr && arr.length) {
this.labels = this.labels.concat(arr);
}
} else { // get all the project labels in specified times
const times: number = Math.ceil(totalCount / PAGE_SIZE);
const observableList: Observable<Label[]>[] = [];
for (let i = 2; i <= times; i++) {
observableList.push(this.labelService.ListLabels({
page: i,
pageSize: PAGE_SIZE,
scope: 'p',
projectId: this.projectId
}));
}
forkJoin(observableList).subscribe(response => {
if (response && response.length) {
response.forEach(item => {
arr = arr.concat(item);
});
this.labels = this.labels.concat(arr);
}
});
}
}
});
// get all global labels
this.labelService.ListLabelsResponse({
pageSize: PAGE_SIZE,
page: 1,
scope: 'g',
}).subscribe(res => {
if (res.headers) {
const xHeader: string = res.headers.get("X-Total-Count");
const totalCount = parseInt(xHeader, 0);
let arr = res.body || [];
if (totalCount <= PAGE_SIZE) { // already gotten all global labels
if (arr && arr.length) {
this.labels = this.labels.concat(arr);
}
} else { // get all the global labels in specified times
const times: number = Math.ceil(totalCount / PAGE_SIZE);
const observableList: Observable<Label[]>[] = [];
for (let i = 2; i <= times; i++) {
observableList.push(this.labelService.ListLabels({
page: i,
pageSize: PAGE_SIZE,
scope: 'g',
}));
}
forkJoin(observableList).subscribe(response => {
if (response && response.length) {
response.forEach(item => {
arr = arr.concat(item);
});
this.labels = this.labels.concat(arr);
}
});
}
}
});
} }
refresh() { refresh() {

View File

@ -3,15 +3,12 @@ import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { ArtifactListTabComponent } from "./artifact-list-tab.component"; import { ArtifactListTabComponent } from "./artifact-list-tab.component";
import { of } from "rxjs"; import { of } from "rxjs";
import { delay } from "rxjs/operators"; import { delay } from "rxjs/operators";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { HttpClient, HttpHeaders, HttpResponse } from "@angular/common/http"; import { HttpClient, HttpHeaders, HttpResponse } from "@angular/common/http";
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { ArtifactDefaultService, ArtifactService } from "../../../artifact.service"; import { ArtifactDefaultService, ArtifactService } from "../../../artifact.service";
import { import {
Label, Label,
LabelDefaultService, LabelDefaultService,
LabelService,
ProjectDefaultService, ProjectDefaultService,
ProjectService, ProjectService,
ScanningResultDefaultService, ScanningResultDefaultService,
@ -31,6 +28,8 @@ import { OperationService } from "../../../../../../../shared/components/operati
import { ArtifactService as NewArtifactService } from "../../../../../../../../../ng-swagger-gen/services/artifact.service"; import { ArtifactService as NewArtifactService } from "../../../../../../../../../ng-swagger-gen/services/artifact.service";
import { Tag } from "../../../../../../../../../ng-swagger-gen/models/tag"; import { Tag } from "../../../../../../../../../ng-swagger-gen/models/tag";
import { SharedTestingModule } from "../../../../../../../shared/shared.module"; import { SharedTestingModule } from "../../../../../../../shared/shared.module";
import { LabelService } from "../../../../../../../../../ng-swagger-gen/services/label.service";
import { Registry } from "../../../../../../../../../ng-swagger-gen/models/registry";
describe("ArtifactListTabComponent (inline template)", () => { describe("ArtifactListTabComponent (inline template)", () => {
@ -297,8 +296,6 @@ describe("ArtifactListTabComponent (inline template)", () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
SharedTestingModule, SharedTestingModule,
BrowserAnimationsModule,
HttpClientTestingModule,
], ],
schemas: [ schemas: [
CUSTOM_ELEMENTS_SCHEMA CUSTOM_ELEMENTS_SCHEMA
@ -318,7 +315,6 @@ describe("ArtifactListTabComponent (inline template)", () => {
{ provide: ArtifactService, useValue: mockNewArtifactService }, { provide: ArtifactService, useValue: mockNewArtifactService },
{ provide: ProjectService, useClass: ProjectDefaultService }, { provide: ProjectService, useClass: ProjectDefaultService },
{ provide: ScanningResultService, useClass: ScanningResultDefaultService }, { provide: ScanningResultService, useClass: ScanningResultDefaultService },
{ provide: LabelService, useClass: LabelDefaultService },
{ provide: UserPermissionService, useClass: UserPermissionDefaultService }, { provide: UserPermissionService, useClass: UserPermissionDefaultService },
{ provide: ErrorHandler, useValue: mockErrorHandler }, { provide: ErrorHandler, useValue: mockErrorHandler },
{ provide: ActivatedRoute, useValue: mockActivatedRoute }, { provide: ActivatedRoute, useValue: mockActivatedRoute },
@ -350,8 +346,14 @@ describe("ArtifactListTabComponent (inline template)", () => {
mockHasDeleteImagePermission, mockHasScanImagePermission])); mockHasDeleteImagePermission, mockHasScanImagePermission]));
labelService = fixture.debugElement.injector.get(LabelService); labelService = fixture.debugElement.injector.get(LabelService);
spyLabels = spyOn(labelService, "getGLabels").and.returnValues(of(mockLabels).pipe(delay(0))); const response: HttpResponse<Array<Registry>> = new HttpResponse<Array<Registry>>({
spyLabels1 = spyOn(labelService, "getPLabels").withArgs(comp.projectId).and.returnValues(of(mockLabels1).pipe(delay(0))); headers: new HttpHeaders({'x-total-count': [].length.toString()}),
body: mockLabels
});
spyLabels = spyOn(labelService, "ListLabelsResponse").and.returnValues(
of(response).pipe(delay(0))
);
spyLabels1 = spyOn(labelService, "ListLabels").withArgs(comp.projectId).and.returnValues(of(mockLabels1).pipe(delay(0)));
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -26,7 +26,7 @@ import { ClrLoadingState, ClrDatagridStateInterface, ClrDatagridComparatorInterf
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { import {
Comparator, Label, LabelService, ScanningResultService, Comparator, ScanningResultService,
UserPermissionService, USERSTATICPERMISSION, UserPermissionService, USERSTATICPERMISSION,
} from "../../../../../../../shared/services"; } from "../../../../../../../shared/services";
import { import {
@ -69,6 +69,8 @@ import { ConfirmationDialogComponent } from "../../../../../../../shared/compone
import { ConfirmationMessage } from "../../../../../../global-confirmation-dialog/confirmation-message"; import { ConfirmationMessage } from "../../../../../../global-confirmation-dialog/confirmation-message";
import { ConfirmationAcknowledgement } from "../../../../../../global-confirmation-dialog/confirmation-state-message"; import { ConfirmationAcknowledgement } from "../../../../../../global-confirmation-dialog/confirmation-state-message";
import { UN_LOGGED_PARAM } from "../../../../../../../account/sign-in/sign-in.service"; import { UN_LOGGED_PARAM } from "../../../../../../../account/sign-in/sign-in.service";
import { Label } from "../../../../../../../../../ng-swagger-gen/models/label";
import { LabelService } from "../../../../../../../../../ng-swagger-gen/services/label.service";
export interface LabelState { export interface LabelState {
iconsShow: boolean; iconsShow: boolean;
@ -77,6 +79,7 @@ export interface LabelState {
} }
export const AVAILABLE_TIME = '0001-01-01T00:00:00.000Z'; export const AVAILABLE_TIME = '0001-01-01T00:00:00.000Z';
const YES: string = 'yes'; const YES: string = 'yes';
const PAGE_SIZE: number = 100;
@Component({ @Component({
selector: 'artifact-list-tab', selector: 'artifact-list-tab',
templateUrl: './artifact-list-tab.component.html', templateUrl: './artifact-list-tab.component.html',
@ -446,15 +449,86 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
}); });
} }
getAllLabels(): void { getAllLabels(): void {
forkJoin(this.labelService.getGLabels(), this.labelService.getPLabels(this.projectId)).subscribe(results => { // get all project labels
results.forEach(labels => { this.labelService.ListLabelsResponse({
labels.forEach(data => { pageSize: PAGE_SIZE,
page: 1,
scope: 'p',
projectId: this.projectId
}).subscribe(res => {
if (res.headers) {
const xHeader: string = res.headers.get("X-Total-Count");
const totalCount = parseInt(xHeader, 0);
let arr = res.body || [];
if (totalCount <= PAGE_SIZE) { // already gotten all project labels
if (arr && arr.length) {
arr.forEach(data => {
this.imageLabels.push({ 'iconsShow': false, 'label': data, 'show': true });
});
this.imageFilterLabels = clone(this.imageLabels);
this.imageStickLabels = clone(this.imageLabels);
}
} else { // get all the project labels in specified times
const times: number = Math.ceil(totalCount / PAGE_SIZE);
const observableList: Observable<Label[]>[] = [];
for (let i = 2; i <= times; i++) {
observableList.push(this.labelService.ListLabels({
page: i,
pageSize: PAGE_SIZE,
scope: 'p',
projectId: this.projectId
}));
}
this.handleLabelRes(observableList, arr);
}
}
});
// get all global labels
this.labelService.ListLabelsResponse({
pageSize: PAGE_SIZE,
page: 1,
scope: 'g',
}).subscribe(res => {
if (res.headers) {
const xHeader: string = res.headers.get("X-Total-Count");
const totalCount = parseInt(xHeader, 0);
let arr = res.body || [];
if (totalCount <= PAGE_SIZE) { // already gotten all global labels
if (arr && arr.length) {
arr.forEach(data => {
this.imageLabels.push({ 'iconsShow': false, 'label': data, 'show': true });
});
this.imageFilterLabels = clone(this.imageLabels);
this.imageStickLabels = clone(this.imageLabels);
}
} else { // get all the global labels in specified times
const times: number = Math.ceil(totalCount / PAGE_SIZE);
const observableList: Observable<Label[]>[] = [];
for (let i = 2; i <= times; i++) {
observableList.push(this.labelService.ListLabels({
page: i,
pageSize: PAGE_SIZE,
scope: 'g',
}));
}
this.handleLabelRes(observableList, arr);
}
}
});
}
handleLabelRes(observableList: Observable<Label[]>[], arr: Label[]) {
forkJoin(observableList).subscribe(response => {
if (response && response.length) {
response.forEach(item => {
arr = arr.concat(item);
});
arr.forEach(data => {
this.imageLabels.push({ 'iconsShow': false, 'label': data, 'show': true }); this.imageLabels.push({ 'iconsShow': false, 'label': data, 'show': true });
}); });
}); this.imageFilterLabels = clone(this.imageLabels);
this.imageFilterLabels = clone(this.imageLabels); this.imageStickLabels = clone(this.imageLabels);
this.imageStickLabels = clone(this.imageLabels); }
}, error => this.errorHandlerService.error(error)); });
} }
labelSelectedChange(artifact?: Artifact[]): void { labelSelectedChange(artifact?: Artifact[]): void {

View File

@ -19,26 +19,20 @@ import {
Input, Input,
OnInit, OnInit,
ViewChild, ViewChild,
ChangeDetectionStrategy,
ChangeDetectorRef
} from "@angular/core"; } from "@angular/core";
import { Label } from "../../../services/interface";
import { clone, compareValue } from "../../../units/utils"; import { clone, compareValue } from "../../../units/utils";
import { ErrorHandler } from "../../../units/error-handler";
import { LabelService } from "../../../services/label.service";
import { ErrorHandler } from "../../../units/error-handler/error-handler";
import { NgForm } from "@angular/forms"; import { NgForm } from "@angular/forms";
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import { debounceTime } from "rxjs/operators"; import { debounceTime } from "rxjs/operators";
import { LabelColor } from "../../../entities/shared.const"; import { LabelColor } from "../../../entities/shared.const";
import { Label } from "../../../../../../ng-swagger-gen/models/label";
import { LabelService } from "../../../../../../ng-swagger-gen/services/label.service";
@Component({ @Component({
selector: "hbr-create-edit-label", selector: "hbr-create-edit-label",
templateUrl: "./create-edit-label.component.html", templateUrl: "./create-edit-label.component.html",
styleUrls: ["./create-edit-label.component.scss"], styleUrls: ["./create-edit-label.component.scss"],
changeDetection: ChangeDetectionStrategy.Default
}) })
export class CreateEditLabelComponent implements OnInit, OnDestroy { export class CreateEditLabelComponent implements OnInit, OnDestroy {
formShow: boolean; formShow: boolean;
@ -61,12 +55,15 @@ export class CreateEditLabelComponent implements OnInit, OnDestroy {
constructor( constructor(
private labelService: LabelService, private labelService: LabelService,
private errorHandler: ErrorHandler, private errorHandler: ErrorHandler,
private ref: ChangeDetectorRef
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
this.nameChecker.pipe(debounceTime(500)).subscribe((name: string) => { this.nameChecker.pipe(debounceTime(500)).subscribe((name: string) => {
this.labelService.getLabels(this.scope, this.projectId, name) this.labelService.ListLabels({
scope: this.scope,
projectId: this.projectId,
name: name
})
.subscribe(targets => { .subscribe(targets => {
this.isLabelNameExist = false; this.isLabelNameExist = false;
if (targets && targets.length) { if (targets && targets.length) {
@ -79,8 +76,6 @@ export class CreateEditLabelComponent implements OnInit, OnDestroy {
}, error => { }, error => {
this.errorHandler.error(error); this.errorHandler.error(error);
}); });
let hnd = setInterval(() => this.ref.markForCheck(), 100);
setTimeout(() => clearInterval(hnd), 5000);
}); });
} }
@ -142,7 +137,7 @@ export class CreateEditLabelComponent implements OnInit, OnDestroy {
if (this.labelId <= 0) { if (this.labelId <= 0) {
this.labelModel.scope = this.scope; this.labelModel.scope = this.scope;
this.labelModel.project_id = this.projectId; this.labelModel.project_id = this.projectId;
this.labelService.createLabel(this.labelModel) this.labelService.CreateLabel(this.labelModel)
.subscribe(res => { .subscribe(res => {
this.inProgress = false; this.inProgress = false;
this.reload.emit(); this.reload.emit();
@ -153,7 +148,10 @@ export class CreateEditLabelComponent implements OnInit, OnDestroy {
this.errorHandler.error(err); this.errorHandler.error(err);
}); });
} else { } else {
this.labelService.updateLabel(this.labelId, this.labelModel) this.labelService.UpdateLabel({
labelId: this.labelId,
label: this.labelModel
})
.subscribe(res => { .subscribe(res => {
this.inProgress = false; this.inProgress = false;
this.reload.emit(); this.reload.emit();

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Component, Input, OnInit, OnChanges } from '@angular/core'; import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { Label } from "../../../services";
import { LabelColor } from "../../../entities/shared.const"; import { LabelColor } from "../../../entities/shared.const";
import { Label } from "../../../../../../ng-swagger-gen/models/label";
@Component({ @Component({

View File

@ -17,12 +17,12 @@
<hbr-create-edit-label [scope]="scope" [projectId]="projectId" (reload)="reload()"></hbr-create-edit-label> <hbr-create-edit-label [scope]="scope" [projectId]="projectId" (reload)="reload()"></hbr-create-edit-label>
</div> </div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<clr-datagrid [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="selectedChange()"> <clr-datagrid (clrDgRefresh)="retrieve($event)" [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow">
<clr-dg-column [clrDgField]="'name'">{{'LABEL.LABEL' | translate}}</clr-dg-column> <clr-dg-column [clrDgSortBy]="'name'">{{'LABEL.LABEL' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'description'">{{'LABEL.DESCRIPTION' | translate}}</clr-dg-column> <clr-dg-column>{{'LABEL.DESCRIPTION' | translate}}</clr-dg-column>
<clr-dg-column [clrDgSortBy]="'creation_time'">{{'LABEL.CREATION_TIME' | translate }}</clr-dg-column> <clr-dg-column [clrDgSortBy]="'creation_time'">{{'LABEL.CREATION_TIME' | translate }}</clr-dg-column>
<clr-dg-placeholder>{{'LABEL.PLACEHOLDER' | translate }}</clr-dg-placeholder> <clr-dg-placeholder>{{'LABEL.PLACEHOLDER' | translate }}</clr-dg-placeholder>
<clr-dg-row *clrDgItems="let label of targets" [clrDgItem]='label'> <clr-dg-row *ngFor="let label of targets" [clrDgItem]='label'>
<clr-dg-cell> <clr-dg-cell>
<hbr-label-piece [label]="label"></hbr-label-piece> <hbr-label-piece [label]="label"></hbr-label-piece>
</clr-dg-cell> </clr-dg-cell>
@ -30,10 +30,10 @@
<clr-dg-cell>{{label.creation_time | harborDatetime: 'short'}}</clr-dg-cell> <clr-dg-cell>{{label.creation_time | harborDatetime: 'short'}}</clr-dg-cell>
</clr-dg-row> </clr-dg-row>
<clr-dg-footer> <clr-dg-footer>
<clr-dg-pagination #pagination [clrDgPageSize]="15"> <clr-dg-pagination #pagination [clrDgPageSize]="pageSize" [(clrDgPage)]="page" [clrDgTotalItems]="total">
<clr-dg-page-size [clrPageSizeOptions]="[15,25,50]">{{"PAGINATION.PAGE_SIZE" | translate}}</clr-dg-page-size> <clr-dg-page-size [clrPageSizeOptions]="[15,25,50]">{{"PAGINATION.PAGE_SIZE" | translate}}</clr-dg-page-size>
<span *ngIf="targets?.length">{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'DESTINATION.OF' | translate}}</span> <span *ngIf="total">{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'DESTINATION.OF' | translate}}</span>
{{targets?.length}} {{'DESTINATION.ITEMS' | translate}} {{total}} {{'DESTINATION.ITEMS' | translate}}
</clr-dg-pagination> </clr-dg-pagination>
</clr-dg-footer> </clr-dg-footer>
</clr-datagrid> </clr-datagrid>

View File

@ -1,18 +1,18 @@
import { Label } from "../../services"; import { Label } from "../../services";
import { LabelComponent } from "./label.component"; import { LabelComponent } from "./label.component";
import { waitForAsync, ComponentFixture, TestBed } from "@angular/core/testing"; import { waitForAsync, ComponentFixture, TestBed } from "@angular/core/testing";
import { LabelDefaultService, LabelService } from "../../services";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { FilterComponent } from "../filter/filter.component"; import { FilterComponent } from "../filter/filter.component";
import { ConfirmationDialogComponent } from "../confirmation-dialog"; import { ConfirmationDialogComponent } from "../confirmation-dialog";
import { CreateEditLabelComponent } from "./create-edit-label/create-edit-label.component"; import { CreateEditLabelComponent } from "./create-edit-label/create-edit-label.component";
import { LabelPieceComponent } from "./label-piece/label-piece.component"; import { LabelPieceComponent } from "./label-piece/label-piece.component";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component"; import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { ErrorHandler } from "../../units/error-handler";
import { OperationService } from "../operation/operation.service"; import { OperationService } from "../operation/operation.service";
import { of } from "rxjs"; import { of } from "rxjs";
import { CURRENT_BASE_HREF } from "../../units/utils"; import { delay } from "rxjs/operators";
import { SharedTestingModule } from "../../shared.module"; import { SharedTestingModule } from "../../shared.module";
import { LabelService } from "../../../../../ng-swagger-gen/services/label.service";
import { HttpHeaders, HttpResponse } from "@angular/common/http";
import { Registry } from "../../../../../ng-swagger-gen/models/registry";
describe('LabelComponent (inline template)', () => { describe('LabelComponent (inline template)', () => {
@ -56,12 +56,10 @@ describe('LabelComponent (inline template)', () => {
let labelService: LabelService; let labelService: LabelService;
let spy: jasmine.Spy; let spy: jasmine.Spy;
let spyOneLabel: jasmine.Spy;
beforeEach(waitForAsync(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
SharedTestingModule, SharedTestingModule,
NoopAnimationsModule
], ],
declarations: [ declarations: [
FilterComponent, FilterComponent,
@ -72,8 +70,6 @@ describe('LabelComponent (inline template)', () => {
InlineAlertComponent InlineAlertComponent
], ],
providers: [ providers: [
ErrorHandler,
{provide: LabelService, useClass: LabelDefaultService},
{provide: OperationService} {provide: OperationService}
] ]
}); });
@ -84,9 +80,11 @@ describe('LabelComponent (inline template)', () => {
comp = fixture.componentInstance; comp = fixture.componentInstance;
labelService = fixture.debugElement.injector.get(LabelService); labelService = fixture.debugElement.injector.get(LabelService);
const response: HttpResponse<Array<Registry>> = new HttpResponse<Array<Registry>>({
spy = spyOn(labelService, 'getLabels').and.returnValues(of(mockData)); headers: new HttpHeaders({'x-total-count': [].length.toString()}),
spyOneLabel = spyOn(labelService, 'getLabel').and.returnValues(of(mockOneData)); body: mockData
});
spy = spyOn(labelService, 'ListLabelsResponse').and.returnValues(of(response).pipe(delay(0)));
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -17,8 +17,6 @@ import {
ViewChild, ViewChild,
Input Input
} from "@angular/core"; } from "@angular/core";
import { Label } from "../../services";
import { LabelService } from "../../services";
import { ErrorHandler } from "../../units/error-handler"; import { ErrorHandler } from "../../units/error-handler";
import { CreateEditLabelComponent } from "./create-edit-label/create-edit-label.component"; import { CreateEditLabelComponent } from "./create-edit-label/create-edit-label.component";
import { import {
@ -35,6 +33,10 @@ import { Observable, throwError as observableThrowError, forkJoin } from "rxjs";
import { errorHandler } from "../../units/shared.utils"; import { errorHandler } from "../../units/shared.utils";
import { ConfirmationMessage } from "../../../base/global-confirmation-dialog/confirmation-message"; import { ConfirmationMessage } from "../../../base/global-confirmation-dialog/confirmation-message";
import { ConfirmationAcknowledgement } from "../../../base/global-confirmation-dialog/confirmation-state-message"; import { ConfirmationAcknowledgement } from "../../../base/global-confirmation-dialog/confirmation-state-message";
import { LabelService } from "../../../../../ng-swagger-gen/services/label.service";
import { Label } from "../../../../../ng-swagger-gen/models/label";
import { DEFAULT_PAGE_SIZE, getSortingString } from "../../units/utils";
import { ClrDatagridStateInterface } from "@clr/angular";
@Component({ @Component({
selector: "hbr-label", selector: "hbr-label",
templateUrl: "./label.component.html", templateUrl: "./label.component.html",
@ -42,7 +44,7 @@ import { ConfirmationAcknowledgement } from "../../../base/global-confirmation-d
}) })
export class LabelComponent implements OnInit { export class LabelComponent implements OnInit {
timerHandler: any; timerHandler: any;
loading: boolean; loading: boolean = true;
targets: Label[]; targets: Label[];
targetName: string; targetName: string;
selectedRow: Label[] = []; selectedRow: Label[] = [];
@ -58,6 +60,9 @@ export class LabelComponent implements OnInit {
@ViewChild("confirmationDialog") @ViewChild("confirmationDialog")
confirmationDialogComponent: ConfirmationDialogComponent; confirmationDialogComponent: ConfirmationDialogComponent;
page: number = 1;
pageSize: number = DEFAULT_PAGE_SIZE;
total: number = 0;
constructor(private labelService: LabelService, constructor(private labelService: LabelService,
private errorHandlerEntity: ErrorHandler, private errorHandlerEntity: ErrorHandler,
private translateService: TranslateService, private translateService: TranslateService,
@ -65,18 +70,40 @@ export class LabelComponent implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
this.retrieve(this.scope);
} }
retrieve(scope: string, name = "") { retrieve(state?: ClrDatagridStateInterface) {
this.loading = true;
this.selectedRow = []; this.selectedRow = [];
this.targetName = ""; // this.targetName = "";
this.labelService.getLabels(scope, this.projectId, name).pipe(finalize(() => { if (state && state.page) {
this.pageSize = state.page.size;
}
let sort: string;
if (state && state.sort && state.sort.by) {
sort = getSortingString(state);
} else { // sort by creation_time desc by default
sort = `-creation_time`;
}
this.loading = true;
this.labelService.ListLabelsResponse({
page: this.page,
pageSize: this.pageSize,
name: this.targetName,
sort: sort,
scope: this.scope,
projectId: this.projectId
}).pipe(finalize(() => {
this.loading = false; this.loading = false;
})) }))
.subscribe(targets => { .subscribe(res => {
this.targets = targets || []; // Get total count
if (res.headers) {
let xHeader: string = res.headers.get("X-Total-Count");
if (xHeader) {
this.total = parseInt(xHeader, 0);
}
}
this.targets = res.body || [];
}, error => { }, error => {
this.errorHandlerEntity.error(error); this.errorHandlerEntity.error(error);
}); });
@ -87,21 +114,28 @@ export class LabelComponent implements OnInit {
} }
reload(): void { reload(): void {
this.retrieve(this.scope); this.targetName = "";
this.page = 1;
this.total = 0;
this.selectedRow = [];
this.retrieve();
} }
doSearchTargets(targetName: string) { doSearchTargets(targetName: string) {
this.retrieve(this.scope, targetName); this.targetName = targetName;
this.page = 1;
this.total = 0;
this.selectedRow = [];
this.retrieve();
} }
refreshTargets() { refreshTargets() {
this.retrieve(this.scope); this.targetName = "";
this.page = 1;
this.total = 0;
this.selectedRow = [];
this.retrieve();
} }
selectedChange(): void {
// this.forceRefreshView(5000);
}
editLabel(label: Label[]): void { editLabel(label: Label[]): void {
this.createEditLabel.editModel(label[0].id, label); this.createEditLabel.editModel(label[0].id, label);
} }
@ -134,8 +168,7 @@ export class LabelComponent implements OnInit {
observableLists.push(this.delOperate(target)); observableLists.push(this.delOperate(target));
}); });
forkJoin(...observableLists).subscribe((item) => { forkJoin(...observableLists).subscribe((item) => {
this.selectedRow = []; this.reload();
this.retrieve(this.scope);
}, error => { }, error => {
this.errorHandlerEntity.error(error); this.errorHandlerEntity.error(error);
}); });
@ -153,7 +186,7 @@ export class LabelComponent implements OnInit {
this.operationService.publishInfo(operMessage); this.operationService.publishInfo(operMessage);
return this.labelService return this.labelService
.deleteLabel(target.id) .DeleteLabel(target.id)
.pipe(map( .pipe(map(
response => { response => {
this.translateService.get('BATCH.DELETED_SUCCESS') this.translateService.get('BATCH.DELETED_SUCCESS')