refactor request chain for /home and /marketplace
MODIFY
src/app/app.component.html
src/app/app.component.html
<app-footer></app-footer>
-<div id="spinner" *ngIf="this.showSpinner">
+<div id="spinner" [hidden]="!this.loadingSpinnerService.isWaiting()">
<mat-spinner strokeWidth="3" diameter="50"></mat-spinner>
</div>

MODIFY
src/app/app.component.ts
src/app/app.component.ts
@@ -13,21 +13,17 @@ import { SpinnerService } from './services/spinner/spinner.service';
export class AppComponent implements OnInit {
@ViewChild('content') content!: ElementRef;
title = 'devportal';
- showSpinner: boolean;
constructor(
private router: Router,
private heroService: HeroService,
private navigationService: NavigationService,
public loadingSpinnerService: SpinnerService
- ) {
- this.showSpinner = false;
- }
+ ) {}
ngOnInit() {
this.initHeroEmitter();
this.initNavigationEmitter();
- this.showSpinner = this.loadingSpinnerService.isWaiting();
}
private initHeroEmitter() {

MODIFY
src/app/components/api-card-list/api-card-list.component.html
src/app/components/api-card-list/api-card-list.component.html
/>
</mat-form-field>
</div>
-<ng-container *ngIf="totalSize === 0">
- <h2 class="align">
- {{'COMMON.NO_DATA_FOUND' | translate}}
- </h2>
-</ng-container>
-<ng-container *ngIf="ready">
+<ng-container *ngIf="apis.length > 0 && ready; else NoDataMsg">
<div id="grid">
<app-api-card
*ngFor="let api of apis"
></app-api-card>
</div>
</ng-container>
+<ng-template #NoDataMsg>
+ <ng-container *ngIf="this.ready">
+ <h2 class="align">
+ {{'COMMON.NO_DATA_FOUND' | translate}}
+ </h2>
+ </ng-container>
+</ng-template>
<div *ngIf="listType === 'api' && totalSize > searchCriteria.paging.pageSize" class="align">
<mat-paginator
[length]="totalSize"

MODIFY
src/app/components/api-card-list/api-card-list.component.ts
src/app/components/api-card-list/api-card-list.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { ApiService } from '../../services/api/api.service';
import { PageEvent } from '@angular/material/paginator';
-import { switchMap, tap } from 'rxjs/operators';
-import { forkJoin, Observable, of } from 'rxjs';
+import {map, switchMap } from 'rxjs/operators';
+import { forkJoin } from 'rxjs';
import { SpinnerService } from '../../services/spinner/spinner.service';
-import {
- IApiListData,
- IApiSummary,
- ISearchCriteria,
- ISearchResult,
-} from '../../interfaces/ICommunication';
+import { IApiSummary, ISearchCriteria } from '../../interfaces/ICommunication';
import {ActivatedRoute, Router} from "@angular/router";
+import {IApiSummaryExt} from "../../interfaces/IApiSummaryExt";
+import {isApiDocAvailable} from "../../shared/utility";
@Component({
selector: 'app-api-card-list',
@@ -18,7 +15,7 @@ import {ActivatedRoute, Router} from "@angular/router";
styleUrls: ['./api-card-list.component.scss'],
})
export class ApiCardListComponent implements OnInit {
- apis: IApiSummary[] = [];
+ apis: IApiSummaryExt[] = [];
totalSize = 0;
ready = false;
searchTerm = '';
@@ -97,63 +94,48 @@ export class ApiCardListComponent implements OnInit {
}
getApiList(): void {
- const docsAvailable: Array<Observable<boolean>> = [];
- const result: ISearchResult = { apis: [], totalSize: 0 };
-
this.loadingSpinnerService.startWaiting();
this.ready = false;
this.apiService
.searchApis(this.searchCriteria)
.pipe(
- // switch from SearchResultsBeanApiSummaryBean to ISearchResult
- switchMap((searchResult) => {
- result.apis = searchResult.beans;
- result.totalSize = searchResult.totalSize;
- return of(result);
+ // map from SearchResultsBeanApiSummaryBean to IApiSummary[]
+ map((searchResult) => {
+ this.totalSize = searchResult.totalSize;
+ return searchResult.beans;
}),
- tap((searchResult) => {
- // Check API docs for every API
- searchResult.apis.forEach((api) => {
- docsAvailable.push(this.checkApiDocs(api));
- });
- // Set docsAvailable once every Request has finished
- forkJoin(docsAvailable).subscribe((result) => {
- result.forEach((eachResult, index) => {
- searchResult.apis[index].docsAvailable = eachResult;
- });
- this.loadingSpinnerService.stopWaiting();
- this.ready = true;
- });
+
+ switchMap((apiSummaries: IApiSummary[]) => {
+ return forkJoin(apiSummaries.map(apiSummary => {
+ return this.apiService.getLatestApiVersion(apiSummary.organizationId, apiSummary.id).pipe(
+ map(latestApiVersion => {
+ return {
+ ...apiSummary,
+ latestVersion: latestApiVersion.version,
+ docsAvailable: isApiDocAvailable(latestApiVersion)
+ } as IApiSummaryExt;
})
- )
- .subscribe((searchResult) => {
+ );
+ }));
+ })
+ ).subscribe((apiList: IApiSummaryExt[]) => {
if (this.listType === 'api') {
- this.apis = searchResult.apis;
+ this.apis = apiList;
} else if (this.listType === 'featuredApi') {
- this.apis = searchResult.apis.slice(0,4);
+ this.apis = apiList.slice(0,4);
}
- this.totalSize = searchResult.totalSize;
+ this.loadingSpinnerService.stopWaiting();
+ this.ready = true;
});
}
- checkApiDocs(api: IApiListData): Observable<boolean> {
- return this.apiService.getLatestApiVersion(api.organizationId, api.id).pipe(
- tap((apiVersion) => (api.latestVersion = apiVersion.version)),
- switchMap((apiVersion) => {
- return of(
- apiVersion.definitionType !== null &&
- apiVersion.definitionType !== 'None'
- );
- })
- );
- }
-
- getFeaturedApis(): void {
+ //TODO implement real api call
+/* getFeaturedApis(): void {
this.apiService
.getFeaturedApis(this.searchCriteria)
.subscribe((searchResult) => {
this.apis = searchResult.beans;
});
- }
+ }*/
}

MODIFY
src/app/components/api-card/api-card.component.ts
src/app/components/api-card/api-card.component.ts
import { Component, Input, OnInit } from '@angular/core';
-import { IApiListData } from '../../interfaces/ICommunication';
+import {IApiSummaryExt} from "../../interfaces/IApiSummaryExt";
@Component({
selector: 'app-api-card',
@@ -13,5 +13,5 @@ export class ApiCardComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
- @Input() api!: IApiListData;
+ @Input() api!: IApiSummaryExt;
}

ADD
src/app/interfaces/IApiSummaryExt.ts
+import {IApiSummary} from "./ICommunication";
+
+export interface IApiSummaryExt extends IApiSummary {
+ docsAvailable: boolean;
+ latestVersion: string;
+}

MODIFY
src/app/interfaces/ICommunication.ts
src/app/interfaces/ICommunication.ts
@@ -342,11 +342,6 @@ export interface IApiSummary {
createdOn: string;
}
-export interface IApiListData extends IApiSummary {
- docsAvailable?: boolean;
- latestVersion?: string;
-}
-
export interface IApiVersionSummary {
organizationId: string;
organizationName: string;
@@ -857,11 +852,6 @@ export interface ISearchResultsApiSummary {
totalSize: number;
}
-export interface ISearchResult {
- apis: IApiListData[];
- totalSize: number;
-}
-
export interface IAvailableApi {
id: string;
icon: string;

MODIFY
src/app/shared/utility.ts
src/app/shared/utility.ts
+import {IApiVersion} from "../interfaces/ICommunication";
+
export function flatArray(array: any[][]): any[] {
let flattenedArray: any[] = []
flattenedArray = flattenedArray.concat(...array)
@@ -16,3 +18,8 @@ export function formatBytes(bytes: number, decimals = 0): string {
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
+
+export function isApiDocAvailable(apiVersion: IApiVersion): boolean {
+ return (apiVersion.definitionType !== null &&
+ apiVersion.definitionType !== 'None')
+}

refactor request chain for /home and /marketplace