Pull request #49: Fullscreen

Merge in RED/ui from fullscreen to master

* commit '5682e0a331114e2a456684db80e5af84e9fc3908':
  Fullscreen keyboard shortcut
  Full screen working, missing icons
  Pages panel fix
This commit is contained in:
Timo Bejan 2020-11-30 08:12:55 +01:00
commit 10899e477a
12 changed files with 174 additions and 81 deletions

View File

@ -30,8 +30,10 @@ export class IconsModule {
'edit',
'entries',
'error',
'exit-fullscreen',
'expand',
'folder',
'fullscreen',
'info',
'lightning',
'logout',

View File

@ -1,4 +1,4 @@
<div class="red-top-bar">
<div class="red-top-bar" [class.fullscreen]="fullScreenService.fullScreen">
<div class="top-bar-row">
<div class="menu visible-lt-lg">
<button [matMenuTriggerFor]="menuNav" mat-flat-button>
@ -64,6 +64,6 @@
</div>
<div class="divider"></div>
</div>
<div class="red-content">
<div class="red-content" [class.fullscreen]="fullScreenService.fullScreen">
<router-outlet></router-outlet>
</div>

View File

@ -4,6 +4,7 @@ import { AppStateService } from '../../state/app-state.service';
import { LanguageService } from '../../i18n/language.service';
import { PermissionsService } from '../../common/service/permissions.service';
import { UserPreferenceService } from '../../common/service/user-preference.service';
import { FullScreenService } from '../../utils/full-screen.service';
@Component({
selector: 'redaction-base-screen',
@ -15,6 +16,8 @@ export class BaseScreenComponent {
public readonly appStateService: AppStateService,
public readonly permissionsService: PermissionsService,
public readonly userPreferenceService: UserPreferenceService,
public readonly fullScreenService: FullScreenService,
private readonly _languageService: LanguageService,
private readonly _userService: UserService
) {}

View File

@ -66,6 +66,12 @@
<div class="vertical-line"></div>
<redaction-file-actions (actionPerformed)="fileActionPerformed($event)" *ngIf="viewReady"></redaction-file-actions>
<redaction-circle-button
(action)="fullScreenService.toggleFullScreen()"
icon="red:fullscreen"
tooltip="file-preview.fullscreen"
tooltipPosition="before"
></redaction-circle-button>
<redaction-circle-button
[routerLink]="['/ui/projects/' + appStateService.activeProjectId]"
class="ml-8"
@ -76,7 +82,7 @@
</div>
</div>
<div class="flex red-content-inner">
<div class="flex red-content-inner" [class.fullscreen]="fullScreenService.fullScreen">
<div class="left-container">
<redaction-pdf-viewer
(annotationSelected)="handleAnnotationSelected($event)"
@ -91,20 +97,29 @@
<div class="right-fixed-container">
<div class="right-title heading" translate="file-preview.tabs.annotations.label">
<redaction-filter
(filtersChanged)="filtersChanged($event)"
[chevron]="true"
[filterTemplate]="annotationFilterTemplate"
[filters]="annotationFilters"
></redaction-filter>
</div>
<div>
<redaction-filter
(filtersChanged)="filtersChanged($event)"
[chevron]="true"
[filterTemplate]="annotationFilterTemplate"
[filters]="annotationFilters"
></redaction-filter>
<redaction-circle-button
*ngIf="fullScreenService.fullScreen"
(action)="fullScreenService.toggleFullScreen()"
icon="red:exit-fullscreen"
tooltip="file-preview.exit-fullscreen"
tooltipPosition="before"
></redaction-circle-button>
</div>
</div>
<div class="right-content">
<div
#quickNavigation
(keydown)="preventArrowDefault($event)"
(keyup)="preventArrowDefault($event)"
[class.activePanel]="pagesPanelActive"
(keydown)="preventKeyDefault($event)"
(keyup)="preventKeyDefault($event)"
[class.active-panel]="pagesPanelActive"
class="pages"
tabindex="0"
>
@ -120,13 +135,12 @@
<div
#annotationsElement
(keydown)="preventArrowDefault($event)"
(keyup)="preventArrowDefault($event)"
[class.activePanel]="!pagesPanelActive"
(keydown)="preventKeyDefault($event)"
(keyup)="preventKeyDefault($event)"
[class.active-panel]="!pagesPanelActive"
class="annotations"
tabindex="1"
>
<!-- <div *ngFor="let page of displayedPages">-->
<div attr.anotation-page-header="{{ activeViewerPage }}" class="page-separator">
<span *ngIf="!!activeViewerPage" class="all-caps-label"
><span translate="page"></span> {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }}
@ -168,7 +182,6 @@
></redaction-annotation-actions>
</div>
</div>
<!-- </div>-->
</div>
</div>
</div>

View File

@ -4,11 +4,21 @@
redaction-pdf-viewer {
position: absolute;
width: calc(100vw - #{$right-container-width});
height: calc(100vh - 110px);
top: 110px;
height: calc(100vh - 111px);
transition: height linear 0.2s;
z-index: 2;
}
.red-content-inner.fullscreen {
redaction-pdf-viewer {
height: 100vh;
}
.right-content {
height: calc(100vh - 71px) !important;
}
}
.vertical-line {
width: 1px;
height: 30px;
@ -45,10 +55,19 @@ redaction-pdf-viewer {
width: 14px;
cursor: pointer;
}
> div {
display: flex;
redaction-circle-button {
margin-left: 2px;
}
}
}
.right-content {
height: calc(100vh - 110px - 72px);
height: calc(100vh - 110px - 71px);
transition: height linear 0.2s;
box-sizing: border-box;
display: flex;
@ -58,16 +77,13 @@ redaction-pdf-viewer {
@include no-scroll-bar();
outline: none;
&.activePanel {
&.active-panel {
background-color: #fafafa;
}
}
.pages {
border-right: 1px solid $separator;
display: flex;
flex-direction: column;
align-items: center;
min-width: 61px;
}
@ -131,10 +147,6 @@ redaction-pdf-viewer {
margin-left: 8px;
}
.mr-8 {
margin-right: 8px;
}
.mr-16 {
margin-right: 16px;
}

View File

@ -25,8 +25,9 @@ import { PermissionsService } from '../../../common/service/permissions.service'
import { Subscription, timer } from 'rxjs';
import { processFilters } from '../../../common/filter/utils/filter-utils';
import { UserPreferenceService } from '../../../common/service/user-preference.service';
import { FullScreenService } from '../../../utils/full-screen.service';
const KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
const KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'f', 'F'];
@Component({
selector: 'redaction-file-preview-screen',
@ -60,6 +61,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
public readonly appStateService: AppStateService,
public readonly permissionsService: PermissionsService,
public readonly userPreferenceService: UserPreferenceService,
public readonly fullScreenService: FullScreenService,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _activatedRoute: ActivatedRoute,
private readonly _dialogService: DialogService,
@ -257,6 +259,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
return;
}
if (['f', 'F'].includes($event.key)) {
this.fullScreenService.toggleFullScreen();
return;
}
if ($event.key === 'ArrowLeft') {
this.pagesPanelActive = true;
}
@ -411,7 +418,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
this._changeDetectorRef.markForCheck();
}
preventArrowDefault($event: KeyboardEvent) {
preventKeyDefault($event: KeyboardEvent) {
if (KEY_ARRAY.includes($event.key)) {
$event.preventDefault();
}

View File

@ -12,7 +12,6 @@ import { FileStatusWrapper } from '../model/file-status.wrapper';
import { KeycloakService } from 'keycloak-angular';
import { environment } from '../../../../environments/environment';
import { AnnotationDrawService } from '../service/annotation-draw.service';
import { keypress } from '../../../utils/functions';
export interface ViewerState {
displayMode?: any;

View File

@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class FullScreenService {
public fullScreen = false;
constructor(private readonly _router: Router) {
this._router.events.subscribe((route) => {
if (route instanceof NavigationStart) {
if (route.url.indexOf('file') === -1) {
this.fullScreen = false;
}
}
});
}
public toggleFullScreen() {
this.fullScreen = !this.fullScreen;
}
}

View File

@ -252,7 +252,9 @@
"unassigned": "Unassigned",
"assign-reviewer": "Assign Reviewer",
"assign-me": "Assign to me",
"last-reviewer": "Last Reviewed by:"
"last-reviewer": "Last Reviewed by:",
"fullscreen": "Full Screen (F)",
"exit-fullscreen": "Exit Full Screen (F)"
},
"annotation-actions": {
"message": {

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></svg>

After

Width:  |  Height:  |  Size: 215 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>

After

Width:  |  Height:  |  Size: 216 B

View File

@ -24,6 +24,7 @@ body {
box-sizing: border-box;
background-color: $white;
z-index: 3;
transition: top linear 0.2s;
.filters {
gap: 2px;
@ -54,55 +55,83 @@ body {
}
}
.red-content-inner {
margin-top: 50px;
}
.red-content {
width: 100vw;
height: calc(100vh - 61px);
overflow: auto;
position: absolute;
transition: top linear 0.2s, height linear 0.2s;
top: 61px;
.left-container {
height: calc(100vh - 61px - 50px);
transition: width ease-in-out 0.1s;
.red-content-inner {
position: absolute;
top: 50px;
&.extended {
width: calc(100vw - 60px) !important;
}
}
.left-container {
transition: width linear 0.1s, height linear 0.2s;
.right-fixed-container {
border-left: 1px solid $grey-4;
background: $white;
position: fixed;
right: 0;
z-index: 2;
transition: width ease-in-out 0.1s;
.collapsed-wrapper {
display: none;
}
&.collapsed {
padding-left: 0 !important;
padding-right: 0 !important;
width: 60px !important;
display: flex;
div:not(.collapsed-wrapper) {
display: none;
&.extended {
width: calc(100vw - 60px) !important;
}
}
.collapsed-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 60px;
.right-fixed-container {
border-left: 1px solid $grey-4;
background: $white;
position: fixed;
right: 0;
top: 111px;
z-index: 2;
transition: width linear 0.1s, top linear 0.2s, height linear 0.2s;
div {
display: initial;
.collapsed-wrapper {
display: none;
}
.all-caps-label {
transform: rotate(90deg) translateX(50%);
white-space: nowrap;
margin-top: 10px;
&.collapsed {
padding-left: 0 !important;
padding-right: 0 !important;
width: 60px !important;
display: flex;
div:not(.collapsed-wrapper) {
display: none;
}
.collapsed-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 60px;
div {
display: initial;
}
.all-caps-label {
transform: rotate(90deg) translateX(50%);
white-space: nowrap;
margin-top: 10px;
}
}
}
}
}
&.fullscreen {
height: 100vh;
top: 0;
.page-header {
top: -51px;
}
.red-content-inner {
top: 0;
.right-fixed-container {
top: 0;
height: 100vh;
}
}
}
@ -155,10 +184,17 @@ body {
.red-top-bar {
height: 61px;
width: 100%;
position: absolute;
width: 100vw;
max-height: 61px;
display: flex;
flex-direction: column;
top: 0;
transition: top linear 0.2s;
&.fullscreen {
top: -61px;
}
.top-bar-row {
height: 60px;
@ -199,12 +235,6 @@ body {
}
}
.red-content {
width: 100vw;
height: calc(100vh - 61px);
overflow: auto;
}
.hidden {
display: none !important;
}