make page rotate
This commit is contained in:
parent
8c5276fc1d
commit
a80f54cdbb
@ -7,11 +7,12 @@
|
||||
class="page-wrapper"
|
||||
>
|
||||
<mat-icon [svgIcon]="showDottedIcon ? 'red:excluded-page' : 'red:page'"></mat-icon>
|
||||
<div class="text">
|
||||
{{ number }}
|
||||
</div>
|
||||
|
||||
<div class="text">{{ number }}</div>
|
||||
|
||||
<div *ngIf="activeSelection" class="dot"></div>
|
||||
<div *ngIf="rotation$ | async" [class.not-applied]="notAppliedRotation$ | async" class="rotated">
|
||||
|
||||
<div *ngIf="isRotated$ | async" class="rotated">
|
||||
<mat-icon svgIcon="red:rotation"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -57,22 +57,13 @@
|
||||
top: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: var(--iqser-white);
|
||||
color: var(--iqser-accent);
|
||||
background-color: var(--iqser-primary);
|
||||
color: var(--iqser-white);
|
||||
|
||||
mat-icon {
|
||||
width: 12px;
|
||||
height: 10px;
|
||||
opacity: 50%;
|
||||
}
|
||||
|
||||
&.not-applied {
|
||||
background-color: var(--iqser-primary);
|
||||
color: var(--iqser-white);
|
||||
|
||||
mat-icon {
|
||||
opacity: 100%;
|
||||
}
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,21 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { ViewedPagesService } from '@services/entity-services/viewed-pages.service';
|
||||
import { IViewedPage } from '@red/domain';
|
||||
import { AutoUnsubscribe } from '@iqser/common-ui';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { PageRotationService } from '../../services/page-rotation.service';
|
||||
|
||||
@Component({
|
||||
@ -14,7 +24,7 @@ import { PageRotationService } from '../../services/page-rotation.service';
|
||||
styleUrls: ['./page-indicator.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy, OnChanges {
|
||||
export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy, OnChanges, OnInit {
|
||||
@Input() active = false;
|
||||
@Input() showDottedIcon = false;
|
||||
@Input() number: number;
|
||||
@ -25,9 +35,7 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
|
||||
|
||||
pageReadTimeout: number = null;
|
||||
read = false;
|
||||
|
||||
rotation$ = new BehaviorSubject(true);
|
||||
notAppliedRotation$ = new BehaviorSubject(true);
|
||||
isRotated$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private readonly _viewedPagesService: ViewedPagesService,
|
||||
@ -52,6 +60,10 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
|
||||
return this._stateService.fileId;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.isRotated$ = this._pageRotationService.isRotated(this.number);
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this._setReadState();
|
||||
return this.handlePageRead();
|
||||
|
||||
@ -27,7 +27,7 @@ import { AnnotationActionsService } from '../../services/annotation-actions.serv
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { BASE_HREF } from '../../../../../../tokens';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { AutoUnsubscribe, ConfirmationDialogInput, LoadingService } from '@iqser/common-ui';
|
||||
import { AutoUnsubscribe, ConfirmationDialogInput, LoadingService, log } from '@iqser/common-ui';
|
||||
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
|
||||
import { loadCompareDocumentWrapper } from '../../../../utils/compare-mode.utils';
|
||||
import { PdfViewerUtils } from '../../../../utils/pdf-viewer.utils';
|
||||
@ -393,7 +393,10 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
cursor: pointer;
|
||||
margin: 0 12px;
|
||||
`;
|
||||
paragraph.addEventListener('click', () => this._pageRotationService.applyRotation());
|
||||
paragraph.addEventListener('click', () => {
|
||||
this._pageRotationService.applyRotation();
|
||||
this._showRotationConfirmationButtons();
|
||||
});
|
||||
return paragraph;
|
||||
},
|
||||
};
|
||||
@ -411,7 +414,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
opacity: 0.7;
|
||||
`;
|
||||
paragraph.addEventListener('click', () => {
|
||||
this._pageRotationService.rotations.clear();
|
||||
this._pageRotationService.clearRotations();
|
||||
this._showRotationConfirmationButtons();
|
||||
});
|
||||
return paragraph;
|
||||
@ -452,6 +455,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
img: this._convertPath('/assets/icons/general/rotate-left.svg'),
|
||||
onClick: () => {
|
||||
this._pageRotationService.addRotation(this.utils.currentPage, RotationTypes.LEFT);
|
||||
this.documentViewer.rotateCounterClockwise(this.utils.currentPage);
|
||||
this._showRotationConfirmationButtons();
|
||||
},
|
||||
},
|
||||
@ -462,6 +466,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
img: this._convertPath('/assets/icons/general/rotate-right.svg'),
|
||||
onClick: () => {
|
||||
this._pageRotationService.addRotation(this.utils.currentPage, RotationTypes.RIGHT);
|
||||
this.documentViewer.rotateClockwise(this.utils.currentPage);
|
||||
this._showRotationConfirmationButtons();
|
||||
},
|
||||
},
|
||||
@ -514,17 +519,12 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
}
|
||||
|
||||
private _showRotationConfirmationButtons() {
|
||||
const rotationValues = Array.from(this._pageRotationService.rotations.values());
|
||||
|
||||
const rotationElements = [elements.APPLY_ROTATION, elements.DISCARD_ROTATION];
|
||||
if (rotationValues.length > 0 && rotationValues.find(v => v !== 0)) {
|
||||
if (!this._pageRotationService.isRotated) {
|
||||
this.instance.UI.enableElements(rotationElements);
|
||||
this._pageRotationService.setRotation(true);
|
||||
}
|
||||
|
||||
if (this._pageRotationService.hasRotations()) {
|
||||
this.instance.UI.enableElements(rotationElements);
|
||||
} else {
|
||||
this.instance.UI.disableElements(rotationElements);
|
||||
this._pageRotationService.setRotation(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, firstValueFrom, Observable, pairwise, switchMap } from 'rxjs';
|
||||
import { BehaviorSubject, firstValueFrom, from, Observable, pairwise, switchMap } from 'rxjs';
|
||||
import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { PermissionsService } from '../../../../../services/permissions.service';
|
||||
import { boolFactory, shareLast } from '@iqser/common-ui';
|
||||
import { boolFactory } from '@iqser/common-ui';
|
||||
import { filter, startWith } from 'rxjs/operators';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
||||
import { wipeFilesCache } from '../../../../../../../../../libs/red-cache/src';
|
||||
|
||||
@Injectable()
|
||||
export class FilePreviewStateService {
|
||||
@ -71,11 +72,11 @@ export class FilePreviewStateService {
|
||||
pairwise(),
|
||||
filter(([oldFile, newFile]) => oldFile?.cacheIdentifier !== newFile.cacheIdentifier),
|
||||
switchMap(([, newFile]) => this.#downloadOriginalFile(newFile.cacheIdentifier)),
|
||||
shareLast(),
|
||||
);
|
||||
}
|
||||
|
||||
#downloadOriginalFile(cacheIdentifier: string): Observable<Blob> {
|
||||
return this._fileManagementService.downloadOriginalFile(this.dossierId, this.fileId, 'body', cacheIdentifier);
|
||||
#downloadOriginalFile(cacheIdentifier?: string): Observable<Blob> {
|
||||
const downloadFile = this._fileManagementService.downloadOriginalFile(this.dossierId, this.fileId, 'body', cacheIdentifier);
|
||||
return from(wipeFilesCache()).pipe(switchMap(() => downloadFile));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,12 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { RotationType } from '@red/domain';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { log } from '@iqser/common-ui';
|
||||
|
||||
@Injectable()
|
||||
export class PageRotationService {
|
||||
readonly rotations = new Map<number, number>();
|
||||
private readonly _isRotated$ = new BehaviorSubject<boolean>(false);
|
||||
readonly rotations$ = new BehaviorSubject<Record<number, number>>({});
|
||||
|
||||
constructor(
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
@ -16,30 +17,38 @@ export class PageRotationService {
|
||||
private readonly _screenState: FilePreviewStateService,
|
||||
) {}
|
||||
|
||||
get isRotated(): boolean {
|
||||
return this._isRotated$.value;
|
||||
}
|
||||
|
||||
get canRotate() {
|
||||
return this._screenState.file.then(file => this._permissionsService.isFileAssignee(file));
|
||||
}
|
||||
|
||||
setRotation(value: boolean): void {
|
||||
this._isRotated$.next(value);
|
||||
isRotated(page: number) {
|
||||
return this.rotations$.pipe(
|
||||
map(rotations => !!rotations[page]),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
}
|
||||
|
||||
hasRotations() {
|
||||
return Object.values(this.rotations$.value).filter(v => !!v).length > 0;
|
||||
}
|
||||
|
||||
applyRotation() {
|
||||
const pages = Object.fromEntries(this.rotations);
|
||||
const pages = this.rotations$.value;
|
||||
const { dossierId, fileId } = this._screenState;
|
||||
const request = this._fileManagementService.rotatePage({ pages }, dossierId, fileId);
|
||||
this.clearRotations();
|
||||
|
||||
return firstValueFrom(request);
|
||||
}
|
||||
|
||||
addRotation(pageNumber: number, rotation: RotationType): void {
|
||||
const pageRotation = this.rotations.get(pageNumber);
|
||||
const pageRotation = this.rotations$.value[pageNumber];
|
||||
const rotationValue = pageRotation ? (pageRotation + Number(rotation)) % 360 : rotation;
|
||||
|
||||
this.rotations.set(pageNumber, rotationValue);
|
||||
this.rotations$.next({ ...this.rotations$.value, [pageNumber]: rotationValue });
|
||||
}
|
||||
|
||||
clearRotations() {
|
||||
this.rotations$.next({});
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,10 @@ export async function wipeCaches(logoutDependant: boolean = false) {
|
||||
}
|
||||
}
|
||||
|
||||
export function wipeFilesCache() {
|
||||
return caches.delete('files');
|
||||
}
|
||||
|
||||
export async function wipeCacheEntry(cacheName: string, entry: string) {
|
||||
caches.open(cacheName).then(cache => {
|
||||
cache.delete(entry, { ignoreSearch: false });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user