Skip to content
Snippets Groups Projects
Verified Commit 1d888ce7 authored by Alex ORLUC's avatar Alex ORLUC
Browse files

FEAT #10387 TIME 5 move document refactoring + fix some bugs

parent b910abec
No related branches found
No related tags found
No related merge requests found
Showing
with 252 additions and 117 deletions
......@@ -67,7 +67,7 @@
"ngx-cookie-service": "^2.1.0",
"ngx-scroll-event": "^1.0.8",
"node-sass": "^4.11.0",
"npm-check-updates": "^^3.1.8",
"npm-check-updates": "^3.1.8",
"pdfjs-dist": "^2.0.943",
"protractor": "^5.4.2",
"rxjs": "^6.5.1",
......@@ -77,7 +77,7 @@
"ts-node": "~8.0.3",
"tslint": "~5.15.0",
"typescript-tools": "^0.3.1",
"typescript": "^3.2.4"
"typescript": "3.2.4"
},
"repository": {}
}
......@@ -344,11 +344,11 @@ class DocumentController
foreach ($data['signatures'] as $signature) {
if ($signature['page'] == $i) {
if ($signature['positionX'] == 0 && $signature['positionY'] == 0) {
$signWidth = $size['width'];
$signWidth = $size['width']*2;
$signPosX = 0;
$signPosY = 0;
} else {
$signWidth = ($signature['width'] * $size['width']) / 100;
$signWidth = $size['width'] / 4;
$signPosX = ($signature['positionX'] * $size['width']) / 100;
$signPosY = ($signature['positionY'] * $size['height']) / 100;
}
......
......@@ -43,6 +43,8 @@ import { ConfirmModalComponent } from './modal/confirm-modal.component';
import { WarnModalComponent } from './modal/warn-modal.component';
import { SuccessInfoValidBottomSheetComponent } from './modal/success-info-valid.component';
import { RejectInfoBottomSheetComponent } from './modal/reject-info.component';
import { OverlayComponent } from './overlay/overlay.component';
// SERVICES
import { NotificationService, CustomSnackbarComponent } from './service/notification.service';
......@@ -70,7 +72,8 @@ import { UpdatePasswordComponent } from './login/updatePassword/updatePassword.c
SuccessInfoValidBottomSheetComponent,
RejectInfoBottomSheetComponent,
ProfileComponent,
CustomSnackbarComponent
CustomSnackbarComponent,
OverlayComponent
],
imports: [
FormsModule,
......
......@@ -27,14 +27,14 @@
disabled>
</mat-form-field>
</div>
<div>
<mat-form-field *ngIf="mainDocument.description != null">
<div *ngIf="mainDocument.description != null">
<mat-form-field>
<input matInput [value]="mainDocument.description" title="{{mainDocument.description}}"
placeholder="{{'lang.description' | translate}}" disabled>
</mat-form-field>
</div>
<div>
<mat-form-field *ngIf="mainDocument.deadline != null">
<div *ngIf="mainDocument.deadline != null">
<mat-form-field>
<input matInput [value]="mainDocument.deadline" title="{{mainDocument.deadline}}"
placeholder="{{'lang.processingDeadline' | translate}}" disabled>
</mat-form-field>
......@@ -78,52 +78,37 @@
</section>
</article>
</header>
<app-overlay *ngIf="this.signaturesService.annotationMode" [appDocumentNotePad]="appDocumentNotePad"></app-overlay>
<ng-container *ngIf="!freezeSidenavClose">
<button class="btn-previous" [disabled]="disableState" (tap)="prevPage()"
<button class="btn-previous" [disabled]="snapshot == null" (tap)="prevPage()"
*ngIf="pageNum > 1 && !this.signaturesService.annotationMode"><i class="fas fa-chevron-left fa-3x"></i></button>
<button class="btn-previous" (tap)="prevDoc()"
*ngIf="currentDoc > 0 && pageNum === 1 && !this.signaturesService.annotationMode"><i
class="fas fa-chevron-left fa-3x"></i><i class="fas fa-chevron-left fa-3x"></i></button>
<button class="btn-next" [disabled]="disableState" (tap)="nextPage()"
<button class="btn-next" [disabled]="snapshot == null" (tap)="nextPage()"
*ngIf="pageNum < totalPages && !this.signaturesService.annotationMode"><i
class="fas fa-chevron-right fa-3x"></i></button>
<button class="btn-next" (tap)="nextDoc()"
*ngIf="pageNum == totalPages && docList.length > currentDoc+1 && !this.signaturesService.annotationMode"><i
class="fas fa-chevron-right fa-3x"></i><i class="fas fa-chevron-right fa-3x"></i></button>
</ng-container>
<article class="article" [class.leftPosDesk]="!this.signaturesService.annotationMode && !this.signaturesService.mobileMode" style="position: fixed;" #article [style.left.px]="this.signaturesService.x"
[style.top.px]="this.signaturesService.y" (panstart)="onPanStart($event)" (panmove)="onPan($event)">
<div class="canvas-wrapper" #canvasWrapper>
<simple-pdf-viewer [ngClass]="{
'pdf-page-canvas':!signaturesService.renderingDoc,
'pdf-page-canvas-loading-doc':signaturesService.renderingDoc
}" #pdfViewer [src]="pdfDataArr" removePageBorders="true" (onLoadComplete)="pdfRendered()"
(onError)="pdfError($event)"></simple-pdf-viewer>
<app-document-note-list [ngClass]="{
'pdf-page-canvas':!signaturesService.renderingDoc,
'pdf-page-canvas-loading-doc':signaturesService.renderingDoc
}" *ngIf="currentDoc == 0"></app-document-note-list>
<div [style.width.px]="signaturesService.workingAreaWidth*signaturesService.scale" (tap)="addAnnotation($event)"
[style.height.px]="signaturesService.workingAreaHeight*signaturesService.scale"
style="position:absolute;left:0;top:0;"></div>
<app-document-sign-list [ngClass]="{
'pdf-page-canvas':!signaturesService.renderingDoc,
'pdf-page-canvas-loading-doc':signaturesService.renderingDoc
}" [canvas]="canvasWrapper" *ngIf="currentDoc == 0"></app-document-sign-list>
<app-document-note-pad (triggerEvent)="zoomMinus()" #appDocumentNotePad *ngIf="currentDoc == 0">
</app-document-note-pad>
<div #canvasWrapper [style.width]="widthDoc" style="height:100%;overflow:hidden;background:grey;">
<div *ngIf="!resetDragPos" #dragElem class="example-box" cdkDragLockAxis="y" cdkDrag [cdkDragDisabled]="this.signaturesService.annotationMode" style="width: 100%;transform: translate3d(0px, 80px, 0px)" (cdkDragEnded)="testDrag($event)">
<app-document-note-list (tap)="addAnnotation($event)" *ngIf="currentDoc == 0 && snapshot != null"></app-document-note-list>
<app-document-sign-list [canvas]="canvasWrapper" *ngIf="currentDoc == 0 && snapshot != null"></app-document-sign-list>
<img (tap)="addAnnotation($event)" *ngIf="snapshot != null" id="test" [src]="snapshot" style="width:100%"/>
<app-document-note-pad (triggerEvent)="zoomForView()" #appDocumentNotePad *ngIf="currentDoc == 0"></app-document-note-pad>
</div>
<div class="page-under">
<div class="page-under-fold"></div>
</div>
<section class="page-info" *ngIf="!this.signaturesService.annotationMode && docList[currentDoc]">
<div class="page-info-doc">{{'lang.doc' | translate}} {{currentDoc+1}}/{{docList.length}} : {{docList[currentDoc].title}}</div>
<div class="page-info-page">{{'lang.page' | translate}} {{ pageNum }} / {{ totalPages }}</div>
</section>
</article>
<simple-pdf-viewer #pdfViewer [src]="pdfDataArr" removePageBorders="true" (onLoadComplete)="pdfRendered()"
(onError)="pdfError($event)" style="display:none;"></simple-pdf-viewer>
<section class="page-info" *ngIf="!this.signaturesService.annotationMode && docList[currentDoc]">
<div class="page-info-doc">{{'lang.doc' | translate}} {{currentDoc+1}}/{{docList.length}} : {{docList[currentDoc].title}}</div>
<div class="page-info-page">{{'lang.page' | translate}} {{ pageNum }} / {{ totalPages }}</div>
</section>
<footer class="footer" *ngIf="!this.signaturesService.annotationMode && !freezeSidenavClose" [@slideUp]>
<ng-container *ngFor="let action of actionsList;">
<button *ngIf="action.allowed" [style.color]="action.color" [style.borderColor]="action.color" class="btn"
......@@ -132,7 +117,7 @@
</footer>
<app-drawer></app-drawer>
</mat-sidenav-content>
<mat-sidenav #snavRight mode="over" fixedInViewport="true" [style.width.%]="80" position='end' disableClose='true'>
<mat-sidenav #snavRight mode="over" fixedInViewport="true" [style.width.%]="99" position='end' disableClose='true'>
<app-my-profile [snavLeftComponent]="this.snav" [snavRightComponent]="this.snavRight"></app-my-profile>
</mat-sidenav>
</mat-sidenav-container>
\ No newline at end of file
......@@ -110,7 +110,7 @@ canvas {
}
&-expand {
width: 80%;
width: 70%;
position: absolute;
left: 50%;
transform: translateX(-50%);
......@@ -164,7 +164,8 @@ canvas {
position: fixed;
bottom: 100px;
height: 30px;
width: 70%;
width: auto;
max-width: 70%;
color: #9B9B9B;
font-size: 12px;
font-weight: 300;
......@@ -188,7 +189,6 @@ canvas {
}
&-page {
max-width: 20%;
text-align: center;
border-radius: 0 14px 14px 0;
padding: 0 20px;
......@@ -196,6 +196,7 @@ canvas {
border: 1px solid #ECF0F1;
margin-left: -15px;
height: 28px;
white-space: pre;
}
}
}
......
......@@ -15,8 +15,9 @@ import { ConfirmModalComponent } from '../modal/confirm-modal.component';
import { SuccessInfoValidBottomSheetComponent } from '../modal/success-info-valid.component';
import { SimplePdfViewerComponent } from 'simple-pdf-viewer';
import { TranslateService } from '@ngx-translate/core';
import { CdkDragEnd, DragRef, CdkDrag } from '@angular/cdk/drag-drop';
declare var PDFJS : any;
declare var PDFJS: any;
@Component({
selector: 'app-document',
......@@ -69,28 +70,29 @@ declare var PDFJS : any;
})
export class DocumentComponent implements OnInit {
enterApp : boolean = true;
pageNum : number = 1;
signaturesContent : any = [];
totalPages : number;
draggable : boolean;
loadingDoc : boolean = true;
currentDoc : number = 0;
docList : any = [];
actionsList : any = [];
pdfDataArr : any;
freezeSidenavClose : boolean = false;
disableState : boolean = true;
startX : number = 0;
startY : number = 0;
enterApp: boolean = true;
pageNum: number = 1;
signaturesContent: any = [];
totalPages: number;
draggable: boolean;
loadingDoc: boolean = true;
currentDoc: number = 0;
docList: any = [];
actionsList: any = [];
pdfDataArr: any;
freezeSidenavClose: boolean = false;
startX: number = 0;
startY: number = 0;
outOfBounds = false;
snapshot: any;
widthDoc: string = '100%';
resetDragPos: boolean = false;
@Input() mainDocument: any = {};
@ViewChild('snav') snav: MatSidenav;
@ViewChild('snavRight') snavRight: MatSidenav;
@ViewChild('canvas') canvas: ElementRef;
@ViewChild('canvasWrapper') canvasWrapper: ElementRef;
@ViewChild('dragElem') dragElem: any;
@ViewChild('appDocumentNotePad') appDocumentNotePad: DocumentNotePadComponent;
@ViewChild(SimplePdfViewerComponent) private pdfViewer: SimplePdfViewerComponent;
......@@ -117,6 +119,7 @@ export class DocumentComponent implements OnInit {
}, 500);
this.route.params.subscribe(params => {
if (typeof params['id'] !== 'undefined') {
this.snapshot = null;
this.signaturesService.renderingDoc = true;
this.http.get('../rest/documents/' + params['id'])
.subscribe((data: any) => {
......@@ -198,35 +201,87 @@ export class DocumentComponent implements OnInit {
pdfRendered() {
this.pdfViewer.setZoom(this.signaturesService.scale);
this.signaturesService.workingAreaHeight = $('.page').height();
this.signaturesService.workingAreaWidth = $('.page').width();
this.totalPages = this.pdfViewer.getNumberOfPages();
this.signaturesService.totalPage = this.totalPages;
this.disableState = false;
this.getPdfImage();
this.signaturesService.renderingDoc = false;
}
getPdfImage() {
this.resetDragPosition();
this.snapshot = null;
this.pdfViewer.getPageSnapshot(2).then(snapshot => {
if (snapshot) {
this.snapshot = URL.createObjectURL(snapshot);
this.snapshot = this.sanitizer.bypassSecurityTrustResourceUrl(this.snapshot);
setTimeout(() => {
this.signaturesService.workingAreaHeight = $('#test').height();
this.signaturesService.workingAreaWidth = $('#test').width();
}, 1000);
}
});
}
testDrag(event: any) {
const element = event.source.getRootElement();
const boundingClientRect = element.getBoundingClientRect();
const parentPosition = this.getPosition(element);
this.signaturesService.y = (boundingClientRect.y - parentPosition.top);
this.signaturesService.x = (boundingClientRect.x - parentPosition.left);
}
getPosition(el: any) {
let x = 0;
let y = 0;
while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
x += el.offsetLeft - el.scrollLeft;
y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: y, left: x };
}
pdfError(e: any) {
console.log(e);
}
zoomPlus() {
this.pdfViewer.setZoom(2);
this.signaturesService.scale = this.pdfViewer.getZoom();
zoomForNotes() {
this.widthDoc = '200%';
this.signaturesService.scale = 2;
$('.example-box').css({ 'transform': 'translate3d(' + this.signaturesService.x * this.signaturesService.scale + 'px, ' + this.signaturesService.y * this.signaturesService.scale + 'px, 0px)' });
this.signaturesService.workingAreaHeight *= this.signaturesService.scale;
this.signaturesService.workingAreaWidth *= this.signaturesService.scale;
}
zoomMinus() {
this.pdfViewer.setZoom(1);
this.signaturesService.scale = this.pdfViewer.getZoom();
zoomForView() {
this.resetDragPosition();
this.widthDoc = '100%';
this.signaturesService.workingAreaHeight /= this.signaturesService.scale;
this.signaturesService.workingAreaWidth /= this.signaturesService.scale;
this.signaturesService.scale = 1;
}
resetDragPosition() {
this.signaturesService.y = 0;
this.signaturesService.x = 0;
this.resetDragPos = true;
setTimeout(() => {
this.resetDragPos = false;
}, 200);
}
prevPage() {
this.disableState = true;
this.pageNum--;
this.pdfViewer.prevPage();
this.getPdfImage();
if (this.pageNum === 0) {
this.pageNum = 1;
} else {
......@@ -235,30 +290,20 @@ export class DocumentComponent implements OnInit {
if (this.currentDoc === 0) {
this.signaturesService.currentPage = this.pageNum;
}
// fix issue render pdf load is quick click
setTimeout(() => {
this.disableState = false;
}, 500);
}
nextPage() {
this.disableState = true;
if (this.pageNum >= this.totalPages) {
this.pageNum = this.totalPages;
} else {
this.pageNum++;
}
this.pdfViewer.nextPage();
this.getPdfImage();
// only for main document
if (this.currentDoc === 0) {
this.signaturesService.currentPage = this.pageNum;
}
// fix issue render pdf load is quick click
setTimeout(() => {
this.disableState = false;
}, 500);
}
nextDoc() {
......@@ -282,18 +327,18 @@ export class DocumentComponent implements OnInit {
}
addAnnotation(e: any) {
console.log(e.srcEvent.layerY);
if (!this.signaturesService.annotationMode && this.currentDoc === 0) {
this.signaturesService.x = -e.srcEvent.layerX;
if (e.srcEvent.layerY > 850) {
this.signaturesService.y = -(e.srcEvent.layerY + 200);
} else {
this.signaturesService.y = -e.srcEvent.layerY;
}
const posX = e.srcEvent.layerX - this.signaturesService.x;
const posY = e.srcEvent.layerY - this.signaturesService.y;
this.signaturesService.x = -posX;
this.signaturesService.y = -posY;
this.zoomForNotes();
$('.example-box').css({ 'transform': 'translate3d(' + -(posX) + 'px, ' + -(posY) + 'px, 0px)' });
this.signaturesService.annotationMode = true;
this.zoomPlus();
this.appDocumentNotePad.initPad();
}
}
......@@ -314,7 +359,6 @@ export class DocumentComponent implements OnInit {
localStorage.removeItem(this.mainDocument.id.toString());
} else if (result === 'annotation') {
this.signaturesService.annotationMode = true;
this.zoomPlus();
this.appDocumentNotePad.initPad();
}
});
......
......@@ -3,6 +3,6 @@
'pdf-page-canvas':!signaturesService.renderingDoc,
'pdf-page-canvas-loading-doc':signaturesService.renderingDoc
}">
<img [style.width.px]="signaturesService.workingAreaWidth*signaturesService.scale" [src]="sanitization.bypassSecurityTrustUrl(note.fullPath)">
<img [style.width.px]="signaturesService.workingAreaWidth*2" [src]="sanitization.bypassSecurityTrustUrl(note.fullPath)">
</div>
</ng-container>
\ No newline at end of file
<div *ngIf="signaturesService.annotationMode">
<span style="z-index:1;position: fixed;left:0;bottom: 10px;top: 10px;font-size: 25px;height:50px;">
<button class="btn blue" (tap)="cancelAnnotation(i);"><i class="fas fa-arrow-left fa-2x"></i>{{'lang.exitAnnotation' | translate}}</button>
</span>
<span style="z-index:1;position: fixed;bottom: 10px;left: 50%;transform: translateX(-50%);font-size: 25px;">
<button class="btn green" (tap)="validateAnnotation();"><i class="fas fa-check-circle fa-2x"></i>{{'lang.validateAnnotation' | translate}}</button>
</span>
</div>
<div *ngIf="signaturesService.annotationMode" [style.width.px]="this.signaturesService.workingAreaWidth*this.signaturesService.scale" [style.height.px]="this.signaturesService.workingAreaHeight*this.signaturesService.scale"
style="top:0;position: absolute;border: dashed 1px grey;overflow: hidden;" [ngClass]="{
'pdf-page-canvas':!signaturesService.renderingDoc,
'pdf-page-canvas-loading-doc':signaturesService.renderingDoc
}">
<!-- <div class="tool-content tool-content-left">
<input type="range" name="dot" min="1" max="10" step="1" value="1" (input)="onDotChange($event.target.value)" class="range">
<i class="fas fa-pen-nib"></i>
</div> -->
<div class="tool-content tool-content-right">
<ng-container *ngFor="let color of penColors" let idx="index">
<input type="radio" name="colors" [checked]="idx === 0" [value]="color.id" class="radio"
[ngStyle]="{'border-color': color.id, 'background-color': color.id}">
</ng-container>
<hr>
<i class="fa fa-undo fa-2x undo" (click)="undo()"></i>
</div>
<canvas id="myCanvas" #canvas></canvas>
</div>
\ No newline at end of file
<ng-container *ngFor="let signature of this.signaturesService.signaturesContent[this.signaturesService.currentPage];let i = index;">
<div [position]="{'x': signature.positionX*signaturesService.scale, 'y': signature.positionY*signaturesService.scale}" id="signaturesContent" style="top:0;left:0;position: absolute;border: dashed 1px grey;background: rgba(255, 255, 255, 0.6) none repeat scroll 0% 0%;"
<div (tap)="$event.preventDefault();" [position]="{'x': signature.positionX*signaturesService.scale, 'y': signature.positionY*signaturesService.scale}" id="signaturesContent" style="top:0;left:0;position: absolute;border: dashed 1px grey;background: rgba(255, 255, 255, 0.6) none repeat scroll 0% 0%;"
ngDraggable preventDefaultEvent="true" [bounds]="page" inBounds="true" (started)="onDragBegin($event)" (endOffset)="moveSign($event,i)" [ngClass]="{
'pdf-page-canvas':!signaturesService.renderingDoc,
'pdf-page-canvas-loading-doc':signaturesService.renderingDoc
......@@ -19,6 +19,6 @@
</button>
</mat-menu>
<img [src]="sanitization.bypassSecurityTrustUrl('data:image/png;base64,' + signature.encodedSignature)"
[style.width.px]="this.signaturesService.signWidth*signaturesService.scale">
[style.width.px]="this.signaturesService.workingAreaWidth/4">
</div>
</ng-container>
\ No newline at end of file
<div>
<span style="z-index:1;position: fixed;left:0;bottom: 10px;top: 10px;font-size: 25px;height:50px;">
<button class="btn blue" (tap)="this.appDocumentNotePad.cancelAnnotation(i);"><i
class="fas fa-arrow-left fa-2x"></i>{{'lang.exitAnnotation' | translate}}</button>
</span>
<span style="z-index:1;position: fixed;bottom: 10px;left: 50%;transform: translateX(-50%);font-size: 25px;">
<button class="btn green" (tap)="this.appDocumentNotePad.validateAnnotation();"><i
class="fas fa-check-circle fa-2x"></i>{{'lang.validateAnnotation' | translate}}</button>
</span>
</div>
<div class="tool-content tool-content-right">
<ng-container *ngFor="let color of this.appDocumentNotePad.penColors" let idx="index">
<input type="radio" name="colors" [checked]="idx === 0" [value]="color.id" class="radio"
[ngStyle]="{'border-color': color.id, 'background-color': color.id}">
</ng-container>
<hr>
<i class="fa fa-undo fa-2x undo" (click)="this.appDocumentNotePad.undo()"></i>
</div>
\ No newline at end of file
.tool-content {
z-index: 1;
display: flex;
position: fixed;
background: #8080804d;
border-radius: 20px;
top: 170px;
transform: translateY(-50%) rotate(-90deg);
padding: 10px;
&-left {
left: -40px;
}
&-right {
right: -40px;
}
}
.undo {
cursor: pointer;
transform: rotate(90deg);
transition: all 0.2s;
&:active {
transform: rotate(90deg) scale(1.5);
}
}
.radio {
appearance: none;
position: relative;
margin: 5px;
width: 30px;
height: 30px;
border-radius: 30px;
border-width: none;
border-style: solid;
outline: none;
cursor: pointer;
transition: all 0.2s;
&:checked, &:hover {
transform: scale(1.5);
}
}
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DocumentComponent } from './overlay.component';
describe('DocumentComponent', () => {
let component: DocumentComponent;
let fixture: ComponentFixture<DocumentComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DocumentComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DocumentComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Input } from '@angular/core';
import { DocumentNotePadComponent } from '../documentNotePad/document-note-pad.component';
@Component({
selector: 'app-overlay',
templateUrl: 'overlay.component.html',
styleUrls: ['overlay.component.scss'],
})
export class OverlayComponent implements OnInit {
// tslint:disable-next-line:no-input-rename
@Input('appDocumentNotePad') appDocumentNotePad: DocumentNotePadComponent;
constructor() { }
ngOnInit(): void { }
}
......@@ -31,7 +31,7 @@ export class SignaturesContentService {
mode = 'SIGN';
scale = 1;
x = 0;
y = 85;
y = 0;
constructor() {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
......
......@@ -173,3 +173,21 @@ button.disabled {
background: white;
border: solid 1px $primary;
}
// bug expand opened if animation, solved it temporarily until a fix arrives
mat-accordion mat-expansion-panel {
mat-expansion-panel-header {
height: 40px; // height may be different for you
}
.mat-expansion-panel-content {
height: 0;
}
&.mat-expanded {
mat-expansion-panel-header {
height: 64px; // height may be different for you
}
.mat-expansion-panel-content {
height: auto;
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment