Skip to content

Commit

Permalink
so tired
Browse files Browse the repository at this point in the history
  • Loading branch information
ntqdinh-axonivy committed Dec 11, 2024
1 parent e71683f commit 73fc859
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 44 deletions.
13 changes: 1 addition & 12 deletions marketplace-ui/src/app/core/interceptors/api.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import {
HttpInterceptorFn
} from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { LoadingService } from '../services/loading/loading.service';
import { inject } from '@angular/core';
import { catchError, EMPTY, finalize } from 'rxjs';
import { catchError, EMPTY } from 'rxjs';
import { Router } from '@angular/router';
import { ERROR_CODES, ERROR_PAGE_PATH } from '../../shared/constants/common.constant';

Expand All @@ -25,7 +24,6 @@ export const ForwardingError = new HttpContextToken<boolean>(() => false);

export const apiInterceptor: HttpInterceptorFn = (req, next) => {
const router = inject(Router);
const loadingService = inject(LoadingService);

if (req.url.includes('i18n')) {
return next(req);
Expand All @@ -41,10 +39,6 @@ export const apiInterceptor: HttpInterceptorFn = (req, next) => {
headers: addIvyHeaders(req.headers)
});

if (!req.context.get(SkipLoading)) {
loadingService.show();
}

if (req.context.get(ForwardingError)) {
return next(cloneReq);
}
Expand All @@ -57,11 +51,6 @@ export const apiInterceptor: HttpInterceptorFn = (req, next) => {
router.navigate([ERROR_PAGE_PATH]);
}
return EMPTY;
}),
finalize(() => {
if (!req.context.get(SkipLoading)) {
loadingService.hide();
}
})
);
};
Expand Down
32 changes: 25 additions & 7 deletions marketplace-ui/src/app/core/services/loading/loading.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
import { computed, Injectable, signal } from '@angular/core';
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class LoadingService {
private readonly isShow = signal(false);
isLoading = computed(() => this.isShow());
private readonly loadingSubject = new BehaviorSubject<{
[key: string]: boolean;
}>({});
loading$ = this.loadingSubject.asObservable;

show() {
this.isShow.set(true);
private setLoading(componentIds: string[], isLoading: boolean): void {
const currentState = this.loadingSubject.value;

// Update the loading state for each component ID
componentIds.forEach(id => {
currentState[id] = isLoading;
});

this.loadingSubject.next({ ...currentState });
}

showLoading(...componentIds: string[]): void {
this.setLoading(componentIds, true);
}

hideLoading(...componentIds: string[]) {
this.setLoading(componentIds, false);
}

hide() {
this.isShow.set(false);
isLoading(compnentId: string): boolean {
return this.loadingSubject.value[compnentId] || false;
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import { CommonModule } from '@angular/common';
import { Component, inject, Input, OnChanges, SimpleChange, SimpleChanges } from '@angular/core';
import {
Component,
inject,
Input,
OnChanges,
SimpleChange,
SimpleChanges
} from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ProductDetail } from '../../../../shared/models/product-detail.model';
import { LanguageService } from '../../../../core/services/language/language.service';
import { ProductDetailService } from '../product-detail.service';
import { VERSION } from '../../../../shared/constants/common.constant';
import { LoadingService } from '../../../../core/services/loading/loading.service';
import { ThemeService } from '../../../../core/services/theme/theme.service';
import { finalize } from 'rxjs';
import { MissingProductInformationContentPipe } from '../../../../shared/pipes/missing-product-Information-content-pipe';
import { LoadingComponentId } from '../../../../shared/enums/loading-component-id';

const SELECTED_VERSION = 'selectedVersion';
const PRODUCT_DETAIL = 'productDetail';
@Component({
selector: 'app-product-detail-information-tab',
standalone: true,
imports: [CommonModule, TranslateModule, MissingProductInformationContentPipe],
imports: [
CommonModule,
TranslateModule,
MissingProductInformationContentPipe
],
templateUrl: './product-detail-information-tab.component.html',
styleUrl: './product-detail-information-tab.component.scss'
})
Expand All @@ -23,6 +36,7 @@ export class ProductDetailInformationTabComponent implements OnChanges {
productDetail!: ProductDetail;
@Input()
selectedVersion!: string;
protected LoadingComponentId = LoadingComponentId;
externalDocumentLink = '';
displayVersion = '';
displayExternalDocName: string | null = '';
Expand All @@ -34,7 +48,11 @@ export class ProductDetailInformationTabComponent implements OnChanges {
ngOnChanges(changes: SimpleChanges): void {
let version = '';
const changedSelectedVersion = changes[SELECTED_VERSION];
if (changedSelectedVersion && changedSelectedVersion.currentValue === changedSelectedVersion.previousValue) {
if (
changedSelectedVersion &&
changedSelectedVersion.currentValue ===
changedSelectedVersion.previousValue
) {
return;
}
const changedProduct = changes[PRODUCT_DETAIL];
Expand All @@ -48,7 +66,18 @@ export class ProductDetailInformationTabComponent implements OnChanges {
return;
}

this.productDetailService.getExternalDocumentForProductByVersion(this.productDetail.id, this.extractVersionValue(version))
this.productDetailService
.getExternalDocumentForProductByVersion(
this.productDetail.id,
this.extractVersionValue(version)
)
.pipe(
finalize(() => {
this.loadingService.hideLoading(
LoadingComponentId.DETAIL_INFORMATION_TAB
);
})
)
.subscribe({
next: response => {
if (response) {
Expand All @@ -57,11 +86,9 @@ export class ProductDetailInformationTabComponent implements OnChanges {
} else {
this.resetValues();
}
this.loadingService.hide();
},
error: () => {
this.resetValues();
this.loadingService.hide();
}
});
this.displayVersion = this.extractVersionValue(this.selectedVersion);
Expand All @@ -79,9 +106,10 @@ export class ProductDetailInformationTabComponent implements OnChanges {
// To ensure the function always returns a boolean, you can explicitly coerce the result into a boolean using the !! operator or default it to false
// Adding !! in case of changedProduct is undefined, it will return false instead of returning undefined
isProductChanged(changedProduct: SimpleChange) {
return !!(changedProduct?.previousValue &&
return !!(
changedProduct?.previousValue &&
Object.keys(changedProduct.previousValue).length > 0 &&
changedProduct.currentValue !== changedProduct.previousValue);
changedProduct.currentValue !== changedProduct.previousValue
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Observable } from 'rxjs';
import { API_URI } from '../../../shared/constants/api.constant';
import { ForwardingError } from '../../../core/interceptors/api.interceptor';
import { ExternalDocument } from '../../../shared/models/external-document.model';
import { LoadingComponentId } from '../../../shared/enums/loading-component-id';

@Injectable({
providedIn: 'root'
Expand All @@ -20,6 +21,7 @@ export class ProductDetailService {
noFeedbackLabel: WritableSignal<string> = signal('');

getExternalDocumentForProductByVersion(productId: string, version: string): Observable<ExternalDocument> {
this.loadingService.showLoading(LoadingComponentId.DETAIL_INFORMATION_TAB);
return this.httpClient.get<ExternalDocument>(
`${API_URI.EXTERNAL_DOCUMENT}/${productId}/${version}`, { context: new HttpContext().set(ForwardingError, true)}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ <h4 [lang]="languageService.selectedLanguage()" class="text-secondary">
</div>
</div>
}

@if (loadingService.isLoading()) {
<app-loading-spinner />
}

<app-loading-spinner [key]="LoadingComponentId.LANDING_PAGE"/>
<div #observer class="observer"></div>
</div>
2 changes: 2 additions & 0 deletions marketplace-ui/src/app/modules/product/product.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
import { ItemDropdown } from '../../shared/models/item-dropdown.model';
import { LoadingSpinnerComponent } from '../../shared/components/loading-spinner/loading-spinner.component';
import { LoadingService } from '../../core/services/loading/loading.service';
import { LoadingComponentId } from '../../shared/enums/loading-component-id';

const SEARCH_DEBOUNCE_TIME = 500;

Expand All @@ -55,6 +56,7 @@ const SEARCH_DEBOUNCE_TIME = 500;
styleUrl: './product.component.scss'
})
export class ProductComponent implements AfterViewInit, OnDestroy {
protected LoadingComponentId = LoadingComponentId;
products: WritableSignal<Product[]> = signal([]);
productDetail!: ProductDetail;
subscriptions: Subscription[] = [];
Expand Down
8 changes: 6 additions & 2 deletions marketplace-ui/src/app/modules/product/product.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HttpClient, HttpContext, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { delay, Observable } from 'rxjs';
import { delay, finalize, Observable } from 'rxjs';
import { LoadingService } from '../../core/services/loading/loading.service';
import { RequestParam } from '../../shared/enums/request-param';
import { ProductApiResponse } from '../../shared/models/apis/product-response.model';
Expand All @@ -10,13 +10,15 @@ import { VersionData } from '../../shared/models/vesion-artifact.model';
import { SkipLoading } from '../../core/interceptors/api.interceptor';
import { VersionAndUrl } from '../../shared/models/version-and-url';
import { API_URI } from '../../shared/constants/api.constant';
import { LoadingComponentId } from '../../shared/enums/loading-component-id';

@Injectable()
export class ProductService {
httpClient = inject(HttpClient);
loadingService = inject(LoadingService);

findProductsByCriteria(criteria: Criteria): Observable<ProductApiResponse> {
this.loadingService.showLoading(LoadingComponentId.LANDING_PAGE);
let requestParams = new HttpParams();
let requestURL = API_URI.PRODUCT;
if (criteria.nextPageHref) {
Expand All @@ -36,7 +38,9 @@ export class ProductService {
}
return this.httpClient.get<ProductApiResponse>(requestURL, {
params: requestParams
});
}).pipe(finalize(()=> {
this.loadingService.hideLoading(LoadingComponentId.LANDING_PAGE);
}));
}

getProductDetailsWithVersion(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<div class="d-flex justify-content-center" data-title="dot-stretching">
<div class="stage">
<div class="dot-stretching"></div>
@if (isLoading()) {
<div [className]="containerClasses">
<div class="d-flex justify-content-center" data-title="dot-stretching">
<div class="stage">
<div class="dot-stretching"></div>
</div>
</div>
</div>
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Component } from '@angular/core';
import { NgClass } from '@angular/common';
import { Component, computed, inject, Input } from '@angular/core';
import { LoadingService } from '../../../core/services/loading/loading.service';

@Component({
selector: 'app-loading-spinner',
standalone: true,
imports: [
NgClass
],
templateUrl: './loading-spinner.component.html',
styleUrl: './loading-spinner.component.scss'
})
export class LoadingSpinnerComponent {
spinners = Array(5).fill(null);
@Input() key: string = '';
@Input() containerClasses: string = '';
loadingService = inject(LoadingService);
isLoading = computed(() => this.loadingService.loadingSubject.value[this.key]);
}
7 changes: 7 additions & 0 deletions marketplace-ui/src/app/shared/enums/loading-component-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum LoadingComponentId {
LANDING_PAGE = 'landing-page',
PRODUCT_DETAIL = 'product-detial',
PRODUCT_VERSION = 'product-version',
DETAIL_PAGE = 'detail-page',
DETAIL_INFORMATION_TAB = 'detail-information-tab'
}

0 comments on commit 73fc859

Please sign in to comment.