diff --git a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.html b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.html
index 41620d1a2..97dac0228 100644
--- a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.html
+++ b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.html
@@ -16,30 +16,30 @@
- @if(pointHistory.length !== 0) {
+ @if(chartStates.length !== 0) {
- {{task().aoi}}
+ All AOIs
- @for (point of pointHistory; track $index) {
+ @for (point of chartStates; track $index) {
-
place
- {{point.flatCoordinates[1] | floatPrecision: 2}}, {{point.flatCoordinates[0] | floatPrecision: 2}}
+ {{point.geoemetry.getFlatCoordinates()[0] | floatPrecision: 2}}, {{point.geoemetry.getFlatCoordinates()[0] | floatPrecision: 2}}
@@ -147,9 +147,7 @@
diff --git a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts
index 1aa97aa2f..13ad08af7 100644
--- a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts
+++ b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts
@@ -1,5 +1,7 @@
import {Component, OnInit, Input, OnDestroy, ViewChild, ElementRef, computed, signal} from '@angular/core';
-import { first, Observable, Subject } from 'rxjs';
+import { first, Observable,
+ // Subject
+} from 'rxjs';
import { ResizeEvent } from 'angular-resizable-element';
import { Store } from '@ngrx/store';
@@ -7,15 +9,20 @@ import { AppState } from '@store';
import * as uiStore from '@store/ui';
import * as searchStore from '@store/search';
import * as mapStore from '@store/map';
+import * as chartStore from '@store/charts';
-import { DrawService, MapService, NetcdfService, PointHistoryService, ScreenSizeService, WktService } from '@services';
+import { DrawService, MapService, NetcdfService, PointHistoryService, ScreenSizeService,
+ // WktService
+} from '@services';
import { Breakpoints, SearchType, MapInteractionModeType, MapDrawModeType } from '@models';
import { SubSink } from 'subsink';
import { Point } from 'ol/geom';
-import { WKT } from 'ol/format';
+// import { WKT } from 'ol/format';
+import { getTimeseriesChartStates } from '@store/charts';
// import { getPathRange } from '@store/filters';
+import * as models from '@models';
export interface Task {
aoi: string;
@@ -49,9 +56,11 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy {
public breakpoints = Breakpoints;
private subs = new SubSink();
- public pointHistory = [];
+ // public pointHistory = [];
- public chartData = new Subject;
+ // public chartData = new Subject;
+ public chartStates: models.timeseriesChartItemState[] = []
+ public allSeriesChecked$ = this.store$.select(chartStore.getAreAllTimeseriesChecked)
public selectedPoint: number;
// private timeseries_subscription: Subscription;
@@ -60,7 +69,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy {
public dateRange = [];
public totalPoints = 0;
- public isLoading = false;
+ // public isLoading = false;
constructor(
private store$: Store,
@@ -69,7 +78,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy {
private drawService: DrawService,
private mapService: MapService,
private netcdfService: NetcdfService,
- private wktService: WktService
+ // private wktService: WktService
) { }
ngOnInit(): void {
@@ -93,45 +102,47 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy {
)
);
+ this.subs.add(this.store$.select(getTimeseriesChartStates).subscribe(chartStates => {
+ this.chartStates = Object.values(chartStates);
+ }
+ ))
this.subs.add(this.pointHistoryService.history$.subscribe(history => {
- this.pointHistory = history;
+ // this.store$.dispatch(chartStore.set)
+ // this.pointHistory = history;
this.mapService.setDisplacementLayer(history);
- console.log('results menu sub this.pointHistory', this.pointHistory);
- const task = this.task();
- let found = false
- for (const point of this.pointHistory) {
- found = false;
- for (const pt of task.subtasks) {
- if (pt.aoi.toString() === point.flatCoordinates.toString()) {
- found = true;
- break;
- }
- }
- if (!found) {
- let p = {aoi: point.flatCoordinates, checked: true};
- task.subtasks.push(p);
- }
- }
-
- console.log('results menu sub task.subtasks', task.subtasks);
-
- return {...task};
+ // const task = this.task();
+ // let found = false
+ // for (const point of this.pointHistory) {
+ // found = false;
+ // for (const pt of task.subtasks) {
+ // if (pt.aoi.toString() === point.flatCoordinates.toString()) {
+ // found = true;
+ // break;
+ // }
+ // }
+ // if (!found) {
+ // let p = {aoi: point.flatCoordinates, checked: true};
+ // task.subtasks.push(p);
+ // }
+ // }
+
+ // return {...task};
}));
- let thing: string = localStorage.getItem('timeseries-points')
- if(thing && thing.length > 0) {
- let previous_points: any[] = thing?.split(';');
- if(previous_points.length > 0) {
- console.log(previous_points)
- previous_points = previous_points?.map(value => {
- return this.wktService.wktToFeature(value, 'EPSG:4326');
- })
- previous_points?.forEach(point => {
- this.pointHistoryService.addPoint(point.getGeometry());
- })
- }
- }
+ // let thing: string = localStorage.getItem('timeseries-points')
+ // if(thing && thing.length > 0) {
+ // let previous_points: any[] = thing?.split(';');
+ // if(previous_points.length > 0) {
+ // console.log(previous_points)
+ // previous_points = previous_points?.map(value => {
+ // return this.wktService.wktToFeature(value, 'EPSG:4326');
+ // })
+ // previous_points?.forEach(point => {
+ // this.pointHistoryService.addPoint(point.getGeometry());
+ // })
+ // }
+ // }
this.subs.add(this.drawService.polygon$.subscribe(polygon => {
if(polygon) {
@@ -179,24 +190,21 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy {
this.store$.dispatch(new mapStore.SetMapInteractionMode(MapInteractionModeType.NONE));
}
- public onPointClick(index: number) {
- this.pointHistoryService.selectedPoint = index;
- this.pointHistoryService.passDraw = true;
- let format = new WKT();
- let wktRepresenation = format.writeGeometry(this.pointHistory[index]);
- this.mapService.loadPolygonFrom(wktRepresenation.toString())
- }
+ // public onPointClick(index: number) {
+ // this.pointHistoryService.selectedPoint = index;
+ // this.pointHistoryService.passDraw = true;
+ // let format = new WKT();
+ // let wktRepresenation = format.writeGeometry(this.pointHistory[index]);
+ // this.mapService.loadPolygonFrom(wktRepresenation.toString())
+ // }
public updateChart(): void {
let allPointsData = [];
- for (const geometry of this.pointHistory) {
- this.netcdfService.getTimeSeries(geometry).pipe(first()).subscribe(data => {
- console.log('updateChart data', data);
- console.log('updateChart geometry', geometry);
+ for (const series of this.chartStates) {
+ this.netcdfService.getTimeSeries(series.geoemetry).pipe(first()).subscribe(data => {
allPointsData.push(data);
})
- console.log('updateChart allPointsData', allPointsData);
- this.chartData.next(allPointsData);
+ // this.chartData.next(allPointsData);
}
}
@@ -214,27 +222,29 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy {
return task.subtasks.some(t => t.checked) && !task.subtasks.every(t => t.checked);
});
+ public toggleAllSeries(checked: boolean) {
+ this.store$.dispatch(chartStore.setAllTimeseriesChecked({checked}))
+ }
public updateSeries(checked: boolean, index?: number) {
- console.log('updateSeries', checked, index);
- this.task.update(task => {
- if (index === undefined) {
- task.checked = checked;
- task.subtasks?.forEach(t => (t.checked = checked));
- } else {
- task.subtasks![index].checked = checked;
- task.checked = task.subtasks?.every(t => t.checked) ?? true;
- this.pointHistoryService.selectedPoint = index;
- console.log('updateSeries() this.pointHistoryService.selectedPoint', this.pointHistoryService.selectedPoint);
- this.pointHistoryService.passDraw = true;
- let format = new WKT();
- let wktRepresentation = format.writeGeometry(this.pointHistory[index]);
- this.mapService.loadPolygonFrom(wktRepresentation.toString())
- }
- console.log('updateSeries() task', task);
- console.log('updateSeries() task.subtasks', task.subtasks);
- console.log('updateSeries() this.pointHistory', this.pointHistory);
- return {...task};
- });
+ const wkt = this.chartStates[index]?.wkt
+
+ this.store$.dispatch(chartStore.setTimeseriesChecked({wkt, checked}))
+
+ // this.task.update(task => {
+ // if (index === undefined) {
+ // task.checked = checked;
+ // task.subtasks?.forEach(t => (t.checked = checked));
+ // } else {
+ // task.subtasks![index].checked = checked;
+ // task.checked = task.subtasks?.every(t => t.checked) ?? true;
+ // this.pointHistoryService.selectedPoint = index;
+ // this.pointHistoryService.passDraw = true;
+ // let format = new WKT();
+ // let wktRepresentation = format.writeGeometry(this.pointHistory[index]);
+ // this.mapService.loadPolygonFrom(wktRepresentation.toString())
+ // }
+ // return {...task};
+ // });
}
public deletePoint(index: number) {
console.log('delete', index);
diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts
index a185c9c91..3ab68b73c 100644
--- a/src/app/components/timeseries-chart/timeseries-chart.component.ts
+++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts
@@ -1,7 +1,10 @@
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import * as d3 from 'd3';
-import { Observable, Subject } from 'rxjs';
+// import * as models from '@models';
+import { first, Observable,
+ // Subject
+} from 'rxjs';
import { Store } from '@ngrx/store';
import { AppState } from '@store';
@@ -9,6 +12,8 @@ import { AppState } from '@store';
import * as chartsStore from '@store/charts';
import { SubSink } from 'subsink';
import { AsfLanguageService } from "@services/asf-language.service";
+import { NetcdfService } from '@services';
+import * as models from '@models';
// import {style} from '@angular/animations';
interface TimeSeriesChartPoint {
@@ -19,7 +24,8 @@ interface TimeSeriesChartPoint {
date: string
file_name: string,
temporal_baseline: number
- id: string
+ id: string,
+ checked: boolean
}
interface TimeSeriesData {
@@ -29,7 +35,8 @@ interface TimeSeriesData {
interface DataReady {
name: string,
- values: TimeSeriesData[]
+ values: TimeSeriesData[],
+ opacity: number,
}
@Component({
@@ -43,7 +50,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
@Input() zoomIn$: Observable;
@Input() zoomOut$: Observable;
@Input() zoomToFit$: Observable;
- @Input() chartData: Subject;
+ // @Input() chartData: models.timeseriesChartItemState[];
public json_data: string = '';
private svg?: d3.Selection;
@@ -76,6 +83,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
private lineLabels;
private points;
public gColorPalette: any;
+
// private selectedScene: string;
@Input() isLoading: boolean = false;
@@ -89,17 +97,39 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
constructor(
private store$: Store,
private language: AsfLanguageService,
+ private netcdfService: NetcdfService
) { }
public ngOnInit(): void {
this.translateChartText();
this.createSVG();
+ this.subs.add(
+ this.store$.select(chartsStore.getIsChartOutOfDate).subscribe(
- this.chartData.subscribe(data => {
- this.data = data;
- this.initChart(data);
- })
+ )
+ )
+ this.subs.add(
+ this.store$.select(chartsStore.getTimeseriesChartStates).subscribe(
+ chartStates => {
+ const allPointsData: {point: {}, state: models.timeseriesChartItemState}[] = []
+ this.store$.dispatch(chartsStore.setChartOutOfDate())
+ for (const state of Object.values(chartStates)) {
+ this.netcdfService.getTimeSeries(state.geoemetry).pipe(first()).subscribe(data => {
+ allPointsData.push({point: data, state});
+ })
+ }
+ this.isLoading = false
+ this.store$.dispatch(chartsStore.setChartUpToDate())
+ this.data = allPointsData
+ this.initChart(this.data)
+ }
+ )
+ )
+ // this.chartData.subscribe(data => {
+ // this.data = data;
+ // this.initChart(data);
+ // })
this.subs.add(
this.store$.select(chartsStore.getShowLines).subscribe(
@@ -149,50 +179,52 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
this.updateChart();
}
- public initChart(data): void {
+ public initChart(data: {point: {}, state: models.timeseriesChartItemState}[]): void {
this.dataSource = []
+ this.dataReadyForChart = []
if (data?.[Symbol.iterator]) {
let aoi: string = '';
- for (let result of data) {
- aoi = '';
- // pre-process data, remove test v_2 files from results
- // won't be necessary in production
- for (let key of Object.keys(result)) {
- if (key.startsWith('v_2_')) {
- delete result[key];
- }
- if (key.startsWith('aoi')) {
- aoi = result[key];
+ for (let result of data) {
+ aoi = '';
+ // pre-process data, remove test v_2 files from results
+ // won't be necessary in production
+ for (let key of Object.keys(result.point)) {
+ if (key.startsWith('v_2_')) {
+ delete result.point[key];
+ }
+ if (key.startsWith('aoi')) {
+ aoi = result.point[key];
+ }
}
- }
- this.timeSeriesData = [];
- for (let key of Object.keys(result).filter(x => x !== 'mean' && x !== 'aoi')) {
- this.dataSource.push({
- 'aoi': aoi,
- 'short_wavelength_displacement': result[key].short_wavelength_displacement,
- 'interferometric_correlation': result[key].interferometric_correlation,
- 'temporal_coherence': result[key].temporal_coherence,
- 'date': result[key].secondary_datetime,
- 'file_name': key,
- 'id': key,
- 'temporal_baseline': result[key].temporal_baseline
- })
- this.timeSeriesData.push({
- 'short_wavelength_displacement': result[key].short_wavelength_displacement,
- 'date': result[key].secondary_datetime
- });
- }
- this.timeSeriesData.sort((a, b) => {
- if(a.date < b.date) {
- return -1
- } else {
- return 1
+ this.timeSeriesData = [];
+ for (let key of Object.keys(result.point).filter(x => x !== 'mean' && x !== 'aoi')) {
+ this.dataSource.push({
+ 'aoi': aoi,
+ 'short_wavelength_displacement': result.point[key].short_wavelength_displacement,
+ 'interferometric_correlation': result.point[key].interferometric_correlation,
+ 'temporal_coherence': result.point[key].temporal_coherence,
+ 'date': result.point[key].secondary_datetime,
+ 'file_name': key,
+ 'id': key,
+ 'temporal_baseline': result.point[key].temporal_baseline,
+ 'checked': result.state.checked
+ })
+ this.timeSeriesData.push({
+ 'short_wavelength_displacement': result.point[key].short_wavelength_displacement,
+ 'date': result.point[key].secondary_datetime,
+ });
}
- })
- this.dataReadyForChart.push({ 'name': aoi, 'values': this.timeSeriesData });
- this.averageData = ({
- ...data.mean
+ this.timeSeriesData.sort((a, b) => {
+ if(a.date < b.date) {
+ return -1
+ } else {
+ return 1
+ }
})
+ this.dataReadyForChart.push({ 'name': aoi, 'values': this.timeSeriesData, 'opacity': result.state.checked ? 1.0 : 0.4});
+ // this.averageData = ({
+ // ...data.mean
+ // })
}
} else {
this.dataSource = [];
@@ -321,6 +353,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
})
// @ts-ignore
.attr("stroke", function (d: DataReady) { return colorPalette(d.name) })
+ .style("opacity", (d: DataReady) => d.opacity)
.style("stroke-width", 1)
.style("fill", "none")
.style("shape-rendering", "geometricprecision")
@@ -356,6 +389,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
.append('g')
.attr('clip-path', 'url(#clip)')
.style('fill', (d) : string=> { return colorPalette(d.name) })
+ .style('opacity', (d) => d.opacity)
.attr('class', (d) : string=> { return d.name.replace(/\W/g, '')})
.selectAll('circle')
.data(d => d.values)
@@ -386,21 +420,14 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
// the corresponding line. Note: we don't actually use Voronoi here, since an exhaustive search
// is fast enough.
private pointerMoved(event, lines, dots, points) {
- console.log('pointerMoved');
if (typeof points === 'undefined') { return; }
if (points == null) { return; }
const [xm, ym] = d3.pointer(event);
const i = d3.leastIndex(points, ([x, y]) => Math.hypot(Number(x) - xm, Number(y) - ym));
if (typeof points[i] === 'undefined') { return; }
- const [x, y, k] = points[i];
+ const [_x, _y, k] = points[i];
let colorName: string;
let dClassName: string;
- console.log('points', points);
- console.log('points[i]', points[i]);
- console.log('dots', dots);
- console.log('xm', xm, 'ym', ym);
- console.log('i', i);
- console.log('x', x, 'y', y, 'k', k);
lines.style("stroke", (d: DataReady)=> {
if (d.name === k) {
dClassName = 'g.' + d.name.replace(/\W/g, '');
@@ -408,34 +435,19 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
return colorName;
}
return '#ddd';
- });
- dots.selectAll('circle').style("fill", '#ddd');
+ })
+ dots.selectAll('circle').style("fill", '#ddd').style('opacity', d => d.opacity);
dots.selectAll(dClassName).style("fill", 'red');
- // dots.selectAll('myDots').data(this.dataReadyForChart).style("fill", (d: DataReady) => {
- // dots.selectAll('circle').style("fill", (d: DataReady) => {
- // console.log('dots d:', d);
- // if (d.name === k) {
- // return this.gColorPalette(d.name);
- // }
- // return '#ddd';
- // });
- // this.lines.style("stroke", "red").filter(({ z }) => z === k).raise();
- // .attr("stroke", function (d: DataReady) { return colorPalette(d.name) })
- // lines.style("stroke", ({z}) => z === k ? null : "#ddd").filter(({z}) => z === k).raise();
- // dots.attr("transform", `translate(${x},${y})`);
dots.select("text").text(k);
- // this.svg.property("value", this.dataReadyForChart[i]).dispatch("input", {bubbles: true});
}
private pointerEntered(lines, dots) {
- console.log('pointerEntered lines, dots', lines, dots);
lines.style("mix-blend-mode", null).style("stroke", "#ddd");
dots.attr("display", null);
}
- private pointerLeft(lines, dots) {
- console.log('pointerLeft', lines, dots);
+ private pointerLeft(lines, _dots) {
lines.style("stroke", (d: DataReady)=> {
return this.gColorPalette(d.name);
})
@@ -471,6 +483,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy {
.attr("d", function (d) { // @ts-ignore
return line(d.values)
})
+ .style('opacity', (d: DataReady) => d.opacity)
this.lineLabels
.attr("transform",d => `translate(${newX(Date.parse(d.value.date))},${newY(d.value.short_wavelength_displacement)})`) // Put the text at the position of the last point
diff --git a/src/app/models/timeseries.model.ts b/src/app/models/timeseries.model.ts
index 5885d9f34..d2bec3de6 100644
--- a/src/app/models/timeseries.model.ts
+++ b/src/app/models/timeseries.model.ts
@@ -1,3 +1,5 @@
+import { SimpleGeometry } from "ol/geom"
+
export interface TimeSeriesResult {
averages: layerInfo,
coordinates: number[],
@@ -9,4 +11,12 @@ export interface layerInfo {
short_wavelength_displacement: number[],
interferometric_correlation: number[],
temporal_coherence: number[]
+}
+
+export interface timeseriesChartItemState {
+ checked: boolean,
+ color: string,
+ name: string,
+ wkt: string,
+ geoemetry: SimpleGeometry
}
\ No newline at end of file
diff --git a/src/app/services/point-history.service.ts b/src/app/services/point-history.service.ts
index 3615e7da4..da19882fe 100644
--- a/src/app/services/point-history.service.ts
+++ b/src/app/services/point-history.service.ts
@@ -1,4 +1,7 @@
import { Injectable } from '@angular/core';
+import { Store } from '@ngrx/store';
+import { AppState } from '@store';
+import { addTimeseriesState } from '@store/charts';
import WKT from 'ol/format/WKT';
import { Point } from 'ol/geom';
@@ -14,7 +17,9 @@ export class PointHistoryService {
public history$ = new Subject();
public passDraw: boolean = false;
public selectedPoint: number = 0;
+
constructor(
+ private store$: Store
) {
@@ -30,7 +35,11 @@ export class PointHistoryService {
this.passDraw = false
return
}
+ const format = new WKT()
+ // this.history.map((value) => {
+ const wkt = format.writeGeometry(point)
this.history.push(point);
+ this.store$.dispatch(addTimeseriesState({item: {geoemetry: point, checked: true, wkt: wkt, color: '#FFFFFF', name: `Series ${this.history.length}`}}))
this.history$.next(this.history);
this.savePoints();
}
diff --git a/src/app/store/charts/charts.action.ts b/src/app/store/charts/charts.action.ts
index 62f5f2bef..6167e0a10 100644
--- a/src/app/store/charts/charts.action.ts
+++ b/src/app/store/charts/charts.action.ts
@@ -1,5 +1,12 @@
-import { createAction } from '@ngrx/store';
+import { createAction, props } from '@ngrx/store';
+import * as models from '@models';
export const showGraphLines = createAction('[Chart] show lines')
export const hideGraphLines = createAction('[Chart] hide lines')
-export const reset = createAction('[Chart] reset chart options')
\ No newline at end of file
+export const reset = createAction('[Chart] reset chart options')
+export const setTimeseriesStates = createAction('[Chart] sets the checked timeseries', props<{'items': models.timeseriesChartItemState[]}>())
+export const addTimeseriesState = createAction('[Chart] add checked timeseries', props<{'item': models.timeseriesChartItemState}>())
+export const setTimeseriesChecked = createAction('[Chart] set single timeseries as checked/unchecked', props<{'wkt': string, 'checked': boolean}>())
+export const setAllTimeseriesChecked = createAction('[Chart] set all timeseries as checked/unchecked', props<{'checked': boolean}>())
+export const setChartOutOfDate = createAction('[Chart] mark chart as out of date')
+export const setChartUpToDate = createAction('[Chart], mark chart as up to date')
\ No newline at end of file
diff --git a/src/app/store/charts/charts.reducer.ts b/src/app/store/charts/charts.reducer.ts
index 8d6f57802..577df7634 100644
--- a/src/app/store/charts/charts.reducer.ts
+++ b/src/app/store/charts/charts.reducer.ts
@@ -1,17 +1,53 @@
import { createReducer, on } from '@ngrx/store';
-import { showGraphLines, hideGraphLines, reset } from './charts.action';
+import * as chartActions from './charts.action';
+import * as models from '@models';
export interface ChartsState {
- showLines: boolean;
+ showLines: boolean;
+ seriesStates: { [key: string]: models.timeseriesChartItemState };
+ outOfDate: boolean;
}
export const initialState: ChartsState = {
- showLines: true
+ showLines: true,
+ seriesStates: {},
+ outOfDate: false
};
export const chartsReducer = createReducer(
initialState,
- on(showGraphLines, (state) => ({...state, showLines: true})),
- on(hideGraphLines, (state) => ({...state, showLines: false})),
- on(reset, (_) => initialState)
+ on(chartActions.showGraphLines, (state) => ({ ...state, showLines: true })),
+ on(chartActions.hideGraphLines, (state) => ({ ...state, showLines: false })),
+ on(chartActions.setTimeseriesChecked, (state, { wkt, checked }) => {
+ // const output = { ...state };
+ // if (wkt in output.seriesStates) {
+ // output.seriesStates[wkt].checked = checked;
+ // }
+
+ const seriesState = { ...state.seriesStates, [wkt]: { ...state.seriesStates[wkt], checked } }
+ return { ...state, seriesStates: seriesState }
+ // return output;
+ }),
+ on(chartActions.setTimeseriesStates, (state, { items }) => ({
+ ...state, seriesStates: items.reduce((prev: { [key: string]: models.timeseriesChartItemState }, curr) => {
+ prev[curr.wkt] = { checked: true, color: curr.color, name: curr.name, wkt: curr.wkt, geoemetry: curr.geoemetry }
+ return prev
+ }, {})
+ }
+ )),
+ on(chartActions.addTimeseriesState, (state, { item }) => {
+
+ const seriesState = { ...state.seriesStates, [item.wkt]: item }
+ return { ...state, seriesStates: seriesState }
+ }),
+ on(chartActions.setAllTimeseriesChecked, (state, { checked }) => {
+ const seriesStates = Object.values(state.seriesStates).reduce((prev, curr) => {
+ prev[curr.wkt] = { ...curr, checked }
+ return prev
+ }, {});
+ return {...state, seriesStates}
+ }),
+ on(chartActions.setChartOutOfDate, (state) => ({...state, outOfDate: true})),
+ on(chartActions.setChartUpToDate, (state) => ({...state, outOfDate: false})),
+ on(chartActions.reset, (_) => initialState)
);
diff --git a/src/app/store/charts/charts.selectors.ts b/src/app/store/charts/charts.selectors.ts
index 94ef485ad..e63bfe248 100644
--- a/src/app/store/charts/charts.selectors.ts
+++ b/src/app/store/charts/charts.selectors.ts
@@ -6,4 +6,36 @@ export const getChartsState = createFeatureSelector('charts');
export const getShowLines = createSelector(
getChartsState,
(state: ChartsState) => state.showLines
+);
+
+export const getTimeseriesChartStates = createSelector(
+ getChartsState,
+ (state: ChartsState) => state.seriesStates
+);
+
+export const getCheckedTimeseries = createSelector(
+ getTimeseriesChartStates,
+ (chartStates) => {
+ const output = {};
+ for (const key in Object.keys(chartStates)) {
+ if (chartStates[key].checked) {
+ output[key] = chartStates[key];
+ }
+ }
+
+ return output;
+ }
+);
+
+export const getAreAllTimeseriesChecked = createSelector(
+ getTimeseriesChartStates,
+ getTimeseriesChartStates,
+ (checked, all) => {
+ return Object.keys(checked).length === Object.keys(all).length
+ }
+)
+
+export const getIsChartOutOfDate = createSelector(
+ getChartsState,
+ (state) => state.outOfDate
)
\ No newline at end of file