diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/ui/databrowserModule/databrowser.module.ts index 056b5973025be34026c80474aeef5707928ccf19..b03aec66953c43b10a40dca97a1f308b85f4cfcd 100644 --- a/src/ui/databrowserModule/databrowser.module.ts +++ b/src/ui/databrowserModule/databrowser.module.ts @@ -3,7 +3,6 @@ import { NgModule, CUSTOM_ELEMENTS_SCHEMA, Optional } from "@angular/core"; import { FormsModule } from "@angular/forms"; import { ComponentsModule } from "src/components/components.module"; import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module' -import { DoiParserPipe } from "src/util/pipes/doiPipe.pipe"; import { UtilModule } from "src/util"; import { DataBrowser } from "./databrowser/databrowser.component"; import { KgSingleDatasetService } from "./kgSingleDatasetService.service" @@ -48,6 +47,7 @@ import { DatabrowserService } from "./databrowser.service"; import { ShownDatasetDirective } from "./shownDataset.directive"; import { SingleDatasetSideNavView } from "./singleDataset/sideNavView/sDsSideNavView.component"; import { RegionalFeaturesModule } from "../regionalFeatures"; +import { SingleDatasetDirective } from "./singleDataset/singleDataset.directive"; const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => { @@ -71,6 +71,7 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => { DataBrowser, ModalityPicker, SingleDatasetView, + SingleDatasetDirective, SingleDatasetListView, DatasetPreviewList, PreviewComponentWrapper, @@ -95,7 +96,6 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => { FilterDataEntriesbyMethods, FilterDataEntriesByRegion, AggregateArrayIntoRootPipe, - DoiParserPipe, DatasetIsFavedPipe, RegionBackgroundToRgbPipe, GetKgSchemaIdFromFullIdPipe, @@ -113,6 +113,7 @@ const previewEmitFactory = ( overrideFn: (file: any, dataset: any) => void) => { exports: [ DataBrowser, SingleDatasetView, + SingleDatasetDirective, SingleDatasetListView, ModalityPicker, FilterDataEntriesbyMethods, diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts index 4db7d45dd6d32450ae35f27434c8970b611157e7..9b0d651a1b1f7767a6fca52e08a79ea6feed1daf 100644 --- a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts +++ b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Input, TemplateRef, OnChanges, OnDestroy } from "@angular/core"; -import { Observable, Subject, Subscription, combineLatest } from "rxjs"; +import { Observable, Subject, Subscription, combineLatest, BehaviorSubject } from "rxjs"; import { IDataEntry, IFile, IPublication } from 'src/services/state/dataStore.store' import { HumanReadableFileSizePipe } from "src/util/pipes/humanReadableFileSize.pipe"; import { DatabrowserService } from "../databrowser.service"; @@ -10,9 +10,10 @@ import { getKgSchemaIdFromFullId } from "../util/getKgSchemaIdFromFullId.pipe"; import { MatSnackBar } from "@angular/material/snack-bar"; import { ARIA_LABELS } from 'common/constants' -import { switchMap, distinctUntilChanged, filter } from "rxjs/operators"; +import { switchMap, distinctUntilChanged, filter, map, shareReplay, startWith } from "rxjs/operators"; import { IContributor } from "../contributor"; import { UNDER_REVIEW } from "../constants"; +import { DatasetIsFavedPipe } from "../util/datasetIsFaved.pipe"; const getDirectLinkToKg = (dataset: { fullId: string, id: string }) => { const { id } = dataset @@ -63,7 +64,7 @@ export class SingleDatasetBase implements OnChanges, OnDestroy { } private _kgSchema: string = 'minds/core/dataset/v1.0.0' - private kgSchema$: Subject<string> = new Subject() + private kgSchema$: Subject<string> = new BehaviorSubject(null) @Input() set kgSchema(val) { @@ -76,7 +77,7 @@ export class SingleDatasetBase implements OnChanges, OnDestroy { } private _kgId: string - private kgId$: Subject<string> = new Subject() + private kgId$: Subject<string> = new BehaviorSubject(null) @Input() set kgId(val){ @@ -116,6 +117,10 @@ export class SingleDatasetBase implements OnChanges, OnDestroy { public selectedTemplateSpace$: Observable<any> public favedDataentries$: Observable<Partial<IDataEntry>[]> + + public isFav$: Observable<boolean> + private dsIsFavPipe = new DatasetIsFavedPipe() + constructor( private dbService: DatabrowserService, private singleDatasetService: KgSingleDatasetService, @@ -125,6 +130,15 @@ export class SingleDatasetBase implements OnChanges, OnDestroy { ) { this.favedDataentries$ = this.dbService.favedDataentries$ + this.isFav$ = combineLatest([ + this.favedDataentries$, + this.kgSchema$, + this.kgId$, + ]).pipe( + map(([ favDs, kgSchema, kgId ]) => this.dsIsFavPipe.transform(favDs, { fullId: `${kgSchema}/${kgId}` })), + startWith(false), + shareReplay(1), + ) this.subscriptions.push( combineLatest([ this.kgSchema$.pipe( diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.directive.ts b/src/ui/databrowserModule/singleDataset/singleDataset.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..3805442e489bfb15aa2db27c975a2a72c509d292 --- /dev/null +++ b/src/ui/databrowserModule/singleDataset/singleDataset.directive.ts @@ -0,0 +1,24 @@ +import { ChangeDetectorRef, Directive } from "@angular/core"; +import { MatSnackBar } from "@angular/material/snack-bar"; +import { DatabrowserService, KgSingleDatasetService, SingleDatasetBase } from "./singleDataset.base"; + +@Directive({ + selector: '[single-dataset-directive]', + exportAs: 'singleDatasetDirective' +}) + +export class SingleDatasetDirective extends SingleDatasetBase{ + constructor( + dbService: DatabrowserService, + singleDatasetService: KgSingleDatasetService, + cdr: ChangeDetectorRef, + snackBar: MatSnackBar, + ){ + super( + dbService, + singleDatasetService, + cdr, + snackBar, + ) + } +} \ No newline at end of file diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index 39068f398680c57a65474a840ac2ec14f5cffbc7..bcf5604f5366d8bd56df8e584618055bc5d14028 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -466,6 +466,30 @@ [region]="region" #iavRegion="iavRegion"> + <!-- desc --> + <ng-container *ngFor="let ods of (region.originDatasets || [])"> + <ng-template #regionDescTmpl> + <single-dataset-view + [hideTitle]="true" + [hideExplore]="true" + [hidePreview]="true" + [hidePinBtn]="true" + [hideDownloadBtn]="true" + [kgSchema]="ods.kgSchema" + [kgId]="ods.kgId"> + + </single-dataset-view> + </ng-template> + <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: { + title: 'Description', + iconClass: 'fas fa-info', + iavNgIf: true, + content: regionDescTmpl + }"> + + </ng-container> + </ng-container> + <!-- Explore in other template --> <ng-container *ngIf="iavRegion.regionInOtherTemplates$ | async as regionInOtherTemplates"> diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts b/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts index 3c7f395eece740396746c2e452f9f9061490736b..fa2cc46ef39e251dad93d3a96cdcc6fa6c467112 100644 --- a/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts +++ b/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts @@ -3,13 +3,11 @@ import { RegionMenuComponent } from "./regionMenu.component" import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module" import { UtilModule } from "src/util/util.module" import { CommonModule } from "@angular/common" -import { provideMockStore, MockStore } from "@ngrx/store/testing" -import { regionInOtherTemplateSelector, RenderViewOriginDatasetLabelPipe } from '../region.base' -import { ARIA_LABELS } from 'common/constants' -import { By } from "@angular/platform-browser" +import { provideMockStore } from "@ngrx/store/testing" +import { RenderViewOriginDatasetLabelPipe } from '../region.base' import { Directive, Input } from "@angular/core" import { NoopAnimationsModule } from "@angular/platform-browser/animations" -import { viewerStateGetSelectedAtlas } from "src/services/state/viewerState/selectors" +import { ComponentsModule } from "src/components" const mt0 = { name: 'mt0' @@ -82,6 +80,19 @@ class MockPrvDsFileDirective { } +@Directive({ + selector: '[single-dataset-directive]', + exportAs: 'singleDatasetDirective' +}) + +class DummySingleDatasetDirective{ + @Input() + kgId: string + + @Input() + kgSchema: string +} + describe('> regionMenu.component.ts', () => { describe('> RegionMenuComponent', () => { beforeEach(async(() => { @@ -92,6 +103,7 @@ describe('> regionMenu.component.ts', () => { AngularMaterialModule, CommonModule, NoopAnimationsModule, + ComponentsModule, ], declarations: [ RegionMenuComponent, @@ -100,6 +112,7 @@ describe('> regionMenu.component.ts', () => { * Used by regionMenu.template.html to show region preview */ MockPrvDsFileDirective, + DummySingleDatasetDirective, ], providers: [ provideMockStore({ initialState: {} }) diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html index b6fd52dd0bc4eb97a1cf6d184e8b4c1b5de118fc..d211e9da73e9eb4da66c7cf1c4809b99babbb779 100644 --- a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html +++ b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html @@ -26,6 +26,55 @@ <span> {{ regionOriginDatasetLabels$ | async | renderViewOriginDatasetlabel : index }} </span> + + <span + aria-hidden="true" + [kgSchema]="originDataset.kgSchema" + [kgId]="originDataset.kgId" + single-dataset-directive + #sdDirective="singleDatasetDirective"> + </span> + + <ng-template [ngIf]="sdDirective.fetchFlag" [ngIfElse]="contentTmpl"> + <spinner-cmp></spinner-cmp> + </ng-template> + + <ng-template #contentTmpl> + + <!-- fall back if no kg ref is available --> + <a *ngIf="sdDirective.kgReference.length === 0" + [href]="sdDirective.directLinkToKg" + target="_blank"> + <button mat-icon-button + color="primary"> + <i class="fas fa-external-link-alt"></i> + </button> + </a> + + <!-- kg ref, normally doi --> + <a *ngFor="let kgRef of sdDirective.kgReference" + [href]="kgRef | doiParserPipe" + target="_blank"> + <button mat-icon-button + color="primary"> + <i class="fas fa-external-link-alt"></i> + </button> + </a> + + <!-- pin/unpin --> + <ng-container *ngTemplateOutlet="pinTmpl; context: { $implicit: sdDirective.isFav$ | async }"> + </ng-container> + + <ng-template #pinTmpl let-isFav> + + <button mat-icon-button + (click)="isFav ? sdDirective.undoableRemoveFav() : sdDirective.undoableAddFav()" + [color]="isFav ? 'primary' : 'default'"> + <i class="fas fa-thumbtack"></i> + </button> + </ng-template> + + </ng-template> </div> <mat-divider vertical="true" class="ml-2 h-2rem"></mat-divider> diff --git a/src/util/util.module.ts b/src/util/util.module.ts index 2259d3b71c8e6a4a035c846e413f0074dffc0040..9bd355200e69f30bac59aa2953818f4c1b71f71b 100644 --- a/src/util/util.module.ts +++ b/src/util/util.module.ts @@ -23,6 +23,7 @@ import { GetPropertyPipe } from "./pipes/getProperty.pipe"; import { FilterArrayPipe } from "./pipes/filterArray.pipe"; import { FilterByPropertyPipe } from "./pipes/filterByProperty.pipe"; import { ArrayContainsPipe } from "./pipes/arrayContains.pipe"; +import { DoiParserPipe } from "./pipes/doiPipe.pipe"; @NgModule({ imports:[ @@ -51,6 +52,7 @@ import { ArrayContainsPipe } from "./pipes/arrayContains.pipe"; FilterArrayPipe, FilterByPropertyPipe, ArrayContainsPipe, + DoiParserPipe, ], exports: [ FilterNullPipe, @@ -75,6 +77,7 @@ import { ArrayContainsPipe } from "./pipes/arrayContains.pipe"; FilterArrayPipe, FilterByPropertyPipe, ArrayContainsPipe, + DoiParserPipe, ] })