diff --git a/common/constants.js b/common/constants.js index bdc389ddccba9f4b6227cec7357fc6def00443cb..6e92cffca6399f0182809b2f5e488ae189fc2471 100644 --- a/common/constants.js +++ b/common/constants.js @@ -17,6 +17,9 @@ ZOOM_OUT: 'Zoom out', MAXIMISE_VIEW: 'Maximise this view', UNMAXIMISE_VIEW: 'Undo maximise', + STATUS_PANEL: 'Viewre status panel', + SHOW_FULL_STATUS_PANEL: 'Show full status panel', + HIDE_FULL_STATUS_PANEL: 'Hide full status panel', // sharing module SHARE_BTN: `Share this view`, diff --git a/e2e/src/layout/statusbar.prod.e2e-spec.js b/e2e/src/layout/statusbar.prod.e2e-spec.js new file mode 100644 index 0000000000000000000000000000000000000000..facf6b01c61327e12946de0f04fdc67f6a43eb72 --- /dev/null +++ b/e2e/src/layout/statusbar.prod.e2e-spec.js @@ -0,0 +1,75 @@ +const { AtlasPage } = require('../util') +const { ARIA_LABELS } = require('../../../common/constants') +const { retry } = require('../../../common/util') +describe('> statusbar', () => { + let atlasPage = new AtlasPage() + beforeEach(async () => { + atlasPage = new AtlasPage() + await atlasPage.init() + }) + + it('> on init, should not be visible', async () => { + await atlasPage.goto() + try { + const visible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.STATUS_PANEL}"]`) + expect(visible).toBeFalsy() + } catch (e) { + + } + }) + + describe('> on template selection', () => { + beforeEach(async () => { + await atlasPage.goto() + await atlasPage.selectTitleCard('MNI Colin 27') + await retry(async () => { + const populated = await atlasPage.viewerIsPopulated() + if (!populated) throw new Error(`viewer not yet populated`) + }, { retries: 10, timeout: 500 }) + + }) + it('> on template selection, should be visible', async () => { + + const visible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.STATUS_PANEL}"]`) + expect(visible).toBeTruthy() + }) + + it('> on template selection, minimised status panel should be visible', async () => { + const maximaizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`) + expect(maximaizeVisible).toBeTruthy() + try { + const minimizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`) + expect(minimizeVisible).toBeFalsy() + } catch (e) { + + } + }) + + it('> clicking maximise btn should maximise the status panel', async () => { + await atlasPage.click(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`) + await atlasPage.wait(500) + const minimizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`) + expect(minimizeVisible).toBeTruthy() + try { + const maxVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`) + expect(maxVisible).toBeFalsy() + } catch (e) { + + } + }) + + it('> click min btn should minimize', async () => { + await atlasPage.click(`[aria-label="${ARIA_LABELS.SHOW_FULL_STATUS_PANEL}"]`) + await atlasPage.wait(500) + await atlasPage.click(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`) + await atlasPage.wait(500) + try { + const minimizeVisible = await atlasPage.isVisible(`[aria-label="${ARIA_LABELS.HIDE_FULL_STATUS_PANEL}"]`) + expect(minimizeVisible).toBeFalsy() + } catch (e) { + + } + }) + }) + +}) \ No newline at end of file diff --git a/src/theme.scss b/src/theme.scss index abd448e9a7231ea1b22d833665f520a585e9ee54..df4be08f036b9b460e39f9af7394e5464e2e2a2d 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -3,6 +3,9 @@ @include mat-core(); @mixin custom-cmp($theme) { + + $foreground: map-get($theme, foreground); + $primary: map-get($theme, primary); $accent: map-get($theme, accent); $warn: map-get($theme, warn); @@ -10,6 +13,11 @@ [iv-custom-comp], .iv-custom-comp { + &[text], + &.text + { + color: mat-color($foreground, text); + } &[primary], &.primary { diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index 01662e13500a7fd8d5f2704f6f63670ab213db75..3f76494c5de503ef47ca433649cdb438ab8dc819 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -28,9 +28,7 @@ <!-- StatusCard container--> <div class="status-card-container muted-7"> <ui-status-card - *ngIf="!(useMobileUI$ | async)" [selectedTemplateName]="selectedTemplate && selectedTemplate.name" - [isMobile]="useMobileUI$ | async" [nehubaViewer]="nehubaViewer"> </ui-status-card> </div> diff --git a/src/ui/nehubaContainer/statusCard/statusCard.component.ts b/src/ui/nehubaContainer/statusCard/statusCard.component.ts index e754370995cbc660dc16ce9bdf2ded98b6ceacac..bdbcea45e00aab2831fcc8da64080f8af97825f9 100644 --- a/src/ui/nehubaContainer/statusCard/statusCard.component.ts +++ b/src/ui/nehubaContainer/statusCard/statusCard.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, OnChanges, TemplateRef } from "@angular/core"; +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"; @@ -8,6 +8,7 @@ import { distinctUntilChanged, shareReplay, map, filter, startWith } from "rxjs/ import { MatBottomSheet } from "@angular/material/bottom-sheet"; import { MatDialog } from "@angular/material/dialog"; import { ARIA_LABELS } from 'common/constants' +import { PureContantService } from "src/util"; @Component({ selector : 'ui-status-card', @@ -17,9 +18,12 @@ import { ARIA_LABELS } from 'common/constants' export class StatusCardComponent implements OnInit, OnChanges{ @Input() public selectedTemplateName: string; - @Input() public isMobile: boolean; @Input() public nehubaViewer: NehubaViewerUnit; + @HostBinding('attr.aria-label') + public arialabel = ARIA_LABELS.STATUS_PANEL + public showFull = false + private selectedTemplateRoot$: Observable<any> private selectedTemplateRoot: any private subscriptions: Subscription[] = [] @@ -27,17 +31,21 @@ export class StatusCardComponent implements OnInit, OnChanges{ public navVal$: Observable<string> public mouseVal$: Observable<string> + public useTouchInterface$: Observable<boolean> + public SHARE_BTN_ARIA_LABEL = ARIA_LABELS.SHARE_BTN public COPY_URL_TO_CLIPBOARD_ARIA_LABEL = ARIA_LABELS.SHARE_COPY_URL_CLIPBOARD public SHARE_CUSTOM_URL_ARIA_LABEL = ARIA_LABELS.SHARE_CUSTOM_URL public SHARE_CUSTOM_URL_DIALOG_ARIA_LABEL = ARIA_LABELS.SHARE_CUSTOM_URL_DIALOG - + 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 bottomSheet: MatBottomSheet, private dialog: MatDialog, + private pureConstantService: PureContantService ) { const viewerState$ = this.store$.pipe( select('viewerState'), @@ -47,6 +55,8 @@ export class StatusCardComponent implements OnInit, OnChanges{ select('fetchedTemplates'), distinctUntilChanged(), ) + + this.useTouchInterface$ = this.pureConstantService.useTouchUI$ } ngOnInit(): void { diff --git a/src/ui/nehubaContainer/statusCard/statusCard.template.html b/src/ui/nehubaContainer/statusCard/statusCard.template.html index b7baf40610f840a848f737c6c85acef0f6af6808..88779b7f4f98be27d66948f9232dcdab028501c2 100644 --- a/src/ui/nehubaContainer/statusCard/statusCard.template.html +++ b/src/ui/nehubaContainer/statusCard/statusCard.template.html @@ -1,4 +1,4 @@ -<mat-card> +<mat-card *ngIf="showFull; else showMin"> <mat-card-content> <!-- reset --> @@ -29,6 +29,14 @@ matTooltip="Reset zoom"> <i class="fas fa-search-plus"></i> </button> + + <mat-divider [vertical]="true"></mat-divider> + + <button mat-icon-button + [attr.aria-label]="HIDE_FULL_STATUS_PANEL_ARIA_LABEL" + (click)="showFull = false"> + <i class="fas fa-angle-down"></i> + </button> </div> <!-- space --> @@ -76,7 +84,7 @@ </div> <!-- cursor pos --> - <mat-form-field *ngIf="!isMobile" + <mat-form-field *ngIf="!(useTouchInterface$ | async)" class="w-100"> <mat-label> Cursor Position @@ -90,6 +98,36 @@ </mat-card-content> </mat-card> +<!-- minimised status bar --> +<ng-template #showMin> + <div class="iv-custom-comp text overflow-visible text-nowrap d-inline-flex align-items-center pb-2"> + + <i aria-label="viewer navigation" class="fas fa-compass"></i> + <span class="pl-2"> + {{ navVal$ | async }} + </span> + + <!-- only show cursor if touch interface is not on --> + <span *ngIf="!(useTouchInterface$ | async)"> + <!-- padding --> + <span class="pl-4"></span> + + <i aria-label="cursor location" class="fas fa-mouse-pointer"></i> + <span class="pl2"> + {{ mouseVal$ | async }} + </span> + </span> + + <mat-divider [vertical]="true"></mat-divider> + + <button mat-icon-button + [attr.aria-label]="SHOW_FULL_STATUS_PANEL_ARIA_LABEL" + (click)="showFull = true"> + <i class="fas fa-angle-up"></i> + </button> + </div> +</ng-template> + <!-- share template --> <ng-template #shareTmpl> <h4 class="mat-h4">