From 3a631412b94f34d026dc8194301ef771eaf94c63 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Mon, 9 Dec 2024 21:08:15 -0500 Subject: [PATCH 1/9] feat: add series to url params --- src/app/services/map/map.service.ts | 1 - src/app/services/point-history.service.ts | 20 +++- src/app/services/url-state.service.ts | 128 +++++++++++++++++----- src/app/store/charts/charts.action.ts | 1 + src/app/store/charts/charts.reducer.ts | 3 + 5 files changed, 122 insertions(+), 31 deletions(-) diff --git a/src/app/services/map/map.service.ts b/src/app/services/map/map.service.ts index ee6c8bf4e..67787495f 100644 --- a/src/app/services/map/map.service.ts +++ b/src/app/services/map/map.service.ts @@ -754,7 +754,6 @@ export class MapService { let base_url = `https://d3g9emy65n853h.cloudfront.net/main/${dir.toLowerCase()}/${layerType.toLowerCase()}`; this.displacementOverview$.next(type); - console.log(type, base_url); this.http.get(`${base_url}/extent.json`).pipe( first() diff --git a/src/app/services/point-history.service.ts b/src/app/services/point-history.service.ts index e64258cfb..9b8787c6b 100644 --- a/src/app/services/point-history.service.ts +++ b/src/app/services/point-history.service.ts @@ -1,7 +1,8 @@ import { Injectable } from '@angular/core'; +import { timeseriesChartItemState } from '@models'; import { Store } from '@ngrx/store'; import { AppState } from '@store'; -import { addTimeseriesState, removeTimeseriesState } from '@store/charts'; +import { addTimeseriesState, removeTimeseriesState, resetTimeseriesStates } from '@store/charts'; import WKT from 'ol/format/WKT'; import { Point } from 'ol/geom'; @@ -42,6 +43,23 @@ export class PointHistoryService { this.history$.next(this.history); this.savePoints(); } + + public addPoints(states: timeseriesChartItemState[]) { + for(let state of states) { + const point = state.geoemetry as Point; + this.history.push({point, wkt: state.wkt}); + this.store$.dispatch(addTimeseriesState({item: state})) + } + this.history$.next(this.history); + this.savePoints(); + } + + public clear() { + this.history = []; + this.history$.next(this.history); + this.store$.dispatch(resetTimeseriesStates()) + this.savePoints(); + } public removePoint(index) { // const format = new WKT() const wkt = this.history[index].wkt diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts index d050046db..1ca1c4d0b 100644 --- a/src/app/services/url-state.service.ts +++ b/src/app/services/url-state.service.ts @@ -7,6 +7,7 @@ import { filter, map, skip, debounceTime, take, distinctUntilChanged } from 'rxj import { AppState } from '@store'; import * as hyp3Store from '@store/hyp3'; +import * as chartsStore from '@store/charts'; import * as scenesStore from '@store/scenes'; import * as mapStore from '@store/map'; import * as filterStore from '@store/filters'; @@ -21,6 +22,9 @@ import { WktService } from './wkt.service'; import { RangeService } from './range.service'; import { PropertyService } from './property.service'; import { ThemingService } from './theming.service'; +import { PointHistoryService } from './point-history.service'; +import WKT from 'ol/format/WKT'; +import { Point } from 'ol/geom'; @Injectable({ @@ -37,7 +41,7 @@ export class UrlStateService { } private kioskMode = false; // for opera displacement - private displacementHostNames = ['displacement.asf.alaska.edu', 'search-displacement.asf.alaska.edu']; + private displacementHostNames = ['local.asf.alaska.edu', 'displacement.asf.alaska.edu', 'search-displacement.asf.alaska.edu']; public isDefaultSearch$ = this.activatedRoute.queryParams.pipe( map(params => { const keys = Object.keys(params) @@ -58,14 +62,19 @@ export class UrlStateService { private router: Router, private prop: PropertyService, private themeService: ThemingService, + private pointHistoryService: PointHistoryService ) { this.kioskMode = this.displacementHostNames.includes(window.location.hostname); - + let params = []; if(this.kioskMode) { this.store$.dispatch(new setSearchKioskMode(true)); + params = [ + ...this.displacementParameters(), + ...this.displacementKioskParameters$() + ] } else { - const params = [ + params = [ ...this.datasetParam(), ...this.mapParameters(), ...this.uiParameters(), @@ -75,20 +84,21 @@ export class UrlStateService { ...this.sbasParameters(), ...this.onDemandParameters(), ...this.eventMonitorParameters(), + ...this.displacementParameters(), ]; + } - this.urlParamNames = params.map(param => param.name); - this.loadLocations = this.urlParamNames.reduce((locations, paramName) => { - locations[paramName] = models.LoadTypes.DEFAULT; + this.urlParamNames = params.map(param => param.name); + this.loadLocations = this.urlParamNames.reduce((locations, paramName) => { + locations[paramName] = models.LoadTypes.DEFAULT; - return locations; - }, {}); - this.urlParams = params.reduce((res, param) => { - res[param.name] = param; + return locations; + }, {}); + this.urlParams = params.reduce((res, param) => { + res[param.name] = param; - return res; - }, {}); - } + return res; + }, {}); this.updateShouldSearch(); } @@ -97,23 +107,21 @@ export class UrlStateService { if (this.kioskMode) { this.store$.dispatch(new SetSearchType(models.SearchType.DISPLACEMENT)) } - else { - this.activatedRoute.queryParams.pipe( + this.activatedRoute.queryParams.pipe( + skip(1), + take(1), + ).subscribe( + params => this.loadStateFrom(params) + ); + + this.urlParamNames.forEach( + paramName => this.urlParams[paramName].source.pipe( skip(1), - take(1), + debounceTime(300) ).subscribe( - params => this.loadStateFrom(params) - ); - - this.urlParamNames.forEach( - paramName => this.urlParams[paramName].source.pipe( - skip(1), - debounceTime(300) - ).subscribe( - this.updateRouteWithParams - ) - ); - } + this.updateRouteWithParams + ) + ); } private updateRouteWithParams = (queryParams: Params): void => { @@ -123,7 +131,6 @@ export class UrlStateService { .filter(key => params[key] !== '' && params[key] !== this.defaultbooleanParams?.[key]) .reduce((res, key) => (res[key] = params[key], res), {}); - this.params = paramsWithValues; this.router.navigate(['.'], { @@ -195,6 +202,8 @@ export class UrlStateService { } else { this.themeService.setTheme('theme-light'); } + } else { + this.store$.dispatch(new scenesStore.SetResultsLoaded(true)) } const action = profile.mapLayer === models.MapLayerTypes.STREET ? new mapStore.SetStreetView() : @@ -314,6 +323,55 @@ export class UrlStateService { }]; } + private displacementParameters() { + return [ + { + name: 'series', + source: this.store$.select(chartsStore.getTimeseriesChartStates).pipe( + // map(productTypes => productTypes.map(productType => productType.id)), + // map(productTypeStrings => productTypeStrings.join(',')), + // map(productTypes => ({eventProductTypes: productTypes ?? ''})) + // this.store$.dispatch(addTimeseriesState({item: {geoemetry: point, checked: true, seriesNumber, wkt: wkt, name: `Series ${seriesNumber}`, linearFit: false}})) + + map(seriesState => { + return {'series': Object.values(seriesState).map(x => [x.wkt, x.seriesNumber].join(';')).join(',')} + }), + ), + loader: this.loadSeriesState + } + ] + } + + private displacementKioskParameters$() { + return [ + { + name: 'view', + source: this.store$.select(mapStore.getMapView).pipe( + map(view => ({ view })) + ), + loader: this.loadMapView + }, { + name: 'center', + source: this.mapService.center$.pipe( + map( + ({ lon, lat }) => ({ + lon: lon.toFixed(3), + lat: lat.toFixed(3) + }) + ), + map(({ lon, lat }) => ({ center: `${lon},${lat}` })) + ), + loader: this.loadMapCenter + }, { + name: 'zoom', + source: this.mapService.zoom$.pipe( + map(zoom => ({ zoom: zoom.toFixed(3) })) + ), + loader: this.loadMapZoom + }, + ] + } + private missionParameters(): models.UrlParameter[] { return [{ @@ -885,4 +943,16 @@ export class UrlStateService { private loadUseCalibrationData = (usingCalibrationData: string): Action => { return new filterStore.setUseCalibrationData(!!usingCalibrationData) } + + private loadSeriesState = (seriesState)=> { + let states: models.timeseriesChartItemState[] = []; + seriesState.split(',').forEach(x => { + const format = new WKT() + let thing = x.split(';') + const point = format.readFeature(thing[0]) as unknown as Point; + states.push({ geoemetry: point, checked: true, seriesNumber: thing[1], wkt: thing[0], name: `Series ${thing[1]}`, linearFit: false }) + }) + this.pointHistoryService.addPoints(states) + return ; + } } diff --git a/src/app/store/charts/charts.action.ts b/src/app/store/charts/charts.action.ts index b9ff76abc..0f9e7c2be 100644 --- a/src/app/store/charts/charts.action.ts +++ b/src/app/store/charts/charts.action.ts @@ -5,6 +5,7 @@ export const showGraphLines = createAction('[Chart] show lines') export const hideGraphLines = createAction('[Chart] hide lines') export const reset = createAction('[Chart] reset chart options') export const setTimeseriesStates = createAction('[Chart] sets the checked timeseries', props<{'items': models.timeseriesChartItemState[]}>()) +export const resetTimeseriesStates = createAction('[Chart] Reset timeseries states') export const addTimeseriesState = createAction('[Chart] add checked timeseries', props<{'item': models.timeseriesChartItemState}>()) export const removeTimeseriesState = createAction('[Chart] removes timeseries by wkt', props<{'wkt': string}>()) export const setTimeseriesChecked = createAction('[Chart] set single timeseries as checked/unchecked', props<{'wkt': string, 'checked': boolean}>()) diff --git a/src/app/store/charts/charts.reducer.ts b/src/app/store/charts/charts.reducer.ts index 2ddde7858..be7583e48 100644 --- a/src/app/store/charts/charts.reducer.ts +++ b/src/app/store/charts/charts.reducer.ts @@ -37,6 +37,9 @@ export const chartsReducer = createReducer( }, {}) } )), + on(chartActions.resetTimeseriesStates, (state) => { + return {...state, seriesStates: {}} + }), on(chartActions.addTimeseriesState, (state, { item }) => { const seriesState = { ...state.seriesStates, [item.wkt]: item } From bd8e835c6abbe9d26a8150a280ec428c773463e3 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Mon, 9 Dec 2024 21:08:34 -0500 Subject: [PATCH 2/9] feat: clear search with series --- src/app/app.component.ts | 19 ++++++++++++++++++- .../timeseries-results-menu.component.ts | 12 +----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index cbfd5b185..b4a04ca09 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -18,6 +18,7 @@ import { HelpComponent } from '@components/help/help.component'; import { AppState } from '@store'; import * as scenesStore from '@store/scenes'; +import * as chartsStore from '@store/charts'; import * as filterStore from '@store/filters'; import * as searchStore from '@store/search'; import * as uiStore from '@store/ui'; @@ -98,6 +99,7 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit { public language: services.AsfLanguageService, public _adapter: DateAdapter, private titleService: Title, + private pointHistoryService: services.PointHistoryService, @Inject(MAT_DATE_LOCALE) public _locale: string, ) { } @@ -458,7 +460,9 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit { this.store$.select(uiStore.getIsResultsMenuOpen), this.store$.select(scenesStore.getAreResultsLoaded) ]).pipe( - filter(([_, searchType, _resultsOpen, resultsLoaded]) => searchType == SearchType.DISPLACEMENT && !resultsLoaded) + filter(([_, searchType, _resultsOpen, resultsLoaded]) => { + // TODO: this seems to sometimes not work, sometimes clearing isn't actually setting resultsLoaded to false + return searchType == SearchType.DISPLACEMENT && !resultsLoaded}) ).subscribe(([polygon, _, __]) => { if (polygon) { if (polygon.getGeometry().getType() === 'Point') { @@ -467,6 +471,18 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit { } } })) + + + this.subs.add(this.store$.select(chartsStore.getTimeseriesChartStates).pipe( + withLatestFrom(this.pointHistoryService.history$) + ).subscribe(([chartStates, history]) => { + let data = [] + for (const p of history) { + data.push({ point: p.point, seriesNumber: chartStates[p.wkt].seriesNumber, color: chartStates[p.wkt].color }) + } + this.mapService.setDisplacementLayer(data); + + })); } public ngAfterViewInit(): void { @@ -480,6 +496,7 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit { } public onClearSearch(): void { + this.pointHistoryService.clear(); this.store$.dispatch(new scenesStore.ClearScenes()); this.store$.dispatch(new scenesStore.SetSelectedSarviewsEvent('')); this.mapService.clearDrawLayer(); 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 a484766c1..f4f1c0320 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 @@ -9,7 +9,7 @@ import * as searchStore from '@store/search'; import * as chartStore from '@store/charts'; import { - DrawService, MapService, NetcdfService, PointHistoryService, ScreenSizeService, + DrawService, NetcdfService, PointHistoryService, ScreenSizeService, WktService } from '@services'; import { Breakpoints, SearchType } from '@models'; @@ -93,7 +93,6 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { private screenSize: ScreenSizeService, public pointHistoryService: PointHistoryService, private drawService: DrawService, - private mapService: MapService, private netcdfService: NetcdfService, private wktService: WktService ) { } @@ -138,16 +137,7 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { ) ); - this.subs.add(this.store$.select(getTimeseriesChartStates).pipe( - withLatestFrom(this.pointHistoryService.history$) - ).subscribe(([chartStates, history]) => { - let data = [] - for (const p of history) { - data.push({ point: p.point, seriesNumber: chartStates[p.wkt].seriesNumber, color: chartStates[p.wkt].color }) - } - this.mapService.setDisplacementLayer(data); - })); let thing: string = localStorage.getItem('timeseries-points') if (thing && thing.length > 0) { From 27f477654998297aaae6fac7667d267c457a8be9 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Mon, 9 Dec 2024 23:05:28 -0500 Subject: [PATCH 3/9] feat: add flight direction to url state --- ...chart-flight-direction-toggle.component.ts | 37 ++++++++++++------- src/app/services/url-state.service.ts | 15 +++++++- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts b/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts index 7fbfb8334..149d3a4bd 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts @@ -4,7 +4,6 @@ import { AppState } from '@store'; import { SubSink } from 'subsink'; import * as filtersStore from '@store/filters'; import * as models from '@models'; -import { SetFlightDirections } from '@store/filters'; import { map } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { MatButtonModule } from '@angular/material/button'; @@ -23,19 +22,29 @@ export class TimeseriesChartFlightDirectionToggleComponent implements OnInit { public FlightDirections = models.FlightDirection; constructor(private store$: Store) {} -ngOnInit(): void { - this.subs.add( - this.store$.select(filtersStore.getFlightDirections).pipe( - map(dir => dir[0] ?? this.flightDirection) - ).subscribe( - dir => this.flightDirection = dir + ngOnInit(): void { + this.subs.add( + this.store$.select(filtersStore.getFlightDirections).pipe( + map(dir => dir[0] ?? this.flightDirection) + ).subscribe( + dir => this.flightDirection = dir + ) ) - ) - -} -public onToggle(): void { - const outputDirection = this.flightDirection === this.FlightDirections.ASCENDING ? this.FlightDirections.DESCENDING : this.FlightDirections.ASCENDING - this.store$.dispatch(new SetFlightDirections([outputDirection])) -} + } + + public onToggle(): void { + const outputDirection = this.flightDirection === this.FlightDirections.ASCENDING ? this.FlightDirections.DESCENDING : this.FlightDirections.ASCENDING + + const dir = outputDirection + .toLowerCase(); + + const capitalized = this.capitalizeFirstLetter(dir); + + const action = new filtersStore.SetFlightDirections([capitalized]); + this.store$.dispatch(action); + } + private capitalizeFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } } diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts index 1ca1c4d0b..816533f95 100644 --- a/src/app/services/url-state.service.ts +++ b/src/app/services/url-state.service.ts @@ -368,7 +368,14 @@ export class UrlStateService { map(zoom => ({ zoom: zoom.toFixed(3) })) ), loader: this.loadMapZoom - }, + }, { + name: 'flightDirs', + source: this.store$.select(filterStore.getFlightDirections).pipe( + map(dirs => dirs.join(',')), + map(flightDirs => ({ flightDirs })) + ), + loader: this.loadFlightDirections + } ] } @@ -801,11 +808,13 @@ export class UrlStateService { }; private loadFlightDirections = (dirsStr: string): Action => { + console.log('test') + console.log(dirsStr) const directions: models.FlightDirection[] = dirsStr .split(',') .filter(direction => !Object.values(models.FlightDirection).includes(direction)) .map(direction => direction); - + console.log(directions) return new filterStore.SetFlightDirections(directions); }; @@ -955,4 +964,6 @@ export class UrlStateService { this.pointHistoryService.addPoints(states) return ; } + + } From d3d3526bb0c515bfcdd3ea1298b174cc9a2c4ce1 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Tue, 10 Dec 2024 10:10:07 -0500 Subject: [PATCH 4/9] feat: add end/start to url --- src/app/app.component.ts | 11 +++++++---- src/app/services/point-history.service.ts | 3 +++ src/app/services/url-state.service.ts | 21 +++++++++++++++------ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b4a04ca09..34374b68a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -476,11 +476,14 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit { this.subs.add(this.store$.select(chartsStore.getTimeseriesChartStates).pipe( withLatestFrom(this.pointHistoryService.history$) ).subscribe(([chartStates, history]) => { - let data = [] - for (const p of history) { - data.push({ point: p.point, seriesNumber: chartStates[p.wkt].seriesNumber, color: chartStates[p.wkt].color }) + if(Object.keys(chartStates).length === history.length) { + let data = [] + + for (const p of history) { + data.push({ point: p.point, seriesNumber: chartStates[p.wkt].seriesNumber, color: chartStates[p.wkt].color }) + } + this.mapService.setDisplacementLayer(data); } - this.mapService.setDisplacementLayer(data); })); } diff --git a/src/app/services/point-history.service.ts b/src/app/services/point-history.service.ts index 9b8787c6b..33979d46d 100644 --- a/src/app/services/point-history.service.ts +++ b/src/app/services/point-history.service.ts @@ -45,6 +45,9 @@ export class PointHistoryService { } public addPoints(states: timeseriesChartItemState[]) { + if(states.length <= 0) { + return + } for(let state of states) { const point = state.geoemetry as Point; this.history.push({point, wkt: state.wkt}); diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts index 816533f95..968460c65 100644 --- a/src/app/services/url-state.service.ts +++ b/src/app/services/url-state.service.ts @@ -41,7 +41,7 @@ export class UrlStateService { } private kioskMode = false; // for opera displacement - private displacementHostNames = ['local.asf.alaska.edu', 'displacement.asf.alaska.edu', 'search-displacement.asf.alaska.edu']; + private displacementHostNames = [ 'displacement.asf.alaska.edu', 'search-displacement.asf.alaska.edu']; public isDefaultSearch$ = this.activatedRoute.queryParams.pipe( map(params => { const keys = Object.keys(params) @@ -375,7 +375,20 @@ export class UrlStateService { map(flightDirs => ({ flightDirs })) ), loader: this.loadFlightDirections - } + }, + { + name: 'start', + source: this.store$.select(filterStore.getStartDate).pipe( + map(start => ({ start: start === null ? '' : moment.utc( start ).format() })) + ), + loader: this.loadStartDate + }, { + name: 'end', + source: this.store$.select(filterStore.getEndDate).pipe( + map(end => ({ end: end === null ? '' : moment.utc( end ).format() })) + ), + loader: this.loadEndDate + }, ] } @@ -808,13 +821,10 @@ export class UrlStateService { }; private loadFlightDirections = (dirsStr: string): Action => { - console.log('test') - console.log(dirsStr) const directions: models.FlightDirection[] = dirsStr .split(',') .filter(direction => !Object.values(models.FlightDirection).includes(direction)) .map(direction => direction); - console.log(directions) return new filterStore.SetFlightDirections(directions); }; @@ -965,5 +975,4 @@ export class UrlStateService { return ; } - } From 06766f470d245aaa7d264dde0fdd4f47ea54fc0a Mon Sep 17 00:00:00 2001 From: tylercchase Date: Tue, 10 Dec 2024 10:35:10 -0500 Subject: [PATCH 5/9] fix: flight direction string weirdness --- ...chart-flight-direction-toggle.component.ts | 8 ++---- src/app/services/map/map.service.ts | 2 +- src/app/services/url-state.service.ts | 26 ++++++++++++------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts b/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts index 149d3a4bd..a7fdddc85 100644 --- a/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart-flight-direction-toggle/timeseries-chart-flight-direction-toggle.component.ts @@ -37,14 +37,10 @@ export class TimeseriesChartFlightDirectionToggleComponent implements OnInit { const outputDirection = this.flightDirection === this.FlightDirections.ASCENDING ? this.FlightDirections.DESCENDING : this.FlightDirections.ASCENDING const dir = outputDirection - .toLowerCase(); + .toUpperCase(); - const capitalized = this.capitalizeFirstLetter(dir); - const action = new filtersStore.SetFlightDirections([capitalized]); + const action = new filtersStore.SetFlightDirections([dir]); this.store$.dispatch(action); } - private capitalizeFirstLetter(str) { - return str.charAt(0).toUpperCase() + str.slice(1); - } } diff --git a/src/app/services/map/map.service.ts b/src/app/services/map/map.service.ts index 67787495f..0d8437005 100644 --- a/src/app/services/map/map.service.ts +++ b/src/app/services/map/map.service.ts @@ -748,7 +748,6 @@ export class MapService { [models.DisplacementLayerTypes.DISPLACEMENT]: 'DISP', [models.DisplacementLayerTypes.VELOCITY]: 'VEL' } - const dir = apiDirValues[direction]; const layerType = apiDispValues[type]; @@ -818,6 +817,7 @@ export class MapService { this.displacementOverview$.next(null); } + public setDisplacementLayer(points: { point: Point, seriesNumber: number, color: string }[]) { if (!!this.displacmentLayer) { this.map.removeLayer(this.displacmentLayer); diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts index 968460c65..504b6b925 100644 --- a/src/app/services/url-state.service.ts +++ b/src/app/services/url-state.service.ts @@ -328,17 +328,19 @@ export class UrlStateService { { name: 'series', source: this.store$.select(chartsStore.getTimeseriesChartStates).pipe( - // map(productTypes => productTypes.map(productType => productType.id)), - // map(productTypeStrings => productTypeStrings.join(',')), - // map(productTypes => ({eventProductTypes: productTypes ?? ''})) - // this.store$.dispatch(addTimeseriesState({item: {geoemetry: point, checked: true, seriesNumber, wkt: wkt, name: `Series ${seriesNumber}`, linearFit: false}})) - map(seriesState => { return {'series': Object.values(seriesState).map(x => [x.wkt, x.seriesNumber].join(';')).join(',')} }), ), loader: this.loadSeriesState - } + }, + // { + // name: 'dispOverview', + // source: this.mapService.displacementOverview$.pipe( + // map(dispOverview => ({dispOverview})), + // ), + // loader: this.loadDispOverview + // } ] } @@ -823,11 +825,14 @@ export class UrlStateService { private loadFlightDirections = (dirsStr: string): Action => { const directions: models.FlightDirection[] = dirsStr .split(',') - .filter(direction => !Object.values(models.FlightDirection).includes(direction)) + .filter(direction => !Object.values(models.FlightDirection).includes(this.capitalizeFirstLetter(direction.toLowerCase()))) .map(direction => direction); return new filterStore.SetFlightDirections(directions); }; + private capitalizeFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } private loadSelectedMission = (mission: string): Action => { return new filterStore.SelectMission(mission); }; @@ -972,7 +977,10 @@ export class UrlStateService { states.push({ geoemetry: point, checked: true, seriesNumber: thing[1], wkt: thing[0], name: `Series ${thing[1]}`, linearFit: false }) }) this.pointHistoryService.addPoints(states) - return ; + return; } - + // private loadDispOverview = (dispOverview) => { + // this.mapService.setDisplacementType(dispOverview); + // return; + // } } From dc1dd14f9207da9ee4b0fc57e1c653663dcb8bd7 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Tue, 10 Dec 2024 11:47:22 -0500 Subject: [PATCH 6/9] feat: disp map layer config url state --- .../displacement-layers.component.html | 3 +- .../displacement-layers.component.ts | 7 +++- src/app/services/map/map.service.ts | 8 +++++ src/app/services/url-state.service.ts | 36 +++++++++++++------ 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/app/components/map/displacement-layers/displacement-layers.component.html b/src/app/components/map/displacement-layers/displacement-layers.component.html index b7a7c3bf3..1e42ad768 100644 --- a/src/app/components/map/displacement-layers/displacement-layers.component.html +++ b/src/app/components/map/displacement-layers/displacement-layers.component.html @@ -15,7 +15,8 @@ - +
Rollout
diff --git a/src/app/components/map/displacement-layers/displacement-layers.component.ts b/src/app/components/map/displacement-layers/displacement-layers.component.ts index 779a49ca0..2f9bca72a 100644 --- a/src/app/components/map/displacement-layers/displacement-layers.component.ts +++ b/src/app/components/map/displacement-layers/displacement-layers.component.ts @@ -21,7 +21,7 @@ export class DisplacementLayersComponent implements OnInit, OnDestroy { public displacementOverview: models.DisplacementLayerTypes | null = null; public DispLayerTypes = models.DisplacementLayerTypes; - + public priorityEnabled = false; private subs = new SubSink(); constructor( @@ -53,6 +53,11 @@ export class DisplacementLayersComponent implements OnInit, OnDestroy { } ) ) + this.subs.add( + this.mapService.priorityEnabled$.subscribe(t => { + this.priorityEnabled = t !== null; + }) + ) } public onUpdatePriority(isChecked: boolean): void { diff --git a/src/app/services/map/map.service.ts b/src/app/services/map/map.service.ts index 0d8437005..81174045a 100644 --- a/src/app/services/map/map.service.ts +++ b/src/app/services/map/map.service.ts @@ -77,6 +77,7 @@ export class MapService { private displacementOverview: TileLayer; public displacementOverview$ = new BehaviorSubject(null); private priorityOverview: VectorLayer; + public priorityEnabled$ = new BehaviorSubject(null); private selectClick = new Select({ condition: click, @@ -816,6 +817,9 @@ export class MapService { this.displacementOverview = null; this.displacementOverview$.next(null); } + public setDisplacementType(type) { + this.displacementOverview$.next(type) + } public setDisplacementLayer(points: { point: Point, seriesNumber: number, color: string }[]) { @@ -894,6 +898,8 @@ export class MapService { format: new GeoJSON({}) }, ) + this.priorityEnabled$.next(flight_dir); + const colorTable = [ 'rgba(174, 174, 174, 0.6)', 'rgba(127, 206, 255, 0.8)', @@ -931,6 +937,8 @@ export class MapService { public disablePriority(): void { this.map.removeLayer(this.priorityOverview); this.priorityOverview = null; + this.priorityEnabled$.next(null); + } public isPriorityEnabled(): boolean { diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts index 504b6b925..e8c41b822 100644 --- a/src/app/services/url-state.service.ts +++ b/src/app/services/url-state.service.ts @@ -334,13 +334,21 @@ export class UrlStateService { ), loader: this.loadSeriesState }, - // { - // name: 'dispOverview', - // source: this.mapService.displacementOverview$.pipe( - // map(dispOverview => ({dispOverview})), - // ), - // loader: this.loadDispOverview - // } + { + name: 'dispOverview', + source: this.mapService.displacementOverview$.pipe( + map(dispOverview => ({dispOverview})), + ), + loader: this.loadDispOverview + }, + { + + name: 'isPriorityEnabled', + source: this.mapService.priorityEnabled$.pipe( + map(isPriorityEnabled => ({isPriorityEnabled})), + ), + loader: this.loadDispPriority + } ] } @@ -979,8 +987,14 @@ export class UrlStateService { this.pointHistoryService.addPoints(states) return; } - // private loadDispOverview = (dispOverview) => { - // this.mapService.setDisplacementType(dispOverview); - // return; - // } + private loadDispOverview = (dispOverview) => { + this.mapService.setDisplacementType(dispOverview); + return; + } + private loadDispPriority = (isDispPriorityEnabled) => { + if(isDispPriorityEnabled) { + this.mapService.enablePriority(isDispPriorityEnabled); + } + return; + } } From e3a53122221852b0d9fe429f40cd8282cca83335 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Tue, 10 Dec 2024 12:06:33 -0500 Subject: [PATCH 7/9] fix: use flight direction when loading in data --- .../timeseries-chart.component.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts index 5fad43e67..90725b47d 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts @@ -2,7 +2,7 @@ import {Component, ElementRef, Input, OnDestroy, OnInit, QueryList, ViewChild, V import * as d3 from 'd3'; // import * as models from '@models'; import { - debounceTime, Observable, withLatestFrom, + debounceTime, map, Observable, withLatestFrom, // Subject } from 'rxjs'; @@ -104,6 +104,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { public lastEndDate: Date = new Date(); public items = Array.from({length: 100000}).map((_, i) => `Item #${i}`); public formulaOverflow = false; + private flightDirection = models.FlightDirection.ASCENDING; // Tyler this is where you would put the series and their best fit formulas public bestFitItems: TimeSeriesFit[] = [ @@ -214,10 +215,19 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { ) ); + this.subs.add( + this.store$.select(filtersStore.getFlightDirections).pipe( + map(dir => dir[0] ?? this.flightDirection) + ).subscribe( + dir => this.flightDirection = dir + ) + ) + } private refreshChart(chartStates: { [key: string]: models.timeseriesChartItemState }): void { - const cache = this.netcdfService.getCache() + const cache = this.netcdfService.getCache(this.flightDirection) + const allPointsData: { point: {}, state: models.timeseriesChartItemState }[] = Object.keys(chartStates).map( wkt => ({ point: cache[wkt], state: chartStates[wkt] }) ); @@ -302,7 +312,6 @@ 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')) { let daDate = new Date(result.point[key].secondary_datetime).valueOf(); @@ -360,7 +369,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.dataSource = []; this.averageData = {}; } - + console.log(this.dataSource) this.drawChart(); } From 970c02f765403e146c02eddaef752d0257672c15 Mon Sep 17 00:00:00 2001 From: tylercchase Date: Tue, 10 Dec 2024 12:09:14 -0500 Subject: [PATCH 8/9] chore: remove console log --- .../components/timeseries-chart/timeseries-chart.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts index 90725b47d..045f27982 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts @@ -369,7 +369,6 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.dataSource = []; this.averageData = {}; } - console.log(this.dataSource) this.drawChart(); } From 5f34423696d6883d553b9c20fa0302bdaeb4339e Mon Sep 17 00:00:00 2001 From: tylercchase Date: Tue, 10 Dec 2024 12:22:02 -0500 Subject: [PATCH 9/9] feat: chart options in url --- src/app/services/url-state.service.ts | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts index e8c41b822..b755b3c4b 100644 --- a/src/app/services/url-state.service.ts +++ b/src/app/services/url-state.service.ts @@ -342,12 +342,25 @@ export class UrlStateService { loader: this.loadDispOverview }, { - name: 'isPriorityEnabled', source: this.mapService.priorityEnabled$.pipe( map(isPriorityEnabled => ({isPriorityEnabled})), ), loader: this.loadDispPriority + }, + { + name: 'isShowLinesEnabled', + source: this.store$.select(chartsStore.getShowLines).pipe( + map(isShowLinesEnabled => ({isShowLinesEnabled})), + ), + loader: this.loadDispShowLines + }, + { + name: 'isLinearFitEnabled', + source: this.store$.select(chartsStore.getShowLinearFit).pipe( + map(isLinearFitEnabled => ({isLinearFitEnabled})), + ), + loader: this.loadDispShowLinearFit } ] } @@ -997,4 +1010,20 @@ export class UrlStateService { } return; } + private loadDispShowLines = (isShowLinesEnabled) => { + if(isShowLinesEnabled === 'true') { + this.store$.dispatch(chartsStore.showGraphLines()) + } else { + this.store$.dispatch(chartsStore.hideGraphLines()) + } + return; + } + private loadDispShowLinearFit = (isLinearFitEnabled) => { + if(isLinearFitEnabled === 'true') { + this.store$.dispatch(chartsStore.showLinearFit()) + } else { + this.store$.dispatch(chartsStore.hideLinearFit()) + } + return; + } }