From db68400ad73d6335c5beae50a03d26889d4315ee Mon Sep 17 00:00:00 2001 From: Andrew Anderson Date: Mon, 11 Nov 2024 16:02:40 -0800 Subject: [PATCH 1/5] WIP before redo of subs --- ...eseries-chart-temporal-slider.component.ts | 141 ++++++++++++++---- 1 file changed, 113 insertions(+), 28 deletions(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts index 7331e2edd..d95c12fb9 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts @@ -11,6 +11,10 @@ import {SubSink} from "subsink"; // import wNumb from 'wnumb'; import * as filtersStore from '@store/filters'; import * as models from '@models'; +import moment from 'moment/moment'; +import {Observable, Subject} from 'rxjs'; +import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; +// import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; @Component({ selector: 'app-timeseries-chart-temporal-slider', @@ -23,9 +27,14 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit { private subs = new SubSink(); - public slider; + public tsSlider: noUiSlider.API; + public timeSeriesSlider: { slider: noUiSlider.API; values$: Observable }; public maxRange: models.Range = {start: Date.now.valueOf(), end: Date.now.valueOf()}; - // private firstLoad = true; + public selectedRange: models.Range = {start: Date.now.valueOf(), end: Date.now.valueOf()}; + public startDate$ = this.store$.select(filtersStore.getStartDate); + public endDate$ = this.store$.select(filtersStore.getEndDate); + public startDate: Date = new Date(); + public endDate: Date = new Date(); @@ -34,20 +43,69 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit { ){} ngOnInit() { + + // this.subs.add( + // this.timeSeriesSlider.values$.subscribe( + // ([start, end]) => { + // console.log('*** timeseries-chart-temporal-slider selected range values$ ***', start, end); + // if (start === this.selectedRange.start && end === this.selectedRange.end) { + // return; + // } + // // const action = new filtersStore.SetPerpendicularRange({ start, end }); + // // this.store$.dispatch(action); + // } + // ) + // ); + this.subs.add( this.store$.select(filtersStore.getTemporalRange).subscribe( temp => { this.maxRange = {start: temp.start, end: temp.end}; console.log('timeseries-chart-temporal-slider', this.maxRange); - if (this.slider) { this.slider.destroy(); } - this.makeDaysSlider(this.sliderRef); + this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); + console.log('**** this.timeSeriesSlider ****', this.timeSeriesSlider); } ) ); - // this.makeDaysSlider(this.sliderRef); + this.subs.add( + this.startDate$.subscribe( + start => { + this.startDate = start; + if (this.endDate < this.startDate && !!this.endDate) { + const endOfDay = this.endDateFormat(this.startDate); + this.store$.dispatch(new filtersStore.SetEndDate(endOfDay)); + } + } + ) + ); + + this.subs.add( + this.endDate$.subscribe( + end => { + this.endDate = end; + if (this.startDate > this.endDate && !!this.startDate && !!this.endDate) { + this.store$.dispatch(new filtersStore.SetStartDate(this.endDate)); + } + } + ) + ); } + public onStartDateChange(date): void { + this.store$.dispatch(new filtersStore.SetStartDate(date)); + } + + public onEndDateChange(date): void { + this.store$.dispatch(new filtersStore.SetEndDate(date)); + } + + private endDateFormat(date: Date | moment.Moment) { + const endDate = moment(date).utc().endOf('day'); + return this.toJSDate(endDate); + } + + private timestamp(str) { return new Date(str).getTime(); } @@ -64,32 +122,59 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit { return new Date(value).toLocaleDateString(); } - public makeDaysSlider(filterRef: ElementRef): void { + private toJSDate(date: moment.Moment) { + return date.toDate(); + } + + // private isNumber(x: any): x is number { + // return typeof x === "number"; + // } + + public makeTimeSeriesSlider(filterRef: ElementRef): { slider: noUiSlider.API; values$: Observable } { const self = this; + const values$ = new Subject(); // Steps of one day const increment = 24 * 60 * 60 * 1000; - this.slider = noUiSlider.create(filterRef.nativeElement, { - start: [this.maxRange.start.valueOf(), this.maxRange.end.valueOf()], - behaviour: 'tap-drag', - tooltips: [{to: (d) => self.toFormat(d)}, {to: (d) => self.toFormat(d)}], - connect: true, - step: increment, - range: { - 'min': this.maxRange.start.valueOf(), - 'max': this.maxRange.end.valueOf() - }, - pips: { - // @ts-ignore - mode: 'count', - values: 5, - stepped: true, - density: 4, - format: { - from: (value) => {return self.timestamp(value);}, - to: self.toFormat - } - }, - }); + let maxStart = this.maxRange.start ? this.maxRange.start.valueOf() : 0; + let maxEnd = this.maxRange.end ? this.maxRange.end.valueOf() : 0; + if (maxStart != 0 && maxEnd != 0) { + if (filterRef.nativeElement && filterRef.nativeElement.noUiSlider) { filterRef.nativeElement.noUiSlider.destroy(); } + this.tsSlider = noUiSlider.create(filterRef.nativeElement, { + start: [maxStart, maxEnd], + behaviour: 'tap-drag', + tooltips: [{to: (d) => self.toFormat(d)}, {to: (d) => self.toFormat(d)}], + connect: true, + step: increment, + range: { + 'min': maxStart, + 'max': maxEnd + }, + pips: { + // @ts-ignore + mode: 'count', + values: 5, + stepped: true, + density: 4, + format: { + from: (value) => {return self.timestamp(value);}, + to: self.toFormat + } + }, + }); + + this.tsSlider.on('update', (values: any[], _: any) => { + console.log('*** timeseries-chart-temporal-slider values ***', values); + values$.next(values.map(v => +v)); + }); + + return { + slider: this.tsSlider, + values$: values$.asObservable().pipe( + debounceTime(500), + distinctUntilChanged() + ) + }; + } } ngOnDestroy(){ From 7c89bb912431f9c3c2fd5d13111ffa279c3217e7 Mon Sep 17 00:00:00 2001 From: Andrew Anderson Date: Tue, 12 Nov 2024 12:18:45 -0800 Subject: [PATCH 2/5] WIP --- ...eseries-chart-temporal-slider.component.ts | 126 ++++++++++-------- 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts index d95c12fb9..9aa1ff4d0 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts @@ -1,4 +1,4 @@ -import {Component, ElementRef, ViewChild, OnInit} from '@angular/core'; +import {Component, ElementRef, ViewChild, OnInit, OnDestroy} from '@angular/core'; import * as noUiSlider from 'nouislider'; import { Store } from "@ngrx/store"; import { AppState } from "@store"; @@ -11,7 +11,7 @@ import {SubSink} from "subsink"; // import wNumb from 'wnumb'; import * as filtersStore from '@store/filters'; import * as models from '@models'; -import moment from 'moment/moment'; +// import moment from 'moment/moment'; import {Observable, Subject} from 'rxjs'; import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; // import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; @@ -22,7 +22,7 @@ import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; templateUrl: './timeseries-chart-temporal-slider.component.html', styleUrls: ['./timeseries-chart-temporal-slider.component.scss'] }) -export class TimeseriesChartTemporalSliderComponent implements OnInit { +export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy { @ViewChild('ts_slider', { static: true }) sliderRef: ElementRef; private subs = new SubSink(); @@ -44,66 +44,86 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit { ngOnInit() { - // this.subs.add( - // this.timeSeriesSlider.values$.subscribe( - // ([start, end]) => { - // console.log('*** timeseries-chart-temporal-slider selected range values$ ***', start, end); - // if (start === this.selectedRange.start && end === this.selectedRange.end) { - // return; - // } - // // const action = new filtersStore.SetPerpendicularRange({ start, end }); - // // this.store$.dispatch(action); - // } - // ) - // ); - this.subs.add( this.store$.select(filtersStore.getTemporalRange).subscribe( temp => { this.maxRange = {start: temp.start, end: temp.end}; + this.selectedRange = {start: temp.start, end: temp.end}; console.log('timeseries-chart-temporal-slider', this.maxRange); this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); console.log('**** this.timeSeriesSlider ****', this.timeSeriesSlider); + this.subs.add( + this.timeSeriesSlider.values$.subscribe( + ([start, end]) => { + console.log('*** timeseries-chart-temporal-slider selected range values$ ***', start, end); + console.log('*** timeseries-chart-temporal-slider selected range types ***', typeof start, typeof end); + if (start === this.selectedRange.start && end === this.selectedRange.end) { + return; + } + const action = new filtersStore.SetStartDate(new Date(start)); + this.store$.dispatch(action); + const action2 = new filtersStore.SetEndDate(new Date(end)); + this.store$.dispatch(action2); + + this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); + + } + ) + ); } ) ); - this.subs.add( - this.startDate$.subscribe( - start => { - this.startDate = start; - if (this.endDate < this.startDate && !!this.endDate) { - const endOfDay = this.endDateFormat(this.startDate); - this.store$.dispatch(new filtersStore.SetEndDate(endOfDay)); - } - } - ) - ); + // this.subs.add( + // this.store$.select(filtersStore.getStartDate).subscribe( + // start => { + // this.startDate = start; + // if (this.lastRange !== this.perpRange) { + // this.lastRange = this.perpRange; + // this.perpendicularSlider.set([perp.start, perp.end]); + // } + // } + // ) + // ); - this.subs.add( - this.endDate$.subscribe( - end => { - this.endDate = end; - if (this.startDate > this.endDate && !!this.startDate && !!this.endDate) { - this.store$.dispatch(new filtersStore.SetStartDate(this.endDate)); - } - } - ) - ); - } + // this.subs.add( + // this.startDate$.subscribe( + // start => { + // this.startDate = start; + // if (this.endDate < this.startDate && !!this.endDate) { + // const endOfDay = this.endDateFormat(this.startDate); + // this.store$.dispatch(new filtersStore.SetEndDate(endOfDay)); + // } + // } + // ) + // ); + // + // this.subs.add( + // this.endDate$.subscribe( + // end => { + // this.endDate = end; + // if (this.startDate > this.endDate && !!this.startDate && !!this.endDate) { + // this.store$.dispatch(new filtersStore.SetStartDate(this.endDate)); + // } + // } + // ) + // ); - public onStartDateChange(date): void { - this.store$.dispatch(new filtersStore.SetStartDate(date)); - } - public onEndDateChange(date): void { - this.store$.dispatch(new filtersStore.SetEndDate(date)); - } + } - private endDateFormat(date: Date | moment.Moment) { - const endDate = moment(date).utc().endOf('day'); - return this.toJSDate(endDate); - } + // public onStartDateChange(date): void { + // this.store$.dispatch(new filtersStore.SetStartDate(date)); + // } + // + // public onEndDateChange(date): void { + // this.store$.dispatch(new filtersStore.SetEndDate(date)); + // } + // + // private endDateFormat(date: Date | moment.Moment) { + // const endDate = moment(date).utc().endOf('day'); + // return this.toJSDate(endDate); + // } private timestamp(str) { @@ -122,9 +142,9 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit { return new Date(value).toLocaleDateString(); } - private toJSDate(date: moment.Moment) { - return date.toDate(); - } + // private toJSDate(date: moment.Moment) { + // return date.toDate(); + // } // private isNumber(x: any): x is number { // return typeof x === "number"; @@ -137,10 +157,12 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit { const increment = 24 * 60 * 60 * 1000; let maxStart = this.maxRange.start ? this.maxRange.start.valueOf() : 0; let maxEnd = this.maxRange.end ? this.maxRange.end.valueOf() : 0; + let selectedStart = this.selectedRange.start ? this.selectedRange.start.valueOf() : 0; + let selectedEnd = this.selectedRange.end ? this.selectedRange.end.valueOf() : 0; if (maxStart != 0 && maxEnd != 0) { if (filterRef.nativeElement && filterRef.nativeElement.noUiSlider) { filterRef.nativeElement.noUiSlider.destroy(); } this.tsSlider = noUiSlider.create(filterRef.nativeElement, { - start: [maxStart, maxEnd], + start: [selectedStart, selectedEnd], behaviour: 'tap-drag', tooltips: [{to: (d) => self.toFormat(d)}, {to: (d) => self.toFormat(d)}], connect: true, From 7ddb6603f96c735a81d1fbd58f789e0f4a81db59 Mon Sep 17 00:00:00 2001 From: Andrew Anderson Date: Tue, 12 Nov 2024 13:33:46 -0800 Subject: [PATCH 3/5] WIP --- ...eseries-chart-temporal-slider.component.ts | 53 ------------------- .../timeseries-chart.component.ts | 53 +++++++++++++++---- 2 files changed, 44 insertions(+), 62 deletions(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts index 9aa1ff4d0..974997fc8 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts @@ -64,9 +64,7 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy this.store$.dispatch(action); const action2 = new filtersStore.SetEndDate(new Date(end)); this.store$.dispatch(action2); - this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); - } ) ); @@ -74,58 +72,8 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy ) ); - // this.subs.add( - // this.store$.select(filtersStore.getStartDate).subscribe( - // start => { - // this.startDate = start; - // if (this.lastRange !== this.perpRange) { - // this.lastRange = this.perpRange; - // this.perpendicularSlider.set([perp.start, perp.end]); - // } - // } - // ) - // ); - - // this.subs.add( - // this.startDate$.subscribe( - // start => { - // this.startDate = start; - // if (this.endDate < this.startDate && !!this.endDate) { - // const endOfDay = this.endDateFormat(this.startDate); - // this.store$.dispatch(new filtersStore.SetEndDate(endOfDay)); - // } - // } - // ) - // ); - // - // this.subs.add( - // this.endDate$.subscribe( - // end => { - // this.endDate = end; - // if (this.startDate > this.endDate && !!this.startDate && !!this.endDate) { - // this.store$.dispatch(new filtersStore.SetStartDate(this.endDate)); - // } - // } - // ) - // ); - - } - // public onStartDateChange(date): void { - // this.store$.dispatch(new filtersStore.SetStartDate(date)); - // } - // - // public onEndDateChange(date): void { - // this.store$.dispatch(new filtersStore.SetEndDate(date)); - // } - // - // private endDateFormat(date: Date | moment.Moment) { - // const endDate = moment(date).utc().endOf('day'); - // return this.toJSDate(endDate); - // } - - private timestamp(str) { return new Date(str).getTime(); } @@ -185,7 +133,6 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy }); this.tsSlider.on('update', (values: any[], _: any) => { - console.log('*** timeseries-chart-temporal-slider values ***', values); values$.next(values.map(v => +v)); }); diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts index 35e76f488..32ed758b7 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts @@ -2,11 +2,12 @@ import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@ang import * as d3 from 'd3'; // import * as models from '@models'; -import { debounceTime, Observable, withLatestFrom, - // Subject +import { debounceTime, Observable, withLatestFrom, + // Subject } from 'rxjs'; import { Store } from '@ngrx/store'; +import * as filtersStore from '@store/filters'; import { AppState } from '@store'; // import * as sceneStore from '@store/scenes'; import * as chartsStore from '@store/charts'; @@ -72,7 +73,12 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { private lineLabels; private points; public gColorPalette: any; - + public startDate: Date = new Date(); + public endDate: Date = new Date(); + public lastStartDate: Date = new Date(); + public lastEndDate: Date = new Date(); + + // private selectedScene: string; @Input() isLoading: boolean = false; @@ -99,8 +105,6 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { ) ) - - this.subs.add( this.netcdfService.cacheUpdated.pipe( debounceTime(1000), @@ -108,12 +112,12 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { ).subscribe(([_updated_id, chartStates]) => { this.refreshChart(chartStates); })); - + this.subs.add( this.store$.select(chartsStore.getTimeseriesChartStates).subscribe( chartStates => { this.refreshChart(chartStates); - } + } ) ); @@ -130,7 +134,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.initChart(this.data); } ) - ) + ); this.subs.add( this.language.translate.onLangChange.subscribe(() => { @@ -141,7 +145,37 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { } ) ); + + this.subs.add( + this.store$.select(filtersStore.getStartDate).subscribe( + start => { + this.startDate = start; + if (this.lastStartDate !== this.startDate) { + this.lastStartDate = this.startDate; + console.log('timeseries-chart has a new start date', this.startDate); + // this.lastRange = this.perpRange; + // this.perpendicularSlider.set([perp.start, perp.end]); + } + } + ) + ); + + this.subs.add( + this.store$.select(filtersStore.getEndDate).subscribe( + end => { + this.endDate = end; + if (this.lastEndDate !== this.endDate) { + this.lastEndDate = this.endDate; + console.log('timeseries-chart has a new end date', this.endDate); + // this.lastRange = this.perpRange; + // this.perpendicularSlider.set([perp.start, perp.end]); + } + } + ) + ); + } + private refreshChart(chartStates: {[key: string]: models.timeseriesChartItemState}): void { const cache = this.netcdfService.getCache() const allPointsData: {point: {}, state: models.timeseriesChartItemState}[] = Object.keys(chartStates).map( @@ -150,6 +184,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.data = allPointsData; this.initChart(this.data) } + public translateChartText() { this.xAxisTitle = this.language.translate.instant('SCENE') + ' ' + this.language.translate.instant('DATE'); @@ -190,7 +225,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { aoi = result.point[key]; } } - + this.timeSeriesData = []; for (let key of Object.keys(result.point).filter(x => x !== 'mean' && x !== 'aoi')) { this.dataSource.push({ From 5fede6770a489e277e782e0a336b2ad392ca4213 Mon Sep 17 00:00:00 2001 From: Andrew Anderson Date: Tue, 12 Nov 2024 16:27:55 -0800 Subject: [PATCH 4/5] WIP slider getting better --- .../timeseries-results-menu.component.ts | 20 +-- ...eseries-chart-temporal-slider.component.ts | 146 ++++++++++-------- 2 files changed, 91 insertions(+), 75 deletions(-) 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 49ec9512c..443ef6029 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 @@ -123,7 +123,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { this.chartStates = Object.values(chartStates); } )); - + this.subs.add( this.temporalRangeValues$.subscribe( range => { @@ -215,13 +215,13 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { allPointsData.push(data); // this.chartData.next(allPointsData); this.temporalRange = this.getMaxRange(allPointsData); - console.log('updateChart dataDateMin, dataDateMax', this.dataDateMin, this.dataDateMax); - console.log('updateChart allPointsData', allPointsData); + // console.log('updateChart dataDateMin, dataDateMax', this.dataDateMin, this.dataDateMax); + // console.log('updateChart allPointsData', allPointsData); }) } this.maxRange = this.getMaxRange(allPointsData); - console.log('updateChart dataDateMin, dataDateMax', this.dataDateMin, this.dataDateMax); - console.log('updateChart allPointsData', allPointsData); + // console.log('updateChart dataDateMin, dataDateMax', this.dataDateMin, this.dataDateMax); + // console.log('updateChart allPointsData', allPointsData); } readonly task = signal({ @@ -246,10 +246,10 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { let maxDate = null; for (let points of allSeries) { for (let key of Object.keys(points).filter(x => x !== 'mean' && x !== 'aoi')) { - console.log('getMaxRange key', key); - console.log('getMaxRange points[key]', points[key]); + // console.log('getMaxRange key', key); + // console.log('getMaxRange points[key]', points[key]); let date = new Date(points[key].secondary_datetime); - console.log('getMaxRange date', date); + // console.log('getMaxRange date', date); if (minDate === null || date < minDate) { minDate = date; } @@ -260,7 +260,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { } let dateRange: models.Range = {start: minDate, end: maxDate}; this.temporalRangeValues$.next([dateRange.start, dateRange.end]); - console.log('getMaxRange dateRange', dateRange); + // console.log('getMaxRange dateRange', dateRange); return dateRange; } @@ -271,7 +271,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { this.store$.dispatch(chartStore.setTimeseriesChecked({wkt, checked})) } public deletePoint(index: number) { - console.log('delete', index); + // console.log('delete', index); this.pointHistoryService.removePoint(index); } ngOnDestroy() { diff --git a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts index 974997fc8..361ed49fc 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts @@ -28,50 +28,72 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy private subs = new SubSink(); public tsSlider: noUiSlider.API; - public timeSeriesSlider: { slider: noUiSlider.API; values$: Observable }; - public maxRange: models.Range = {start: Date.now.valueOf(), end: Date.now.valueOf()}; - public selectedRange: models.Range = {start: Date.now.valueOf(), end: Date.now.valueOf()}; + public timeSeriesSlider: any; + public maxRange: models.Range = {start: 0, end: 100}; + public lastMaxRange: models.Range = {start: 0, end: 100}; + public selectedRange: models.Range = {start: 0, end: 100}; public startDate$ = this.store$.select(filtersStore.getStartDate); public endDate$ = this.store$.select(filtersStore.getEndDate); public startDate: Date = new Date(); public endDate: Date = new Date(); - - constructor( private store$: Store ){} ngOnInit() { + this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); + this.tsSlider = this.timeSeriesSlider.slider; + this.subs.add( this.store$.select(filtersStore.getTemporalRange).subscribe( temp => { - this.maxRange = {start: temp.start, end: temp.end}; - this.selectedRange = {start: temp.start, end: temp.end}; - console.log('timeseries-chart-temporal-slider', this.maxRange); - this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); + console.log('timeseries-chart-temporal-slider temporal range', temp); + if (!temp.start || !temp.end) { return; } + this.maxRange = {start: temp.start.valueOf(), end: temp.end.valueOf()}; + console.log('timeseries-chart-temporal-slider maxRange', this.maxRange); console.log('**** this.timeSeriesSlider ****', this.timeSeriesSlider); - this.subs.add( - this.timeSeriesSlider.values$.subscribe( - ([start, end]) => { - console.log('*** timeseries-chart-temporal-slider selected range values$ ***', start, end); - console.log('*** timeseries-chart-temporal-slider selected range types ***', typeof start, typeof end); - if (start === this.selectedRange.start && end === this.selectedRange.end) { - return; - } - const action = new filtersStore.SetStartDate(new Date(start)); - this.store$.dispatch(action); - const action2 = new filtersStore.SetEndDate(new Date(end)); - this.store$.dispatch(action2); - this.timeSeriesSlider = this.makeTimeSeriesSlider(this.sliderRef); + if (this.lastMaxRange.start !== this.maxRange.start || this.lastMaxRange.end !== this.maxRange.end) { + this.lastMaxRange.start = this.maxRange.start; + this.lastMaxRange.end = this.maxRange.end; + + console.log('**** this.timeSeriesSlider.noUiSlider.updateOptions range ****', this.maxRange.start, this.maxRange.end); + this.sliderRef.nativeElement.noUiSlider.updateOptions({ + start: [this.maxRange.start, this.maxRange.end], + range: { + 'min': this.maxRange.start, + 'max': this.maxRange.end } - ) - ); + }); + } } ) ); + this.subs.add( + this.timeSeriesSlider.values$.subscribe( + ([start, end]) => { + if (!start || !end) { return; } + console.log('*** timeseries-chart-temporal-slider selected range values$ ***', start, end); + console.log('*** timeseries-chart-temporal-slider selected range types ***', typeof start, typeof end); + if (start === this.selectedRange.start && end === this.selectedRange.end) { + return; + } + this.selectedRange = {start: start, end: end}; + console.log('**** this.timeSeriesSlider.noUiSlider.updateOptions start ****', this.selectedRange.start, this.selectedRange.end); + this.sliderRef.nativeElement.noUiSlider.updateOptions({ + start: [this.selectedRange.start, this.selectedRange.end] + }); + const action = new filtersStore.SetStartDate(new Date(start)); + this.store$.dispatch(action); + const action2 = new filtersStore.SetEndDate(new Date(end)); + this.store$.dispatch(action2); + } + ) + ); + + } private timestamp(str) { @@ -103,47 +125,41 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy const values$ = new Subject(); // Steps of one day const increment = 24 * 60 * 60 * 1000; - let maxStart = this.maxRange.start ? this.maxRange.start.valueOf() : 0; - let maxEnd = this.maxRange.end ? this.maxRange.end.valueOf() : 0; - let selectedStart = this.selectedRange.start ? this.selectedRange.start.valueOf() : 0; - let selectedEnd = this.selectedRange.end ? this.selectedRange.end.valueOf() : 0; - if (maxStart != 0 && maxEnd != 0) { - if (filterRef.nativeElement && filterRef.nativeElement.noUiSlider) { filterRef.nativeElement.noUiSlider.destroy(); } - this.tsSlider = noUiSlider.create(filterRef.nativeElement, { - start: [selectedStart, selectedEnd], - behaviour: 'tap-drag', - tooltips: [{to: (d) => self.toFormat(d)}, {to: (d) => self.toFormat(d)}], - connect: true, - step: increment, - range: { - 'min': maxStart, - 'max': maxEnd - }, - pips: { - // @ts-ignore - mode: 'count', - values: 5, - stepped: true, - density: 4, - format: { - from: (value) => {return self.timestamp(value);}, - to: self.toFormat - } - }, - }); - - this.tsSlider.on('update', (values: any[], _: any) => { - values$.next(values.map(v => +v)); - }); - - return { - slider: this.tsSlider, - values$: values$.asObservable().pipe( - debounceTime(500), - distinctUntilChanged() - ) - }; - } + const slider = noUiSlider.create(filterRef.nativeElement, { + start: [1, 100], + behaviour: 'tap-drag', + tooltips: [{to: (d) => self.toFormat(d)}, {to: (d) => self.toFormat(d)}], + connect: true, + step: increment, + range: { + 'min': 1, + 'max': 100 + }, + pips: { + // @ts-ignore + mode: 'count', + values: 5, + stepped: true, + density: 4, + format: { + from: (value) => {return self.timestamp(value);}, + to: self.toFormat + } + }, + }); + + // this.tsSlider.on('update', (values: any[], _: any) => { + // values$.next(values.map(v => +v)); + // }); + + return { + slider, + values$: values$.asObservable().pipe( + debounceTime(500), + distinctUntilChanged() + ) + }; + } ngOnDestroy(){ From fc1fc65bde9c0a4861994e72dc57129bd434d4d7 Mon Sep 17 00:00:00 2001 From: Andrew Anderson Date: Tue, 12 Nov 2024 17:46:35 -0800 Subject: [PATCH 5/5] Slider fully working - first draft --- .../timeseries-results-menu.component.ts | 10 ---------- ...timeseries-chart-temporal-slider.component.ts | 14 +++----------- .../timeseries-chart.component.ts | 16 +++++----------- 3 files changed, 8 insertions(+), 32 deletions(-) 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 443ef6029..e01f20a8c 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 @@ -148,7 +148,6 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { 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'); }) @@ -215,13 +214,9 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { allPointsData.push(data); // this.chartData.next(allPointsData); this.temporalRange = this.getMaxRange(allPointsData); - // console.log('updateChart dataDateMin, dataDateMax', this.dataDateMin, this.dataDateMax); - // console.log('updateChart allPointsData', allPointsData); }) } this.maxRange = this.getMaxRange(allPointsData); - // console.log('updateChart dataDateMin, dataDateMax', this.dataDateMin, this.dataDateMax); - // console.log('updateChart allPointsData', allPointsData); } readonly task = signal({ @@ -246,10 +241,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { let maxDate = null; for (let points of allSeries) { for (let key of Object.keys(points).filter(x => x !== 'mean' && x !== 'aoi')) { - // console.log('getMaxRange key', key); - // console.log('getMaxRange points[key]', points[key]); let date = new Date(points[key].secondary_datetime); - // console.log('getMaxRange date', date); if (minDate === null || date < minDate) { minDate = date; } @@ -260,7 +252,6 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { } let dateRange: models.Range = {start: minDate, end: maxDate}; this.temporalRangeValues$.next([dateRange.start, dateRange.end]); - // console.log('getMaxRange dateRange', dateRange); return dateRange; } @@ -271,7 +262,6 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { this.store$.dispatch(chartStore.setTimeseriesChecked({wkt, checked})) } public deletePoint(index: number) { - // console.log('delete', index); this.pointHistoryService.removePoint(index); } ngOnDestroy() { diff --git a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts index 361ed49fc..111d51fcd 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-temporal-slider/timeseries-chart-temporal-slider.component.ts @@ -49,16 +49,12 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy this.subs.add( this.store$.select(filtersStore.getTemporalRange).subscribe( temp => { - console.log('timeseries-chart-temporal-slider temporal range', temp); if (!temp.start || !temp.end) { return; } this.maxRange = {start: temp.start.valueOf(), end: temp.end.valueOf()}; - console.log('timeseries-chart-temporal-slider maxRange', this.maxRange); - console.log('**** this.timeSeriesSlider ****', this.timeSeriesSlider); if (this.lastMaxRange.start !== this.maxRange.start || this.lastMaxRange.end !== this.maxRange.end) { this.lastMaxRange.start = this.maxRange.start; this.lastMaxRange.end = this.maxRange.end; - console.log('**** this.timeSeriesSlider.noUiSlider.updateOptions range ****', this.maxRange.start, this.maxRange.end); this.sliderRef.nativeElement.noUiSlider.updateOptions({ start: [this.maxRange.start, this.maxRange.end], range: { @@ -75,13 +71,10 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy this.timeSeriesSlider.values$.subscribe( ([start, end]) => { if (!start || !end) { return; } - console.log('*** timeseries-chart-temporal-slider selected range values$ ***', start, end); - console.log('*** timeseries-chart-temporal-slider selected range types ***', typeof start, typeof end); if (start === this.selectedRange.start && end === this.selectedRange.end) { return; } this.selectedRange = {start: start, end: end}; - console.log('**** this.timeSeriesSlider.noUiSlider.updateOptions start ****', this.selectedRange.start, this.selectedRange.end); this.sliderRef.nativeElement.noUiSlider.updateOptions({ start: [this.selectedRange.start, this.selectedRange.end] }); @@ -103,7 +96,6 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy // Create a string representation of the date. public formatDate(date: any) :string { let fDateStr = date.toLocaleDateString() - console.log('date, formatDate', date, fDateStr); return ( fDateStr ); } @@ -148,9 +140,9 @@ export class TimeseriesChartTemporalSliderComponent implements OnInit, OnDestroy }, }); - // this.tsSlider.on('update', (values: any[], _: any) => { - // values$.next(values.map(v => +v)); - // }); + slider.on('update', (values: any[], _: any) => { + values$.next(values.map(v => +v)); + }); return { slider, diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts index 32ed758b7..b55a8b66c 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts @@ -152,10 +152,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.startDate = start; if (this.lastStartDate !== this.startDate) { this.lastStartDate = this.startDate; - console.log('timeseries-chart has a new start date', this.startDate); - // this.lastRange = this.perpRange; - // this.perpendicularSlider.set([perp.start, perp.end]); - } + this.initChart(this.data); } } ) ); @@ -166,10 +163,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.endDate = end; if (this.lastEndDate !== this.endDate) { this.lastEndDate = this.endDate; - console.log('timeseries-chart has a new end date', this.endDate); - // this.lastRange = this.perpRange; - // this.perpendicularSlider.set([perp.start, perp.end]); - } + this.initChart(this.data); } } ) ); @@ -228,6 +222,8 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.timeSeriesData = []; for (let key of Object.keys(result.point).filter(x => x !== 'mean' && x !== 'aoi')) { + let daDate = new Date(result.point[key].secondary_datetime).valueOf(); + if (daDate < this.startDate.valueOf() || daDate > this.endDate.valueOf()) { continue; } this.dataSource.push({ 'aoi': aoi, 'short_wavelength_displacement': result.point[key].short_wavelength_displacement, @@ -483,13 +479,11 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { } private pointerEntered(lines, dots) { - console.log('pointerEntered lines, dots', lines, dots); lines.style("mix-blend-mode", null).style("stroke", unSelectedColor); dots.attr("display", null); } - private pointerLeft(lines, dots) { - console.log('pointerLeft', lines, dots); + private pointerLeft(lines, _dots) { let colorName: string; let dClassName: string; lines.style("stroke", (d: DataReady)=> {