File

components/info-popup/info-popup.component.ts

Description

Angular Material card for feature properties that have been clicked on the map.

Slides up from bottom left.

Metadata

Index

Properties
Methods

Constructor

constructor(service: AppService)
Parameters :
Name Type Optional
service AppService No

Methods

close
close()

Close the popup card and reset layers.

Returns : void
earthquakeDepth
earthquakeDepth()
Returns : string
earthquakeLocation
earthquakeLocation()
Returns : string
Private getMfdParameters
getMfdParameters(model: NshmId, infoPopupData: InfoPopupData, treesUsage: SourceLogicTreesUsage)

Returns the MFD parameters for URL.

Parameters :
Name Type Optional Description
model NshmId No
infoPopupData InfoPopupData No

The info popup data

treesUsage SourceLogicTreesUsage No

The tree usage

Returns : MfdQuery
Private getSourceType
getSourceType(infoPopupData: InfoPopupData)

Returns the feature type display.

Parameters :
Name Type Optional Description
infoPopupData InfoPopupData No

The info popup data

Returns : string

Properties

earthquakeInfoPopupData
Default value : this.service.earthquakeInfoPopupData
earthquakeProperties
Default value : computed( () => this.earthquakeInfoPopupData().feature.properties, )
infoPopupData
Default value : this.service.infoPopupData

Info data for popup

Keys
Default value : Object.keys
mfdParameters
Default value : computed(() => this.getMfdParameters( this.service.formGroup.getRawValue().model, this.infoPopupData(), this.service.treesUsageResponse(), ), )

Query parameters for MFD link.

properties
Default value : computed(() => { const entries: [string, unknown][] = Object.entries( this.infoPopupData()?.feature.properties, ); return entries.map(([key, value]) => ({key, value})); })

Feature properties

sourceType
Default value : computed(() => this.getSourceType(this.infoPopupData()))

Source type display

