mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-18 22:57:38 +01:00
Merge pull request #9833 from jwangyangls/fix-page-not-refresh
Solve the problem that the style cannot be neat because the page is not refreshed
This commit is contained in:
commit
8849b0fb9c
@ -70,7 +70,6 @@ export abstract class ProjectService {
|
|||||||
pageSize?: number
|
pageSize?: number
|
||||||
): Observable<HttpResponse<Project[]>>;
|
): Observable<HttpResponse<Project[]>>;
|
||||||
abstract createProject(name: string, metadata: any, countLimit: number, storageLimit: number): Observable<any>;
|
abstract createProject(name: string, metadata: any, countLimit: number, storageLimit: number): Observable<any>;
|
||||||
abstract toggleProjectPublic(projectId: number, isPublic: string): Observable<any>;
|
|
||||||
abstract deleteProject(projectId: number): Observable<any>;
|
abstract deleteProject(projectId: number): Observable<any>;
|
||||||
abstract checkProjectExists(projectName: string): Observable<any>;
|
abstract checkProjectExists(projectName: string): Observable<any>;
|
||||||
abstract checkProjectMember(projectId: number): Observable<any>;
|
abstract checkProjectMember(projectId: number): Observable<any>;
|
||||||
@ -162,12 +161,6 @@ export class ProjectDefaultService extends ProjectService {
|
|||||||
catchError(error => observableThrowError(error)), );
|
catchError(error => observableThrowError(error)), );
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleProjectPublic(projectId: number, isPublic: string): Observable<any> {
|
|
||||||
return this.http
|
|
||||||
.put(`/api/projects/${projectId}`, { 'metadata': {'public': isPublic} }, HTTP_JSON_OPTIONS).pipe(
|
|
||||||
catchError(error => observableThrowError(error)), );
|
|
||||||
}
|
|
||||||
|
|
||||||
public deleteProject(projectId: number): Observable<any> {
|
public deleteProject(projectId: number): Observable<any> {
|
||||||
return this.http
|
return this.http
|
||||||
.delete(`/api/projects/${projectId}`)
|
.delete(`/api/projects/${projectId}`)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<clr-datagrid (clrDgRefresh)="clrLoad($event)" [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="selectedChange()">
|
<clr-datagrid (clrDgRefresh)="clrLoad($event)" [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow">
|
||||||
<clr-dg-action-bar>
|
<clr-dg-action-bar>
|
||||||
<button type="button" class="btn btn-sm btn-secondary" (click)="addNewProject()" *ngIf="projectCreationRestriction">
|
<button type="button" class="btn btn-sm btn-secondary" (click)="addNewProject()" *ngIf="projectCreationRestriction">
|
||||||
<clr-icon shape="plus" size="16"></clr-icon> {{'PROJECT.NEW_PROJECT' | translate}}</button>
|
<clr-icon shape="plus" size="16"></clr-icon> {{'PROJECT.NEW_PROJECT' | translate}}</button>
|
||||||
@ -8,7 +8,7 @@
|
|||||||
</clr-dg-action-bar>
|
</clr-dg-action-bar>
|
||||||
<clr-dg-column [clrDgField]="'name'">{{'PROJECT.NAME' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'name'">{{'PROJECT.NAME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgSortBy]="accessLevelComparator">{{'PROJECT.ACCESS_LEVEL' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="accessLevelComparator">{{'PROJECT.ACCESS_LEVEL' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column *ngIf="showRoleInfo" [clrDgSortBy]="roleComparator">{{'PROJECT.ROLE' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="roleComparator">{{'PROJECT.ROLE' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgSortBy]="repoCountComparator">{{'PROJECT.REPO_COUNT'| translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="repoCountComparator">{{'PROJECT.REPO_COUNT'| translate}}</clr-dg-column>
|
||||||
<clr-dg-column *ngIf="withChartMuseum" [clrDgSortBy]="chartCountComparator">{{'PROJECT.CHART_COUNT'| translate}}</clr-dg-column>
|
<clr-dg-column *ngIf="withChartMuseum" [clrDgSortBy]="chartCountComparator">{{'PROJECT.CHART_COUNT'| translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgSortBy]="timeComparator">{{'PROJECT.CREATION_TIME' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="timeComparator">{{'PROJECT.CREATION_TIME' | translate}}</clr-dg-column>
|
||||||
@ -17,13 +17,13 @@
|
|||||||
<a href="javascript:void(0)" (click)="goToLink(p.project_id)">{{p.name}}</a>
|
<a href="javascript:void(0)" (click)="goToLink(p.project_id)">{{p.name}}</a>
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell>{{ (p.metadata.public === 'true' ? 'PROJECT.PUBLIC' : 'PROJECT.PRIVATE') | translate}}</clr-dg-cell>
|
<clr-dg-cell>{{ (p.metadata.public === 'true' ? 'PROJECT.PUBLIC' : 'PROJECT.PRIVATE') | translate}}</clr-dg-cell>
|
||||||
<clr-dg-cell *ngIf="showRoleInfo">{{roleInfo[p.current_user_role_id] | translate}}</clr-dg-cell>
|
<clr-dg-cell>{{ roleInfo[p.current_user_role_id]? (roleInfo[p.current_user_role_id] | translate): "-"}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{p.repo_count}}</clr-dg-cell>
|
<clr-dg-cell>{{p.repo_count}}</clr-dg-cell>
|
||||||
<clr-dg-cell *ngIf="withChartMuseum">{{p.chart_count}}</clr-dg-cell>
|
<clr-dg-cell *ngIf="withChartMuseum">{{p.chart_count}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{p.creation_time | date: 'short'}}</clr-dg-cell>
|
<clr-dg-cell>{{p.creation_time | date: 'short'}}</clr-dg-cell>
|
||||||
</clr-dg-row>
|
</clr-dg-row>
|
||||||
<clr-dg-footer>
|
<clr-dg-footer>
|
||||||
<span *ngIf="pagination.totalItems">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'PROJECT.OF' | translate}} </span> {{pagination.totalItems
|
<span *ngIf="totalCount">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'PROJECT.OF' | translate}} </span> {{pagination.totalItems
|
||||||
}} {{'PROJECT.ITEMS' | translate}}
|
}} {{'PROJECT.ITEMS' | translate}}
|
||||||
<clr-dg-pagination #pagination [clrDgPageSize]="pageSize" [(clrDgPage)]="currentPage" [clrDgTotalItems]="totalCount"></clr-dg-pagination>
|
<clr-dg-pagination #pagination [clrDgPageSize]="pageSize" [(clrDgPage)]="currentPage" [clrDgTotalItems]="totalCount"></clr-dg-pagination>
|
||||||
</clr-dg-footer>
|
</clr-dg-footer>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed, ComponentFixtureAutoDetect } from '@angular/core/testing';
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
import { ListProjectComponent } from './list-project.component';
|
import { ListProjectComponent } from './list-project.component';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectorRef } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectorRef } from '@angular/core';
|
||||||
@ -14,6 +14,7 @@ import { StatisticHandler } from "../../shared/statictics/statistic-handler.serv
|
|||||||
import { ConfirmationDialogService } from "../../shared/confirmation-dialog/confirmation-dialog.service";
|
import { ConfirmationDialogService } from "../../shared/confirmation-dialog/confirmation-dialog.service";
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { BrowserAnimationsModule, NoopAnimationsModule } from "@angular/platform-browser/animations";
|
import { BrowserAnimationsModule, NoopAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
|
import { delay } from 'rxjs/operators';
|
||||||
describe('ListProjectComponent', () => {
|
describe('ListProjectComponent', () => {
|
||||||
let component: ListProjectComponent;
|
let component: ListProjectComponent;
|
||||||
let fixture: ComponentFixture<ListProjectComponent>;
|
let fixture: ComponentFixture<ListProjectComponent>;
|
||||||
@ -21,7 +22,7 @@ describe('ListProjectComponent', () => {
|
|||||||
listProjects: () => {
|
listProjects: () => {
|
||||||
return of({
|
return of({
|
||||||
body: []
|
body: []
|
||||||
});
|
}).pipe(delay(0));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const mockSessionService = {
|
const mockSessionService = {
|
||||||
@ -85,6 +86,7 @@ describe('ListProjectComponent', () => {
|
|||||||
{ provide: StatisticHandler, useValue: mockStatisticHandler },
|
{ provide: StatisticHandler, useValue: mockStatisticHandler },
|
||||||
{ provide: ConfirmationDialogService, useValue: mockConfirmationDialogService },
|
{ provide: ConfirmationDialogService, useValue: mockConfirmationDialogService },
|
||||||
{ provide: OperationService, useValue: mockOperationService },
|
{ provide: OperationService, useValue: mockOperationService },
|
||||||
|
{ provide: ComponentFixtureAutoDetect, useValue: true }
|
||||||
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@ -16,8 +16,6 @@ import {forkJoin as observableForkJoin, Subscription, forkJoin } from "rxjs";
|
|||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
Output,
|
Output,
|
||||||
ChangeDetectionStrategy,
|
|
||||||
ChangeDetectorRef,
|
|
||||||
OnDestroy, EventEmitter
|
OnDestroy, EventEmitter
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
@ -43,8 +41,7 @@ import { throwError as observableThrowError } from "rxjs";
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "list-project",
|
selector: "list-project",
|
||||||
templateUrl: "list-project.component.html",
|
templateUrl: "list-project.component.html"
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
|
||||||
})
|
})
|
||||||
export class ListProjectComponent implements OnDestroy {
|
export class ListProjectComponent implements OnDestroy {
|
||||||
loading = true;
|
loading = true;
|
||||||
@ -53,7 +50,7 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
searchKeyword = "";
|
searchKeyword = "";
|
||||||
selectedRow: Project[] = [];
|
selectedRow: Project[] = [];
|
||||||
|
|
||||||
@Output() addProject = new EventEmitter<void>();
|
@Output() addProject = new EventEmitter<void>();
|
||||||
|
|
||||||
roleInfo = RoleInfo;
|
roleInfo = RoleInfo;
|
||||||
repoCountComparator: Comparator<Project> = new CustomComparator<Project>("repo_count", "number");
|
repoCountComparator: Comparator<Project> = new CustomComparator<Project>("repo_count", "number");
|
||||||
@ -78,8 +75,7 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private deletionDialogService: ConfirmationDialogService,
|
private deletionDialogService: ConfirmationDialogService,
|
||||||
private operationService: OperationService,
|
private operationService: OperationService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService) {
|
||||||
private ref: ChangeDetectorRef) {
|
|
||||||
this.subscription = deletionDialogService.confirmationConfirm$.subscribe(message => {
|
this.subscription = deletionDialogService.confirmationConfirm$.subscribe(message => {
|
||||||
if (message &&
|
if (message &&
|
||||||
message.state === ConfirmationState.CONFIRMED &&
|
message.state === ConfirmationState.CONFIRMED &&
|
||||||
@ -89,10 +85,6 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get showRoleInfo(): boolean {
|
|
||||||
return this.filteredType !== 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
get projectCreationRestriction(): boolean {
|
get projectCreationRestriction(): boolean {
|
||||||
let account = this.session.getCurrentUser();
|
let account = this.session.getCurrentUser();
|
||||||
if (account) {
|
if (account) {
|
||||||
@ -144,12 +136,10 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
this.router.navigate(linkUrl);
|
this.router.navigate(linkUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedChange(): void {
|
|
||||||
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
clrLoad(state: State) {
|
clrLoad(state: State) {
|
||||||
|
if (!state || !state.page) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.selectedRow = [];
|
this.selectedRow = [];
|
||||||
|
|
||||||
// Keep state for future filtering and sorting
|
// Keep state for future filtering and sorting
|
||||||
@ -166,10 +156,8 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
this.proService.listProjects(this.searchKeyword, passInFilteredType, pageNumber, this.pageSize)
|
this.proService.listProjects(this.searchKeyword, passInFilteredType, pageNumber, this.pageSize)
|
||||||
.pipe(finalize(() => {
|
.pipe(finalize(() => {
|
||||||
// Force refresh view
|
this.loading = false;
|
||||||
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
}))
|
||||||
setTimeout(() => clearInterval(hnd), 1000);
|
|
||||||
}))
|
|
||||||
.subscribe(response => {
|
.subscribe(response => {
|
||||||
// Get total count
|
// Get total count
|
||||||
if (response.headers) {
|
if (response.headers) {
|
||||||
@ -184,9 +172,7 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
this.projects = doFiltering<Project>(this.projects, state);
|
this.projects = doFiltering<Project>(this.projects, state);
|
||||||
this.projects = doSorting<Project>(this.projects, state);
|
this.projects = doSorting<Project>(this.projects, state);
|
||||||
|
|
||||||
this.loading = false;
|
|
||||||
}, error => {
|
}, error => {
|
||||||
this.loading = false;
|
|
||||||
this.msgHandler.handleError(error);
|
this.msgHandler.handleError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -197,29 +183,6 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleProject(p: Project) {
|
|
||||||
if (p) {
|
|
||||||
p.metadata.public === "true" ? p.metadata.public = "false" : p.metadata.public = "true";
|
|
||||||
this.proService
|
|
||||||
.toggleProjectPublic(p.project_id, p.metadata.public)
|
|
||||||
.subscribe(
|
|
||||||
response => {
|
|
||||||
this.msgHandler.showSuccess("PROJECT.TOGGLED_SUCCESS");
|
|
||||||
let pp: Project = this.projects.find((item: Project) => item.project_id === p.project_id);
|
|
||||||
if (pp) {
|
|
||||||
pp.metadata.public = p.metadata.public;
|
|
||||||
this.statisticHandler.refresh();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error => this.msgHandler.handleError(error)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Force refresh view
|
|
||||||
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteProjects(p: Project[]) {
|
deleteProjects(p: Project[]) {
|
||||||
let nameArr: string[] = [];
|
let nameArr: string[] = [];
|
||||||
if (p && p.length) {
|
if (p && p.length) {
|
||||||
|
@ -625,7 +625,7 @@
|
|||||||
"PULL_COMMAND": "Pull命令",
|
"PULL_COMMAND": "Pull命令",
|
||||||
"PULL_TIME": "拉取时间",
|
"PULL_TIME": "拉取时间",
|
||||||
"PUSH_TIME": "推送时间",
|
"PUSH_TIME": "推送时间",
|
||||||
"IMMUTABLE": "保留的",
|
"IMMUTABLE": "不可变的",
|
||||||
"MY_REPOSITORY": "我的仓库",
|
"MY_REPOSITORY": "我的仓库",
|
||||||
"PUBLIC_REPOSITORY": "公共仓库",
|
"PUBLIC_REPOSITORY": "公共仓库",
|
||||||
"DELETION_TITLE_REPO": "删除镜像仓库确认",
|
"DELETION_TITLE_REPO": "删除镜像仓库确认",
|
||||||
|
Loading…
Reference in New Issue
Block a user