11 Commits

12 changed files with 179 additions and 31 deletions

View File

@@ -39,7 +39,10 @@ def parse_query(query: str, model):
or_array = [] or_array = []
for field in model.Settings.fulltext_search: for field in model.Settings.fulltext_search:
or_array.append(RegEx(field, value, 'i')) words_and_array = []
for word in value.split(' '):
words_and_array.append(RegEx(field, word, 'i'))
or_array.append(And(*words_and_array) if len(words_and_array) > 1 else words_and_array[0])
operand = Or(or_array) if len(or_array) > 1 else or_array[0] operand = Or(or_array) if len(or_array) > 1 else or_array[0]
elif operator == 'eq': elif operator == 'eq':

View File

@@ -5,10 +5,11 @@ from beanie import init_beanie
from .user import User, AccessToken from .user import User, AccessToken
from .entity.models import Entity from .entity.models import Entity
from .template.models import ContractTemplate, ProvisionTemplate from .template.models import ContractTemplate, ProvisionTemplate
from .order.models import Order
from .contract.models import ContractDraft, Contract from .contract.models import ContractDraft, Contract
# from .order.models import Order
DATABASE_URL = "mongodb://root:example@mongo:27017/" DB_PASSWORD = "IBO3eber0mdw2R9pnInLdtFykQFY2f06"
DATABASE_URL = f"mongodb://root:{DB_PASSWORD}@mongo:27017/"
async def init_db(): async def init_db():

View File

@@ -1,5 +1,5 @@
import uuid import uuid
from typing import Any, Dict, Generic, Optional from typing import Any
from bson import ObjectId from bson import ObjectId
from fastapi import Depends from fastapi import Depends

View File

@@ -3,10 +3,10 @@ import asyncio
import json import json
from os import path from os import path
from app.db import init_db, Entity, Order, Contract, User, AccessToken from app.db import init_db, Entity, Contract, ContractTemplate, ProvisionTemplate, User
models = [Entity, Order, Contract, User] models = [Entity, Contract, User, ContractTemplate, ProvisionTemplate]
async def handle_migration(args): async def handle_migration(args):

33
docker-compose.prod.yml Normal file
View File

@@ -0,0 +1,33 @@
version: "3.9"
services:
back:
build:
context: ${ROOT_PATH}/back
image: cht-lawfirm-back-prod
restart: always
volumes:
- ${ROOT_PATH}/back/app:/code/app
- ${ROOT_PATH}/back/media:/code/media
nginx:
build:
context: ${ROOT_PATH}/front
dockerfile: prod.Dockerfile
image: cht-lawfirm-nginx-prod
restart: always
ports:
- "3820:80"
mongo:
image: "mongo:4.4.19"
restart: always
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: IBO3eber0mdw2R9pnInLdtFykQFY2f06
volumes:
- database:/data/db
volumes:
database:

View File

@@ -3,6 +3,7 @@ services:
back: back:
build: build:
context: ./back context: ./back
image: cht-lawfirm-back-dev
restart: always restart: always
ports: ports:
- "8000:8000" - "8000:8000"
@@ -13,6 +14,7 @@ services:
front: front:
build: build:
context: ./front context: ./front
image: cht-lawfirm-front-dev
restart: always restart: always
ports: ports:
- "4200:4200" - "4200:4200"
@@ -23,18 +25,19 @@ services:
nginx: nginx:
build: build:
context: ./nginx context: ./nginx
image: cht-lawfirm-nginx-dev
restart: always restart: always
ports: ports:
- "80:80" - "80:80"
mongo: mongo:
image: "mongo:4.4.18" image: "mongo:4.4.19"
restart: always restart: always
ports: ports:
- "27017:27017" - "27017:27017"
environment: environment:
MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example MONGO_INITDB_ROOT_PASSWORD: IBO3eber0mdw2R9pnInLdtFykQFY2f06
volumes: volumes:
- database:/data/db - database:/data/db

View File

@@ -1,22 +1,11 @@
FROM node:lts-alpine FROM node:lts-alpine
# install simple http server for serving static content
RUN npm install -g http-server
# make the 'app' folder the current working directory
WORKDIR /app WORKDIR /app
RUN npm install -g @angular/cli http-server
RUN npm install -g @angular/cli
# copy both 'package.json' and 'package-lock.json' (if available)
COPY app/package*.json ./ COPY app/package*.json ./
# install project dependencies
RUN npm install RUN npm install
# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY app/ . COPY app/ .
# build app for production with minification
RUN npm run build RUN npm run build
EXPOSE 4200 EXPOSE 4200

View File

