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
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ repos:
- id: terraform_docs
args:
- --args=--config=.terraform-docs.yml
files: ^modules/[^/]+/[^/]+/.+\.tf$ # Only run on .tf files in modules/*/*/ directories
# Only run terraform_docs on .tf files inside 'backplane' or 'buildingblock' folders
files: ^modules/[^/]+/[^/]+/(backplane|buildingblock)/.+\.tf$
- id: terraform_fmt
- id: terragrunt_fmt
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand Down
17 changes: 13 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ function findPlatforms(): Platform[] {
const platformDir: string = path.join(repoRoot, dir.name);
const platformLogo = getPlatformLogoOrThrow(platformDir, dir.name);
const platformReadme = getPlatformReadmeOrThrow(platformDir);
const { name, description, content } = extractReadmeFrontMatter(platformReadme);
const { name, description, category, content } = extractReadmeFrontMatter(platformReadme);
const terraformSnippet = getTerraformSnippet(platformDir);

return {
platformType: dir.name,
name,
description,
category,
logo: platformLogo,
readme: content,
terraformSnippet
Expand All @@ -81,11 +82,11 @@ function getPlatformReadmeOrThrow(platformDir: string) {
try {
return fs.readFileSync(path.join(platformDir, "README.md"), "utf-8");
} catch {
throw new Error('Platform README.md not found. Each platform should have a README.md file.');
throw new Error(`Platform README.md not found for ${platformDir}. Each platform should have a README.md file.`);
}
}

function extractReadmeFrontMatter(platformReadme: string): { name: string; description: string; content: string } {
function extractReadmeFrontMatter(platformReadme: string): { name: string; description: string; category?: string; content: string } {
const { data, content } = matter(platformReadme);

const name = data.name;
Expand All @@ -98,10 +99,13 @@ function extractReadmeFrontMatter(platformReadme: string): { name: string; descr
throw new Error('Property "description" is missing in the front matter of the platform README.md. Each platform README.md should have a description defined in the front matter.');
}

const category = data.category;

return {
name,
description,
content
content,
category
}
}

Expand Down Expand Up @@ -169,12 +173,16 @@ function parseReadme(filePath) {
? getBuildingBlockFolderUrl(backplaneDir)
: null;

const terraformSnippetDir = path.join(buildingBlockDir, "..");
const terraformSnippet = getTerraformSnippet(terraformSnippetDir);

return {
id,
platformType: platform,
logo: buildingBlockLogoPath,
buildingBlockUrl,
backplaneUrl,
terraformSnippet,
...data,
howToUse: extractSection(/## How to Use([\s\S]*?)(##|$)/),
resources: parseTable(body.match(/## Resources([\s\S]*)/)),
Expand Down Expand Up @@ -224,5 +232,6 @@ export interface Platform {
description: string;
logo: string;
readme: string;
category?: string;
terraformSnippet?: string;
}
6 changes: 6 additions & 0 deletions modules/meshstack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: meshStack
description: meshStack is a cloud management platform that provides a unified interface for managing and governing cloud environments
---


1 change: 1 addition & 0 deletions website/src/app/core/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface Template {
buildingBlockUrl: string;
backplaneUrl: string | null;
supportedPlatforms: string[];
terraformSnippet?: string;
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { CommonModule } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { Dialog } from '@angular/cdk/dialog';
import { Observable, Subscription, map, switchMap } from 'rxjs';
import { Observable, Subscription, map, switchMap, of } from 'rxjs';

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 { CardComponent } from 'app/shared/card';
import { TemplateService } from 'app/shared/template';
import { extractLogoColor } from 'app/shared/util/logo-color.util';

import { ImportDialogComponent } from './import-dialog/import-dialog.component';

const DEFAULT_HEADER_BG_COLOR = 'rgba(203,213,225,0.3)';

interface TemplateDetailsVm {
imageUrl: string | null;
name: string;
Expand All @@ -19,11 +23,12 @@ interface TemplateDetailsVm {
howToUse: string;
source: string;
backplaneUrl: string | null;
terraformSnippet?: string;
}

@Component({
selector: 'mst-template-details',
imports: [CommonModule, BreadcrumbComponent],
imports: [CommonModule, BreadcrumbComponent, CardComponent, RouterLink],
templateUrl: './template-details.component.html',
styleUrl: './template-details.component.scss',
standalone: true
Expand All @@ -37,6 +42,10 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {

public copyLabel = 'Copy';

public copiedTerraform = false;

public headerBgColor$!: Observable<string>;

private routeSubscription!: Subscription;

constructor(
Expand All @@ -54,6 +63,17 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {

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

// Reactive header background color
this.headerBgColor$ = this.template$.pipe(
switchMap(template =>
template && template.imageUrl
? extractLogoColor(template.imageUrl).pipe(
map(color => color || DEFAULT_HEADER_BG_COLOR)
)
: of(DEFAULT_HEADER_BG_COLOR)
)
);
}

public ngOnDestroy(): void {
Expand All @@ -65,6 +85,16 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {
.then(() => this.updateCopyLabel());
}

public copyTerraform(value: string): void {
navigator.clipboard.writeText(value)
.then(() => {
this.copiedTerraform = true;
setTimeout(() => {
this.copiedTerraform = false;
}, 2000);
});
}

public open(template: TemplateDetailsVm): void {
const modulePath = this.extractModulePath(template.source);

Expand Down Expand Up @@ -102,7 +132,8 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {
...template,
imageUrl: template.logo,
source: template.buildingBlockUrl,
howToUse: template.howToUse
howToUse: template.howToUse,
terraformSnippet: template.terraformSnippet
}))
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<div class="mb-12">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
<div *ngFor="let card of cards">
<div *ngFor="let card of sortedCards">
<mst-card [routePath]="card.routePath"
[label]="card.title"
[logoSourceImage]="card.cardLogo"
(backgroundColorExtracted)="onBackgroundColorExtracted(card.title, $event)">
<div class="p-4 flex flex-col justify-between min-h-[9rem]" card-body>
<div class="p-4 flex flex-col min-h-[10rem] h-full" card-body>
<!-- Title with Logo - Left Aligned -->
<div class="flex items-center gap-2 mb-2">
<div class="w-10 h-10 flex-shrink-0 flex items-center justify-center rounded-lg transition-colors"
<div class="flex items-center gap-2 mb-1">
<div class="w-9 h-9 flex-shrink-0 flex items-center justify-center rounded-lg transition-colors"
[ngStyle]="{'background-color': logoBackgroundColors[card.title] || 'rgba(203, 213, 225, 0.3)'}">
<img *ngIf="card.cardLogo; else unknownLogo"
[src]="card.cardLogo"
[alt]="card.title"
class="w-6 h-6 object-contain" />
class="w-5 h-5 object-contain" />
<ng-template #unknownLogo>
<img src="assets/meshstack-logo.png" alt="Unknown Logo" class="w-6 h-6 object-contain" />
<img src="assets/meshstack-logo.png" alt="Unknown Logo" class="w-5 h-5 object-contain" />
</ng-template>
</div>
<h5 class="font-semibold text-slate-900 mb-0 text-base leading-tight">
Expand All @@ -24,7 +24,7 @@ <h5 class="font-semibold text-slate-900 mb-0 text-base leading-tight">
</div>

<!-- Description -->
<p *ngIf="card.description" class="text-slate-600 text-sm line-clamp-2 mb-2 leading-snug">
<p *ngIf="card.description" class="text-slate-600 text-sm line-clamp-2 mb-1 leading-snug max-h-10 overflow-hidden text-ellipsis">
{{ card.description }}
</p>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@ export class PlatformCardsComponent {
@Input()
public cards!: PlatformCard[];

/**
* Define your custom order here. Use the property that uniquely identifies the platform (e.g., title or id).
* Example: ['Azure', 'AWS', 'GCP']
*/
public customOrder: string[] = ['Microsoft Azure', 'Amazon Web Services', 'Google Cloud Platform', 'Azure Kubernetes Service', 'STACKIT']; // <-- customize as needed

/**
* Returns the cards sorted by customOrder, with others following in original order.
*/
public get sortedCards(): PlatformCard[] {
console.log(this.cards);
if (!this.cards) return [];
const order = this.customOrder;
return [
...this.cards.filter(card => order.includes(card.title)).sort((a, b) => order.indexOf(a.title) - order.indexOf(b.title)),
...this.cards.filter(card => !order.includes(card.title))
];
}

public logoBackgroundColors: { [key: string]: string } = {};

public onBackgroundColorExtracted(cardTitle: string, color: string): void {
Expand Down
Loading