From 39348bffcdc50ca075d011d198b67302fce9f0b0 Mon Sep 17 00:00:00 2001
From: kaw67872 <kawtar.laariche@iais.fraunhofer.de>
Date: Mon, 29 Jul 2024 08:53:23 +0200
Subject: [PATCH] #25: add catalogs list page

---
 .../core/services/private-catalogs.service.ts |  40 ++++++
 .../catalogs/catalogs.component.html          | 117 ++++++++++++++-
 .../catalogs/catalogs.component.scss          | 135 ++++++++++++++++++
 .../dashboard/catalogs/catalogs.component.ts  | 103 ++++++++++++-
 .../marketplace/marketplace.component.html    |   2 +-
 .../marketplace/marketplace.component.scss    |   1 -
 .../marketplace/marketplace.component.ts      |   1 +
 .../shared/models/public-solution.model.ts    |   1 +
 8 files changed, 393 insertions(+), 7 deletions(-)

diff --git a/src/app/core/services/private-catalogs.service.ts b/src/app/core/services/private-catalogs.service.ts
index cc7776a..c9266ce 100644
--- a/src/app/core/services/private-catalogs.service.ts
+++ b/src/app/core/services/private-catalogs.service.ts
@@ -895,4 +895,44 @@ export class PrivateCatalogsService {
       }),
     );
   }
+
+  loadCatalogs(pageNumber: number, totalCatalogsElements: number) {
+    const request = {
+      request_body: {
+        fieldToDirectionMap: {
+          created: 'ASC',
+        },
+        page: pageNumber,
+        size: totalCatalogsElements,
+      },
+    };
+    const url = apiConfig.apiBackendURL + apiConfig.urlAllCatalogsList;
+
+    return this._httpSharedService.post(url, undefined, request).pipe(
+      //map((res) => res.response_body.content),
+      catchError((error) => {
+        throw error;
+      }),
+    );
+  }
+
+  loadTotalCatalog(): Observable<number> {
+    const request = {
+      request_body: {
+        fieldToDirectionMap: {
+          created: 'ASC',
+        },
+        page: 0,
+        size: 1,
+      },
+    };
+    const url = apiConfig.apiBackendURL + apiConfig.urlAllCatalogsList;
+
+    return this._httpSharedService.post(url, undefined, request).pipe(
+      map((res) => res.response_body.totalElements),
+      catchError((error) => {
+        throw error;
+      }),
+    );
+  }
 }
