raain-app 1.6.11 → 1.6.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, EventEmitter, Component, Input, Output, ViewChild, HostListener, Pipe, Directive, NgModule, Optional, SkipSelf } from '@angular/core';
3
- import { CartesianTools, SpeedMatrixContainer, GaugeNode, RadarNode, CartesianMeasureValue, Link, EventNode, TeamNode, RainNode, RainComputationMap, RainComputation, RainComputationQuality, GaugeMeasure, RainSpeedMap } from 'raain-model';
3
+ import { CartesianTools, GaugeNode, SpeedMatrixContainer, RadarNode, CartesianMeasureValue, TeamNode, Link, EventNode, RainNode, RainComputationMap, RainComputation, RainComputationQuality, GaugeMeasure, RainSpeedMap } from 'raain-model';
4
4
  import { RaainDivIcon, ElementsFactory, MapLatLng, ChartScaleColors, ScaleElementInput, CompareElementInput, ConfigurationElementInput, Tools, DateRange, DateStatusElementInput, DynamicDateStatusElementInput, SpeedMatrixElementInput, EarthMapElementInput, TimeframeContainers, CartesianMapValue, PolarMapValue } from 'raain-ui';
5
5
  import * as i2 from 'fidj-angular';
6
6
  import { LocalStorage, LoggerLevelEnum } from 'fidj-angular';
@@ -1342,15 +1342,18 @@ class CompareManager {
1342
1342
  this.onChanges();
1343
1343
  return;
1344
1344
  }
1345
- const uiCompares = comparePerDate.compareTimeline.map((c) => {
1345
+ const uiCompares = comparePerDate.compareTimeline
1346
+ .map((c) => {
1346
1347
  return {
1348
+ date: c.date,
1347
1349
  name: c.name,
1348
1350
  comparePoints: c.qualityPoints.map((p) => new XYType(p.getGaugeValue(), p.getRainValue(), 2, p.gaugeLabel, p.gaugeId)),
1349
1351
  comparePointsMax: new XYType(c.maxValue * 1.2, c.maxValue * 1.2),
1350
1352
  comparePointsHistory: c.qualityPointsLegacy,
1351
1353
  remarks: c.remarks,
1352
1354
  };
1353
- });
1355
+ })
1356
+ .sort((a, b) => a.date?.getTime() - b.date?.getTime());
1354
1357
  this.currentQualityDoneDate = comparePerDate.rainComputationQuality.isDoneDate;
1355
1358
  this.currentQualityTimeSpentInMs = comparePerDate.rainComputationQuality.timeSpentInMs;
1356
1359
  this.currentQualityLaunchedBy = comparePerDate.rainComputationQuality.launchedBy;
@@ -1370,8 +1373,8 @@ class CompareManager {
1370
1373
  return;
1371
1374
  }
1372
1375
  const countForAverage = targetsOrdered.length;
1373
- const maxValue = (this.buildCompares.compareCumulative.maxValue / 12) * 1.2;
1374
- this.globalComparePoints = this.buildCompares.compareCumulative.qualityPoints.map((qp) => new XYType(qp.getGaugeValue() / 12, qp.getRainValue() / 12, 2, qp.gaugeLabel, qp.gaugeId));
1376
+ const maxValue = this.buildCompares.compareCumulative.maxValue * 1.2;
1377
+ this.globalComparePoints = this.buildCompares.compareCumulative.qualityPoints.map((qp) => new XYType(qp.getGaugeValue(), qp.getRainValue(), 2, qp.gaugeLabel, qp.gaugeId));
1375
1378
  this.globalComparePointsMax = new XYType(maxValue, maxValue);
1376
1379
  }
1377
1380
  catch (e) {
@@ -1386,7 +1389,7 @@ class CompareManager {
1386
1389
  b.approxDistanceFrom(this.rainNode.getCenter()));
1387
1390
  })
1388
1391
  .filter((v, index) => index < 200);
1389
- const rainNodeGaugeIds = this.rainNode.getLinks('gauge').map((l) => l.getId());
1392
+ const rainNodeGaugeIds = this.rainNode.getLinks(GaugeNode.TYPE).map((l) => l.getId());
1390
1393
  const visibleGauges = gaugesToFilter.filter((g) => rainNodeGaugeIds.indexOf(g.id) > -1);
1391
1394
  console.log('visibleGauges:', visibleGauges);
1392
1395
  const gaugesLatLng = [];
@@ -1411,7 +1414,6 @@ class CompareManager {
1411
1414
  this.resetSelectedGauges();
1412
1415
  }
