fix(console): reduce initial load time (#8273)

This reduces the initial payload of the `listMyProjectOrgs` to get the
active org by setting the limit of the initial orgs to 100.

Partial of #8272

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Max Peintner 2024-07-22 16:18:26 +02:00 committed by GitHub
parent 0e99c8356a
commit 215dbf0cf6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 61 additions and 45 deletions

View File

@ -26,6 +26,8 @@ export enum UserTarget {
EXTERNAL = 'external',
}
const USER_LIMIT = 25;
@Component({
selector: 'cnsl-search-user-autocomplete',
templateUrl: './search-user-autocomplete.component.html',
@ -67,9 +69,9 @@ export class SearchUserAutocompleteComponent implements OnInit, AfterContentChec
// feat-3916 show users as soon as I am in the input field of the user
const query = new SearchQuery();
const lnQuery = new LoginNameQuery();
lnQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE);
lnQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_STARTS_WITH_IGNORE_CASE);
query.setLoginNameQuery(lnQuery);
this.userService.listUsers(10, 0, [query]).then((users) => {
this.userService.listUsers(USER_LIMIT, 0, [query]).then((users) => {
this.filteredUsers = users.resultList;
});
@ -97,7 +99,7 @@ export class SearchUserAutocompleteComponent implements OnInit, AfterContentChec
query.setLoginNameQuery(lnQuery);
if (this.target === UserTarget.SELF) {
return from(this.userService.listUsers(10, 0, [query]));
return from(this.userService.listUsers(USER_LIMIT, 0, [query]));
} else {
return of();
}

View File

@ -18,7 +18,7 @@ import { PageEvent, PaginatorComponent } from '../paginator/paginator.component'
import { UserGrantRoleDialogComponent } from '../user-grant-role-dialog/user-grant-role-dialog.component';
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
import { UserGrantContext, UserGrantsDataSource } from './user-grants-datasource';
import { Org, OrgState } from 'src/app/proto/generated/zitadel/org_pb';
import { Org, OrgIDQuery, OrgQuery, OrgState } from 'src/app/proto/generated/zitadel/org_pb';
export enum UserGrantListSearchKey {
DISPLAY_NAME,
@ -306,17 +306,15 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
}
}
public showUser(grant: UserGrant.AsObject) {
const org: Org.AsObject = {
id: grant.grantedOrgId,
name: grant.grantedOrgName,
state: OrgState.ORG_STATE_ACTIVE,
primaryDomain: grant.grantedOrgDomain,
};
public async showUser(grant: UserGrant.AsObject) {
const orgQuery = new OrgQuery();
const orgIdQuery = new OrgIDQuery();
orgIdQuery.setId(grant.grantedOrgId);
orgQuery.setIdQuery(orgIdQuery);
// Check if user has permissions for that org before changing active org
if (this.myOrgs.find((org) => org.id === grant.grantedOrgId)) {
this.authService.setActiveOrg(org);
const orgs = (await this.authService.listMyProjectOrgs(1, 0, [orgQuery])).resultList;
if (orgs.length === 1) {
this.authService.setActiveOrg(orgs[0]);
this.router.navigate(['/users', grant.userId]);
} else {
this.toast.showInfo('GRANTS.TOAST.CANTSHOWINFO', true);

View File

@ -4,7 +4,7 @@
<cnsl-refresh-table
[loading]="dataSource.loading$ | async"
*ngIf="projectId"
(refreshed)="loadGrantsPage()"
(refreshed)="refreshPage()"
[dataSize]="dataSource.totalResult"
[selection]="selection"
[timestamp]="dataSource.viewTimestamp"
@ -154,11 +154,11 @@
<cnsl-paginator
class="paginator"
#paginator
[pageSize]="50"
[pageSize]="INITIAL_PAGESIZE"
[timestamp]="dataSource.viewTimestamp"
[pageSizeOptions]="[25, 50, 100, 250]"
[length]="dataSource.totalResult"
(page)="loadGrantsPage($event.pageIndex, $event.pageSize)"
(page)="loadGrantsPage($event)"
>
</cnsl-paginator>
</cnsl-refresh-table>

View File

@ -6,7 +6,7 @@ import { MatSelectChange } from '@angular/material/select';
import { MatTable } from '@angular/material/table';
import { Router } from '@angular/router';
import { tap } from 'rxjs/operators';
import { PaginatorComponent } from 'src/app/modules/paginator/paginator.component';
import { PageEvent, PaginatorComponent } from 'src/app/modules/paginator/paginator.component';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import { GrantedProject, ProjectGrantState, Role } from 'src/app/proto/generated/zitadel/project_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
@ -14,8 +14,6 @@ import { ToastService } from 'src/app/services/toast.service';
import { ProjectGrantsDataSource } from './project-grants-datasource';
const ROUTEPARAM = 'projectid';
@Component({
selector: 'cnsl-project-grants',
templateUrl: './project-grants.component.html',
@ -28,7 +26,9 @@ const ROUTEPARAM = 'projectid';
]),
],
})
export class ProjectGrantsComponent implements OnInit, AfterViewInit {
export class ProjectGrantsComponent implements OnInit {
public INITIAL_PAGESIZE: number = 10;
@Input() public projectId: string = '';
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
@ViewChild(MatTable) public table!: MatTable<GrantedProject.AsObject>;
@ -51,16 +51,12 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
}
public ngOnInit(): void {
this.dataSource.loadGrants(this.projectId, 0, 25, 'asc');
this.dataSource.loadGrants(this.projectId, 0, this.INITIAL_PAGESIZE);
this.getRoleOptions(this.projectId);
}
public ngAfterViewInit(): void {
this.paginator.page.pipe(tap(() => this.loadGrantsPage())).subscribe();
}
public loadGrantsPage(pageIndex?: number, pageSize?: number): void {
this.dataSource.loadGrants(this.projectId, pageIndex ?? this.paginator.pageIndex, pageSize ?? this.paginator.pageSize);
public loadGrantsPage(event: PageEvent): void {
this.dataSource.loadGrants(this.projectId, event.pageIndex, event.pageSize);
}
public isAllSelected(): boolean {
@ -92,6 +88,11 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
});
}
public refreshPage(): void {
this.selection.clear();
this.dataSource.loadGrants(this.projectId, this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
}
public deleteGrant(grant: GrantedProject.AsObject): void {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {

View File

@ -97,12 +97,14 @@ import {
import { ChangeQuery } from '../proto/generated/zitadel/change_pb';
import { MetadataQuery } from '../proto/generated/zitadel/metadata_pb';
import { ListQuery } from '../proto/generated/zitadel/object_pb';
import { Org, OrgFieldName, OrgQuery } from '../proto/generated/zitadel/org_pb';
import { Org, OrgFieldName, OrgIDQuery, OrgQuery } from '../proto/generated/zitadel/org_pb';
import { LabelPolicy, PrivacyPolicy } from '../proto/generated/zitadel/policy_pb';
import { Gender, MembershipQuery, User, WebAuthNVerification } from '../proto/generated/zitadel/user_pb';
import { GrpcService } from './grpc.service';
import { StorageKey, StorageLocation, StorageService } from './storage.service';
const ORG_LIMIT = 10;
@Injectable({
providedIn: 'root',
})
@ -249,36 +251,49 @@ export class GrpcAuthService {
this.setActiveOrg(find);
return Promise.resolve(find);
} else {
const orgs = (await this.listMyProjectOrgs(10, 0)).resultList;
this.cachedOrgs.next(orgs);
const toFind = orgs.find((tmp) => tmp.id === id);
if (toFind) {
this.setActiveOrg(toFind);
return Promise.resolve(toFind);
const orgQuery = new OrgQuery();
const orgIdQuery = new OrgIDQuery();
orgIdQuery.setId(id);
orgQuery.setIdQuery(orgIdQuery);
const orgs = (await this.listMyProjectOrgs(ORG_LIMIT, 0, [orgQuery])).resultList;
if (orgs.length === 1) {
this.setActiveOrg(orgs[0]);
return Promise.resolve(orgs[0]);
} else {
return Promise.reject(new Error('requested organization not found'));
}
}
} else {
let orgs = this.cachedOrgs.getValue();
if (orgs.length === 0) {
orgs = (await this.listMyProjectOrgs()).resultList;
this.cachedOrgs.next(orgs);
}
const org = this.storage.getItem<Org.AsObject>(StorageKey.organization, StorageLocation.local);
if (org && orgs.find((tmp) => tmp.id === org.id)) {
this.storage.setItem(StorageKey.organization, org, StorageLocation.session);
this.setActiveOrg(org);
return Promise.resolve(org);
if (org) {
const orgQuery = new OrgQuery();
const orgIdQuery = new OrgIDQuery();
orgIdQuery.setId(org.id);
orgQuery.setIdQuery(orgIdQuery);
const specificOrg = (await this.listMyProjectOrgs(ORG_LIMIT, 0, [orgQuery])).resultList;
if (specificOrg.length === 1) {
this.setActiveOrg(specificOrg[0]);
return Promise.resolve(specificOrg[0]);
} else {
orgs = (await this.listMyProjectOrgs(ORG_LIMIT, 0)).resultList;
this.cachedOrgs.next(orgs);
}
} else {
orgs = (await this.listMyProjectOrgs(ORG_LIMIT, 0)).resultList;
this.cachedOrgs.next(orgs);
}
if (orgs.length === 0) {
this._activeOrgChanged.next(undefined);
return Promise.reject(new Error('No organizations found!'));
}
const orgToSet = orgs.find((element) => element.id !== '0' && element.name !== '');
const orgToSet = orgs.find((element) => element.id !== '0' && element.name !== '');
if (orgToSet) {
this.setActiveOrg(orgToSet);
return Promise.resolve(orgToSet);
@ -396,7 +411,7 @@ export class GrpcAuthService {
}
public async revalidateOrgs() {
const orgs = (await this.listMyProjectOrgs()).resultList;
const orgs = (await this.listMyProjectOrgs(ORG_LIMIT, 0)).resultList;
this.cachedOrgs.next(orgs);
}