diff --git a/console/src/app/app.component.html b/console/src/app/app.component.html index ced4b37c8a..dfbb789d22 100644 --- a/console/src/app/app.component.html +++ b/console/src/app/app.component.html @@ -20,17 +20,17 @@ - + - + *ngFor="let temporg of orgs$ | async" mat-menu-item (click)="setActiveOrg(temporg)"> {{temporg?.name ? temporg.name : 'NO NAME'}} diff --git a/console/src/app/app.component.ts b/console/src/app/app.component.ts index c73ae17693..06d082776d 100644 --- a/console/src/app/app.component.ts +++ b/console/src/app/app.component.ts @@ -2,13 +2,14 @@ import { BreakpointObserver } from '@angular/cdk/layout'; import { OverlayContainer } from '@angular/cdk/overlay'; import { DOCUMENT, ViewportScroller } from '@angular/common'; import { Component, ElementRef, HostBinding, Inject, OnDestroy, ViewChild } from '@angular/core'; +import { FormControl } from '@angular/forms'; import { MatIconRegistry } from '@angular/material/icon'; import { MatDrawer } from '@angular/material/sidenav'; import { DomSanitizer } from '@angular/platform-browser'; import { Router, RouterOutlet } from '@angular/router'; import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; -import { Observable, of, Subscription } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs'; +import { catchError, debounceTime, finalize, map, take } from 'rxjs/operators'; import { accountCard, navAnimations, routeAnimations, toolbarAnimation } from './animations'; import { @@ -48,17 +49,18 @@ export class AppComponent implements OnDestroy { public showAccount: boolean = false; public org!: Org.AsObject; - public orgs: Org.AsObject[] = []; + public orgs$: Observable = of([]); public profile!: UserProfileView.AsObject; public isDarkTheme: Observable = of(true); - public orgLoading: boolean = false; + public orgLoading$: BehaviorSubject = new BehaviorSubject(false); public showProjectSection: boolean = false; public grantedProjectsCount: number = 0; public ownedProjectsCount: number = 0; + public filterControl: FormControl = new FormControl(''); private authSub: Subscription = new Subscription(); private orgSub: Subscription = new Subscription(); @@ -148,7 +150,6 @@ export class AppComponent implements OnDestroy { this.orgSub = this.authService.activeOrgChanged.subscribe(org => { this.org = org; - this.getProjectCount(); }); @@ -172,6 +173,12 @@ export class AppComponent implements OnDestroy { this.translate.onLangChange.subscribe((language: LangChangeEvent) => { this.document.documentElement.lang = language.lang; }); + + this.filterControl.valueChanges.pipe(debounceTime(300)).subscribe(value => { + this.loadOrgs( + value.trim().toLowerCase(), + ); + }); } public ngOnDestroy(): void { @@ -188,14 +195,17 @@ export class AppComponent implements OnDestroy { query.setValue(filter); } - this.orgLoading = true; - this.authService.SearchMyProjectOrgs(10, 0, query ? [query] : undefined).then(res => { - this.orgs = res.toObject().resultList; - this.orgLoading = false; - }).catch(error => { - this.toast.showError(error); - this.orgLoading = false; - }); + this.orgLoading$.next(true); + this.orgs$ = from(this.authService.SearchMyProjectOrgs(10, 0, query ? [query] : undefined)).pipe( + map(resp => { + return resp.toObject().resultList; + }), + catchError(() => of([])), + finalize(() => { + this.orgLoading$.next(false); + this.focusFilter(); + }), + ); } public prepareRoute(outlet: RouterOutlet): boolean { @@ -231,7 +241,9 @@ export class AppComponent implements OnDestroy { public setActiveOrg(org: Org.AsObject): void { this.org = org; this.authService.setActiveOrg(org); - this.router.navigate(['/']); + this.authService.zitadelPermissionsChanged.pipe(take(1)).subscribe(() => { + this.router.navigate(['/']); + }); } private getProjectCount(): void { @@ -248,13 +260,6 @@ export class AppComponent implements OnDestroy { }); } - public applyFilter(event: Event): void { - const filterValue = (event.target as HTMLInputElement).value; - this.loadOrgs( - filterValue.trim().toLowerCase(), - ); - } - focusFilter(): void { setTimeout(() => { this.input.nativeElement.focus(); diff --git a/console/src/app/app.module.ts b/console/src/app/app.module.ts index bd79899e2e..e4e7f13bc8 100644 --- a/console/src/app/app.module.ts +++ b/console/src/app/app.module.ts @@ -3,6 +3,7 @@ import { CommonModule, registerLocaleData } from '@angular/common'; import { HttpClient, HttpClientModule } from '@angular/common/http'; import localeDe from '@angular/common/locales/de'; import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatNativeDateModule } from '@angular/material/core'; @@ -115,6 +116,7 @@ const authConfig: AuthConfig = { MatProgressBarModule, MatProgressSpinnerModule, MatToolbarModule, + ReactiveFormsModule, MatMenuModule, MatSnackBarModule, AvatarModule, diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.ts b/console/src/app/modules/policies/login-policy/login-policy.component.ts index 7157e1ab3e..e6353eaf19 100644 --- a/console/src/app/modules/policies/login-policy/login-policy.component.ts +++ b/console/src/app/modules/policies/login-policy/login-policy.component.ts @@ -165,6 +165,8 @@ export class LoginPolicyComponent implements OnDestroy { setTimeout(() => { this.fetchData(); }, 2000); + }).catch(error => { + this.toast.showError(error); }); } }); @@ -183,10 +185,20 @@ export class LoginPolicyComponent implements OnDestroy { public removeIdp(idp: AdminIdpProviderView.AsObject | MgmtIdpProviderView.AsObject): void { switch (this.serviceType) { case PolicyComponentServiceType.MGMT: - (this.service as ManagementService).RemoveIdpProviderFromLoginPolicy(idp.idpConfigId); + (this.service as ManagementService).RemoveIdpProviderFromLoginPolicy(idp.idpConfigId).then(() => { + const index = this.idps.findIndex(temp => temp === idp); + if (index > -1) { + this.idps.splice(index, 1); + } + }); break; case PolicyComponentServiceType.ADMIN: - (this.service as AdminService).RemoveIdpProviderFromDefaultLoginPolicy(idp.idpConfigId); + (this.service as AdminService).RemoveIdpProviderFromDefaultLoginPolicy(idp.idpConfigId).then(() => { + const index = this.idps.findIndex(temp => temp === idp); + if (index > -1) { + this.idps.splice(index, 1); + } + }); break; } } diff --git a/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.html b/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.html index 1ae2416630..cda4237607 100644 --- a/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.html +++ b/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.html @@ -4,8 +4,8 @@ {{'ORG.POLICY.DEFAULTLABEL' | translate}} - + {{'ORG.POLICY.RESET' | translate}} diff --git a/console/src/app/modules/policies/password-age-policy/password-age-policy.component.html b/console/src/app/modules/policies/password-age-policy/password-age-policy.component.html index 7bc43aaafd..b9f215bcf6 100644 --- a/console/src/app/modules/policies/password-age-policy/password-age-policy.component.html +++ b/console/src/app/modules/policies/password-age-policy/password-age-policy.component.html @@ -1,8 +1,8 @@ - + {{'ORG.POLICY.RESET' | translate}} diff --git a/console/src/app/modules/policies/password-age-policy/password-age-policy.component.ts b/console/src/app/modules/policies/password-age-policy/password-age-policy.component.ts index 6b6ee7fdad..9fcf4f611a 100644 --- a/console/src/app/modules/policies/password-age-policy/password-age-policy.component.ts +++ b/console/src/app/modules/policies/password-age-policy/password-age-policy.component.ts @@ -112,7 +112,6 @@ export class PasswordAgePolicyComponent implements OnDestroy { this.ageData.expireWarnDays, ).then(() => { this.toast.showInfo('ORG.POLICY.TOAST.SET', true); - this.getData(); }).catch(error => { this.toast.showError(error); }); @@ -122,7 +121,6 @@ export class PasswordAgePolicyComponent implements OnDestroy { this.ageData.expireWarnDays, ).then(() => { this.toast.showInfo('ORG.POLICY.TOAST.SET', true); - this.getData(); }).catch(error => { this.toast.showError(error); }); @@ -134,12 +132,18 @@ export class PasswordAgePolicyComponent implements OnDestroy { this.ageData.expireWarnDays, ).then(() => { this.toast.showInfo('ORG.POLICY.TOAST.SET', true); - this.getData(); }).catch(error => { this.toast.showError(error); }); break; } + } + public get isDefault(): boolean { + if (this.ageData && this.serviceType === PolicyComponentServiceType.MGMT) { + return (this.ageData as PasswordAgePolicyView.AsObject).pb_default; + } else { + return false; + } } } diff --git a/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.html b/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.html index 1c93f82c8d..8ac36fa793 100644 --- a/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.html +++ b/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.html @@ -4,8 +4,8 @@ {{'ORG.POLICY.DEFAULTLABEL' | translate}} - + {{'ORG.POLICY.RESET' | translate}} diff --git a/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.ts b/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.ts index aaef63cef7..0ed3b0985d 100644 --- a/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.ts +++ b/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.ts @@ -45,11 +45,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy { return this.route.params; })).subscribe(() => { - this.getData().then(data => { - if (data) { - this.lockoutData = data.toObject() as PasswordLockoutPolicyView.AsObject; - } - }); + this.fetchData(); }); } @@ -57,6 +53,14 @@ export class PasswordLockoutPolicyComponent implements OnDestroy { this.sub.unsubscribe(); } + private fetchData(): void { + this.getData().then(data => { + if (data) { + this.lockoutData = data.toObject() as PasswordLockoutPolicyView.AsObject; + } + }); + } + private getData(): Promise { switch (this.serviceType) { case PolicyComponentServiceType.MGMT: @@ -70,9 +74,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy { if (this.service instanceof ManagementService) { this.service.RemovePasswordLockoutPolicy().then(() => { this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true); - setTimeout(() => { - this.getData(); - }, 1000); + this.fetchData(); }).catch(error => { this.toast.showError(error); }); @@ -99,7 +101,6 @@ export class PasswordLockoutPolicyComponent implements OnDestroy { this.lockoutData.showLockoutFailure, ).then(() => { this.toast.showInfo('ORG.POLICY.TOAST.SET', true); - this.getData(); }).catch(error => { this.toast.showError(error); }); @@ -110,7 +111,6 @@ export class PasswordLockoutPolicyComponent implements OnDestroy { this.lockoutData.showLockoutFailure, ).then(() => { this.toast.showInfo('ORG.POLICY.TOAST.SET', true); - this.getData(); }).catch(error => { this.toast.showError(error); }); @@ -120,7 +120,6 @@ export class PasswordLockoutPolicyComponent implements OnDestroy { this.lockoutData.showLockoutFailure, ).then(() => { this.toast.showInfo('ORG.POLICY.TOAST.SET', true); - this.getData(); }).catch(error => { this.toast.showError(error); });
{{'ORG.POLICY.DEFAULTLABEL' | translate}}