Browse Source

Merge pull request #25578 from abpframework/issue/loading-sm-problem

Angular - Fixing the loading state management problem for manage profile
pull/25632/head
oykuermann 4 months ago
committed by GitHub
parent
commit
ca744ded76
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 88
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html
  2. 28
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
  3. 39
      npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts

88
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html

@ -1,51 +1,65 @@
<div id="AbpContentToolbar"></div>
<div class="card border-0 shadow-sm min-h-400" [abpLoading]="!(profile$ | async)?.userName">
<div class="card border-0 shadow-sm min-h-400" [abpLoading]="profileLoading()">
<div class="card-body">
<div class="row">
<div class="col-12 col-md-3">
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist">
@if (!hideChangePasswordTab && (profile$ | async)) {
<li class="nav-item" (click)="selectedTab = 0">
<a class="nav-link" [class.active]="selectedTab === 0" role="tab" href="javascript:void(0)">{{
'AbpUi::ChangePassword' | abpLocalization }}</a>
</li>
@if (!hideChangePasswordTab && profile()) {
<li class="nav-item" (click)="selectedTab = 0">
<a
class="nav-link"
[class.active]="selectedTab === 0"
role="tab"
href="javascript:void(0)"
>{{ 'AbpUi::ChangePassword' | abpLocalization }}</a
>
</li>
}
<li class="nav-item mb-2" (click)="selectedTab = 1">
<a class="nav-link" [class.active]="selectedTab === 1" role="tab" href="javascript:void(0)">{{
'AbpAccount::PersonalSettings' | abpLocalization }}</a>
<a
class="nav-link"
[class.active]="selectedTab === 1"
role="tab"
href="javascript:void(0)"
>{{ 'AbpAccount::PersonalSettings' | abpLocalization }}</a
>
</li>
</ul>
</div>
@if (profile$ | async) {
<div class="col-12 col-md-9">
@if (selectedTab === 0) {
<div class="tab-content fade-in">
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::ChangePassword' | abpLocalization }}
<hr />
</h4>
<abp-change-password-form *abpReplaceableTemplate="{
componentKey: changePasswordKey
}"></abp-change-password-form>
</div>
</div>
}
@if (selectedTab === 1) {
<div class="tab-content fade-in">
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::PersonalSettings' | abpLocalization }}
<hr />
</h4>
<abp-personal-settings-form *abpReplaceableTemplate="{
componentKey: personalSettingsKey
}"></abp-personal-settings-form>
</div>
@if (profile()) {
<div class="col-12 col-md-9">
@if (selectedTab === 0) {
<div class="tab-content fade-in">
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::ChangePassword' | abpLocalization }}
<hr />
</h4>
<abp-change-password-form
*abpReplaceableTemplate="{
componentKey: changePasswordKey,
}"
></abp-change-password-form>
</div>
</div>
}
@if (selectedTab === 1) {
<div class="tab-content fade-in">
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::PersonalSettings' | abpLocalization }}
<hr />
</h4>
<abp-personal-settings-form
*abpReplaceableTemplate="{
componentKey: personalSettingsKey,
}"
></abp-personal-settings-form>
</div>
</div>
}
</div>
}
</div>
}
</div>
</div>
</div>
</div>

28
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts

@ -1,9 +1,10 @@
import { ProfileService } from '@abp/ng.account.core/proxy';
import { LoadingDirective } from '@abp/ng.theme.shared';
import { Component, inject, OnInit } from '@angular/core';
import { Component, inject, OnInit, signal } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { finalize } from 'rxjs/operators';
import { eAccountComponents } from '../../enums/components';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
import { AsyncPipe } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { LocalizationPipe, ReplaceableTemplateDirective } from '@abp/ng.core';
import { PersonalSettingsComponent } from '../personal-settings/personal-settings.component';
@ -33,7 +34,6 @@ import { ChangePasswordComponent } from '../change-password/change-password.comp
`,
],
imports: [
AsyncPipe,
ReactiveFormsModule,
PersonalSettingsComponent,
ChangePasswordComponent,
@ -52,17 +52,23 @@ export class ManageProfileComponent implements OnInit {
personalSettingsKey = eAccountComponents.PersonalSettings;
profile$ = this.manageProfileState.getProfile$();
profile = toSignal(this.manageProfileState.getProfile$());
profileLoading = signal(false);
hideChangePasswordTab?: boolean;
ngOnInit() {
this.profileService.get().subscribe(profile => {
this.manageProfileState.setProfile(profile);
if (profile.isExternal) {
this.hideChangePasswordTab = true;
this.selectedTab = 1;
}
});
this.profileLoading.set(true);
this.profileService
.get()
.pipe(finalize(() => this.profileLoading.set(false)))
.subscribe(profile => {
this.manageProfileState.setProfile(profile);
if (profile.isExternal) {
this.hideChangePasswordTab = true;
this.selectedTab = 1;
}
});
}
}

39
npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts

@ -47,32 +47,31 @@ export class LoadingDirective implements OnInit, OnDestroy {
private handleLoadingChange(newValue: boolean) {
setTimeout(() => {
if (!newValue && this.timerSubscription) {
this.timerSubscription.unsubscribe();
this.timerSubscription = null;
if (this.rootNode) {
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode);
this.rootNode = null;
}
if (!newValue) {
this.clearLoading();
return;
}
if (this.timerSubscription) {
this.timerSubscription.unsubscribe();
}
this.timerSubscription = timer(this.delay())
.pipe(take(1))
.subscribe(() => {
if (!this.loading()) {
return;
}
if (!this.componentRef) {
this.componentRef = this.viewContainerRef.createComponent(LoadingComponent, {
injector: this.injector
});
}
if (newValue && !this.rootNode) {
if (!this.rootNode) {
this.rootNode = (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0];
this.targetElement?.appendChild(this.rootNode as HTMLDivElement);
} else if (this.rootNode) {
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode);
this.rootNode = null;
}
this.timerSubscription = null;
@ -80,6 +79,18 @@ export class LoadingDirective implements OnInit, OnDestroy {
}, 0);
}
private clearLoading() {
if (this.timerSubscription) {
this.timerSubscription.unsubscribe();
this.timerSubscription = null;
}
if (this.rootNode?.parentElement) {
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode);
this.rootNode = null;
}
}
ngOnInit() {
this.targetElement = this.targetElementInput();
if (!this.targetElement) {
@ -93,8 +104,6 @@ export class LoadingDirective implements OnInit, OnDestroy {
}
ngOnDestroy() {
if (this.timerSubscription) {
this.timerSubscription.unsubscribe();
}
this.clearLoading();
}
}

Loading…
Cancel
Save