diff --git a/libs/asset-viewer/src/lib/asset-viewer.module.ts b/libs/asset-viewer/src/lib/asset-viewer.module.ts index 2624d43e..94757d6d 100644 --- a/libs/asset-viewer/src/lib/asset-viewer.module.ts +++ b/libs/asset-viewer/src/lib/asset-viewer.module.ts @@ -1,6 +1,6 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; -import { ReactiveFormsModule } from '@angular/forms'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -90,6 +90,7 @@ import { assetViewerReducer } from './state/asset-viewer.reducer'; DrawerComponent, DrawerPanelComponent, DatepickerToggleIconComponent, + FormsModule, ], providers: [ { provide: MAT_DATE_LOCALE, useValue: de }, diff --git a/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.html b/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.html index e02bf40c..2bec85e0 100644 --- a/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.html +++ b/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.html @@ -1,65 +1,68 @@ + [rdStudies$]="rdStudies$" + [rdCurrentAssetDetail$]="rdCurrentAssetDetail$" + [searchPolygon$]="searchPolygon$" + [highlightAssetStudies]="highlightAssetStudies$" + (studiesSelected)="doSearch($event)" + (mapInitialised)="handleMapInitialised()"> + + + + [assets]="assetsForPicker$" + [currentAssetId]="currentAssetId$" + (assetMouseOver)="highlightAssetStudies$.next($event)" /> - + - - - - - - - - - - - - - search.searchInstructionsHeading - search.searchInstructions - - - - - - + + + + + + + + + + + + + search.searchInstructionsHeading + search.searchInstructions + + + + + + diff --git a/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.ts b/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.ts index 0686593c..ea59fc58 100644 --- a/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.ts +++ b/libs/asset-viewer/src/lib/components/asset-viewer-page/asset-viewer-page.component.ts @@ -1,4 +1,3 @@ -import { ENTER } from '@angular/cdk/keycodes'; import { TemplatePortal } from '@angular/cdk/portal'; import { ApplicationRef, @@ -17,7 +16,6 @@ import * as RD from '@devexperts/remote-data-ts'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { Store } from '@ngrx/store'; import * as A from 'fp-ts/Array'; -import { flow } from 'fp-ts/function'; import { Eq as eqNumber } from 'fp-ts/number'; import * as O from 'fp-ts/Option'; import { @@ -44,12 +42,12 @@ import { LifecycleHooksDirective, } from '@asset-sg/client-shared'; import { isTruthy, ORD, rdSequenceProps } from '@asset-sg/core'; -import { LV95 } from '@asset-sg/shared'; import { BaseClientAssetSearchRefinement } from '../../models'; import * as actions from '../../state/asset-viewer.actions'; import { AppStateWithAssetViewer } from '../../state/asset-viewer.reducer'; import * as fromAssetViewer from '../../state/asset-viewer.selectors'; +import { AssetSearchService } from '../../services/asset-search.service'; @UntilDestroy() @Component({ @@ -86,17 +84,6 @@ export class AssetViewerPageComponent { public refinementChanged$ = new Subject>(); public removePolygon$ = new Subject(); - public _searchTextKeyDown$ = new Subject(); - private _searchTextChanged$ = this._searchTextKeyDown$.pipe( - filter(ev => ev.keyCode === ENTER), - map(ev => { - const value = (ev.target as HTMLInputElement).value; - return value ? O.some(value) : O.none; - }), - ); - - public polygonChanged$ = new Subject(); - public assetClicked$ = new Subject(); public closeSearchResultsClicked$ = new Subject(); public closeInstructions$ = new Subject(); @@ -104,7 +91,11 @@ export class AssetViewerPageComponent { public highlightAssetStudies$ = new Subject>(); - constructor() { + public assetClicked$ = new Subject(); + searchQuery = ''; + selectedStudyIds: string[] = []; + + constructor(private readonly assetSearchService: AssetSearchService) { const setupPortals$ = this._lc.afterViewInit$.pipe( observeOn(asyncScheduler), switchMap( @@ -165,15 +156,6 @@ export class AssetViewerPageComponent { this.closeSearchResultsClicked$.pipe(map(() => actions.closeRefineAndResults())), this.closeInstructions$.pipe(map(() => appSharedStateActions.closePanel())), this.refinementChanged$.pipe(map(refinement => actions.refine({ refinement }))), - this._searchTextChanged$.pipe( - map( - flow( - O.map(text => actions.searchByText({ text })), - O.getOrElseW(() => actions.clearSearchText()), - ), - ), - ), - this.polygonChanged$.pipe(map(polygon => actions.searchByPolygon({ polygon }))), this.removePolygon$.pipe(map(() => actions.removePolygon())), ) .pipe(untilDestroyed(this)) @@ -187,4 +169,15 @@ export class AssetViewerPageComponent { }); }); } + + public handleSearchKey(event: KeyboardEvent) { + if (event.key === 'Enter') { + this.doSearch(this.selectedStudyIds); + } + } + + public doSearch(filter: string[]) { + this.selectedStudyIds = filter; + this.assetSearchService.searchByStudyIds(filter).subscribe(); + } } diff --git a/libs/asset-viewer/src/lib/components/map/map.component.ts b/libs/asset-viewer/src/lib/components/map/map.component.ts index 614e3f18..4dc2718b 100644 --- a/libs/asset-viewer/src/lib/components/map/map.component.ts +++ b/libs/asset-viewer/src/lib/components/map/map.component.ts @@ -93,6 +93,7 @@ const initialMapState: MapState = { export class MapComponent { @ViewChild('map', { static: true }) mapDiv!: ElementRef; @Output('polygonChanged') public polygonChanged$ = new EventEmitter(); + @Output('studiesSelected') public studiesSelected$ = new EventEmitter(); private _lc = inject(LifecycleHooks); private _dcmnt = inject(DOCUMENT); @@ -452,6 +453,39 @@ export class MapComponent { ) .subscribe(this.assetClicked$); + // const dragBox = new DragBox({ + // condition: platformModifierKeyOnly, + // }); + // + // dragBox.on('boxend', event => { + // const extent = dragBox.getGeometry().getExtent(); + // vectorSourceAllStudies.forEachFeature(f => { + // const geometry = f.getGeometry(); + // if (geometry && geometry.intersectsExtent(extent)) { + // clickSelect.getFeatures().push(f); + // console.log(clickSelect.getFeatures().getArray()); + // } + // }); + // }); + // olMap.addInteraction(dragBox); + // + // fromEventPattern( + // h => clickSelect.on('select', h), + // h => clickSelect.un('select', h), + // ) + // .pipe( + // withLatestFrom(this.state.select('selectionMode')), + // filter(([, selectionMode]) => selectionMode), + // map(([event]) => { + // console.log('event', event); + // zoomControlsInstance.setSelectionMode(false); + // return event; + // }), + // ) + // .subscribe(event => { + // console.log('event2', event); + // }); + fromEventPattern>( h => olMap.on('click', h), h => olMap.un('click', h), @@ -491,7 +525,10 @@ export class MapComponent { ); }), ) - .subscribe(ss => console.log(ss)); + .subscribe(ss => { + this.studiesSelected$.emit(ss); + console.log(ss); + }); this.state .select(['highlightAssetStudies', 'rdStudies'], ({ rdStudies, highlightAssetStudies }) => diff --git a/libs/asset-viewer/src/lib/services/asset-search.service.ts b/libs/asset-viewer/src/lib/services/asset-search.service.ts index 22e92141..7f93267f 100644 --- a/libs/asset-viewer/src/lib/services/asset-search.service.ts +++ b/libs/asset-viewer/src/lib/services/asset-search.service.ts @@ -8,7 +8,7 @@ import queryString from 'query-string'; import { map, startWith } from 'rxjs'; import { ApiError, httpErrorResponseError } from '@asset-sg/client-shared'; -import { OE, ORD, decodeError } from '@asset-sg/core'; +import { decodeError, OE, ORD } from '@asset-sg/core'; import { AssetSearchParamsOld, LV95, ReferenceData } from '@asset-sg/shared'; import { AssetDetail, SearchAssetResultClient, SearchAssetResultClientDecoder } from '../models'; @@ -47,6 +47,17 @@ export class AssetSearchService { ); } + public searchByStudyIds(studyIds: string[]): ORD.ObservableRemoteData { + return this._httpClient + .post('/api/assets', { ids: studyIds }) + .pipe( + map(flow(SearchAssetResultClientDecoder.decode, E.mapLeft(decodeError))), + OE.catchErrorW(httpErrorResponseError), + map(RD.fromEither), + startWith(RD.pending), + ); + } + public searchByPolygonRefineBySearchText( polygon: LV95[], searchText: string,
search.searchInstructions