mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-29 21:54:13 +01:00
Add pagination support to label list (#14714)
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
705cb5b55d
commit
0c724d3a44
@ -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 },
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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({
|
||||||
|
@ -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>
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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')
|
||||||
|
Loading…
Reference in New Issue
Block a user