Skip to content
Snippets Groups Projects
Commit ae0f56f7 authored by Xiao Gui's avatar Xiao Gui
Browse files

feat: move receptor to into regional features

chore: removed debugger statement
chore: removed console
refactor: remove unused directives
parent e34eebe4
No related branches found
No related tags found
No related merge requests found
Showing
with 237 additions and 133 deletions
...@@ -230,7 +230,6 @@ describe('> saneUrl/index.js', () => { ...@@ -230,7 +230,6 @@ describe('> saneUrl/index.js', () => {
}) })
}) })
it('> checks if the name is available', async () => { it('> checks if the name is available', async () => {
debugger
await got(`http://localhost:50000/${name}`, { await got(`http://localhost:50000/${name}`, {
method: 'POST', method: 'POST',
headers: { headers: {
......
...@@ -36,7 +36,6 @@ import { LayerBrowserModule } from "../../ui/layerbrowser"; ...@@ -36,7 +36,6 @@ import { LayerBrowserModule } from "../../ui/layerbrowser";
import { ContributorModule } from "./contributor"; import { ContributorModule } from "./contributor";
import { DatabrowserService } from "./databrowser.service"; import { DatabrowserService } from "./databrowser.service";
import { ShownDatasetDirective } from "./shownDataset.directive";
import { RegionalFeaturesModule } from "../regionalFeatures"; import { RegionalFeaturesModule } from "../regionalFeatures";
import { SingleDatasetDirective } from "./singleDataset/singleDataset.directive"; import { SingleDatasetDirective } from "./singleDataset/singleDataset.directive";
import { KgDatasetModule } from "../regionalFeatures/bsFeatures/kgDataset"; import { KgDatasetModule } from "../regionalFeatures/bsFeatures/kgDataset";
...@@ -75,7 +74,6 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => { ...@@ -75,7 +74,6 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => {
*/ */
PreviewDatasetFile, PreviewDatasetFile,
ShownPreviewsDirective, ShownPreviewsDirective,
ShownDatasetDirective,
/** /**
* pipes * pipes
...@@ -106,7 +104,6 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => { ...@@ -106,7 +104,6 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => {
PreviewDatasetFile, PreviewDatasetFile,
PreviewFileTypePipe, PreviewFileTypePipe,
ShownPreviewsDirective, ShownPreviewsDirective,
ShownDatasetDirective,
], ],
entryComponents: [ entryComponents: [
PreviewComponentWrapper PreviewComponentWrapper
......
import { Directive } from "@angular/core";
import { select, Store } from "@ngrx/store";
import { Observable } from "rxjs";
import { uiStateShownDatasetIdSelector } from "src/services/state/uiState/selectors";
@Directive({
selector: '[iav-shown-dataset]',
exportAs: 'iavShownDataset'
})
export class ShownDatasetDirective{
public shownDatasetId$: Observable<string[]>
constructor(
store$: Store<any>
){
this.shownDatasetId$ = store$.pipe(
select(uiStateShownDatasetIdSelector)
)
}
}
...@@ -20,7 +20,6 @@ const isSubRegion = (high, low) => regionsEqual(high, low) ...@@ -20,7 +20,6 @@ const isSubRegion = (high, low) => regionsEqual(high, low)
const filterSubSelect = (dataEntry, selectedRegions) => { const filterSubSelect = (dataEntry, selectedRegions) => {
if (dataEntry.name === 'Density measurements of different receptors for Area 7A (SPL) [human, v1.0]') console.log(dataEntry)
return dataEntry.parcellationRegion.some(pr => selectedRegions.some(sr => isSubRegion(pr, sr))) return dataEntry.parcellationRegion.some(pr => selectedRegions.some(sr => isSubRegion(pr, sr)))
} }
......
...@@ -61,7 +61,7 @@ export class RegionBase { ...@@ -61,7 +61,7 @@ export class RegionBase {
return this._region return this._region
} }
private region$: BehaviorSubject<any> = new BehaviorSubject(null) public region$: BehaviorSubject<any> = new BehaviorSubject(null)
@Input() @Input()
public isSelected: boolean = false public isSelected: boolean = false
......
...@@ -86,24 +86,6 @@ ...@@ -86,24 +86,6 @@
</ng-container> </ng-container>
</ng-template> </ng-template>
<!-- receptor -->
<div bs-features-receptor-directive
(bs-features-receptor-directive-fetching-flag$)="handleBusySignal('receptor', $event)"
[region]="region"
#bsFeatureReceptorDirective="bsFeatureReceptorDirective">
</div>
<ng-template #regionalReceptorTmpl>
<bs-features-receptor-entry [region]="region">
</bs-features-receptor-entry>
</ng-template>
<ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
title: 'ReceptorDistribution',
iconClass: 'fas fa-info',
iavNgIf: bsFeatureReceptorDirective.hasReceptor$ | async,
content: regionalReceptorTmpl
}">
</ng-container>
<!-- Explore in other template --> <!-- Explore in other template -->
<ng-container *ngIf="regionInOtherTemplates$ | async as regionInOtherTemplates"> <ng-container *ngIf="regionInOtherTemplates$ | async as regionInOtherTemplates">
...@@ -135,23 +117,17 @@ ...@@ -135,23 +117,17 @@
<!-- kg regional features list --> <!-- kg regional features list -->
<ng-template #kgRegionalFeatureList> <ng-template #kgRegionalFeatureList>
<kg-regional-features-list [region]="region"> <regional-feature-wrapper [region]="region$ | async">
</kg-regional-features-list> </regional-feature-wrapper>
</ng-template> </ng-template>
<div kg-regional-features-list-directive
[region]="region"
(kg-regional-features-list-directive-busy)="handleBusySignal('regionFeatureList', $event)"
#kgRegFeatlist="kgRegionalFeaturesListDirective">
</div>
<ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: { <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
title: CONST.REGIONAL_FEATURES, title: CONST.REGIONAL_FEATURES,
iconClass: 'fas fa-database', iconClass: 'fas fa-database',
content: kgRegionalFeatureList, content: kgRegionalFeatureList,
desc: kgRegFeatlist.kgRegionalFeatures.length, desc: '',
iconTooltip: kgRegFeatlist.kgRegionalFeatures.length | regionAccordionTooltipTextPipe : 'regionalFeatures', iconTooltip: 'Regional Features',
iavNgIf: (kgRegFeatlist.kgRegionalFeatures$ | async ).length iavNgIf: true
}"> }">
</ng-container> </ng-container>
......
import { BehaviorSubject, throwError } from "rxjs"; import { BehaviorSubject, throwError } from "rxjs";
import { map, switchMap } from "rxjs/operators"; import { map, switchMap } from "rxjs/operators";
import { TRegion, IBSSummaryResponse, IBSDetailResponse } from "./type"; import { TRegion, IBSSummaryResponse, IBSDetailResponse } from "./type";
import { BsFeatureService } from "./service"; import { BsFeatureService, TFeatureCmpInput } from "./service";
import { flattenReducer } from 'common/util' import { flattenReducer } from 'common/util'
import { Input } from "@angular/core"; import { Input } from "@angular/core";
...@@ -21,8 +21,13 @@ export class BsRegionInputBase{ ...@@ -21,8 +21,13 @@ export class BsRegionInputBase{
} }
constructor( constructor(
private svc: BsFeatureService private svc: BsFeatureService,
){} data?: TFeatureCmpInput
){
if (data) {
this.region = data.region
}
}
protected featuresList$ = this.region$.pipe( protected featuresList$ = this.region$.pipe(
switchMap(region => this.svc.listFeatures(region)), switchMap(region => this.svc.listFeatures(region)),
......
...@@ -3,3 +3,4 @@ import { Observable } from "rxjs"; ...@@ -3,3 +3,4 @@ import { Observable } from "rxjs";
export { BS_ENDPOINT } from 'src/util/constants' export { BS_ENDPOINT } from 'src/util/constants'
export const BS_DARKTHEME = new InjectionToken<Observable<boolean>>('BS_DARKTHEME') export const BS_DARKTHEME = new InjectionToken<Observable<boolean>>('BS_DARKTHEME')
export const REGISTERED_FEATURE_INJECT_DATA = new InjectionToken('REGISTERED_FEATURE_INJECT_DATA')
import { Component, Directive, HostListener, Inject, Input, Optional } from "@angular/core"; import { Directive, HostListener, Inject, Input, Optional } from "@angular/core";
import { MatDialog, MatDialogConfig } from "@angular/material/dialog"; import { MatDialog, MatDialogConfig } from "@angular/material/dialog";
import { MatSnackBar } from "@angular/material/snack-bar"; import { MatSnackBar } from "@angular/material/snack-bar";
import { OVERWRITE_SHOW_DATASET_DIALOG_TOKEN, TOverwriteShowDatasetDialog } from "src/util/interfaces"; import { OVERWRITE_SHOW_DATASET_DIALOG_TOKEN, TOverwriteShowDatasetDialog } from "src/util/interfaces";
import { TRegion as TSiibraRegion } from "src/util/siibraApiConstants/types";
import { TRegion as TContextRegion } from 'src/atlasComponents/regionalFeatures/bsFeatures/type'
export const IAV_DATASET_SHOW_DATASET_DIALOG_CMP = 'IAV_DATASET_SHOW_DATASET_DIALOG_CMP' export const IAV_DATASET_SHOW_DATASET_DIALOG_CMP = 'IAV_DATASET_SHOW_DATASET_DIALOG_CMP'
export const IAV_DATASET_SHOW_DATASET_DIALOG_CONFIG = `IAV_DATASET_SHOW_DATASET_DIALOG_CONFIG` export const IAV_DATASET_SHOW_DATASET_DIALOG_CONFIG = `IAV_DATASET_SHOW_DATASET_DIALOG_CONFIG`
...@@ -37,6 +39,9 @@ export class ShowDatasetDialogDirective{ ...@@ -37,6 +39,9 @@ export class ShowDatasetDialogDirective{
doi: string doi: string
}[] = [] }[] = []
@Input('iav-dataset-show-dataset-dialog-contexted-region')
region: TSiibraRegion & TContextRegion
constructor( constructor(
private matDialog: MatDialog, private matDialog: MatDialog,
private snackbar: MatSnackBar, private snackbar: MatSnackBar,
...@@ -63,7 +68,7 @@ export class ShowDatasetDialogDirective{ ...@@ -63,7 +68,7 @@ export class ShowDatasetDialogDirective{
} }
if (this.overwriteFn) { if (this.overwriteFn) {
return this.overwriteFn(data) return this.overwriteFn(data, this)
} }
if (!this.dialogCmp) throw new Error(`IAV_DATASET_SHOW_DATASET_DIALOG_CMP not provided!`) if (!this.dialogCmp) throw new Error(`IAV_DATASET_SHOW_DATASET_DIALOG_CMP not provided!`)
......
import { TBSDetail, TCountedDataModality } from "./type";
export function filterKgFeatureByModailty(modalities: TCountedDataModality[]){
const visibleModNames = modalities
.filter(mod => mod.visible)
.map(mod => mod.name)
const visibleModNameSet = new Set(visibleModNames)
return function(feature: TBSDetail){
if (modalities.every(m => !m.visible)) return true
return feature.__detail.methods.some(m => visibleModNameSet.has(m))
}
}
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, ViewChild } from "@angular/core"; import { ChangeDetectionStrategy, Component, Inject, Input, OnDestroy, Optional } from "@angular/core";
import { Subscription } from "rxjs"; import { BehaviorSubject, Subscription } from "rxjs";
import { filter, switchMap, tap } from "rxjs/operators"; import { filter, switchMap, tap } from "rxjs/operators";
import { TCountedDataModality } from '../../kgDataset' import { TCountedDataModality } from '../../kgDataset'
import { BsRegionInputBase } from "../../bsRegionInputBase"; import { BsRegionInputBase } from "../../bsRegionInputBase";
import { BsFeatureService } from "../../service"; import { BsFeatureService, TFeatureCmpInput } from "../../service";
import { KG_REGIONAL_FEATURE_KEY, TBSDetail, TBSSummary } from "../type"; import { KG_REGIONAL_FEATURE_KEY, TBSDetail, TBSSummary } from "../type";
import { ARIA_LABELS } from 'common/constants' import { ARIA_LABELS } from 'common/constants'
import { filterKgFeatureByModailty } from "../../kgDataset/util"; import { REGISTERED_FEATURE_INJECT_DATA } from "../../constants";
@Component({ @Component({
selector: 'kg-regional-features-list', selector: 'kg-regional-features-list',
...@@ -29,12 +29,25 @@ export class KgRegionalFeaturesList extends BsRegionInputBase implements OnDestr ...@@ -29,12 +29,25 @@ export class KgRegionalFeaturesList extends BsRegionInputBase implements OnDestr
public visibleRegionalFeatures: TBSSummary[] = [] public visibleRegionalFeatures: TBSSummary[] = []
public kgRegionalFeatures: TBSSummary[] = [] public kgRegionalFeatures: TBSSummary[] = []
public kgRegionalFeatures$ = this.region$.pipe( public kgRegionalFeatures$ = this.region$.pipe(
filter(v => !!v), filter(v => {
this.busy$.next(false)
return !!v
}),
// must not use switchmapto here // must not use switchmapto here
switchMap(() => this.getFeatureInstancesList(KG_REGIONAL_FEATURE_KEY)) switchMap(() => {
this.busy$.next(true)
return this.getFeatureInstancesList(KG_REGIONAL_FEATURE_KEY).pipe(
tap(() => {
this.busy$.next(false)
})
)
})
) )
constructor(private cdr: ChangeDetectorRef, svc: BsFeatureService){ constructor(
super(svc) svc: BsFeatureService,
@Optional() @Inject(REGISTERED_FEATURE_INJECT_DATA) data: TFeatureCmpInput
){
super(svc, data)
this.sub.push( this.sub.push(
this.kgRegionalFeatures$.subscribe(val => { this.kgRegionalFeatures$.subscribe(val => {
this.kgRegionalFeatures = val this.kgRegionalFeatures = val
...@@ -72,26 +85,5 @@ export class KgRegionalFeaturesList extends BsRegionInputBase implements OnDestr ...@@ -72,26 +85,5 @@ export class KgRegionalFeaturesList extends BsRegionInputBase implements OnDestr
this.dataModalities = [...this.dataModalities] this.dataModalities = [...this.dataModalities]
} }
public handleModalityVisbilityChange(modalityFilter: TCountedDataModality[]){ public busy$ = new BehaviorSubject(false)
this.dataModalities = modalityFilter
const visibleCountedDataM = modalityFilter.filter(dm => dm.visible)
const filterFunc = filterKgFeatureByModailty(visibleCountedDataM)
this.visibleRegionalFeatures = this.kgRegionalFeatures.filter(sum => {
const detail = this.detailDict[sum['@id']]
if (!detail) return false
return filterFunc(detail)
})
this.cdr.markForCheck()
}
public clearFilters(){
const dataModalities = this.dataModalities.map(v => {
return {
...v,
visible: false
}
})
this.handleModalityVisbilityChange(dataModalities)
}
} }
<ng-container *ngTemplateOutlet="virtualScrollTmpl"> <spinner-cmp *ngIf="busy$ | async; else contentTmpl"></spinner-cmp>
</ng-container>
<ng-template #virtualScrollTmpl> <ng-template #contentTmpl>
<cdk-virtual-scroll-viewport <cdk-virtual-scroll-viewport
[attr.aria-label]="ARIA_LABELS.LIST_OF_DATASETS_ARIA_LABEL" [attr.aria-label]="ARIA_LABELS.LIST_OF_DATASETS_ARIA_LABEL"
class="h-100" class="h-100"
...@@ -18,6 +17,7 @@ ...@@ -18,6 +17,7 @@
mat-ripple mat-ripple
iav-dataset-show-dataset-dialog iav-dataset-show-dataset-dialog
[iav-dataset-show-dataset-dialog-fullid]="dataset['@id']" [iav-dataset-show-dataset-dialog-fullid]="dataset['@id']"
[iav-dataset-show-dataset-dialog-contexted-region]="region"
class="d-block pb-1 pt-1" class="d-block pb-1 pt-1"
[region]="region" [region]="region"
[loadFull]="false" [loadFull]="false"
......
...@@ -2,15 +2,16 @@ import { Directive, EventEmitter, OnDestroy, Output } from "@angular/core"; ...@@ -2,15 +2,16 @@ import { Directive, EventEmitter, OnDestroy, Output } from "@angular/core";
import { KG_REGIONAL_FEATURE_KEY, TBSSummary } from "../type"; import { KG_REGIONAL_FEATURE_KEY, TBSSummary } from "../type";
import { BsFeatureService } from "../../service"; import { BsFeatureService } from "../../service";
import { BsRegionInputBase } from "../../bsRegionInputBase"; import { BsRegionInputBase } from "../../bsRegionInputBase";
import { Subscription } from "rxjs"; import { merge, of, Subscription } from "rxjs";
import { filter, startWith, switchMap, tap } from "rxjs/operators"; import { filter, mapTo, startWith, switchMap, tap } from "rxjs/operators";
import { IRegionalFeatureReadyDirective } from "../../type";
@Directive({ @Directive({
selector: '[kg-regional-features-list-directive]', selector: '[kg-regional-features-list-directive]',
exportAs: 'kgRegionalFeaturesListDirective' exportAs: 'kgRegionalFeaturesListDirective'
}) })
export class KgRegionalFeaturesListDirective extends BsRegionInputBase implements OnDestroy { export class KgRegionalFeaturesListDirective extends BsRegionInputBase implements IRegionalFeatureReadyDirective, OnDestroy {
public kgRegionalFeatures: TBSSummary[] = [] public kgRegionalFeatures: TBSSummary[] = []
public kgRegionalFeatures$ = this.region$.pipe( public kgRegionalFeatures$ = this.region$.pipe(
filter(v => !!v), filter(v => !!v),
...@@ -18,7 +19,9 @@ export class KgRegionalFeaturesListDirective extends BsRegionInputBase implement ...@@ -18,7 +19,9 @@ export class KgRegionalFeaturesListDirective extends BsRegionInputBase implement
switchMap(() => { switchMap(() => {
this.busyEmitter.emit(true) this.busyEmitter.emit(true)
return this.getFeatureInstancesList(KG_REGIONAL_FEATURE_KEY).pipe( return this.getFeatureInstancesList(KG_REGIONAL_FEATURE_KEY).pipe(
tap(() => this.busyEmitter.emit(false)) tap(() => {
this.busyEmitter.emit(false)
})
) )
}), }),
startWith([]) startWith([])
...@@ -37,6 +40,16 @@ export class KgRegionalFeaturesListDirective extends BsRegionInputBase implement ...@@ -37,6 +40,16 @@ export class KgRegionalFeaturesListDirective extends BsRegionInputBase implement
while (this.sub.length) this.sub.pop().unsubscribe() while (this.sub.length) this.sub.pop().unsubscribe()
} }
results$ = this.kgRegionalFeatures$
busy$ = this.region$.pipe(
switchMap(() => merge(
of(true),
this.results$.pipe(
mapTo(false)
)
))
)
@Output('kg-regional-features-list-directive-busy') @Output('kg-regional-features-list-directive-busy')
busyEmitter = new EventEmitter<boolean>() busyEmitter = new EventEmitter<boolean>()
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ import { KgDatasetModule } from "../kgDataset"; ...@@ -9,6 +9,7 @@ import { KgDatasetModule } from "../kgDataset";
import { IAV_DATASET_SHOW_DATASET_DIALOG_CMP } from "../kgDataset/showDataset/showDataset.directive"; import { IAV_DATASET_SHOW_DATASET_DIALOG_CMP } from "../kgDataset/showDataset/showDataset.directive";
import { UtilModule } from "src/util"; import { UtilModule } from "src/util";
import { ComponentsModule } from "src/components"; import { ComponentsModule } from "src/components";
import { BsFeatureService } from "../service";
@Component({ @Component({
selector: 'blabla', selector: 'blabla',
...@@ -56,4 +57,13 @@ export class ShowDsDialogCmp{} ...@@ -56,4 +57,13 @@ export class ShowDsDialogCmp{}
] ]
}) })
export class KgRegionalFeatureModule{} export class KgRegionalFeatureModule{
constructor(svc: BsFeatureService){
svc.registerFeature({
name: 'ebrains datasets',
icon: 'fas fa-ellipsis-h',
View: KgRegionalFeaturesList,
Ctrl: KgRegionalFeaturesListDirective,
})
}
}
import { CommonModule } from "@angular/common"; import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { ComponentsModule } from "src/components";
import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
import { KgRegionalFeatureModule } from "./kgRegionalFeature"; import { KgRegionalFeatureModule } from "./kgRegionalFeature";
import { BSFeatureReceptorModule } from "./receptor"; import { BSFeatureReceptorModule } from "./receptor";
import { RegionalFeatureWrapperCmp } from "./regionalFeatureWrapper/regionalFeatureWrapper.component";
import { BsFeatureService } from "./service"; import { BsFeatureService } from "./service";
@NgModule({ @NgModule({
imports: [ imports: [
AngularMaterialModule,
CommonModule, CommonModule,
BSFeatureReceptorModule,
KgRegionalFeatureModule, KgRegionalFeatureModule,
BSFeatureReceptorModule,
ComponentsModule,
],
declarations: [
RegionalFeatureWrapperCmp,
], ],
providers: [ providers: [
BsFeatureService BsFeatureService
], ],
exports: [ exports: [
BSFeatureReceptorModule, RegionalFeatureWrapperCmp,
KgRegionalFeatureModule,
] ]
}) })
......
import { Component, OnDestroy } from "@angular/core"; import { Component, Inject, OnDestroy, Optional } from "@angular/core";
import { Observable, of, Subject, Subscription } from "rxjs"; import { Observable, of, Subject, Subscription } from "rxjs";
import { filter, map, shareReplay, startWith, switchMap, tap } from "rxjs/operators"; import { filter, map, shareReplay, startWith, switchMap, tap } from "rxjs/operators";
import { BsRegionInputBase } from "../../bsRegionInputBase"; import { BsRegionInputBase } from "../../bsRegionInputBase";
import { BsFeatureService } from "../../service"; import { REGISTERED_FEATURE_INJECT_DATA } from "../../constants";
import { BsFeatureService, TFeatureCmpInput } from "../../service";
import { TBSDetail } from "../type"; import { TBSDetail } from "../type";
@Component({ @Component({
...@@ -66,9 +67,10 @@ export class BsFeatureReceptorEntry extends BsRegionInputBase implements OnDestr ...@@ -66,9 +67,10 @@ export class BsFeatureReceptorEntry extends BsRegionInputBase implements OnDestr
) )
constructor( constructor(
svc: BsFeatureService svc: BsFeatureService,
@Optional() @Inject(REGISTERED_FEATURE_INJECT_DATA) data: TFeatureCmpInput
){ ){
super(svc) super(svc, data)
this.sub.push( this.sub.push(
this.selectedReceptor$.subscribe() this.selectedReceptor$.subscribe()
) )
......
import { Directive, EventEmitter, OnDestroy, Output } from "@angular/core"; import { Directive, EventEmitter, Inject, OnDestroy, Optional, Output } from "@angular/core";
import { merge, of, Subscription } from "rxjs"; import { merge, Observable, of, Subscription } from "rxjs";
import { catchError, map, mapTo, switchMap } from "rxjs/operators"; import { catchError, map, mapTo, switchMap } from "rxjs/operators";
import { BsRegionInputBase } from "../bsRegionInputBase"; import { BsRegionInputBase } from "../bsRegionInputBase";
import { BsFeatureService } from "../service"; import { REGISTERED_FEATURE_INJECT_DATA } from "../constants";
import { BsFeatureService, TFeatureCmpInput } from "../service";
import { IBSSummaryResponse, IRegionalFeatureReadyDirective } from "../type";
@Directive({ @Directive({
selector: '[bs-features-receptor-directive]', selector: '[bs-features-receptor-directive]',
exportAs: 'bsFeatureReceptorDirective' exportAs: 'bsFeatureReceptorDirective'
}) })
export class BsFeatureReceptorDirective extends BsRegionInputBase implements OnDestroy { export class BsFeatureReceptorDirective extends BsRegionInputBase implements IRegionalFeatureReadyDirective, OnDestroy {
private sub: Subscription[] = [] private sub: Subscription[] = []
ngOnDestroy(){ ngOnDestroy(){
while (this.sub.length > 0) this.sub.pop().unsubscribe() while (this.sub.length > 0) this.sub.pop().unsubscribe()
} }
public results$: Observable<IBSSummaryResponse['ReceptorDistribution'][]> = this.region$.pipe(
public hasReceptor$ = this.region$.pipe( switchMap(() => merge(
switchMap(val => merge( of([]),
of(null),
this.getFeatureInstancesList('ReceptorDistribution').pipe( this.getFeatureInstancesList('ReceptorDistribution').pipe(
map(arr => arr.length > 0), catchError(() => of([]))
catchError(() => of(false))
) )
)), )),
) )
public fetching$ = this.hasReceptor$.pipe( public hasReceptor$ = this.results$.pipe(
map(v => v === null), map(arr => arr.length > 0)
)
public busy$ = this.region$.pipe(
switchMap(() => merge(
of(true),
this.results$.pipe(
mapTo(false)
)
))
) )
constructor( constructor(
svc: BsFeatureService svc: BsFeatureService,
@Optional() @Inject(REGISTERED_FEATURE_INJECT_DATA) data: TFeatureCmpInput,
){ ){
super(svc) super(svc, data)
this.sub.push( this.sub.push(
this.fetching$.subscribe(flag => this.fetchingFlagEmitter.emit(flag)) this.busy$.subscribe(flag => this.fetchingFlagEmitter.emit(flag))
) )
} }
......
...@@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core"; ...@@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module"; import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
import { UtilModule } from "src/util"; import { UtilModule } from "src/util";
import { BsFeatureService } from "../service";
import { BsFeatureReceptorAR } from "./ar/autoradiograph.component"; import { BsFeatureReceptorAR } from "./ar/autoradiograph.component";
import { BsFeatureReceptorEntry } from "./entry/entry.component"; import { BsFeatureReceptorEntry } from "./entry/entry.component";
import { BsFeatureReceptorFingerprint } from "./fp/fp.component"; import { BsFeatureReceptorFingerprint } from "./fp/fp.component";
...@@ -32,4 +33,13 @@ import { BsFeatureReceptorProfile } from "./profile/profile.component"; ...@@ -32,4 +33,13 @@ import { BsFeatureReceptorProfile } from "./profile/profile.component";
] ]
}) })
export class BSFeatureReceptorModule{} export class BSFeatureReceptorModule{
constructor(svc: BsFeatureService){
svc.registerFeature({
name: 'receptor',
icon: 'fas fa-info',
View: BsFeatureReceptorEntry,
Ctrl: BsFeatureReceptorDirective,
})
}
}
...@@ -29,6 +29,15 @@ export type TBSSummary = { ...@@ -29,6 +29,15 @@ export type TBSSummary = {
['@id']: string ['@id']: string
name: string name: string
info: string info: string
origin_datainfos?: ({
name: string
description: string
} | {
urls: {
doi: string
cite?: string
}[]
})[]
} }
export type TBSDetail = TBSSummary & { export type TBSDetail = TBSSummary & {
......
import { Component, ComponentFactory, ComponentFactoryResolver, Injector, Input, OnChanges, ViewChild, ViewContainerRef } from "@angular/core";
import { TRegion } from "../type";
import { BsFeatureService, TFeatureCmpInput, TRegisteredFeature } from "../service";
import { BehaviorSubject, Observable } from "rxjs";
import { map } from "rxjs/operators";
import { REGISTERED_FEATURE_INJECT_DATA } from "../constants";
@Component({
selector: 'regional-feature-wrapper',
templateUrl: './regionalFeatureWrapper.template.html',
styleUrls: [
'./regionalFeatureWrapper.style.css'
]
})
export class RegionalFeatureWrapperCmp implements OnChanges{
@Input()
region: TRegion
@ViewChild('regionalFeatureContainerTmpl', { read: ViewContainerRef })
regionalFeatureContainerRef: ViewContainerRef
private weakmap = new WeakMap<(new () => any), ComponentFactory<any>>()
public registeredFeatures$ = this.svc.registeredFeatures$
constructor(
private svc: BsFeatureService,
private cfr: ComponentFactoryResolver,
private injector: Injector,
){
}
private regionOnDestroyCb: (() => void)[] = []
private setupRegionalFeatureCtrl(){
if (!this.region) return
const { region } = this
for (const feat of this.svc.registeredFeatures){
const ctrl = new feat.Ctrl(this.svc, { region })
const sub = ctrl.busy$.subscribe(
flag => {
this.busyMasterStream$.next({
[feat.name]: flag
})
}
)
this.regionOnDestroyCb.push(() => sub.unsubscribe())
}
}
private cleanUpRegionalFeature(){
while (this.regionOnDestroyCb.length) this.regionOnDestroyCb.pop()()
this.busyMasterStream$.next({})
}
private busyMasterStream$ = new BehaviorSubject<{
[key: string]: boolean
}>({})
public busy$: Observable<boolean> = this.busyMasterStream$.pipe(
map(obj => {
for (const key in obj) {
if(obj[key]) return true
}
return false
}),
)
ngOnChanges(){
this.cleanUpRegionalFeature()
this.setupRegionalFeatureCtrl()
}
public activatedFeatureName: string = null
activateFeature(feat: TRegisteredFeature){
this.activatedFeatureName = feat.name
if (!this.regionalFeatureContainerRef) {
console.warn(`regionalFeatureContainerRef not defined.`)
return
}
this.regionalFeatureContainerRef.clear()
const cf = (() => {
const mapped = this.weakmap.get(feat.View)
if (mapped) return mapped
const _cf = this.cfr.resolveComponentFactory(feat.View)
this.weakmap.set(feat.View ,_cf)
return _cf
})()
const { region } = this
const injector = Injector.create({
providers: [{
provide: REGISTERED_FEATURE_INJECT_DATA,
useValue: { region } as TFeatureCmpInput
}],
parent: this.injector
})
this.regionalFeatureContainerRef.createComponent(cf, null, injector)
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment