Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions website/src/app/features/platform-view/platform-view.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<div class="pt-5 ps-5 pe-5" >
<div class="pb-5" *ngIf="platform$ | async as platform">
<div class="pt-5 ps-5 pe-5" *ngIf="platform$ | async as platform">
<ng-container *ngIf="breadcrumbs$ | async as breadcrumbs">
<mst-breadcrumb [breadcrumbs]="breadcrumbs"></mst-breadcrumb>
</ng-container>
<div class="pt-5 pb-5">
<mst-card [label]="platform.title" [borderColorSourceImage]="platform.logo">
<div class="card-body d-flex" card-body>
<mst-logo-circle [title]="platform.title" [sourceImage]="platform.logo" [size]="'md'"></mst-logo-circle>
Expand All @@ -10,19 +13,19 @@ <h5 class="ms-3 card-title fw-bold align-self-center">
</mst-card>
</div>

<h2>Platform building block definitions</h2>
These building block definitions provide pre-configured Terraform modules for automating common cloud tasks
<ng-container *ngIf="templates$ | async as templates">
<h2 class="fw-bold">{{ platform.title }} building block definitions</h2>
<p class="mt-2 mb-5" *ngIf="templates.length; else noTemplates">These <b>{{ platform.title }} building block
definitions</b> provide pre-configured Terraform modules
for automating common cloud tasks</p>
<ng-template #noTemplates>
<p class="mt-2">No building block definitions</p>
</ng-template>

<div class="row mt-4">
<ng-container *ngIf="templates$ | async as templates">
<ng-container *ngIf="templates.length > 0; else noTemplates">
<div class="col-sm-3 mb-3" *ngFor="let template of templates">
<mst-definition-card [card]="template"></mst-definition-card>
</div>
</ng-container>
<ng-template #noTemplates>
<p class="p-2">No building block definitions</p>
</ng-template>
</ng-container>
</div>
<div class="row mt-4">
<div class="col-sm-3 mb-3" *ngFor="let template of templates">
<mst-definition-card [card]="template"></mst-definition-card>
</div>
</div>
</ng-container>
</div>
14 changes: 11 additions & 3 deletions website/src/app/features/platform-view/platform-view.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { CommonModule } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subscription, forkJoin, map } from 'rxjs';
import { Observable, Subscription, forkJoin, map, switchMap } from 'rxjs';

