Skip to content

Commit 4dc22e2

Browse files
committed
feat: open meshstack url also considers to remove anything after '#', and query correctly
* refactor template gallery view * fix eslint rules, remove deprecated ones and pin typescript eslint to version 7
1 parent 4158a39 commit 4dc22e2

File tree

17 files changed

+226
-121
lines changed

17 files changed

+226
-121
lines changed

website/.eslintrc.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
}
4141
],
4242
"@angular-eslint/no-output-native": "warn",
43-
"@angular-eslint/no-host-metadata-property": "warn",
4443
// @typescript-eslint
4544
"@typescript-eslint/explicit-member-accessibility": [
4645
"error",

website/package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
"@fortawesome/fontawesome-free": "^6.7.2",
2929
"@ng-bootstrap/ng-bootstrap": "^18.0.0",
3030
"@popperjs/core": "^2.11.8",
31+
"@typescript-eslint/eslint-plugin": "7",
32+
"@typescript-eslint/parser": "7",
3133
"bootstrap": "^5.3.3",
3234
"eslint-plugin-import": "^2.31.0",
3335
"eslint-plugin-jsdoc": "^50.6.8",
@@ -49,16 +51,12 @@
4951
"@types/express": "^4.17.17",
5052
"@types/jasmine": "~5.1.0",
5153
"@types/node": "20",
52-
"@typescript-eslint/eslint-plugin": "^8.28.0",
53-
"@typescript-eslint/parser": "^8.28.0",
5454
"@typescript-eslint/types": "^8.0.0",
5555
"@typescript-eslint/utils": "^8.0.0",
5656
"angular-eslint": "19.2.1",
5757
"eslint": "^8.57.0",
5858
"eslint-import-resolver-typescript": "^3.6.1",
59-
"eslint-plugin-import": "2.25.2",
6059
"eslint-plugin-jasmine": "^4.2.2",
61-
"eslint-plugin-jsdoc": "^43.0.5",
6260
"eslint-plugin-local-rules": "^3.0.2",
6361
"eslint-plugin-prefer-arrow": "1.2.2",
6462
"jasmine-core": "~5.6.0",

website/src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { HeaderComponent } from 'app/shared/header/header.component';
88
import { FooterComponent } from './shared/footer';
99

1010
@Component({
11-
selector: 'app-root',
11+
selector: 'mst-root',
1212
imports: [CommonModule, RouterOutlet, HeaderComponent, FooterComponent, NgbModule],
1313
templateUrl: './app.component.html',
1414
standalone: true

website/src/app/app.config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@ import { provideRouter } from '@angular/router';
66
import { routes } from './app.routes';
77

88
export const appConfig: ApplicationConfig = {
9-
providers: [provideHttpClient(withFetch()), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideClientHydration(withEventReplay())]
9+
providers: [
10+
provideHttpClient(withFetch()),
11+
provideZoneChangeDetection({ eventCoalescing: true }),
12+
provideRouter(routes),
13+
provideClientHydration(withEventReplay())
14+
]
1015
};

website/src/app/core/template.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface Template {
88
githubUrls: {
99
ssh: string;
1010
https: string;
11-
},
11+
};
1212
supportedPlatforms: PlatformType[];
1313
}
1414

website/src/app/features/template-details/import-dialog/import-dialog.component.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class ImportDialogComponent implements OnInit {
2929
private fb: FormBuilder
3030
) { }
3131

32-
ngOnInit(): void {
32+
public ngOnInit(): void {
3333
this.form = this.fb.group({
3434
meshStackUrl: this.fb.nonNullable.control('', [Validators.required, Validators.pattern(/^(https?:\/\/).*/)]),
3535
});
@@ -47,10 +47,16 @@ export class ImportDialogComponent implements OnInit {
4747

4848
private getSanitizedMeshStackUrl(): string {
4949
let meshStackUrl = this.form.controls.meshStackUrl.value;
50-
if (meshStackUrl.endsWith('/')) {
51-
meshStackUrl = meshStackUrl.slice(0, -1);
52-
}
50+
const hashIndex = meshStackUrl.indexOf('#');
5351

54-
return meshStackUrl;
52+
if (hashIndex !== -1) {
53+
meshStackUrl = meshStackUrl.substring(0, hashIndex);
54+
}
55+
56+
if (meshStackUrl.endsWith('/')) {
57+
meshStackUrl = meshStackUrl.slice(0, -1);
58+
}
59+
60+
return meshStackUrl;
5561
}
5662
}

website/src/app/features/template-details/template-details.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ <h2 class="fw-bold h4">
3939
<a [href]="template.source" target="_blank" rel="noopener noreferrer" class="mr-3 flex-grow-1">
4040
{{ template.source }}
4141
</a>
42-
<button (click)="copyToClipboard(template.source)" class="btn btn-light btn-sm">
42+
<button type="button" (click)="copyToClipboard(template.source)" class="btn btn-light btn-sm">
4343
<i *ngIf="copyLabel === 'Copy'" class="fas fa-copy"></i>
4444
<i *ngIf="copyLabel === 'Copied'" class="fa-solid fa-check"></i>
4545
{{ copyLabel }}
@@ -79,7 +79,7 @@ <h3 class="fw-bold h6">Option 2: Copy the Files into your own Repository</h3>
7979

8080
<div class="pt-5 d-flex justify-content-end">
8181
<a href="#" class="btn btn-outline-primary me-2">Go Back</a>
82-
<button class="btn btn-primary" (click)="open(template)">Add to meshStack</button>
82+
<button type="button" class="btn btn-primary" (click)="open(template)">Add to meshStack</button>
8383
</div>
8484
</div>
8585
</div>

website/src/app/features/template-details/template-details.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class TemplateDetailsComponent implements OnInit, OnDestroy {
7878
}
7979

8080
public open(template: TemplateDetailsVm) {
81-
const regex = /modules\/[^\/]+\/[^\/]+/;
81+
const regex = /modules\/[^/]+\/[^/]+/;
8282
const match = template.source.match(regex);
8383
const modulePath = match ? match[0] : '';
8484

website/src/app/features/template-gallery/template-gallery.component.ts

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { TemplateService } from 'app/shared/template';
1919
standalone: true
2020
})
2121
export class TemplateGalleryComponent implements OnInit, OnDestroy {
22-
2322
public templates$!: Observable<Card[]>;
2423

2524
public searchForm!: FormGroup;
@@ -36,63 +35,62 @@ export class TemplateGalleryComponent implements OnInit, OnDestroy {
3635
private fb: FormBuilder,
3736
private templateService: TemplateService,
3837
private platformLogoService: PlatformLogoService
39-
) { }
38+
) {}
4039

4140
public ngOnInit(): void {
41+
this.initializeSearchForm();
42+
this.subscribeToRouteParams();
43+
}
44+
45+
public ngOnDestroy(): void {
46+
this.paramSubscription.unsubscribe();
47+
}
48+
49+
public onSearch(): void {
50+
const searchTerm = this.searchForm.value.searchTerm;
51+
this.templates$ = this.getTemplatesWithLogos(
52+
this.templateService.search(searchTerm)
53+
);
54+
55+
this.isSearch = !!searchTerm;
56+
this.router.navigate(['/all']);
57+
}
58+
59+
private initializeSearchForm(): void {
4260
this.searchForm = this.fb.group({
4361
searchTerm: ['']
4462
});
63+
}
4564

65+
private subscribeToRouteParams(): void {
4666
this.paramSubscription = this.route.paramMap.subscribe(params => {
4767
const type = params.get('type') ?? 'all';
48-
4968
const templateObs$ = this.templateService.filterTemplatesByPlatformType(type as PlatformType);
50-
this.logos$ = this.platformLogoService.getLogoUrls();
51-
this.templates$ = forkJoin({
52-
templates: templateObs$,
53-
logos: this.logos$
54-
})
55-
.pipe(
56-
tap(() => this.isSearch = false),
57-
map(({ templates, logos }) => templates.map(item => ({
58-
cardLogo: item.logo,
59-
title: item.name,
60-
description: item.description,
61-
detailsRoute: `/template/${item.id}`,
62-
supportedPlatforms: item.supportedPlatforms.map(platform => ({ platformType: platform, imageUrl: logos[item.platformType] ?? null }))
63-
}))
64-
),
6569

66-
);
70+
this.logos$ = this.platformLogoService.getLogoUrls();
71+
this.templates$ = this.getTemplatesWithLogos(templateObs$);
6772
});
6873
}
6974

70-
public ngOnDestroy(): void {
71-
this.paramSubscription.unsubscribe();
72-
}
73-
74-
public onSearch(): void {
75-
const searchTerm = this.searchForm.value.searchTerm;
76-
this.templates$ = forkJoin({
77-
templates: this.templateService.search(searchTerm),
75+
private getTemplatesWithLogos(templateObs$: Observable<any>): Observable<Card[]> {
76+
return forkJoin({
77+
templates: templateObs$,
7878
logos: this.logos$
7979
})
8080
.pipe(
81-
tap(() => {
82-
this.isSearch = !!searchTerm
83-
}),
84-
map(({ templates, logos }) => templates.map(item => ({
85-
cardLogo: item.logo,
86-
title: item.name,
87-
description: item.description,
88-
detailsRoute: `/template/${item.id}`,
89-
supportedPlatforms: item.supportedPlatforms.map(platform => ({ platformType: platform, imageUrl: logos[item.platformType] ?? null }))
90-
}))
81+
tap(() => (this.isSearch = false)),
82+
map(({ templates, logos }) =>
83+
templates.map(item => ({
84+
cardLogo: item.logo,
85+
title: item.name,
86+
description: item.description,
87+
detailsRoute: `/template/${item.id}`,
88+
supportedPlatforms: item.supportedPlatforms.map(platform => ({
89+
platformType: platform,
90+
imageUrl: logos[item.platformType] ?? null
91+
}))
92+
}))
9193
)
9294
);
93-
94-
this.router.navigate(
95-
['/all']
96-
);
9795
}
9896
}

website/src/app/shared/card/card.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@ import { Card } from './card';
1313
})
1414
export class CardComponent {
1515
@Input()
16-
public card!:Card;
16+
public card!: Card;
1717

1818
constructor(private router: Router) {}
1919

2020
public goToDetails() {
21-
console.log('Navigating to details route', this.card.detailsRoute);
2221
this.router.navigate([this.card.detailsRoute]);
2322
}
2423
}

0 commit comments

Comments
 (0)