Merge branch 'master' of git.dorfsvald.net:ewandor/cht-lawfirm

This commit is contained in:
2023-03-14 19:00:18 +01:00
8 changed files with 112 additions and 74 deletions

View File

@@ -2,7 +2,7 @@ import datetime
import os
import base64
from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.templating import Jinja2Templates
@@ -61,47 +61,47 @@ print_router = APIRouter()
templates = Jinja2Templates(directory=str(BASE_PATH / "templates"))
async def render_print(host, contract):
async def render_print(root_url, contract):
template = templates.get_template("print.html")
return template.render({
"contract": contract,
"static_host": host
"root_url": root_url
})
async def render_css(host, contract):
async def render_css(root_url, contract):
template = templates.get_template("styles.css")
return template.render({
"contract": contract,
"static_host": host
"root_url": root_url
})
@print_router.get("/preview/draft/{draft_id}", response_class=HTMLResponse)
async def preview_draft(draft_id: str) -> str:
async def preview_draft(draft_id: str, request: Request) -> str:
draft = await build_model(await ContractDraft.get(draft_id))
return await render_print('localhost', draft)
return await render_print(f'{request.url.scheme}://{request.url.hostname}', draft)
@print_router.get("/preview/signature/{signature_id}", response_class=HTMLResponse)
async def preview_contract_by_signature(signature_id: str) -> str:
async def preview_contract_by_signature(signature_id: str, request: Request) -> str:
contract = await Contract.find_by_signature_id(signature_id)
for p in contract.parties:
if p.signature_affixed:
p.signature_png = retrieve_signature_png(f'media/signatures/{p.signature_uuid}.png')
return await render_print('localhost', contract)
return await render_print(f'{request.url.scheme}://{request.url.hostname}', contract)
@print_router.get("/preview/{contract_id}", response_class=HTMLResponse)
async def preview_contract(contract_id: str) -> str:
async def preview_contract(contract_id: str, request: Request) -> str:
contract = await Contract.get(contract_id)
for p in contract.parties:
if p.signature_affixed:
p.signature_png = retrieve_signature_png(f'media/signatures/{p.signature_uuid}.png')
return await render_print('localhost', contract)
return await render_print(f'{request.url.scheme}://{request.url.hostname}', contract)
@print_router.get("/pdf/{contract_id}", response_class=FileResponse)
@@ -118,8 +118,8 @@ async def create_pdf(contract_id: str) -> str:
# os.remove(signature_path)
font_config = FontConfiguration()
html = HTML(string=await render_print('nginx', contract))
css = CSS(string=await render_css('nginx', contract), font_config=font_config)
html = HTML(string=await render_print('http://nginx', contract))
css = CSS(string=await render_css('http://nginx', contract), font_config=font_config)
html.write_pdf(contract_path, stylesheets=[css], font_config=font_config)
update_query = {"$set": {

View File

@@ -8,7 +8,7 @@
<div class="frontpage">
<div id="front-page-header">
<table><tr>
<td><img id="top-logo" src="http://{{ static_host }}/assets/logotransparent.png" alt="Cooper, Hillman & Toshi logo"></td>
<td><img id="top-logo" src="{{ root_url }}/assets/logotransparent.png" alt="Cooper, Hillman & Toshi logo"></td>
<td id="office-info">Cooper, Hillman & Toshi LLP<br />6834 Innocence Boulevard<br />LOS SANTOS - SA<br /><a href="#">consulting@cht.law.com</a></td>
</tr></table>
<h1>{{ contract.title|upper }}</h1>
@@ -27,7 +27,7 @@
{{ party.entity.entity_data.title }} soci&eacute;t&eacute; de {{ party.entity.entity_data.activity }} enregistr&eacute;e aupr&egrave;s du gouvernement de San Andreas et domicili&eacute;e au {{ party.entity.address }}{% if party.representative %}, repr&eacute;sent&eacute;e par {{ party.representative.entity_data.firstname }} {{ party.representative.entity_data.middlenames }} {{ party.representative.entity_data.lastname }}{% endif %}
{% elif party.entity.entity_data.type == "individual" %}
{{ party.entity.entity_data.firstname }} {{ party.entity.entity_data.middlenames }} {{ party.entity.entity_data.lastname }}
{% if party.entity.entity_data.day_of_birth %} n&eacute; le {{ party.entity.entity_data.day_of_birth.strftime('%d/%m/%Y') }} {% if true %} &agrave; {{ party.entity.entity_data.place_of_birth }}{% endif %},{% endif %}
{% if party.entity.entity_data.day_of_birth %} n&eacute; le {{ party.entity.entity_data.day_of_birth.strftime('%d/%m/%Y') }} {% if party.entity.entity_data.place_of_birth %} &agrave; {{ party.entity.entity_data.place_of_birth }}{% endif %},{% endif %}
{% if party.entity.address %} r&eacute;sidant &agrave; {{ party.entity.address }}, {% endif %}
{% elif party.entity.entity_data.type == "institution" %}

View File

@@ -1,24 +1,24 @@
@font-face {
font-family: 'Century Schoolbook';
src: url('http://{{ static_host }}/assets/century-schoolbook/CenturySchoolbookRegular.ttf');
src: url('{{ root_url }}/assets/century-schoolbook/CenturySchoolbookRegular.ttf');
}
@font-face {
font-family: "Century Schoolbook";
src: url("http://{{ static_host }}/assets/century-schoolbook/CenturySchoolbookBold.ttf");
src: url("{{ root_url }}/assets/century-schoolbook/CenturySchoolbookBold.ttf");
font-weight: bold;
}
@font-face {
font-family: "Century Schoolbook";
src: url("http://{{ static_host }}/assets/century-schoolbook/CenturySchoolbookItalic.ttf");
src: url("{{ root_url }}/assets/century-schoolbook/CenturySchoolbookItalic.ttf");
font-style: italic;
}
@font-face {
font-family: "Century Schoolbook";
src: url("http://{{ static_host }}/assets/century-schoolbook/CenturySchoolbookBoldItalic.ttf");
src: url("{{ root_url }}/assets/century-schoolbook/CenturySchoolbookBoldItalic.ttf");
font-weight: bold;
font-style: italic;
}
@@ -31,7 +31,7 @@
content: "© Cooper, Hillman & Toshi LLC - {{ contract.name }} - Page " counter(page) "/" counter(pages);
font-size: 0.8em;
}
background: url('http://{{ static_host }}/assets/watermark.png') no-repeat;
background: url('{{ root_url }}/assets/watermark.png') no-repeat;
background-size:contain;
}

