diff --git a/src/frontend/app/document/document.component.ts b/src/frontend/app/document/document.component.ts index 6f46e74558574d3d52a6ae18339241b171e511db..4a96c8cb594f7465b3a1b469b68c1bdac45e732c 100755 --- a/src/frontend/app/document/document.component.ts +++ b/src/frontend/app/document/document.component.ts @@ -244,8 +244,7 @@ export class DocumentComponent implements OnInit { this.dragging = false; if (data !== undefined) { if (data === 'success') { - this.scrollToElem(); - // this.addSignature(); + // this.scrollToElem(); } else if (data.redirectPage !== undefined) { this.goTo(data.redirectPage); } @@ -326,6 +325,7 @@ export class DocumentComponent implements OnInit { item.userSignatureModes.unshift('visa'); return { ...item, + 'datePositions': [], 'role': item.mode === 'visa' ? 'visa' : item.signatureMode, 'modes': item.userSignatureModes }; @@ -443,6 +443,7 @@ export class DocumentComponent implements OnInit { this.docList = []; this.signaturesService.signaturesContent = []; this.signaturesService.notesContent = []; + this.signaturesService.datesContent = []; this.signaturesService.sideNavRigtDatas.mode = 'mainDocumentDetail'; const notesContent = this.localStorage.get(this.mainDocument.id.toString()); @@ -451,6 +452,7 @@ export class DocumentComponent implements OnInit { const storageContent = JSON.parse(notesContent); this.signaturesService.notesContent = storageContent['note']; this.signaturesService.signaturesContent = storageContent['sign']; + this.signaturesService.datesContent = storageContent['date']; } this.signaturesService.currentAction = 0; @@ -700,6 +702,20 @@ export class DocumentComponent implements OnInit { const signatures: any[] = []; if (this.signaturesService.currentAction > 0) { for (let index = 1; index <= this.signaturesService.totalPage; index++) { + if (this.signaturesService.datesContent[index]) { + this.signaturesService.datesContent[index].forEach((date: any) => { + signatures.push( + { + 'encodedImage': date.content.replace('data:image/svg+xml;base64,', ''), + 'width': date.width, + 'positionX': date.positionX, + 'positionY': date.positionY, + 'type': 'SVG', + 'page': index, + } + ); + }); + } if (this.signaturesService.signaturesContent[index]) { this.signaturesService.signaturesContent[index].forEach((signature: any) => { signatures.push( @@ -729,7 +745,6 @@ export class DocumentComponent implements OnInit { }); } } - this.http.put('../rest/documents/' + this.signaturesService.mainDocumentId + '/actions/' + this.signaturesService.currentAction, { 'signatures': signatures, 'note': data.note }) .pipe( tap(() => { @@ -778,6 +793,7 @@ export class DocumentComponent implements OnInit { handler: () => { this.signaturesService.signaturesContent = []; this.signaturesService.notesContent = []; + this.signaturesService.datesContent = []; this.localStorage.remove(this.mainDocument.id.toString()); this.notificationService.success('lang.noteAndSignatureDeleted'); } @@ -827,6 +843,12 @@ export class DocumentComponent implements OnInit { checkEmptiness() { let state = true; for (let pageNum = 1; pageNum <= this.signaturesService.totalPage; pageNum++) { + if (this.signaturesService.datesContent[pageNum]) { + if (this.signaturesService.datesContent[pageNum].length > 0) { + state = false; + break; + } + } if (this.signaturesService.notesContent[pageNum]) { if (this.signaturesService.notesContent[pageNum].length > 0) { state = false; diff --git a/src/frontend/app/documentSignList/document-sign-list.component.html b/src/frontend/app/documentSignList/document-sign-list.component.html index 7aafcabbb46ae40fd1efc12fccccfcd07443fac7..9f045e1eb09ea7aed32dfa51f72806ce96f3c53d 100644 --- a/src/frontend/app/documentSignList/document-sign-list.component.html +++ b/src/frontend/app/documentSignList/document-sign-list.component.html @@ -1,15 +1,42 @@ -<div *ngFor="let signature of this.signaturesService.signaturesContent[this.signaturesService.currentPage];let i = index;" -[position]="{x: (signature.positionX*this.signaturesService.workingAreaWidth)/100, y:(signature.positionY*this.signaturesService.workingAreaHeight)/100}" [style.width.%]="signature.width" - [ngDraggable]="!signaturesService.resizing" ngResizable [rzAspectRatio]="true" (rzResizing)="onResizing($event, i)" (rzStart)="signaturesService.resizing=true" - (movingOffset)="signaturesService.dragging=true" - (endOffset)="moveSign($event, i);" (rzStop)="onResizeStop($event, i);signaturesService.resizing=false;" - [preventDefaultEvent]="false" [bounds]="bounds" - [inBounds]="true" style="position:absolute;border: dashed 1px grey;background: rgba(255, 255, 255, 0.6) none repeat scroll 0% 0%;" [style.height]="fix" #test> +<div + *ngFor="let signature of this.signaturesService.signaturesContent[this.signaturesService.currentPage];let i = index;" + [position]="{x: (signature.positionX*this.signaturesService.workingAreaWidth)/100, y:(signature.positionY*this.signaturesService.workingAreaHeight)/100}" + [style.width.%]="signature.width" [ngDraggable]="!signaturesService.resizing" ngResizable [rzAspectRatio]="true" + (rzResizing)="onResizing($event, i)" (rzStart)="signaturesService.resizing=true" + (movingOffset)="signaturesService.dragging=true" (endOffset)="moveSign($event, i);" + (rzStop)="onResizeStop($event, i);signaturesService.resizing=false;" [preventDefaultEvent]="false" [bounds]="bounds" + [inBounds]="true" + style="position:absolute;border: dashed 1px grey;background: rgba(255, 255, 255, 0.6) none repeat scroll 0% 0%;" + [style.height]="fix" #test> <ion-item style="position: absolute;--background: none;right: 0;--border-width: 0;"> - <ion-select (click)="$event.stopPropagation();" selectedText=" " value="" interface="popover" (ionChange)="select($event,i)"> - <ion-select-option class="action-item"value="deleteSignature">{{'lang.delete' | translate}}</ion-select-option> - <ion-select-option class="action-item" [disabled]="signature.inAllPage" value="cloneSign">{{'lang.replicate' | translate}}</ion-select-option> + <ion-select (click)="$event.stopPropagation();" selectedText=" " value="" interface="popover" + (ionChange)="select($event,i)"> + <ion-select-option class="action-item" value="deleteSignature">{{'lang.delete' | translate}}</ion-select-option> + <ion-select-option class="action-item" [disabled]="signature.inAllPage" value="cloneSign"> + {{'lang.replicate' | translate}}</ion-select-option> </ion-select> </ion-item> - <img class="img-content" [src]="sanitization.bypassSecurityTrustUrl('data:image/png;base64,' + signature.encodedSignature)" [style.width.%]="100"> + <img class="img-content" + [src]="sanitization.bypassSecurityTrustUrl('data:image/png;base64,' + signature.encodedSignature)" + [style.width.%]="100"> +</div> + +<div *ngFor="let date of this.signaturesService.datesContent[this.signaturesService.currentPage];let i = index;" + class="test" + [position]="{x: (date.positionX*this.signaturesService.workingAreaWidth)/100, y:(date.positionY*this.signaturesService.workingAreaHeight)/100}" + [style.width.%]="date.width" + [style.height.%]="date.height" + [ngDraggable]="!signaturesService.resizing" ngResizable [rzAspectRatio]="true" + (rzStart)="signaturesService.resizing=true" + (movingOffset)="signaturesService.dragging=true" (endOffset)="moveDate($event, i);" + (rzStop)="onResizeDateStop($event, i);signaturesService.resizing=false;" [preventDefaultEvent]="false" [bounds]="bounds" + [inBounds]="true" + (click)="$event.stopPropagation();"> + <svg [id]="'testSVG_'+ i" viewBox="0 0 130 30" preserveAspectRatio="xMinYMin meet"> + <text y="10" font-size="16" dy=".3em" style="fill: #0000ff;">25 décembre 2020</text></svg> +</div> + +<div class="test" ngDraggable ngResizable [rzAspectRatio]="true" style="position: absolute" + (movingOffset)="signaturesService.dragging=true"> + </div> \ No newline at end of file diff --git a/src/frontend/app/documentSignList/document-sign-list.component.scss b/src/frontend/app/documentSignList/document-sign-list.component.scss index 00204044aaecdb4d9e9381059e770080debcbe9b..b1fe6cd27947a295ff06a8cea7f4075340ab6b44 100644 --- a/src/frontend/app/documentSignList/document-sign-list.component.scss +++ b/src/frontend/app/documentSignList/document-sign-list.component.scss @@ -1,4 +1,28 @@ ::ng-deep .action-item ion-radio { - --color:transparent; + --color: transparent; --color-checked: transparent; +} + +.test { + position: absolute; + border: dashed 1px grey; + background: rgba(255, 255, 255, 0.6) none repeat scroll 0% 0%; + position: absolute; + // margin-right: 10px; + background: none; + font: sans-serif; + overflow: hidden; + // margin-bottom: 26px; +} + +svg { + width: 100%; + height: 100%; + pointer-events: none; + /* so that you can resize the element */ +} + +text { + pointer-events: auto; + /* Cancel the svg’s pointer-events */ } \ No newline at end of file diff --git a/src/frontend/app/documentSignList/document-sign-list.component.ts b/src/frontend/app/documentSignList/document-sign-list.component.ts index e18aaac90162f141c75fc60f3b79e24fe8e48024..1ca1e86efc30c33cbf4f6d0aa6e11b9ae2b5a1d1 100644 --- a/src/frontend/app/documentSignList/document-sign-list.component.ts +++ b/src/frontend/app/documentSignList/document-sign-list.component.ts @@ -47,7 +47,17 @@ export class DocumentSignListComponent implements OnInit { this.signaturesService.signaturesContent[this.signaturesService.currentPage][i].positionX = percentx; this.signaturesService.signaturesContent[this.signaturesService.currentPage][i].positionY = percenty; - this.localStorage.save(this.signaturesService.mainDocumentId.toString(), JSON.stringify({ 'sign': this.signaturesService.signaturesContent, 'note': this.signaturesService.notesContent })); + this.localStorage.save(this.signaturesService.mainDocumentId.toString(), JSON.stringify({ 'date': this.signaturesService.datesContent, 'sign': this.signaturesService.signaturesContent, 'note': this.signaturesService.notesContent })); + this.signaturesService.dragging = false; + } + + moveDate(event: any, i: number) { + const percentx = (event.x * 100) / this.signaturesService.workingAreaWidth; + const percenty = (event.y * 100) / this.signaturesService.workingAreaHeight; + + this.signaturesService.datesContent[this.signaturesService.currentPage][i].positionX = percentx; + this.signaturesService.datesContent[this.signaturesService.currentPage][i].positionY = percenty; + this.localStorage.save(this.signaturesService.mainDocumentId.toString(), JSON.stringify({ 'date': this.signaturesService.datesContent, 'sign': this.signaturesService.signaturesContent, 'note': this.signaturesService.notesContent })); this.signaturesService.dragging = false; } @@ -55,6 +65,11 @@ export class DocumentSignListComponent implements OnInit { this.test.nativeElement.style.height = 'auto'; } + onResizeDateStop(event: any, index: number) { + this.signaturesService.datesContent[this.signaturesService.currentPage][index].height = (event.size.height * 100) / this.signaturesService.workingAreaHeight; + this.signaturesService.datesContent[this.signaturesService.currentPage][index].width = (event.size.width * 100) / this.signaturesService.workingAreaWidth; + } + onResizeStop(event: any, index: number) { this.test.nativeElement.style.height = 'auto'; this.signaturesService.signaturesContent[this.signaturesService.currentPage][index].width = (event.size.width * 100) / this.signaturesService.workingAreaWidth; diff --git a/src/frontend/app/service/signatures.service.ts b/src/frontend/app/service/signatures.service.ts index 60bfbd7749eda9fba813a2c91650829dd1e1d2ef..37f581d9832f87cda14f62f687f90e9f9d036f6c 100755 --- a/src/frontend/app/service/signatures.service.ts +++ b/src/frontend/app/service/signatures.service.ts @@ -6,6 +6,7 @@ export class SignaturesContentService { mainDocumentId = 0; signaturesContent: any[] = []; + datesContent: any[] = []; notesContent: any[] = []; signaturesList: any[] = []; signaturesListSubstituted: any[] = []; @@ -69,6 +70,7 @@ export class SignaturesContentService { reset() { this.mainDocumentId = 0; this.signaturesContent = []; + this.datesContent = []; this.notesContent = []; this.signaturesList = []; this.signaturesListSubstituted = []; diff --git a/src/frontend/app/signatures/signatures.component.html b/src/frontend/app/signatures/signatures.component.html index ef1a5db149bc614bcfc9ae27e0267ee17aa0c6d7..7d7d944e03966f45fffbae1b52ba70bc023b91c6 100755 --- a/src/frontend/app/signatures/signatures.component.html +++ b/src/frontend/app/signatures/signatures.component.html @@ -37,6 +37,9 @@ <ion-icon name="chevron-up-outline"></ion-icon> </ion-fab-button> <ion-fab-list side="top"> + <ion-fab-button color="light" [title]="'lang.addNewDate' | translate" (click)="addNewDate()"> + <ion-icon name="calendar-outline"></ion-icon> + </ion-fab-button> <ion-fab-button color="light" [title]="'lang.importNewSignature' | translate" (click)="uploadFile.click()"> <ion-icon name="download-outline"></ion-icon> </ion-fab-button> diff --git a/src/frontend/app/signatures/signatures.component.ts b/src/frontend/app/signatures/signatures.component.ts index 03c26d9914794d24b9509236735d1bfda07023ab..701b40d2f17bb69a6a3317f950b20455a1ae3c7b 100755 --- a/src/frontend/app/signatures/signatures.component.ts +++ b/src/frontend/app/signatures/signatures.component.ts @@ -25,6 +25,7 @@ export class SignaturesComponent implements OnInit { loading: boolean = true; scrolling: boolean = false; signPosMode: boolean = false; + datePosMode: boolean = false; title: string = 'lang.signatures'; slideOpts = { initialSlide: 0, @@ -161,12 +162,93 @@ export class SignaturesComponent implements OnInit { } } + addNewDate() { + const dateBlock: any = { + width: (130 * 100) / this.signaturesService.workingAreaWidth, + height: (30 * 100) / this.signaturesService.workingAreaHeight, + positionX: 0, + positionY: 0 + }; + const datePosCurrentPage = this.currentWorflow.datePositions.filter((item: any) => item.page === this.signaturesService.currentPage); + const datePosOtherPage = this.currentWorflow.datePositions.filter((item: any) => item.page !== this.signaturesService.currentPage); + + if (!this.datePosMode || (datePosCurrentPage.length === 0 && datePosOtherPage.length === 0)) { + dateBlock.positionX = 130; + dateBlock.positionY = 30; + this.storeDate(dateBlock, this.signaturesService.currentPage); + this.notificationService.success('lang.dateInDocAdded'); + setTimeout(() => { + const svg = document.getElementById('testSVG_' + (this.signaturesService.datesContent[this.signaturesService.currentPage].length - 1)); + console.log(svg); + }, 200); + this.modalController.dismiss('success'); + } else { + if (datePosCurrentPage.length > 0) { + dateBlock.positionX = datePosCurrentPage[0].positionX; + dateBlock.positionY = datePosCurrentPage[0].positionY; + this.storeDate(dateBlock, this.signaturesService.currentPage); + } + + datePosOtherPage.forEach((postion: any) => { + dateBlock.positionX = postion.positionX; + dateBlock.positionY = postion.positionY; + this.storeDate(dateBlock, postion.page); + }); + + if (this.currentWorflow.signaturePositions.length === 1) { + this.notificationService.success('lang.dateInDocAddedAlt'); + } else { + this.translate.get('lang.dateInDocAdded', { 0: this.currentWorflow.signaturePositions.map((item: any) => item.page) }).subscribe((res: string) => { + this.notificationService.success(res); + }); + } + + if (datePosCurrentPage.length === 0 && datePosOtherPage.length > 0) { + this.modalController.dismiss({ redirectPage: datePosOtherPage[0].page }); + } else { + this.modalController.dismiss('success'); + } + } + } + + getDateContent() { + const svg = document.getElementById('testSVG_' + (this.signaturesService.datesContent[this.signaturesService.currentPage].length - 1)); + const data = new XMLSerializer().serializeToString(svg); + const blob = new Blob([data], { type: 'image/svg+xml' }); + + const reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onloadend = function () { + var base64data = reader.result; + console.log(base64data); + } + } + storeSignature(signature: any, page: number) { if (!this.signaturesService.signaturesContent[page]) { this.signaturesService.signaturesContent[page] = []; } this.signaturesService.signaturesContent[page].push(JSON.parse(JSON.stringify(signature))); - this.localStorage.save(this.signaturesService.mainDocumentId.toString(), JSON.stringify({ 'sign': this.signaturesService.signaturesContent, 'note': this.signaturesService.notesContent })); + this.localStorage.save(this.signaturesService.mainDocumentId.toString(), JSON.stringify({ 'date': this.signaturesService.datesContent, 'sign': this.signaturesService.signaturesContent, 'note': this.signaturesService.notesContent })); + } + + storeDate(date: any, page: number) { + if (!this.signaturesService.datesContent[page]) { + this.signaturesService.datesContent[page] = []; + } + this.signaturesService.datesContent[page].push(JSON.parse(JSON.stringify(date))); + setTimeout(() => { + const svg = document.getElementById('testSVG_' + (this.signaturesService.datesContent[this.signaturesService.currentPage].length - 1)); + const data = new XMLSerializer().serializeToString(svg); + const blob = new Blob([data], { type: 'image/svg+xml' }); + + const reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onloadend = () => { + this.signaturesService.datesContent[page][this.signaturesService.datesContent[page].length - 1].content = reader.result; + this.localStorage.save(this.signaturesService.mainDocumentId.toString(), JSON.stringify({ 'date': this.signaturesService.datesContent, 'sign': this.signaturesService.signaturesContent, 'note': this.signaturesService.notesContent })); + }; + }, 200); } removeSignature(signature: any) {