@@ -13,7 +13,8 @@
"sourceLocale": "en-US", "sourceLocale": "en-US",
"locales": { "locales": {
"fr": { "fr": {
"translation": "src/locale/messages.fr.xlf" "translation": "src/locale/messages.fr.xlf",
"baseHref": ""
} }
} }
}, },
@@ -63,9 +64,6 @@
"extractLicenses": false, "extractLicenses": false,
"sourceMap": true, "sourceMap": true,
"namedChunks": true "namedChunks": true
},
"fr": {
"localize": ["fr"]
} }
}, },
"defaultConfiguration": "production" "defaultConfiguration": "production"
@@ -80,7 +78,7 @@
"browserTarget": "app:build:development" "browserTarget": "app:build:development"
}, },
"fr": { "fr": {
"browserTarget": "App:build:fr" "browserTarget": "app:build:fr"
} }
}, },
"defaultConfiguration": "development" "defaultConfiguration": "development"

View File

@@ -6,7 +6,7 @@ import { ListComponent } from "./list/list.component";
const routes: Routes = [ const routes: Routes = [
{ path: '', component: ListComponent }, { path: '', component: ListComponent },
{ path: ':id', component: CardComponent }, { path: ':id', component: CardComponent },
];; ];
@NgModule({ @NgModule({
imports: [RouterModule.forChild(routes)], imports: [RouterModule.forChild(routes)],

View File

@@ -1,6 +1,7 @@
import {Component, OnInit} from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { FormlyFieldInput } from "@ngx-formly/bootstrap/input"; import { FormlyFieldInput } from "@ngx-formly/bootstrap/input";
@Component({ @Component({
selector: 'formly-richtext-type', selector: 'formly-richtext-type',
template: ` template: `
@@ -42,11 +43,19 @@ export class RichtextTypeComponent extends FormlyFieldInput implements OnInit {
statusbar: false, statusbar: false,
autoresize_bottom_margin: 0, autoresize_bottom_margin: 0,
body_class: "contract-body", body_class: "contract-body",
content_style: ".contract-body { font-family: 'Century Schoolbook', 'sans-serif' }" content_style: ".contract-body { font-family: 'Century Schoolbook', 'sans-serif' }",
paste_preprocess: function (plugin: any, args: any) {
console.log(args.content)
let container = document.createElement('div');
container.innerHTML = args.content.trim();
cleanPastedElement(container)
console.log(container.innerHTML);
args.content = container.innerHTML;
}
} }
init_multiline = { init_multiline = {
plugins: 'lists image imagetools table code searchreplace autoresize', plugins: 'lists image imagetools table code searchreplace paste autoresize',
menubar: 'edit insert format tools table', menubar: 'edit insert format tools table',
menu: { menu: {
edit: { title: 'Edit', items: 'undo redo | cut copy paste | selectall | searchreplace' }, edit: { title: 'Edit', items: 'undo redo | cut copy paste | selectall | searchreplace' },
@@ -59,7 +68,7 @@ export class RichtextTypeComponent extends FormlyFieldInput implements OnInit {
} }
init_singleline = { init_singleline = {
plugins: 'autoresize', plugins: 'paste autoresize',
menubar: '', menubar: '',
toolbar: 'undo redo | bold italic underline', toolbar: 'undo redo | bold italic underline',
} }
@@ -92,7 +101,49 @@ export class RichtextTypeComponent extends FormlyFieldInput implements OnInit {
} }
} }
} }
}
function cleanPastedElement(htmlElement: HTMLElement): string {
if (! htmlElement.innerHTML) {
return "";
}
let innerHtml = ""
for(let i = 0; i < htmlElement.childNodes.length; i++){
const childNode = htmlElement.childNodes[i] as HTMLElement
if (childNode.nodeName == "#text") {
innerHtml += childNode.nodeValue;
} else {
innerHtml += cleanPastedElement(childNode);
}
}
htmlElement.innerHTML = innerHtml
if (htmlElement.tagName == "SPAN") {
let text = htmlElement.innerHTML
const style = htmlElement.style
if (style.fontWeight == "700") {
let strong = document.createElement('b');
strong.innerHTML = text
text = strong.outerHTML;
}
if (style.textDecoration == "underline") {
let underline = document.createElement('u');
underline.innerHTML = text;
text = underline.outerHTML;
}
if (style.fontStyle == "italic") {
let italic = document.createElement('em');
italic.innerHTML = text;
text = italic.outerHTML;
}
return text;
}
htmlElement.style.removeProperty("line-height")
htmlElement.style.removeProperty("margin")
return htmlElement.outerHTML
} }

53
front/nginx.prod.conf Normal file
View File

@@ -0,0 +1,53 @@
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-back {
server back:8000;
}
types {
module js;
}
include /etc/nginx/mime.types;
server {
listen 80;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 256;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 9;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html?$args;
}
location ~* ^.+\.css$ {
default_type text/css;
}
location ~* ^.+\.js$ {
default_type text/javascript;
}
location /api/v1/ {
proxy_pass http://docker-back/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}

17
front/prod.Dockerfile Normal file
View File

@@ -0,0 +1,17 @@
FROM node:lts-alpine AS builder
WORKDIR /app
RUN npm install -g @angular/cli
COPY app/package*.json ./
RUN npm install
COPY app/ .
RUN npm run build --prod
FROM nginx:alpine
COPY nginx.prod.conf /etc/nginx/nginx.conf
COPY --from=builder /app/dist/app/fr/ /usr/share/nginx/html/