working callbacks, working search filtering/facets
This commit is contained in:
parent
4758f2adcc
commit
363dc49636
14
Makefile
14
Makefile
|
@ -7,6 +7,20 @@
|
|||
.PHONY: test
|
||||
test: backend-test frontend-test
|
||||
|
||||
.PHONY: serve-frontend
|
||||
serve-web:
|
||||
cd frontend
|
||||
yarn dist -- -c sandbox
|
||||
|
||||
.PHONY: serve-frontend-prod
|
||||
serve-web:
|
||||
cd frontend
|
||||
yarn dist -- -c prod
|
||||
|
||||
.PHONY: serve-backend
|
||||
serve-web:
|
||||
go run backend/cmd/fasten/fasten.go start --config ./config.dev.yaml --debug
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# Backend
|
||||
|
|
|
@ -7,15 +7,16 @@ import {MetadataSource} from '../../models/fasten/metadata-source';
|
|||
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {environment} from '../../../environments/environment';
|
||||
import {BehaviorSubject, forkJoin, Observable, Subject} from 'rxjs';
|
||||
import {BehaviorSubject, forkJoin, Observable, of, Subject} from 'rxjs';
|
||||
import {
|
||||
LighthouseSourceSearch,
|
||||
LighthouseSourceSearchAggregation,
|
||||
LighthouseSourceSearchResult
|
||||
} from '../../models/lighthouse/lighthouse-source-search';
|
||||
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
|
||||
import {debounceTime, distinctUntilChanged, pairwise, startWith} from 'rxjs/operators';
|
||||
import {MedicalSourcesFilter, MedicalSourcesFilterService} from '../../services/medical-sources-filter.service';
|
||||
import {FormControl, FormGroup} from '@angular/forms';
|
||||
import * as _ from 'lodash';
|
||||
// If you dont import this angular will import the wrong "Location"
|
||||
|
||||
export const sourceConnectWindowTimeout = 24*5000 //wait 2 minutes (5 * 24 = 120)
|
||||
|
@ -78,7 +79,22 @@ export class MedicalSourcesComponent implements OnInit {
|
|||
private activatedRoute: ActivatedRoute,
|
||||
private filterService: MedicalSourcesFilterService,
|
||||
private modalService: NgbModal,
|
||||
) { }
|
||||
) {
|
||||
this.filterService.filterChanges.subscribe((filterInfo) => {
|
||||
|
||||
console.log("medical-sources - filterChanges", filterInfo)
|
||||
|
||||
//this function should only trigger when there's a change to the filter values -- which requires a new query
|
||||
this.availableSourceList = []
|
||||
this.resultLimits.totalItems = 0
|
||||
this.resultLimits.scrollComplete = false
|
||||
|
||||
//update the form with data from route (don't emit a new patch event), then submit query
|
||||
this.querySources(filterInfo?.filter).subscribe(null, null, () => {
|
||||
console.log("querySources() complete")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
|
@ -92,7 +108,6 @@ export class MedicalSourcesComponent implements OnInit {
|
|||
if(inProgressAvailableIndex > -1){
|
||||
let sourcesInProgress = this.availableSourceList.splice(inProgressAvailableIndex, 1);
|
||||
}
|
||||
|
||||
}
|
||||
//we're not in a callback redirect, lets load the sources
|
||||
if(this.activatedRoute.snapshot.queryParams['query']){
|
||||
|
@ -100,26 +115,6 @@ export class MedicalSourcesComponent implements OnInit {
|
|||
}
|
||||
|
||||
|
||||
//changing the route should trigger a query
|
||||
this.activatedRoute.queryParams
|
||||
.subscribe(params => {
|
||||
console.log("QUERY PARAMS CHANGED ON ROUTE", params); // {order: "popular"}
|
||||
var updatedForm = this.filterService.parseQueryParams(params);
|
||||
|
||||
//this is a "breaking change" to the filter values, causing a reset and a new query
|
||||
this.availableSourceList = []
|
||||
this.resultLimits.totalItems = 0
|
||||
this.resultLimits.scrollComplete = false
|
||||
this.filterService.resetControl("categories")
|
||||
// this.filterService.filterForm.setControl("categories", this.{: {}}, { emitEvent: false})
|
||||
|
||||
//update the form with data from route (don't emit a new patch event), then submit query
|
||||
var searchObservable = this.querySources(this.filterService.toMedicalSourcesFilter(updatedForm));
|
||||
searchObservable.subscribe(null, null, () => {
|
||||
this.filterForm.patchValue(updatedForm, { emitEvent: false});
|
||||
})
|
||||
});
|
||||
|
||||
//register a callback for when the search box content changes
|
||||
this.searchTermUpdate
|
||||
.pipe(
|
||||
|
@ -137,8 +132,10 @@ export class MedicalSourcesComponent implements OnInit {
|
|||
}
|
||||
|
||||
private querySources(filter?: MedicalSourcesFilter): Observable<LighthouseSourceSearch> {
|
||||
console.log("querySources()", filter)
|
||||
if(this.loading){
|
||||
return
|
||||
console.log("already loading, ignoring querySources()")
|
||||
return of(null)
|
||||
}
|
||||
//TODO: pass filter to function.
|
||||
// this.location.replaceState('/dashboard','', this.filter)
|
||||
|
@ -161,11 +158,12 @@ export class MedicalSourcesComponent implements OnInit {
|
|||
return {metadata: result._source}
|
||||
}))
|
||||
|
||||
//change the current Page (but don't cause a new query)
|
||||
if(!wrapper?.hits || !wrapper?.hits || wrapper?.hits?.hits?.length == 0){
|
||||
//check if scroll is complete.
|
||||
if(!wrapper?.hits || !wrapper?.hits?.hits || wrapper?.hits?.hits?.length == 0 || wrapper?.hits?.total?.value == wrapper?.hits?.hits?.length){
|
||||
console.log("SCROLL_COMPLETE!@@@@@@@@")
|
||||
this.resultLimits.scrollComplete = true;
|
||||
} else {
|
||||
//change the current Page (but don't cause a new query)
|
||||
console.log("SETTING NEXT SORT KEY:", wrapper.hits.hits[wrapper.hits.hits.length - 1].sort.join(','))
|
||||
this.filterService.filterForm.patchValue({searchAfter: wrapper.hits.hits[wrapper.hits.hits.length - 1].sort.join(",")}, {emitEvent: false})
|
||||
}
|
||||
|
@ -218,8 +216,10 @@ export class MedicalSourcesComponent implements OnInit {
|
|||
|
||||
|
||||
public onScroll(): void {
|
||||
if(!this.resultLimits.scrollComplete) {
|
||||
this.querySources()
|
||||
}
|
||||
}
|
||||
|
||||
//OLD FUNCTIONS
|
||||
//
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
|
||||
import {debounceTime} from 'rxjs/operators';
|
||||
import {debounceTime, pairwise, startWith} from 'rxjs/operators';
|
||||
import {Router} from '@angular/router';
|
||||
import * as _ from 'lodash';
|
||||
import {BehaviorSubject} from 'rxjs';
|
||||
|
||||
|
||||
export class MedicalSourcesFilter {
|
||||
searchAfter: string | string[] = '';
|
||||
//primary search terms (changes here should restart the search completely)
|
||||
query: string;
|
||||
|
||||
//secondary search terms/facets (changes here should restart pagination)
|
||||
platformTypes: string[] = [];
|
||||
categories: string[] = [];
|
||||
showHidden: boolean = false;
|
||||
|
||||
//pagination - this is the current page (changes here should be ignored)
|
||||
searchAfter: string | string[] = '';
|
||||
|
||||
fields: string[] = []; //specify the fields to return. if null or empty list, return all.
|
||||
}
|
||||
|
||||
|
@ -27,24 +34,90 @@ export class MedicalSourcesFilterService {
|
|||
showHidden: [false],
|
||||
})
|
||||
|
||||
filterChanges = new BehaviorSubject<{filter: MedicalSourcesFilter, changed:string[] }>(null);
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
// private router: Router,
|
||||
) {
|
||||
|
||||
//changing the form, should change the URL, BUT NOT do a query
|
||||
this.filterForm.valueChanges.pipe(debounceTime(100)).subscribe(val => {
|
||||
console.log("FILTER FORM CHANGED:", val, this.toQueryParams())
|
||||
// //changing the form, should change the URL, BUT NOT do a query
|
||||
// this.filterForm.valueChanges.pipe(debounceTime(100)).subscribe(val => {
|
||||
// console.log("FILTER FORM CHANGED:", val, this.toQueryParams())
|
||||
//
|
||||
// // change the browser url whenever the filter is updated.
|
||||
// this.updateBrowserUrl(this.toQueryParams())
|
||||
// })
|
||||
|
||||
// change the browser url whenever the filter is updated.
|
||||
this.updateBrowserUrl(this.toQueryParams())
|
||||
|
||||
this.filterForm.valueChanges
|
||||
//see https://stackoverflow.com/questions/44898010/form-control-valuechanges-gives-the-previous-value
|
||||
.pipe(startWith(null), pairwise())
|
||||
.subscribe(pairParams => {
|
||||
let prevParams = this.toMedicalSourcesFilter(pairParams[0])
|
||||
let nextParams = this.toMedicalSourcesFilter(pairParams[1])
|
||||
let changed = [];
|
||||
|
||||
//check if primary has changed
|
||||
if(!_.isEqual(prevParams.query, nextParams.query)){
|
||||
changed.push('query')
|
||||
this.resetSecondary();
|
||||
nextParams.platformTypes = [];
|
||||
nextParams.categories = [];
|
||||
nextParams.showHidden = false;
|
||||
|
||||
this.resetPagination();
|
||||
nextParams.searchAfter = ''
|
||||
|
||||
//check if secondary/facets have changed
|
||||
} else if (!_.isEqual(prevParams.platformTypes, nextParams.platformTypes)
|
||||
|| !_.isEqual(prevParams.categories, nextParams.categories)
|
||||
|| !_.isEqual(prevParams.showHidden, nextParams.showHidden)
|
||||
){
|
||||
if(!_.isEqual(prevParams.platformTypes, nextParams.platformTypes)){
|
||||
changed.push('platformTypes')
|
||||
}
|
||||
if(!_.isEqual(prevParams.categories, nextParams.categories)){
|
||||
changed.push('categories')
|
||||
}
|
||||
if(!_.isEqual(prevParams.showHidden, nextParams.showHidden)){
|
||||
changed.push('showHidden')
|
||||
}
|
||||
this.resetPagination();
|
||||
nextParams.searchAfter = ''
|
||||
}
|
||||
|
||||
//emit the changes
|
||||
if (changed.length > 0){
|
||||
console.log("FILTER FORM - CHANGED:", nextParams, changed)
|
||||
|
||||
this.filterChanges.next({
|
||||
filter: nextParams,
|
||||
changed: changed
|
||||
})
|
||||
} else {
|
||||
console.log("FILTER FORM - NO CHANGES:", nextParams)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updateBrowserUrl(queryParams: {[name: string]: string}){
|
||||
console.log("update the browser url with query params data", queryParams)
|
||||
this.router.navigate(['/sources'], { queryParams: queryParams })
|
||||
resetPrimary(emit: boolean = false){
|
||||
this.filterForm.get('query').reset(undefined, {emitEvent: emit});
|
||||
}
|
||||
resetSecondary(emit: boolean = false){
|
||||
this.filterForm.get('platformTypes').reset(undefined, {emitEvent: emit});
|
||||
this.filterForm.get('categories').reset(undefined, {emitEvent: emit});
|
||||
this.filterForm.get('showHidden').reset(undefined, {emitEvent: emit});
|
||||
}
|
||||
resetPagination(emit: boolean = false){
|
||||
this.filterForm.get('searchAfter').reset(undefined, {emitEvent: emit});
|
||||
}
|
||||
|
||||
//
|
||||
// updateBrowserUrl(queryParams: {[name: string]: string}){
|
||||
// console.log("update the browser url with query params data", queryParams)
|
||||
// this.router.navigate(['/sources'], { queryParams: queryParams })
|
||||
// }
|
||||
|
||||
resetControl(controlName: string){
|
||||
this.filterForm.get(controlName).reset();
|
||||
|
@ -105,8 +178,10 @@ export class MedicalSourcesFilterService {
|
|||
return updateData;
|
||||
}
|
||||
|
||||
toQueryParams() : {[name:string]:string} {
|
||||
var form = this.filterForm.value;
|
||||
toQueryParams(form) : {[name:string]:string} {
|
||||
if(!form){
|
||||
form = this.filterForm.value;
|
||||
}
|
||||
|
||||
var queryParams = {};
|
||||
|
||||
|
@ -156,7 +231,9 @@ export class MedicalSourcesFilterService {
|
|||
toMedicalSourcesFilter(form): MedicalSourcesFilter {
|
||||
|
||||
var medicalSourcesFilter = new MedicalSourcesFilter();
|
||||
|
||||
if(!form){
|
||||
return medicalSourcesFilter
|
||||
}
|
||||
if(form.searchAfter){
|
||||
medicalSourcesFilter.searchAfter = form.searchAfter
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue