Contract Signing and contract printing
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import { fabric } from 'fabric';
|
||||
import {ActivatedRoute, ParamMap} from "@angular/router";
|
||||
import {DomSanitizer} from "@angular/platform-browser";
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, ParamMap } from "@angular/router";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { ImageUploaderCrudService } from "@common/crud/crud.service";
|
||||
|
||||
|
||||
export class BaseContractsComponent {
|
||||
@@ -24,9 +24,36 @@ export class ContractsNewComponent extends BaseContractsComponent {
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: '../base-view/templates/card.template.html'
|
||||
template:`
|
||||
<label>Download Link:</label>
|
||||
<div class="input-group mb-12">
|
||||
<span class="input-group-text"><a href="{{ this.contractPrintLink! }}" target="_blank">{{ this.contractPrintLink! }} </a></span>
|
||||
<button type="button" class="btn btn-light" [cdkCopyToClipboard]="this.contractPrintLink!"><i-bs name="text-paragraph"/></button>
|
||||
</div>
|
||||
<base-card
|
||||
[resource_id]="this.resource_id"
|
||||
[resource]="this.resource"
|
||||
[schema]="this.schema">
|
||||
</base-card>
|
||||
`,
|
||||
})
|
||||
export class ContractsCardComponent extends BaseContractsComponent{
|
||||
resource_id: string | null = null;
|
||||
contractPrintLink: string | null = null;
|
||||
constructor(
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.resource_id === null) {
|
||||
this.route.paramMap.subscribe((params: ParamMap) => {
|
||||
this.resource_id = params.get('id')
|
||||
this.contractPrintLink = `${location.origin}/api/v1/contract/print/pdf/${this.resource_id}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -47,7 +74,17 @@ export class ContractsCardComponent extends BaseContractsComponent{
|
||||
<span>Signature</span>
|
||||
</ng-template>
|
||||
<ng-template ngbPanelContent>
|
||||
<signature-drawer></signature-drawer>
|
||||
<ng-container *ngIf="this.affixed">This Contract has already been signed by {{ this.signatory }}</ng-container>
|
||||
<div class="row" *ngIf="!this.affixed">
|
||||
<signature-drawer class="col-7"
|
||||
(signatureDrawn$)="postSignature($event)"></signature-drawer>
|
||||
<div class="col-5">
|
||||
<p>Cette page est à la destination exclusive de <strong>{{ this.signatory }}</strong></p>
|
||||
<p>Si vous n'êtes <strong>pas</strong> {{ this.signatory }}, veuillez <strong>fermer cette page immédiatement</strong> et surpprimer tous les liens en votre possession menant vers celle-ci.</p>
|
||||
<p>En vous maintenant et/ou en interagissant avec cette page, vous enfreignez l'article L.229 du code pénal de l'Etat de San Andreas pour <strong>usurpation d'identité</strong> et vous vous exposez ainsi à une amende de 20 000$ ainsi qu'à des poursuites civiles.</p>
|
||||
<p>Le cabinet Cooper, Hillman & Toshi LLC</p>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
@@ -55,18 +92,41 @@ export class ContractsCardComponent extends BaseContractsComponent{
|
||||
})
|
||||
export class ContractsSignatureComponent implements OnInit {
|
||||
signature_id: string | null = null;
|
||||
signature: any = {}
|
||||
signatory = ""
|
||||
|
||||
affixed = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private sanitizer: DomSanitizer
|
||||
private route: ActivatedRoute,
|
||||
private sanitizer: DomSanitizer,
|
||||
private crudService: ImageUploaderCrudService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {this.route.paramMap.subscribe((params: ParamMap) => {
|
||||
this.signature_id = params.get('id')
|
||||
})
|
||||
ngOnInit() {
|
||||
this.route.paramMap.subscribe((params: ParamMap) => {
|
||||
this.signature_id = params.get('id');
|
||||
this.crudService.get('contract/signature', this.signature_id!).subscribe( (response:any) => {
|
||||
this.signature = response;
|
||||
this.affixed = this.signature.signature_affixed;
|
||||
if (this.signature.representative) {
|
||||
this.signatory = this.signature.representative.entity_data.firstname + " " + this.signature.representative.entity_data.lastname;
|
||||
} else {
|
||||
this.signatory = this.signature.entity.entity_data.firstname + " " + this.signature.entity.entity_data.lastname;
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getPreview() {
|
||||
return this.sanitizer.bypassSecurityTrustResourceUrl("/api/v1/contract/print/preview/" + this.signature_id);
|
||||
}
|
||||
|
||||
postSignature(image: string) {
|
||||
this.crudService.upload('contract/signature', this.signature_id!, image).subscribe((v: any) => {
|
||||
if (v) {
|
||||
this.affixed = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,13 @@ import { DraftsCardComponent, DraftsListComponent, DraftsNewComponent, DraftsNew
|
||||
import { FormlyModule } from "@ngx-formly/core";
|
||||
import { FormlyBootstrapModule } from "@ngx-formly/bootstrap";
|
||||
import { ForeignkeyTypeComponent } from "@common/crud/types/foreignkey.type";
|
||||
import { CrudService } from "@common/crud/crud.service";
|
||||
import { CrudService, ImageUploaderCrudService } from "@common/crud/crud.service";
|
||||
|
||||
import { NgbAccordionModule, NgbCollapseModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { allIcons, NgxBootstrapIconsModule } from "ngx-bootstrap-icons";
|
||||
import { ContractsCardComponent, ContractsListComponent, ContractsNewComponent, ContractsSignatureComponent } from "../contracts/contracts.component";
|
||||
import { AlphaRangeComponent, BlackBlueRangeComponent, SignatureDrawerComponent } from "./signature-drawer/signature-drawer.component";
|
||||
import { ClipboardModule } from "@angular/cdk/clipboard";
|
||||
|
||||
|
||||
@NgModule({
|
||||
@@ -29,6 +30,7 @@ import { AlphaRangeComponent, BlackBlueRangeComponent, SignatureDrawerComponent
|
||||
]
|
||||
}),
|
||||
FormlyBootstrapModule,
|
||||
ClipboardModule,
|
||||
],
|
||||
declarations: [
|
||||
DraftsListComponent,
|
||||
@@ -43,7 +45,7 @@ import { AlphaRangeComponent, BlackBlueRangeComponent, SignatureDrawerComponent
|
||||
BlackBlueRangeComponent,
|
||||
AlphaRangeComponent
|
||||
],
|
||||
providers: [CrudService]
|
||||
providers: [CrudService, ImageUploaderCrudService]
|
||||
})
|
||||
export class ContractsModule {
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
|
||||
<div class="row align-items-start">
|
||||
<canvas id="signatureCanvas" class="col" width="320" height="320"></canvas>
|
||||
<div class="col-sm-2">
|
||||
<canvas id="signatureCanvas" class="col-9" width="320" height="320"></canvas>
|
||||
<div class="col-3" style="width: 90px">
|
||||
<div class="card">
|
||||
<span class="btn btn-light btn-file">
|
||||
<i-bs name="image-fill"></i-bs><input #imageInput type="file" accept="image/png, image/gif, image/jpeg, image/bmp" (change)="addImage($event)">
|
||||
@@ -13,7 +13,6 @@
|
||||
<alpha-range (change)="updateAlpha($event)"></alpha-range>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<button
|
||||
type="button"
|
||||
@@ -37,7 +36,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary">Sign!</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
(click)="sign()"
|
||||
>Sign!</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
|
||||
@@ -8,6 +8,8 @@ import { fabric } from 'fabric';
|
||||
})
|
||||
export class SignatureDrawerComponent implements OnInit
|
||||
{
|
||||
@Output() signatureDrawn$ = new EventEmitter<string>()
|
||||
|
||||
size = 320;
|
||||
canvas: any;
|
||||
isEditImage = false;
|
||||
@@ -26,6 +28,14 @@ export class SignatureDrawerComponent implements OnInit
|
||||
'selection:updated': function() {self.handleElement()},
|
||||
'selection:created': function() {self.handleElement()}
|
||||
});
|
||||
|
||||
const image = localStorage.getItem('signature_image');
|
||||
if (image) {
|
||||
fabric.Image.fromURL(image , function(img: any) {
|
||||
self.canvas.add(img);
|
||||
self.canvas.renderAll();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
toggleDrawing() {
|
||||
@@ -160,6 +170,15 @@ export class SignatureDrawerComponent implements OnInit
|
||||
clear() {
|
||||
this.canvas.clear();
|
||||
}
|
||||
|
||||
sign() {
|
||||
const image = this.canvas.toDataURL({
|
||||
format: 'png',
|
||||
quality: 0.8
|
||||
});
|
||||
localStorage.setItem('signature_image', image);
|
||||
this.signatureDrawn$.next(image)
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -222,4 +241,4 @@ export class AlphaRangeComponent implements OnInit
|
||||
|
||||
this.change.emit(this.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ArrayTypeComponent } from "./types/array.type";
|
||||
import { ObjectTypeComponent } from "./types/object.type";
|
||||
import { DatetimeTypeComponent } from "./types/datetime.type";
|
||||
import { DateTypeComponent } from "./types/date.type";
|
||||
import { ApiService, CrudService } from "./crud.service";
|
||||
import { ApiService, CrudService, ImageUploaderCrudService } from "./crud.service";
|
||||
import { CrudFormlyJsonschemaService } from "./crud-formly-jsonschema.service";
|
||||
import { NgbModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import { allIcons, NgxBootstrapIconsModule } from "ngx-bootstrap-icons";
|
||||
@@ -49,6 +49,7 @@ import { ClipboardModule } from '@angular/cdk/clipboard';
|
||||
JsonschemasService,
|
||||
ApiService,
|
||||
CrudService,
|
||||
ImageUploaderCrudService,
|
||||
CrudFormlyJsonschemaService,
|
||||
DictionaryService
|
||||
],
|
||||
|
||||
@@ -116,3 +116,28 @@ export class CrudService extends ApiService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ImageUploaderCrudService extends CrudService {
|
||||
public upload(resource: string, signature_id: string, image: string) {
|
||||
const formData: FormData = new FormData();
|
||||
formData.append("signature_file", dataURIToBlob(image), signature_id + ".png");
|
||||
|
||||
return this.http.post<{ menu: [{}] }>(
|
||||
`${this.api_root}/${resource.toLowerCase()}/${signature_id}`,
|
||||
formData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function dataURIToBlob(dataURI: string) {
|
||||
const splitDataURI = dataURI.split(',')
|
||||
const byteString = splitDataURI[0].indexOf('base64') >= 0 ? atob(splitDataURI[1]) : decodeURI(splitDataURI[1])
|
||||
const mimeString = splitDataURI[0].split(':')[1].split(';')[0]
|
||||
|
||||
const ia = new Uint8Array(byteString.length)
|
||||
for (let i = 0; i < byteString.length; i++)
|
||||
ia[i] = byteString.charCodeAt(i)
|
||||
|
||||
return new Blob([ia], { type: mimeString })
|
||||
}
|
||||
Reference in New Issue
Block a user