View File

@@ -15,13 +15,17 @@ class ContractDraftRead(ContractDraft):
class ContractDraftCreate(Writer):
name: str
title: str
parties: List[DraftParty]
provisions: List[DraftProvision]
name: str = Field(title='Nom')
title: str = Field(title='Titre')
parties: List[DraftParty] = Field(title='Parties')
provisions: List[DraftProvision] = Field(
props={"items-per-row": "1", "numbered": True},
title='Clauses'
)
variables: List[DictionaryEntry] = Field(
default=[],
format="dictionary",
title='Variables'
)
async def validate_foreign_key(self):

View File

@@ -23,10 +23,9 @@ class Individual(EntityType):
props={"items-per-row": "4", "numbered": True},
title="Surnoms"
)
day_of_birth: date = Field(title='Date de naissance')
day_of_birth: date = Field(default=None, title='Date de naissance')
place_of_birth: str = Field(default="", title='Lieu de naissance')
@property
def label(self) -> str:
if len(self.surnames) > 0:

View File

@@ -97,7 +97,7 @@ export class DraftsNewComponent extends BaseDraftsComponent implements OnInit {
(resourceReceived)="this.onResourceReceived($event)"
>
</base-card>
<a class="btn btn-link" href="http://localhost/api/v1/contract/print/preview/draft/{{this.resource_id}}" target="_blank">Preview</a>
<a class="btn btn-link" href="/api/v1/contract/print/preview/draft/{{this.resource_id}}" target="_blank">Preview</a>
<ng-container *ngIf="this.isReadyForPublication;">
<formly-form [fields]="newContractFormfields" [form]="newContractForm" [model]="newContractModel"></formly-form>
<button class="btn btn-success" (click)="publish()">Publish</button>
@@ -105,18 +105,20 @@ export class DraftsNewComponent extends BaseDraftsComponent implements OnInit {
`
})
export class DraftsCardComponent extends BaseDraftsComponent implements OnInit {
resource_id: string | null = null;templateModel: {} = {};
resource_id: string | null = null;
templateModel: {} = {};
isReadyForPublication = false;
newContractFormfields: FormlyFieldConfig[] = [];
newContractForm: FormGroup = new FormGroup({});
newContractModel: any = {
date: formatDate(new Date(),'YYYY-MM-dd', 'EN_US', 'CET'),
date: new Date(),
location: "Los Santos, SA",
draft_id: null
}
fieldJson = {
type: "object",
required: ["date", "location", "draft_id"],
properties: {
date: {
type: "string",

View File

@@ -1,7 +1,6 @@
import { Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { formatDate } from "@angular/common";
import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
@@ -15,12 +14,12 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
<div class="alert alert-danger" role="alert" *ngIf="showError && formControl.errors">
<formly-validation-message [field]="field"></formly-validation-message>
</div>
<input type="hidden"
[formControl]="formControl"
[formlyAttributes]="field"
/>
<div class="input-group" *ngIf="! this.field.props.readonly">
<input type="hidden"
[formControl]="formControl"
[formlyAttributes]="field"
[class.is-invalid]="showError"
/>
<button class="btn btn-outline-secondary" (click)="d.toggle()" type="button"><i-bs name="calendar-date-fill"></i-bs></button>
<input
class="form-control"
placeholder="yyyy-mm-dd"
@@ -29,33 +28,40 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
(ngModelChange)="changeDatetime($event)"
ngbDatepicker
#d="ngbDatepicker"
[class.is-invalid]="showError"
/>
<button class="btn btn-outline-secondary" (click)="d.toggle()" type="button"><i-bs name="calendar-date-fill"></i-bs></button>
</div>
<div class="input-group" *ngIf="this.field.props.readonly">
<input class="form-control" value="{{ this.datetime.toLocaleString() }}" disabled=""/>
<input class="form-control" value="{{ this.datetime ? this.datetime.toLocaleString() : '' }}" disabled=""/>
</div>
`,
})
export class DateTypeComponent extends FieldType<FieldTypeConfig> implements OnInit
{
public date : NgbDateStruct;
public datetime : Date = new Date();
public date : NgbDateStruct | null = null;
public datetime : Date | null = null;
constructor() {
super();
this.date = this.getDateStruct(new Date());
}
ngOnInit() {
if (this.formControl.value === undefined) {
this.changeDatetime({});
} else {
this.datetime = new Date(this.formControl.value);
this.date = this.getDateStruct(this.datetime);
}
this.formControl.valueChanges.subscribe(value => {
this.datetime = new Date(value)
this.date = this.getDateStruct(this.datetime);
if (value) {
this.datetime = new Date(value);
this.date = this.getDateStruct(this.datetime);
} else {
this.datetime = null;
this.date = null;
}
})
}
@@ -68,12 +74,21 @@ export class DateTypeComponent extends FieldType<FieldTypeConfig> implements OnI
}
changeDatetime(event: any) {
this.datetime.setFullYear(this.date.year)
this.datetime.setMonth(this.date.month - 1)
this.datetime.setDate(this.date.day)
if (this.date) {
if (!this.datetime) {
this.datetime = new Date();
}
this.datetime.setFullYear(this.date.year)
this.datetime.setMonth(this.date.month - 1)
this.datetime.setDate(this.date.day)
this.formControl.setValue(
formatDate(this.datetime, 'YYYY-MM-dd', 'EN_US', 'CET')
)
this.formControl.setValue(
formatDate(this.datetime, 'YYYY-MM-dd', 'EN_US', 'CET')
)
} else {
this.datetime = null;
this.date = null;
this.formControl.setValue('')
}
}
}

