components/content/content.component.ts
Main content for application.
Angular material expansion panels with links to swagger pages of all services.
AfterViewInit
selector | app-content |
imports |
MatSidenavContainer
MatSidenav
NgClass
MatNavList
MatListItem
MatListItemLine
MatButton
MatIcon
MatSidenavContent
MatCard
MatCardHeader
MatCardTitle
MatIconButton
MatCardSubtitle
MatCardContent
MatDivider
RouterLink
AsyncPipe
|
templateUrl | ./content.component.html |
styleUrl | ./content.component.scss |
Properties |
Methods |
|
constructor(templateService: NshmpTemplateService, el: ElementRef
|
|||||||||||||||||||||
Defined in components/content/content.component.ts:236
|
|||||||||||||||||||||
Parameters :
|
Private addActive | ||||||||
addActive(cardEl: Element)
|
||||||||
Defined in components/content/content.component.ts:349
|
||||||||
Add
Parameters :
Returns :
void
|
Private checkUrl |
checkUrl()
|
Defined in components/content/content.component.ts:357
|
Check URL parameters.
Returns :
void
|
ngAfterViewInit |
ngAfterViewInit()
|
Defined in components/content/content.component.ts:247
|
Returns :
void
|
onExpansionPanelClosed |
onExpansionPanelClosed()
|
Defined in components/content/content.component.ts:255
|
Reset navigation parameters.
Returns :
void
|
onExpansionPanelOpen | ||||||||
onExpansionPanelOpen(serviceGroup: ServiceGroup)
|
||||||||
Defined in components/content/content.component.ts:267
|
||||||||
Set URL query parameters.
Parameters :
Returns :
void
|
onLinkIconClick | ||||||||
onLinkIconClick(serviceGroup: string)
|
||||||||
Defined in components/content/content.component.ts:287
|
||||||||
Update query parameters on URL on link click.
Parameters :
Returns :
void
|
onNavClick | ||||||||
onNavClick(serviceGroup: string)
|
||||||||
Defined in components/content/content.component.ts:304
|
||||||||
Scroll to expansion panel and set URL parameters.
Parameters :
Returns :
void
|
onScroll |
onScroll()
|
Defined in components/content/content.component.ts:320
|
Handle on scroll on scroll event. Highlight navigation if scrolling over expansion panel.
Returns :
void
|
Private resetActive |
resetActive()
|
Defined in components/content/content.component.ts:370
|
Remove
Returns :
void
|
toServiceId | ||||||||
toServiceId(service: ServiceConfig)
|
||||||||
Defined in components/content/content.component.ts:340
|
||||||||
Convert label to id.
Parameters :
Returns :
string
|
cardTriggerHeight |
Type : number
|
Default value : 100
|
Defined in components/content/content.component.ts:72
|
Trigger height |
dynamicHazardServices$ |
Type : Observable<ServiceConfig[]>
|
Default value : this.hazardService
.dynamicNshmService$(
`${this.nshmpHazWs.url}${this.nshmpHazWs.services.nshms}`,
)
.pipe(
map(usage => {
return usage.response.map(nshm => ({
contextPath: nshm.url.split('.gov').pop(),
label: nshm.label,
swaggerEndPoint: this.nshmpHazWs.services.curveServices.swagger,
url: nshm.url,
}));
}),
)
|
Defined in components/content/content.component.ts:75
|
Dynamic hazard services |
nshmpHazWs |
Default value : environment.webServices.nshmpHazWs
|
Defined in components/content/content.component.ts:68
|
nshmpWsStatic |
Default value : environment.webServices.nshmpWsStatic
|
Defined in components/content/content.component.ts:69
|
serviceGroups |
Type : ServiceGroup[]
|
Default value : [
// Dynamic hazard caluclations
{
applicationsUsedIn: [
APPS.hazard.disagg,
APPS.hazard.dynamic,
APPS.source.mfd,
APPS.source.rateAndProbability,
],
id: ServiceGroupId.NSHMP_HAZ,
images: [
{
darkModeImage: 'dynamic-hazard-dark-mode.webp',
image: 'dynamic-hazard.webp',
},
{
darkModeImage: 'disagg-dark-mode.jpeg',
image: 'disagg.jpeg',
},
],
services$: this.dynamicHazardServices$,
subtitle: 'Hazard, Disaggregation, Rate, and Probabilities of a NSHM',
title: 'NSHM Dynamic Hazard Calculations',
},
// Data services
{
applicationsUsedIn: [...gmmApps(), APPS.source.data],
id: ServiceGroupId.NSHMP_WS,
images: [
{
darkModeImage: 'gmm-spectra-dark-mode.webp',
image: 'gmm-spectra.webp',
},
{
image: 'fault-sections.jpeg',
},
],
services$: of([
{
...environment.webServices.data,
swaggerEndPoint: environment.webServices.data.services.swagger,
},
]),
subtitle: 'Ground Motion Models, Faults Sections, and GPS Data',
title: 'Data Services',
},
// Static hazard services
{
applicationsUsedIn: [APPS.hazard.static],
id: ServiceGroupId.NSHMP_WS_STATIC_HAZARD,
images: [
{
darkModeImage: 'static-hazard-dark-mode.webp',
image: 'static-hazard.webp',
},
{
darkModeImage: 'static-hazard-spectra-dark-mode.webp',
image: 'static-hazard-spectra.webp',
},
],
services$: this.staticHazardServices$,
subtitle: 'Pre-Computed and Published Hazard Curves',
title: 'NSHM Static Hazard Curve Services',
},
// RTGM services
{
applicationsUsedIn: [apps().designMaps.rtgm],
id: ServiceGroupId.RTGM,
images: [
{
darkModeImage: 'rtgm-derivative-dark-mode.webp',
image: 'rtgm-derivative.webp',
},
{
darkModeImage: 'rtgm-integral-dark-mode.webp',
image: 'rtgm-integral.webp',
},
],
services$: of([
{
...environment.webServices.rtgm,
swaggerEndPoint: environment.webServices.rtgm.services.swagger,
},
]),
subtitle: 'RTGM from hazard curves',
title: 'Risk-Targeted Ground Motion Service',
},
// NCM services
{
applicationsUsedIn: [],
id: ServiceGroupId.NCM,
images: [
{
image: 'ncm-geophys.png',
},
{
image: 'ncm-temp.png',
},
],
services$: of([
{
...environment.webServices.ncm,
swaggerEndPoint: environment.webServices.ncm.services.swagger,
},
]),
subtitle: 'Geologic, Geophysical, Mineral, and Temperature Profiles',
title: 'National Crustal Model Services',
},
// AASHTO 2023 services
{
applicationsUsedIn: [],
id: ServiceGroupId.AASHTO_2023,
images: [{image: 'aashto-logo.jpeg'}],
services$: of([
{
...environment.webServices.aashto2023,
swaggerEndPoint: environment.webServices.aashto2023.services.swagger,
},
]),
subtitle: 'Risk-Targeted Desgin Response Spectra for 2023 Edition',
title: 'AASHTO 2023 Services',
},
]
|
Defined in components/content/content.component.ts:114
|
List of web services. |
sidenavCollapsed |
Default value : false
|
Defined in components/content/content.component.ts:109
|
Whether sidenav is collapsed |
staticHazardServices$ |
Type : Observable<ServiceConfig[]>
|
Default value : this.hazardService
.staticNshmService$(
`${this.nshmpWsStatic.url}${this.nshmpWsStatic.services.nshms}`,
)
.pipe(
map(usage => {
const nshmpWsStatic = environment.webServices.nshmpWsStatic;
return usage.response.map(nshm => ({
contextPath: nshm.url.split('.gov').pop(),
label: nshm.label,
swaggerEndPoint: nshmpWsStatic.services.curveServices.swagger,
url: nshm.url,
}));
}),
)
|
Defined in components/content/content.component.ts:91
|
Static hazard services |
Public templateService |
Type : NshmpTemplateService
|
Defined in components/content/content.component.ts:239
|
import {AsyncPipe, NgClass} from '@angular/common';
import {AfterViewInit, Component, ElementRef} from '@angular/core';
import {MatButton, MatIconButton} from '@angular/material/button';
import {
MatCard,
MatCardContent,
MatCardHeader,
MatCardSubtitle,
MatCardTitle,
} from '@angular/material/card';
import {MatDivider} from '@angular/material/divider';
import {MatIcon} from '@angular/material/icon';
import {MatListItem, MatListItemLine, MatNavList} from '@angular/material/list';
import {
MatSidenav,
MatSidenavContainer,
MatSidenavContent,
} from '@angular/material/sidenav';
import {ActivatedRoute, Router, RouterLink} from '@angular/router';
import {HazardService} from '@ghsc/nshmp-lib-ng/hazard';
import {NshmpService} from '@ghsc/nshmp-lib-ng/nshmp';
import {NshmpTemplateService} from '@ghsc/nshmp-template';
import {environment} from 'projects/nshmp-apps/src/environments/environment';
import {apps} from 'projects/nshmp-apps/src/shared/utils/applications.utils';
import {gmmApps} from 'projects/nshmp-apps/src/shared/utils/navigation.utils';
import {map, Observable, of} from 'rxjs';
import {QueryParameters} from '../../models/query-parameters.model';
import {
ServiceConfig,
ServiceGroup,
ServiceGroupId,
} from '../../models/service.model';
const APPS = apps();
/**
* Main content for application.
*
* Angular material expansion panels with links to swagger pages of all services.
*/
@Component({
imports: [
MatSidenavContainer,
MatSidenav,
NgClass,
MatNavList,
MatListItem,
MatListItemLine,
MatButton,
MatIcon,
MatSidenavContent,
MatCard,
MatCardHeader,
MatCardTitle,
MatIconButton,
MatCardSubtitle,
MatCardContent,
MatDivider,
RouterLink,
AsyncPipe,
],
selector: 'app-content',
styleUrl: './content.component.scss',
templateUrl: './content.component.html',
})
export class ContentComponent implements AfterViewInit {
nshmpHazWs = environment.webServices.nshmpHazWs;
nshmpWsStatic = environment.webServices.nshmpWsStatic;
/** Trigger height */
cardTriggerHeight = 100;
/** Dynamic hazard services */
dynamicHazardServices$: Observable<ServiceConfig[]> = this.hazardService
.dynamicNshmService$(
`${this.nshmpHazWs.url}${this.nshmpHazWs.services.nshms}`,
)
.pipe(
map(usage => {
return usage.response.map(nshm => ({
contextPath: nshm.url.split('.gov').pop(),
label: nshm.label,
swaggerEndPoint: this.nshmpHazWs.services.curveServices.swagger,
url: nshm.url,
}));
}),
);
/** Static hazard services */
staticHazardServices$: Observable<ServiceConfig[]> = this.hazardService
.staticNshmService$(
`${this.nshmpWsStatic.url}${this.nshmpWsStatic.services.nshms}`,
)
.pipe(
map(usage => {
const nshmpWsStatic = environment.webServices.nshmpWsStatic;
return usage.response.map(nshm => ({
contextPath: nshm.url.split('.gov').pop(),
label: nshm.label,
swaggerEndPoint: nshmpWsStatic.services.curveServices.swagger,
url: nshm.url,
}));
}),
);
/** Whether sidenav is collapsed */
sidenavCollapsed = false;
/**
* List of web services.
*/
serviceGroups: ServiceGroup[] = [
// Dynamic hazard caluclations
{
applicationsUsedIn: [
APPS.hazard.disagg,
APPS.hazard.dynamic,
APPS.source.mfd,
APPS.source.rateAndProbability,
],
id: ServiceGroupId.NSHMP_HAZ,
images: [
{
darkModeImage: 'dynamic-hazard-dark-mode.webp',
image: 'dynamic-hazard.webp',
},
{
darkModeImage: 'disagg-dark-mode.jpeg',
image: 'disagg.jpeg',
},
],
services$: this.dynamicHazardServices$,
subtitle: 'Hazard, Disaggregation, Rate, and Probabilities of a NSHM',
title: 'NSHM Dynamic Hazard Calculations',
},
// Data services
{
applicationsUsedIn: [...gmmApps(), APPS.source.data],
id: ServiceGroupId.NSHMP_WS,
images: [
{
darkModeImage: 'gmm-spectra-dark-mode.webp',
image: 'gmm-spectra.webp',
},
{
image: 'fault-sections.jpeg',
},
],
services$: of([
{
...environment.webServices.data,
swaggerEndPoint: environment.webServices.data.services.swagger,
},
]),
subtitle: 'Ground Motion Models, Faults Sections, and GPS Data',
title: 'Data Services',
},
// Static hazard services
{
applicationsUsedIn: [APPS.hazard.static],
id: ServiceGroupId.NSHMP_WS_STATIC_HAZARD,
images: [
{
darkModeImage: 'static-hazard-dark-mode.webp',
image: 'static-hazard.webp',
},
{
darkModeImage: 'static-hazard-spectra-dark-mode.webp',
image: 'static-hazard-spectra.webp',
},
],
services$: this.staticHazardServices$,
subtitle: 'Pre-Computed and Published Hazard Curves',
title: 'NSHM Static Hazard Curve Services',
},
// RTGM services
{
applicationsUsedIn: [apps().designMaps.rtgm],
id: ServiceGroupId.RTGM,
images: [
{
darkModeImage: 'rtgm-derivative-dark-mode.webp',
image: 'rtgm-derivative.webp',
},
{
darkModeImage: 'rtgm-integral-dark-mode.webp',
image: 'rtgm-integral.webp',
},
],
services$: of([
{
...environment.webServices.rtgm,
swaggerEndPoint: environment.webServices.rtgm.services.swagger,
},
]),
subtitle: 'RTGM from hazard curves',
title: 'Risk-Targeted Ground Motion Service',
},
// NCM services
{
applicationsUsedIn: [],
id: ServiceGroupId.NCM,
images: [
{
image: 'ncm-geophys.png',
},
{
image: 'ncm-temp.png',
},
],
services$: of([
{
...environment.webServices.ncm,
swaggerEndPoint: environment.webServices.ncm.services.swagger,
},
]),
subtitle: 'Geologic, Geophysical, Mineral, and Temperature Profiles',
title: 'National Crustal Model Services',
},
// AASHTO 2023 services
{
applicationsUsedIn: [],
id: ServiceGroupId.AASHTO_2023,
images: [{image: 'aashto-logo.jpeg'}],
services$: of([
{
...environment.webServices.aashto2023,
swaggerEndPoint: environment.webServices.aashto2023.services.swagger,
},
]),
subtitle: 'Risk-Targeted Desgin Response Spectra for 2023 Edition',
title: 'AASHTO 2023 Services',
},
];
constructor(
public templateService: NshmpTemplateService,
private el: ElementRef<HTMLDivElement>,
private route: ActivatedRoute,
private router: Router,
private hazardService: HazardService,
private nshmpService: NshmpService,
) {}
ngAfterViewInit() {
this.checkUrl();
this.onScroll();
}
/**
* Reset navigation parameters.
*/
onExpansionPanelClosed(): void {
this.router
.navigate([])
.catch((error: Error) => this.nshmpService.throwError$(error));
}
/**
* Set URL query parameters.
*
* @param serviceGroup The service group opened
* @param service The service
*/
onExpansionPanelOpen(serviceGroup: ServiceGroup): void {
const queryParams: QueryParameters = {
serviceGroup: serviceGroup.id,
};
this.router
.navigate([], {
queryParams: {
...this.route.snapshot.queryParams,
...queryParams,
},
})
.catch((error: Error) => this.nshmpService.throwError$(error));
}
/**
* Update query parameters on URL on link click.
*
* @param serviceGroup The service group
*/
onLinkIconClick(serviceGroup: string): void {
const queryParams: QueryParameters = {
serviceGroup,
};
this.router
.navigate([], {
queryParams,
})
.catch((error: Error) => this.nshmpService.throwError$(error));
}
/**
* Scroll to expansion panel and set URL parameters.
*
* @param serviceGroup The service group clicked
*/
onNavClick(serviceGroup: string): void {
const serviceEl = this.el.nativeElement.querySelector(`#${serviceGroup}`);
serviceEl?.scrollIntoView();
this.onLinkIconClick(serviceGroup);
setTimeout(() => {
this.resetActive();
this.addActive(serviceEl);
}, 0);
}
/**
* Handle on scroll on scroll event.
*
* Highlight navigation if scrolling over expansion panel.
*/
onScroll() {
this.resetActive();
document.querySelectorAll('mat-card').forEach(cardEl => {
const rect = cardEl.getBoundingClientRect();
if (
rect.bottom > this.cardTriggerHeight &&
rect.top < this.cardTriggerHeight
) {
this.addActive(cardEl);
}
});
}
/**
* Convert label to id.
*
* @param service The service
*/
toServiceId(service: ServiceConfig): string {
return service.label.replace(/ /g, '-').replace(/\./g, '-');
}
/**
* Add `active` class name to element.
*
* @param cardEl The mat card element
*/
private addActive(cardEl: Element): void {
const navEl = this.el.nativeElement.querySelector(`.${cardEl.id}`);
navEl?.classList.add('active');
}
/**
* Check URL parameters.
*/
private checkUrl() {
const query: QueryParameters = this.route.snapshot.queryParams;
if (query.serviceGroup) {
this.el.nativeElement
.querySelector(`#${query.serviceGroup}`)
?.scrollIntoView();
}
}
/**
* Remove `active` class name from menu.
*/
private resetActive() {
document
.querySelector('mat-nav-list')
.querySelectorAll('a')
.forEach(navEl => navEl.classList.remove('active'));
}
}
<mat-sidenav-container class="height-full" autosize>
@if ((templateService.isSmallScreen$ | async) === false) {
<mat-sidenav
mode="side"
opened
class="mat-elevation-z2"
[ngClass]="{collapsed: sidenavCollapsed}"
>
@if (sidenavCollapsed === false) {
<mat-nav-list>
@for (serviceGroup of serviceGroups; track serviceGroup) {
<a
mat-list-item
(click)="onNavClick(serviceGroup.id)"
[class]="serviceGroup.id"
>
<span matListItemLine>
{{ serviceGroup.title }}
</span>
</a>
}
</mat-nav-list>
}
<div class="collapse-sidenav">
<button
mat-button
class="grid-col-12"
(click)="sidenavCollapsed = !sidenavCollapsed"
>
@if (sidenavCollapsed === false) {
<div class="icon-text">
<mat-icon aria-label="Left arrow icon">
keyboard_double_arrow_left
</mat-icon>
<span>Collapse sidebar</span>
</div>
} @else {
<mat-icon aria-label="Right arrow icon">
keyboard_double_arrow_right
</mat-icon>
}
</button>
</div>
</mat-sidenav>
}
<mat-sidenav-content (scroll)="onScroll()">
<div class="service-content grid-container-widescreen">
@for (serviceGroup of serviceGroups; track serviceGroup) {
<div class="service-group">
<!-- Service info -->
<mat-card [id]="serviceGroup.id">
<mat-card-header>
<mat-card-title>
<div class="card-title">
<button
mat-icon-button
(click)="onLinkIconClick(serviceGroup.id)"
>
<mat-icon aria-label="Link Icon">link</mat-icon>
</button>
{{ serviceGroup.title }}
</div>
</mat-card-title>
<mat-card-subtitle>{{ serviceGroup.subtitle }}</mat-card-subtitle>
</mat-card-header>
<!-- Images -->
<mat-card-content>
@if (
(templateService.isSmallScreen$ | async) === false &&
serviceGroup.images.length > 0
) {
<mat-divider />
<div class="card-section">
<div class="grid-row">
@for (
serviceImage of serviceGroup.images;
track serviceImage
) {
<div class="grid-col-12 tablet:grid-col-6 content-image">
@if (
templateService.isDarkMode &&
serviceImage.darkModeImage
) {
<img
src="assets/services/{{
serviceImage.darkModeImage
}}"
[alt]="serviceImage.darkModeImage"
/>
} @else {
<img
src="assets/services/{{ serviceImage.image }}"
[alt]="serviceImage.image"
/>
}
</div>
}
</div>
</div>
}
@if (serviceGroup.applicationsUsedIn.length > 0) {
<mat-divider />
<!-- Application used list -->
<div class="card-section">
<h4>Applications Used In</h4>
<mat-nav-list>
@for (app of serviceGroup.applicationsUsedIn; track app) {
<a
mat-list-item
[routerLink]="app.routerLink"
target="_blank"
>
{{ app.display }}
</a>
}
</mat-nav-list>
</div>
}
<mat-divider />
<!-- Expansion panels with Swagger -->
@if (serviceGroup.services$ | async; as services) {
@if (services.length > 0) {
<div class="card-section">
<h4>Service Information</h4>
<!-- List of links to swagger pages -->
<mat-nav-list>
@for (service of services; track service) {
<a mat-list-item [href]="service.url" target="_blank">
{{ service.label }}
</a>
}
</mat-nav-list>
</div>
}
}
</mat-card-content>
</mat-card>
</div>
}
</div>
</mat-sidenav-content>
</mat-sidenav-container>