{ "version": 3, "sources": ["src/app/sidenav/_components/side-nav-item/side-nav-item.component.ts", "src/app/sidenav/_components/side-nav-item/side-nav-item.component.html", "src/app/_pipes/setting-fragment.pipe.ts", "src/app/sidenav/preference-nav/preference-nav.component.ts", "src/app/sidenav/preference-nav/preference-nav.component.html"], "sourcesContent": ["import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, Input, OnInit} from '@angular/core';\nimport {NavigationEnd, Router, RouterLink} from '@angular/router';\nimport {filter, map, tap} from 'rxjs';\nimport {NavService} from 'src/app/_services/nav.service';\nimport {takeUntilDestroyed} from \"@angular/core/rxjs-interop\";\nimport {AsyncPipe, NgClass, NgOptimizedImage, NgTemplateOutlet} from \"@angular/common\";\nimport {ImageComponent} from \"../../../shared/image/image.component\";\nimport {Breakpoint, UtilityService} from \"../../../shared/_services/utility.service\";\n\n\n@Component({\n selector: 'app-side-nav-item',\n standalone: true,\n imports: [RouterLink, NgOptimizedImage, ImageComponent, NgTemplateOutlet, NgClass, AsyncPipe],\n templateUrl: './side-nav-item.component.html',\n styleUrls: ['./side-nav-item.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SideNavItemComponent implements OnInit {\n private readonly destroyRef = inject(DestroyRef);\n private readonly router = inject(Router);\n private readonly cdRef = inject(ChangeDetectorRef);\n protected readonly navService = inject(NavService);\n protected readonly utilityService = inject(UtilityService);\n\n /**\n * Id for automatic scrolling to.\n */\n @Input() id: string | null = null;\n\n /**\n * Icon to display next to item. ie) 'fa-home'\n */\n @Input() icon: string = '';\n @Input() imageUrl: string | null = '';\n /**\n * Removes all the space around the icon area\n */\n @Input() noIcon: boolean = false;\n /**\n * Text for the item\n */\n @Input() title: string = '';\n\n /**\n * If a link should be generated when clicked. By default (undefined), no link will be generated\n */\n @Input() link: string | undefined;\n /**\n * If external, link will be used as full href and rel will be applied\n */\n @Input() external: boolean = false;\n /**\n * If using a link, then you can pass optional queryParameters\n */\n @Input() queryParams: any | undefined = undefined;\n /**\n * If using a lin, then you can pass optional fragment to append to the end\n */\n @Input() fragment: string | undefined = undefined;\n /**\n * Optional count to pass in that will show as a red badge on the side, indicating some action needs to be taken\n */\n @Input() badgeCount: number | null = -1;\n\n\n @Input() comparisonMethod: 'startsWith' | 'equals' = 'equals';\n\n\n\n highlighted = false;\n\n constructor() {\n this.router.events\n .pipe(\n filter(event => event instanceof NavigationEnd),\n takeUntilDestroyed(this.destroyRef),\n map(evt => evt as NavigationEnd),\n tap((evt: NavigationEnd) => this.triggerHighlightCheck(evt.url)),\n tap(_ => this.collapseNavIfApplicable())\n ).subscribe();\n }\n\n ngOnInit(): void {\n setTimeout(() => {\n this.triggerHighlightCheck(this.router.url);\n }, 100);\n }\n\n triggerHighlightCheck(routeUrl: string) {\n const [url, queryParams] = routeUrl.split('?');\n const [page, fragment = ''] = url.split('#');\n\n this.updateHighlight(page, queryParams, url.includes('#') ? fragment : undefined);\n }\n\n\n updateHighlight(page: string, queryParams?: string, fragment?: string) {\n if (this.link === undefined) {\n this.highlighted = false;\n this.cdRef.markForCheck();\n return;\n }\n\n if (!page.endsWith('/') && !queryParams && this.fragment === undefined && queryParams === undefined) {\n page = page + '/';\n }\n\n let fragmentEqual = false;\n if (fragment === this.fragment) {\n fragmentEqual = true;\n }\n if (this.fragment === '' && fragment === undefined) { // This is the case where we load a fragment of nothing and browser removes the #\n fragmentEqual = true;\n }\n\n const queryParamsEqual = this.queryParams === queryParams;\n\n if (this.comparisonMethod === 'equals' && page === this.link && fragmentEqual && queryParamsEqual) {\n this.highlighted = true;\n this.cdRef.markForCheck();\n return;\n }\n\n if (this.comparisonMethod === 'startsWith' && page.startsWith(this.link)) {\n if (queryParams && queryParams === this.queryParams && fragmentEqual) {\n this.highlighted = true;\n this.cdRef.markForCheck();\n return;\n }\n\n this.highlighted = true;\n this.cdRef.markForCheck();\n return;\n }\n\n this.highlighted = false;\n this.cdRef.markForCheck();\n }\n\n openLink() {\n this.collapseNavIfApplicable();\n\n if (Object.keys(this.queryParams).length !== 0) {\n this.router.navigateByUrl(this.link + '?' + this.queryParams);\n return;\n } else if (this.fragment) {\n this.router.navigateByUrl(this.link + '#' + this.fragment);\n return;\n }\n\n this.router.navigateByUrl(this.link!);\n }\n\n // If on mobile, automatically collapse the side nav after making a selection\n collapseNavIfApplicable() {\n if (this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet) {\n this.navService.collapseSideNav(true);\n }\n }\n\n}\n", "@if (link === undefined || link.length === 0) {\n