View File

@@ -1,5 +1,4 @@
import { Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { formatDate } from "@angular/common";
import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
@@ -12,12 +11,12 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
class="form-label">{{ props.label }}
<span *ngIf="props.required && props['hideRequiredMarker'] !== true" aria-hidden="true">*</span>
</label>
<input type="hidden"
[formControl]="formControl"
[formlyAttributes]="field"
/>
<div class="input-group" *ngIf="! this.field.props.readonly">
<input type="hidden"
[formControl]="formControl"
[formlyAttributes]="field"
[class.is-invalid]="showError"
/>
<button class="btn btn-outline-secondary bi bi-calendar3" (click)="d.toggle()" type="button"></button>
<input
class="form-control"
placeholder="yyyy-mm-dd"
@@ -26,8 +25,8 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
(ngModelChange)="changeDatetime($event)"
ngbDatepicker
#d="ngbDatepicker"
[class.is-invalid]="showError"
/>
<button class="btn btn-outline-secondary bi bi-calendar3" (click)="d.toggle()" type="button"></button>
<ngb-timepicker
(ngModelChange)="changeDatetime($event)"
[(ngModel)]="time"
@@ -35,15 +34,15 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
</ngb-timepicker>
</div>
<div class="input-group" *ngIf="this.field.props.readonly">
<input class="form-control" value="{{ this.datetime.toLocaleString() }}" disabled=""/>
<input class="form-control" value="{{ this.datetime ? this.datetime.toLocaleString() : '' }}" disabled=""/>
</div>
`,
})
export class DatetimeTypeComponent extends FieldType<FieldTypeConfig> implements OnInit
{
public time : NgbTimeStruct;
public date : NgbDateStruct;
public datetime : Date = new Date()
public time : NgbTimeStruct | null = null;
public date : NgbDateStruct | null = null;
public datetime : Date | null = null;
constructor() {
@@ -55,12 +54,21 @@ export class DatetimeTypeComponent extends FieldType<FieldTypeConfig> implements
ngOnInit() {
if (this.formControl.value === undefined) {
this.changeDatetime({});
} else {
this.datetime = new Date(this.formControl.value);
this.date = this.getDateStruct(this.datetime);
}
this.formControl.valueChanges.subscribe(value => {
this.datetime = new Date(value)
this.date = this.getDateStruct(this.datetime);
this.time = this.getTimeStruct(this.datetime);
if (value) {
this.datetime = new Date(value);
this.date = this.getDateStruct(this.datetime);
this.time = this.getTimeStruct(this.datetime);
} else {
this.datetime = null;
this.date = null;
this.time = null;
}
})
}
@@ -81,15 +89,25 @@ export class DatetimeTypeComponent extends FieldType<FieldTypeConfig> implements
}
changeDatetime(event: any) {
this.datetime.setFullYear(this.date.year)
this.datetime.setMonth(this.date.month - 1)
this.datetime.setDate(this.date.day)
this.datetime.setHours(this.time.hour)
this.datetime.setMinutes(this.time.minute)
this.datetime.setSeconds(this.time.second)
if (this.date && this.time) {
if (!this.datetime) {
this.datetime = new Date();
}
this.datetime.setFullYear(this.date.year)
this.datetime.setMonth(this.date.month - 1)
this.datetime.setDate(this.date.day)
this.datetime.setHours(this.time.hour)
this.datetime.setMinutes(this.time.minute)
this.datetime.setSeconds(this.time.second)
this.formControl.setValue(
formatDate(this.datetime, 'YYYY-MM-ddTHH:mm:ss.SSS', 'EN_US', 'CET')
)
this.formControl.setValue(
formatDate(this.datetime, 'YYYY-MM-ddTHH:mm:ss.SSS', 'EN_US', 'CET')
)
} else {
this.datetime = null;
this.date = null;
this.time = null;
this.formControl.setValue('')
}
}
}