Posted by bolatah on 7/10/2024, 9:25:22 AM
import { Component, OnInit, AfterViewInit, AfterViewChecked, ElementRef } from "@angular/core";
import { ActivatedRoute, Router, NavigationEnd } from "@angular/router";
import { DocumentationService } from "./documentation.service";
import { filter, delay } from "rxjs/operators";
interface Subtitle {
title: string;
content: string;
}
interface Item {
name: string;
subtitles: Subtitle[];
}
@Component({
selector: "app-documentation",
templateUrl: "./documentation.component.html",
styleUrls: ["./documentation.component.scss"],
})
export class DocumentationComponent implements OnInit , AfterViewInit{
items: Item[] = [];
selectedItem: Item | null = null;
selectedSubtitle: Subtitle | null = null;
pendingFragment: string | null = null;
constructor(
private documentationService: DocumentationService,
private route: ActivatedRoute,
private router: Router,
private elementRef: ElementRef
) {
this.items = this.documentationService.getItems();
}
ngOnInit() {
// Handle route params
this.route.paramMap.subscribe((params) => {
const itemName = params.get("itemName");
if (itemName) {
this.selectItemByName(itemName);
} else if (this.items.length > 0) {
const firstItem = this.items[0];
this.selectItemByName(firstItem.name);
}
});
// Handle fragment changes
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
delay(1000), // Add delay to allow the DOM to update
filter(() => !!this.selectedSubtitle) // Ensure selectedSubtitle is defined
)
.subscribe(() => {
const fragment = this.route.snapshot.fragment;
this.scrollToFragment(fragment);
});
}
ngAfterViewInit(): void {
}
sanitizeForURL(str: string): string {
return str.replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase();
}
selectItemByName(name: string) {
this.selectedItem =
this.items.find((item) => this.sanitizeForURL(item.name) === this.sanitizeForURL(name)) || null;
if (this.selectedItem) {
const firstSubtitle = this.selectedItem.subtitles[0];
this.selectedSubtitle = firstSubtitle || null;
this.updateUrlParams();
}
}
selectSubtitleByTitle(title: string) {
if (this.selectedItem) {
this.selectedSubtitle =
this.selectedItem.subtitles.find(
(subtitle) => this.sanitizeForURL(subtitle.title) === this.sanitizeForURL(title)
) || null;
const sanitizedId = this.sanitizeForURL(title);
this.updateUrlParams(sanitizedId);
}
}
updateUrlParams(fragment?: string) {
if (this.selectedItem) {
const itemName = this.sanitizeForURL(this.selectedItem.name);
this.router.navigate(["/documentation", itemName], {
fragment: fragment ? fragment : null,
});
}
}
scrollToFragment(fragment: string) {
const element = document.getElementById(fragment);
if (element) {
element.scrollIntoView();
}
}
}
<mat-drawer-container class="drawer-container" autosize>
<!-- Left Sidebar -->
<mat-drawer #leftDrawer mode="side" opened class="left-sidenav">
<div class="center-content">
<mat-nav-list>
<a mat-list-item *ngFor="let item of items"
(click)="selectItemByName(item.name)"
[class.selected]="item === selectedItem">
{{ item.name }}
</a>
</mat-nav-list>
</div>
</mat-drawer>
<!-- Main Content -->
<div class="main-content">
<div class="center-content">
<mat-toolbar color="primary">
{{ selectedItem?.name }}
</mat-toolbar>
<div class="page-content" #content>
<ng-container *ngIf="selectedItem">
<div *ngFor="let subtitle of selectedItem.subtitles">
<!-- Apply the sanitized ID to the subtitle -->
<h2 [id]="sanitizeForURL(subtitle.title)">
{{ subtitle.title }}
</h2>
<p>{{ subtitle.content }}</p>
</div>
</ng-container>
</div>
</div>
</div>
<!-- Right Sidebar -->
<mat-drawer #rightDrawer mode="side" opened position="end" class="right-sidenav">
<div class="center-content">
<h2><strong>On This Page</strong></h2>
<mat-nav-list *ngFor="let subtitle of selectedItem?.subtitles" >
<a mat-list-item
(click)="selectSubtitleByTitle(subtitle.title)"
[class.selected]="subtitle === selectedSubtitle">
{{ subtitle.title }}
</a>
</mat-nav-list>
</div>
</mat-drawer>
</mat-drawer-container>