From c9f9f0430d9bd413f29fed83ee9d1f0d1451bb81 Mon Sep 17 00:00:00 2001 From: Le Date: Tue, 15 Apr 2025 19:31:51 +0200 Subject: [PATCH 1/2] feat: capture original meshStack URL when user visits hub from meshStack CU-86c2pmn6q --- website/src/app/app.component.ts | 2 +- .../import-dialog/import-dialog.component.ts | 5 ++- .../template-gallery.component.ts | 34 +++++++++++++++---- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/website/src/app/app.component.ts b/website/src/app/app.component.ts index 6c54f9f..9080335 100644 --- a/website/src/app/app.component.ts +++ b/website/src/app/app.component.ts @@ -18,7 +18,7 @@ export class AppComponent { this.loadPlausible(); } - loadPlausible() { + public loadPlausible() { // Ensure we are in the browser (not SSR) if (isPlatformBrowser(this.platformId)) { const script = document.createElement('script'); diff --git a/website/src/app/features/template-details/import-dialog/import-dialog.component.ts b/website/src/app/features/template-details/import-dialog/import-dialog.component.ts index 09e4cc6..43a088f 100644 --- a/website/src/app/features/template-details/import-dialog/import-dialog.component.ts +++ b/website/src/app/features/template-details/import-dialog/import-dialog.component.ts @@ -31,8 +31,11 @@ export class ImportDialogComponent implements OnInit { ) { } public ngOnInit(): void { + const originUrl = sessionStorage.getItem('referrerUrl') ?? ''; this.form = this.fb.group({ - meshStackUrl: this.fb.nonNullable.control('', [Validators.required, Validators.pattern(/^(https?:\/\/).*/)]), + meshStackUrl: this.fb.nonNullable.control( + originUrl, [Validators.required, Validators.pattern(/^(https?:\/\/).*/)] + ), }); } diff --git a/website/src/app/features/template-gallery/template-gallery.component.ts b/website/src/app/features/template-gallery/template-gallery.component.ts index d734ff6..c89cabf 100644 --- a/website/src/app/features/template-gallery/template-gallery.component.ts +++ b/website/src/app/features/template-gallery/template-gallery.component.ts @@ -1,5 +1,5 @@ -import { CommonModule } from '@angular/common'; -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { CommonModule, isPlatformBrowser } from '@angular/common'; +import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable, Subscription, forkJoin, map, tap } from 'rxjs'; @@ -34,24 +34,24 @@ export class TemplateGalleryComponent implements OnInit, OnDestroy { private route: ActivatedRoute, private fb: FormBuilder, private templateService: TemplateService, - private platformLogoService: PlatformLogoService + private platformLogoService: PlatformLogoService, + @Inject(PLATFORM_ID) private platformId: Object ) {} public ngOnInit(): void { this.initializeSearchForm(); this.subscribeToRouteParams(); + this.setupMessageListener(); } public ngOnDestroy(): void { this.paramSubscription.unsubscribe(); + this.removeMessageListener(); } public onSearch(): void { const searchTerm = this.searchForm.value.searchTerm; - this.templates$ = this.getTemplatesWithLogos( - this.templateService.search(searchTerm) - ); - + this.templates$ = this.getTemplatesWithLogos(this.templateService.search(searchTerm)); this.isSearch = !!searchTerm; this.router.navigate(['/all']); } @@ -93,4 +93,24 @@ export class TemplateGalleryComponent implements OnInit, OnDestroy { ) ); } + + private setupMessageListener(): void { + if (isPlatformBrowser(this.platformId)) { + window.addEventListener('message', this.handleMessage.bind(this), false); + } + } + + private removeMessageListener(): void { + if (isPlatformBrowser(this.platformId)) { + window.removeEventListener('message', this.handleMessage.bind(this), false); + } + } + + private handleMessage(event: MessageEvent): void { + const originUrl = event.data.originUrl; + + if (typeof originUrl === 'string') { + sessionStorage.setItem('referrerUrl', originUrl); + } + } } From df3290d50e617cb64d064091955d3fe7250564d1 Mon Sep 17 00:00:00 2001 From: Le Date: Wed, 16 Apr 2025 14:54:55 +0200 Subject: [PATCH 2/2] feat: store referrerUrl to localstorage * move logic to listen to message into app component --- website/src/app/app.component.ts | 43 +++++++++++++++---- .../import-dialog/import-dialog.component.ts | 2 +- .../template-gallery.component.ts | 28 ++---------- .../app/shared/header/header.component.html | 26 ++++++++--- 4 files changed, 57 insertions(+), 42 deletions(-) diff --git a/website/src/app/app.component.ts b/website/src/app/app.component.ts index 9080335..a85aeaa 100644 --- a/website/src/app/app.component.ts +++ b/website/src/app/app.component.ts @@ -1,5 +1,5 @@ import { CommonModule, isPlatformBrowser } from '@angular/common'; -import { Component, Inject, PLATFORM_ID } from '@angular/core'; +import { Component, Inject, OnDestroy, PLATFORM_ID } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @@ -13,19 +13,44 @@ import { FooterComponent } from './shared/footer'; templateUrl: './app.component.html', standalone: true }) -export class AppComponent { +export class AppComponent implements OnDestroy{ constructor(@Inject(PLATFORM_ID) private platformId: Object) { - this.loadPlausible(); + // Ensure we are in the browser (not SSR) + if (isPlatformBrowser(this.platformId)) { + this.loadPlausible(); + this.setupMessageListener(); + } + } + + public ngOnDestroy(): void { + this.removeMessageListener(); } public loadPlausible() { - // Ensure we are in the browser (not SSR) + const script = document.createElement('script'); + script.src = 'https://plausible.cluster.dev.meshcloud.io/js/script.js'; + script.setAttribute('data-domain', 'hub.meshcloud.io'); + script.defer = true; + document.head.appendChild(script); + } + + private setupMessageListener(): void { if (isPlatformBrowser(this.platformId)) { - const script = document.createElement('script'); - script.src = 'https://plausible.cluster.dev.meshcloud.io/js/script.js'; - script.setAttribute('data-domain', 'hub.meshcloud.io'); - script.defer = true; - document.head.appendChild(script); + window.addEventListener('message', this.handleMessage.bind(this), false); + } + } + + private removeMessageListener(): void { + if (isPlatformBrowser(this.platformId)) { + window.removeEventListener('message', this.handleMessage.bind(this), false); + } + } + + private handleMessage(event: MessageEvent): void { + const originUrl = event.data.originUrl; + + if (typeof originUrl === 'string') { + localStorage.setItem('referrerUrl', originUrl); } } } diff --git a/website/src/app/features/template-details/import-dialog/import-dialog.component.ts b/website/src/app/features/template-details/import-dialog/import-dialog.component.ts index 43a088f..6583fbe 100644 --- a/website/src/app/features/template-details/import-dialog/import-dialog.component.ts +++ b/website/src/app/features/template-details/import-dialog/import-dialog.component.ts @@ -31,7 +31,7 @@ export class ImportDialogComponent implements OnInit { ) { } public ngOnInit(): void { - const originUrl = sessionStorage.getItem('referrerUrl') ?? ''; + const originUrl = localStorage.getItem('referrerUrl') ?? ''; this.form = this.fb.group({ meshStackUrl: this.fb.nonNullable.control( originUrl, [Validators.required, Validators.pattern(/^(https?:\/\/).*/)] diff --git a/website/src/app/features/template-gallery/template-gallery.component.ts b/website/src/app/features/template-gallery/template-gallery.component.ts index c89cabf..38567e2 100644 --- a/website/src/app/features/template-gallery/template-gallery.component.ts +++ b/website/src/app/features/template-gallery/template-gallery.component.ts @@ -1,5 +1,5 @@ -import { CommonModule, isPlatformBrowser } from '@angular/common'; -import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable, Subscription, forkJoin, map, tap } from 'rxjs'; @@ -34,19 +34,16 @@ export class TemplateGalleryComponent implements OnInit, OnDestroy { private route: ActivatedRoute, private fb: FormBuilder, private templateService: TemplateService, - private platformLogoService: PlatformLogoService, - @Inject(PLATFORM_ID) private platformId: Object + private platformLogoService: PlatformLogoService ) {} public ngOnInit(): void { this.initializeSearchForm(); this.subscribeToRouteParams(); - this.setupMessageListener(); } public ngOnDestroy(): void { this.paramSubscription.unsubscribe(); - this.removeMessageListener(); } public onSearch(): void { @@ -94,23 +91,4 @@ export class TemplateGalleryComponent implements OnInit, OnDestroy { ); } - private setupMessageListener(): void { - if (isPlatformBrowser(this.platformId)) { - window.addEventListener('message', this.handleMessage.bind(this), false); - } - } - - private removeMessageListener(): void { - if (isPlatformBrowser(this.platformId)) { - window.removeEventListener('message', this.handleMessage.bind(this), false); - } - } - - private handleMessage(event: MessageEvent): void { - const originUrl = event.data.originUrl; - - if (typeof originUrl === 'string') { - sessionStorage.setItem('referrerUrl', originUrl); - } - } } diff --git a/website/src/app/shared/header/header.component.html b/website/src/app/shared/header/header.component.html index fd87707..a292964 100644 --- a/website/src/app/shared/header/header.component.html +++ b/website/src/app/shared/header/header.component.html @@ -6,11 +6,23 @@

Welcome to meshStack Hub!

-
-

- Find ready-to-use Terraform modules to integrate with meshStack. Automate cloud governance or roll out commonly - used cloud resources. Built for scalability and security, these modules help you build your platform faster! - Explore the collection below and get started! -

+
+
+

+ Find ready-to-use Terraform modules to integrate with meshStack. Automate cloud governance or roll out commonly + used cloud resources. Built for scalability and security, these modules help you build your platform faster! + Explore the collection below and get started! +

+
+ + Eggcelent! 🥚
Now copy & paste me!
+ You've cracked the clue wide open LOL + And this my friend, is an example of *what not to do* when hiding content. + #Accessibility Talk + You've discovered what was meant to hide, + a div transparent just like we tried. + Now for your next, look up hiiiigh + where muscles pull and ceiling tiles lie. +
- + \ No newline at end of file