diff --git a/package.json b/package.json index f0352b0a22df72e2100c414b104484356a142414..a6b1fbe644a63dd1d587f804097a064f79a66819 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,6 @@ "karma-jasmine": "^2.0.1", "karma-typescript": "^4.1.1", "karma-webpack": "^3.0.0", - "kg-dataset-previewer": "0.0.11", "lodash.merge": "^4.6.2", "mini-css-extract-plugin": "^0.8.0", "node-sass": "^4.12.0", diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html index df66f5d5ad5a9c6ae73294a135f22723cebf290f..7e07c0079a961e828fd75351add23bb1a3038cdf 100644 --- a/src/atlasViewer/atlasViewer.template.html +++ b/src/atlasViewer/atlasViewer.template.html @@ -59,7 +59,7 @@ [hasBackdrop]="false" class="w-100 h-100 bg-none mat-drawer-content-overflow-visible"> <mat-drawer mode="push" - class="col-10 col-sm-10 col-md-4 col-lg-3 col-xl-2 p-2 bg-none box-shadow-none overflow-visible" + class="col-10 col-sm-10 col-md-5 col-lg-4 col-xl-3 col-xxl-2 p-2 bg-none box-shadow-none overflow-visible" [disableClose]="true" [autoFocus]="false" [opened]="sidePanelIsOpen$ | async" diff --git a/src/index.html b/src/index.html index 383b96ce10f87e94b77bcd98bd78e63e28ecbba3..23558e3947d5e0d45617f3217ff3a4d1d0d07130 100644 --- a/src/index.html +++ b/src/index.html @@ -11,6 +11,9 @@ <link rel="stylesheet" href="plugin_styles.css"> <link rel="stylesheet" href="theme.css"> <link rel="stylesheet" href="version.css"> + + <script src="https://unpkg.com/kg-dataset-previewer@0.0.17/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer> + </script> <title>Interactive Atlas Viewer</title> <script type="application/ld+json"> diff --git a/src/main-common.ts b/src/main-common.ts index bab701a2d3fe8a9393ce15baff88cdfc41ada238..06e9222bef12cbabfaeeee0df0b43df0d106abb1 100644 --- a/src/main-common.ts +++ b/src/main-common.ts @@ -7,7 +7,6 @@ import 'zone.js' import { enableProdMode } from '@angular/core'; import * as ConnectivityComponent from 'hbp-connectivity-component/dist/loader' -import * as PreviewDatasetComponent from 'kg-dataset-previewer/loader' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { MainModule } from './main.module'; @@ -21,5 +20,4 @@ requireAll(require.context(`./plugin_examples`, true)) platformBrowserDynamic().bootstrapModule(MainModule) -PreviewDatasetComponent.defineCustomElements(window) ConnectivityComponent.defineCustomElements(window) \ No newline at end of file diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index fe2e37e3fa217284365790cf3d3fc7b92c64aedc..52503c7c789b31592f4b928030d79eb3de2c4821 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -669,5 +669,34 @@ kg-dataset-previewer > img .h-117px { min-height:117px!important; + max-height:117px!important; flex-basis: 117px!important; } + +.hover-grab +{ + opacity: 0.5; + transition: opacity 200ms ease-in-out; +} + +.hover-grab:hover +{ + cursor: grab; + opacity: 1.0; +} + +.ml-4-n +{ + margin-left: -1rem!important; +} +.mr-4-n +{ + margin-right: -1rem!important; +} + +.mat-card-sm > mat-dialog-container +{ + padding-left: 16px!important; + padding-right: 16px!important; + padding-top: 16px!important; +} diff --git a/src/theme.scss b/src/theme.scss index 2603ff81c7c0cd003777a057e40f570cc59ae9f6..71c0a7c3daf2b3dcc3be5cc537971efc75e1aecd 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -45,3 +45,11 @@ $iv-dark-theme: mat-dark-theme($iv-dark-theme-primary, $iv-dark-theme-accent, max-width: 50vw!important; } } + +.col-xxl-2 +{ + @media (min-width: 2000px) { + max-width: 16.67%; + flex: 0 0 16.67%; + } +} diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/ui/databrowserModule/databrowser.module.ts index 3656b5d487fe9be1e7a445762e087952babf0f75..e2691ed9f9b9088343111934b521167d2a3857b4 100644 --- a/src/ui/databrowserModule/databrowser.module.ts +++ b/src/ui/databrowserModule/databrowser.module.ts @@ -26,6 +26,7 @@ import { GetKgSchemaIdFromFullIdPipe } from "./util/getKgSchemaIdFromFullId.pipe import { ResetCounterModalityPipe } from "./util/resetCounterModality.pipe"; import { PreviewFileVisibleInSelectedReferenceTemplatePipe } from "./util/previewFileDisabledByReferenceSpace.pipe"; import { DatasetPreviewList, UnavailableTooltip } from "./singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.component"; +import { PreviewComponentWrapper } from "./preview/previewComponentWrapper/previewCW.component"; @NgModule({ imports: [ @@ -42,6 +43,7 @@ import { DatasetPreviewList, UnavailableTooltip } from "./singleDataset/datasetP SingleDatasetView, SingleDatasetListView, DatasetPreviewList, + PreviewComponentWrapper, /** * pipes @@ -73,6 +75,7 @@ import { DatasetPreviewList, UnavailableTooltip } from "./singleDataset/datasetP entryComponents: [ DataBrowser, SingleDatasetView, + PreviewComponentWrapper ], providers: [ KgSingleDatasetService, diff --git a/src/ui/databrowserModule/databrowser.useEffect.ts b/src/ui/databrowserModule/databrowser.useEffect.ts index f59176760a1dde918e854dbd722b645bb841a668..968f04f0a9cb7cbf40409e2aea164a27d5d506ab 100644 --- a/src/ui/databrowserModule/databrowser.useEffect.ts +++ b/src/ui/databrowserModule/databrowser.useEffect.ts @@ -6,13 +6,15 @@ import { catchError, filter, map, scan, switchMap, withLatestFrom, mapTo, shareR import { LoggingService } from "src/services/logging.service"; import { DATASETS_ACTIONS_TYPES, IDataEntry, ViewerPreviewFile } from "src/services/state/dataStore.store"; import { IavRootStoreInterface, ADD_NG_LAYER, CHANGE_NAVIGATION } from "src/services/stateStore.service"; -import { LOCAL_STORAGE_CONST } from "src/util/constants"; +import { LOCAL_STORAGE_CONST, DS_PREVIEW_URL } from "src/util/constants"; import { getIdFromDataEntry } from "./databrowser.service"; import { KgSingleDatasetService } from "./kgSingleDatasetService.service"; import { determinePreviewFileType, PREVIEW_FILE_TYPES } from "./preview/previewFileIcon.pipe"; import { GLSL_COLORMAP_JET } from "src/atlasViewer/atlasViewer.constantService.service"; import { SHOW_BOTTOM_SHEET } from "src/services/state/uiState.store"; import {MatSnackBar} from "@angular/material/snack-bar"; +import { MatDialog } from "@angular/material/dialog"; +import { PreviewComponentWrapper } from "./preview/previewComponentWrapper/previewCW.component"; const savedFav$ = of(window.localStorage.getItem(LOCAL_STORAGE_CONST.FAV_DATASET)).pipe( map(string => JSON.parse(string)), @@ -56,9 +58,47 @@ export class DataBrowserUseEffect implements OnDestroy { private actions$: Actions<any>, private kgSingleDatasetService: KgSingleDatasetService, private log: LoggingService, - private snackbar: MatSnackBar + private snackbar: MatSnackBar, + private dialog: MatDialog ) { + this.subscriptions.push( + this.store$.pipe( + select('dataStore'), + select('datasetPreviews'), + filter(datasetPreviews => datasetPreviews.length > 0), + map((datasetPreviews) => datasetPreviews[datasetPreviews.length - 1]), + filter(({ file }) => determinePreviewFileType(file) !== PREVIEW_FILE_TYPES.NIFTI) + ).subscribe(({ dataset, file }) => { + + const { fullId, name } = dataset + const { filename } = file + + // TODO replace with common/util/getIdFromFullId + const previewKgId = /\/([a-f0-9-]{1,})$/.exec(fullId)[1] + + this.dialog.open( + PreviewComponentWrapper, + { + hasBackdrop: false, + disableClose: true, + autoFocus: false, + panelClass: 'mat-card-sm', + height: '50vh', + position: { + left: '5px' + }, + data: { + filename, + kgId: previewKgId, + backendUrl: DS_PREVIEW_URL, + datasetName: name + } + } + ) + }) + ) + this.previewDatasetFile$ = actions$.pipe( ofType(DATASETS_ACTIONS_TYPES.PREVIEW_DATASET), map(actionBody => { diff --git a/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts b/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..48094f998f402e8d4230e16da6b7ab3740ad6b2d --- /dev/null +++ b/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts @@ -0,0 +1,43 @@ +import { Component, Input, Inject } from "@angular/core"; +import { MAT_DIALOG_DATA } from "@angular/material/dialog"; +import { AtlasViewerConstantsServices } from "../../singleDataset/singleDataset.base"; +import { Observable } from "rxjs"; + +@Component({ + templateUrl: './previewCW.template.html', + styleUrls: [ + './previewCW.style.css' + ] +}) + +export class PreviewComponentWrapper{ + + public darktheme$: Observable<boolean> + + @Input() + filename: string + + @Input() + kgId: string + + @Input() + backendUrl: string + + @Input() + datasetName: string + + constructor( + @Inject(MAT_DIALOG_DATA) data: any, + private constantService: AtlasViewerConstantsServices + ){ + + this.darktheme$ = this.constantService.darktheme$ + if (data) { + const { filename, kgId, backendUrl, datasetName } = data + this.filename = filename + this.kgId = kgId + this.backendUrl = backendUrl + this.datasetName = datasetName + } + } +} \ No newline at end of file diff --git a/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.style.css b/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.style.css new file mode 100644 index 0000000000000000000000000000000000000000..e2a3a332d36f04c17c2eea1ff89e212e0a026519 --- /dev/null +++ b/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.style.css @@ -0,0 +1,6 @@ +:host +{ + height:100%; + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.template.html b/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.template.html new file mode 100644 index 0000000000000000000000000000000000000000..bb6a1112dcc8bc26f0f4dd41a2a020e2974b773c --- /dev/null +++ b/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.template.html @@ -0,0 +1,39 @@ +<h1 mat-dialog-title + class="flex-shrink-0 flex-grow-0"> + <div class="d-flex flex-row"> + + <!-- drag handle --> + <div class="flex-grow-0 flex-shrink-0 d-flex align-items-center hover-grab ml-4-n" + cdkDrag + cdkDragHandle + cdkDragRootElement=".cdk-overlay-pane"> + <i class="fas fa-grip-vertical pr-4 pl-4"></i> + </div> + + <!-- main content --> + <div class="flex-grow-1 flex-shrink-1"> + <span class="d-block"> + {{ filename }} + </span> + <small class="text-muted d-block"> + {{ datasetName }} + </small> + </div> + + <!-- close btn --> + <div class="flex-grow-0 flex-shrink-0 d-flex align-items-center text-muted"> + <button mat-dialog-close mat-icon-button> + <i class="fa-2x fas fa-times"></i> + </button> + </div> + </div> +</h1> + +<kg-dataset-previewer + class="flex-grow-1 flex-shrink-1" + [darkmode]="darktheme$ | async" + [filename]="filename" + [kgId]="kgId" + [backendUrl]="backendUrl"> + +</kg-dataset-previewer> diff --git a/src/ui/searchSideNav/searchSideNav.component.ts b/src/ui/searchSideNav/searchSideNav.component.ts index ccc9b068fa8d4a492d881e0587368a531baba131..019d18d1c60825ef954d8cd3cede36438bb8fc1e 100644 --- a/src/ui/searchSideNav/searchSideNav.component.ts +++ b/src/ui/searchSideNav/searchSideNav.component.ts @@ -13,7 +13,6 @@ import { IavRootStoreInterface, SELECT_REGIONS } from "src/services/stateStore.s import { LayerBrowser } from "../layerbrowser/layerbrowser.component"; import { trackRegionBy } from '../viewerStateController/regionHierachy/regionHierarchy.component' import { determinePreviewFileType, PREVIEW_FILE_TYPES } from "../databrowserModule/preview/previewFileIcon.pipe"; -import { DS_PREVIEW_URL } from 'src/util/constants' import {MatDialog, MatDialogRef} from "@angular/material/dialog"; import {MatSnackBar} from "@angular/material/snack-bar"; @@ -34,7 +33,6 @@ export class SearchSideNav implements OnDestroy { @Output() public dismiss: EventEmitter<any> = new EventEmitter() @ViewChild('layerBrowserTmpl', {read: TemplateRef}) public layerBrowserTmpl: TemplateRef<any> - @ViewChild('kgDatasetPreviewer', {read: TemplateRef}) private kgDatasetPreview: TemplateRef<any> public autoOpenSideNavDataset$: Observable<any> @@ -43,13 +41,11 @@ export class SearchSideNav implements OnDestroy { public darktheme$: Observable<boolean> - public DS_PREVIEW_URL = DS_PREVIEW_URL - constructor( public dialog: MatDialog, private store$: Store<IavRootStoreInterface>, private snackBar: MatSnackBar, - private constantService: AtlasViewerConstantsServices, + private constantService: AtlasViewerConstantsServices ) { this.darktheme$ = this.constantService.darktheme$ @@ -71,35 +67,10 @@ export class SearchSideNav implements OnDestroy { this.sidePanelCurrentViewContent = this.store$.pipe( select('uiState'), - select("sidePanelCurrentViewContent"), - ) - - this.subscriptions.push( - this.store$.pipe( - select('dataStore'), - select('datasetPreviews'), - filter(datasetPreviews => datasetPreviews.length > 0), - map((datasetPreviews) => datasetPreviews[datasetPreviews.length - 1]), - filter(({ file }) => determinePreviewFileType(file) !== PREVIEW_FILE_TYPES.NIFTI) - ).subscribe(({ dataset, file }) => { - - const { fullId } = dataset - const { filename } = file - - // TODO replace with common/util/getIdFromFullId - this.previewKgId = /\/([a-f0-9-]{1,})$/.exec(fullId)[1] - this.previewFilename = filename - this.dialog.open(this.kgDatasetPreview, { - minWidth: '50vw', - minHeight: '50vh' - }) - }) + select("sidePanelCurrentViewContent") ) } - public previewKgId: string - public previewFilename: string - public collapseSidePanelCurrentView() { this.store$.dispatch({ type: COLLAPSE_SIDE_PANEL_CURRENT_VIEW, diff --git a/src/ui/searchSideNav/searchSideNav.template.html b/src/ui/searchSideNav/searchSideNav.template.html index 223de4c5cabc39966f89dbb477513dad065072ce..d504105a6a72b6ff19ec6dcb48fff8d778529fde 100644 --- a/src/ui/searchSideNav/searchSideNav.template.html +++ b/src/ui/searchSideNav/searchSideNav.template.html @@ -172,14 +172,3 @@ </ng-template> </ng-container> </ng-template> - - -<ng-template #kgDatasetPreviewer> - <kg-dataset-previewer - [darkmode]="darktheme$ | async" - [filename]="previewFilename" - [kgId]="previewKgId" - [backendUrl]="DS_PREVIEW_URL"> - - </kg-dataset-previewer> -</ng-template> \ No newline at end of file