import { PlatformType } from 'app/core';
import { BreadcrumbComponent } from 'app/shared/breadcrumb';
import { BreadCrumbService } from 'app/shared/breadcrumb/bread-crumb.service';
import { BreadcrumbItem } from 'app/shared/breadcrumb/breadcrumb';
import { CardComponent } from 'app/shared/card';
import { DefinitionCard } from 'app/shared/definition-card/definition-card';
import { DefinitionCardComponent } from 'app/shared/definition-card/definition-card.component';
Expand All @@ -18,14 +21,16 @@ interface PlatformVM {

@Component({
selector: 'mst-platform-view',
imports: [CommonModule, DefinitionCardComponent, CardComponent, LogoCircleComponent],
imports: [CommonModule, DefinitionCardComponent, CardComponent, LogoCircleComponent, BreadcrumbComponent],
templateUrl: './platform-view.component.html',
styleUrl: './platform-view.component.scss',
standalone: true
})
export class PlatformViewComponent implements OnInit, OnDestroy {
public platform$!: Observable<PlatformVM>;

public breadcrumbs$!: Observable<BreadcrumbItem[]>;

public templates$!: Observable<DefinitionCard[]>;

private paramSubscription!: Subscription;
Expand All @@ -36,11 +41,14 @@ export class PlatformViewComponent implements OnInit, OnDestroy {
private router: Router,
private route: ActivatedRoute,
private templateService: TemplateService,
private platformLogoService: PlatformService
private platformLogoService: PlatformService,
private breadcrumbService: BreadCrumbService
) { }

public ngOnInit(): void {
this.subscribeToRouteParams();
this.breadcrumbs$ = this.route.paramMap.pipe(switchMap(x => this.breadcrumbService.getBreadcrumbs(x)));

}

public ngOnDestroy(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,16 @@
<ng-container *ngIf="breadcrumbs$ | async as breadcrumbs">
<mst-breadcrumb [breadcrumbs]="breadcrumbs"></mst-breadcrumb>
</ng-container>

<div class="pt-5">
<div class="d-flex">
<div class="ps-2 pe-2">
<img
*ngIf="template.imageUrl; else unknownLogo"
class="logo"
[src]="template.imageUrl"
[alt]="template.platformType"
/>
<div class="row ">
<div class="col-12 col-md-auto text-center mb-3 mb-md-0">
<img *ngIf="template.imageUrl; else unknownLogo" class="logo img-fluid" [src]="template.imageUrl"
[alt]="template.platformType" />
<ng-template #unknownLogo>
<img src="assets/meshstack-logo.png" class="logo" alt="Unknown Logo" />
<img src="assets/meshstack-logo.png" class="logo img-fluid" alt="Unknown Logo" />
</ng-template>
</div>
<div class="ps-5">
<div class="col-12 col-md">
<h1 class="fw-bold h3">
<span class="pe-4">{{ template.name }}</span>
<span class="badge bg-secondary fw-bold">Building Block</span>
Expand All @@ -32,8 +27,8 @@ <h2 class="fw-bold h4">
<i class="fa-solid fa-code pe-2"></i>
Source
</h2>
<div class="d-flex align-items-center p-2 bg-light border rounded shadow-sm">
<a [href]="template.source" target="_blank" rel="noopener noreferrer" class="mr-3 flex-grow-1">
<div class="d-flex flex-column flex-md-row align-items-start align-items-md-center p-2 bg-light border rounded shadow-sm">
<a [href]="template.source" target="_blank" rel="noopener noreferrer" class="mb-2 mb-md-0 me-md-3 flex-grow-1">
{{ template.source }}
</a>
<button type="button" (click)="copyToClipboard(template.source)" class="btn btn-light btn-sm">
Expand Down Expand Up @@ -74,8 +69,10 @@ <h3 class="fw-bold h6">Option 2: Copy the Files into your own Repository</h3>
</div>
</div>

<div class="pt-5 d-flex justify-content-end">
<a href="#" class="btn btn-outline-primary me-2">Go Back</a>
<div class="pt-5 d-flex flex-column flex-md-row justify-content-end">
<ng-container *ngIf="backPath$ | async as backPath">
<a [href]="backPath" class="btn btn-outline-primary mb-2 mb-md-0 me-md-2">Go Back</a>
</ng-container>
<button type="button" class="btn btn-primary" (click)="open(template)">Add to meshStack</button>
</div>
</div>
Expand All @@ -84,4 +81,4 @@ <h3 class="fw-bold h6">Option 2: Copy the Files into your own Repository</h3>
</div>
</ng-container>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { CommonModule } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Observable, Subscription, map, of, switchMap } from 'rxjs';
import { Observable, Subscription, map, switchMap } from 'rxjs';

import { PlatformType } from 'app/core';
import { BreadCrumbService } from 'app/shared/breadcrumb/bread-crumb.service';
import { BreadcrumbItem } from 'app/shared/breadcrumb/breadcrumb';
import { BreadcrumbComponent } from 'app/shared/breadcrumb/breadcrumb.component';
import { PlatformService } from 'app/shared/platform-logo';
import { TemplateService } from 'app/shared/template';

import { ImportDialogComponent } from './import-dialog/import-dialog.component';
Expand All @@ -33,20 +33,27 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {

public breadcrumbs$!: Observable<BreadcrumbItem[]>;

public backPath$!: Observable<string>;

public copyLabel = 'Copy';

private routeSubscription!: Subscription;

constructor(
private route: ActivatedRoute,
private templateService: TemplateService,
private platformService: PlatformService,
private modalService: NgbModal
private modalService: NgbModal,
private breadcrumbService: BreadCrumbService
) { }

public ngOnInit(): void {
this.initializeBreadcrumbs();
this.initializeTemplate();
this.breadcrumbs$ = this.route.paramMap.pipe(switchMap(x => this.breadcrumbService.getBreadcrumbs(x)));
this.backPath$ = this.breadcrumbs$.pipe(map(breadcrumbs => {
const secondLastBreadcrumb = breadcrumbs[breadcrumbs.length - 2].routePath;

return secondLastBreadcrumb ? secondLastBreadcrumb : '/';
}));
}

public ngOnDestroy(): void {
Expand Down Expand Up @@ -80,56 +87,6 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {
return match ? match[0] : '';
}

private initializeBreadcrumbs(): void {
this.breadcrumbs$ = this.route.paramMap.pipe(
switchMap(params => {
const id = params.get('id');
const type = params.get('type');

if (!id) {
throw new Error('Template ID is required');
}

return this.getPlatformData(type)
.pipe(
switchMap((platformName) =>
this.templateService.getTemplateById(id)
.pipe(
map(template => this.buildBreadcrumbs(template.name, platformName, type))
)
)
);
})
);
}

private getPlatformData(type: string | null): Observable<string|null> {
if (!type) {
return of(null);
}

return this.platformService.getPlatformData(type)
.pipe(
map(x => x.name)
);
}

private buildBreadcrumbs(
templateName: string,
platformName: string | null,
type: string | null,
): BreadcrumbItem[] {
const breadcrumbs: BreadcrumbItem[] = [{ label: 'Overview', routePath: '/' }];

if (platformName) {
breadcrumbs.push({ label: platformName, routePath: `/platforms/${type}` });
}

breadcrumbs.push({ label: templateName, routePath: '' });

return breadcrumbs;
}

private initializeTemplate(): void {
this.routeSubscription = this.route.paramMap.subscribe(params => {
const id = params.get('id');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './platform-cards.component';
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';

import { NavigationComponent } from './navigation.component';
import { PlatformCardsComponent } from './platform-cards.component';


describe('NavigationComponent', () => {
let component: NavigationComponent;
let fixture: ComponentFixture<NavigationComponent>;
let component: PlatformCardsComponent;
let fixture: ComponentFixture<PlatformCardsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NavigationComponent, RouterTestingModule]
imports: [PlatformCardsComponent, RouterTestingModule]
})
.compileComponents();

fixture = TestBed.createComponent(NavigationComponent);
fixture = TestBed.createComponent(PlatformCardsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { BehaviorSubject, Observable, combineLatest, map, tap } from 'rxjs';

import { CardComponent } from 'app/shared/card';
import { LogoCircleComponent } from 'app/shared/logo-circle/logo-circle.component';
import { PlatformService } from 'app/shared/platform-logo';

interface PlatformCard {
cardLogo: string | null;
title: string;
routePath: string;
}

@Component({
selector: 'mst-platform-cards',
imports: [CommonModule, CardComponent, LogoCircleComponent],
templateUrl: './platform-cards.component.html',
styleUrl: './platform-cards.component.scss',
standalone: true
})
export class PlatformCardsComponent implements OnInit {
@Input()
public set searchTerm(value: string) {
this.searchTermSubject.next(value);
}

@Output()
public resultCount: EventEmitter<number> = new EventEmitter<number>();

public cards$!: Observable<PlatformCard[]>;

private searchTermSubject = new BehaviorSubject<string>('');

private searchTerm$ = this.searchTermSubject.asObservable();

constructor(private readonly platformService: PlatformService) { }

public ngOnInit(): void {
const platformCards$ = this.platformService.getAllPlatformData()
.pipe(map((logos) => this.mapLogosToPlatformCards(logos)));

this.cards$ = combineLatest([platformCards$, this.searchTerm$])
.pipe(
map(([cards, searchTerm]) => this.filterCardsBySearchTerm(cards, searchTerm)),
tap(cards => this.resultCount.emit(cards.length))
);
}

private mapLogosToPlatformCards(logos: Record<string, { name: string; logo: string }>): PlatformCard[] {
return Object.entries(logos)
.map(([key, platform]) =>
this.createPlatformCard(platform.name, platform.logo, `/platforms/${key}`)
);
}

private createPlatformCard(title: string, logoUrl: string, routePath: string): PlatformCard {
return { cardLogo: logoUrl, title, routePath };
}

private filterCardsBySearchTerm(cards: PlatformCard[], searchTerm: string): PlatformCard[] {
const searchTermLower = searchTerm.toLowerCase();

return cards.filter(card => card.title.toLowerCase()
.includes(searchTermLower));
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
<div class="pt-5 ps-5 pe-5">
<ng-container *ngIf="!isSearch">
<mst-navigation></mst-navigation>
<div class="pt-5 pb-4">
<h2>All building block definitions</h2>
These are pre-configured Terraform modules for automating common cloud tasks across AWS, Azure, GCP, and custom
cloud platforms, enabling rapid and consistent infrastructure provisioning and management
</div>
</ng-container>
<div class="pb-2" *ngIf="isSearch">
<mst-breadcrumb [breadcrumbs]="breadcrumbs"></mst-breadcrumb>
</div>
<mst-platform-cards [searchTerm]="searchTerm" (resultCount)="updateCount($event)"></mst-platform-cards>
<div class="pt-5 pb-4">
<h2>All building block definitions</h2>
<p *ngIf="!isSearch">These are pre-configured Terraform modules for automating common cloud tasks across AWS, Azure,
GCP, and custom
cloud platforms, enabling rapid and consistent infrastructure provisioning and management </p>
</div>


<div class="row">
<ng-container *ngIf="templates$ | async as templates">
<p class="pb-2" *ngIf="isSearch && templates.length">{{ templates.length }} building block definitions found</p>
<ng-container *ngIf="templates.length > 0; else noTemplates">
<div class="col-sm-3 mb-3" *ngFor="let template of templates">
<mst-definition-card [card]="template"></mst-definition-card>
</div>
</ng-container>
<ng-template #noTemplates>
<p class="p-2">No building block definitions found</p>
<p class="p-2">No building block definitions</p>
</ng-template>
</ng-container>
</div>
</div>
</div>
Loading
Loading