diff --git a/src/app/core/config/api-config.ts b/src/app/core/config/api-config.ts index 025faa86fc8d5f0758f4e7cf997af496c7f3541a..dab1cb1fe6ba4daf7645fdb7861900132c833609 100644 --- a/src/app/core/config/api-config.ts +++ b/src/app/core/config/api-config.ts @@ -68,4 +68,6 @@ export const apiConfig = { urlPublishSolution: '/api/publish', urlSearchPublishRequest: '/api/publish/request/search/revision', withdrawPublishRequestUrl: '/api/publish/request/withdraw/', + urlCatalogPath: '/api/catalog', + urlSiteConfig: '/api/admin/config', }; diff --git a/src/app/core/services/private-catalogs.service.ts b/src/app/core/services/private-catalogs.service.ts index cc7776af31b3f58eb774396c410580474b768772..ef5b8f766d74561ed0621dac97a0b78092994d34 100644 --- a/src/app/core/services/private-catalogs.service.ts +++ b/src/app/core/services/private-catalogs.service.ts @@ -895,4 +895,101 @@ 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; + }), + ); + } + + createCatalog(catalog: Catalog) { + const requestObj = { + request_body: { + ...catalog, + url: 'http://localhost', + }, + }; + const url = apiConfig.apiBackendURL + apiConfig.urlCatalogPath; + + return this._httpSharedService.post(url, undefined, requestObj).pipe( + catchError((error) => { + throw error; + }), + ); + } + + updateCatalog(catalog: Catalog) { + const requestObj = { + request_body: { + ...catalog, + url: 'http://localhost', + }, + }; + const url = apiConfig.apiBackendURL + apiConfig.urlCatalogPath; + + return this._httpSharedService.put(url, undefined, requestObj).pipe( + catchError((error) => { + throw error; + }), + ); + } + + deleteCatalog(catalog: Catalog) { + const url = + apiConfig.apiBackendURL + + apiConfig.urlCatalogPath + + '/' + + catalog.catalogId; + + return this._httpSharedService.delete(url).pipe( + catchError((error) => { + throw error; + }), + ); + } + + getSiteConfig() { + const url = + apiConfig.apiBackendURL + apiConfig.urlSiteConfig + '/site_config'; + + return this._httpSharedService.get(url, undefined).pipe( + catchError((error) => { + throw error; + }), + ); + } } diff --git a/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.html b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..eeb2c4817ecc5c8d25494a619fcd7101a0e41bb3 --- /dev/null +++ b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.html @@ -0,0 +1,105 @@ +<mat-toolbar class="dialog-header"> + <div class="dialog-title"> + <h2> + {{ + data.dataKey.actionType === "edit" ? "Edit catalog" : "Add new catalog" + }} + </h2> + </div> + <button + type="button" + mat-icon-button + [mat-dialog-close]="true" + class="close" + tabindex="-1" + > + <mat-icon aria-hidden="false" aria-label="Close icon">close</mat-icon> + </button> +</mat-toolbar> +<mat-dialog-content> + <div class="star-rating-container"> + <form [formGroup]="addEditDialogForm"> + <div class="flex-column"> + <mat-form-field> + <mat-label>Catalog name</mat-label> + <input matInput formControlName="name" /> + + @if ( + controls["name"].touched && controls["name"].hasError("required") + ) { + <mat-error class="validation-msgs" + >Catalog name required.</mat-error + > + } + </mat-form-field> + <div class="type-access-level-container"> + <mat-form-field class="full-width"> + <mat-label>Select access level</mat-label> + <mat-select formControlName="accessTypeCode"> + @for (accessTypeCode of accessTypeCodes; track accessTypeCode) { + <mat-option [value]="accessTypeCode.value">{{ + accessTypeCode.name + }}</mat-option> + } + </mat-select> + @if ( + controls["accessTypeCode"].touched && + controls["accessTypeCode"].hasError("required") + ) { + <mat-error class="validation-msgs" + >Catalog access level required.</mat-error + > + } + </mat-form-field> + <mat-form-field class="full-width"> + <mat-label>Select catalog type</mat-label> + <mat-select formControlName="type"> + @for (type of catalogTypes; track type) { + <mat-option [value]="type.value">{{ type.name }}</mat-option> + } + </mat-select> + @if ( + controls["type"].touched && controls["type"].hasError("required") + ) { + <mat-error class="validation-msgs" + >Catalog type required.</mat-error + > + } + </mat-form-field> + </div> + + <mat-form-field> + <mat-label>Add description</mat-label> + <textarea matInput formControlName="description"></textarea> + @if ( + controls["description"].touched && + controls["description"].hasError("required") + ) { + <mat-error class="validation-msgs" + >Catalog description required.</mat-error + > + } + </mat-form-field> + + <mat-checkbox formControlName="selfPublish" color="primary"> + Self publish? + </mat-checkbox> + </div> + </form> + </div></mat-dialog-content +> +<mat-toolbar class="form-footer"> + <button mat-dialog-close mat-raised-button class="cancel-button"> + Cancel + </button> + <button + [disabled]="addEditDialogForm.invalid" + color="primary" + mat-raised-button + (click)="addEditCatalog()" + > + {{ + data.dataKey.actionType === "edit" ? "Update catalog" : "Create catalog" + }} + </button> +</mat-toolbar> diff --git a/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.scss b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..a076f5ed028c8b2f6ce5a5bfd86aa2def4cf8025 --- /dev/null +++ b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.scss @@ -0,0 +1,97 @@ +@use "@angular/material" as mat; +@import "../../../../../styles.scss"; + +.form-container { + width: 100%; +} + +.asterix--after:after { + content: "*"; + color: red; +} + +.login-form { + display: flex; + flex-direction: column; + padding: 10px; +} + +.mat-mdc-dialog-content { + max-height: 75vh; + min-width: 800px; +} + +.dialog-header { + background-color: mat.get-color-from-palette($graphene-ui-primary); + height: 39px; + color: #fff; + + h2 { + color: #fff; + font-size: 16px; + font-weight: 600; + margin: 0; + } +} + +.version { + font-size: 12px; + color: #bbb; + padding-left: 5px; +} + +.legend { + width: 100%; + max-width: 100%; + white-space: normal; + font-size: 16px !important; + font-weight: 600; + line-height: 30px !important; + border-bottom: 1px solid #e5e5e5; + margin-bottom: 8px !important; + padding: 5px 8px 5px 0 !important; + color: #671c9d !important; + text-transform: uppercase; + font-family: "Open Sans", sans-serif; +} + +.font600 { + font-weight: 600; +} + +.md-txtarea { + border: 1px solid #d5d5d5; + padding: 7px; + height: 82px; + font-size: 14px; +} + +.cancel-button { + margin-right: auto; +} + +.dialog-title { + display: flex; + align-items: center; + padding: 0; + flex: 1 1 auto; +} + +.flex-column { + display: flex; + flex-direction: column; +} + +.type-access-level-container { + display: flex; + gap: 10px; + width: 100%; +} +.full-width { + width: 100%; +} + +.validation-msgs { + font-size: 11px !important; + font-weight: 600 !important; +} diff --git a/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.spec.ts b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f1585f125bb9a3811a19daa9324e9bc5a39bdc7 --- /dev/null +++ b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddEditCatalogDialogComponent } from './add-edit-catalog-dialog.component'; + +describe('AddEditCatalogDialogComponent', () => { + let component: AddEditCatalogDialogComponent; + let fixture: ComponentFixture<AddEditCatalogDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddEditCatalogDialogComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AddEditCatalogDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.ts b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9cf01acb62a0fd2f8a997e2a65132c6c530ca6f3 --- /dev/null +++ b/src/app/features/dashboard/catalogs/add-edit-catalog-dialog/add-edit-catalog-dialog.component.ts @@ -0,0 +1,129 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { + FormBuilder, + FormGroup, + FormsModule, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectChange, MatSelectModule } from '@angular/material/select'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { AlertService } from 'src/app/core/services/alert.service'; +import { + AccessTypeCode, + AlertType, + CatalogType, + SortOption, +} from 'src/app/shared/models'; + +@Component({ + selector: 'gp-add-edit-catalog-dialog', + standalone: true, + imports: [ + MatDialogModule, + MatButtonModule, + MatToolbarModule, + MatIconModule, + ReactiveFormsModule, + MatFormFieldModule, + MatInputModule, + FormsModule, + MatCheckboxModule, + MatSelectModule, + ], + templateUrl: './add-edit-catalog-dialog.component.html', + styleUrl: './add-edit-catalog-dialog.component.scss', +}) +export class AddEditCatalogDialogComponent implements OnInit { + title!: string; + alertMessage!: string; + addEditDialogForm!: FormGroup; + message: string = ''; + catalogTypes = Object.keys(CatalogType).map((key) => ({ + name: key, + value: CatalogType[key as keyof typeof CatalogType], + })); + accessTypeCodes = Object.keys(AccessTypeCode).map((key) => ({ + name: key, + value: AccessTypeCode[key as keyof typeof AccessTypeCode], + })); + + constructor( + public dialogRef: MatDialogRef<AddEditCatalogDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: any, + private alertService: AlertService, + private formBuilder: FormBuilder, + ) { + this.addEditDialogForm = this.formBuilder.group({ + name: ['', [Validators.required]], + accessTypeCode: ['', [Validators.required]], + type: ['', [Validators.required]], + description: ['', [Validators.required]], + selfPublish: [false, [Validators.required]], + }); + } + + ngOnInit(): void { + console.log('modelData', this.data.dataKey.modelData); + this.title = this.data.dataKey.title; + this.alertMessage = this.data.dataKey.alertMessage; + if (this.data.dataKey.actionType === 'edit') { + this.addEditDialogForm.patchValue({ + name: this.data.dataKey.modelData.name, + }); + this.addEditDialogForm.patchValue({ + accessTypeCode: this.data.dataKey.modelData.accessTypeCode, + }); + this.addEditDialogForm.patchValue({ + type: this.data.dataKey.modelData.type, + }); + this.addEditDialogForm.patchValue({ + description: this.data.dataKey.modelData.description, + }); + this.addEditDialogForm.patchValue({ + selfPublish: this.data.dataKey.modelData.selfPublish, + }); + console.log('form after update', this.addEditDialogForm.value); + } + } + + addEditCatalog() { + if (this.addEditDialogForm.valid) + this.data.dataKey.action(this.addEditDialogForm.value).subscribe({ + next: (res: any) => { + this.alertService.notify( + { + message: + this.data.dataKey.actionType === 'create' + ? 'Catalog created successfully' + : 'Catalog updated successfully', + type: AlertType.Success, + }, + 3000, + ); + this.dialogRef.close(true); + }, + error: (err: any) => { + this.alertService.notify( + { message: 'Operation failed', type: AlertType.Error }, + 3000, + ); + this.dialogRef.close(false); + }, + }); + } + + get controls() { + return this.addEditDialogForm.controls; + } +} diff --git a/src/app/features/dashboard/catalogs/catalogs.component.html b/src/app/features/dashboard/catalogs/catalogs.component.html index 3d7afe0ccd389bb950ac6347d888fbdeac39c5db..1a3cfdcdda9c58a518156a97f97f7e1a6f11c081 100644 --- a/src/app/features/dashboard/catalogs/catalogs.component.html +++ b/src/app/features/dashboard/catalogs/catalogs.component.html @@ -1 +1,134 @@ -<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="controls-container"> + <mat-form-field> + <mat-label>Filter</mat-label> + <input + matInput + (keyup)="applyFilter($event)" + placeholder="Ex. Mia" + #input + /> + </mat-form-field> + <button mat-raised-button color="primary" (click)="onClickAddNewCatalog()"> + Add new catalog + </button> + </div> + <div class="table-container"> + <table + mat-table + [dataSource]="dataSource" + matSort + matSortActive="name" + matSortDisableClear + matSortDirection="asc" + > + <!-- Name Column --> + <ng-container matColumnDef="name"> + <th mat-header-cell *matHeaderCellDef mat-sort-header>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 mat-sort-header>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 mat-sort-header> + 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 mat-sort-header>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 mat-sort-header>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 mat-sort-header>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 mat-sort-header>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"> + <div class="actions-container"> + <button class="custom-icon" (click)="onClickEditCatalog(element)"> + <mat-icon>edit</mat-icon> + </button> + <button + [disabled]="element.solutionCount > 0" + (click)="onClickDeleteCatalog(element)" + class="custom-icon" + > + <mat-icon>delete</mat-icon> + </button> + </div> + </td> + </ng-container> + + <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> + <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> + <tr class="mat-row" *matNoDataRow> + <td class="mat-cell" colspan="4"> + No data matching the filter "{{ input.value }}" + </td> + </tr> + </table> + </div> + <div class="pagination-container"> + <div class="pagination-text"> + <mat-paginator + [pageSizeOptions]="pageSizeOptions" + paginator + 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f893baa384012ea3cd196828eb899f99a1123c51 100644 --- a/src/app/features/dashboard/catalogs/catalogs.component.scss +++ b/src/app/features/dashboard/catalogs/catalogs.component.scss @@ -0,0 +1,162 @@ +@use "@angular/material" as mat; +@import "../../../../styles.scss"; + +.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; +} + +.filter { + display: flex; + justify-content: flex-end; +} + +.custom-icon { + background-color: transparent !important; + border: none !important; + color: mat.get-color-from-palette($graphene-ui-primary); + cursor: pointer; + + mat-icon { + font-size: 16px !important; + } +} + +.actions-container { + display: flex; +} + +.custom-icon[disabled] { + color: #b3b3b3; + border-color: #d3d1d1; + cursor: not-allowed; + background: #efefef; +} + +.controls-container { + display: flex; + gap: 20px; + justify-content: space-between; + align-items: center; +} diff --git a/src/app/features/dashboard/catalogs/catalogs.component.ts b/src/app/features/dashboard/catalogs/catalogs.component.ts index f22e4a187cf7e11f80f78ac8d0921136412d3627..ac3d27d1cb8f8f45b67b76d89632cce6f363e99d 100644 --- a/src/app/features/dashboard/catalogs/catalogs.component.ts +++ b/src/app/features/dashboard/catalogs/catalogs.component.ts @@ -1,13 +1,209 @@ -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 { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { + MatPaginator, + MatPaginatorIntl, + MatPaginatorModule, +} from '@angular/material/paginator'; +import { Catalog } from 'src/app/shared/models'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { AddEditCatalogDialogComponent } from './add-edit-catalog-dialog/add-edit-catalog-dialog.component'; +import { MatIconModule } from '@angular/material/icon'; +import { DeleteUserDialogConfirmationActionComponent } from 'src/app/shared/components/delete-user-dialog-confirmation-action/delete-user-dialog-confirmation-action.component'; +import { MatInputModule } from '@angular/material/input'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatFormFieldModule } from '@angular/material/form-field'; @Component({ selector: 'gp-catalogs', standalone: true, - imports: [CommonModule], + imports: [ + CommonModule, + BreadcrumbNavigationComponent, + HeadlineComponent, + MatTableModule, + MatPaginatorModule, + MatButtonModule, + MatIconModule, + MatInputModule, + MatSortModule, + MatFormFieldModule, + ], templateUrl: './catalogs.component.html', - styleUrl: './catalogs.component.scss' + styleUrl: './catalogs.component.scss', }) -export class CatalogsComponent { +export class CatalogsComponent implements OnInit { + @ViewChild(MatSort) sort!: MatSort; + @ViewChild(MatPaginator) paginator!: MatPaginator; + userId$: Observable<string | undefined>; + displayedColumns: string[] = [ + 'name', + 'type', + 'publisher', + 'selfPublish', + 'accessTypeCode', + 'solutionCount', + 'created', + 'action', + ]; + catalogs!: Catalog[]; + pageSizeOptions = [10, 25, 50, 100]; + siteInstanceName!: string; + selectedCatalog!: Catalog; + dataSource = new MatTableDataSource<Catalog>([]); + + constructor( + private privateCatalogsService: PrivateCatalogsService, + private router: Router, + private browserStorageService: BrowserStorageService, + private paginatorInt: MatPaginatorIntl, + public dialog: MatDialog, + ) { + this.userId$ = this.browserStorageService + .getUserDetails() + .pipe(map((details) => details?.userId)); + paginatorInt.itemsPerPageLabel = 'Showing'; + } + ngOnInit(): void { + this.loadData(); + this.getInstanceName(); + } + + ngAfterViewInit() { + this.dataSource.sort = this.sort; + this.dataSource.paginator = this.paginator; + } + + 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.privateCatalogsService.loadCatalogs(0, res).subscribe({ + next: (res) => { + this.catalogs = res.response_body.content; + this.dataSource.data = res.response_body.content; + }, + error: (error) => {}, + }); + }, + error: (error) => {}, + }); + } + getInstanceName() { + this.privateCatalogsService.getSiteConfig().subscribe({ + next: (res) => { + JSON.parse(res.response_body.configValue).fields.forEach( + (field: any) => { + if (field.name === 'siteInstanceName') { + this.siteInstanceName = field.data; + } + }, + ); + }, + error: (error) => {}, + }); + } + + addNewCatalog(newCatalog: Catalog) { + const catalog: Catalog = { + ...newCatalog, + publisher: this.siteInstanceName, + }; + + return this.privateCatalogsService.createCatalog(catalog); + } + onClickAddNewCatalog() { + const dialogRef: MatDialogRef<AddEditCatalogDialogComponent> = + this.dialog.open(AddEditCatalogDialogComponent, { + data: { + dataKey: { + action: (catalog: Catalog) => this.addNewCatalog(catalog), + actionType: 'create', + }, + }, + }); + + dialogRef.afterClosed().subscribe((result) => { + this.loadData(); + }); + } + + editCatalog(editedCatalog: Catalog) { + const catalog: Catalog = { + ...editedCatalog, + publisher: this.siteInstanceName, + catalogId: this.selectedCatalog.catalogId, + }; + + return this.privateCatalogsService.updateCatalog(catalog); + } + + onClickEditCatalog(catalog: Catalog) { + this.selectedCatalog = catalog; + const dialogRef: MatDialogRef<AddEditCatalogDialogComponent> = + this.dialog.open(AddEditCatalogDialogComponent, { + data: { + dataKey: { + action: (catalog: Catalog) => this.editCatalog(catalog), + actionType: 'edit', + modelData: this.selectedCatalog, + }, + }, + }); + + dialogRef.afterClosed().subscribe((result) => { + this.loadData(); + }); + } + + deleteCatalog(catalog: Catalog) { + return this.privateCatalogsService.deleteCatalog(catalog); + } + + onClickDeleteCatalog(catalog: Catalog) { + this.selectedCatalog = catalog; + const dialogRef: MatDialogRef<DeleteUserDialogConfirmationActionComponent> = + this.dialog.open(DeleteUserDialogConfirmationActionComponent, { + data: { + dataKey: { + title: `Delete Confirmation ${catalog.name}`, + content: `Are you sure that you wish to delete' ${catalog.name}`, + alertMessage: 'Catalog deleted successfully. ', + + action: () => this.deleteCatalog(catalog), + }, + }, + autoFocus: false, + }); + + dialogRef.afterClosed().subscribe((result) => { + this.loadData(); + }); + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + } } diff --git a/src/app/features/marketplace/marketplace.component.html b/src/app/features/marketplace/marketplace.component.html index 1e1ff78f2e2b810295c7c6f5571533b48b872977..b819a41ebd5def2c9e1ad5b1c94e62a198b14e9b 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 d5e101033e7cc7e1c0c1ac741cb920d67b640bec..aef4871a9050163613d64f0204d5c3be79222f18 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 2c09ec786c1ba9fe31ff341f19fbe9be2cc7a913..625914df6e4068ed7768e53084eae1c5788aa605 100644 --- a/src/app/features/marketplace/marketplace.component.ts +++ b/src/app/features/marketplace/marketplace.component.ts @@ -116,7 +116,7 @@ export class MarketplaceComponent { .getPublicCatalogs() .subscribe((catalogs) => { this.catalogIds = catalogs?.map( - (catalog: Catalog) => catalog.catalogId, + (catalog: Catalog) => catalog.catalogId ?? '', ); const requestPayload: PublicSolutionsRequestPayload = { @@ -356,6 +356,7 @@ export class MarketplaceComponent { this.isOnMyFavoriteSelected = false; this.loadPublicSolutions(); } + onMyFavoriteCatalogsClick() { this.isOnMyFavoriteSelected = true; this.isLoading = true; diff --git a/src/app/features/model-details/model-details.component.ts b/src/app/features/model-details/model-details.component.ts index 5b36486b99c61a5701a05d1ca63b77672179168c..b754df78b03ca8ddc5edb7cd8c00ba7e26bcbaf1 100644 --- a/src/app/features/model-details/model-details.component.ts +++ b/src/app/features/model-details/model-details.component.ts @@ -276,7 +276,7 @@ export class ModelDetailsComponent implements OnInit { setSelectedCatalogIdInService(): void { const selectedCatalogId = this.selectedDefaultCatalog.catalogId; - this.sharedDataService.selectedCatalogId = selectedCatalogId; + this.sharedDataService.selectedCatalogId = selectedCatalogId ?? ''; } setVersionIdInService(): void { diff --git a/src/app/shared/components/publish-to-marketplace-page/publish-to-marketplace-page.component.ts b/src/app/shared/components/publish-to-marketplace-page/publish-to-marketplace-page.component.ts index 4653169547bb2c8800107a9e4cec04995637892b..5d849781c2c6c2c9dc684a9463c63df87469850f 100644 --- a/src/app/shared/components/publish-to-marketplace-page/publish-to-marketplace-page.component.ts +++ b/src/app/shared/components/publish-to-marketplace-page/publish-to-marketplace-page.component.ts @@ -390,21 +390,15 @@ export class PublishToMarketplacePageComponent implements OnInit { return updatedTags; } - convertToolkitTypesToCodes( - selectedToolkitTypes: string[], - ): ToolkitTypeCode[] { - return selectedToolkitTypes.map( - (toolkitTypeName) => - toolkitTypeCodeMap[toolkitTypeName] as ToolkitTypeCode, - ); - } - onChangeCatalog(event: MatSelectChange) { this.selectedCatalog = event.value; if (this.selectedCatalog.catalogId !== '') { this.publicSolutionsService - .getSolutionDescription(this.revisionId, this.selectedCatalog.catalogId) + .getSolutionDescription( + this.revisionId, + this.selectedCatalog.catalogId ?? '', + ) .subscribe({ next: (res) => { this.publishToMarketPlaceForm.patchValue({ @@ -421,7 +415,7 @@ export class PublishToMarketplacePageComponent implements OnInit { .getSolutionDocuments( this.solutionId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { @@ -441,7 +435,7 @@ export class PublishToMarketplacePageComponent implements OnInit { this.privateCatalogsService .searchPublishRequestWithCatalogIds( this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { @@ -476,7 +470,7 @@ export class PublishToMarketplacePageComponent implements OnInit { this.selectedCatalog.accessTypeCode, this.userId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { @@ -567,7 +561,7 @@ export class PublishToMarketplacePageComponent implements OnInit { return this.privateCatalogsService.updateSolutionFiles( this.solutionId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', file, ); } @@ -598,7 +592,7 @@ export class PublishToMarketplacePageComponent implements OnInit { .getSolutionDocuments( this.solutionId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { @@ -647,7 +641,7 @@ export class PublishToMarketplacePageComponent implements OnInit { .deleteSolutionsFiles( this.solutionId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', document.documentId, ) .subscribe({ @@ -725,7 +719,7 @@ export class PublishToMarketplacePageComponent implements OnInit { htmlVal, this.solutionId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { @@ -1016,7 +1010,7 @@ export class PublishToMarketplacePageComponent implements OnInit { .getSolutionDocuments( this.solutionId, this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { @@ -1036,7 +1030,7 @@ export class PublishToMarketplacePageComponent implements OnInit { this.privateCatalogsService .searchPublishRequestWithCatalogIds( this.revisionId, - this.selectedCatalog.catalogId, + this.selectedCatalog.catalogId ?? '', ) .subscribe({ next: (res) => { diff --git a/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.html b/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.html index 096c89fc621f5e60019db37f44ae49208e47885c..85f7737cdf37122c03cac188b63fc1b01fa88796 100644 --- a/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.html +++ b/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.html @@ -33,7 +33,7 @@ </mat-form-field> <mat-form-field> <mat-label>Model Id</mat-label> - <input matInput formControlName="modelId " [disabled]="true" /> + <input matInput formControlName="modelId" [disabled]="true" /> </mat-form-field> </div> </form></div diff --git a/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.ts b/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.ts index c365ec93388daf92e308dbfe747d5b12c16589e2..1f1f9f2cc5305f73121546acad432b0102d41803 100644 --- a/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.ts +++ b/src/app/shared/components/update-model-name-dialog/update-model-name-dialog.component.ts @@ -18,6 +18,7 @@ import { MatInputModule } from '@angular/material/input'; import { MatToolbarModule } from '@angular/material/toolbar'; import { AlertService } from 'src/app/core/services/alert.service'; import { AlertType } from '../../models'; +import { MatCheckboxModule } from '@angular/material/checkbox'; @Component({ selector: 'gp-update-model-name-dialog', diff --git a/src/app/shared/models/catalog.model.ts b/src/app/shared/models/catalog.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..60f9c84403e546ad57b736ab2d899947fbebb974 --- /dev/null +++ b/src/app/shared/models/catalog.model.ts @@ -0,0 +1,23 @@ +export interface Catalog { + name: string; + accessTypeCode: string; + catalogId?: string; + created?: string; + description: string; + modified?: string; + origin?: string; + publisher?: string; + selfPublish: boolean; + url: string; + solutionCount?: number; + type: string; +} + +export enum AccessTypeCode { + Public = 'PB', + Restricted = 'RS', +} +export enum CatalogType { + LeaderBoard = 'LEADERBOARD', + Standard = 'STANDARD', +} diff --git a/src/app/shared/models/index.ts b/src/app/shared/models/index.ts index e3fdb9fae0c8c6648282d0768f2fe13fca8703a6..4604e45df05b4ea27d64d745c367f360281d9fd3 100644 --- a/src/app/shared/models/index.ts +++ b/src/app/shared/models/index.ts @@ -7,3 +7,4 @@ export * from './navigation-label.model'; export * from './empty-models.model'; export * from './document.model'; export * from './publish-request.model'; +export * from './catalog.model'; diff --git a/src/app/shared/models/public-solution.model.ts b/src/app/shared/models/public-solution.model.ts index e11be06ec466ddb4e2f6db7fc76070e93f9465d5..3144a6df676ea3aa3616db1b6ef5957ee0cd6f73 100644 --- a/src/app/shared/models/public-solution.model.ts +++ b/src/app/shared/models/public-solution.model.ts @@ -57,19 +57,6 @@ export interface Tag { tag: string; } -export interface Catalog { - name: string; - accessTypeCode: string; - catalogId: string; - created: string; - description: string; - modified: string; - origin: string; - publisher: string; - selfPublish: boolean; - url: string; -} - export interface Revision { revisionId: string; version: string; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index e0a56ed7d55e9f9aa1d58ec3f18c09d3a7f976da..87f4dc1fec574da1a6f1df0291aed272c28e7703 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -2,7 +2,7 @@ export const environment = { // local with session production: false, skipAuth: false, - apiBackendURL: 'https://aiexp-dev.ai4europe.eu', + apiBackendURL: 'https://dev02.ki-lab.nrw', isDebugMode: true, logging: { level: {