import {animate, style, transition, trigger} from '@angular/animations';
import {DatePipe} from '@angular/common';
import {Component, computed} from '@angular/core';
import {MatButton} from '@angular/material/button';
import {
  MatCard,
  MatCardContent,
  MatCardFooter,
  MatCardHeader,
  MatCardTitle,
} from '@angular/material/card';
import {MatDivider} from '@angular/material/divider';
import {MatListModule} from '@angular/material/list';
import {RouterLink} from '@angular/router';
import {FeatureType} from '@ghsc/nshmp-utils-ts/libs/nshmp-haz/www/features-service';
import {SourceLogicTreesUsage} from '@ghsc/nshmp-utils-ts/libs/nshmp-haz/www/source-logic-trees-service';
import {
  SourceType,
  TectonicSettings,
  TreeInfo,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/model';
import {NshmId} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/nshm';

import {MfdQuery} from '../../../mfd/services/app.service';
import {InfoPopupData} from '../../models/state.model';
import {AppService} from '../../services/app.service';

/**
 * Angular Material card for feature properties that have been clicked on the map.
 *
 * Slides up from bottom left.
 */
@Component({
  animations: [
    trigger('slideUpDown', [
      transition(':enter', [
        style({transform: 'translateY(100%)'}),
        animate('200ms ease-in', style({transform: 'translateY(0%)'})),
      ]),
      transition(':leave', [
        animate('200ms ease-in', style({transform: 'translateY(100%)'})),
      ]),
    ]),
  ],
  imports: [
    MatCard,
    MatCardHeader,
    MatCardTitle,
    MatCardContent,
    MatDivider,
    RouterLink,
    MatCardFooter,
    MatButton,
    DatePipe,
    MatListModule,
  ],
  selector: 'app-info-popup',
  styleUrl: './info-popup.component.scss',
  templateUrl: './info-popup.component.html',
})
export class InfoPopupComponent {
  /** Info data for popup */
  infoPopupData = this.service.infoPopupData;

  earthquakeInfoPopupData = this.service.earthquakeInfoPopupData;

  /**
   * Query parameters for MFD link.
   */
  mfdParameters = computed(() =>
    this.getMfdParameters(
      this.service.formGroup.getRawValue().model,
      this.infoPopupData(),
      this.service.treesUsageResponse(),
    ),
  );

  /** Feature properties */
  properties = computed(() => {
    const entries: [string, unknown][] = Object.entries(
      this.infoPopupData()?.feature.properties,
    );

    return entries.map(([key, value]) => ({key, value}));
  });

  earthquakeProperties = computed(
    () => this.earthquakeInfoPopupData().feature.properties,
  );

  Keys = Object.keys;

  /** Source type display */
  sourceType = computed(() => this.getSourceType(this.infoPopupData()));

  constructor(private service: AppService) {}

  /**
   * Close the popup card and reset layers.
   */
  close() {
    this.service.resetLayers();

    this.service.updateState({
      earthquakeInfoPopupData:
        this.service.initialState().earthquakeInfoPopupData,
      infoPopupData: this.service.initialState().infoPopupData,
    });
  }

  earthquakeDepth(): string {
    return this.earthquakeInfoPopupData()?.feature.geometry.coordinates[2].toFixed(
      1,
    );
  }

  earthquakeLocation(): string {
    const [longitude, latitude] =
      this.earthquakeInfoPopupData().feature.geometry.coordinates;

    const latStr = [
      Math.abs(latitude).toFixed(3),
      '°',
      latitude < 0 ? 'S' : 'N',
    ].join('');

    const lonStr = [
      Math.abs(longitude).toFixed(3),
      '°',
      longitude < 0 ? 'W' : 'E',
    ].join('');

    return `${lonStr}, ${latStr}`;
  }

  /**
   * Returns the MFD parameters for URL.
   *
   * @param infoPopupData The info popup data
   * @param treesUsage The tree usage
   */
  private getMfdParameters(
    model: NshmId,
    infoPopupData: InfoPopupData,
    treesUsage: SourceLogicTreesUsage,
  ): MfdQuery {
    if (infoPopupData.feature === null || infoPopupData.featureType === null) {
      return null;
    }

    let treeInfo: TreeInfo = null;
    let setting: TectonicSettings = null;
    let sourceType: SourceType = null;

    treesUsage.response.trees.forEach(tree => {
      tree.data.forEach(group => {
        group.data.forEach(data => {
          if (data.name === infoPopupData.feature.properties.name) {
            setting = tree.setting;
            sourceType = group.type;
            treeInfo = data;
          }
        });
      });
    });

    const query: MfdQuery = {
      cumulative: false.toString(),
      model,
      setting,
      sourceTree: treeInfo?.id.toString(),
      sourceType,
      weightedMfds: false.toString(),
    };

    return query;
  }

  /**
   * Returns the feature type display.
   *
   * @param infoPopupData The info popup data
   */
  private getSourceType(infoPopupData: InfoPopupData): string {
    if (infoPopupData.featureType === null) {
      return;
    }

    const {featureType} = infoPopupData;
    let display = featureType.toString();

    switch (featureType) {
      case FeatureType.DECOLLEMENT:
        display = 'Décollement Sections';
        break;
      case FeatureType.FAULT:
        display = 'Fault Sections';
        break;
      case FeatureType.INTERFACE:
        display = 'Interface Sections';
        break;
      case FeatureType.ZONE:
        display = 'Zone Sources';
        break;
    }

    return display;
  }
}
<div class="leaflet-feature-popup">
  @if (infoPopupData()?.feature && infoPopupData()) {
    <mat-card [@slideUpDown]>
      <mat-card-header>
        <mat-card-title> Feature Properties </mat-card-title>
      </mat-card-header>

      <mat-card-content>
        <mat-divider />

        <div class="card-content">
          <table>
            <tbody>
              @if (mfdParameters()?.sourceTree) {
                <tr>
                  <th>
                    <a
                      routerLink="/source/mfd"
                      [queryParams]="mfdParameters()"
                      queryParamsHandling="merge"
                      target="_blank"
                      >Show MFD</a
                    >
                  </th>
                </tr>
              }
              <tr>
                <th>id</th>
                <td>{{ infoPopupData().feature.id }}</td>
              </tr>
              <tr>
                <th>Source Type</th>
                <td>{{ sourceType() }}</td>
              </tr>
              @for (item of properties(); track item) {
                @if (item.key !== 'mfd-tree' && item.key !== 'rate-map') {
                  <tr>
                    <th>{{ item.key }}</th>
                    <td>{{ item.value }}</td>
                  </tr>
                }
              }
            </tbody>
          </table>
        </div>

        <mat-divider />
      </mat-card-content>

      <mat-card-footer align="end">
        <button mat-raised-button color="primary" (click)="close()">
          Close
        </button>
      </mat-card-footer>
    </mat-card>
  }

  @if (earthquakeInfoPopupData()?.feature && earthquakeInfoPopupData()) {
    <mat-card [@slideUpDown]>
      <mat-card-header>
        <mat-card-title>
          <a [href]="earthquakeProperties().url" target="_blank">
            {{ earthquakeProperties().title }}
          </a>
        </mat-card-title>
      </mat-card-header>

      <mat-card-content>
        <mat-divider />

        @if (earthquakeProperties(); as props) {
          <div class="card-content">
            <table class="earthquake-properties">
              @if (props.time) {
                <tr>
                  <th>Time</th>
                  <td>
                    {{ earthquakeProperties().time | date: 'long' }}
                  </td>
                </tr>
              }

              @if (props.mag) {
                <tr>
                  <th>Magnitude</th>
                  <td>{{ earthquakeProperties().mag }}</td>
                </tr>
              }

              @if (earthquakeInfoPopupData().feature.geometry.coordinates) {
                <tr>
                  <th>Location</th>
                  <td>{{ earthquakeLocation() }}</td>
                </tr>
                <tr>
                  <th>Depth</th>
                  <td>{{ earthquakeDepth() }} km</td>
                </tr>
              }
            </table>
          </div>
        }

        <mat-divider />
      </mat-card-content>

      <mat-card-footer align="end">
        <button mat-raised-button color="primary" (click)="close()">
          Close
        </button>
      </mat-card-footer>
    </mat-card>
  }
</div>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""