Support searching quota by project name (#14881)

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Will Sun 2021-05-17 09:46:24 +08:00 committed by GitHub
parent 7fb1bc538c
commit ba68f16b8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 96 additions and 30 deletions

View File

@ -22,8 +22,11 @@
{{'QUOTA.EDIT' | translate}} {{'QUOTA.EDIT' | translate}}
</button> </button>
</div> </div>
<div class="clr-col-1"> <div class="clr-col">
<div class="action-head-pos"> <div class="clr-row search">
<hbr-filter [withDivider]="true"
filterPlaceholder='{{"QUOTA.FILTER_PLACEHOLDER" | translate}}'
(filterEvt)="doSearch($event)"></hbr-filter>
<span class="refresh-btn" (click)="refresh()"> <span class="refresh-btn" (click)="refresh()">
<clr-icon shape="refresh"></clr-icon> <clr-icon shape="refresh"></clr-icon>
</span> </span>

View File

@ -51,7 +51,7 @@
margin-bottom: .35rem; margin-bottom: .35rem;
} }
::ng-deep { :host::ng-deep {
.progress { .progress {
&.warning>progress { &.warning>progress {
color: orange; color: orange;
@ -77,3 +77,14 @@
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
} }
.search {
align-items: baseline;
padding-top: 0.2rem;
justify-content: flex-end;
margin-right: 2rem;
}
:host::ng-deep {
.filter-input {
width: 210px;
}
}

View File

@ -11,6 +11,7 @@ import { APP_BASE_HREF } from '@angular/common';
import { SharedTestingModule } from "../../../../shared/shared.module"; import { SharedTestingModule } from "../../../../shared/shared.module";
import { EditProjectQuotasComponent } from "./edit-project-quotas/edit-project-quotas.component"; import { EditProjectQuotasComponent } from "./edit-project-quotas/edit-project-quotas.component";
import { QuotaService } from "../../../../../../ng-swagger-gen/services/quota.service"; import { QuotaService } from "../../../../../../ng-swagger-gen/services/quota.service";
import { ProjectService } from "../../../../../../ng-swagger-gen/services/project.service";
describe('ProjectQuotasComponent', () => { describe('ProjectQuotasComponent', () => {
@ -53,6 +54,11 @@ describe('ProjectQuotasComponent', () => {
const timeout = (ms: number) => { const timeout = (ms: number) => {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
}; };
const fakedProjectService = {
listProjects() {
return of([]);
}
}
beforeEach(waitForAsync(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
@ -63,6 +69,7 @@ describe('ProjectQuotasComponent', () => {
EditProjectQuotasComponent EditProjectQuotasComponent
], ],
providers: [ providers: [
{ provide: ProjectService, useValue: fakedProjectService },
{ provide: ErrorHandler, useValue: fakedErrorHandler }, { provide: ErrorHandler, useValue: fakedErrorHandler },
{ provide: APP_BASE_HREF, useValue : '/' }, { provide: APP_BASE_HREF, useValue : '/' },
{ provide: Router, useValue: fakedRouter } { provide: Router, useValue: fakedRouter }
@ -120,4 +127,22 @@ describe('ProjectQuotasComponent', () => {
a.dispatchEvent(new Event("click")); a.dispatchEvent(new Event("click"));
expect(spyRoute.calls.count()).toEqual(1); expect(spyRoute.calls.count()).toEqual(1);
}); });
it('should refresh', async () => {
fixture.detectChanges();
await fixture.whenStable();
component.doSearch(null);
fixture.detectChanges();
await fixture.whenStable();
expect(spy.calls.count()).toEqual(2);
}); });
it('should get no quota', async () => {
fixture.detectChanges();
await fixture.whenStable();
component.doSearch('test');
fixture.detectChanges();
await fixture.whenStable();
expect(component.quotaList.length).toEqual(0);
});
});

View File

@ -1,27 +1,27 @@
import { Component, Input, Output, EventEmitter, ViewChild, SimpleChanges, OnChanges } from '@angular/core'; import { Component, Input, Output, EventEmitter, ViewChild, SimpleChanges, OnChanges } from '@angular/core';
import { Configuration } from '../../config/config'; import { Configuration } from '../../config/config';
import { import {
Quota, State, QuotaHardLimitInterface, State, QuotaHardLimitInterface,
} from '../../../../shared/services'; } from '../../../../shared/services';
import { import {
clone, isEmpty, getChanges, getSuitableUnit, calculatePage, CustomComparator clone, isEmpty, getChanges, getSuitableUnit, calculatePage
, getByte, GetIntegerAndUnit , getByte, GetIntegerAndUnit
} from '../../../../shared/units/utils'; } from '../../../../shared/units/utils';
import { ErrorHandler } from '../../../../shared/units/error-handler'; import { ErrorHandler } from '../../../../shared/units/error-handler';
import { QuotaUnits, QuotaUnlimited, QUOTA_DANGER_COEFFICIENT, QUOTA_WARNING_COEFFICIENT } from '../../../../shared/entities/shared.const'; import { QuotaUnits, QuotaUnlimited, QUOTA_DANGER_COEFFICIENT, QUOTA_WARNING_COEFFICIENT } from '../../../../shared/entities/shared.const';
import { EditProjectQuotasComponent } from './edit-project-quotas/edit-project-quotas.component'; import { EditProjectQuotasComponent } from './edit-project-quotas/edit-project-quotas.component';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { forkJoin } from 'rxjs'; import { forkJoin, of } from 'rxjs';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { finalize } from 'rxjs/operators'; import { finalize, mergeMap } from 'rxjs/operators';
import { ClrDatagridStateInterface } from '@clr/angular'; import { ClrDatagridStateInterface } from '@clr/angular';
import { ConfigurationService } from "../../../../services/config.service"; import { ConfigurationService } from "../../../../services/config.service";
import { QuotaService } from "../../../../../../ng-swagger-gen/services/quota.service"; import { QuotaService } from "../../../../../../ng-swagger-gen/services/quota.service";
import { QuotaUpdateReq } from "../../../../../../ng-swagger-gen/models/quota-update-req"; import { QuotaUpdateReq } from "../../../../../../ng-swagger-gen/models/quota-update-req";
const quotaSort = { import { ProjectService } from "../../../../../../ng-swagger-gen/services/project.service";
storage: "used.storage", import { Quota } from "../../../../../../ng-swagger-gen/models/quota";
sortType: 'string' import { FilterComponent } from "../../../../shared/components/filter/filter.component";
};
const QuotaType = 'project'; const QuotaType = 'project';
@Component({ @Component({
@ -56,13 +56,15 @@ export class ProjectQuotasComponent implements OnChanges {
this.configChange.emit(this.config); this.configChange.emit(this.config);
} }
selectedRow: Quota[] = []; selectedRow: Quota[] = [];
@ViewChild(FilterComponent)
filterComponent: FilterComponent;
constructor( constructor(
private configService: ConfigurationService, private configService: ConfigurationService,
private quotaService: QuotaService, private quotaService: QuotaService,
private translate: TranslateService, private translate: TranslateService,
private router: Router, private router: Router,
private errorHandler: ErrorHandler) { } private errorHandler: ErrorHandler,
private projectService: ProjectService) { }
editQuota() { editQuota() {
if (this.selectedRow && this.selectedRow.length === 1) { if (this.selectedRow && this.selectedRow.length === 1) {
@ -221,14 +223,31 @@ export class ProjectQuotasComponent implements OnChanges {
this.router.navigate(linkUrl); this.router.navigate(linkUrl);
} }
refresh() { refresh() {
const state: State = { if (this.filterComponent) {
page: { this.filterComponent.currentValue = null;
from: 0, }
to: 14, this.currentPage = 1;
size: 15
},
};
this.getQuotaList(state);
this.selectedRow = []; this.selectedRow = [];
this.getQuotaList(this.currentState);
}
doSearch(name: string) {
if (name) {
// should query project by name first, then query quota by referenceId(project_id)
this.projectService.listProjects({
withDetail: false,
q: encodeURIComponent(`name=${name}`)
}).pipe(mergeMap(projects => {
if (projects && projects.length) {
return this.quotaService.listQuotas({
referenceId: projects[0].project_id.toString()
});
}
return of([]);
})).subscribe(res => {
this.quotaList = res;
});
} else {
this.refresh();
}
} }
} }

View File

@ -1158,7 +1158,8 @@
"SAVE_SUCCESS": "Ändern der Begrenzung erfolgreich", "SAVE_SUCCESS": "Ändern der Begrenzung erfolgreich",
"UNLIMITED": "unlimitiert", "UNLIMITED": "unlimitiert",
"INVALID_INPUT": "ungültige Eingabe", "INVALID_INPUT": "ungültige Eingabe",
"PLACEHOLDER": "Es konnten keine Begrenzungen gefunden werden" "PLACEHOLDER": "Es konnten keine Begrenzungen gefunden werden",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "Montag", "MONDAY": "Montag",

View File

@ -1158,7 +1158,8 @@
"SAVE_SUCCESS": "Quota edit success", "SAVE_SUCCESS": "Quota edit success",
"UNLIMITED": "unlimited", "UNLIMITED": "unlimited",
"INVALID_INPUT": "invalid input", "INVALID_INPUT": "invalid input",
"PLACEHOLDER": "We couldn't find any project quotas" "PLACEHOLDER": "We couldn't find any project quotas",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "Monday", "MONDAY": "Monday",

View File

@ -1159,7 +1159,8 @@
"SAVE_SUCCESS": "Quota edit success", "SAVE_SUCCESS": "Quota edit success",
"UNLIMITED": "unlimited", "UNLIMITED": "unlimited",
"INVALID_INPUT": "invalid input", "INVALID_INPUT": "invalid input",
"PLACEHOLDER": "We couldn't find any project quotas" "PLACEHOLDER": "We couldn't find any project quotas",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "Monday", "MONDAY": "Monday",

View File

@ -1130,7 +1130,8 @@
"SAVE_SUCCESS": "Quota edit success", "SAVE_SUCCESS": "Quota edit success",
"UNLIMITED": "unlimited", "UNLIMITED": "unlimited",
"INVALID_INPUT": "invalid input", "INVALID_INPUT": "invalid input",
"PLACEHOLDER": "We couldn't find any project quotas" "PLACEHOLDER": "We couldn't find any project quotas",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "Monday", "MONDAY": "Monday",

View File

@ -1151,7 +1151,8 @@
"SAVE_SUCCESS": "Quota edit success", "SAVE_SUCCESS": "Quota edit success",
"UNLIMITED": "unlimited", "UNLIMITED": "unlimited",
"INVALID_INPUT": "invalid input", "INVALID_INPUT": "invalid input",
"PLACEHOLDER": "We couldn't find any project quotas" "PLACEHOLDER": "We couldn't find any project quotas",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "Segunda Feira", "MONDAY": "Segunda Feira",

View File

@ -1158,7 +1158,8 @@
"SAVE_SUCCESS": "Kota düzenleme başarısı", "SAVE_SUCCESS": "Kota düzenleme başarısı",
"UNLIMITED": "sınırsız", "UNLIMITED": "sınırsız",
"INVALID_INPUT": "geçersiz giriş", "INVALID_INPUT": "geçersiz giriş",
"PLACEHOLDER": "We couldn't find any project quotas" "PLACEHOLDER": "We couldn't find any project quotas",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "Pazartesi", "MONDAY": "Pazartesi",

View File

@ -1159,7 +1159,8 @@
"SAVE_SUCCESS": "项目容量修改成功", "SAVE_SUCCESS": "项目容量修改成功",
"UNLIMITED": "不设限", "UNLIMITED": "不设限",
"INVALID_INPUT": "输入错误", "INVALID_INPUT": "输入错误",
"PLACEHOLDER": "我们找不到任何可以配置定额的项目" "PLACEHOLDER": "我们找不到任何可以配置定额的项目",
"FILTER_PLACEHOLDER": "按名称查找(完全匹配)"
}, },
"WEEKLY": { "WEEKLY": {
"MONDAY": "周一", "MONDAY": "周一",

View File

@ -1148,7 +1148,8 @@
"SAVE_SUCCESS": "項目容量修改成功", "SAVE_SUCCESS": "項目容量修改成功",
"UNLIMITED": "不設限", "UNLIMITED": "不設限",
"INVALID_INPUT": "輸入錯誤", "INVALID_INPUT": "輸入錯誤",
"PLACEHOLDER": "我們找不到任何可以配置定額的項目" "PLACEHOLDER": "我們找不到任何可以配置定額的項目",
"FILTER_PLACEHOLDER": "Search by name(exact match)"
}, },
"WEEKLY":{ "WEEKLY":{
"MONDAY": "週一", "MONDAY": "週一",