Commit 15f9e92a authored by Kostis Trantzas's avatar Kostis Trantzas
Browse files

Merge branch...

Merge branch '33-enhance-the-user-experience-at-landing-metrics-page-when-apis-are-not-responding' into 'develop'

Resolve "Enhance the user experience at landing/metrics page, when APIs are not responding"

See merge request !31
parents 3a75bba7 e0187018
Loading
Loading
Loading
Loading
Loading
+19 −17
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ import { DoughnutchartComponent } from './landing/metrics/doughnutchart/doughnut
import { StatusCardComponent } from './landing/metrics/statuscard/statuscard.component';
import { PortalCardComponent } from './landing/portalcard/portalcard.component';
import { SkeletonComponent } from './landing/metrics/skeleton.component';
import { CdkTableModule } from "@angular/cdk/table";

registerLocaleData(enGB);
export function initializeApp(bootstrap: BootstrapService) {
@@ -131,7 +132,8 @@ export function initializeAppTheme(bootstrap: BootstrapService) {
    MatCheckboxModule,
    OAuthModule.forRoot(),
    ToastrModule.forRoot({ progressBar: true, preventDuplicates: true }),
    NgChartsModule
    NgChartsModule,
    CdkTableModule
],
    providers: [
        AppService,
+20 −3
Original line number Diff line number Diff line
@@ -46,7 +46,13 @@
					</svg>
				</div>
				<div class="card-body p-3">
					<div *ngIf="isNaN(animatedCounts.registeredUsers) || isLoading; else apiRespondedUsers">
						<h5 class="card-title"><skeleton [width]="'35%'" [height]="'24px'"></skeleton></h5>
					</div>
					<ng-template #apiRespondedUsers>
						<!-- <h5 class="card-title font-weight-bold">{{isNaN(animatedCounts.registeredUsers) ? 'NaN': animatedCounts.registeredUsers}}</h5> -->
						 <h5 class="card-title font-weight-bold">{{animatedCounts.registeredUsers}}</h5>
					</ng-template>
					<div class="card-text">Registered Users</div>
				</div>
			</div>
@@ -61,7 +67,13 @@
					</svg>
				</div>
				<div class="card-body p-3">
					<div *ngIf="isNaN(animatedCounts.publishedServiceSpecs) || isLoading; else apiRespondedServiceSpecs">
						<h5 class="card-title"><skeleton [width]="'35%'" [height]="'24px'"></skeleton></h5>
					</div>
					<ng-template #apiRespondedServiceSpecs>
						<!-- <h5 class="card-title font-weight-bold">{{isNaN(animatedCounts.publishedServiceSpecs) ? ' ': animatedCounts.publishedServiceSpecs}}</h5> -->
						 <h5 class="card-title font-weight-bold">{{animatedCounts.publishedServiceSpecs}}</h5>
					</ng-template>
					<div class="card-text">Published Service Specifications</div>
				</div>
			</div>
@@ -77,7 +89,12 @@
					</svg>
				</div>
				<div class="card-body p-3">
					<div *ngIf="isNaN(animatedCounts.registeredResourceSpecs) || isLoading; else apiRespondedResourceSpecs">
						<h5 class="card-title"><skeleton [width]="'35%'" [height]="'24px'"></skeleton></h5>
					</div>
					<ng-template #apiRespondedResourceSpecs>
						<h5 class="card-title font-weight-bold">{{animatedCounts.registeredResourceSpecs}}</h5>
					</ng-template>
					<div class="card-text">Registered Resource Specifications</div>
				</div>
			</div>
+2 −0
Original line number Diff line number Diff line
@@ -95,6 +95,8 @@
.card-title {
    padding-top: 1.5rem;
    transition: all 0.3s ease-in-out;
    display: flex;
    justify-content: center;
}


+47 −28
Original line number Diff line number Diff line
@@ -23,25 +23,23 @@ export class LandingComponent implements OnInit {

  config: IAppConfig
  loggedIn: boolean
  
  // Video section variables
  private player: Player;
  videoLoaded: boolean = false;
  isLoading: boolean = true;

  @ViewChild('videoRef', { static: true }) videoElement!: ElementRef<HTMLIFrameElement>;

  // Metrics section variables
  registeredUsers = 9999;
  publishedServiceSpecs = 9999;
  registeredResourceSpecs = 9999;
  animatedCounts = {
    registeredUsers: 0,
    publishedServiceSpecs: 0,
    registeredResourceSpecs: 0
    registeredUsers: NaN,
    publishedServiceSpecs: NaN,
    registeredResourceSpecs: NaN
  };
  targetCounts = {
    registeredUsers: 0,
    publishedServiceSpecs: 0,
    registeredResourceSpecs: 0
    registeredUsers: NaN,
    publishedServiceSpecs: NaN,
    registeredResourceSpecs: NaN
  };
  private intervalId: any;

@@ -54,36 +52,44 @@ export class LandingComponent implements OnInit {
    this.initializePlayer()


    // Initialize animated counts
    this.startAnimation();
    forkJoin({
      registeredUsers: this.generalMetricsService.getRegisteredIndividuals().pipe(
        catchError(error => {
          console.error('Failed to load registered users', error);
          return scheduled([{ registeredIndividuals: this.registeredUsers }], asyncScheduler);
          return scheduled([{ registeredIndividuals: NaN }], asyncScheduler);
        })
      ),
      publishedServiceSpecs: this.generalMetricsService.getPublishedServiceSpecifications().pipe(
        catchError(error => {
          console.error('Failed to load published specs', error);
          return scheduled([{ publishedServiceSpecifications: this.publishedServiceSpecs }], asyncScheduler);
          return scheduled([{ publishedServiceSpecifications: NaN }], asyncScheduler);
        })
      ),
      registeredResourceSpecs: this.generalMetricsService.getRegisteredResourceSpecifications().pipe(
        catchError(error => {
          console.error('Failed to load resource specs', error);
          return scheduled([{ registeredResourceSpecifications: this.registeredResourceSpecs }], asyncScheduler);
          return scheduled([{ registeredResourceSpecifications: NaN }], asyncScheduler);
        })
      )
    }).subscribe(
    })
      // .pipe(delay(500))
      .subscribe(
        results => {

          this.targetCounts.registeredUsers = results.registeredUsers.registeredIndividuals;
          this.targetCounts.publishedServiceSpecs = results.publishedServiceSpecs.publishedServiceSpecifications;
          this.targetCounts.registeredResourceSpecs = results.registeredResourceSpecs.registeredResourceSpecifications;
          this.isLoading = false;
          // Initialize animated counts
          this.startAnimation();

        }
    ) 
      );
  }

  isNaN(value: any): boolean {
    return isNaN(value);
  }

  initializePlayer() {
    this.player = new Player(this.videoElement.nativeElement, {
@@ -159,12 +165,24 @@ export class LandingComponent implements OnInit {
  startAnimation() {
    const stepTime = 50;

    // Initialize counts to NaN if the target is NaN (api didn't respond), otherwise start from 0 and animate the count
    this.animatedCounts = {
      registeredUsers: isNaN(this.targetCounts.registeredUsers) ? NaN : 0,
      publishedServiceSpecs: isNaN(this.targetCounts.publishedServiceSpecs) ? NaN : 0,
      registeredResourceSpecs: isNaN(this.targetCounts.registeredResourceSpecs) ? NaN : 0
    };

    this.intervalId = setInterval(() => {
      for (const key in this.animatedCounts) {
        const k = key as keyof typeof this.animatedCounts;
        const current = this.animatedCounts[k];
        const target = this.targetCounts[k];

        if (isNaN(target)) {
          this.animatedCounts[k] = NaN;
          continue;
        }

        const delta = target - current;

        if (Math.abs(delta) > 0) {
@@ -172,6 +190,7 @@ export class LandingComponent implements OnInit {
        }
      }
    }, stepTime);

  }

  ngOnDestroy() {
+7 −7
Original line number Diff line number Diff line
<div class="chart-container">
    
    <div class="service-chart">
        <div *ngIf="isLoading" class="pie-chart">
        <div *ngIf="isLoading || isNaN(totalChartData)" class="pie-chart">
            <skeleton [height]="'100%'" [width]="'100%'" [borderRadius]="'50%'"></skeleton>
        </div>
        <div *ngIf="totalChartData==0 && !isLoading" class="no-data-found">
        <div *ngIf="totalChartData==0 && !isLoading && !isNaN(totalChartData)" class="no-data-found">
            {{noDataMessage}}
        </div>
        <canvas *ngIf="totalChartData!=0 && !isLoading" baseChart [data]="chartData" [type]="'doughnut'"
        <canvas *ngIf="totalChartData!=0 && !isLoading && !isNaN(totalChartData)" baseChart [data]="chartData" [type]="'doughnut'"
        [options]="chartOptions" [plugins]="plugins">
        </canvas>  
    </div>
    <div class="chart-info">
        <div *ngIf="isLoading" style="height: 20%; width: 65%; margin-bottom: 0.5rem">
        <div *ngIf="isLoading || isNaN(totalChartData)" style="height: 20%; width: 65%; margin-bottom: 0.5rem">
            <skeleton [height]="'100%'" [width]="'100%'"></skeleton>
        </div>
        <div class="chart-title" *ngIf="!isLoading"> 
        <div class="chart-title" *ngIf="!isLoading && !isNaN(totalChartData)"> 
            {{chartTitle}}
        </div> 
        <div *ngIf="isLoading" style="height: 50%; width: 50%">
        <div *ngIf="isLoading || isNaN(totalChartData)" style="height: 50%; width: 50%">
            <skeleton [height]="'100%'" [width]="'100%'"></skeleton>
        </div>
        <div class="chart-legend" *ngIf="!isLoading">
        <div class="chart-legend" *ngIf="!isLoading && !isNaN(totalChartData)">
            <ul style="padding: 0; margin-bottom: 0;">
                <li style="display: flex; align-items: center; padding-right: 20px" *ngFor="let label of chartData.labels; index as i">
                    <span [ngStyle]="{
Loading