mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 10:15:35 +01:00
Remove forced ng-check for registries component (#14302)
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
a4a995327b
commit
1955b57701
@ -17,7 +17,6 @@ import {
|
||||
EventEmitter,
|
||||
ViewChild,
|
||||
AfterViewChecked,
|
||||
ChangeDetectorRef,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from "@angular/core";
|
||||
@ -78,7 +77,6 @@ export class CreateEditEndpointComponent
|
||||
private endpointService: EndpointService,
|
||||
private errorHandler: ErrorHandler,
|
||||
private translateService: TranslateService,
|
||||
private ref: ChangeDetectorRef,
|
||||
private http: HttpClient,
|
||||
private appConfigService: AppConfigService,
|
||||
) {}
|
||||
@ -201,22 +199,6 @@ export class CreateEditEndpointComponent
|
||||
this.endpointId = "";
|
||||
this.inlineAlert.close();
|
||||
}
|
||||
|
||||
// Forcely refresh the view
|
||||
forceRefreshView(duration: number): void {
|
||||
// Reset timer
|
||||
if (this.timerHandler) {
|
||||
clearInterval(this.timerHandler);
|
||||
}
|
||||
this.timerHandler = setInterval(() => this.ref.markForCheck(), 100);
|
||||
setTimeout(() => {
|
||||
if (this.timerHandler) {
|
||||
clearInterval(this.timerHandler);
|
||||
this.timerHandler = null;
|
||||
}
|
||||
}, duration);
|
||||
}
|
||||
|
||||
openCreateEditTarget(editable: boolean, targetId?: number | string) {
|
||||
this.editable = editable;
|
||||
// reset
|
||||
@ -238,7 +220,6 @@ export class CreateEditEndpointComponent
|
||||
// Open the modal now
|
||||
this.open();
|
||||
this.editDisabled = true;
|
||||
this.forceRefreshView(2000);
|
||||
},
|
||||
error => this.errorHandler.error(error)
|
||||
);
|
||||
@ -308,12 +289,10 @@ export class CreateEditEndpointComponent
|
||||
this.inlineAlert.showInlineSuccess({
|
||||
message: "DESTINATION.TEST_CONNECTION_SUCCESS"
|
||||
});
|
||||
this.forceRefreshView(2000);
|
||||
this.testOngoing = false;
|
||||
},
|
||||
error => {
|
||||
this.inlineAlert.showInlineError("DESTINATION.TEST_CONNECTION_FAILURE");
|
||||
this.forceRefreshView(2000);
|
||||
this.testOngoing = false;
|
||||
}
|
||||
);
|
||||
@ -340,12 +319,10 @@ export class CreateEditEndpointComponent
|
||||
this.reload.emit(true);
|
||||
this.onGoing = false;
|
||||
this.close();
|
||||
this.forceRefreshView(2000);
|
||||
},
|
||||
error => {
|
||||
this.onGoing = false;
|
||||
this.inlineAlert.showInlineError(error);
|
||||
this.forceRefreshView(2000);
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -383,12 +360,10 @@ export class CreateEditEndpointComponent
|
||||
this.reload.emit(true);
|
||||
this.close();
|
||||
this.onGoing = false;
|
||||
this.forceRefreshView(2000);
|
||||
},
|
||||
error => {
|
||||
this.inlineAlert.showInlineError(error);
|
||||
this.onGoing = false;
|
||||
this.forceRefreshView(2000);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -12,11 +12,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<clr-datagrid [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="selectedChange()">
|
||||
<clr-datagrid [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow">
|
||||
<clr-dg-action-bar>
|
||||
<button type="button" class="btn btn-secondary" (click)="openModal()"><clr-icon shape="plus" size="16"></clr-icon> {{'DESTINATION.NEW_ENDPOINT' | translate}}</button>
|
||||
<button type="button" class="btn btn-secondary" [disabled]="!(selectedRow.length ===1)" (click)="editTargets(selectedRow)" ><clr-icon shape="pencil" size="16"></clr-icon> {{'DESTINATION.EDIT' | translate}}</button>
|
||||
<button type="button" class="btn btn-secondary" [disabled]="!selectedRow.length" (click)="deleteTargets(selectedRow)"><clr-icon shape="times" size="16"></clr-icon> {{'DESTINATION.DELETE' | translate}}</button>
|
||||
<button id="add" type="button" class="btn btn-secondary" (click)="openModal()"><clr-icon shape="plus" size="16"></clr-icon> {{'DESTINATION.NEW_ENDPOINT' | translate}}</button>
|
||||
<button id="edit" type="button" class="btn btn-secondary" [disabled]="!(selectedRow.length ===1)" (click)="editTargets(selectedRow)" ><clr-icon shape="pencil" size="16"></clr-icon> {{'DESTINATION.EDIT' | translate}}</button>
|
||||
<button id="delete" type="button" class="btn btn-secondary" [disabled]="!selectedRow.length" (click)="deleteTargets(selectedRow)"><clr-icon shape="times" size="16"></clr-icon> {{'DESTINATION.DELETE' | translate}}</button>
|
||||
</clr-dg-action-bar>
|
||||
<clr-dg-column [clrDgField]="'name'" class="flex-min-width">{{'DESTINATION.NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column [clrDgField]="'status'" class="flex-min-width">{{'DESTINATION.STATUS' | translate}}</clr-dg-column>
|
||||
|
@ -1,22 +1,17 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { DebugElement } from "@angular/core";
|
||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { EndpointComponent } from "./endpoint.component";
|
||||
import { FilterComponent } from "../../../shared/components/filter/filter.component";
|
||||
import { ConfirmationDialogComponent } from "../../../shared/components/confirmation-dialog/confirmation-dialog.component";
|
||||
import { CreateEditEndpointComponent } from "./create-edit-endpoint/create-edit-endpoint.component";
|
||||
import { InlineAlertComponent } from "../../../shared/components/inline-alert/inline-alert.component";
|
||||
import { ErrorHandler } from "../../../shared/units/error-handler";
|
||||
import { Endpoint } from "../../../shared/services";
|
||||
import { OperationService } from "../../../shared/components/operation/operation.service";
|
||||
import { click } from "../../../shared/units/utils";
|
||||
import { of } from "rxjs";
|
||||
import { HttpClientTestingModule } from "@angular/common/http/testing";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { AppConfigService } from '../../../services/app-config.service';
|
||||
import { SharedTestingModule } from "../../../shared/shared.module";
|
||||
import { EndpointDefaultService, EndpointService } from "../../../shared/services/endpoint.service";
|
||||
import { ADAPTERS_MAP, EndpointService } from "../../../shared/services/endpoint.service";
|
||||
import { delay } from "rxjs/operators";
|
||||
|
||||
describe("EndpointComponent (inline template)", () => {
|
||||
let adapterInfoMockData = {
|
||||
@ -237,7 +232,7 @@ describe("EndpointComponent (inline template)", () => {
|
||||
};
|
||||
let fakedHttp = {
|
||||
get() {
|
||||
return of(adapterInfoMockData);
|
||||
return of(adapterInfoMockData).pipe(delay(0));
|
||||
}
|
||||
};
|
||||
let mockData: Endpoint[] = [
|
||||
@ -294,21 +289,6 @@ describe("EndpointComponent (inline template)", () => {
|
||||
url: "https://4.4.4.4"
|
||||
}
|
||||
];
|
||||
let mockOne: Endpoint[] = [
|
||||
{
|
||||
id: 1,
|
||||
credential: {
|
||||
access_key: "admin",
|
||||
access_secret: "",
|
||||
type: "basic"
|
||||
},
|
||||
description: "test",
|
||||
insecure: false,
|
||||
name: "target_01",
|
||||
type: "Harbor",
|
||||
url: "https://10.117.4.151"
|
||||
}
|
||||
];
|
||||
let mockAdapters = ['harbor', 'docker hub'];
|
||||
let comp: EndpointComponent;
|
||||
let fixture: ComponentFixture<EndpointComponent>;
|
||||
@ -320,119 +300,109 @@ describe("EndpointComponent (inline template)", () => {
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let endpointService: EndpointService;
|
||||
let spy: jasmine.Spy;
|
||||
let spyAdapter: jasmine.Spy;
|
||||
let spyOnRules: jasmine.Spy;
|
||||
let spyOne: jasmine.Spy;
|
||||
const mockedEndpointService = {
|
||||
getEndpoints(targetName: string) {
|
||||
if (targetName) {
|
||||
const endpoints: Endpoint[] = [];
|
||||
mockData.forEach( item => {
|
||||
if (item.name.indexOf(targetName) !== -1) {
|
||||
endpoints.push(item);
|
||||
}
|
||||
});
|
||||
return of(endpoints).pipe(delay(0));
|
||||
}
|
||||
return of(mockData).pipe(delay(0));
|
||||
},
|
||||
getAdapters() {
|
||||
return of(mockAdapters).pipe(delay(0));
|
||||
},
|
||||
getEndpointWithReplicationRules() {
|
||||
return of([]).pipe(delay(0));
|
||||
},
|
||||
getEndpoint(endPointId: number | string) {
|
||||
if (endPointId) {
|
||||
let endpoint: Endpoint;
|
||||
mockData.forEach( item => {
|
||||
if (item.id === endPointId) {
|
||||
endpoint = item;
|
||||
}
|
||||
});
|
||||
return of(endpoint).pipe(delay(0));
|
||||
}
|
||||
return of(mockData[0]).pipe(delay(0));
|
||||
},
|
||||
getAdapterText(adapter: string): string {
|
||||
if (ADAPTERS_MAP && ADAPTERS_MAP[adapter]) {
|
||||
return ADAPTERS_MAP[adapter];
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
};
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [SharedTestingModule, NoopAnimationsModule, HttpClientTestingModule],
|
||||
imports: [SharedTestingModule],
|
||||
declarations: [
|
||||
FilterComponent,
|
||||
ConfirmationDialogComponent,
|
||||
CreateEditEndpointComponent,
|
||||
InlineAlertComponent,
|
||||
EndpointComponent
|
||||
],
|
||||
providers: [
|
||||
ErrorHandler,
|
||||
{ provide: EndpointService, useClass: EndpointDefaultService },
|
||||
{ provide: EndpointService, useValue: mockedEndpointService },
|
||||
{ provide: OperationService },
|
||||
{ provide: HttpClient, useValue: fakedHttp },
|
||||
{ provide: AppConfigService, useValue: mockAppConfigService }
|
||||
{ provide: AppConfigService, useValue: mockAppConfigService },
|
||||
],
|
||||
schemas: [
|
||||
NO_ERRORS_SCHEMA
|
||||
]
|
||||
});
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EndpointComponent);
|
||||
comp = fixture.componentInstance;
|
||||
endpointService = fixture.debugElement.injector.get(EndpointService);
|
||||
spy = spyOn(endpointService, "getEndpoints").and.returnValues(
|
||||
of(mockData)
|
||||
);
|
||||
|
||||
spyAdapter = spyOn(endpointService, "getAdapters").and.returnValue(
|
||||
of(mockAdapters)
|
||||
);
|
||||
|
||||
spyOnRules = spyOn(
|
||||
endpointService,
|
||||
"getEndpointWithReplicationRules"
|
||||
).and.returnValue(of([]));
|
||||
spyOne = spyOn(endpointService, "getEndpoint").and.returnValue(
|
||||
of(mockOne[0])
|
||||
);
|
||||
fixture.detectChanges();
|
||||
fixture.autoDetectChanges(true);
|
||||
});
|
||||
|
||||
it("should retrieve endpoint data", () => {
|
||||
fixture.detectChanges();
|
||||
expect(spy.calls.any()).toBeTruthy();
|
||||
it("should retrieve endpoint data", async () => {
|
||||
await fixture.whenStable();
|
||||
const rows = fixture.nativeElement.querySelectorAll('clr-dg-row');
|
||||
expect(rows.length).toEqual(4);
|
||||
});
|
||||
it("should open edit endpoint modal", async () => {
|
||||
await fixture.whenStable();
|
||||
const editButton: HTMLButtonElement = fixture.nativeElement.querySelector("#edit");
|
||||
comp.selectedRow = [mockData[0]] ;
|
||||
await fixture.whenStable();
|
||||
expect(editButton).toBeTruthy();
|
||||
editButton.click();
|
||||
editButton.dispatchEvent(new Event('click'));
|
||||
await fixture.whenStable();
|
||||
const nameInput: HTMLInputElement = fixture.nativeElement.querySelector("#destination_name");
|
||||
expect(nameInput.value).toEqual('target_01');
|
||||
});
|
||||
it("should open create endpoint modal", waitForAsync(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
comp.editTargets(mockOne);
|
||||
fixture.detectChanges();
|
||||
expect(comp.target.name).toEqual("target_01");
|
||||
});
|
||||
}));
|
||||
|
||||
it("should filter endpoints by keyword", waitForAsync(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
comp.doSearchTargets("target_02");
|
||||
fixture.detectChanges();
|
||||
expect(comp.targets.length).toEqual(1);
|
||||
});
|
||||
}));
|
||||
|
||||
it("should render data", waitForAsync(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let de: DebugElement = fixture.debugElement.query(
|
||||
By.css("datagrid-cell")
|
||||
);
|
||||
expect(de).toBeTruthy();
|
||||
let el: HTMLElement = de.nativeElement;
|
||||
expect(el.textContent).toEqual("target_01");
|
||||
});
|
||||
}));
|
||||
|
||||
it("should open creation endpoint", waitForAsync(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let de: DebugElement = fixture.debugElement.query(By.css("btn-link"));
|
||||
expect(de).toBeTruthy();
|
||||
fixture.detectChanges();
|
||||
click(de);
|
||||
fixture.detectChanges();
|
||||
let deInput: DebugElement = fixture.debugElement.query(By.css("input"));
|
||||
expect(deInput).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
|
||||
it("should open to edit existing endpoint", waitForAsync(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let de: DebugElement = fixture.debugElement.query(
|
||||
del => del.classes["action-item"]
|
||||
);
|
||||
expect(de).toBeTruthy();
|
||||
fixture.detectChanges();
|
||||
click(de);
|
||||
fixture.detectChanges();
|
||||
let deInput: DebugElement = fixture.debugElement.query(By.css("input"));
|
||||
expect(deInput).toBeTruthy();
|
||||
let elInput: HTMLElement = deInput.nativeElement;
|
||||
expect(elInput).toBeTruthy();
|
||||
expect(elInput.textContent).toEqual("target_01");
|
||||
});
|
||||
}));
|
||||
it("should filter endpoints by keyword", async () => {
|
||||
await fixture.whenStable();
|
||||
comp.doSearchTargets("target_02");
|
||||
await fixture.whenStable();
|
||||
const editButton: HTMLButtonElement = fixture.nativeElement.querySelector("#edit");
|
||||
comp.selectedRow = [mockData[0]] ;
|
||||
await fixture.whenStable();
|
||||
editButton.click();
|
||||
editButton.dispatchEvent(new Event('click'));
|
||||
await fixture.whenStable();
|
||||
expect(comp.targets.length).toEqual(1);
|
||||
expect(comp.targets[0].name).toEqual('target_02');
|
||||
});
|
||||
it("should open creation endpoint", async () => {
|
||||
await fixture.whenStable();
|
||||
const addButton: HTMLButtonElement = fixture.nativeElement.querySelector("#add");
|
||||
expect(addButton).toBeTruthy();
|
||||
addButton.click();
|
||||
addButton.dispatchEvent(new Event('click'));
|
||||
await fixture.whenStable();
|
||||
const nameInput: HTMLInputElement = fixture.nativeElement.querySelector("#destination_name");
|
||||
expect(nameInput).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -16,8 +16,6 @@ import {
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef
|
||||
} from "@angular/core";
|
||||
import { Subscription, Observable, forkJoin, throwError as observableThrowError } from "rxjs";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
@ -45,7 +43,6 @@ import { EndpointService, HELM_HUB } from "../../../shared/services/endpoint.ser
|
||||
selector: "hbr-endpoint",
|
||||
templateUrl: "./endpoint.component.html",
|
||||
styleUrls: ["./endpoint.component.scss"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class EndpointComponent implements OnInit, OnDestroy {
|
||||
@ViewChild(CreateEditEndpointComponent)
|
||||
@ -88,8 +85,7 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
||||
constructor(private endpointService: EndpointService,
|
||||
private errorHandlerEntity: ErrorHandler,
|
||||
private translateService: TranslateService,
|
||||
private operationService: OperationService,
|
||||
private ref: ChangeDetectorRef) {
|
||||
private operationService: OperationService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -102,17 +98,11 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
selectedChange(): void {
|
||||
this.forceRefreshView(5000);
|
||||
}
|
||||
|
||||
retrieve(): void {
|
||||
this.loading = true;
|
||||
this.selectedRow = [];
|
||||
this.endpointService.getEndpoints(this.targetName).pipe(finalize(() => {
|
||||
this.loading = false;
|
||||
this.forceRefreshView(1000);
|
||||
}))
|
||||
.subscribe(targets => {
|
||||
this.targets = targets || [];
|
||||
@ -183,7 +173,6 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
||||
.pipe(finalize(() => {
|
||||
this.selectedRow = [];
|
||||
this.reload(true);
|
||||
this.forceRefreshView(2000);
|
||||
}))
|
||||
.subscribe((item) => {
|
||||
}, error => {
|
||||
@ -219,22 +208,6 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
// Forcely refresh the view
|
||||
forceRefreshView(duration: number): void {
|
||||
// Reset timer
|
||||
if (this.timerHandler) {
|
||||
clearInterval(this.timerHandler);
|
||||
}
|
||||
this.timerHandler = setInterval(() => this.ref.markForCheck(), 100);
|
||||
setTimeout(() => {
|
||||
if (this.timerHandler) {
|
||||
clearInterval(this.timerHandler);
|
||||
this.timerHandler = null;
|
||||
}
|
||||
}, duration);
|
||||
}
|
||||
|
||||
getAdapterText(adapter: string): string {
|
||||
return this.endpointService.getAdapterText(adapter);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { RequestQueryParams } from "./index";
|
||||
import { Endpoint, ReplicationRule, PingEndpoint } from "./index";
|
||||
import { catchError, map } from "rxjs/operators";
|
||||
|
||||
const ADAPTERS_MAP = {
|
||||
export const ADAPTERS_MAP = {
|
||||
"ali-acr": "Alibaba ACR",
|
||||
"aws-ecr": "Aws ECR",
|
||||
"azure-acr": "Azure ACR",
|
||||
|
Loading…
Reference in New Issue
Block a user