Skip to content
Permalink
Browse files
feat(representation)!: new navigation in still-image viewer (DEV-895) (
…#742)

* feat(representation)!: new still image navigation concept (DEV-895)

* style(representation): resolve style issue

* test(representation): the iiif url caption does not exist anymore

* style(representation): same button arrangement in video as in image
  • Loading branch information
kilchenmann committed May 17, 2022
1 parent 87124e9 commit dbc75ff5283ef995d4d9757e12c9391d17b7c493
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 167 deletions.
@@ -1,52 +1,5 @@
<!-- openseadragon (osd) viewer -->
<div class="osd-container" [class.drawing]="regionDrawMode">
<div class="action horizontal top overlay">
<div class="captions-container">
<div class="top">
<span class="caption mat-caption">{{imageCaption}}</span>
</div>
<div class="bottom">
<div class="iiif-url">
<a href="{{iiifUrl}}" target="_blank" class="mat-caption">{{iiifUrl}}</a>
</div>
<div class="copy-button">
<button
mat-icon-button
matTooltip="Copy IIIF URL to clipboard"
[cdkCopyToClipboard]="iiifUrl"
(click)="openSnackBar('IIIF URL copied to clipboard!')">
<mat-icon>content_copy</mat-icon>
</button>
</div>
</div>
</div>
<!-- caption -->

<span class="fill-remaining-space"></span>
<!-- image action tools e.g. zoom, rotate and flip -->
<span>
<!-- zoom buttons -->
<button mat-icon-button id="DSP_OSD_ZOOM_OUT" matTooltip="Zoom out">
<mat-icon>remove_circle_outline</mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_HOME" matTooltip="Reset zoom">
<mat-icon>adjust</mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_ZOOM_IN" matTooltip="Zoom in">
<mat-icon>add_circle_outline</mat-icon>
</button>
<!-- window button -->
<button mat-icon-button id="DSP_OSD_FULL_PAGE" matTooltip="Open in fullscreen">
<mat-icon>fullscreen</mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_DRAW_REGION" matTooltip="Draw Region" (click)="drawButtonClicked()">
<mat-icon svgIcon="draw_region_icon"></mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_REPLACE_IMAGE" class="replace-image" matTooltip="Replace image" (click)="openReplaceFileDialog()">
<mat-icon>cloud_upload</mat-icon>
</button>
</span>
</div>

<!-- navigation in case of compound object: previous and next page -->
<div class="navigation vertical previous" *ngIf="compoundNavigation">
@@ -62,9 +15,40 @@
</button>
</div>

<!-- footer with image caption e.g. copyright information -->
<div class="navigation horizontal bottom" *ngIf="compoundNavigation">
<span class="compound-nav">
</div>
<!-- /openseadragon (osd) -->

<div class="toolbar bottom">
<!-- navigation -->
<div class="navigation horizontal" *ngIf="compoundNavigation">
<mat-slider [color]="'primary'" [disabled]="compoundNavigation.totalPages < 2"
[max]="compoundNavigation.totalPages" [min]="1" [step]="1" [thumbLabel]="true" [tickInterval]="'auto'"
[(ngModel)]="compoundNavigation.page" (change)="goToPage.emit($event.value)">
</mat-slider>
</div>
<!-- toolbar -->
<div class="action horizontal">
<!-- vertical more button with menu to open and copy iiif url -->
<button mat-icon-button [matMenuTriggerFor]="more">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #more="matMenu">
<a mat-menu-item href="{{iiifUrl}}" target="_blank">
Open file in new tab
</a>
<button mat-menu-item [cdkCopyToClipboard]="iiifUrl"
(click)="openSnackBar('IIIF URL copied to clipboard!')">
Copy IIIF URL to clipboard
</button>
</mat-menu>
<!-- empty placeholder to simulate two buttons; this helps to have the zoom buttons centered with fill-remaining-space setup -->
<span class="empty-space"></span>
<span class="empty-space"></span>

<span class="fill-remaining-space"></span>

<!-- navigation in case of compound object: first page and previous page -->
<span class="compound-nav" *ngIf="compoundNavigation">
<button mat-icon-button [disabled]="compoundNavigation.page <= 1" matTooltip="First page"
(click)="goToPage.emit(1)">
<mat-icon>first_page</mat-icon>
@@ -73,12 +57,23 @@
(click)="goToPage.emit(compoundNavigation.page - 1)">
<mat-icon>navigate_before</mat-icon>
</button>
</span>

<mat-slider [color]="'primary'" [disabled]="compoundNavigation.totalPages < 2"
[max]="compoundNavigation.totalPages" [min]="1" [step]="1" [thumbLabel]="true" [tickInterval]="'auto'"
[(ngModel)]="compoundNavigation.page" (change)="goToPage.emit($event.value)">
</mat-slider>
<!-- zoom buttons: zoom out, home/reset, zoom in -->
<span>
<button mat-icon-button id="DSP_OSD_ZOOM_OUT" matTooltip="Zoom out">
<mat-icon>remove_circle_outline</mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_HOME" matTooltip="Reset zoom">
<mat-icon>adjust</mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_ZOOM_IN" matTooltip="Zoom in">
<mat-icon>add_circle_outline</mat-icon>
</button>
</span>

<!-- navigation in case of compound object: next page and last page -->
<span class="compound-nav" *ngIf="compoundNavigation">
<button mat-icon-button [disabled]="compoundNavigation.page >= compoundNavigation.totalPages"
matTooltip="Next page" (click)="goToPage.emit(compoundNavigation.page + 1)">
<mat-icon>navigate_next</mat-icon>
@@ -88,6 +83,21 @@
<mat-icon>last_page</mat-icon>
</button>
</span>

<span class="fill-remaining-space"></span>

<!-- action buttons: create annotation/region, replace file, fullscreen -->
<span>
<button mat-icon-button id="DSP_OSD_DRAW_REGION" matTooltip="Draw Region" (click)="drawButtonClicked()">
<mat-icon svgIcon="draw_region_icon"></mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_REPLACE_IMAGE" class="replace-image" matTooltip="Replace image"
(click)="openReplaceFileDialog()">
<mat-icon>cloud_upload</mat-icon>
</button>
<button mat-icon-button id="DSP_OSD_FULL_PAGE" matTooltip="Open in fullscreen">
<mat-icon>fullscreen</mat-icon>
</button>
</span>
</div>
</div>
<!-- /openseadragon (osd) -->
@@ -1,12 +1,6 @@
@import "../../../../../assets/style/config";
// sizes
$max-width: 800px;
$panelSize: 40px;

$osd-height: 460px;

:host {
// display: inline-flex;
width: 100%;

@media (max-height: 636px) {
@@ -16,7 +10,7 @@ $osd-height: 460px;
.osd-container {
color: $bright;
background-color: $dark;
height: 100%;
height: calc(100% - 64px);

&.drawing {
cursor: crosshair;
@@ -25,33 +19,59 @@ $osd-height: 460px;
&.fullscreen {
max-width: 100vw;
}
}

.captions-container {
.top, .bottom {
text-align: left;
.iiif-url, .copy-button {
display: inline-block;
}
.iiif-url {
a {
padding: 0px 0px 0px 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 50%;
}
}
.copy-button button {
background: none;
border: none;
color: white;
mat-icon {
font-size: 16px;
}
}
.toolbar {
color: $primary_50;
background-color: $dark;
height: 64px;

.action {
height: 40px;
bottom: 0;
padding: 8px 0;
}
}

.navigation {
position: absolute;
z-index: 1;

// vertical navigation
// on the left resp. on the right hand side of osd viewer
&.vertical {
height: calc(100% - #{$panel-height});
width: $panel-height;
top: $panel-height;
&.previous {
left: 0;
}
&.next {
right: 0;
}
.mat-button.full-size {
height: 100% !important;
width: $panel-height !important;

padding: 0 !important;
min-width: $panel-height !important;
}
}

// horizontal navigation
// slider control container
&.horizontal {
width: 100%;

.mat-slider {
width: 100%;
height: 4px;
bottom: 20px;
}

}
}

}

.annotation-tooltip {
@@ -7,6 +7,7 @@ import { Component, OnInit, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatToolbarModule } from '@angular/material/toolbar';
import { By } from '@angular/platform-browser';
@@ -143,6 +144,7 @@ describe('StillImageComponent', () => {
HttpClientModule,
MatDialogModule,
MatIconModule,
MatMenuModule,
MatSnackBarModule,
MatToolbarModule,
],
@@ -201,31 +203,6 @@ describe('StillImageComponent', () => {

});

it('should display the image caption', () => {

const hostCompDe = testHostFixture.debugElement;
const stillImageComponentDe = hostCompDe.query(By.directive(StillImageComponent));

const captionDebugElement = stillImageComponentDe.query(By.css('.caption'));
const captionEle = captionDebugElement.nativeElement;

expect(captionEle.innerText).toEqual('test image');

});

it('should display the iiifUrl of the image', () => {

const hostCompDe = testHostFixture.debugElement;
const stillImageComponentDe = hostCompDe.query(By.directive(StillImageComponent));

const iiifUrlDebugElement = stillImageComponentDe.query(By.css('.iiif-url a'));
const iiifUrlEle = iiifUrlDebugElement.nativeElement;

expect(iiifUrlEle.innerText).toEqual('https://iiif.test.dasch.swiss:443/0803/incunabula_0000003840.jp2/full/3210,5144/0/default.jpg');
expect(iiifUrlEle.getAttribute('target')).toEqual('_blank');
expect(iiifUrlEle.getAttribute('href')).toEqual('https://iiif.test.dasch.swiss:443/0803/incunabula_0000003840.jp2/full/3210,5144/0/default.jpg');
});

it('should have 1 test region loaded (rectangle)', () => {

const osd = testHostComponent.osdViewerComp['_viewer'];
@@ -66,15 +66,13 @@
{{ muted ? "volume_mute" : "volume_up" }}
</mat-icon>
</button>
<button mat-icon-button (click)="toggleCinemaMode()"
[matTooltip]="(cinemaMode ? 'Default view' : 'Cinema mode')" [matTooltipPosition]="matTooltipPos">
<mat-icon>{{
cinemaMode ? "fullscreen_exit" : "fullscreen"
}}</mat-icon>
</button>
<button mat-icon-button (click)="openReplaceFileDialog()" class="replace-file" matTooltip="Replace video file" [matTooltipPosition]="matTooltipPos">
<mat-icon>cloud_upload</mat-icon>
</button>
<button mat-icon-button (click)="toggleCinemaMode()"
[matTooltip]="(cinemaMode ? 'Default view' : 'Cinema mode')" [matTooltipPosition]="matTooltipPos">
<mat-icon>{{cinemaMode ? "fullscreen_exit" : "fullscreen"}}</mat-icon>
</button>
</mat-toolbar-row>
</mat-toolbar>

@@ -73,11 +73,6 @@
color: rgba(255, 255, 255, 0.26);
}

.empty-space {
display: block;
width: 48px;
}

.time {
margin-top: 12px;
padding: 0 6px;

0 comments on commit dbc75ff

Please sign in to comment.