16 Commits

25 changed files with 390 additions and 96 deletions

View File

@@ -7,7 +7,7 @@ from .routes_draft import draft_router
from .print import print_router
from .models import Contract, ContractDraft, ContractDraftStatus, Party, replace_variables_in_value
from .schemas import ContractCreate, ContractRead, ContractUpdate
from .schemas import ContractCreate, ContractRead, ContractUpdate, SignatureRead
from ..entity.models import Entity
from ..template.models import ProvisionTemplate
@@ -75,10 +75,12 @@ async def update(id: str, contract_form: ContractUpdate, user=Depends(get_curren
@contract_router.get("/signature/{signature_id}", response_description="")
async def get_signature(signature_id: str) -> Party:
async def get_signature(signature_id: str) -> SignatureRead:
contract = await Contract.find_by_signature_id(signature_id)
signature = contract.get_signature(signature_id)
return signature
signature_dict = signature.dict()
signature_dict['contract_label'] = contract.label
return signature_dict
@contract_router.post("/signature/{signature_id}", response_description="")

View File

@@ -2,7 +2,7 @@ import datetime
from typing import List, Literal
from enum import Enum
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, validator
from beanie.operators import ElemMatch
from ..core.models import CrudDocument, RichtextSingleline, RichtextMultiline, DictionaryEntry
@@ -90,7 +90,7 @@ class DraftProvision(BaseModel):
provision: ContractProvisionTemplateReference | ProvisionGenuine = Field(..., discriminator='type')
class Config:
title = 'Provision'
title = 'Clause'
class Provision(BaseModel):
@@ -166,6 +166,10 @@ class ContractDraft(CrudDocument):
class Contract(CrudDocument):
"""
Contrat publié. Les contrats ne peuvent pas être modifiés.
Ils peuvent seulement être signés par les parties et imprimés par l'avocat
"""
name: str = Field(title="Nom")
title: str = Field(title="Titre")
parties: List[Party] = Field(title="Parties")
@@ -177,6 +181,19 @@ class Contract(CrudDocument):
lawyer: Entity = Field(title="Avocat en charge")
location: str = Field(title="Lieu")
date: datetime.date = Field(title="Date")
label: str = None
@validator("label", always=True)
def generate_label(cls, v, values, **kwargs):
if not v:
contract_label = values['title']
for p in values['parties']:
contract_label = contract_label + f" - {p.entity.label}"
contract_label = contract_label + f" {values['date'].strftime('%m/%d/%Y')}"
return contract_label
return v
class Settings(CrudDocument.Settings):
fulltext_search = ['name', 'title']

View File

@@ -73,3 +73,12 @@ class ContractCreate(Writer):
class ContractUpdate(BaseModel):
pass
class SignatureRead(BaseModel):
signature_uuid: str
entity: Entity
part: str
representative: Entity = None
signature_affixed: bool
contract_label: str

View File

@@ -28,8 +28,8 @@ class Individual(EntityType):
@property
def label(self) -> str:
if len(self.surnames) > 0:
return '{} "{}" {}'.format(self.firstname, self.surnames[0], self.lastname)
# if len(self.surnames) > 0:
# return '{} "{}" {}'.format(self.firstname, self.surnames[0], self.lastname)
return '{} {}'.format(self.firstname, self.lastname)

View File

@@ -1,6 +1,5 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {ContractsModule} from "./views/contracts/contracts.module";
const routes: Routes = [
{
@@ -30,6 +29,11 @@ const routes: Routes = [
loadChildren: () =>
import('./views/templates/templates.module').then((m) => m.TemplatesModule)
},
{
path: 'contract-drafts',
loadChildren: () =>
import('./views/contract-drafts/contract-drafts.module').then((m) => m.ContractDraftsModule)
},
{
path: 'contracts',
loadChildren: () =>

View File

@@ -0,0 +1,5 @@
.sidenav {
background-image: url("/assets/leather_texture.png");
background-size: 220px;
max-width: 220px;
}

View File

@@ -3,7 +3,7 @@
<main style="margin-top: 0px;">
<div class="container-fluid">
<div class="row flex-nowrap">
<div class="col-auto col-md-3 col-xl-2 px-sm-2 px-0 bg-dark" style="max-width: 200px;">
<div class="sidenav col-auto col-md-3 col-xl-2 px-sm-2 px-0 bg-dark">
<sidenav class="sticky-top"></sidenav>
</div>
<div class="col py-3">

View File

@@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import {Title} from "@angular/platform-browser";
@Component({
selector: 'app-root',
@@ -8,5 +9,7 @@ import { Component } from '@angular/core';
export class AppComponent {
title = 'Cooper, Hillman & Toshi';
constructor() {}
constructor(private titleService: Title) {
titleService.setTitle(this.title)
}
}

View File

@@ -0,0 +1,3 @@
.logout {
margin-top: 25px;
}

View File

@@ -11,6 +11,6 @@
</a>
</li>
</ng-container>
<li><logout></logout></li>
<li class="logout"><logout></logout></li>
</ul>
</div>

View File

@@ -3,13 +3,21 @@ import { Router } from '@angular/router';
import { IconNamesEnum } from "ngx-bootstrap-icons";
import { AuthService } from "../auth/auth.service";
interface MenuItem {
title: string,
link: string,
icon: IconNamesEnum
}
@Component({
selector: "sidenav",
templateUrl: "./sidenav.component.html",
styleUrls: ["./sidenav.component.css"]
})
export class SidenavComponent {
Menu = [
Menu: MenuItem[] = [
{
title: $localize`Dashboard`,
link: "/dashboard",
@@ -32,7 +40,7 @@ export class SidenavComponent {
},
{
title: $localize`Contracts&nbsp;Drafts`,
link: "/contracts/drafts",
link: "/contract-drafts",
icon: IconNamesEnum.PencilSquare
},
{
@@ -54,7 +62,7 @@ export class SidenavComponent {
})
}
is_current_page(menu_item: any) {
return this.router.url.indexOf(menu_item.link) > -1;
is_current_page(menu_item: MenuItem) {
return this.router.url.startsWith(menu_item.link);
}
}

View File

@@ -0,0 +1,44 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DraftsCardComponent, DraftsListComponent, DraftsNewComponent } from "./drafts.component";
const routes: Routes = [
{
path: '',
data: {
title: 'Contract Drafts',
},
children: [
{ path: '', redirectTo: 'list', pathMatch: 'full' },
{
path: 'list',
component: DraftsListComponent,
data: {
title: 'List',
},
},
{
path: 'new',
component: DraftsNewComponent,
data: {
title: 'New',
},
},
{
path: ':id',
component: DraftsCardComponent,
data: {
title: 'Card',
},
},
],
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ContractDraftsRoutingModule {}

View File

@@ -0,0 +1,42 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { BaseViewModule } from "../base-view/base-view.module";
import { ContractDraftsRoutingModule } from './contract-drafts-routing.module';
import { DraftsCardComponent, DraftsListComponent, DraftsNewComponent, DraftsNewFormComponent } from "./drafts.component";
import { FormlyModule } from "@ngx-formly/core";
import { FormlyBootstrapModule } from "@ngx-formly/bootstrap";
import { ForeignkeyTypeComponent } from "@common/crud/types/foreignkey.type";
import { CrudService, ImageUploaderCrudService } from "@common/crud/crud.service";
import { NgbAccordionModule, NgbCollapseModule } from "@ng-bootstrap/ng-bootstrap";
import { allIcons, NgxBootstrapIconsModule } from "ngx-bootstrap-icons";
import { ClipboardModule } from "@angular/cdk/clipboard";
@NgModule({
imports: [
CommonModule,
BaseViewModule,
ContractDraftsRoutingModule,
NgbAccordionModule,
NgbCollapseModule,
NgxBootstrapIconsModule.pick(allIcons),
FormlyModule.forRoot({
types: [
{ name: 'foreign-key', component: ForeignkeyTypeComponent }
]
}),
FormlyBootstrapModule,
ClipboardModule,
],
declarations: [
DraftsListComponent,
DraftsNewComponent,
DraftsCardComponent,
DraftsNewFormComponent
],
providers: [CrudService, ImageUploaderCrudService]
})
export class ContractDraftsModule {
}

View File

@@ -98,10 +98,10 @@ export class DraftsNewComponent extends BaseDraftsComponent implements OnInit {
(resourceReceived)="this.onResourceReceived($event)"
>
</base-card>
<a class="btn btn-link" href="/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" i18n>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>
<button class="btn btn-success" (click)="publish()" i18n>Publish</button>
</ng-container>
`
})
@@ -162,7 +162,7 @@ export class DraftsCardComponent extends BaseDraftsComponent implements OnInit {
publish() {
this.crudService.create('contract', this.newContractModel).subscribe({
next: (response: any) => this.router.navigate([`../../${response.id}`], {relativeTo: this.route}),
next: (response: any) => this.router.navigate([`../../contracts/${response.id}`], {relativeTo: this.route}),
error: (err) => this.flashService.error(err)
});
}

View File

@@ -1,7 +1,6 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DraftsCardComponent, DraftsListComponent, DraftsNewComponent } from "./drafts.component";
import { ContractsCardComponent, ContractsListComponent, ContractsNewComponent, ContractsSignatureComponent} from "./contracts.component";
@@ -13,6 +12,7 @@ const routes: Routes = [
},
children: [
{ path: '', redirectTo: 'list', pathMatch: 'full' },
{ path: 'drafts', redirectTo: '/contract-drafts/list' },
{
path: 'list',
component: ContractsListComponent,
@@ -34,36 +34,6 @@ const routes: Routes = [
title: 'New',
},
},
{
path: 'drafts',
data: {
title: 'Drafts',
},
children: [
{ path: '', redirectTo: 'list', pathMatch: 'full' },
{
path: 'list',
component: DraftsListComponent,
data: {
title: 'List',
},
},
{
path: 'new',
component: DraftsNewComponent,
data: {
title: 'New',
},
},
{
path: ':id',
component: DraftsCardComponent,
data: {
title: 'Card',
},
},
],
},
{
path: ':id',
component: ContractsCardComponent,

View File

@@ -1,6 +1,6 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, ElementRef, Input, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from "@angular/router";
import { DomSanitizer } from "@angular/platform-browser";
import { DomSanitizer, Meta } from "@angular/platform-browser";
import { ImageUploaderCrudService } from "@common/crud/crud.service";
@@ -81,7 +81,7 @@ export class ContractsCardComponent extends BaseContractsComponent{
<ngb-accordion #acc="ngbAccordion" activeIds="ngb-panel-1">
<ngb-panel>
<ng-template ngbPanelTitle>
<span>Preview</span>
<span i18n>Preview</span>
</ng-template>
<ng-template ngbPanelContent>
<iframe width="100%"
@@ -91,19 +91,14 @@ export class ContractsCardComponent extends BaseContractsComponent{
</ngb-panel>
<ngb-panel>
<ng-template ngbPanelTitle>
<span>Signature</span>
<span i18n>Signature</span>
</ng-template>
<ng-template ngbPanelContent>
<ng-container *ngIf="this.affixed">This Contract has already been signed by {{ this.signatory }}</ng-container>
<ng-container *ngIf="this.affixed"><ng-container i18n>This Contract has already been signed by</ng-container> {{ 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 class="col-5" i18n [innerHTML]="this.legalText"></div>
</div>
</ng-template>
</ngb-panel>
@@ -117,10 +112,13 @@ export class ContractsSignatureComponent implements OnInit {
affixed = false;
public legalText: string = "";
constructor(
private route: ActivatedRoute,
private sanitizer: DomSanitizer,
private crudService: ImageUploaderCrudService,
private meta: Meta,
) {}
ngOnInit() {
@@ -134,8 +132,26 @@ export class ContractsSignatureComponent implements OnInit {
} else {
this.signatory = this.signature.entity.entity_data.firstname + " " + this.signature.entity.entity_data.lastname;
}
})
})
this.legalText = `
<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>
`
this.meta.updateTag({
name: 'og:title',
property: 'og:title',
content: this.signature.contract_label});
this.meta.updateTag({
name: 'og:description',
property: 'og:description',
content: this.legalText.replace(/<[^>]*>/g, '').trim()
});
this.meta.updateTag({ name: 'og:image', content: `${location.origin}/assets/logo.png` });
});
});
}
getPreview() {

View File

@@ -3,7 +3,6 @@ import { NgModule } from '@angular/core';
import { BaseViewModule } from "../base-view/base-view.module";
import { ContractsRoutingModule } from './contracts-routing.module';
import { DraftsCardComponent, DraftsListComponent, DraftsNewComponent, DraftsNewFormComponent } from "./drafts.component";
import { FormlyModule } from "@ngx-formly/core";
import { FormlyBootstrapModule } from "@ngx-formly/bootstrap";
import { ForeignkeyTypeComponent } from "@common/crud/types/foreignkey.type";
@@ -33,10 +32,6 @@ import { ClipboardModule } from "@angular/cdk/clipboard";
ClipboardModule,
],
declarations: [
DraftsListComponent,
DraftsNewComponent,
DraftsCardComponent,
DraftsNewFormComponent,
ContractsListComponent,
ContractsNewComponent,
ContractsCardComponent,

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -30,7 +30,7 @@ export class JsonschemasService {
buildResource(resourceName: string) {
let resource;
resource = { ... this.rawSchemas.components.schemas[resourceName]};
resource = structuredClone(this.rawSchemas.components.schemas[resourceName]);
resource.components = { schemas: {} };
for (let prop_name in resource.properties) {
let prop = resource.properties[prop_name];
@@ -162,6 +162,14 @@ export class JsonschemasService {
}
return false;
}
} else if (this.is_enum(resource)) {
for (const ref of resource.allOf!) {
// @ts-ignore
if (this.has_descendant(ref, property_name)) {
return true;
}
return false;
}
}
throw new Error("Jsonschema format not implemented in property finder");
return false;
@@ -186,6 +194,14 @@ export class JsonschemasService {
return this.get_descendant(ref, property_name);
}
}
} else if (this.is_enum(resource)) {
for (const ref of resource.allOf!) {
// @ts-ignore
if (this.has_descendant(ref, property_name)) {
// @ts-ignore
return this.get_descendant(ref, property_name);
}
}
}
throw new Error("property not found or Jsonschema format not implemented");
}

View File

@@ -14,13 +14,14 @@ import {CrudFormlyJsonschemaService} from "@common/crud/crud-formly-jsonschema.s
export class FilterListComponent implements OnInit {
@Input() filters: string[] = [];
@Input() schema = "";
@Input() values = {};
@Output() filterChange: EventEmitter<{[key: string]: any}> = new EventEmitter();
form = new FormGroup({});
fields: FormlyFieldConfig[] = [];
searchTerms = {}
searchTerms: {[key: string]: string | {}} = {}
public fieldJson = {
components: {},
@@ -48,6 +49,16 @@ export class FilterListComponent implements OnInit {
prop = schema.components.schemas[prop.allOf![0]['$ref'].replace('#/components/schemas/', '')];
prop.type = "array";
prop.items = {"type": "string", "enum": prop.enum};
if (filter in this.values) {
this.searchTerms[filter] = {};
// @ts-ignore
for (let val of this.values[filter]) {
// @ts-ignore
this.searchTerms[filter][val] = true;
}
}
} else if(true) {
}
if (prop.hasOwnProperty('readOnly') && prop.readOnly) {

View File

@@ -14,7 +14,12 @@
/>
</div>
<div class="col-xs-3 col-sm-auto">
<crud-list-filter-list [filters]="this.filters" [schema]="this.schema!" (filterChange)="onFilterChange($event)"></crud-list-filter-list>
<crud-list-filter-list
[filters]="this.filters"
[schema]="this.schema!"
[values]="this.searchFilters"
(filterChange)="onFilterChange($event)"
></crud-list-filter-list>
</div>
<span class="col col-form-label" i18n *ngIf="loading$ | async">Loading...</span>
</div>

View File

@@ -40,7 +40,6 @@ export class ListComponent implements OnInit {
public displayedColumns: Column[] = [];
private _loading$ = new BehaviorSubject<boolean>(true);
//private _search$ = new Subject<void>();
private _listData$ = new BehaviorSubject<any[]>([]);
private _total$ = new BehaviorSubject<number>(0);
@@ -64,7 +63,14 @@ export class ListComponent implements OnInit {
next: (schema: any) => this.getColumnDefinition(schema),
error: (err) => this.error.emit("Error loading the schema:" + err)
});
this._search();
this.route.queryParams.subscribe(params => {
let parsedParams = {...params};
if (parsedParams.hasOwnProperty('searchFilters')) {
parsedParams['searchFilters'] = JSON.parse(parsedParams['searchFilters']);
}
this._total$.next(this.page * this.pageSize);
this._set(parsedParams)
});
}
getColumnDefinition(schema: JSONSchema7) {
@@ -149,7 +155,7 @@ export class ListComponent implements OnInit {
}
onRowMiddleClick(id: string) {
let newUrl = window.location.href.replace('list', id)
let newUrl = window.location.href.replace('list', id).split('?')[0]
window.open(newUrl, '_blank');
}
@@ -182,30 +188,43 @@ export class ListComponent implements OnInit {
return this._state.searchTerm;
}
get searchFilters() {
return this._state.searchFilters;
return this._state.searchFilters;
}
set page(page: number) {
this._set({ page });
}
set pageSize(pageSize: number) {
this._set({ pageSize });
}
set searchTerm(searchTerm: string) {
this._set({ searchTerm });
}
set searchFilters(searchFilters: {[key: string]: any}) {
this._set({ searchFilters });
}
set sortColumn(sortColumn: SortColumn) {
this._set({ sortColumn });
}
set sortDirection(sortDirection: SortDirection) {
this._set({ sortDirection });
}
set page(page: number) {
this.updateState({ page });
}
private _set(patch: Partial<State>) {
Object.assign(this._state, patch);
this._search();
}
set pageSize(pageSize: number) {
this.updateState({ pageSize });
}
set searchTerm(searchTerm: string) {
this.updateState({ searchTerm });
}
set searchFilters(searchFilters: {[key: string]: any}) {
this.updateState({ searchFilters: JSON.stringify(searchFilters) });
}
set sortColumn(sortColumn: SortColumn) {
this.updateState({ sortColumn });
}
set sortDirection(sortDirection: SortDirection) {
this.updateState({ sortDirection });
}
private updateState(patch: any) {
this.router.navigate([], {
relativeTo: this.route,
queryParams: patch ,
queryParamsHandling: 'merge'
});
}
private _set(patch: Partial<State>) {
Object.assign(this._state, patch);
this._search();
}
}

View File

@@ -354,5 +354,69 @@
<target>Mettre à jour</target>
</segment>
</unit>
<unit id="6061331044524123789">
<segment state="initial">
<source>Authentication required</source>
<target>Authentification nécessaire</target>
</segment>
</unit>
<unit id="3624268617519726175">
<segment state="initial">
<source>Permissions too low</source>
<target>Permissions trop basses</target>
</segment>
</unit>
<unit id="6833883791906187270">
<segment state="initial">
<source>Download Link:</source>
<target>Lien de téléchargement:</target>
</segment>
</unit>
<unit id="8168599357858858911">
<segment state="initial">
<source>Preview Link:</source>
<target>Lien de prévisualisation:</target>
</segment>
</unit>
<unit id="1295614462098694869">
<segment state="initial">
<source>Preview</source>
<target>Prévisualisation</target>
</segment>
</unit>
<unit id="2445188258613609179">
<segment state="initial">
<source>Signature</source>
<target>Signature</target>
</segment>
</unit>
<unit id="8474971383445371291">
<segment state="initial">
<source>
<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Cette page est à la destination exclusive de <pc id="1" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;"><ph id="2" equiv="INTERPOLATION" disp="{{ this.signatory }}"/></pc></pc>
<pc id="3" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Si vous n&apos;êtes <pc id="4" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">pas</pc> <ph id="5" equiv="INTERPOLATION" disp="{{ this.signatory }}"/>, veuillez <pc id="6" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">fermer cette page immédiatement</pc> et surpprimer tous les liens en votre possession menant vers celle-ci.</pc>
<pc id="7" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">En vous maintenant et/ou en interagissant avec cette page, vous enfreignez l&apos;article L.229 du code pénal de l&apos;Etat de San Andreas pour <pc id="8" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">usurpation d&apos;identité</pc> et vous vous exposez ainsi à une amende de 20 000$ ainsi qu&apos;à des poursuites civiles.</pc>
<pc id="9" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Le cabinet Cooper, Hillman &amp; Toshi LLC</pc>
</source>
<target>
<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Cette page est à la destination exclusive de <pc id="1" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;"><ph id="2" equiv="INTERPOLATION" disp="{{ this.signatory }}"/></pc></pc>
<pc id="3" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Si vous n&apos;êtes <pc id="4" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">pas</pc> <ph id="5" equiv="INTERPOLATION" disp="{{ this.signatory }}"/>, veuillez <pc id="6" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">fermer cette page immédiatement</pc> et surpprimer tous les liens en votre possession menant vers celle-ci.</pc>
<pc id="7" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">En vous maintenant et/ou en interagissant avec cette page, vous enfreignez l&apos;article L.229 du code pénal de l&apos;Etat de San Andreas pour <pc id="8" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">usurpation d&apos;identité</pc> et vous vous exposez ainsi à une amende de 20 000$ ainsi qu&apos;à des poursuites civiles.</pc>
<pc id="9" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Le cabinet Cooper, Hillman &amp; Toshi LLC</pc>
</target>
</segment>
</unit>
<unit id="7430416142942514215">
<segment state="initial">
<source>Publish</source>
<target>Publier</target>
</segment>
</unit>
<unit id="2990108023996257960">
<segment state="initial">
<source>This Contract has already been signed by</source>
<target>Ce contrat a déjà été signé par</target>
</segment>
</unit>
</file>
</xliff>

View File

@@ -292,5 +292,55 @@
<source>100 items per page</source>
</segment>
</unit>
<unit id="3624268617519726175">
<segment>
<source>Permissions too low</source>
</segment>
</unit>
<unit id="6061331044524123789">
<segment>
<source>Authentication required</source>
</segment>
</unit>
<unit id="6833883791906187270">
<segment>
<source>Download Link:</source>
</segment>
</unit>
<unit id="8168599357858858911">
<segment>
<source>Preview Link:</source>
</segment>
</unit>
<unit id="1295614462098694869">
<segment>
<source>Preview</source>
</segment>
</unit>
<unit id="2445188258613609179">
<segment>
<source>Signature</source>
</segment>
</unit>
<unit id="7430416142942514215">
<segment>
<source>Publish</source>
</segment>
</unit>
<unit id="8474971383445371291">
<segment>
<source>
<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Cette page est à la destination exclusive de <pc id="1" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;"><ph id="2" equiv="INTERPOLATION" disp="{{ this.signatory }}"/></pc></pc>
<pc id="3" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Si vous n&apos;êtes <pc id="4" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">pas</pc> <ph id="5" equiv="INTERPOLATION" disp="{{ this.signatory }}"/>, veuillez <pc id="6" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">fermer cette page immédiatement</pc> et surpprimer tous les liens en votre possession menant vers celle-ci.</pc>
<pc id="7" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">En vous maintenant et/ou en interagissant avec cette page, vous enfreignez l&apos;article L.229 du code pénal de l&apos;Etat de San Andreas pour <pc id="8" equivStart="START_TAG_STRONG" equivEnd="CLOSE_TAG_STRONG" type="other" dispStart="&lt;strong&gt;" dispEnd="&lt;/strong&gt;">usurpation d&apos;identité</pc> et vous vous exposez ainsi à une amende de 20 000$ ainsi qu&apos;à des poursuites civiles.</pc>
<pc id="9" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="&lt;p&gt;" dispEnd="&lt;/p&gt;">Le cabinet Cooper, Hillman &amp; Toshi LLC</pc>
</source>
</segment>
</unit>
<unit id="2990108023996257960">
<segment>
<source>This Contract has already been signed by</source>
</segment>
</unit>
</file>
</xliff>

View File

@@ -26,3 +26,14 @@
.contract-body {
font-family: 'Century Schoolbook';
}
.nav-link {
color: #D2BA6F;
--bs-nav-link-hover-color: #9c8a51;
--bs-nav-pills-link-active-color: #D2BA6F;
--bs-nav-pills-link-active-bg: #114856;
}
.nav-link.active {
border: #D2BA6F solid 2px;
}