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