Skip to content

Commit b8a2a95

Browse files
committed
feat: enhance routing and SEO optimization across components; add route data retrieval
1 parent 67853ea commit b8a2a95

17 files changed

Lines changed: 195 additions & 137 deletions

File tree

src/app/_services/route.service.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,7 @@ import { Observable } from 'rxjs';
44

55
export class RouteService {
66
public static getRoutes() {
7-
const routes: Routes = [
8-
{
9-
path: '',
10-
pathMatch: 'full',
11-
loadComponent: () => import('../pages/welcome/welcome.component').then((mod) => mod.WelcomeComponent),
12-
data: {
13-
title: 'UtilPlex | Free Online JSON Formatter, SQL Beautifier, YAML Converter',
14-
description: 'Welcome to Util Plex, your go-to online developer tools for various utilities.',
15-
},
16-
},
17-
];
7+
const routes: Routes = [];
188

199
for (const c of RouteService.routeCategories) {
2010
for (const route of c.routes) {
@@ -23,21 +13,32 @@ export class RouteService {
2313
path: route.url.substring(1),
2414
pathMatch: 'full',
2515
loadComponent: route.loadComponent,
26-
data: { title: route.title, description: route.description },
2716
});
2817
} else {
2918
routes.push({
3019
path: route.url.substring(1),
3120
pathMatch: 'full',
3221
component: route.component,
33-
data: { title: route.title, description: route.description },
3422
});
3523
}
3624
}
3725
}
3826
return routes;
3927
}
4028
public static routeCategories: RouteCategory[] = [
29+
{
30+
name: 'Home',
31+
routes: [
32+
{
33+
name: 'Welcome',
34+
title: 'Free Online JSON Formatter, SQL Beautifier, YAML Converter',
35+
url: '/',
36+
description:
37+
'Util Plex is a web-based platform designed to assist developers and coders by providing tools for formatting programming code and converting data formats.',
38+
loadComponent: () => import('../pages/welcome/welcome.component').then((mod) => mod.WelcomeComponent),
39+
},
40+
],
41+
},
4142
{
4243
name: 'Formatters',
4344
routes: [
@@ -126,3 +127,14 @@ export interface UpRoute {
126127
| Observable<Type<unknown> | DefaultExport<Type<unknown>>>
127128
| Promise<Type<unknown> | DefaultExport<Type<unknown>>>;
128129
}
130+
131+
export function getRouteData(name: string): UpRoute | null {
132+
for (const c of RouteService.routeCategories) {
133+
for (const route of c.routes) {
134+
if (route.name === name) {
135+
return route;
136+
}
137+
}
138+
}
139+
return null;
140+
}

src/app/app.component.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Component, inject, signal } from '@angular/core';
2-
import { Meta, Title } from '@angular/platform-browser';
3-
import { ActivationStart, Router, RouterOutlet } from '@angular/router';
2+
import { Router, RouterOutlet } from '@angular/router';
43
import { SideBarComponent } from './nav/side-bar/side-bar.component';
54
@Component({
65
selector: 'app-root',
@@ -11,24 +10,4 @@ import { SideBarComponent } from './nav/side-bar/side-bar.component';
1110
export class AppComponent {
1211
router = inject(Router);
1312
title = signal(null);
14-
private metaService = inject(Meta);
15-
private titleService = inject(Title);
16-
constructor() {
17-
this.router.events.subscribe((event) => {
18-
if (event instanceof ActivationStart) {
19-
const data = event.snapshot.data;
20-
21-
if (data['title']) {
22-
this.titleService.setTitle(data['title']);
23-
this.title.set(data['title']);
24-
}
25-
if (data['description']) {
26-
this.metaService.updateTag({
27-
name: 'description',
28-
content: data['description'],
29-
});
30-
}
31-
}
32-
});
33-
}
3413
}
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Observable } from "rxjs";
1+
import { Observable } from 'rxjs';
22

33
export abstract class ConverterServiceBase {
4-
abstract title: string;
5-
abstract languageFrom: string;
6-
abstract languageTo: string;
7-
abstract convert(input: string): Observable<string>;
8-
}
4+
abstract title: string;
5+
abstract languageFrom: string;
6+
abstract languageTo: string;
7+
abstract routeName: string;
8+
abstract convert(input: string): Observable<string>;
9+
}

src/app/converters/_services/json-to-yaml.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export class JsonToYamlConverter extends ConverterServiceBase {
99
override title = 'Json to Yaml';
1010
override languageFrom = 'json';
1111
override languageTo = 'yaml';
12+
override routeName = 'Json To Yaml';
1213
override convert(input: string): Observable<string> {
1314
if (!input) return of('');
1415
const json = JSON.parse(input);

src/app/converters/c-json-yaml/c-json-yaml.component.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ import { JsonToYamlConverter } from '../_services/json-to-yaml.service';
66
import { ConvertViewComponent } from '../convert-view/convert-view.component';
77

88
@Component({
9-
selector: 'app-c-json-yaml',
10-
templateUrl: './c-json-yaml.component.html',
11-
styleUrls: ['./c-json-yaml.component.scss'],
12-
providers: [{ provide: ConverterServiceBase, useClass: JsonToYamlConverter }],
13-
imports: [CommonModule, FormsModule, ConvertViewComponent]
9+
selector: 'app-c-json-yaml',
10+
templateUrl: './c-json-yaml.component.html',
11+
styleUrls: ['./c-json-yaml.component.scss'],
12+
providers: [{ provide: ConverterServiceBase, useClass: JsonToYamlConverter }],
13+
imports: [CommonModule, FormsModule, ConvertViewComponent],
1414
})
15-
export class CJsonYamlComponent {
16-
17-
}
15+
export class CJsonYamlComponent {}

src/app/converters/convert-view/convert-view.component.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { CommonModule } from '@angular/common';
2-
import { Component, signal } from '@angular/core';
2+
import { Component, inject, signal } from '@angular/core';
33
import { FormsModule } from '@angular/forms';
4+
import { Meta, Title } from '@angular/platform-browser';
45
import { MonacoEditorModule, NGX_MONACO_EDITOR_CONFIG } from 'ngx-monaco-editor-v2';
56
import { from } from 'rxjs';
7+
import { getRouteData } from 'src/app/_services/route.service';
68
import { MonacoEditorConfig } from 'src/app/monaco/monaco-global-config';
79
import { MonacoConfig } from 'src/app/monaco/ng-monaco-config';
810
import { ConverterServiceBase } from '../_services/converter.service';
@@ -15,6 +17,7 @@ import { ConverterServiceBase } from '../_services/converter.service';
1517
providers: [{ provide: NGX_MONACO_EDITOR_CONFIG, useClass: MonacoEditorConfig }],
1618
})
1719
export class ConvertViewComponent {
20+
private convertService = inject(ConverterServiceBase);
1821
inputOptions: MonacoConfig;
1922
outputOptions: MonacoConfig;
2023

@@ -24,15 +27,23 @@ export class ConvertViewComponent {
2427

2528
title = '';
2629

27-
constructor(private convertService: ConverterServiceBase) {
28-
this.title = convertService.title;
30+
private meta = inject(Meta);
31+
private titleService = inject(Title);
32+
constructor() {
33+
var data = getRouteData(this.convertService.routeName);
34+
if (!data) {
35+
throw new Error('Route data not found for welcome');
36+
}
37+
this.titleService.setTitle('UtilPlex |' + data.title);
38+
if (data.description) this.meta.updateTag({ name: 'description', content: data.description });
39+
this.title = this.convertService.title;
2940
this.inputOptions = {
3041
theme: 'dracula',
31-
language: convertService.languageFrom,
42+
language: this.convertService.languageFrom,
3243
} as MonacoConfig;
3344
this.outputOptions = {
3445
theme: 'dracula',
35-
language: convertService.languageTo,
46+
language: this.convertService.languageTo,
3647
readOnly: false,
3748
};
3849
}

src/app/encoders/_services/encoder.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Observable } from 'rxjs';
33

44
export abstract class EncoderServiceBase {
55
abstract title: string;
6+
abstract routeName: string;
67
abstract options: any;
78
abstract optionsChanged: EventEmitter<any>;
89
abstract convert(input: string, encode: boolean): Observable<string>;

src/app/encoders/base-64-encoder/base-64-encoder.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { EncoderServiceBase } from '../_services/encoder.service';
55
@Injectable()
66
export class Base64Encoder extends EncoderServiceBase {
77
override title = 'Base64 Encoder';
8+
override routeName = 'Base64';
89
override options: Base64EncodingOptions = new Base64EncodingOptions();
910
override optionsChanged = new EventEmitter<Base64EncodingOptions>();
1011
constructor() {

src/app/encoders/encoder-view/encoder-view.component.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { CommonModule } from '@angular/common';
2-
import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';
2+
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
33
import { FormsModule } from '@angular/forms';
44
import { MonacoEditorModule, NGX_MONACO_EDITOR_CONFIG } from 'ngx-monaco-editor-v2';
55
import { from } from 'rxjs';
66

77
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
8+
import { Meta, Title } from '@angular/platform-browser';
9+
import { getRouteData } from 'src/app/_services/route.service';
810
import { MonacoEditorConfig } from 'src/app/monaco/monaco-global-config';
911
import { MonacoConfig } from 'src/app/monaco/ng-monaco-config';
1012
import { SwitchComponent } from '../../components/switch/switch.component';
@@ -59,6 +61,7 @@ import { EncoderServiceBase } from '../_services/encoder.service';
5961
changeDetection: ChangeDetectionStrategy.OnPush,
6062
})
6163
export class EncoderViewComponent {
64+
private convertService = inject(EncoderServiceBase);
6265
inputOptions: MonacoConfig;
6366
outputOptions: MonacoConfig;
6467

@@ -69,9 +72,16 @@ export class EncoderViewComponent {
6972
isEncode = signal<boolean>(true);
7073
modeLabel = computed(() => (this.isEncode() ? 'Encode' : 'Decode'));
7174
title = '';
72-
73-
constructor(private convertService: EncoderServiceBase) {
74-
this.title = convertService.title;
75+
private meta = inject(Meta);
76+
private titleService = inject(Title);
77+
constructor() {
78+
var data = getRouteData(this.convertService.routeName);
79+
if (!data) {
80+
throw new Error('Route data not found for welcome');
81+
}
82+
this.titleService.setTitle('UtilPlex |' + data.title);
83+
if (data.description) this.meta.updateTag({ name: 'description', content: data.description });
84+
this.title = this.convertService.title;
7585
toObservable(this.isEncode)
7686
.pipe(takeUntilDestroyed())
7787
.subscribe(() => {
@@ -87,7 +97,7 @@ export class EncoderViewComponent {
8797
language: '',
8898
readOnly: true,
8999
};
90-
convertService.optionsChanged.subscribe(() => {
100+
this.convertService.optionsChanged.subscribe(() => {
91101
this.inputChanged(this.inputCode());
92102
});
93103
}
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
import { Injectable } from "@angular/core";
2-
import * as prettier from "prettier";
3-
import * as postcss from "prettier/plugins/postcss";
4-
import { Observable, from } from "rxjs";
5-
import { FormatViewService } from "./sql-format.service";
1+
import { Injectable } from '@angular/core';
2+
import * as prettier from 'prettier';
3+
import * as postcss from 'prettier/plugins/postcss';
4+
import { Observable, from } from 'rxjs';
5+
import { FormatViewService } from './sql-format.service';
66

77
@Injectable()
88
export class CssFormatService extends FormatViewService {
9-
override title = 'Css Formatter';
10-
override language = 'css';
11-
override format(input: string): Observable<string> {
12-
return from(prettier.format(input, { parser: "css", plugins: [postcss] }));
13-
}
9+
override title = 'Css Formatter';
10+
override language = 'css';
11+
override routeName = 'CSS';
12+
override format(input: string): Observable<string> {
13+
return from(prettier.format(input, { parser: 'css', plugins: [postcss] }));
14+
}
1415
}

0 commit comments

Comments
 (0)