1413
1416
  async selectGauge(gaugeId, compareIndex) {
1414
- // console.log('selectGauge', gaugeId, compareIndex);
1415
1417
  if (gaugeId) {
1416
1418
  const xys = this.getCurrentQualityPoints(compareIndex).filter((p) => p.gaugeId === gaugeId);
1417
1419
  this.selectedGauge = xys.length === 1 ? xys[0] : null;
@@ -1420,7 +1422,12 @@ class CompareManager {
1420
1422
  this.selectedGauge = null;
1421
1423
  }
1422
1424
  if (!this.selectedGauge) {
1423
- return this.resetSelectedGauges();
1425
+ this.resetSelectedGauges();
1426
+ const gaugesFiltered = this.gaugesInMap.filter((g) => g.id === gaugeId);
1427
+ if (gaugesFiltered.length === 1) {
1428
+ this.selectedGauges = [gaugesFiltered[0]];
1429
+ }
1430
+ return;
1424
1431
  }
1425
1432
  const selectedGaugeInPoints = this.getCurrentQualityPoints(compareIndex).filter((p) => p.gaugeId === this.selectedGauge.gaugeId);
1426
1433
  let pixelsSolutions = [];
@@ -1612,6 +1619,7 @@ class RefreshManager {
1612
1619
  this.compareManager = compareManager;
1613
1620
  this.provider = 'Raain';
1614
1621
  this.timeStepInMinutes = 10;
1622
+ this.lastError = '';
1615
1623
  this._period = { begin: new Date(), end: new Date() };
1616
1624
  this.closeRefreshTimer = new Subject();
1617
1625
  this.cartesianTools = new CartesianTools();
@@ -1632,15 +1640,13 @@ class RefreshManager {
1632
1640
  this._period.end = new Date(period.end);
1633
1641
  this.refreshCounts().then((ignored) => { });
1634
1642
  }
1635
- static Delay(ms) {
1636
- return new Promise((resolve) => setTimeout(resolve, ms));
1637
- }
1638
1643
  setMethods(onRefreshInProgress, onRefreshDone, onFetchDone) {
1639
1644
  this.onRefreshInProgress = onRefreshInProgress;
1640
1645
  this.onRefreshDone = onRefreshDone;
1641
1646
  this.onFetchDone = onFetchDone;
1642
1647
  }
1643
1648
  cleanAll() {
1649
+ this.lastError = '';
1644
1650
  this.countsPeriod = { percentImages: [], queueRunning: 0, progress: 0 };
1645
1651
  this.timeframesFromRadars = [];
1646
1652
  this.timeframesFromRadarsExtended = [];
@@ -1675,6 +1681,7 @@ class RefreshManager {
1675
1681
  return this.timelineSelectedFrameSet;
1676
1682
  }
1677
1683
  async refresh(launchQualityAfter, dataInternal) {
1684
+ this.lastError = '';
1678
1685
  this.checkPeriod();
1679
1686
  this.dataInternal = dataInternal;
1680
1687
  const asyncDone = (error) => {
@@ -1715,7 +1722,9 @@ class RefreshManager {
1715
1722
  }
1716
1723
  checkPeriod() {
1717
1724
  if (this.period.begin.getTime() === this.period.end.getTime()) {
1718
- throw new Error('need a period');
1725
+ const message = 'need a period';
1726
+ this.lastError += message;
1727
+ throw new Error(message);
1719
1728
  }
1720
1729
  }
1721
1730
  async refreshCounts() {
@@ -1753,6 +1762,7 @@ class RefreshManager {
1753
1762
  }
1754
1763
  catch (e) {
1755
1764
  console.warn(e);
1765
+ this.lastError += e.message;
1756
1766
  }
1757
1767
  return false;
1758
1768
  }
@@ -1776,8 +1786,22 @@ class RefreshManager {
1776
1786
  frameSet.date.getTime() <= this.period.end.getTime())
1777
1787
  .sort((a, b) => a.date.getTime() - b.date.getTime());
1778
1788
  this.timeframeDates = this.timeframesFromRadars.map((frameSet) => frameSet.date);
1779
- // console.log('timeframesFromRadarsExtended:', this.timeframesFromRadarsExtended);
1780
- // console.log('timeframeDates:', this.timeframeDates);
1789
+ // Compute all expected dates from period.begin to period.end with timeStepInMinutes
1790
+ const allExpectedDates = [];
1791
+ const currentDate = new Date(this.period.begin);
1792
+ while (currentDate.getTime() <= this.period.end.getTime()) {
1793
+ allExpectedDates.push(new Date(currentDate));
1794
+ currentDate.setMinutes(currentDate.getMinutes() + this.timeStepInMinutes);
1795
+ }
1796
+ // Check if all expected dates are present in timeframeDates
1797
+ const timeframeDateTimes = new Set(this.timeframeDates.map((d) => d.getTime()));
1798
+ const missingDates = allExpectedDates.filter((expectedDate) => !timeframeDateTimes.has(expectedDate.getTime()));
1799
+ if (missingDates.length > 0) {
1800
+ const message = `Missing ${missingDates.length} timeframe(s) out of ${allExpectedDates.length} expected: ` +
1801
+ missingDates.map((d) => d.toISOString()).join(', ');
1802
+ console.warn(message);
1803
+ this.lastError += message;
1804
+ }
1781
1805
  return this.timeframesFromRadars;
1782
1806
  }
1783
1807
  catch (e) {
@@ -1805,7 +1829,9 @@ class RefreshManager {
1805
1829
  }
1806
1830
  async refreshMapTimeframeContainers(target) {
1807
1831
  if (!target?.rainComputationId && !target?.rainComputationCumulativeId) {
1808
- console.warn(`Pb with refreshMapTimeframeContainers insights ${target?.date.toISOString()}`);
1832
+ const message = `Pb with refreshMapTimeframeContainers insights ${target?.date.toISOString()}`;
1833
+ console.warn(message);
1834
+ this.lastError += message;
1809
1835
  return null;
1810
1836
  }
1811
1837
  const rainNode = this.rainNode;
@@ -1840,7 +1866,9 @@ class RefreshManager {
1840
1866
  }
1841
1867
  }
1842
1868
  catch (e) {
1843
- console.warn('Pb with computations for id:', target.rainComputationId, e);
1869
+ const message = `Pb with computations for id: ${target.rainComputationId} ${e.message}`;
1870
+ console.warn(message);
1871
+ this.lastError += message;
1844
1872
  }
1845
1873
  return newCreatedTimeframeContainers;
1846
1874
  }
@@ -1851,7 +1879,9 @@ class RefreshManager {
1851
1879
  }
1852
1880
  async getValues(target) {
1853
1881
  if (!target?.rainComputationId && !target?.rainComputationCumulativeId) {
1854
- console.warn(`Pb with target insights ${target?.date.toISOString()}`);
1882
+ const message = `Pb with target insights ${target?.date.toISOString()}`;
1883
+ console.warn(message);
1884
+ this.lastError += message;
1855
1885
  return [];
1856
1886
  }
1857
1887
  let values = [];
@@ -1876,7 +1906,9 @@ class RefreshManager {
1876
1906
  }
1877
1907
  }
1878
1908
  catch (e) {
1879
- console.warn('Pb with computations for id:', target.rainComputationId, target.rainComputationCumulativeId, e);
1909
+ const message = `Pb with computations for id: ${target.rainComputationId} ${target.rainComputationCumulativeId} ${e.message}`;
1910
+ console.warn(message);
1911
+ this.lastError += message;
1880
1912
  }
1881
1913
  return values;
1882
1914
  }
@@ -2067,7 +2099,7 @@ class RaainDetailsComponent {
2067
2099
  dateChanged.toLocaleTimeString().substring(0, 5);
2068
2100
  this.periodDurationAsString = '1';
2069
2101
  await this.onPeriodBeginChange(null);
2070
- this.refreshManager.refresh(false, true);
2102
+ await this.refreshManager.refresh(false, true);
2071
2103
  }
2072
2104
  async onDateChangeInMap(dateShown) {
2073
2105
  // console.log('onDateChangeInMap', dateShown);
@@ -2092,9 +2124,13 @@ class RaainDetailsComponent {
2092
2124
  await this.compareManager.selectGauge(gaugeSelected.id, 0);
2093
2125
  }
2094
2126
  async refreshGaugeValues(gaugeSelected) {
2095
- const dayBegin = new Date(this.periodBegin.toISOString().substring(0, 10));
2096
- const dayEnd = new Date(dayBegin.getTime() + 24 * 60 * 60 * 1000 - 1);
2097
- const gaugeMeasures = await this.profileService.getGaugeMeasures(gaugeSelected.id, dayBegin, dayEnd);
2127
+ const gaugeValueShowBegin = new Date(this.periodBegin.getTime() - 24 * 60 * 60 * 1000);
2128
+ const gaugeValueShowEnd = new Date(this.periodEnd.getTime() + 24 * 60 * 60 * 1000);
2129
+ gaugeValueShowBegin.setHours(0);
2130
+ gaugeValueShowBegin.setMinutes(0);
2131
+ gaugeValueShowEnd.setHours(23);
2132
+ gaugeValueShowEnd.setMinutes(59);
2133
+ const gaugeMeasures = await this.profileService.getGaugeMeasures(gaugeSelected.id, gaugeValueShowBegin, gaugeValueShowEnd);
2098
2134
  const gaugeValues = gaugeMeasures.map((gm) => {
2099
2135
  const cartesianMeasureValue = new CartesianMeasureValue(gm.values[0]);
2100
2136
  const value = cartesianMeasureValue.getCartesianValues()[0].value;
@@ -2203,7 +2239,7 @@ class RaainDetailsComponent {
2203
2239
  this.refreshManager.setMethods(this.onRefreshInProgress.bind(this), this.onRefreshDone.bind(this), this.onFetchDone.bind(this));
2204
2240
  const center = this.rainNode.getCenter();
2205
2241
  this.coordinates = new MapLatLng(center.lat, center.lng);
2206
- this.teamNode = await this.profileService.getTeam(this.rainNode.getLink('team').getId());
2242
+ this.teamNode = await this.profileService.getTeam(this.rainNode.getLink(TeamNode.TYPE).getId());
2207
2243
  if (this.periodBegin && this.periodEnd) {
2208
2244
  this.refreshManager.period = { begin: this.periodBegin, end: this.periodEnd };
2209
2245
  await this.refreshManager.refresh(false, this.toggleAdmin);
@@ -2228,10 +2264,10 @@ class RaainDetailsComponent {
2228
2264
  }
2229
2265
  }
2230
2266
  RaainDetailsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: RaainDetailsComponent, deps: [{ token: Storage }], target: i0.ɵɵFactoryTarget.Component });
2231
- RaainDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: RaainDetailsComponent, selector: "raain-details", inputs: { toggleAdmin: "toggleAdmin", rainNode: "rainNode", compareManager: "compareManager", refreshManager: "refreshManager", profileService: "profileService", radarService: "radarService", toggleCumulative: "toggleCumulative" }, usesOnChanges: true, ngImport: i0, template: "<!-- Main content container -->\n<div *ngIf=\"rainNode\" class=\"raain-details-container\">\n\n <!-- Period selection section -->\n <ion-card class=\"period-card\">\n <ion-card-content>\n <div class=\"period-controls\">\n <div class=\"period-row\">\n <ion-button (click)=\"setPeriodOfNow()\" class=\"now-button\" fill=\"outline\">\n <ion-icon name=\"time-outline\" slot=\"start\"></ion-icon>\n Now\n </ion-button>\n\n <div class=\"period-start ion-hide-md-down\">\n <ion-label>Start:</ion-label>\n <input (change)=\"onPeriodBeginChange($event)\"\n [value]=\"periodBeginAsString\"\n class=\"datetime-input\"\n type=\"datetime-local\">\n </div>\n\n <div class=\"period-duration ion-hide-md-down\">\n <ion-label>Duration:</ion-label>\n <ion-select (ionDismiss)=\"onPeriodDurationChange($event)\"\n [(ngModel)]=\"periodDurationAsString\"\n class=\"duration-select\"\n id=\"periodDuration\"\n interface=\"popover\">\n <ion-select-option value=\"0.25\">15 minutes</ion-select-option>\n <ion-select-option value=\"0.5\">30 minutes</ion-select-option>\n <ion-select-option value=\"1\">1 hour</ion-select-option>\n <ion-select-option value=\"2\">2 hours</ion-select-option>\n <ion-select-option value=\"3\">3 hours</ion-select-option>\n <ion-select-option value=\"4\">4 hours</ion-select-option>\n <ion-select-option value=\"5\">5 hours</ion-select-option>\n <ion-select-option value=\"6\">6 hours</ion-select-option>\n <ion-select-option *ngIf=\"isAdmin\" value=\"24\">24 hours</ion-select-option>\n </ion-select>\n </div>\n\n <div id=\"all-dates\" slot=\"end\">\n <ion-label class=\"toggle-label\">All dates</ion-label>\n <ion-toggle (ionChange)=\"onEnableCountHistoryTab(rainNode)\"\n [(ngModel)]=\"toggleHistory\"\n [checked]=\"toggleHistory\">\n </ion-toggle>\n </div>\n </div>\n\n <!-- Hidden label for change detection -->\n <div class=\"hidden-label\">{{ onChangeDetectionTest(rainNode) }}</div>\n </div>\n\n <!-- Historical map section -->\n <div *ngIf=\"toggleHistory\" class=\"period-controls\">\n <raain-date-dynamic (changedDate)=\"onDateChangeInCount($event)\"\n [currentHeight]=\"300\"\n [fetchData]=\"fetchDataWrapper\"\n [points]=\"countPoints\">\n </raain-date-dynamic>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Map section -->\n <ion-card class=\"map-card\">\n <ion-card-content class=\"map-content\">\n <ion-grid>\n <ion-row id=\"progressAndRefresh\">\n <ion-col size=\"12\" size-md=\"6\">\n <!-- left content (if any) -->\n </ion-col>\n <ion-col class=\"ion-text-right\" size=\"12\" size-md=\"6\">\n <ion-label class=\"ion-margin-end\">\n <span *ngIf=\"getPercentOfComputations()\">\n {{ getPercentOfComputations() }}% Images\n <i *ngIf=\"countsPeriod.progress\" class=\"progress-indicator\">\n In Progress: {{ countsPeriod.progress }}...\n </i>\n </span>\n <span *ngIf=\"!getPercentOfComputations()\">\n No image available\n </span>\n </ion-label>\n\n <ion-button (click)=\"refreshMap()\" [disabled]=\"refreshInProgress\" class=\"refresh-button\">\n Refresh Map\n </ion-button>\n </ion-col>\n\n <!-- Progress indicator -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n <ion-row *ngIf=\"toggleMap && getPercentOfImages()\">\n <!-- Map component -->\n <ion-col class=\"map-column\" size-lg=\"7\">\n <div class=\"map-container\">\n <raain-map\n (changedDate)=\"onDateChangeInMap($event)\"\n (changedSum)=\"onSumChangeInMap($event)\"\n (selectedMarker)=\"onGaugeSelectInMap($event)\"\n [coordinates]=\"coordinates\"\n [currentHeight]=\"500\"\n [defaultDate]=\"dateShown\"\n [markers]=\"{\n borders,\n gauges: compareManager.gaugesInMap,\n gaugesInCompare: compareManager.gaugesInCompare,\n selectedGauges: compareManager.selectedGauges,\n pixels: compareManager.selectedPixels,\n pixelsSolution: compareManager.pixelsSolutions?.length ? compareManager.pixelsSolutions[0] : [],\n speeds: compareManager.speeds\n }\"\n [showCumulative]=\"toggleCumulative\"\n [sumFn]=\"refreshManager.sumFn\"\n [sumValues]=\"refreshManager.sumValues\"\n [timeframeContainers]=\"timeframeContainers\"\n [timeframeDates]=\"timeframeDates\">\n </raain-map>\n </div>\n\n <div class=\"data-column\">\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Image Details</summary>\n <div class=\"details-content\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Date:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDate?.toISOString() }}\n | {{ refreshManager.rainComputationMapDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Water in the map:</span>\n <span class=\"detail-value\">{{ sumDetails }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ min:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMin }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ max:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMax }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n\n <!-- Data panel -->\n <ion-col class=\"data-column\" size-lg=\"5\">\n <div class=\"data-panel\">\n <!-- Compare stack component -->\n <div class=\"compare-stack\">\n <raain-compare-stack\n (selectedPoint)=\"onGaugeSelectInCompare($event)\"\n [compareManager]=\"compareManager\"\n [cumulative]=\"toggleCumulative\">\n </raain-compare-stack>\n </div>\n\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Compare Details</summary>\n <div class=\"details-content\">\n <div [ngClass]=\"{'warning': refreshManager.rainComputationMapDoneDate?.getTime() > compareManager.currentQualityDoneDate?.getTime() + 60000}\"\n class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ compareManager.compareVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Gauges:</span>\n <span class=\"detail-value\">{{ compareManager.gaugesInCompare.length }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Points:</span>\n <span class=\"detail-value\">{{ compareManager.globalComparePoints.length }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n </ion-row>\n <ion-row>\n <!-- Bottom progress bar -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n\n <!-- Gauge values section -->\n <ion-card *ngIf=\"gaugeSelectedPoints.length && gaugeSelectedPoints[0].values.length\" class=\"gauge-card\">\n <ion-card-header>\n <ion-card-title>\n <ion-icon name=\"analytics-outline\"></ion-icon>\n Selected Gauge Data\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <raain-date-focus\n [currentHeight]=\"300\"\n [focusDate]=\"periodBegin\"\n [focusRange]=\"DateRange.DAY\"\n [points]=\"gaugeSelectedPoints\"\n [withoutAll]=\"true\">\n </raain-date-focus>\n </ion-card-content>\n </ion-card>\n\n</div>\n", styles: [".raain-details-container{max-width:var(--app-max-width);margin:0 auto;padding:0 0 24px}.raain-details-card{width:100%;margin-bottom:20px}.raain-details-card ion-card-header{border-bottom:1px solid rgba(var(--ion-color-medium-rgb),.2)}.raain-details-card ion-card-header ion-card-title{display:flex;align-items:center}.raain-details-card ion-card-header ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary)}.node-info-card{background-color:var(--ion-color-light)}.node-info-card .node-header{display:flex;align-items:center}.node-info-card .node-header .node-status{margin-right:16px}.node-info-card .node-header .node-status ion-icon{font-size:24px}.node-info-card .node-header .node-titles{flex:1}.node-info-card .node-header .node-titles ion-card-title{margin:0;font-size:1.4rem;font-weight:600;color:var(--ion-color-dark)}.node-info-card .node-header .node-titles ion-card-subtitle{padding-left:0;margin:4px 0 0;font-size:.9rem;color:var(--ion-color-medium)}.count-map-card,.period-card{background-color:var(--ion-color-light)}.period-card ion-card-title{display:flex;align-items:center}.period-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}.period-row{display:flex;flex-wrap:wrap;align-items:center;gap:16px;position:relative}.now-button{min-width:100px}#all-dates{display:flex;align-items:center;margin-left:auto}#all-dates .toggle-label{margin-right:8px;white-space:nowrap}.refresh-button ion-icon{margin-right:4px;color:var(--ion-color-light)}.period-start,.period-duration{display:flex;align-items:center}.hidden-label{display:none}.datetime-input,#periodDuration,.duration-select{padding:8px 12px;border:1px solid rgba(var(--ion-color-medium-rgb),.3);border-radius:var(--ion-border-radius);background-color:var(--ion-color-light);font-family:var(--ion-font-family)}.datetime-input:focus,#periodDuration:focus,.duration-select:focus{outline:none;border-color:var(--ion-color-primary)}#periodDuration,.duration-select{min-width:150px}.gauge-card{background-color:var(--ion-color-light)}.gauge-card ion-card-title{display:flex;align-items:center}.gauge-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}raain-compare-stack{width:100%;display:block}@media (max-width: 768px){.period-row{flex-direction:row;justify-content:space-between;align-items:center}#all-dates{margin-left:auto;padding-left:8px}#all-dates .toggle-label{font-size:.9rem}.map-header{flex-direction:row;justify-content:space-between;align-items:center;gap:16px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i4.IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: i4.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: i4.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i4.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonProgressBar, selector: "ion-progress-bar", inputs: ["buffer", "color", "mode", "reversed", "type", "value"] }, { kind: "component", type: i4.IonRow, selector: "ion-row" }, { kind: "component", type: i4.IonSelect, selector: "ion-select", inputs: ["cancelText", "compareWith", "disabled", "interface", "interfaceOptions", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "value"] }, { kind: "component", type: i4.IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: i4.IonToggle, selector: "ion-toggle", inputs: ["checked", "color", "disabled", "mode", "name", "value"] }, { kind: "directive", type: i4.BooleanValueAccessor, selector: "ion-checkbox,ion-toggle" }, { kind: "directive", type: i4.SelectValueAccessor, selector: "ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "component", type: RaainMapComponent, selector: "raain-map", inputs: ["coordinates", "markers", "timeframeContainers", "autoplay", "showMarkers", "showSpeedMarkers", "showCumulative", "currentHeight", "timeframeDates", "defaultDate", "sumValues", "sumFn"], outputs: ["selectedMarker", "changedDate", "changedSum"] }, { kind: "component", type: RaainCompareStackComponent, selector: "raain-compare-stack", inputs: ["compareManager", "currentHeight", "cumulative"], outputs: ["selectedPoint"] }, { kind: "component", type: RaainDateFocusComponent, selector: "raain-date-focus", inputs: ["points", "focusDate", "focusRange", "withoutAll", "currentHeight"] }, { kind: "component", type: RaainDateDynamicComponent, selector: "raain-date-dynamic", inputs: ["points", "focusDate", "focusRange", "withoutAll", "currentHeight", "fetchData"], outputs: ["changedDate"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
2267
+ RaainDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: RaainDetailsComponent, selector: "raain-details", inputs: { toggleAdmin: "toggleAdmin", rainNode: "rainNode", compareManager: "compareManager", refreshManager: "refreshManager", profileService: "profileService", radarService: "radarService", toggleCumulative: "toggleCumulative" }, usesOnChanges: true, ngImport: i0, template: "<!-- Main content container -->\n<div *ngIf=\"rainNode\" class=\"raain-details-container\">\n\n <!-- Period selection section -->\n <ion-card class=\"period-card\">\n <ion-card-content>\n <div class=\"period-controls\">\n <div class=\"period-row\">\n <ion-button (click)=\"setPeriodOfNow()\" class=\"now-button\" fill=\"outline\">\n <ion-icon name=\"time-outline\" slot=\"start\"></ion-icon>\n Now\n </ion-button>\n\n <div class=\"period-start ion-hide-md-down\">\n <ion-label>Start:</ion-label>\n <input (change)=\"onPeriodBeginChange($event)\"\n [value]=\"periodBeginAsString\"\n class=\"datetime-input\"\n type=\"datetime-local\">\n </div>\n\n <div class=\"period-duration ion-hide-md-down\">\n <ion-label>Duration:</ion-label>\n <ion-select (ionDismiss)=\"onPeriodDurationChange($event)\"\n [(ngModel)]=\"periodDurationAsString\"\n class=\"duration-select\"\n id=\"periodDuration\"\n interface=\"popover\">\n <ion-select-option value=\"0.25\">15 minutes</ion-select-option>\n <ion-select-option value=\"0.5\">30 minutes</ion-select-option>\n <ion-select-option value=\"1\">1 hour</ion-select-option>\n <ion-select-option value=\"2\">2 hours</ion-select-option>\n <ion-select-option value=\"3\">3 hours</ion-select-option>\n <ion-select-option value=\"4\">4 hours</ion-select-option>\n <ion-select-option value=\"5\">5 hours</ion-select-option>\n <ion-select-option value=\"6\">6 hours</ion-select-option>\n <ion-select-option *ngIf=\"isAdmin\" value=\"24\">24 hours</ion-select-option>\n </ion-select>\n </div>\n\n <div id=\"all-dates\" slot=\"end\">\n <ion-label class=\"toggle-label\">All dates</ion-label>\n <ion-toggle (ionChange)=\"onEnableCountHistoryTab(rainNode)\"\n [(ngModel)]=\"toggleHistory\"\n [checked]=\"toggleHistory\">\n </ion-toggle>\n </div>\n </div>\n\n <!-- Hidden label for change detection -->\n <div class=\"hidden-label\">{{ onChangeDetectionTest(rainNode) }}</div>\n </div>\n\n <!-- Historical map section -->\n <div *ngIf=\"toggleHistory\" class=\"period-controls\">\n <raain-date-dynamic (changedDate)=\"onDateChangeInCount($event)\"\n [currentHeight]=\"300\"\n [fetchData]=\"fetchDataWrapper\"\n [points]=\"countPoints\">\n </raain-date-dynamic>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Map section -->\n <ion-card class=\"map-card\">\n <ion-card-content class=\"map-content\">\n <ion-grid>\n <ion-row id=\"progressAndRefresh\">\n <ion-col size=\"12\" size-md=\"6\">\n <!-- left content (if any) -->\n </ion-col>\n <ion-col class=\"ion-text-right\" size=\"12\" size-md=\"6\">\n <ion-label class=\"ion-margin-end\">\n <span *ngIf=\"getPercentOfComputations()\">\n {{ getPercentOfComputations() }}% Images\n <i *ngIf=\"countsPeriod.progress\" class=\"progress-indicator\">\n In Progress: {{ countsPeriod.progress }}...\n </i>\n </span>\n <span *ngIf=\"!getPercentOfComputations()\">\n No image available\n </span>\n <span *ngIf=\"refreshManager.lastError\">\n <b>Errors: {{ refreshManager.lastError }}</b>\n </span>\n </ion-label>\n\n <ion-button (click)=\"refreshMap()\" [disabled]=\"refreshInProgress\" class=\"refresh-button\">\n Refresh Map\n </ion-button>\n </ion-col>\n\n <!-- Progress indicator -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n <ion-row *ngIf=\"toggleMap && getPercentOfImages()\">\n <!-- Map component -->\n <ion-col class=\"map-column\" size-lg=\"7\">\n <div class=\"map-container\">\n <raain-map\n (changedDate)=\"onDateChangeInMap($event)\"\n (changedSum)=\"onSumChangeInMap($event)\"\n (selectedMarker)=\"onGaugeSelectInMap($event)\"\n [coordinates]=\"coordinates\"\n [currentHeight]=\"500\"\n [defaultDate]=\"dateShown\"\n [markers]=\"{\n borders,\n gauges: compareManager.gaugesInMap,\n gaugesInCompare: compareManager.gaugesInCompare,\n selectedGauges: compareManager.selectedGauges,\n pixels: compareManager.selectedPixels,\n pixelsSolution: compareManager.pixelsSolutions?.length ? compareManager.pixelsSolutions[0] : [],\n speeds: compareManager.speeds\n }\"\n [showCumulative]=\"toggleCumulative\"\n [sumFn]=\"refreshManager.sumFn\"\n [sumValues]=\"refreshManager.sumValues\"\n [timeframeContainers]=\"timeframeContainers\"\n [timeframeDates]=\"timeframeDates\">\n </raain-map>\n </div>\n\n <div class=\"data-column\">\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Image Details</summary>\n <div class=\"details-content\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Date:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDate?.toISOString() }}\n | {{ refreshManager.rainComputationMapDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Water in the map:</span>\n <span class=\"detail-value\">{{ sumDetails }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ min:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMin }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ max:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMax }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n\n <!-- Data panel -->\n <ion-col class=\"data-column\" size-lg=\"5\">\n <div class=\"data-panel\">\n <!-- Compare stack component -->\n <div class=\"compare-stack\">\n <raain-compare-stack\n (selectedPoint)=\"onGaugeSelectInCompare($event)\"\n [compareManager]=\"compareManager\"\n [cumulative]=\"toggleCumulative\">\n </raain-compare-stack>\n </div>\n\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Compare Details</summary>\n <div class=\"details-content\">\n <div [ngClass]=\"{'warning': refreshManager.rainComputationMapDoneDate?.getTime() > compareManager.currentQualityDoneDate?.getTime() + 60000}\"\n class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ compareManager.compareVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Gauges:</span>\n <span class=\"detail-value\">{{ compareManager.gaugesInCompare.length }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Points:</span>\n <span class=\"detail-value\">{{ compareManager.globalComparePoints.length }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n </ion-row>\n <ion-row>\n <!-- Bottom progress bar -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n\n <!-- Gauge values section -->\n <ion-card *ngIf=\"gaugeSelectedPoints.length && gaugeSelectedPoints[0].values.length\" class=\"gauge-card\">\n <ion-card-header>\n <ion-card-title>\n <ion-icon name=\"analytics-outline\"></ion-icon>\n Selected Gauge Data\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <raain-date-focus\n [currentHeight]=\"300\"\n [focusDate]=\"periodBegin\"\n [focusRange]=\"DateRange.DAY\"\n [points]=\"gaugeSelectedPoints\"\n [withoutAll]=\"true\">\n </raain-date-focus>\n </ion-card-content>\n </ion-card>\n\n</div>\n", styles: [".raain-details-container{max-width:var(--app-max-width);margin:0 auto;padding:0 0 24px}.raain-details-card{width:100%;margin-bottom:20px}.raain-details-card ion-card-header{border-bottom:1px solid rgba(var(--ion-color-medium-rgb),.2)}.raain-details-card ion-card-header ion-card-title{display:flex;align-items:center}.raain-details-card ion-card-header ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary)}.node-info-card{background-color:var(--ion-color-light)}.node-info-card .node-header{display:flex;align-items:center}.node-info-card .node-header .node-status{margin-right:16px}.node-info-card .node-header .node-status ion-icon{font-size:24px}.node-info-card .node-header .node-titles{flex:1}.node-info-card .node-header .node-titles ion-card-title{margin:0;font-size:1.4rem;font-weight:600;color:var(--ion-color-dark)}.node-info-card .node-header .node-titles ion-card-subtitle{padding-left:0;margin:4px 0 0;font-size:.9rem;color:var(--ion-color-medium)}.count-map-card,.period-card{background-color:var(--ion-color-light)}.period-card ion-card-title{display:flex;align-items:center}.period-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}.period-row{display:flex;flex-wrap:wrap;align-items:center;gap:16px;position:relative}.now-button{min-width:100px}#all-dates{display:flex;align-items:center;margin-left:auto}#all-dates .toggle-label{margin-right:8px;white-space:nowrap}.refresh-button ion-icon{margin-right:4px;color:var(--ion-color-light)}.period-start,.period-duration{display:flex;align-items:center}.hidden-label{display:none}.datetime-input,#periodDuration,.duration-select{padding:8px 12px;border:1px solid rgba(var(--ion-color-medium-rgb),.3);border-radius:var(--ion-border-radius);background-color:var(--ion-color-light);font-family:var(--ion-font-family)}.datetime-input:focus,#periodDuration:focus,.duration-select:focus{outline:none;border-color:var(--ion-color-primary)}#periodDuration,.duration-select{min-width:150px}.gauge-card{background-color:var(--ion-color-light)}.gauge-card ion-card-title{display:flex;align-items:center}.gauge-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}raain-compare-stack{width:100%;display:block}@media (max-width: 768px){.period-row{flex-direction:row;justify-content:space-between;align-items:center}#all-dates{margin-left:auto;padding-left:8px}#all-dates .toggle-label{font-size:.9rem}.map-header{flex-direction:row;justify-content:space-between;align-items:center;gap:16px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i4.IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: i4.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: i4.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i4.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonProgressBar, selector: "ion-progress-bar", inputs: ["buffer", "color", "mode", "reversed", "type", "value"] }, { kind: "component", type: i4.IonRow, selector: "ion-row" }, { kind: "component", type: i4.IonSelect, selector: "ion-select", inputs: ["cancelText", "compareWith", "disabled", "interface", "interfaceOptions", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "value"] }, { kind: "component", type: i4.IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: i4.IonToggle, selector: "ion-toggle", inputs: ["checked", "color", "disabled", "mode", "name", "value"] }, { kind: "directive", type: i4.BooleanValueAccessor, selector: "ion-checkbox,ion-toggle" }, { kind: "directive", type: i4.SelectValueAccessor, selector: "ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "component", type: RaainMapComponent, selector: "raain-map", inputs: ["coordinates", "markers", "timeframeContainers", "autoplay", "showMarkers", "showSpeedMarkers", "showCumulative", "currentHeight", "timeframeDates", "defaultDate", "sumValues", "sumFn"], outputs: ["selectedMarker", "changedDate", "changedSum"] }, { kind: "component", type: RaainCompareStackComponent, selector: "raain-compare-stack", inputs: ["compareManager", "currentHeight", "cumulative"], outputs: ["selectedPoint"] }, { kind: "component", type: RaainDateFocusComponent, selector: "raain-date-focus", inputs: ["points", "focusDate", "focusRange", "withoutAll", "currentHeight"] }, { kind: "component", type: RaainDateDynamicComponent, selector: "raain-date-dynamic", inputs: ["points", "focusDate", "focusRange", "withoutAll", "currentHeight", "fetchData"], outputs: ["changedDate"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
2232
2268
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: RaainDetailsComponent, decorators: [{
2233
2269
  type: Component,
2234
- args: [{ selector: 'raain-details', template: "<!-- Main content container -->\n<div *ngIf=\"rainNode\" class=\"raain-details-container\">\n\n <!-- Period selection section -->\n <ion-card class=\"period-card\">\n <ion-card-content>\n <div class=\"period-controls\">\n <div class=\"period-row\">\n <ion-button (click)=\"setPeriodOfNow()\" class=\"now-button\" fill=\"outline\">\n <ion-icon name=\"time-outline\" slot=\"start\"></ion-icon>\n Now\n </ion-button>\n\n <div class=\"period-start ion-hide-md-down\">\n <ion-label>Start:</ion-label>\n <input (change)=\"onPeriodBeginChange($event)\"\n [value]=\"periodBeginAsString\"\n class=\"datetime-input\"\n type=\"datetime-local\">\n </div>\n\n <div class=\"period-duration ion-hide-md-down\">\n <ion-label>Duration:</ion-label>\n <ion-select (ionDismiss)=\"onPeriodDurationChange($event)\"\n [(ngModel)]=\"periodDurationAsString\"\n class=\"duration-select\"\n id=\"periodDuration\"\n interface=\"popover\">\n <ion-select-option value=\"0.25\">15 minutes</ion-select-option>\n <ion-select-option value=\"0.5\">30 minutes</ion-select-option>\n <ion-select-option value=\"1\">1 hour</ion-select-option>\n <ion-select-option value=\"2\">2 hours</ion-select-option>\n <ion-select-option value=\"3\">3 hours</ion-select-option>\n <ion-select-option value=\"4\">4 hours</ion-select-option>\n <ion-select-option value=\"5\">5 hours</ion-select-option>\n <ion-select-option value=\"6\">6 hours</ion-select-option>\n <ion-select-option *ngIf=\"isAdmin\" value=\"24\">24 hours</ion-select-option>\n </ion-select>\n </div>\n\n <div id=\"all-dates\" slot=\"end\">\n <ion-label class=\"toggle-label\">All dates</ion-label>\n <ion-toggle (ionChange)=\"onEnableCountHistoryTab(rainNode)\"\n [(ngModel)]=\"toggleHistory\"\n [checked]=\"toggleHistory\">\n </ion-toggle>\n </div>\n </div>\n\n <!-- Hidden label for change detection -->\n <div class=\"hidden-label\">{{ onChangeDetectionTest(rainNode) }}</div>\n </div>\n\n <!-- Historical map section -->\n <div *ngIf=\"toggleHistory\" class=\"period-controls\">\n <raain-date-dynamic (changedDate)=\"onDateChangeInCount($event)\"\n [currentHeight]=\"300\"\n [fetchData]=\"fetchDataWrapper\"\n [points]=\"countPoints\">\n </raain-date-dynamic>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Map section -->\n <ion-card class=\"map-card\">\n <ion-card-content class=\"map-content\">\n <ion-grid>\n <ion-row id=\"progressAndRefresh\">\n <ion-col size=\"12\" size-md=\"6\">\n <!-- left content (if any) -->\n </ion-col>\n <ion-col class=\"ion-text-right\" size=\"12\" size-md=\"6\">\n <ion-label class=\"ion-margin-end\">\n <span *ngIf=\"getPercentOfComputations()\">\n {{ getPercentOfComputations() }}% Images\n <i *ngIf=\"countsPeriod.progress\" class=\"progress-indicator\">\n In Progress: {{ countsPeriod.progress }}...\n </i>\n </span>\n <span *ngIf=\"!getPercentOfComputations()\">\n No image available\n </span>\n </ion-label>\n\n <ion-button (click)=\"refreshMap()\" [disabled]=\"refreshInProgress\" class=\"refresh-button\">\n Refresh Map\n </ion-button>\n </ion-col>\n\n <!-- Progress indicator -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n <ion-row *ngIf=\"toggleMap && getPercentOfImages()\">\n <!-- Map component -->\n <ion-col class=\"map-column\" size-lg=\"7\">\n <div class=\"map-container\">\n <raain-map\n (changedDate)=\"onDateChangeInMap($event)\"\n (changedSum)=\"onSumChangeInMap($event)\"\n (selectedMarker)=\"onGaugeSelectInMap($event)\"\n [coordinates]=\"coordinates\"\n [currentHeight]=\"500\"\n [defaultDate]=\"dateShown\"\n [markers]=\"{\n borders,\n gauges: compareManager.gaugesInMap,\n gaugesInCompare: compareManager.gaugesInCompare,\n selectedGauges: compareManager.selectedGauges,\n pixels: compareManager.selectedPixels,\n pixelsSolution: compareManager.pixelsSolutions?.length ? compareManager.pixelsSolutions[0] : [],\n speeds: compareManager.speeds\n }\"\n [showCumulative]=\"toggleCumulative\"\n [sumFn]=\"refreshManager.sumFn\"\n [sumValues]=\"refreshManager.sumValues\"\n [timeframeContainers]=\"timeframeContainers\"\n [timeframeDates]=\"timeframeDates\">\n </raain-map>\n </div>\n\n <div class=\"data-column\">\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Image Details</summary>\n <div class=\"details-content\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Date:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDate?.toISOString() }}\n | {{ refreshManager.rainComputationMapDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Water in the map:</span>\n <span class=\"detail-value\">{{ sumDetails }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ min:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMin }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ max:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMax }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n\n <!-- Data panel -->\n <ion-col class=\"data-column\" size-lg=\"5\">\n <div class=\"data-panel\">\n <!-- Compare stack component -->\n <div class=\"compare-stack\">\n <raain-compare-stack\n (selectedPoint)=\"onGaugeSelectInCompare($event)\"\n [compareManager]=\"compareManager\"\n [cumulative]=\"toggleCumulative\">\n </raain-compare-stack>\n </div>\n\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Compare Details</summary>\n <div class=\"details-content\">\n <div [ngClass]=\"{'warning': refreshManager.rainComputationMapDoneDate?.getTime() > compareManager.currentQualityDoneDate?.getTime() + 60000}\"\n class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ compareManager.compareVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Gauges:</span>\n <span class=\"detail-value\">{{ compareManager.gaugesInCompare.length }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Points:</span>\n <span class=\"detail-value\">{{ compareManager.globalComparePoints.length }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n </ion-row>\n <ion-row>\n <!-- Bottom progress bar -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n\n <!-- Gauge values section -->\n <ion-card *ngIf=\"gaugeSelectedPoints.length && gaugeSelectedPoints[0].values.length\" class=\"gauge-card\">\n <ion-card-header>\n <ion-card-title>\n <ion-icon name=\"analytics-outline\"></ion-icon>\n Selected Gauge Data\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <raain-date-focus\n [currentHeight]=\"300\"\n [focusDate]=\"periodBegin\"\n [focusRange]=\"DateRange.DAY\"\n [points]=\"gaugeSelectedPoints\"\n [withoutAll]=\"true\">\n </raain-date-focus>\n </ion-card-content>\n </ion-card>\n\n</div>\n", styles: [".raain-details-container{max-width:var(--app-max-width);margin:0 auto;padding:0 0 24px}.raain-details-card{width:100%;margin-bottom:20px}.raain-details-card ion-card-header{border-bottom:1px solid rgba(var(--ion-color-medium-rgb),.2)}.raain-details-card ion-card-header ion-card-title{display:flex;align-items:center}.raain-details-card ion-card-header ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary)}.node-info-card{background-color:var(--ion-color-light)}.node-info-card .node-header{display:flex;align-items:center}.node-info-card .node-header .node-status{margin-right:16px}.node-info-card .node-header .node-status ion-icon{font-size:24px}.node-info-card .node-header .node-titles{flex:1}.node-info-card .node-header .node-titles ion-card-title{margin:0;font-size:1.4rem;font-weight:600;color:var(--ion-color-dark)}.node-info-card .node-header .node-titles ion-card-subtitle{padding-left:0;margin:4px 0 0;font-size:.9rem;color:var(--ion-color-medium)}.count-map-card,.period-card{background-color:var(--ion-color-light)}.period-card ion-card-title{display:flex;align-items:center}.period-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}.period-row{display:flex;flex-wrap:wrap;align-items:center;gap:16px;position:relative}.now-button{min-width:100px}#all-dates{display:flex;align-items:center;margin-left:auto}#all-dates .toggle-label{margin-right:8px;white-space:nowrap}.refresh-button ion-icon{margin-right:4px;color:var(--ion-color-light)}.period-start,.period-duration{display:flex;align-items:center}.hidden-label{display:none}.datetime-input,#periodDuration,.duration-select{padding:8px 12px;border:1px solid rgba(var(--ion-color-medium-rgb),.3);border-radius:var(--ion-border-radius);background-color:var(--ion-color-light);font-family:var(--ion-font-family)}.datetime-input:focus,#periodDuration:focus,.duration-select:focus{outline:none;border-color:var(--ion-color-primary)}#periodDuration,.duration-select{min-width:150px}.gauge-card{background-color:var(--ion-color-light)}.gauge-card ion-card-title{display:flex;align-items:center}.gauge-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}raain-compare-stack{width:100%;display:block}@media (max-width: 768px){.period-row{flex-direction:row;justify-content:space-between;align-items:center}#all-dates{margin-left:auto;padding-left:8px}#all-dates .toggle-label{font-size:.9rem}.map-header{flex-direction:row;justify-content:space-between;align-items:center;gap:16px}}\n"] }]
2270
+ args: [{ selector: 'raain-details', template: "<!-- Main content container -->\n<div *ngIf=\"rainNode\" class=\"raain-details-container\">\n\n <!-- Period selection section -->\n <ion-card class=\"period-card\">\n <ion-card-content>\n <div class=\"period-controls\">\n <div class=\"period-row\">\n <ion-button (click)=\"setPeriodOfNow()\" class=\"now-button\" fill=\"outline\">\n <ion-icon name=\"time-outline\" slot=\"start\"></ion-icon>\n Now\n </ion-button>\n\n <div class=\"period-start ion-hide-md-down\">\n <ion-label>Start:</ion-label>\n <input (change)=\"onPeriodBeginChange($event)\"\n [value]=\"periodBeginAsString\"\n class=\"datetime-input\"\n type=\"datetime-local\">\n </div>\n\n <div class=\"period-duration ion-hide-md-down\">\n <ion-label>Duration:</ion-label>\n <ion-select (ionDismiss)=\"onPeriodDurationChange($event)\"\n [(ngModel)]=\"periodDurationAsString\"\n class=\"duration-select\"\n id=\"periodDuration\"\n interface=\"popover\">\n <ion-select-option value=\"0.25\">15 minutes</ion-select-option>\n <ion-select-option value=\"0.5\">30 minutes</ion-select-option>\n <ion-select-option value=\"1\">1 hour</ion-select-option>\n <ion-select-option value=\"2\">2 hours</ion-select-option>\n <ion-select-option value=\"3\">3 hours</ion-select-option>\n <ion-select-option value=\"4\">4 hours</ion-select-option>\n <ion-select-option value=\"5\">5 hours</ion-select-option>\n <ion-select-option value=\"6\">6 hours</ion-select-option>\n <ion-select-option *ngIf=\"isAdmin\" value=\"24\">24 hours</ion-select-option>\n </ion-select>\n </div>\n\n <div id=\"all-dates\" slot=\"end\">\n <ion-label class=\"toggle-label\">All dates</ion-label>\n <ion-toggle (ionChange)=\"onEnableCountHistoryTab(rainNode)\"\n [(ngModel)]=\"toggleHistory\"\n [checked]=\"toggleHistory\">\n </ion-toggle>\n </div>\n </div>\n\n <!-- Hidden label for change detection -->\n <div class=\"hidden-label\">{{ onChangeDetectionTest(rainNode) }}</div>\n </div>\n\n <!-- Historical map section -->\n <div *ngIf=\"toggleHistory\" class=\"period-controls\">\n <raain-date-dynamic (changedDate)=\"onDateChangeInCount($event)\"\n [currentHeight]=\"300\"\n [fetchData]=\"fetchDataWrapper\"\n [points]=\"countPoints\">\n </raain-date-dynamic>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Map section -->\n <ion-card class=\"map-card\">\n <ion-card-content class=\"map-content\">\n <ion-grid>\n <ion-row id=\"progressAndRefresh\">\n <ion-col size=\"12\" size-md=\"6\">\n <!-- left content (if any) -->\n </ion-col>\n <ion-col class=\"ion-text-right\" size=\"12\" size-md=\"6\">\n <ion-label class=\"ion-margin-end\">\n <span *ngIf=\"getPercentOfComputations()\">\n {{ getPercentOfComputations() }}% Images\n <i *ngIf=\"countsPeriod.progress\" class=\"progress-indicator\">\n In Progress: {{ countsPeriod.progress }}...\n </i>\n </span>\n <span *ngIf=\"!getPercentOfComputations()\">\n No image available\n </span>\n <span *ngIf=\"refreshManager.lastError\">\n <b>Errors: {{ refreshManager.lastError }}</b>\n </span>\n </ion-label>\n\n <ion-button (click)=\"refreshMap()\" [disabled]=\"refreshInProgress\" class=\"refresh-button\">\n Refresh Map\n </ion-button>\n </ion-col>\n\n <!-- Progress indicator -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n <ion-row *ngIf=\"toggleMap && getPercentOfImages()\">\n <!-- Map component -->\n <ion-col class=\"map-column\" size-lg=\"7\">\n <div class=\"map-container\">\n <raain-map\n (changedDate)=\"onDateChangeInMap($event)\"\n (changedSum)=\"onSumChangeInMap($event)\"\n (selectedMarker)=\"onGaugeSelectInMap($event)\"\n [coordinates]=\"coordinates\"\n [currentHeight]=\"500\"\n [defaultDate]=\"dateShown\"\n [markers]=\"{\n borders,\n gauges: compareManager.gaugesInMap,\n gaugesInCompare: compareManager.gaugesInCompare,\n selectedGauges: compareManager.selectedGauges,\n pixels: compareManager.selectedPixels,\n pixelsSolution: compareManager.pixelsSolutions?.length ? compareManager.pixelsSolutions[0] : [],\n speeds: compareManager.speeds\n }\"\n [showCumulative]=\"toggleCumulative\"\n [sumFn]=\"refreshManager.sumFn\"\n [sumValues]=\"refreshManager.sumValues\"\n [timeframeContainers]=\"timeframeContainers\"\n [timeframeDates]=\"timeframeDates\">\n </raain-map>\n </div>\n\n <div class=\"data-column\">\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Image Details</summary>\n <div class=\"details-content\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Date:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapDate?.toISOString() }}\n | {{ refreshManager.rainComputationMapDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Water in the map:</span>\n <span class=\"detail-value\">{{ sumDetails }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ min:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMin }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Source DBZ max:</span>\n <span class=\"detail-value\">{{ refreshManager.rainComputationMapOriginalMax }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n\n <!-- Data panel -->\n <ion-col class=\"data-column\" size-lg=\"5\">\n <div class=\"data-panel\">\n <!-- Compare stack component -->\n <div class=\"compare-stack\">\n <raain-compare-stack\n (selectedPoint)=\"onGaugeSelectInCompare($event)\"\n [compareManager]=\"compareManager\"\n [cumulative]=\"toggleCumulative\">\n </raain-compare-stack>\n </div>\n\n <!-- Technical details (collapsible for cleaner UI) -->\n <details class=\"technical-details\">\n <summary>Compare Details</summary>\n <div class=\"details-content\">\n <div [ngClass]=\"{'warning': refreshManager.rainComputationMapDoneDate?.getTime() > compareManager.currentQualityDoneDate?.getTime() + 60000}\"\n class=\"detail-row\">\n <span class=\"detail-label\">Computed:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityDoneDate | date:'yyyy-MM-dd HH:mm' }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Version:</span>\n <span class=\"detail-value\">{{ compareManager.compareVersion }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Launched by:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityLaunchedBy }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Time spent:</span>\n <span class=\"detail-value\">{{ compareManager.currentQualityTimeSpentInMs }}\n ms</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Gauges:</span>\n <span class=\"detail-value\">{{ compareManager.gaugesInCompare.length }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Points:</span>\n <span class=\"detail-value\">{{ compareManager.globalComparePoints.length }}</span>\n </div>\n </div>\n </details>\n </div>\n </ion-col>\n </ion-row>\n <ion-row>\n <!-- Bottom progress bar -->\n <ion-progress-bar *ngIf=\"refreshInProgress\"\n [buffer]=\"(countsPeriod.progress / ((timeframeDates?.length || 10) +3))+0.01\"\n [value]=\"countsPeriod.progress / ((timeframeDates?.length || 10) +3)\"\n color=\"primary\">\n </ion-progress-bar>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n\n <!-- Gauge values section -->\n <ion-card *ngIf=\"gaugeSelectedPoints.length && gaugeSelectedPoints[0].values.length\" class=\"gauge-card\">\n <ion-card-header>\n <ion-card-title>\n <ion-icon name=\"analytics-outline\"></ion-icon>\n Selected Gauge Data\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <raain-date-focus\n [currentHeight]=\"300\"\n [focusDate]=\"periodBegin\"\n [focusRange]=\"DateRange.DAY\"\n [points]=\"gaugeSelectedPoints\"\n [withoutAll]=\"true\">\n </raain-date-focus>\n </ion-card-content>\n </ion-card>\n\n</div>\n", styles: [".raain-details-container{max-width:var(--app-max-width);margin:0 auto;padding:0 0 24px}.raain-details-card{width:100%;margin-bottom:20px}.raain-details-card ion-card-header{border-bottom:1px solid rgba(var(--ion-color-medium-rgb),.2)}.raain-details-card ion-card-header ion-card-title{display:flex;align-items:center}.raain-details-card ion-card-header ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary)}.node-info-card{background-color:var(--ion-color-light)}.node-info-card .node-header{display:flex;align-items:center}.node-info-card .node-header .node-status{margin-right:16px}.node-info-card .node-header .node-status ion-icon{font-size:24px}.node-info-card .node-header .node-titles{flex:1}.node-info-card .node-header .node-titles ion-card-title{margin:0;font-size:1.4rem;font-weight:600;color:var(--ion-color-dark)}.node-info-card .node-header .node-titles ion-card-subtitle{padding-left:0;margin:4px 0 0;font-size:.9rem;color:var(--ion-color-medium)}.count-map-card,.period-card{background-color:var(--ion-color-light)}.period-card ion-card-title{display:flex;align-items:center}.period-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}.period-row{display:flex;flex-wrap:wrap;align-items:center;gap:16px;position:relative}.now-button{min-width:100px}#all-dates{display:flex;align-items:center;margin-left:auto}#all-dates .toggle-label{margin-right:8px;white-space:nowrap}.refresh-button ion-icon{margin-right:4px;color:var(--ion-color-light)}.period-start,.period-duration{display:flex;align-items:center}.hidden-label{display:none}.datetime-input,#periodDuration,.duration-select{padding:8px 12px;border:1px solid rgba(var(--ion-color-medium-rgb),.3);border-radius:var(--ion-border-radius);background-color:var(--ion-color-light);font-family:var(--ion-font-family)}.datetime-input:focus,#periodDuration:focus,.duration-select:focus{outline:none;border-color:var(--ion-color-primary)}#periodDuration,.duration-select{min-width:150px}.gauge-card{background-color:var(--ion-color-light)}.gauge-card ion-card-title{display:flex;align-items:center}.gauge-card ion-card-title ion-icon{margin-right:8px;color:var(--ion-color-primary);font-size:20px}raain-compare-stack{width:100%;display:block}@media (max-width: 768px){.period-row{flex-direction:row;justify-content:space-between;align-items:center}#all-dates{margin-left:auto;padding-left:8px}#all-dates .toggle-label{font-size:.9rem}.map-header{flex-direction:row;justify-content:space-between;align-items:center;gap:16px}}\n"] }]
2235
2271
  }], ctorParameters: function () { return [{ type: Storage }]; }, propDecorators: { toggleAdmin: [{
2236
2272
  type: Input
2237
2273
  }], rainNode: [{
@@ -2711,7 +2747,7 @@ class ProfileService {
2711
2747
  radars.forEach((radar) => {
2712
2748
  let found = false;
2713
2749
  rains.forEach((rain) => {
2714
- const rdId = rain.getLink('radar').getId();
2750
+ const rdId = rain.getLink(RadarNode.TYPE).getId();
2715
2751
  if (rdId === radar.id) {
2716
2752
  found = true;
2717
2753
  }