diff --git a/src/app/features/dashboard/catalogs/catalogs.component.html b/src/app/features/dashboard/catalogs/catalogs.component.html
index 3d7afe0..1f6b913 100644
--- a/src/app/features/dashboard/catalogs/catalogs.component.html
+++ b/src/app/features/dashboard/catalogs/catalogs.component.html
@@ -1 +1,116 @@
-<p>catalogs works!</p>
+<div class="catalogs-container">
+  <section class="pageheadsection mob-pageheadsection1">
+    <div class="mdl-grid mdl-grid.mdl-grid--no-spacing">
+      <div>
+        <gp-headline [headlineTitle]="'Catalogs'"></gp-headline>
+      </div>
+      <gp-breadcrumb-navigation
+        [firstNavigationLabel]="{ label: 'Home' }"
+        [secondNavigationLabel]="{ label: 'Catalogs', disabled: true }"
+        (firstNavigationClicked)="onHomeClick()"
+      ></gp-breadcrumb-navigation>
+    </div>
+  </section>
+  <div class="add-catalog">
+    <button mat-raised-button color="primary">Add new catalog</button>
+  </div>
+  <div class="filter">
+    <span>Filter</span>
+  </div>
+  <div class="table-container">
+    <table mat-table [dataSource]="catalogs">
+      <!-- Name Column -->
+      <ng-container matColumnDef="name">
+        <th mat-header-cell *matHeaderCellDef>Catalog name</th>
+        <td mat-cell *matCellDef="let element">
+          {{ element.name }}
+        </td>
+      </ng-container>
+
+      <!-- Type Column -->
+      <ng-container matColumnDef="type">
+        <th mat-header-cell *matHeaderCellDef>Catalog type</th>
+        <td mat-cell *matCellDef="let element" class="font-weight500">
+          {{ element.type }}
+        </td>
+      </ng-container>
+
+      <!-- Published Column -->
+      <ng-container matColumnDef="publisher">
+        <th mat-header-cell *matHeaderCellDef>Publisher name</th>
+        <td mat-cell *matCellDef="let element" class="font-weight500">
+          {{ element.publisher }}
+        </td>
+      </ng-container>
+
+      <!-- Self Pub Column -->
+      <ng-container matColumnDef="selfPublish">
+        <th mat-header-cell *matHeaderCellDef>Self-PUB</th>
+        <td mat-cell *matCellDef="let element" class="font-weight500">
+          {{ element.selfPublish ? "Yes" : "No" }}
+        </td>
+      </ng-container>
+
+      <!-- Access type Column -->
+      <ng-container matColumnDef="accessTypeCode">
+        <th mat-header-cell *matHeaderCellDef>Access type</th>
+        <td mat-cell *matCellDef="let element">
+          {{ element.accessTypeCode === "PB" ? "Public" : "Restricted" }}
+        </td>
+      </ng-container>
+
+      <!-- Total models Column -->
+      <ng-container matColumnDef="solutionCount">
+        <th mat-header-cell *matHeaderCellDef>Total models</th>
+        <td mat-cell *matCellDef="let element">
+          {{ element.solutionCount }}
+        </td>
+      </ng-container>
+
+      <!-- Created date Column -->
+      <ng-container matColumnDef="created">
+        <th mat-header-cell *matHeaderCellDef>Created date</th>
+        <td mat-cell *matCellDef="let element">
+          {{ element.created | date: "dd/MM/yyyy" }}
+        </td>
+      </ng-container>
+
+      <!-- Action Column -->
+      <ng-container matColumnDef="action">
+        <th mat-header-cell *matHeaderCellDef>Action</th>
+        <td mat-cell *matCellDef="let element">
+          {{ element.action }}
+        </td>
+      </ng-container>
+
+      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+      <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
+    </table>
+  </div>
+  <div class="pagination-container">
+    <div class="total-items-container">
+      @if (totalItems > 0) {
+        <div class="total-items-text-container">
+          <span class="showing-text"
+            >Showing -
+            <span class="total-items-text">
+              {{ calculateStartIndex() }} to {{ calculateEndIndex() }} of
+              {{ totalItems }} Models</span
+            ></span
+          >
+        </div>
+      }
+    </div>
+    <div class="pagination-text">
+      <mat-paginator
+        [length]="totalItems"
+        [pageSize]="pageSize"
+        [pageSizeOptions]="pageSizeOptions"
+        (page)="onPageChange($event)"
+        aria-label="Select page"
+        aria-label="Select page"
+      >
+      </mat-paginator>
+    </div>
+  </div>
+</div>
diff --git a/src/app/features/dashboard/catalogs/catalogs.component.scss b/src/app/features/dashboard/catalogs/catalogs.component.scss
index e69de29..afd7ff2 100644
--- a/src/app/features/dashboard/catalogs/catalogs.component.scss
+++ b/src/app/features/dashboard/catalogs/catalogs.component.scss
@@ -0,0 +1,135 @@
+.content {
+  padding: 24px;
+}
+
+.page-wrap {
+  display: flex !important;
+  flex-direction: column !important;
+  min-height: 100vh !important;
+}
+
+.content-router-outlet {
+  flex: 1;
+}
+
+// content height
+::ng-deep.mat-drawer-content {
+  height: 89.1% !important;
+}
+
+mat-sidenav-container {
+  overflow: hidden;
+}
+
+mat-sidenav {
+  width: 300px;
+  background: #f1f1f1;
+  height: 100%;
+  overflow: hidden;
+}
+
+:host ::ng-deep .mat-drawer-inner-container {
+  overflow: hidden !important;
+  padding: 20px 0 20px 0;
+}
+
+mat-sidenav-content {
+  overflow: hidden;
+}
+
+.md-intro-container {
+  display: flex;
+  flex-wrap: nowrap;
+  justify-content: flex-start;
+  align-content: center;
+  border-bottom: 1px solid #e5e5e5;
+  margin-bottom: 20px;
+  margin-left: 20px;
+}
+
+.spacebetween {
+  justify-content: space-between !important;
+}
+
+.md-intro-container h6 {
+  margin-right: 30px;
+  margin-top: 30px !important;
+}
+
+.sectiontitle9 {
+  color: #671c9d;
+  margin-bottom: 0;
+  border-bottom: none;
+  font-size: 16px;
+  font-weight: 600;
+  line-height: 30px;
+  padding: 0;
+}
+
+.mat-mdc-header-cell {
+  color: #671c9d;
+  background: #e8e5ec !important;
+}
+
+.btn-grid-action {
+  cursor: pointer;
+  background: transparent;
+  border: none;
+  color: #0366d6;
+  padding: 0;
+  min-width: 10px;
+}
+.btn-grid-action i {
+  font-size: 14px !important;
+}
+.btn-grid-action:hover {
+  background: none;
+  color: #0366d6;
+}
+
+.mdl-button.mdl-js-button[disabled] {
+  color: #b3b3b3;
+  border-color: #d3d1d1;
+  cursor: not-allowed;
+  background: #efefef;
+}
+
+.font-weight500 {
+  font-weight: 500;
+}
+
+.pagination-container {
+  display: flex;
+  align-items: center;
+}
+
+.pagination-text {
+  flex: 1;
+}
+
+.catalogs-container {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  height: 100%;
+  gap: 30px;
+  margin: 20px;
+}
+
+.mat-mdc-paginator {
+  background-color: transparent !important;
+}
+
+.table-container {
+  flex-grow: 2 !important;
+}
+
+.add-catalog {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.filter {
+  display: flex;
+  justify-content: flex-end;
+}
diff --git a/src/app/features/dashboard/catalogs/catalogs.component.ts b/src/app/features/dashboard/catalogs/catalogs.component.ts
index f22e4a1..7410316 100644
--- a/src/app/features/dashboard/catalogs/catalogs.component.ts
+++ b/src/app/features/dashboard/catalogs/catalogs.component.ts
@@ -1,13 +1,108 @@
-import { Component } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { CommonModule } from '@angular/common';
+import { BreadcrumbNavigationComponent } from 'src/app/shared/components/breadcrumb-navigation/breadcrumb-navigation.component';
+import { map, Observable } from 'rxjs';
+import { PrivateCatalogsService } from 'src/app/core/services/private-catalogs.service';
+import { BrowserStorageService } from 'src/app/core/services/storage/browser-storage.service';
+import { Router } from '@angular/router';
+import { HeadlineComponent } from 'src/app/shared/components/headline/headline.component';
+import { MatSidenavModule } from '@angular/material/sidenav';
+import { MatTableModule } from '@angular/material/table';
+import {
+  MatPaginator,
+  MatPaginatorIntl,
+  MatPaginatorModule,
+  PageEvent,
+} from '@angular/material/paginator';
+import { Catalog } from 'src/app/shared/models';
+import { MatButtonModule } from '@angular/material/button';
 
 @Component({
   selector: 'gp-catalogs',
   standalone: true,
-  imports: [CommonModule],
+  imports: [
+    CommonModule,
+    BreadcrumbNavigationComponent,
+    HeadlineComponent,
+    MatTableModule,
+    MatPaginatorModule,
+    MatButtonModule,
+  ],
   templateUrl: './catalogs.component.html',
-  styleUrl: './catalogs.component.scss'
+  styleUrl: './catalogs.component.scss',
 })
-export class CatalogsComponent {
+export class CatalogsComponent implements OnInit {
+  userId$: Observable<string | undefined>;
+  displayedColumns: string[] = [
+    'name',
+    'type',
+    'publisher',
+    'selfPublish',
+    'accessTypeCode',
+    'solutionCount',
+    'created',
+    'action',
+  ];
+  catalogs!: Catalog[];
+  pageSizeOptions = [10, 50, 100];
+  pageSize = 10;
+  pageIndex = 0;
+  totalItems = 0;
 
+  constructor(
+    private privateCatalogsService: PrivateCatalogsService,
+    private router: Router,
+    private browserStorageService: BrowserStorageService,
+    private paginator: MatPaginatorIntl,
+  ) {
+    this.userId$ = this.browserStorageService
+      .getUserDetails()
+      .pipe(map((details) => details?.userId));
+    paginator.itemsPerPageLabel = 'Showing';
+  }
+  ngOnInit(): void {
+    this.loadData();
+  }
+
+  onHomeClick() {
+    this.userId$.subscribe((userId) => {
+      if (userId) {
+        this.router.navigate(['/dashboard/home']);
+      } else {
+        this.router.navigate(['/home']);
+      }
+    });
+  }
+
+  loadData() {
+    this.privateCatalogsService.loadTotalCatalog().subscribe({
+      next: (res) => {
+        this.totalItems = res;
+        this.privateCatalogsService.loadCatalogs(0, this.totalItems).subscribe({
+          next: (res) => {
+            console.log({ res });
+            this.catalogs = res.response_body.content;
+            this.totalItems = res.response_body.totalElements;
+          },
+          error: (error) => {},
+        });
+      },
+      error: (error) => {},
+    });
+  }
+
+  onPageChange(event: PageEvent): void {
+    this.pageSize = event.pageSize;
+    this.pageIndex = event.pageIndex;
+    this.loadData();
+  }
+
+  calculateStartIndex(): number {
+    return this.pageIndex * this.pageSize + 1;
+  }
+
+  calculateEndIndex(): number {
+    const endIndex = (this.pageIndex + 1) * this.pageSize;
+    return endIndex > this.totalItems ? this.totalItems : endIndex;
+  }
 }
diff --git a/src/app/features/marketplace/marketplace.component.html b/src/app/features/marketplace/marketplace.component.html
index 1e1ff78..b819a41 100644
--- a/src/app/features/marketplace/marketplace.component.html
+++ b/src/app/features/marketplace/marketplace.component.html
@@ -1,4 +1,4 @@
-<div class="flex-column">
+<div class="catalogs-container">
   <section class="pageheadsection mob-pageheadsection1">
     <div class="mdl-grid mdl-grid.mdl-grid--no-spacing">
       <div>
diff --git a/src/app/features/marketplace/marketplace.component.scss b/src/app/features/marketplace/marketplace.component.scss
index d5e1010..aef4871 100644
--- a/src/app/features/marketplace/marketplace.component.scss
+++ b/src/app/features/marketplace/marketplace.component.scss
@@ -39,7 +39,6 @@ mat-sidenav {
   width: 300px;
   background: #f1f1f1;
   height: 100%;
-  //overflow-y: auto;
   overflow: hidden;
 }
 
diff --git a/src/app/features/marketplace/marketplace.component.ts b/src/app/features/marketplace/marketplace.component.ts
index 2c09ec7..ed73370 100644
--- a/src/app/features/marketplace/marketplace.component.ts
+++ b/src/app/features/marketplace/marketplace.component.ts
@@ -356,6 +356,7 @@ export class MarketplaceComponent {
     this.isOnMyFavoriteSelected = false;
     this.loadPublicSolutions();
   }
+
   onMyFavoriteCatalogsClick() {
     this.isOnMyFavoriteSelected = true;
     this.isLoading = true;
diff --git a/src/app/shared/models/public-solution.model.ts b/src/app/shared/models/public-solution.model.ts
index e11be06..13cbc15 100644
--- a/src/app/shared/models/public-solution.model.ts
+++ b/src/app/shared/models/public-solution.model.ts
@@ -68,6 +68,7 @@ export interface Catalog {
   publisher: string;
   selfPublish: boolean;
   url: string;
+  solutionCount: number;
 }
 
 export interface Revision {
-- 
GitLab