Skip to content
Snippets Groups Projects
Unverified Commit d3f98db1 authored by xgui3783's avatar xgui3783 Committed by GitHub
Browse files

Merge pull request #711 from HumanBrainProject/bugfix_statusPanelReset

bugfix: status panel causes nav errors (#707)
parents 21df7e8a 29c31f41
No related branches found
No related tags found
No related merge requests found
......@@ -25,6 +25,7 @@ import {
viewerStateNewViewer
} from './viewerState.store.helper';
import { cvtNehubaConfigToNavigationObj } from 'src/ui/viewerStateController/viewerState.useEffect';
import { viewerStateChangeNavigation } from './viewerState/actions';
export interface StateInterface {
fetchedTemplates: any[]
......@@ -162,6 +163,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Part
fetchedTemplates: prevState.fetchedTemplates.concat(action.fetchedTemplate),
}
}
case viewerStateChangeNavigation.type:
case CHANGE_NAVIGATION : {
return {
...prevState,
......@@ -271,7 +273,7 @@ export const UNLOAD_DEDICATED_LAYER = 'UNLOAD_DEDICATED_LAYER'
export const NEWVIEWER = viewerStateNewViewer.type
export const FETCHED_TEMPLATE = 'FETCHED_TEMPLATE'
export const CHANGE_NAVIGATION = 'CHANGE_NAVIGATION'
export const CHANGE_NAVIGATION = viewerStateChangeNavigation.type
export const SELECT_PARCELLATION = viewerStateSelectParcellation.type
......
......@@ -105,3 +105,7 @@ export const viewerStateMouseOverCustomLandmarkInPerspectiveView = createAction(
props<{ payload: { label: string } }>()
)
export const viewerStateChangeNavigation = createAction(
`[viewerState] changeNavigation`,
props<{ navigation: any }>()
)
import { createSelector } from "@ngrx/store"
import { create } from "domain"
import { viewerStateHelperStoreName } from "../viewerState.store.helper"
export const viewerStateSelectedRegionsSelector = createSelector(
......@@ -32,6 +33,18 @@ export const viewerStateSelectedTemplateSelector = createSelector(
viewerState => viewerState['templateSelected']
)
/**
* viewerStateSelectedTemplateSelector may have it navigation mutated to allow for initiliasation of viewer at the correct navigation
* in some circumstances, it may be required to get the original navigation object
*/
export const viewerStateSelectedTemplatePureSelector = createSelector(
viewerStateFetchedTemplatesSelector,
viewerStateSelectedTemplateSelector,
(fetchedTemplates, selectedTemplate) => {
return fetchedTemplates.find(t => t['@id'] === selectedTemplate('@id'))
}
)
export const viewerStateSelectedParcellationSelector = createSelector(
state => state['viewerState'],
viewerState => viewerState['parcellationSelected']
......
import { async, TestBed } from "@angular/core/testing"
import { async, ComponentFixture, TestBed } from "@angular/core/testing"
import { CommonModule } from "@angular/common"
import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module"
import { StatusCardComponent } from "./statusCard.component"
import { Directive, Component } from "@angular/core"
import { of } from "rxjs"
import { Observable, of } from "rxjs"
import { ShareModule } from "src/share"
import { StateModule } from "src/state"
import { MockStore, provideMockStore } from "@ngrx/store/testing"
......@@ -13,6 +13,9 @@ import { NoopAnimationsModule } from "@angular/platform-browser/animations"
import { FormsModule, ReactiveFormsModule } from "@angular/forms"
import { UtilModule } from "src/util"
import { viewerConfigSelectorUseMobileUi } from "src/services/state/viewerConfig.store.helper"
import { viewerStateNavigationStateSelector, viewerStateSelectedTemplatePureSelector } from "src/services/state/viewerState/selectors"
import * as util from '../util'
import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions"
@Directive({
selector: '[iav-auth-authState]',
......@@ -73,55 +76,126 @@ describe('> statusCard.component.ts', () => {
expect(fixture.debugElement.nativeElement).toBeTruthy()
})
it('> toggle can be found if showFull is set to true', () => {
const fixture = TestBed.createComponent(StatusCardComponent)
fixture.detectChanges()
fixture.componentInstance.showFull = true
fixture.detectChanges()
const slider = fixture.debugElement.query( By.directive(MatSlideToggle) )
expect(slider).toBeTruthy()
})
describe('> in full mode, UIs are visible', () => {
let fixture: ComponentFixture<StatusCardComponent>
it('> toggling voxel/real toggle also toggles statusPanelRealSpace flag', () => {
beforeEach(() => {
const fixture = TestBed.createComponent(StatusCardComponent)
fixture.detectChanges()
fixture.componentInstance.showFull = true
fixture.detectChanges()
fixture = TestBed.createComponent(StatusCardComponent)
fixture.detectChanges()
fixture.componentInstance.showFull = true
fixture.detectChanges()
})
it('> toggle can be found', () => {
const prevFlag = fixture.componentInstance.statusPanelRealSpace
const sliderEl = fixture.debugElement.query( By.directive(MatSlideToggle) )
const slider = sliderEl.injector.get(MatSlideToggle)
slider.toggle()
fixture.detectChanges()
expect(fixture.componentInstance.statusPanelRealSpace).toEqual(!prevFlag)
const slider = fixture.debugElement.query( By.directive(MatSlideToggle) )
expect(slider).toBeTruthy()
})
it('> toggling voxel/real toggle also toggles statusPanelRealSpace flag', () => {
const prevFlag = fixture.componentInstance.statusPanelRealSpace
const sliderEl = fixture.debugElement.query( By.directive(MatSlideToggle) )
const slider = sliderEl.injector.get(MatSlideToggle)
slider.toggle()
fixture.detectChanges()
expect(fixture.componentInstance.statusPanelRealSpace).toEqual(!prevFlag)
})
describe('> textNavigationTo', () => {
it('> takes into account of statusPanelRealSpace panel', () => {
const setNavigationStateSpy = jasmine.createSpy('setNavigationState')
fixture.componentInstance.nehubaViewer = {
setNavigationState: setNavigationStateSpy
} as any
fixture.componentInstance.statusPanelRealSpace = true
fixture.componentInstance.textNavigateTo('1, 0, 0')
expect(setNavigationStateSpy).toHaveBeenCalledWith({
position: [1e6, 0, 0],
positionReal: true
})
fixture.componentInstance.statusPanelRealSpace = false
fixture.componentInstance.textNavigateTo('1, 0, 0')
expect(setNavigationStateSpy).toHaveBeenCalledWith({
position: [1, 0, 0],
positionReal: false
})
})
})
})
describe('> textNavigationTo', () => {
it('> takes into account of statusPanelRealSpace panel', () => {
const fixture = TestBed.createComponent(StatusCardComponent)
describe('> resetNavigation', () => {
let fixture: ComponentFixture<StatusCardComponent>
const mockCurrNavigation = {
orientation: [1,0,0,0],
position: [100,200,300],
perspectiveZoom: 1e9,
zoom: 1e9,
perspectiveOrientation: [1,0,0,0]
}
const mockNavState = {
orientation: [0,0,0,1],
position: [10,20,30],
perspectiveZoom: 1e6,
zoom: 1e6,
perspectiveOrientation: [0,0,0,1]
}
const mockTemplate = { foo:'bar', nehubaConfig: { foo2: 'bar2' } }
let getNavigationStateFromConfigSpy: jasmine.Spy = jasmine.createSpy('getNavigationStateFromConfig').and.returnValue(mockNavState)
beforeEach(() => {
const mockStore = TestBed.inject(MockStore)
mockStore.overrideSelector(viewerStateSelectedTemplatePureSelector, mockTemplate)
mockStore.overrideSelector(viewerStateNavigationStateSelector, mockCurrNavigation)
spyOnProperty(util, 'getNavigationStateFromConfig').and.returnValue(getNavigationStateFromConfigSpy)
fixture = TestBed.createComponent(StatusCardComponent)
fixture.detectChanges()
const setNavigationStateSpy = jasmine.createSpy('setNavigationState')
fixture.componentInstance.nehubaViewer = {
setNavigationState: setNavigationStateSpy
} as any
fixture.componentInstance.statusPanelRealSpace = true
fixture.componentInstance.textNavigateTo('1, 0, 0')
expect(setNavigationStateSpy).toHaveBeenCalledWith({
position: [1e6, 0, 0],
positionReal: true
})
fixture.componentInstance.showFull = true
fixture.detectChanges()
})
for (const method of ['rotation', 'position', 'zoom' ]) {
describe(`> method: ${method}`, () => {
it(`> resetNavigation call calls getNavigationStateFromConfig`, () => {
fixture.componentInstance.resetNavigation({ [method]: true, })
fixture.detectChanges()
expect(getNavigationStateFromConfigSpy).toHaveBeenCalled()
})
fixture.componentInstance.statusPanelRealSpace = false
fixture.componentInstance.textNavigateTo('1, 0, 0')
expect(setNavigationStateSpy).toHaveBeenCalledWith({
position: [1, 0, 0],
positionReal: false
it('> resetNavigation dispatches correct action', () => {
const mockStore = TestBed.inject(MockStore)
const idspatchSpy = spyOn(mockStore, 'dispatch')
fixture.componentInstance.resetNavigation({ [method]: true, })
fixture.detectChanges()
const overrideObj = {}
if (method === 'rotation') overrideObj['orientation'] = mockNavState['orientation']
if (method === 'position') overrideObj['position'] = mockNavState['position']
if (method === 'zoom') overrideObj['zoom'] = mockNavState['zoom']
expect(idspatchSpy).toHaveBeenCalledWith(
viewerStateChangeNavigation({
navigation: {
...mockCurrNavigation,
...overrideObj,
positionReal: false,
animation: {},
}
})
)
})
})
})
}
})
})
})
import { Component, Input, OnInit, OnChanges, TemplateRef, HostBinding } from "@angular/core";
import { select, Store } from "@ngrx/store";
import { LoggingService } from "src/logging";
import { CHANGE_NAVIGATION, IavRootStoreInterface, ViewerStateInterface } from "src/services/stateStore.service";
import { IavRootStoreInterface } from "src/services/stateStore.service";
import { NehubaViewerUnit } from "../nehubaViewer/nehubaViewer.component";
import { Observable, Subscription, of, combineLatest, BehaviorSubject } from "rxjs";
import { distinctUntilChanged, shareReplay, map, filter, startWith } from "rxjs/operators";
import { Observable, Subscription, of, combineLatest } from "rxjs";
import { map, filter, startWith } from "rxjs/operators";
import { MatBottomSheet } from "@angular/material/bottom-sheet";
import { MatDialog } from "@angular/material/dialog";
import { ARIA_LABELS } from 'common/constants'
import { PureContantService } from "src/util";
import { FormControl } from "@angular/forms";
import { viewerStateNavigationStateSelector, viewerStateSelectedTemplatePureSelector } from "src/services/state/viewerState/selectors";
import { getNavigationStateFromConfig } from "../util";
import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
@Component({
selector : 'ui-status-card',
......@@ -25,8 +28,8 @@ export class StatusCardComponent implements OnInit, OnChanges{
public arialabel = ARIA_LABELS.STATUS_PANEL
public showFull = false
private selectedTemplateRoot$: Observable<any>
private selectedTemplateRoot: any
private selectedTemplatePure: any
private currentNavigation: any
private subscriptions: Subscription[] = []
public navVal$: Observable<string>
......@@ -41,36 +44,32 @@ export class StatusCardComponent implements OnInit, OnChanges{
public SHOW_FULL_STATUS_PANEL_ARIA_LABEL = ARIA_LABELS.SHOW_FULL_STATUS_PANEL
public HIDE_FULL_STATUS_PANEL_ARIA_LABEL = ARIA_LABELS.HIDE_FULL_STATUS_PANEL
constructor(
private store: Store<ViewerStateInterface>,
private log: LoggingService,
private store$: Store<IavRootStoreInterface>,
private log: LoggingService,
private bottomSheet: MatBottomSheet,
private dialog: MatDialog,
private pureConstantService: PureContantService
) {
const viewerState$ = this.store$.pipe(
select('viewerState'),
shareReplay(1),
)
this.selectedTemplateRoot$ = viewerState$.pipe(
select('fetchedTemplates'),
distinctUntilChanged(),
)
this.useTouchInterface$ = this.pureConstantService.useTouchUI$
}
ngOnInit(): void {
this.subscriptions.push(
this.selectedTemplateRoot$.subscribe(template => {
this.selectedTemplateRoot = template.find(t => t.name === this.selectedTemplateName)
this.statusPanelFormCtrl.valueChanges.subscribe(val => {
this.statusPanelRealSpace = val
})
)
this.subscriptions.push(
this.statusPanelFormCtrl.valueChanges.subscribe(val => {
this.statusPanelRealSpace = val
})
this.store$.pipe(
select(viewerStateSelectedTemplatePureSelector)
).subscribe(n => this.selectedTemplatePure = n)
)
this.subscriptions.push(
this.store$.pipe(
select(viewerStateNavigationStateSelector)
).subscribe(nav => this.currentNavigation = nav)
)
}
......@@ -80,7 +79,7 @@ export class StatusCardComponent implements OnInit, OnChanges{
this.mouseVal$ = of(`neubaViewer is undefined`)
return
}
this.navVal$ = combineLatest(
this.navVal$ = combineLatest([
this.statusPanelRealSpace$,
this.nehubaViewer.viewerPosInReal$.pipe(
filter(v => !!v)
......@@ -88,14 +87,14 @@ export class StatusCardComponent implements OnInit, OnChanges{
this.nehubaViewer.viewerPosInVoxel$.pipe(
filter(v => !!v)
)
).pipe(
]).pipe(
map(([realFlag, real, voxel]) => realFlag
? real.map(v => `${ (v / 1e6).toFixed(3) }mm`).join(', ')
: voxel.map(v => v.toFixed(3)).join(', ') ),
startWith(`nehubaViewer initialising`)
)
this.mouseVal$ = combineLatest(
this.mouseVal$ = combineLatest([
this.statusPanelRealSpace$,
this.nehubaViewer.mousePosInReal$.pipe(
filter(v => !!v)
......@@ -103,7 +102,7 @@ export class StatusCardComponent implements OnInit, OnChanges{
this.nehubaViewer.mousePosInVoxel$.pipe(
filter(v => !!v)
)
).pipe(
]).pipe(
map(([realFlag, real, voxel]) => realFlag
? real.map(v => `${ (v/1e6).toFixed(3) }mm`).join(', ')
: voxel.map(v => v.toFixed(3)).join(', ')),
......@@ -111,7 +110,7 @@ export class StatusCardComponent implements OnInit, OnChanges{
)
}
statusPanelFormCtrl = new FormControl(true, [])
public statusPanelFormCtrl = new FormControl(true, [])
public statusPanelRealSpace = true
public statusPanelRealSpace$ = this.statusPanelFormCtrl.valueChanges.pipe(
startWith(true)
......@@ -143,44 +142,26 @@ export class StatusCardComponent implements OnInit, OnChanges{
* the info re: nehubaViewer can stay there, too
*/
public resetNavigation({rotation: rotationFlag = false, position: positionFlag = false, zoom : zoomFlag = false}: {rotation?: boolean, position?: boolean, zoom?: boolean}) {
const initialNgState = this.selectedTemplateRoot.nehubaConfig.dataset.initialNgState // d sa dsa
const perspectiveZoom = initialNgState ? initialNgState.perspectiveZoom : undefined
const perspectiveOrientation = initialNgState ? initialNgState.perspectiveOrientation : undefined
const zoom = (zoomFlag
&& initialNgState
&& initialNgState.navigation
&& initialNgState.navigation.zoomFactor)
|| undefined
const position = (positionFlag
&& initialNgState
&& initialNgState.navigation
&& initialNgState.navigation.pose
&& initialNgState.navigation.pose.position.voxelCoordinates
&& initialNgState.navigation.pose.position.voxelCoordinates)
|| undefined
const orientation = rotationFlag
? [0, 0, 0, 1]
: undefined
this.store.dispatch({
type : CHANGE_NAVIGATION,
navigation : {
...{
perspectiveZoom,
perspectiveOrientation,
zoom,
position,
orientation,
},
...{
const {
orientation,
perspectiveOrientation,
perspectiveZoom,
position,
zoom
} = getNavigationStateFromConfig(this.selectedTemplatePure.nehubaConfig)
this.store$.dispatch(
viewerStateChangeNavigation({
navigation: {
...this.currentNavigation,
...(rotationFlag ? { orientation: orientation } : {}),
...(positionFlag ? { position: position } : {}),
...(zoomFlag ? { zoom: zoom } : {}),
positionReal : false,
animation : {},
},
},
})
}
})
)
}
openDialog(tmpl: TemplateRef<any>, options) {
......
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