cookiecutter template
commit
80a4b62b40
|
|
@ -0,0 +1,13 @@
|
|||
*/.git
|
||||
*/node_modules
|
||||
*/__pycache__
|
||||
*.pyc
|
||||
*/log.json
|
||||
*/conf_auto.js
|
||||
*/conf_auto.js.gz
|
||||
*/puntamenti.js
|
||||
*/vue/dist
|
||||
red/*
|
||||
dist.*
|
||||
docker/.cups*
|
||||
*/.venv
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
.env
|
||||
.vscode/
|
||||
*.sqlite3
|
||||
*.pyc
|
||||
nginx.pid
|
||||
nginx_localrun.conf
|
||||
nginx.conf
|
||||
django_static
|
||||
!docker/deployment/staging/.env
|
||||
!docker/deployment/production/.env
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
# syntax=docker/dockerfile:1.3
|
||||
FROM python:3.10-slim-bullseye AS sistema_base
|
||||
USER root
|
||||
RUN useradd --create-home --uid 1000 --shell /bin/bash briq
|
||||
# installo le dipendenze che servono anche a runtime
|
||||
RUN apt-get update\
|
||||
&& apt-get install -y libpq-dev nginx curl bash\
|
||||
gettext mosquitto-clients libjpeg-dev postgresql-client-13 \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf /var/cache/apt/archives
|
||||
RUN mkdir -p /django /django_static /var/lib/nginx /vue /logs /home/briq/.cache/pypoetry && \
|
||||
touch /nginx.conf /maybe_ssl.conf /full_chain.pem /poetry_location && \
|
||||
chown -R briq:briq /var/lib/nginx /django /vue /django_static /nginx.conf /logs /maybe_ssl.conf /full_chain.pem /poetry_location /home/briq/.cache/pypoetry
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
USER briq
|
||||
RUN curl -sSL https://install.python-poetry.org | python3 -\
|
||||
&& echo "/home/briq/.local/bin/poetry" > /poetry_location
|
||||
|
||||
USER root
|
||||
RUN ln -s "$(cat /poetry_location)" /usr/bin/ && rm /poetry_location
|
||||
|
||||
|
||||
FROM sistema_base as sistema_build
|
||||
USER root
|
||||
RUN apt-get update\
|
||||
&& apt-get -y install npm --no-install-recommends\
|
||||
&& npm install -g javascript-obfuscator\
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf /var/cache/apt/archives
|
||||
|
||||
FROM sistema_build as sistema_build_dipendenze_python
|
||||
USER root
|
||||
RUN apt-get update\
|
||||
&& apt-get -y install gcc build-essential git libpython3-dev ccache
|
||||
|
||||
COPY --chown=briq:briq /django/pyproject.toml /django/poetry.lock /django/
|
||||
USER briq
|
||||
RUN --mount=target=/home/briq/.cache/pypoetry/cache,type=cache,uid=1000,gid=1000 cd /django && poetry install --no-dev
|
||||
USER root
|
||||
RUN bash -c "set -e; find / -iname '__pycache__' -prune -exec rm -rf '{}' \; \
|
||||
&& find / -iname '*.pyc' -delete"
|
||||
|
||||
|
||||
FROM sistema_base AS sistema_base_con_python
|
||||
USER briq:briq
|
||||
COPY --from=sistema_build_dipendenze_python /home/briq/.cache/pypoetry/ /home/briq/.cache/pypoetry/
|
||||
|
||||
|
||||
FROM sistema_build_dipendenze_python as sistema_build_python
|
||||
USER briq:briq
|
||||
WORKDIR /django
|
||||
RUN --mount=target=/home/briq/.cache/pypoetry/cache,type=cache,uid=1000,gid=1000 poetry install
|
||||
USER root
|
||||
COPY --chown=briq:briq django /django/
|
||||
USER briq:briq
|
||||
RUN --mount=target=/ccache,type=cache,uid=1000,gid=1000 env CCACHE_DIR=/ccache bash compila_apps.sh
|
||||
USER root
|
||||
|
||||
|
||||
FROM sistema_build AS sistema_build_js
|
||||
USER root
|
||||
COPY --chown=briq:briq vue/package.json vue/package-lock.json /vue/
|
||||
USER briq:briq
|
||||
WORKDIR /vue
|
||||
RUN npm install
|
||||
COPY /vue/ /vue/
|
||||
#COPY docker/babel.config.js /vue/babel.config.js
|
||||
RUN npm run build
|
||||
|
||||
|
||||
FROM sistema_base_con_python AS sistema_deploy
|
||||
USER briq:briq
|
||||
COPY --from=sistema_build_python /django_static/ /django_static/
|
||||
RUN true #vedi https://github.com/moby/moby/issues/37965
|
||||
COPY --from=sistema_build_python /django /django/
|
||||
RUN true
|
||||
COPY --from=sistema_build_python /django/pyproject.toml /django/
|
||||
RUN true
|
||||
COPY --from=sistema_build_js /vue/dist /vue/dist
|
||||
WORKDIR /
|
||||
ARG GIT_COMMIT_SHA=N/A
|
||||
ARG GIT_COMMIT_REF=N/A
|
||||
ARG GIT_CLEAN=true
|
||||
ARG GIT_COMMIT_DATE=ContinuousIntegration
|
||||
USER root
|
||||
RUN echo "{\"shash\": \"${GIT_COMMIT_SHA}\", \"lhash\": \"${GIT_COMMIT_SHA}\", \"commsdate\": \"${GIT_COMMIT_DATE}\", \"refnames\": \"${GIT_COMMIT_REF}\", \"clean\":\"${GIT_CLEAN}\"}" > /git_info
|
||||
COPY --chown=briq:briq docker/test_and_build/run_in_docker.sh docker/test_and_build/startstop_utils.sh docker/test_and_build/nginx.conf.tpl /
|
||||
RUN cp -f /git_info /vue/dist/ver.json
|
||||
RUN chown briq:briq /vue/dist/ver.json
|
||||
USER briq:briq
|
||||
CMD /run_in_docker.sh
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
node {
|
||||
stage('Checkout') {
|
||||
checkout scm
|
||||
}
|
||||
if ("${env.BRANCH_NAME}".startsWith('my-')) {
|
||||
print "è un branch da non compilare"
|
||||
currentBuild.result = 'SUCCESS'
|
||||
return
|
||||
}
|
||||
stage('Extract Git Info') {
|
||||
commitId = sh(returnStdout: true, script: 'git --no-pager log -1 --pretty=format:"%H"')
|
||||
commitDate = sh(returnStdout: true, script: 'git --no-pager log -1 --pretty=format:"%ai"')
|
||||
refs = sh(returnStdout: true, script: 'git --no-pager log -1 --pretty=format:"%d"')
|
||||
}
|
||||
stage('Build docker') {
|
||||
withEnv(['DOCKER_BUILDKIT=1']) {
|
||||
customImage = docker.build("briq/sangue:${env.BUILD_ID}", "--build-arg GIT_COMMIT_SHA=\"${commitId}\" --build-arg GIT_COMMIT_DATE=\"${commitDate}\" --build-arg GIT_COMMIT_REF=\"${refs}\" .")
|
||||
}
|
||||
}
|
||||
stage('Push to registry') {
|
||||
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||
docker.withRegistry('https://docker.briq.it', 'briq-docker-cred') {
|
||||
customImage.push("${env.BRANCH_NAME}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="{% url 'admin:index' %}">{% translate 'Home' %}</a></div>{% endblock %}
|
||||
|
||||
{% block nav-sidebar %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<p><a href="{% url 'admin:index' %}">{% translate 'Log in again' %}</a></p>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash --
|
||||
set -e
|
||||
IFS=$'\n'
|
||||
mkdir -p /django_static
|
||||
find /django \( -iname '*.js' -and ! -path '*/vendor/*' \) -prune -exec bash -c 'set -x; mv "$1" "$1.orig.js" && javascript-obfuscator "$1.orig.js" -o "$1" && rm "$1.orig.js"' '' '{}' \;
|
||||
env DEBUG_TOOLBAR=true poetry run python manage.py collectstatic --no-input
|
||||
for DJANGO_APP in $(poetry run python manage.py shell < get_django_apps.py); do
|
||||
echo -ne "Compilo app $DJANGO_APP..."
|
||||
rm -rf "${DJANGO_APP}/migrations"
|
||||
poetry run python -m nuitka --module "${DJANGO_APP}" --include-package="${DJANGO_APP}"
|
||||
rm -rf "${DJANGO_APP}.build"
|
||||
pushd "${DJANGO_APP}" || exit 1
|
||||
find . -iname '*.py*' -delete;
|
||||
popd
|
||||
done
|
||||
find . -iname '__pycache__' -prune -exec rm -rf '{}' \;
|
||||
find . -iname '*.pyc' -delete
|
||||
find . -iname 'compila_apps.sh' -delete
|
||||
find . -iname 'sqldes2django.py' -delete
|
||||
find . -iname 'modello_*.xml' -delete
|
||||
#poetry cache:clear --all -n ..
|
||||
#poetry install --no-dev && rm -rf /root/.cache/pypoetry/cache/
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Nov 27 17:59:25 2019
|
||||
|
||||
@author: Guido Longoni - guidolongoni@gmail.com
|
||||
"""
|
||||
import os
|
||||
from django.conf import settings
|
||||
|
||||
out = set()
|
||||
for x in settings.INSTALLED_APPS:
|
||||
stem = x.split('.')[0]
|
||||
if stem in next(d for _, d, _ in os.walk('.')):
|
||||
out.add(stem)
|
||||
print('\n'.join(out))
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Nov 27 17:59:25 2019
|
||||
|
||||
@author: Guido Longoni - guidolongoni@gmail.com
|
||||
"""
|
||||
import os
|
||||
from django.conf import settings
|
||||
|
||||
print(settings.ASGI_APPLICATION.split('.')[0])
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
from django.db import connection
|
||||
import logging
|
||||
import sys
|
||||
from manage import main
|
||||
|
||||
|
||||
logger = logging.getLogger("locking_manage")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)-24s|%(levelname)-7s|%(name)-4s:%(lineno)-2d: %(message)s')
|
||||
console_h = logging.StreamHandler(sys.stderr)
|
||||
console_h.setLevel(logging.DEBUG)
|
||||
console_h.setFormatter(formatter)
|
||||
logger.addHandler(console_h)
|
||||
with connection.cursor() as c:
|
||||
# acquisisco un lock con una chiave che è unica per questa applicazione
|
||||
logger.info("Acquisizione advisory lock:")
|
||||
c.execute("select pg_advisory_lock(132306982255);")
|
||||
logger.info("advisory lock acquisito.")
|
||||
logger.info("Eseguo manage.py con argomenti %s", sys.argv)
|
||||
main()
|
||||
logger.info("Rilascio advisory lock")
|
||||
# il lock viene rilasciato automaticamente
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sangue_django.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,36 @@
|
|||
[tool.poetry]
|
||||
name = "sangue"
|
||||
version = "0.1.0"
|
||||
description = "Gestione Briq"
|
||||
authors = ["Guido Longoni <guido.longoni@briq.it>"]
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.10"
|
||||
django = "^4.1.6"
|
||||
python-dotenv = "^0.21.1"
|
||||
djangorestframework = "^3.14.0"
|
||||
django-cors-headers = "^3.13.0"
|
||||
drf-yasg = "^1.21.4"
|
||||
django-import-export = "^3.0.2"
|
||||
psycopg2 = "^2.9.5"
|
||||
channels = "^4.0.0"
|
||||
uvicorn = {extras = ["standard"], version = "^0.20.0"}
|
||||
channels-redis = "^4.0.0"
|
||||
django-ordered-model = "^3.6"
|
||||
django-auto-prefetching = "^0.2.12"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
nuitka = "^1.4.4"
|
||||
ordered-set = "^4.1.0"
|
||||
autopep8 = "^2.0.1"
|
||||
pylint = "^2.16.1"
|
||||
rope = "^1.7.0"
|
||||
django-extensions = "^3.2.1"
|
||||
docopt = "^0.6.2"
|
||||
lark = "^1.1.5"
|
||||
django-debug-toolbar = "^3.8.1"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
from import_export.admin import ImportExportModelAdmin
|
||||
from django.contrib import admin
|
||||
# from django.core.cache import cache
|
||||
# from django.core.paginator import Paginator
|
||||
from . import models
|
||||
from . import resources
|
||||
|
||||
|
||||
# # Modified version of a GIST I found in a SO thread
|
||||
# # cfr. http://masnun.rocks/2017/03/20/django-admin-expensive-count-all-queries/
|
||||
# class CachingPaginator(Paginator):
|
||||
# def _get_count(self):
|
||||
# if not hasattr(self, "_count"):
|
||||
# self._count = None
|
||||
# if self._count is None:
|
||||
# try:
|
||||
# key = "adm:{0}:count".format(hash(self.object_list.query.__str__()))
|
||||
# self._count = cache.get(key, -1)
|
||||
# if self._count == -1:
|
||||
# self._count = super().count
|
||||
# cache.set(key, self._count, 60)
|
||||
# except:
|
||||
# self._count = len(self.object_list)
|
||||
# return self._count
|
||||
# count = property(_get_count)
|
||||
|
||||
# # Main reusable Admin class for only viewing
|
||||
# class ViewAdminMixin(admin.ModelAdmin):
|
||||
# def has_add_permission(self, request):
|
||||
# return False
|
||||
#
|
||||
# def has_change_permission(self, request, obj=None):
|
||||
# return False
|
||||
#
|
||||
# def has_delete_permission(self, request, obj=None):
|
||||
# return False
|
||||
|
||||
# --------------- FINE PREFISSO TEMPLATE ---------------
|
||||
raise Exception('Fai girare sqldes2django oppure elimina questa eccezione.')
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import pathlib
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class SangueAppConfig(AppConfig):
|
||||
name = 'sangue_app'
|
||||
verbose_name = 'Sangue'
|
||||
path = pathlib.Path(__file__).parent
|
||||
|
||||
def ready(self):
|
||||
from . import signals
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
import json
|
||||
from channels.generic.websocket import WebsocketConsumer
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
|
||||
class WsConsumer(WebsocketConsumer):
|
||||
def connect(self):
|
||||
self.accept()
|
||||
print("accept ws connection")
|
||||
|
||||
def disconnect(self, close_code):
|
||||
print("ws disconnection")
|
||||
|
||||
def receive(self, text_data):
|
||||
text_data_json = json.loads(text_data)
|
||||
print("ws receive", text_data_json)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,4 @@
|
|||
from django.db import models
|
||||
|
||||
# --------------- FINE PREFISSO TEMPLATE ---------------
|
||||
raise Exception('Fai girare sqldes2django oppure elimina questa eccezione.')
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from import_export import resources
|
||||
from . import models
|
||||
|
||||
# --------------- FINE PREFISSO TEMPLATE ---------------
|
||||
raise Exception('Fai girare sqldes2django oppure elimina questa eccezione.')
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from rest_framework import serializers
|
||||
from . import models
|
||||
|
||||
# --------------- FINE PREFISSO TEMPLATE ---------------
|
||||
raise Exception('Fai girare sqldes2django oppure elimina questa eccezione.')
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete
|
||||
from django.dispatch import receiver
|
||||
from . import models
|
||||
|
||||
# @receiver(pre_save, sender=models.ExampleModel)
|
||||
# def example_callback(sender, instance, created=False, **kwargs):
|
||||
# if kwargs['raw'] or created:
|
||||
# return
|
||||
|
|
@ -0,0 +1,480 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sqldes2django.
|
||||
|
||||
Usage:
|
||||
sqldes2django.py write [--tgt-dir=<tgt-dir>] [--unmanaged=<unmanaged-name>] [--models-file=<models-file>] [--serializers-file=<serializers-file>] [--views-file=<views-file>] [--urls-file=<urls-file>] [--admin-file=<admin-file>] [--resources-file=<resources-file>] [--no-format] [--xml=<xml-path>]
|
||||
sqldes2django.py (-h | --help)
|
||||
sqldes2django.py (--version)
|
||||
|
||||
|
||||
Options:
|
||||
--tgt-dir=<tgt-dir> Directory di output [default: .].
|
||||
--xml=<xml-path> Directory di output [default: modello_database.xml].
|
||||
--models-file=<models-file> Nome del file dei modelli [default: <tgt-dir>/models.py].
|
||||
--serializers-file=<serializers-file> Nome del file dei serializers [default: <tgt-dir>/serializers.py].
|
||||
--views-file=<views-file> Nome del file delle views [default: <tgt-dir>/views.py].
|
||||
--urls-file=<urls-file> Nome del file degli url [default: <tgt-dir>/urls.py].
|
||||
--admin-file=<admin-file> Nome del file dell'admin [default: <tgt-dir>/admin.py].
|
||||
--resources-file=<resources-file> Nome del file delle resources [default: <tgt-dir>/resources.py].
|
||||
--no-format Non formattare l'output con autopep8.
|
||||
--unmanaged=<unmanaged-name> Crea modelli unmanaged (senza migrazioni): supporta pk e fk multiple, setta database=<unmanaged-name>
|
||||
--version Show version.
|
||||
-h --help Show this screen.
|
||||
"""
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import defaultdict
|
||||
import lark
|
||||
import os
|
||||
import sys
|
||||
import autopep8
|
||||
import re
|
||||
from docopt import docopt
|
||||
"""
|
||||
Created on Thu Feb 28 15:28:17 2019
|
||||
|
||||
@author: guido
|
||||
"""
|
||||
# TODO: Validare nomi per uso con Django
|
||||
# TODO: Trattare le chiavi primarie manuali e le chiavi primarie composite
|
||||
# TODO: Aggiungere tipi mancanti alla mappa
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
arguments = docopt(__doc__, version='Sqldes2django 0.1')
|
||||
for arg in arguments:
|
||||
if isinstance(arguments[arg], str):
|
||||
arguments[arg] = arguments[arg].replace("<tgt-dir>",
|
||||
arguments['--tgt-dir'])
|
||||
|
||||
tgtdir = arguments['--tgt-dir']
|
||||
|
||||
unmanaged = False
|
||||
if arguments['--unmanaged']:
|
||||
unmanaged = True
|
||||
nome_db = arguments['--unmanaged']
|
||||
print(arguments)
|
||||
|
||||
tgtfil = {x: arguments["--" + x + "-file"]
|
||||
for x in ('models', 'admin', 'serializers', 'views', 'urls', 'resources',)}
|
||||
|
||||
sql_type_grammar = lark.Lark(r"""
|
||||
%import common.ESCAPED_STRING
|
||||
%import common.SIGNED_NUMBER
|
||||
%import common.WS
|
||||
%import common.CNAME
|
||||
%ignore WS
|
||||
|
||||
tipo: costruttore | costruttore "(" [arg ("," arg)* ] ")"
|
||||
?costruttore: CNAME
|
||||
?arg: val | keyword_argument
|
||||
val: SIGNED_NUMBER | ESCAPED_STRING
|
||||
keyword_argument: CNAME "=" val""",
|
||||
parser="lalr",
|
||||
start="tipo") # TODO: leggere lo standard vero sql
|
||||
|
||||
def tutti_parametri(stringa_orig):
|
||||
params = sql_type_grammar.parse(stringa_orig)
|
||||
parametri = params.children[1:]
|
||||
posizionali = []
|
||||
keyword_args = {}
|
||||
trovato_kw = False
|
||||
for x in parametri:
|
||||
if x.data == "val":
|
||||
assert not trovato_kw, f"Argomento posizionale non può seguire keyword argument in '{stringa_orig}'"
|
||||
posizionali.append(x.children[0].value)
|
||||
if x.data == "keyword_argument":
|
||||
trovato_kw = True
|
||||
keyword_args[x.children[0].value] = x.children[1].children[0].value
|
||||
return {"costruttore": params.children[0].value, "posizionali": posizionali, "keyword_args": keyword_args, "stringa": stringa_orig}
|
||||
|
||||
def get_tipo_mappato(parsato):
|
||||
tipodato = parsato['costruttore'].upper()
|
||||
return mappa_tipi[tipodato]
|
||||
|
||||
def is_parametrico(parsato):
|
||||
return len(parsato["posizionali"]) > 0 or len(parsato["keyword_args"]) > 0
|
||||
|
||||
def get_parametro(parametri, positional=None, keyword=None):
|
||||
if keyword is not None and keyword in parametri['keyword_args']:
|
||||
val = parametri['keyword_args'][keyword]
|
||||
del parametri['keyword_args'][keyword]
|
||||
return val
|
||||
if positional is not None:
|
||||
try:
|
||||
return parametri['posizionali'][positional]
|
||||
except IndexError as e:
|
||||
raise Exception(
|
||||
f"Richiesti almeno {positional + 1} argomenti posizionali, trovati {len(parametri['posizionali'])} in {paremtri['stringa']}") from e
|
||||
raise Exception("Occorre specificare positional o keyword")
|
||||
|
||||
fine_prefisso_RE = re.compile(r'# +-+ +FINE PREFISSO TEMPLATE +-+')
|
||||
def leggi_prefisso(nome_modulo):
|
||||
tmpl_prefisso = []
|
||||
with open(tgtfil[nome_modulo]) as fp:
|
||||
for l in fp.readlines():
|
||||
tmpl_prefisso.append(l)
|
||||
if fine_prefisso_RE.search(l):
|
||||
break
|
||||
return ''.join(tmpl_prefisso)
|
||||
|
||||
|
||||
multifkimport = "from compositefk.fields import CompositeForeignKey # Installa django-composite-foreignkey"
|
||||
multipkmodel = """
|
||||
class MultiPkModel(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
def save(self, *args, **kwargs):
|
||||
raise NotImplementedError("È un MultiPkModel")
|
||||
# TODO
|
||||
def __hash__(self):
|
||||
attributi_chiave_multipla = self._meta.unique_together[0]
|
||||
parti = []
|
||||
for x in attributi_chiave_multipla:
|
||||
try:
|
||||
parte = getattr(self, x + '_id') # se oltre che parte di primary è foreign, non vogliamo fetchare tutto l'oggetto
|
||||
except AttributeError:
|
||||
parte = getattr(self, x)
|
||||
parti.append(parte)
|
||||
return hash(tuple(parti))
|
||||
|
||||
|
||||
|
||||
class MultiPkQuerySet(models.QuerySet):
|
||||
def get(self, *args, **kwargs):
|
||||
attributi_chiave_multipla = self.model._meta.unique_together[0]
|
||||
if any(key not in kwargs for key in attributi_chiave_multipla):
|
||||
raise Exception("È un MultiPkModel. Fornire anche i seguenti keywoard arguments: " + str(set(attributi_chiave_multipla) - set(kwargs.keys())))
|
||||
filtro = {k : kwargs[k] for k in attributi_chiave_multipla}
|
||||
risultati = list(self.filter(**filtro).all())
|
||||
if len(risultati) == 1:
|
||||
return risultati[0]
|
||||
elif len(risultati) == 0:
|
||||
raise self.model.DoesNotExist(self.model._meta.object_name + " with " + str(filtro))
|
||||
else:
|
||||
raise Exception("MultiPkQuerySet.get: righe multiple con " + str(filtro))
|
||||
|
||||
|
||||
class MultiPkManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return MultiPkQuerySet(self.model, using=self._db)
|
||||
"""
|
||||
|
||||
tmpl_models_prefisso = leggi_prefisso('models')
|
||||
tmpl_models = '''
|
||||
{multifkimport}
|
||||
{multipkmodel}
|
||||
|
||||
{corpo}
|
||||
'''
|
||||
|
||||
tmpl_model_class = '''
|
||||
class {nometab}({classe_model}):{db_name}
|
||||
class Meta:
|
||||
verbose_name = '{nometab_lower}'
|
||||
verbose_name_plural = '{nometab_lower}'
|
||||
{is_managed}{unique_together}
|
||||
def __str__(self):
|
||||
return f"{nometab} ({chiavi})"
|
||||
|
||||
{righetxt}
|
||||
'''
|
||||
tmpl_riga = '''{nomeriga} = models.{tiporiga}({opzioniriga})'''
|
||||
tmpl_chiave_fk = '''{nomeriga} = models.ForeignKey('{altratab}', {opzioniriga})'''
|
||||
|
||||
tmpl_admin_prefisso = leggi_prefisso('admin')
|
||||
tmpl_admin = '''
|
||||
{corpo}
|
||||
'''
|
||||
|
||||
tmpl_admin_class = '''
|
||||
@admin.register(models.{nometab})
|
||||
class {nometab}Admin(ImportExportModelAdmin):
|
||||
# resource = resources.{nometab}Resource
|
||||
# list_per_page = 15
|
||||
# paginator = CachingPaginator
|
||||
# show_full_result_count = False
|
||||
pass
|
||||
'''
|
||||
|
||||
|
||||
tmpl_serializers_prefisso = leggi_prefisso('serializers')
|
||||
tmpl_serializers = '''
|
||||
{corpo}
|
||||
'''
|
||||
|
||||
tmpl_serializer_class = '''
|
||||
class {nometab}Serializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = models.{nometab}
|
||||
fields = ('{campi}')
|
||||
'''
|
||||
|
||||
tmpl_views_prefisso = leggi_prefisso('views')
|
||||
tmpl_views = '''
|
||||
{corpo}
|
||||
'''
|
||||
|
||||
tmpl_view_class = '''
|
||||
class {nometab}_View(viewsets.ModelViewSet):
|
||||
# authentication_classes = [BasicAuthentication, SessionAuthentication, TokenAuthentication]
|
||||
# permission_classes = [DjangoModelPermissions]
|
||||
|
||||
queryset = models.{nometab}.objects.all()
|
||||
serializer_class = serializers.{nometab}Serializer
|
||||
'''
|
||||
|
||||
tmpl_urls_prefisso = leggi_prefisso('urls')
|
||||
tmpl_urls = '''
|
||||
{urls}
|
||||
|
||||
urlpatterns += router.urls
|
||||
'''
|
||||
|
||||
tmpl_url_route = '''router.register(r'{nometaburl}', views.{nometab}_View)'''
|
||||
tmpl_resources_prefisso = leggi_prefisso('resources')
|
||||
tmpl_resources = '''
|
||||
{corpo}
|
||||
'''
|
||||
|
||||
tmpl_resource_class = '''
|
||||
class {nometab}Resource(resources.ModelResource):
|
||||
class Meta:
|
||||
model = models.{nometab}
|
||||
'''
|
||||
|
||||
mappa_tipi = {
|
||||
'INTEGER': 'IntegerField',
|
||||
'INT': 'IntegerField',
|
||||
'NUMERIC': 'DecimalField',
|
||||
'DECIMAL': 'DecimalField',
|
||||
'SMALLINT': 'SmallIntegerField',
|
||||
'FLOAT': 'FloatField',
|
||||
'TEXT': 'TextField',
|
||||
'VARCHAR': 'CharField',
|
||||
'CHAR': 'CharField',
|
||||
'MEDIUMTEXT': 'TextField',
|
||||
'DATE': 'DateField',
|
||||
'TIME': 'TimeField',
|
||||
'DATETIME': 'DateTimeField',
|
||||
'TIMESTAMP': 'DateTimeField',
|
||||
'DECIMAL': 'DecimalField',
|
||||
'BIT': 'BooleanField',
|
||||
'BINARY': 'BooleanField',
|
||||
'JSONB': 'JSONField'
|
||||
}
|
||||
|
||||
tabelle = list(ET.ElementTree(file=arguments['--xml'])
|
||||
.findall('.//table'))
|
||||
tabelle2 = (ET.ElementTree(file=arguments['--xml'])
|
||||
.findall('.//table'))
|
||||
|
||||
models = []
|
||||
admin = []
|
||||
serializers = []
|
||||
views = []
|
||||
urls = []
|
||||
resources = []
|
||||
nomi_tabelle = []
|
||||
any_multiple_fk = False
|
||||
any_multiple_pk = False
|
||||
|
||||
tabelle_multi_pk = set()
|
||||
for t in tabelle2:
|
||||
nome = t.get('name')
|
||||
chiave = t.findall('.//key/part')
|
||||
if len(chiave) > 1:
|
||||
tabelle_multi_pk.add(nome)
|
||||
any_multiple_pk = True
|
||||
|
||||
renames = {}
|
||||
is_fk_and_pk = set()
|
||||
for t in tabelle:
|
||||
righe = t.findall('.//row')
|
||||
n_tab = t.get('name')
|
||||
chiave = t.findall('.//key/part')
|
||||
|
||||
# prima decido i rename
|
||||
for r in righe:
|
||||
fk = r.find('relation')
|
||||
n = r.get('name')
|
||||
is_simple_fk = fk is not None and fk.get(
|
||||
'table') not in tabelle_multi_pk
|
||||
if is_simple_fk and unmanaged:
|
||||
# renames[(n_tab, n)] = 'fk_' + n # poi ci pensiamo
|
||||
renames[(n_tab, n)] = n
|
||||
else:
|
||||
renames[(n_tab, n)] = n
|
||||
if is_simple_fk and n in [x.text for x in chiave]:
|
||||
is_fk_and_pk.add((n_tab, n))
|
||||
|
||||
for t in tabelle:
|
||||
rec_tabella = dict()
|
||||
rec_serializers = dict()
|
||||
rec_tabella['nometab'] = t.get('name')
|
||||
rec_tabella['nometab_lower'] = rec_tabella['nometab'].lower()
|
||||
n_tab = t.get('name')
|
||||
rec_tabella['classe_model'] = 'models.Model'
|
||||
nomi_tabelle.append(rec_tabella['nometab'])
|
||||
rec_serializers['nometab'] = t.get('name')
|
||||
rec_tabella['is_managed'] = ''
|
||||
rec_tabella['db_name'] = ''
|
||||
rec_tabella['unique_together'] = ''
|
||||
if unmanaged:
|
||||
rec_tabella['is_managed'] = f'managed = False\n db_table = "{rec_tabella["nometab"]}"\n '
|
||||
rec_tabella['db_name'] = f'\n database = "{nome_db}"'
|
||||
righe = t.findall('.//row')
|
||||
chiave = t.findall('.//key/part')
|
||||
pk_singola = None
|
||||
righetxt = []
|
||||
if len(chiave) == 1:
|
||||
if not unmanaged:
|
||||
righe = [r for r in righe if r.get('name') != chiave[0].text]
|
||||
pk_singola = chiave[0].text
|
||||
if unmanaged:
|
||||
rec_tabella['chiavi'] = renames[(n_tab, pk_singola)] + ': {self.' + (renames[(n_tab, pk_singola)]+'_id' if (
|
||||
n_tab, pk_singola) in is_fk_and_pk else renames[(n_tab, pk_singola)]) + '}'
|
||||
else:
|
||||
rec_tabella['chiavi'] = "id: {self.id}"
|
||||
elif len(chiave) > 1:
|
||||
multi_pk = True
|
||||
rec_tabella['classe_model'] = "MultiPkModel"
|
||||
nomi = ", ".join(f"'{renames[(n_tab, x.text)]}'" for x in chiave)
|
||||
rec_tabella['unique_together'] = f"unique_together=[({nomi})]"
|
||||
if unmanaged:
|
||||
rec_tabella['chiavi'] = ", ".join(renames[(n_tab, x.text)] + ': {self.' + (renames[(n_tab, x.text)]+'_id' if (
|
||||
n_tab, x.text) in is_fk_and_pk else renames[(n_tab, x.text)]) + '}' for x in chiave)
|
||||
else:
|
||||
rec_tabella['chiavi'] = "non puoi fare una pk multipla in django"
|
||||
righetxt.append('objects = MultiPkManager()')
|
||||
righeserializerstxt = []
|
||||
# TODO: implementare eventuali tipi multiparametro e con spazi
|
||||
|
||||
datoparametricoRE = re.compile(
|
||||
r'(?P<tipo>[^(]*)\((?P<lunghezza>[^)]*)\)')
|
||||
fk_composite = defaultdict(list)
|
||||
is_first = True
|
||||
for r in righe:
|
||||
rec_riga = dict()
|
||||
rec_chiave_fk = dict()
|
||||
rec_chiave_fk['opzioniriga'] = dict()
|
||||
rec_riga['opzioniriga'] = dict()
|
||||
comm = r.find('comment')
|
||||
if comm is not None and 'django_ignore' in comm.text:
|
||||
continue
|
||||
riga_nullable = r.get('null', "1") == "1"
|
||||
if is_first and unmanaged and rec_tabella['nometab'] in tabelle_multi_pk:
|
||||
if not riga_nullable:
|
||||
# il primo field diventa chiave primaria fittizia. Attenzione a non usarlo davvero!
|
||||
righetxt.append("")
|
||||
righetxt.append(
|
||||
"# chiave primaria fittizia. Attenzione a non usarla! Fa fede unique_together.")
|
||||
rec_riga['opzioniriga']['primary_key'] = True
|
||||
rec_chiave_fk['opzioniriga']['primary_key'] = True
|
||||
is_first = False
|
||||
fk = r.find('relation')
|
||||
is_simple_fk = fk is not None and fk.get(
|
||||
'table') not in tabelle_multi_pk
|
||||
if is_simple_fk:
|
||||
rec_chiave_fk['nomeriga'] = renames[(n_tab, r.get('name'))]
|
||||
n_altra_tab = rec_chiave_fk['altratab'] = fk.get('table')
|
||||
rec_chiave_fk['altracol'] = renames[(
|
||||
n_altra_tab, fk.get('row'))]
|
||||
rec_chiave_fk['opzioniriga']['on_delete'] = 'models.CASCADE'
|
||||
rec_chiave_fk['opzioniriga']['null'] = riga_nullable
|
||||
rec_chiave_fk['opzioniriga']['blank'] = riga_nullable
|
||||
if unmanaged:
|
||||
rec_chiave_fk['opzioniriga']['to_field'] = f"'{rec_chiave_fk['altracol']}'"
|
||||
rec_chiave_fk['opzioniriga']['db_column'] = f"'{r.get('name')}'"
|
||||
rec_chiave_fk['opzioniriga']['related_name'] = (
|
||||
f""""{rec_tabella['nometab']}_da_{rec_chiave_fk['altratab']}_{rec_chiave_fk['nomeriga']}" """.strip())
|
||||
if not rec_chiave_fk['opzioniriga']['null']:
|
||||
del rec_chiave_fk['opzioniriga']['null']
|
||||
del rec_chiave_fk['opzioniriga']['blank']
|
||||
rec_chiave_fk['opzioniriga'] = ', '.join(
|
||||
f'{k}={v}' for k, v in rec_chiave_fk['opzioniriga'].items())
|
||||
righetxt.append(tmpl_chiave_fk.format(**rec_chiave_fk))
|
||||
else:
|
||||
rec_riga['opzioniriga']['null'] = riga_nullable
|
||||
rec_riga['opzioniriga']['blank'] = riga_nullable
|
||||
if fk is not None: # è composita
|
||||
tab_target = fk.get('table')
|
||||
fk_composite[tab_target].append({"campo": r.get('name'),
|
||||
"campo_tgt": renames[(tab_target, fk.get("row"))],
|
||||
"nullabile": rec_riga['opzioniriga']['null']})
|
||||
rec_riga['nomeriga'] = r.get('name')
|
||||
orig = tipodato = str(r.find('datatype').text)
|
||||
parsato = tutti_parametri(tipodato)
|
||||
#parametrico = datoparametricoRE.match(tipodato)
|
||||
parametrico = is_parametrico(parsato)
|
||||
# parametrico = tipo
|
||||
rec_riga['tiporiga'] = get_tipo_mappato(parsato)
|
||||
if parametrico:
|
||||
if rec_riga['tiporiga'] in ('CharField',):
|
||||
lunghezza = get_parametro(
|
||||
parsato, positional=0, keyword="max_length")
|
||||
rec_riga['opzioniriga']['max_length'] = int(lunghezza)
|
||||
elif rec_riga['tiporiga'] == "DecimalField":
|
||||
max_digits = get_parametro(
|
||||
parsato, positional=0, keyword="max_digits")
|
||||
decimal_places = get_parametro(
|
||||
parsato, positional=1, keyword="decimal_places")
|
||||
rec_riga['opzioniriga']['max_digits'] = int(max_digits)
|
||||
rec_riga['opzioniriga']['decimal_places'] = int(
|
||||
decimal_places)
|
||||
arg_avanzati = parsato["keyword_args"]
|
||||
for x in arg_avanzati:
|
||||
rec_riga['opzioniriga'][x] = arg_avanzati[x]
|
||||
elif unmanaged:
|
||||
if tipodato in ('CHAR', 'VARCHAR'):
|
||||
rec_riga['opzioniriga']['max_length'] = 1000000
|
||||
if r.get('name') == pk_singola:
|
||||
# chiave singola
|
||||
rec_riga['opzioniriga']['primary_key'] = True
|
||||
if not rec_riga['opzioniriga']['null']:
|
||||
del rec_riga['opzioniriga']['null']
|
||||
del rec_riga['opzioniriga']['blank']
|
||||
if rec_riga['tiporiga'] in ('CharField', 'TextField') and 'blank' in rec_riga['opzioniriga']:
|
||||
del rec_riga['opzioniriga']['blank']
|
||||
rec_riga['opzioniriga'] = ','.join(
|
||||
f'{k}={v}' for k, v in rec_riga['opzioniriga'].items())
|
||||
righetxt.append(tmpl_riga.format(**rec_riga))
|
||||
rec_riga_serializers = dict()
|
||||
rec_riga_serializers['nomecampo'] = r.get('name')
|
||||
righeserializerstxt.append(rec_riga_serializers['nomecampo'])
|
||||
for tgt in fk_composite:
|
||||
nullabile = any(x['nullabile'] for x in fk_composite[tgt])
|
||||
fk_fields = ",\n ".join(
|
||||
f"'{x['campo_tgt']}': '{x['campo']}'" for x in fk_composite[tgt])
|
||||
asd = f"fk_{tgt} = CompositeForeignKey('{tgt}', on_delete=models.CASCADE, null={nullabile}, to_fields=" + "{\n " + fk_fields + "\n })"
|
||||
righetxt.append(asd)
|
||||
any_multiple_fk = True
|
||||
rec_tabella['righetxt'] = '\n '.join(righetxt)
|
||||
rec_serializers['campi'] = "','".join(righeserializerstxt)
|
||||
models.append(tmpl_model_class.format(**rec_tabella))
|
||||
admin.append(tmpl_admin_class.format(**rec_tabella))
|
||||
serializers.append(tmpl_serializer_class.format(**rec_serializers))
|
||||
views.append(tmpl_view_class.format(nometab=rec_tabella['nometab']))
|
||||
urls.append(tmpl_url_route.format(
|
||||
nometaburl=rec_tabella['nometab'].lower(), nometab=rec_tabella['nometab']))
|
||||
resources.append(tmpl_resource_class.format(
|
||||
nometab=rec_tabella['nometab']))
|
||||
|
||||
models = tmpl_models_prefisso + tmpl_models.format(corpo='\n'.join(models),
|
||||
multipkmodel=multipkmodel if any_multiple_pk else "",
|
||||
multifkimport=multifkimport if any_multiple_fk else "")
|
||||
admin = tmpl_admin_prefisso + tmpl_admin.format(corpo='\n'.join(admin))
|
||||
serializers = tmpl_serializers_prefisso + tmpl_serializers.format(corpo='\n'.join(serializers))
|
||||
views = tmpl_views_prefisso + tmpl_views.format(corpo='\n'.join(views))
|
||||
urls = tmpl_urls_prefisso + tmpl_urls.format(urls='\n'.join(urls))
|
||||
resources = tmpl_resources_prefisso + tmpl_resources.format(corpo='\n'.join(resources))
|
||||
|
||||
for tgt_name, tgt_path in tgtfil.items():
|
||||
with open(tgt_path, 'w') as f:
|
||||
print(
|
||||
f"Writing {tgt_name} to {tgt_path}, autopep8: {not arguments['--no-format']}...")
|
||||
if arguments['--no-format']:
|
||||
f.write(globals()[tgt_name])
|
||||
else:
|
||||
f.write(autopep8.fix_code(globals()[tgt_name]))
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from rest_framework import routers
|
||||
from django.urls import include, path
|
||||
from . import views
|
||||
|
||||
app_name = "sangue_app"
|
||||
|
||||
urlpatterns = [
|
||||
# path('', views.index, name='index'),
|
||||
]
|
||||
router = routers.DefaultRouter()
|
||||
|
||||
# --------------- FINE PREFISSO TEMPLATE ---------------
|
||||
raise Exception('Fai girare sqldes2django oppure elimina questa eccezione.')
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from django.shortcuts import render, redirect
|
||||
from django.http import JsonResponse, HttpResponse
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
|
||||
from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated
|
||||
|
||||
from django_auto_prefetching import AutoPrefetchViewSetMixin
|
||||
from . import models
|
||||
from . import serializers
|
||||
|
||||
# def index(request):
|
||||
# return HttpResponse("Hello, %s!" % (request.user.username if request.user.is_authenticated else 'World'))
|
||||
|
||||
# --------------- FINE PREFISSO TEMPLATE ---------------
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
ASGI config for sangue_app project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
import django
|
||||
from channels.routing import get_default_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sangue_django.settings')
|
||||
django.setup()
|
||||
application = get_default_application()
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
from django.core.asgi import get_asgi_application
|
||||
from django.urls import path
|
||||
from sangue_app import consumers
|
||||
|
||||
application = ProtocolTypeRouter({
|
||||
# "websocket": URLRouter([path(r'ws/sangue_app', consumers.WsConsumer), ])
|
||||
"http": get_asgi_application(),
|
||||
})
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
"""
|
||||
Django settings for sangue_django project.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import find_dotenv, load_dotenv
|
||||
|
||||
load_dotenv(find_dotenv())
|
||||
|
||||
def tristate_env_flag(name):
|
||||
env_flag = os.getenv(name)
|
||||
if env_flag:
|
||||
globals()[name] = True if env_flag.strip().lower() in (
|
||||
'true', '1') else False
|
||||
|
||||
|
||||
|
||||
# ADMINS =
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
ASGI_APPLICATION = "sangue_django.routing.application"
|
||||
|
||||
# AUTHENTICATION_BACKENDS =
|
||||
|
||||
# AUTHLIB_OAUTH_CLIENTS =
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
# AUTH_USER_MODEL =
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# BOWER_COMPONENTS_ROOT =
|
||||
# BOWER_INSTALLED_APPS =
|
||||
# CACHES = {
|
||||
# "default": {
|
||||
# "BACKEND": "django_redis.cache.RedisCache",
|
||||
# "LOCATION": f"redis://{os.getenv('REDIS_HOST', 'Invalid redis host')}:{ os.getenv('REDIS_PORT', 'Invalid redis port')}/0",
|
||||
# "OPTIONS": {
|
||||
# "CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# CONTEXT =
|
||||
# CORS_ORIGIN_ALLOW_ALL =
|
||||
# CSP_FRAME_ANCESTORS =
|
||||
tristate_env_flag('CSRF_COOKIE_SECURE')
|
||||
MYHOSTNAME = os.getenv('MYHOSTNAME','http://imposta-MYHOSTNAME-nell-env.briq.it')
|
||||
CSRF_TRUSTED_ORIGINS = list({x for x in (os.getenv('CSRF_TRUSTED_ORIGINS','').split(',')+[MYHOSTNAME]) if x})
|
||||
# DATABASE_ROUTERS =
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': os.getenv('DB_NAME'),
|
||||
'USER': os.getenv('DB_USER'),
|
||||
'PASSWORD': os.getenv('DB_PASSWORD'),
|
||||
'HOST': os.getenv('DB_HOST'),
|
||||
'PORT': os.getenv('DB_PORT', "5432"),
|
||||
'CONN_MAX_AGE': 120,
|
||||
'TEST': {
|
||||
'NAME': os.getenv('DB_TEST_NAME')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG=True
|
||||
DEBUG_TOOLBAR=False
|
||||
tristate_env_flag('DEBUG')
|
||||
if DEBUG:
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels.layers.InMemoryChannelLayer"
|
||||
}
|
||||
}
|
||||
tristate_env_flag('DEBUG_TOOLBAR')
|
||||
else:
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [(os.getenv("REDIS_HOST", "Invalid redis host"), os.getenv("REDIS_PORT", "Invalid redis port"))],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
DEBUG_TOOLBAR = True if os.getenv('DEBUG_TOOLBAR') in (
|
||||
'True', 'true', '1', 'TRUE') else False
|
||||
|
||||
DEFAULT_AUTO_FIELD='django.db.models.AutoField'
|
||||
# DEPLOY_NAME =
|
||||
# DOCS_DIR =
|
||||
tristate_env_flag('ENABLE_MQTT')
|
||||
if any(x in sys.argv for x in ['test', 'dumpdata', 'sqlshell', 'loaddata', 'sqlflush']):
|
||||
ENABLE_MQTT = False
|
||||
|
||||
FIXTURE_DIRS = (
|
||||
'sangue_app/fixtures/',
|
||||
)
|
||||
|
||||
# IMPORT_EXPORT_USE_TRANSACTIONS
|
||||
|
||||
# Application definition
|
||||
INSTALLED_APPS = [
|
||||
'sangue_app.apps.SangueAppConfig',
|
||||
'rest_framework',
|
||||
# 'rest_framework.authtoken',
|
||||
'corsheaders',
|
||||
'drf_yasg',
|
||||
'import_export',
|
||||
'ordered_model',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'channels',
|
||||
# 'django_q',
|
||||
]
|
||||
if DEBUG_TOOLBAR:
|
||||
INSTALLED_APPS.append('debug_toolbar')
|
||||
if DEBUG:
|
||||
INSTALLED_APPS.append('django_extensions')
|
||||
|
||||
INTERNAL_IPS = [
|
||||
'127.0.0.1',
|
||||
]
|
||||
|
||||
LANGUAGE_CODE = 'it-it'
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'handlers': {
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
'root': {
|
||||
'handlers': ['console'],
|
||||
'level': 'WARNING',
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
'handlers': ['console'],
|
||||
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
|
||||
'propagate': False,
|
||||
},
|
||||
'django.db.backends': {
|
||||
'handlers': ['console'],
|
||||
'level': os.getenv('DJANGO_LOG_SQL', 'INFO'),
|
||||
'propagate': False,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# LOGIN_REDIRECT_URL =
|
||||
# LOGIN_URL =
|
||||
# MAIN_SITE_URL =
|
||||
# MANAGERS =
|
||||
|
||||
MEDIA_ROOT = os.getenv('MEDIA_ROOT')
|
||||
if MEDIA_ROOT:
|
||||
MEDIA_ROOT=MEDIA_ROOT.replace("$(pwd)", os.path.realpath(os.path.dirname(BASE_DIR)))
|
||||
|
||||
MEDIA_URL = os.getenv('MEDIA_URL')
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
if DEBUG_TOOLBAR:
|
||||
MIDDLEWARE = [
|
||||
'debug_toolbar.middleware.DebugToolbarMiddleware'] + MIDDLEWARE
|
||||
|
||||
if os.getenv('MQTT_HOST') and os.getenv('MQTT_PORT'):
|
||||
MQTT_ADDR = [os.getenv('MQTT_HOST'), int(os.getenv('MQTT_PORT'))]
|
||||
else:
|
||||
# stesso default che usano i programmi mosquitto_pub etc
|
||||
MQTT_ADDR = ["localhost", 1883]
|
||||
|
||||
# PROJECT_ROOT =
|
||||
|
||||
Q_CLUSTER = {
|
||||
'name': 'sangue',
|
||||
'workers': 1,
|
||||
'recycle': 10,
|
||||
'timeout': 7200,
|
||||
'retry': 8000,
|
||||
'max_attempts': 2,
|
||||
'compress': True,
|
||||
'save_limit': 250,
|
||||
'queue_limit': 100,
|
||||
'cpu_affinity': 1,
|
||||
'label': 'Django Q',
|
||||
'django_redis': 'default',
|
||||
'redis': {
|
||||
'host': os.getenv("REDIS_HOST", "Invalid redis host"),
|
||||
'port': os.getenv("REDIS_PORT", "Invalid redis port"),
|
||||
'db': 0, },
|
||||
}
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
],
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
'rest_framework.permissions.DjangoModelPermissions'
|
||||
]
|
||||
}
|
||||
|
||||
ROOT_URLCONF = 'sangue_django.urls'
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = (os.getenv('SECRET_KEY')
|
||||
if os.getenv('SECRET_KEY')
|
||||
else 'YCaAOqbBzWCYvNXfwbqntFvNhElemwclBzjWenTcpPYdYtcEOzAYfzkqnoqQYXKirtcDzRmwvpGCzuoRCkrMINUtWzEAonGKpcsZ')
|
||||
|
||||
# SECURE_HSTS_INCLUDE_SUBDOMAINS =
|
||||
# SECURE_HSTS_PRELOAD =
|
||||
# SECURE_HSTS_SECONDS =
|
||||
# SECURE_PROXY_SSL_HEADER =
|
||||
# SECURE_REFERRER_POLICY =
|
||||
tristate_env_flag('SECURE_SSL_REDIRECT')
|
||||
tristate_env_flag('SESSION_COOKIE_SECURE')
|
||||
|
||||
# SILENCED_SYSTEM_CHECKS = ['security.W019'] # Per la modale di Django Admin interface
|
||||
|
||||
# SILKY_ANALYZE_QUERIES =
|
||||
# SILKY_AUTHENTICATION =
|
||||
# SILKY_AUTHORISATION =
|
||||
# SILKY_INTERCEPT_PERCENT =
|
||||
# SILKY_MAX_RECORDED_REQUESTS =
|
||||
# SILKY_MAX_RESPONSE_BODY_SIZE =
|
||||
# SILKY_PERMISSIONS =
|
||||
# SITE_ID =
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
os.path.join(BASE_DIR, "static")
|
||||
]
|
||||
|
||||
# STATICFILES_FINDERS =
|
||||
|
||||
STATIC_ROOT = '../django_static/'
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(BASE_DIR, 'Templates')],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
# TEST_RUNNER =
|
||||
|
||||
TIME_ZONE = 'Europe/Rome'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
"""sangue_django URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/3.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.index, name='index'),
|
||||
path('login/', views.login_page, name='login'),
|
||||
path('logout/', views.logout_page, name='logout'),
|
||||
path('is_authenticated/', views.is_authenticated, name='is_authenticated'),
|
||||
path('admin/', admin.site.urls),
|
||||
path('sangue_app/', include('sangue_app.urls')),
|
||||
]
|
||||
if settings.DEBUG_TOOLBAR:
|
||||
import debug_toolbar
|
||||
urlpatterns = [path('__debug__/', include(debug_toolbar.urls))] + urlpatterns
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += static(settings.MEDIA_URL,
|
||||
document_root=settings.MEDIA_ROOT)
|
||||
|
||||
admin.site.index_title = 'Portale Sangue'
|
||||
admin.site.site_title = 'Portale Sangue'
|
||||
admin.site.site_header = 'Portale Sangue'
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
from django.shortcuts import render, redirect
|
||||
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.shortcuts import reverse
|
||||
import os
|
||||
import json
|
||||
|
||||
def login_page(request):
|
||||
if request.method == 'POST':
|
||||
redirect_to = request.POST.get('next', "/")
|
||||
redirect_to = (redirect_to
|
||||
if url_has_allowed_host_and_scheme(redirect_to, request.get_host())
|
||||
else "/endpointnonvalido")
|
||||
form = AuthenticationForm(request, request.POST)
|
||||
if form.is_valid():
|
||||
user = form.get_user()
|
||||
login(request, user)
|
||||
return redirect(redirect_to)
|
||||
else:
|
||||
print(form.errors.as_data())
|
||||
return render(request, "login.html", {'form': form})
|
||||
else:
|
||||
if request.user.is_authenticated:
|
||||
return redirect("/")
|
||||
form = AuthenticationForm()
|
||||
for x in form.fields:
|
||||
form.fields[x].widget.attrs.update({"class": "form-control"})
|
||||
redirect_to = request.GET.get('next', '/')
|
||||
redirect_to = (redirect_to
|
||||
if url_has_allowed_host_and_scheme(redirect_to, request.get_host())
|
||||
else '/')
|
||||
return render(request, "login.html", {'form': form, 'next': redirect_to})
|
||||
|
||||
|
||||
def logout_page(request):
|
||||
logout(request)
|
||||
return redirect("/")
|
||||
|
||||
def is_authenticated(request):
|
||||
if request.user.is_authenticated:
|
||||
out = {'user': request.user.username}
|
||||
else:
|
||||
out = {'user': None}
|
||||
return JsonResponse(out)
|
||||
|
||||
def index(request):
|
||||
return HttpResponseRedirect("/admin/")
|
||||
|
||||
def auto_config_frontend(request):
|
||||
auto_config_frontend = {
|
||||
#'api_url': reverse('sangue_app:api-root'),
|
||||
#'mqtt_url': "/mqtt/",
|
||||
'nome_deployment': os.getenv('DEPLOY_NAME',''),
|
||||
'context': os.getenv('CONTEXT','')
|
||||
}
|
||||
return HttpResponse("let auto_config_frontend = " + json.dumps(auto_config_frontend) + ";", content_type="text/javascript")
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
.inline-group .tabular tr.has_original td {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container {
|
||||
width: auto!important;
|
||||
min-width: 274px;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
{
|
||||
window.addEventListener("load", function() {
|
||||
const $ = django.jQuery;
|
||||
$(document).ready(function() {
|
||||
$('.vDateField').each(function() {
|
||||
this.setAttribute('type', 'date');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,17 @@
|
|||
version: "3.4"
|
||||
|
||||
services: {}
|
||||
# red:
|
||||
# image: "nodered/node-red"
|
||||
# volumes:
|
||||
# - "./red_data:/data:rw"
|
||||
# network_mode: host
|
||||
# env_file:
|
||||
# - env_docker
|
||||
# hivemq:
|
||||
# image: "docker.briq.it/public/hivemq-community-edition:master"
|
||||
# env_file:
|
||||
# - env_docker
|
||||
# volumes:
|
||||
# - ./hivemq.config.xml:/config.xml
|
||||
# network_mode: host
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
#! /bin/bash --
|
||||
set -e
|
||||
set -o pipefail
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
FROM="production"
|
||||
TO="none (export only)"
|
||||
EXIT_STATUS_ON_NO_TARGET=0
|
||||
SERVICE="sangue"
|
||||
|
||||
print_usage() {
|
||||
echo "copydb.sh [options]
|
||||
|
||||
Copy db.
|
||||
|
||||
Options:
|
||||
-f, --from source deployment name [default: $FROM]
|
||||
-t, --to destination deployment name [default: $TO]
|
||||
-s, --service service name [default: $SERVICE]
|
||||
-h, --help show this help
|
||||
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
set +e
|
||||
TEMP=$(getopt -o f:t:s:h --long from:,to:,service:,help -- "$@")
|
||||
GETOPT_STATUS=$?
|
||||
set -e
|
||||
|
||||
if [[ ! $GETOPT_STATUS = 0 ]]; then
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
eval set -- "$TEMP"
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-f|--from)
|
||||
FROM="$2"
|
||||
shift 2
|
||||
;;
|
||||
-t|--to)
|
||||
EXIT_STATUS_ON_NO_TARGET=6
|
||||
TO="$2"
|
||||
shift 2
|
||||
;;
|
||||
-s|--service)
|
||||
SERVICE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Internal error!" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
OUTNAME="/tmp/$SERVICE-$FROM-$(date '+%s')-XXXXXX.dump.zstd"
|
||||
OUTFILE="$(mktemp $OUTNAME)"
|
||||
|
||||
echo -e "from deployment:\t$FROM\nto deployment:\t$TO\ncompose service:\t$SERVICE\ntemporary file:\t$OUTFILE" | column -t -s "$(printf '\t')"
|
||||
read -p "Are you sure? (y/n) " -n 1 -r CONFIRM
|
||||
echo #a capo
|
||||
|
||||
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
|
||||
exit 3;
|
||||
fi
|
||||
|
||||
|
||||
|
||||
COMANDO_EXPORT='set -e; set -o pipefail; env PGPASSWORD="$DB_PASSWORD" pg_dump -h ${DB_HOST:-localhost} -p "${DB_PORT:-5432}" -U "${DB_USER:-postgres}" -c -Fc -Z0 "$DB_NAME"'
|
||||
B64_EXPORT=$(echo "$COMANDO_EXPORT" | base64)
|
||||
COMANDO_DROP='set -e; set -o pipefail; echo "DROP DATABASE IF EXISTS \"$DB_NAME\"; CREATE DATABASE \"$DB_NAME\" WITH OWNER=\"$DB_USER\"; " | env PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h ${DB_HOST:-localhost} -p "${DB_PORT:-5432}" -U "${DB_USER:-postgres}" postgres'
|
||||
COMANDO_IMPORT='set -e; set -o pipefail; env PGPASSWORD="$DB_PASSWORD" pg_restore --no-owner -h ${DB_HOST:-localhost} -p "${DB_PORT:-5432}" -U "${DB_USER:postgres}" -d "$DB_NAME" -Fc'
|
||||
B64_IMPORT=$(echo "$COMANDO_IMPORT" | base64)
|
||||
|
||||
echo "Exporting from $FROM..."
|
||||
echo "$B64_EXPORT" | (cd "$FROM" && docker-compose exec -T "$SERVICE" "/bin/bash" -c 'base64 -d | bash' | zstd )> "$OUTFILE"
|
||||
echo "Export from $FROM OK"
|
||||
if [[ ! -f "./$TO/docker-compose.yml" ]]; then
|
||||
if [[ ! $EXIT_STATUS_ON_NO_TARGET = 0 ]]; then
|
||||
echo "No target specified or found"
|
||||
fi
|
||||
exit $EXIT_STATUS_ON_NO_TARGET
|
||||
fi
|
||||
|
||||
MUST_RESTART=0
|
||||
IS_RUNNING=$(cd "$TO" && docker-compose ps -q "$SERVICE" | wc -l)
|
||||
if [[ $IS_RUNNING != "0" ]]; then
|
||||
MUST_RESTART=1
|
||||
echo -n "Stop $SERVICE in $TO... "
|
||||
(cd "$TO" && docker-compose stop -t3 "$SERVICE")
|
||||
echo "stopped."
|
||||
else
|
||||
echo "$TO is already stopped."
|
||||
fi
|
||||
|
||||
echo "Drop old/create new database in $TO..."
|
||||
DROP_OUTPUT=$(cd "$TO" && docker-compose run --rm -T "$SERVICE" "/bin/bash" -c "$COMANDO_DROP")
|
||||
echo "Drop/create database in $TO OK"
|
||||
|
||||
echo "Importing into $TO..."
|
||||
zstdcat "$OUTFILE" | (cd "$TO" && docker-compose run --rm -T "$SERVICE" "/bin/bash" -c "$COMANDO_IMPORT")
|
||||
echo "Import into $TO OK"
|
||||
if [[ $MUST_RESTART = "1" ]]; then
|
||||
echo -n "Starting $TO... "
|
||||
(cd "$TO" && docker-compose up -d)
|
||||
echo "started."
|
||||
fi
|
||||
exit 0
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/bash --
|
||||
set -e
|
||||
cd "$(dirname "$0")/production"
|
||||
source .env && PGPASSWORD="$DB_PASSWORD" pg_dump -h localhost -p "${DB_PORT:-5432}" -U "${DB_USER:postgres}" -c -Fp -Z0 "$DB_NAME" | zstd
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/bash --
|
||||
set -e
|
||||
cd "$(dirname "$0")/staging"
|
||||
source .env && PGPASSWORD="$DB_PASSWORD" pg_dump -h localhost -p "${DB_PORT:-5432}" -U "${DB_USER:postgres}" -c -Fp -Z0 "$DB_NAME" | zstd
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#! /bin/bash --
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
CD_TO="./staging/"
|
||||
PROJ="sangue"
|
||||
|
||||
cd-docker-compose() {
|
||||
(cd "$1" && docker-compose "${@:2}")
|
||||
}
|
||||
|
||||
log_images() {
|
||||
if cd-docker-compose "$CD_TO" exec "$PROJ" bash -c 'exit 0'; then
|
||||
{
|
||||
date | tr -d '\n';
|
||||
echo -ne "\t";
|
||||
cd-docker-compose "$CD_TO" exec "$PROJ" bash -c 'cat /git_info' | jq -r '.lhash' | tr -d '\n';
|
||||
echo -ne '\t';
|
||||
cd-docker-compose "$CD_TO" images -q "$PROJ" | tr -d '\n';
|
||||
echo -e "\t$1";
|
||||
} >> "$2"
|
||||
else
|
||||
{
|
||||
date | tr -d '\n';
|
||||
echo -ne "\timpossibile leggere il tag git\t";
|
||||
{ cd-docker-compose "$CD_TO" images -q "$PROJ" || echo "N/A"; } | tr -d '\n';
|
||||
echo -e "\t$1";
|
||||
} >> "$2"
|
||||
fi
|
||||
}
|
||||
log_images "prima" "log_deployment_staging.txt"
|
||||
cd-docker-compose "$CD_TO" pull
|
||||
PULL_OK=$?
|
||||
if [[ $PULL_OK -eq 0 && "$1" == "-d" ]]; then
|
||||
echo "Copia del database da produzione a staging..."
|
||||
if ./copydb.sh --from production --to staging; #l'utente può dire no
|
||||
then
|
||||
echo "Copia completata"
|
||||
else
|
||||
echo "Copia annullata"
|
||||
fi
|
||||
fi
|
||||
[[ $PULL_OK -eq 0 ]] && cd-docker-compose "$CD_TO" up -d
|
||||
echo "Master caricato su ambiente di TEST (Staging)"
|
||||
log_images "dopo" "log_deployment_staging.txt"
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#! /bin/bash --
|
||||
|
||||
set -e
|
||||
DOVE="$(mktemp)"
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
pushd production
|
||||
source .env && \
|
||||
PGPASSWORD="$DB_PASSWORD" \
|
||||
pg_dump \
|
||||
-h localhost \
|
||||
-p "${DB_PORT:-5432}" \
|
||||
-U "${DB_USER:postgres}" \
|
||||
-c -Fc -Z0 "$DB_NAME" > "$DOVE"
|
||||
popd
|
||||
pushd staging
|
||||
source .env && \
|
||||
echo 'DROP DATABASE "'"$DB_NAME"'";' | \
|
||||
psql \
|
||||
-h localhost \
|
||||
-p "${DB_PORT:-5432}" \
|
||||
-U "${DB_USER:postgres}"
|
||||
pg_restore \
|
||||
-h localhost \
|
||||
-p "${DB_PORT:-5432}" \
|
||||
-U "${DB_USER:postgres}" \
|
||||
-d "$DB_NAME" \
|
||||
--clean -Fc \
|
||||
-j $(cat /proc/cpuinfo | grep processor | wc -l) "$DOVE"
|
||||
popd
|
||||
rm -rf "$DOVE"
|
||||
docker-compose -f ./staging/docker-compose.yml up -dt1
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
COMPOSE_PROJECT_NAME=sangue_production
|
||||
|
||||
EVERYTHING_EXTERNAL_PORT=9090
|
||||
|
||||
SECRET_KEY=QDMneXbKaRPQpkOLkbpzoUxrEXQJfSCtmkFAXnMvMiBCQVAXdpohVphkzakVKBbFQxISUMKDMldMhSQwqcYOOmcmTsGzuNzUjNFA
|
||||
DEBUG=false
|
||||
|
||||
DOLLAR=$
|
||||
|
||||
# usato per nginx
|
||||
EVERYTHING_LISTEN=0.0.0.0
|
||||
EVERYTHING_PORT=9090
|
||||
|
||||
DJANGO_PORT=8000
|
||||
|
||||
# path assoluti:
|
||||
MEDIA_ROOT=/django_upload/
|
||||
|
||||
# url che deve coincidere in django e nginx
|
||||
MEDIA_URL=uploads/
|
||||
|
||||
|
||||
# Redis serve per i django channels
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
|
||||
# DJANGO DB
|
||||
DB_NAME=sangue
|
||||
DB_USER=sangue
|
||||
DB_PASSWORD=sangue
|
||||
DB_HOST=postgres_svc # se fisso, vedere yml di infrastruttura briq
|
||||
DB_TEST_NAME=sangue_test
|
||||
|
||||
# MQTT
|
||||
ENABLE_MQTT=false
|
||||
MQTT_HOST=hivemq_svc
|
||||
MQTT_WEBSOCKET_HOST=hivemq_svc
|
||||
|
||||
MQTT_PORT=1833
|
||||
MQTT_WEBSOCKET_PORT=1834
|
||||
|
||||
#MQTT_PORT=
|
||||
#MQTT_WEBSOCKET_PORT=
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
version: "3.5"
|
||||
|
||||
services:
|
||||
sangue:
|
||||
image: sangue:production
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./.django_uploads:/django_upload
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- sangue_prod_net
|
||||
- bq_infrastructure_net
|
||||
# - fixed_ip_host_net # Rete per accedere a servizi dell'host tramite ip fisso
|
||||
# - postgres_sys_relay_net # Rete per postgres esterno ultia spiaggia
|
||||
ports:
|
||||
- "127.0.0.1:${EVERYTHING_EXTERNAL_PORT}:${EVERYTHING_PORT}"
|
||||
logging:
|
||||
driver: journald
|
||||
options:
|
||||
tag: sangue-production
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
redis:
|
||||
image: redis:6
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- sangue_prod_net
|
||||
|
||||
## ATTENZIONE: se si usa il docker-compose.yml standard dell'infrastruttura briq,
|
||||
## allora c'è già un hivemq che ascolta globalmente
|
||||
# hivemq:
|
||||
# restart: unless-stopped
|
||||
# image: "docker.briq.it/public/hivemq-community-edition:master"
|
||||
# env_file:
|
||||
# - .env
|
||||
# volumes:
|
||||
# - ./hivemq.config.xml:/config.xml
|
||||
# logging:
|
||||
# driver: syslog
|
||||
# options:
|
||||
# tag: "hivemq-prod"
|
||||
# ports:
|
||||
# - 127.0.0.1:${MQTT_PORT}:1833
|
||||
# - 127.0.0.1:${MQTT_WEBSOCKET_PORT}:1834
|
||||
# networks:
|
||||
# - sangue_prod_net
|
||||
|
||||
networks:
|
||||
sangue_prod_net:
|
||||
driver: bridge
|
||||
bq_infrastructure_net:
|
||||
external: true
|
||||
name: bq_infrastructure_net
|
||||
# fixed_ip_host_net:
|
||||
# external: true
|
||||
# name: fixed_ip_host_net
|
||||
# postgres_sys_relay_net:
|
||||
# external: true
|
||||
# name: postgres_sys_relay_net
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0"?>
|
||||
<hivemq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="hivemq-config.xsd">
|
||||
|
||||
<listeners>
|
||||
<tcp-listener>
|
||||
<port>1833</port>
|
||||
<bind-address>0.0.0.0</bind-address>
|
||||
</tcp-listener>
|
||||
<websocket-listener>
|
||||
<port>1834</port>
|
||||
<path>/</path>
|
||||
<bind-address>0.0.0.0</bind-address>
|
||||
</websocket-listener>
|
||||
</listeners>
|
||||
<mqtt>
|
||||
<max-client-id-length>65535</max-client-id-length>
|
||||
<retry-interval>0</retry-interval>
|
||||
<no-connect-packet-idle-timeout-millis>10000</no-connect-packet-idle-timeout-millis>
|
||||
<max-queued-messages>100000</max-queued-messages>
|
||||
</mqtt>
|
||||
<throttling>
|
||||
<max-connections>-1</max-connections>
|
||||
<max-message-size>268435456</max-message-size>
|
||||
<outgoing-limit>0</outgoing-limit>
|
||||
<incoming-limit>0</incoming-limit>
|
||||
</throttling>
|
||||
<general>
|
||||
<update-check-enabled>false</update-check-enabled>
|
||||
</general>
|
||||
|
||||
</hivemq>
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
COMPOSE_PROJECT_NAME=sangue_staging
|
||||
|
||||
EVERYTHING_EXTERNAL_PORT=9070
|
||||
|
||||
SECRET_KEY=EaqzWFIUeWsNfAeBYTJFgnysbqcMlVASyDNTxAJitXzUmesuPvFprXMuFnoEIPbsZysKgLNzqFDdEmmfHirYrOkDFVnkoABJySVV
|
||||
DEBUG=false
|
||||
|
||||
DOLLAR=$
|
||||
|
||||
# usato per nginx
|
||||
EVERYTHING_LISTEN=0.0.0.0
|
||||
EVERYTHING_PORT=9090
|
||||
|
||||
DJANGO_PORT=8000
|
||||
|
||||
# path assoluti:
|
||||
MEDIA_ROOT=/django_upload/
|
||||
|
||||
# url che deve coincidere in django e nginx
|
||||
MEDIA_URL=uploads/
|
||||
|
||||
|
||||
# Redis serve per i django channels
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
|
||||
# DJANGO DB
|
||||
DB_NAME=sangue_staging
|
||||
DB_USER=sangue_staging
|
||||
DB_PASSWORD=sangue_staging
|
||||
DB_HOST=postgres_svc # se fisso, vedere yml di infrastruttura briq
|
||||
DB_TEST_NAME=sangue_staging_test
|
||||
|
||||
# MQTT
|
||||
|
||||
ENABLE_MQTT=false
|
||||
MQTT_HOST=hivemq_svc
|
||||
MQTT_WEBSOCKET_HOST=hivemq_svc
|
||||
|
||||
MQTT_PORT=1833
|
||||
MQTT_WEBSOCKET_PORT=1834
|
||||
|
||||
#MQTT_PORT=
|
||||
#MQTT_WEBSOCKET_PORT=
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
version: "3.5"
|
||||
|
||||
services:
|
||||
sangue:
|
||||
image: docker.briq.it/briq/sangue:master
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./.django_uploads:/django_upload
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- sangue_staging_net
|
||||
- bq_infrastructure_net
|
||||
# - fixed_ip_host_net # Rete per accedere a servizi dell'host tramite ip fisso
|
||||
# - postgres_sys_relay_net # Rete per postgres esterno ultia spiaggia
|
||||
ports:
|
||||
- "127.0.0.1:${EVERYTHING_EXTERNAL_PORT}:${EVERYTHING_PORT}"
|
||||
logging:
|
||||
driver: journald
|
||||
options:
|
||||
tag: sangue-staging
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
redis:
|
||||
image: redis:6
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- sangue_staging_net
|
||||
|
||||
## ATTENZIONE: se si usa il docker-compose.yml standard dell'infrastruttura briq,
|
||||
## allora c'è già un hivemq che ascolta globalmente
|
||||
# hivemq:
|
||||
# restart: unless-stopped
|
||||
# image: "docker.briq.it/public/hivemq-community-edition:master"
|
||||
# env_file:
|
||||
# - .env
|
||||
# volumes:
|
||||
# - ./hivemq.config.xml:/config.xml
|
||||
# logging:
|
||||
# driver: syslog
|
||||
# options:
|
||||
# tag: "hivemq-staging"
|
||||
# ports:
|
||||
# - 127.0.0.1:${MQTT_PORT}:1833
|
||||
# - 127.0.0.1:${MQTT_WEBSOCKET_PORT}:1834
|
||||
# networks:
|
||||
# - sangue_staging_net
|
||||
|
||||
networks:
|
||||
sangue_staging_net:
|
||||
driver: bridge
|
||||
bq_infrastructure_net:
|
||||
external: true
|
||||
name: bq_infrastructure_net
|
||||
# fixed_ip_host_net:
|
||||
# external: true
|
||||
# name: fixed_ip_host_net
|
||||
# postgres_sys_relay_net:
|
||||
# external: true
|
||||
# name: postgres_sys_relay_net
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0"?>
|
||||
<hivemq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="hivemq-config.xsd">
|
||||
|
||||
<listeners>
|
||||
<tcp-listener>
|
||||
<port>1833</port>
|
||||
<bind-address>0.0.0.0</bind-address>
|
||||
</tcp-listener>
|
||||
<websocket-listener>
|
||||
<port>1834</port>
|
||||
<path>/</path>
|
||||
<bind-address>0.0.0.0</bind-address>
|
||||
</websocket-listener>
|
||||
</listeners>
|
||||
<mqtt>
|
||||
<max-client-id-length>65535</max-client-id-length>
|
||||
<retry-interval>0</retry-interval>
|
||||
<no-connect-packet-idle-timeout-millis>10000</no-connect-packet-idle-timeout-millis>
|
||||
<max-queued-messages>100000</max-queued-messages>
|
||||
</mqtt>
|
||||
<throttling>
|
||||
<max-connections>-1</max-connections>
|
||||
<max-message-size>268435456</max-message-size>
|
||||
<outgoing-limit>0</outgoing-limit>
|
||||
<incoming-limit>0</incoming-limit>
|
||||
</throttling>
|
||||
<general>
|
||||
<update-check-enabled>false</update-check-enabled>
|
||||
</general>
|
||||
|
||||
</hivemq>
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#! /bin/bash --
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
DOCKER_NAMESPACE="briq"
|
||||
PROJ="sangue"
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
CD_TO="./production/"
|
||||
|
||||
cd-docker-compose() {
|
||||
(cd "$1" && docker-compose "${@:2}")
|
||||
}
|
||||
|
||||
log_images() {
|
||||
if cd-docker-compose "$CD_TO" exec "$PROJ" bash -c 'exit 0'; then
|
||||
{
|
||||
date | tr -d '\n';
|
||||
echo -ne "\t";
|
||||
cd-docker-compose "$CD_TO" exec "$PROJ" bash -c 'cat /git_info' | jq -r '.lhash' | tr -d '\n';
|
||||
echo -ne '\t';
|
||||
cd-docker-compose "$CD_TO" images -q "$PROJ" | tr -d '\n';
|
||||
echo -e "\t$1";
|
||||
} >> "$2"
|
||||
else
|
||||
{
|
||||
date | tr -d '\n';
|
||||
echo -ne "\timpossibile leggere il tag git\t";
|
||||
{ cd-docker-compose "$CD_TO" images -q "$PROJ" || echo "N/A"; } | tr -d '\n';
|
||||
echo -e "\t$1";
|
||||
} >> "$2"
|
||||
fi
|
||||
}
|
||||
log_images "prima" "log_deployment_production.txt"
|
||||
|
||||
docker tag "$PROJ":production "$PROJ":backup || true
|
||||
docker tag docker.briq.it/"$DOCKER_NAMESPACE/$PROJ":master "$PROJ":production
|
||||
cd-docker-compose "$CD_TO" up -dt1
|
||||
log_images "dopo" "log_deployment_production.txt"
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
version: '3.5'
|
||||
|
||||
services:
|
||||
hivemq_svc:
|
||||
restart: unless-stopped
|
||||
image: "docker.briq.it/public/hivemq-community-edition:master"
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- ./hivemq.config.xml:/config.xml
|
||||
logging:
|
||||
driver: journald
|
||||
options:
|
||||
tag: hivemq-briq
|
||||
ports:
|
||||
- 127.0.0.1:1833:1833
|
||||
- 127.0.0.1:1834:1834
|
||||
networks:
|
||||
- bq_infrastructure_net
|
||||
- bq_infrastructure_ext_net
|
||||
|
||||
postgres_svc:
|
||||
image: postgres:14
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- bq_infrastructure_net
|
||||
- bq_infrastructure_ext_net
|
||||
ports:
|
||||
- 127.0.0.1:5432:5432
|
||||
environment:
|
||||
POSTGRES_PASSWORD: LvdSkluLfE
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: postgres
|
||||
logging:
|
||||
driver: journald
|
||||
options:
|
||||
tag: postgres-briq
|
||||
#volumes:
|
||||
# - ./data:/var/lib/postgresql/data
|
||||
#
|
||||
## ATTENZIONE: avviare con volume qui sopra commentato, poi eseguire dalla cartella corrente (e poi decommentare il volume):
|
||||
## docker-compose exec postgres_svc sh -c "tar -cpO -C /var/lib/postgresql data | base64" | base64 -di | tar -xp
|
||||
# nodered_svc:
|
||||
# image: nodered/node-red:3.0.0
|
||||
# restart: unless-stopped
|
||||
# environment:
|
||||
# - TZ=Europe/Rome
|
||||
# ports:
|
||||
# - "127.0.0.1:1880:1880"
|
||||
# - "0.0.0.0:1890:1890" # per mandare il file da windows fuori (particolarità di eusebio)
|
||||
# networks:
|
||||
# - bq_infrastructure_net
|
||||
# - bq_infrastructure_ext_net
|
||||
# # volumes:
|
||||
# # - ./red_data:/data
|
||||
# ## ATTENZIONE: avviare con volume qui sopra commentato, poi eseguire dalla cartella corrente (e poi decommentare il volume):
|
||||
# ## mkdir -p red_data && docker-compose exec -u0 nodered_svc sh -c "tar -cpO -C /data . | base64" | base64 -di | sudo tar -C ./red_data -xp
|
||||
|
||||
# # Questo è il relay. Usare come ultima spiaggia e soltanto con postgresql di sistema.
|
||||
# postgres_sys:
|
||||
# image: docker.briq.it/public/psql_relay:master
|
||||
# restart: unless-stopped
|
||||
# networks:
|
||||
# - postgres_sys_relay_net
|
||||
# environment:
|
||||
# - PSQL_SOCK_NAME=postgresql/.s.PGSQL.5432
|
||||
# volumes:
|
||||
# - /var/run/:/psql_sock/
|
||||
|
||||
networks:
|
||||
postgres_sys_relay_net:
|
||||
name: postgres_sys_relay_net
|
||||
internal: true
|
||||
bq_infrastructure_net:
|
||||
name: bq_infrastructure_net
|
||||
internal: true
|
||||
bq_infrastructure_ext_net:
|
||||
name: bq_infrastructure_ext_net
|
||||
# # Usare in caso di bisogno di connettere servizi dell'host direttamente ai container
|
||||
# fixed_ip_host_net:
|
||||
# name: fixed_ip_host_net
|
||||
# ipam:
|
||||
# driver: default
|
||||
# config:
|
||||
# - subnet: 172.28.42.0/24
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
version: "3.4"
|
||||
|
||||
services:
|
||||
# red:
|
||||
# image: "nodered/node-red"
|
||||
# volumes:
|
||||
# - "./red_data:/data:rw"
|
||||
# environment:
|
||||
# - PORT=${NODE_RED_PORT}
|
||||
# - DJANGO_URL=http://localhost:${EVERYTHING_EXTERNAL_PORT}/api
|
||||
# network_mode: host
|
||||
# # env_file:
|
||||
# # - .env
|
||||
# hivemq:
|
||||
# image: "docker.briq.it/public/hivemq-community-edition:master"
|
||||
# # env_file:
|
||||
# # - .env
|
||||
# volumes:
|
||||
# - ./hivemq.config.xml:/config.xml
|
||||
# ports:
|
||||
# - "${EVERYTHING_LISTEN}:${MQTT_PORT}:1833"
|
||||
# - "${EVERYTHING_LISTEN}:${MQTT_WEBSOCKET_PORT}:1834"
|
||||
sangue:
|
||||
image: sangue
|
||||
build:
|
||||
context: ../..
|
||||
args:
|
||||
GIT_COMMIT_SHA: ${GIT_COMMIT_SHA}
|
||||
GIT_COMMIT_DATE: ${GIT_COMMIT_DATE}
|
||||
GIT_COMMIT_REF: ${GIT_COMMIT_REF}
|
||||
GIT_CLEAN: ${GIT_CLEAN}
|
||||
container_name: "sangue"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- ./.django_uploads:/django_upload
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "127.0.0.1:${EVERYTHING_EXTERNAL_PORT}:${EVERYTHING_PORT}"
|
||||
redis:
|
||||
image: redis:6
|
||||
restart: unless-stopped
|
||||
psql_relay:
|
||||
image: docker.briq.it/public/psql_relay:master
|
||||
environment:
|
||||
- PSQL_SOCK_NAME=postgresql/.s.PGSQL.5432
|
||||
volumes:
|
||||
- /var/run/:/psql_sock/
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
# cupsd:
|
||||
# image: "docker.briq.it/public/cupsd:master"
|
||||
# volumes:
|
||||
# - /etc/timezone:/etc/timezone:ro
|
||||
# - ./.cups_sock:/run/cups/
|
||||
# - ./.cups_config/:/etc/cups/
|
||||
# ports:
|
||||
# - "1631:631"
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
pid /django/nginx.pid;
|
||||
daemon off;
|
||||
|
||||
error_log /dev/stderr warn;
|
||||
|
||||
events {}
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
client_body_temp_path /tmp/nginx;
|
||||
proxy_temp_path /tmp/nginx;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 100;
|
||||
|
||||
gzip_types *;
|
||||
upstream django {
|
||||
server unix:///django/sock fail_timeout=0;
|
||||
}
|
||||
|
||||
server {
|
||||
include /maybe_ssl.conf;
|
||||
access_log /dev/stdout;
|
||||
root /django_static;
|
||||
charset utf-8;
|
||||
|
||||
|
||||
# location = /django_auth {
|
||||
# internal;
|
||||
# proxy_pass http://django/auth/is_authorized/;
|
||||
# proxy_pass_request_body off;
|
||||
# proxy_set_header Content-Length "";
|
||||
# proxy_set_header Host ${DOLLAR}http_host;
|
||||
# proxy_set_header X-Original-URI ${DOLLAR}request_uri;
|
||||
# proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Proto ${DOLLAR}http_x_forwarded_proto;
|
||||
# }
|
||||
|
||||
location /frontend/ {
|
||||
# auth_request /django_auth;
|
||||
alias /vue/dist/;
|
||||
}
|
||||
location /static {
|
||||
alias /django_static;
|
||||
}
|
||||
keepalive_timeout 5;
|
||||
location / {
|
||||
client_max_body_size 10M;
|
||||
proxy_pass http://django;
|
||||
proxy_redirect off;
|
||||
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto ${DOLLAR}http_x_forwarded_proto;
|
||||
proxy_set_header Host ${DOLLAR}http_host;
|
||||
}
|
||||
location /ws/ {
|
||||
# we don't want nginx trying to do something clever with
|
||||
# redirects, we set the Host: header above already.
|
||||
proxy_pass http://django/ws/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade ${DOLLAR}http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto ${DOLLAR}http_x_forwarded_proto;
|
||||
proxy_set_header Host ${DOLLAR}http_host;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
location /${MEDIA_URL} {
|
||||
# auth_request /django_auth;
|
||||
# error_page 403 = @error403;
|
||||
alias ${MEDIA_ROOT};
|
||||
}
|
||||
|
||||
location @error403 {
|
||||
absolute_redirect off;
|
||||
return 302 /;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#! /bin/bash --
|
||||
set -x
|
||||
export DOLLAR="$"
|
||||
|
||||
. "./startstop_utils.sh"
|
||||
|
||||
DJANGO_WEB_PID=none
|
||||
DJANGO_QCLUSTER_PID=none
|
||||
NGINX_PID=none
|
||||
trap 'stop $DJANGO_WEB_PID $NGINX_PID $DJANGO_QCLUSTER_PID' SIGTERM SIGINT SIGQUIT SIGHUP ERR
|
||||
|
||||
# mkdir -p "$MEDIA_ROOT"
|
||||
if [ -S '/django/sock' ]; then
|
||||
# exit code speciale interpretato da briq-docker-watcher (in briq-docker-utils)
|
||||
# che forza la ricreazione del container
|
||||
exit 47
|
||||
fi
|
||||
|
||||
echo >&2 "Nginx ..."
|
||||
envsubst <"/nginx.conf.tpl" >"/nginx.conf"
|
||||
{ if [ "$NGINX_SSL" = "1" ]; then
|
||||
{ cat "${NGINX_SSL_CERTIFICATE}"; echo; cat "${NGINX_SSL_CHAIN}"; } > "/full_chain.pem";
|
||||
echo "listen ${EVERYTHING_LISTEN}:${EVERYTHING_PORT} ssl;
|
||||
ssl_certificate /full_chain.pem;
|
||||
ssl_certificate_key ${NGINX_SSL_KEY};
|
||||
ssl_session_cache shared:le_nginx_SSL:10m;
|
||||
ssl_session_timeout 1440m;
|
||||
ssl_session_tickets off;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_ciphers \"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384\";"
|
||||
if [ -n "$NGINX_DH_PARAM" ]; then
|
||||
echo "ssl_dhparam ${NGINX_DH_PARAM};"
|
||||
fi
|
||||
else
|
||||
echo "listen ${EVERYTHING_LISTEN}:${EVERYTHING_PORT};"
|
||||
fi; } > "/maybe_ssl.conf"
|
||||
nginx -c /nginx.conf -p / &
|
||||
NGINX_PID=$!
|
||||
|
||||
echo "Setting Django up..."
|
||||
cd /django/ || exit 1
|
||||
DJANGO_PROJ="$(poetry run python manage.py shell < get_django_proj.py)"
|
||||
if [[ "$(poetry run python manage.py help | grep -o '\[django_q\]')" == "[django_q]" ]]; then
|
||||
echo "Django qcluster..."
|
||||
poetry run python manage.py qcluster &
|
||||
DJANGO_QCLUSTER_PID=$!
|
||||
fi
|
||||
|
||||
echo "Django web..."
|
||||
env DJANGO_SETTINGS_MODULE="$DJANGO_PROJ.settings" poetry run uvicorn "$DJANGO_PROJ".asgi:application --uds /django/sock --workers="${DJANGO_WORKERS:-4}" &
|
||||
DJANGO_WEB_PID=$!
|
||||
|
||||
wait
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#! /bin/bash --
|
||||
killa() {
|
||||
if [[ "$1" != 'none' ]]; then
|
||||
if [[ "$2" == "" ]]; then
|
||||
SIGNAL=15
|
||||
else
|
||||
SIGNAL="$2"
|
||||
fi
|
||||
case "$SIGNAL" in
|
||||
15)
|
||||
echo >&2 "stopping $1..."
|
||||
;;
|
||||
9)
|
||||
echo >&2 "killing $1..."
|
||||
;;
|
||||
*)
|
||||
echo >&2 "sending signal $SIGNAL to $1..."
|
||||
;;
|
||||
esac
|
||||
kill -"$SIGNAL" "$1" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
PID_DA_WAITARE=()
|
||||
for pid in "$@"; do
|
||||
if [[ "$pid" != 'none' ]]; then
|
||||
PID_DA_WAITARE+=("$pid")
|
||||
killa "$pid"
|
||||
fi
|
||||
done
|
||||
{
|
||||
if sleep 5; then
|
||||
for pid in "$@"; do
|
||||
killa "$pid" 9
|
||||
done
|
||||
wait
|
||||
fi
|
||||
}&
|
||||
SLEEP_PID=$!
|
||||
wait "${PID_DA_WAITARE[@]}" #aspetto solo i pid nei parametri, non sleep...&
|
||||
# se questo kill fallisce vuol dire che il ciclo con sleep 5 è terminato -> è servito killare qualche processo
|
||||
kill "$SLEEP_PID" 2>/dev/null && echo >&2 "Tutti i processi terminati normalmente"
|
||||
exit 0
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# ADDRESSES
|
||||
export EVERYTHING_LISTEN=127.0.0.1 # security by default!
|
||||
# export EVERYTHING_PORT=9090
|
||||
|
||||
export DJANGO_HOST=127.0.0.1
|
||||
export CONTEXT=Locale
|
||||
# export MYHOSTNAME=
|
||||
|
||||
# PORTS
|
||||
export DJANGO_PORT=8000
|
||||
export DBG_PORT=9090
|
||||
export VUE_PORT=9091
|
||||
|
||||
# DJANGO DB
|
||||
export DB_NAME=sangue
|
||||
export DB_USER=sangue
|
||||
export DB_PASSWORD=sangue
|
||||
export DB_HOST=127.0.0.1
|
||||
# export DB_PORT=5432
|
||||
export DB_TEST_NAME=sangue_test
|
||||
|
||||
# DJANGO MISC
|
||||
export SECRET_KEY=FpstwQgWItsIpsaBuPlTwZIYynCdkdrIieYstnifekcgxfxMdIqVsflNuGrDTbFeiCUTMiGonXDfjyEKxHeHgfXFIwlUTiFdmVId
|
||||
export MEDIA_ROOT=$(pwd)/django_upload/
|
||||
export MEDIA_URL=uploads/
|
||||
export DEBUG=true
|
||||
export DEBUG_TOOLBAR=true
|
||||
# export DJANGO_LOG_LEVEL=DEBUG
|
||||
# export DJANGO_LOG_SQL
|
||||
|
||||
# MQTT
|
||||
# export ENABLE_MQTT=
|
||||
# export MQTT_HOST=
|
||||
# export MQTT_PORT=
|
||||
|
||||
# REDIS
|
||||
# export REDIS_HOST=
|
||||
# export REDIS_PORT=
|
||||
|
||||
# SECURITY
|
||||
# export CSRF_COOKIE_SECURE=
|
||||
# export CSRF_TRUSTED_ORIGINS=
|
||||
# export SECURE_SSL_REDIRECT=
|
||||
# export SESSION_COOKIE_SECURE=
|
||||
|
||||
|
||||
# workarounds
|
||||
export DOLLAR=$
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#! /bin/bash --
|
||||
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
. "docker/test_and_build/startstop_utils.sh"
|
||||
|
||||
DJANGO_WEB_PID=none
|
||||
DJANGO_QCLUSTER_PID=none
|
||||
VUE_PID=none
|
||||
NGINX_PID=none
|
||||
trap 'stop $DJANGO_WEB_PID $NGINX_PID $DJANGO_QCLUSTER_PID' SIGTERM SIGINT SIGQUIT SIGHUP ERR
|
||||
|
||||
root="$(pwd)"
|
||||
export root
|
||||
source ".env"
|
||||
# # DECOMMENTARE QUI DI SEGUITO SE NEL PROGETTO SERVE REDIS:
|
||||
# if ! nc -z "$REDIS_HOST" "$REDIS_PORT"; then
|
||||
# echo >&2 "Non c'è redis su $REDIS_HOST:$REDIS_PORT"
|
||||
# exit 1
|
||||
# fi
|
||||
pushd django/ || exit 1
|
||||
echo >&2 "Starting django web server..."
|
||||
poetry run python manage.py runserver "127.0.0.1:$DJANGO_PORT" &
|
||||
DJANGO_WEB_PID=$!
|
||||
# echo >&2 "Starting django qcluster..."
|
||||
# poetry run python manage.py qcluster &
|
||||
# DJANGO_QCLUSTER_PID=$!
|
||||
popd || exit 1
|
||||
pushd vue || exit 1
|
||||
echo >&2 "Starting vue dev server..."
|
||||
npm run serve -- --port "$VUE_PORT" &
|
||||
VUE_PID=$!
|
||||
|
||||
popd || exit 1
|
||||
echo >&2 "Starting nginx..."
|
||||
envsubst < nginx_localrun.conf.tpl > nginx_localrun.conf
|
||||
nginx -c "$root/nginx_localrun.conf"&
|
||||
NGINX_PID=$!
|
||||
|
||||
echo >&2 "Starting docker compose localrun services..."
|
||||
export COMPOSE_PROJECT_NAME="sangue_localrun"
|
||||
docker-compose --log-level error -f docker-compose-localrun.yml up --timeout 1 1>/dev/null
|
||||
# ctrl-c su docker compose killa tutto. docker-compose sostituisce il wait.
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
pid ${root}/nginx.pid;
|
||||
daemon off;
|
||||
|
||||
error_log /dev/stderr warn;
|
||||
|
||||
events {}
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
client_body_temp_path /tmp/nginx;
|
||||
proxy_temp_path /tmp/nginx;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 100;
|
||||
|
||||
gzip_types *;
|
||||
upstream django {
|
||||
server 127.0.0.1:${DJANGO_PORT} fail_timeout=0;
|
||||
}
|
||||
# upstream mqtt {
|
||||
# server 127.0.0.1:${MQTT_WEBSOCKET_PORT} fail_timeout=0;
|
||||
# }
|
||||
upstream vue {
|
||||
server 127.0.0.1:${VUE_PORT} fail_timeout=0;
|
||||
}
|
||||
|
||||
|
||||
# server {
|
||||
# access_log /dev/stdout;
|
||||
# charset utf-8;
|
||||
# listen 127.0.0.1:${DJANGO_PORT};
|
||||
# location / {
|
||||
# client_max_body_size 10M;
|
||||
# # we don't want nginx trying to do something clever with
|
||||
# # redirects, we set the Host: header above already.
|
||||
# proxy_pass http://django;
|
||||
# proxy_redirect off;
|
||||
# proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
|
||||
# proxy_set_header Host ${DOLLAR}http_host;
|
||||
# }
|
||||
# }
|
||||
server {
|
||||
access_log /dev/stdout;
|
||||
#root /vue/dist;
|
||||
listen ${EVERYTHING_LISTEN}:${DBG_PORT};
|
||||
charset utf-8;
|
||||
|
||||
|
||||
# location = /django_auth {
|
||||
# internal;
|
||||
# proxy_pass http://django/auth/is_authorized/;
|
||||
# proxy_pass_request_body off;
|
||||
# proxy_set_header Content-Length "";
|
||||
# proxy_set_header Host ${DOLLAR}http_host;
|
||||
# proxy_set_header X-Original-URI ${DOLLAR}request_uri;
|
||||
# }
|
||||
|
||||
location /frontend/ {
|
||||
# auth_request /django_auth;
|
||||
# error_page 403 = @error403;
|
||||
proxy_pass http://vue/;
|
||||
proxy_redirect off;
|
||||
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
|
||||
proxy_set_header Host ${DOLLAR}http_host;
|
||||
}
|
||||
location /sockjs-node/ {
|
||||
proxy_pass http://vue;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade ${DOLLAR}http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
|
||||
proxy_set_header Host ${DOLLAR}http_host;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
# location /backend/static/ {
|
||||
# proxy_pass http://django/static/;
|
||||
# proxy_set_header Host ${DOLLAR}http_host;
|
||||
# proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
# }
|
||||
location / {
|
||||
client_max_body_size 10M;
|
||||
proxy_pass http://django/;
|
||||
# set ${DOLLAR}sc_name ${DOLLAR}http_x_script_name/backend;
|
||||
# proxy_set_header X-Script-Name ${DOLLAR}sc_name;
|
||||
proxy_redirect off;
|
||||
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
|
||||
proxy_set_header Host ${DOLLAR}http_host;
|
||||
}
|
||||
location /ws/ {
|
||||
# we don't want nginx trying to do something clever with
|
||||
# redirects, we set the Host: header above already.
|
||||
proxy_pass http://django/ws/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade ${DOLLAR}http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
|
||||
proxy_set_header Host ${DOLLAR}http_host;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
location /${MEDIA_URL} {
|
||||
# auth_request /django_auth;
|
||||
# error_page 403 = @error403;
|
||||
alias ${MEDIA_ROOT};
|
||||
}
|
||||
|
||||
location @error403 {
|
||||
absolute_redirect off;
|
||||
return 302 /;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#! /bin/bash --
|
||||
|
||||
# REQUISITI:
|
||||
# sul server E sul client ci deve essere installato:
|
||||
# - pgdump versione corretta
|
||||
# - zstd
|
||||
# - base64
|
||||
# - ssh server
|
||||
|
||||
set -e
|
||||
DOVE="$(mktemp)"
|
||||
|
||||
cd "$(dirname "$0")/.." && source .env
|
||||
COMANDO='set -e; cd "'"$2"'" && source env_docker && PGPASSWORD="$DB_PASSWORD" pg_dump -h localhost -p "${DB_PORT:-5432}" -U "${DB_USER:postgres}" -c -Fc -Z0 "$DB_NAME" | zstd'
|
||||
B64=$(echo "$COMANDO" | base64)
|
||||
ssh "$1" "echo '$B64' | base64 -d | bash" | zstdcat > "$DOVE"
|
||||
echo 'DROP DATABASE "'"$DB_NAME"'";' | psql -h localhost -p "${DB_PORT:-5432}" -U "${DB_USER:postgres}"
|
||||
pg_restore -h localhost -p "${DB_PORT:-5432}" -U "${DB_USER:postgres}" -d "$DB_NAME" --clean -Fc -j $(cat /proc/cpuinfo | grep processor | wc -l) "$DOVE"
|
||||
rm -rf "$DOVE"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#! /bin/bash --
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
set -e
|
||||
|
||||
pushd vue
|
||||
npm install
|
||||
popd
|
||||
|
||||
pushd django
|
||||
poetry install
|
||||
popd
|
||||
|
||||
# pushd docker/red_data
|
||||
# pushd lib/vendor
|
||||
# git clone https://git.briq.it/Briq/node-red-contrib-s7-briq || git pull
|
||||
# git clone https://git.briq.it/Briq/red-briq-nodes || git pull
|
||||
# popd
|
||||
# npm install
|
||||
# popd
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# sangue_app
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run your tests
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"name": "sangue",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0",
|
||||
"vuex": "^4.0.2",
|
||||
"webpack-obfuscator": "^2.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^7.0.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"rules": {
|
||||
"vue/no-v-for-template-key-on-child": 2,
|
||||
"no-console": 0,
|
||||
"no-unused-vars": [
|
||||
2,
|
||||
{
|
||||
"vars": "all",
|
||||
"varsIgnorePattern": "^_",
|
||||
"argsIgnorePattern": "^_"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"plugins": {
|
||||
"autoprefixer": {}
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>{{cookiecutter.project_name_snake}}_django</title>
|
||||
|
||||
|
||||
<!--<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"/>
|
||||
<link rel="stylesheet" id="Oswald-css" href="http://fonts.googleapis.com/css?family=Oswald%3A100%2C300%2C400%2C400italic%2C700&ver=d900f3de0b340aaffdf647c3002595eb" type="text/css" media="all"/>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/tabulator/4.2.2/css/bootstrap/tabulator_bootstrap4.min.css" rel="stylesheet"/>-->
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<link rel="stylesheet" id="Oswald-css" href="http://fonts.googleapis.com/css?family=Oswald%3A100%2C300%2C400%2C400italic%2C700&ver=d900f3de0b340aaffdf647c3002595eb" type="text/css" media="all"/>
|
||||
<script type="text/javascript" src="/auto_config_frontend.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but {{cookiecutter.project_name_snake}}_django doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<Vista />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vista from "./views/Vista.vue";
|
||||
|
||||
export default {
|
||||
name: "app",
|
||||
components: {
|
||||
Vista,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*#app {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}*/
|
||||
</style>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,551 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by FontForge 20120731 at Tue Jan 22 19:36:11 2019
|
||||
By www
|
||||
Copyright 2002 YouWorkForThem. All Rights Reserved. http://www.youworkforthem.com. YWFT Administration Contact: info@youworkforthem.com
|
||||
</metadata>
|
||||
<defs>
|
||||
<font id="MaetlExtraBold" horiz-adv-x="914" >
|
||||
<font-face
|
||||
font-family="Maetl"
|
||||
font-weight="800"
|
||||
font-stretch="normal"
|
||||
units-per-em="1000"
|
||||
panose-1="0 0 8 0 0 0 0 0 0 0"
|
||||
ascent="800"
|
||||
descent="-200"
|
||||
x-height="582"
|
||||
cap-height="728"
|
||||
bbox="-143 -254 1166 1074"
|
||||
underline-thickness="20"
|
||||
underline-position="-123"
|
||||
unicode-range="U+0020-F002"
|
||||
/>
|
||||
<missing-glyph horiz-adv-x="500"
|
||||
d="M63 0v800h375v-800h-375zM125 63h250v675h-250v-675z" />
|
||||
<glyph glyph-name=".notdef" horiz-adv-x="500"
|
||||
d="M63 0v800h375v-800h-375zM125 63h250v675h-250v-675z" />
|
||||
<glyph glyph-name="glyph1" horiz-adv-x="0"
|
||||
/>
|
||||
<glyph glyph-name="glyph2" horiz-adv-x="300"
|
||||
/>
|
||||
<glyph glyph-name="space" unicode=" " horiz-adv-x="300"
|
||||
/>
|
||||
<glyph glyph-name=".null" horiz-adv-x="0"
|
||||
/>
|
||||
<glyph glyph-name="Eth" unicode="Ð" horiz-adv-x="871"
|
||||
d="M817 120l-120 -120h-643v290h-73v147h73v291h643l120 -120v-488zM670 147v434h-470v-144h109v-147h-109v-143h470z" />
|
||||
<glyph glyph-name="eth" unicode="ð" horiz-adv-x="871"
|
||||
d="M817 120l-120 -120h-523l-120 120v197l120 120h361l-35 35h-192v147h81l-108 109h199l109 -109h228v-147h-82l82 -82v-270zM670 147v143h-470v-143h470z" />
|
||||
<glyph glyph-name="Lslash" unicode="Ł" horiz-adv-x="798"
|
||||
d="M745 0h-691v290h-73v147h73v327h146v-327h109v-147h-109v-143h545v-147z" />
|
||||
<glyph glyph-name="lslash" unicode="ł" horiz-adv-x="363"
|
||||
d="M309 0h-135l-120 120v170h-73v147h73v291h146v-291h109v-147h-109v-143h109v-147z" />
|
||||
<glyph glyph-name="Scaron" unicode="Š" horiz-adv-x="871"
|
||||
d="M839 120l-120 -120h-524l-120 120v136h147v-109h470v143h-497l-120 120v198l120 120h524l120 -120v-136h-147v109h-470v-144h497l120 -120v-197zM600 866l-120 -120h-89l-120 120v99h100l64 -64l65 64h100v-99z" />
|
||||
<glyph glyph-name="scaron" unicode="š" horiz-adv-x="871"
|
||||
d="M766 120l-120 -120h-571v147h544v71h-424l-120 120v124l120 120h571v-147h-544v-70h424l120 -120v-125zM600 721l-120 -120h-89l-120 120v99h100l64 -65l65 65h100v-99z" />
|
||||
<glyph glyph-name="Yacute" unicode="Ý" horiz-adv-x="835"
|
||||
d="M803 592l-291 -291v-301h-147v301l-290 291v136h147v-84l217 -217l217 217v84h147v-136zM600 975l-193 -193h-136v63l193 193h136v-63z" />
|
||||
<glyph glyph-name="yacute" unicode="ý" horiz-adv-x="835"
|
||||
d="M803 -98l-120 -120h-499v147h472v117l-46 -46h-415l-120 120v462h147v-435h434v435h147v-680zM636 793l-193 -192h-135v63l192 192h136v-63z" />
|
||||
<glyph glyph-name="HT" horiz-adv-x="0"
|
||||
/>
|
||||
<glyph glyph-name="Thorn" unicode="Þ" horiz-adv-x="871"
|
||||
d="M817 229l-120 -120h-451l-46 46v-155h-146v728h146v-146h497l120 -120v-233zM670 256v179h-470v-179h470z" />
|
||||
<glyph glyph-name="thorn" unicode="þ" horiz-adv-x="871"
|
||||
d="M817 120l-120 -120h-451l-46 46v-264h-146v946h146v-191l46 45h451l120 -120v-342zM670 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="nonmarkingreturn" horiz-adv-x="0"
|
||||
/>
|
||||
<glyph glyph-name="Zcaron" unicode="Ž" horiz-adv-x="762"
|
||||
d="M730 0h-655v136l445 445h-445v147h655v-136l-445 -445h445v-147zM563 902l-120 -120h-88l-120 120v100h99l65 -65l65 65h99v-100z" />
|
||||
<glyph glyph-name="zcaron" unicode="ž" horiz-adv-x="798"
|
||||
d="M766 0h-691v245l120 120h424v70h-544v147h691v-244l-120 -120h-424v-71h544v-147zM563 721l-120 -120h-88l-120 120v99h99l65 -65l65 65h99v-99z" />
|
||||
<glyph glyph-name="brokenbar" unicode="¦" horiz-adv-x="254"
|
||||
d="M200 399h-146v329h146v-329zM200 0h-146v328h146v-328z" />
|
||||
<glyph glyph-name="minus" unicode="­" horiz-adv-x="472"
|
||||
d="M418 290h-364v147h364v-147z" />
|
||||
<glyph glyph-name="minus" unicode="−" horiz-adv-x="472"
|
||||
d="M418 290h-364v147h364v-147z" />
|
||||
<glyph glyph-name="multiply" unicode="×" horiz-adv-x="617"
|
||||
d="M563 109h-99l-156 155l-155 -155h-99v136l137 137l-137 137v100h135l119 -119l120 119h135v-100l-137 -137l137 -137v-136z" />
|
||||
<glyph glyph-name="exclam" unicode="!" horiz-adv-x="297"
|
||||
d="M222 218h-147v510h147v-510zM222 0h-147v147h147v-147z" />
|
||||
<glyph glyph-name="quotedbl" unicode=""" horiz-adv-x="478"
|
||||
d="M403 556l-47 -48h-52l-48 48v172h147v-172zM222 556l-47 -48h-53l-47 48v172h147v-172z" />
|
||||
<glyph glyph-name="numbersign" unicode="#" horiz-adv-x="732"
|
||||
d="M657 181h-108v-108h-147v108h-71v-108h-147v108h-109v147h109v71h-109v147h109v109h147v-109h71v109h147v-109h108v-147h-108v-71h108v-147zM402 328v71h-71v-71h71z" />
|
||||
<glyph glyph-name="dollar" unicode="$" horiz-adv-x="878"
|
||||
d="M803 156l-120 -120h-171v-109h-147v109h-170l-120 120v100h147v-73h434v107h-461l-120 120v161l120 120h170v109h147v-109h171l120 -120v-99h-147v72h-434v-107h461l120 -120v-161z" />
|
||||
<glyph glyph-name="percent" unicode="%" horiz-adv-x="878"
|
||||
d="M766 592l-508 -508v-84h-147v136l508 508v84h147v-136zM803 120l-120 -120h-125l-120 120v125l120 120h125l120 -120v-125zM440 483l-120 -120h-125l-120 120v125l120 120h125l120 -120v-125zM329 535v21l-61 61h-21l-61 -61v-21l61 -61h21zM692 172v21l-61 61h-21
|
||||
l-61 -61v-21l61 -61h21z" />
|
||||
<glyph glyph-name="ampersand" unicode="&"
|
||||
d="M839 290h-109v-170l-120 -120h-415l-120 120v161l83 83l-83 83v161l120 120h426v-147h-399v-144h361v109h147v-109h109v-147zM583 147v143h-361v-143h361z" />
|
||||
<glyph glyph-name="quotesingle" unicode="'" horiz-adv-x="297"
|
||||
d="M222 556l-47 -48h-53l-47 48v172h147v-172z" />
|
||||
<glyph glyph-name="parenleft" unicode="(" horiz-adv-x="406"
|
||||
d="M331 -109h-136l-120 120v705l120 120h136v-146h-109v-652h109v-147z" />
|
||||
<glyph glyph-name="parenright" unicode=")" horiz-adv-x="406"
|
||||
d="M331 11l-120 -120h-136v147h109v652h-109v146h136l120 -120v-705z" />
|
||||
<glyph glyph-name="asterisk" unicode="*" horiz-adv-x="732"
|
||||
d="M657 254h-99l-118 118v-107l-48 -47h-52l-47 47v107l-118 -118h-100v100l119 119l-119 119v99h100l118 -118v107l47 48h52l48 -48v-107l118 118h99v-99l-119 -119l119 -119v-100z" />
|
||||
<glyph glyph-name="plus" unicode="+" horiz-adv-x="587"
|
||||
d="M512 290h-145v-145h-147v145h-145v147h145v145h147v-145h145v-147z" />
|
||||
<glyph glyph-name="comma" unicode="," horiz-adv-x="297"
|
||||
d="M222 -73h-63l-48 48v36l-36 36v100h147v-220z" />
|
||||
<glyph glyph-name="hyphen" unicode="-" horiz-adv-x="515"
|
||||
d="M440 290h-365v147h365v-147z" />
|
||||
<glyph glyph-name="hyphen" unicode="‐" horiz-adv-x="515"
|
||||
d="M440 290h-365v147h365v-147z" />
|
||||
<glyph glyph-name="period" unicode="." horiz-adv-x="297"
|
||||
d="M222 0h-147v147h147v-147z" />
|
||||
<glyph glyph-name="slash" unicode="/" horiz-adv-x="805"
|
||||
d="M730 592l-508 -508v-84h-147v136l508 508v84h147v-136z" />
|
||||
<glyph glyph-name="zero" unicode="0" horiz-adv-x="841"
|
||||
d="M766 120l-120 -120h-451l-120 120v488l120 120h451l120 -120v-488zM619 147v434h-397v-434h397z" />
|
||||
<glyph glyph-name="one" unicode="1" horiz-adv-x="515"
|
||||
d="M440 0h-365v147h109v434h-109v147h256v-581h109v-147z" />
|
||||
<glyph glyph-name="two" unicode="2" horiz-adv-x="841"
|
||||
d="M766 0h-691v317l120 120h424v144h-544v147h571l120 -120v-198l-120 -120h-424v-143h544v-147z" />
|
||||
<glyph glyph-name="three" unicode="3" horiz-adv-x="805"
|
||||
d="M730 120l-120 -120h-535v147h508v143h-508v147h508v144h-508v147h535l120 -120v-198l-47 -46l47 -47v-197z" />
|
||||
<glyph glyph-name="four" unicode="4" horiz-adv-x="878"
|
||||
d="M803 181h-109v-181h-147v181h-472v245l301 302h200l-354 -354v-46h325v400h147v-400h109v-147z" />
|
||||
<glyph glyph-name="five" unicode="5" horiz-adv-x="805"
|
||||
d="M730 120l-120 -120h-535v147h508v180h-508v401h655v-147h-508v-107h388l120 -120v-234z" />
|
||||
<glyph glyph-name="six" unicode="6" horiz-adv-x="841"
|
||||
d="M766 120l-120 -120h-451l-120 120v488l120 120h462v-147h-435v-153l46 46h378l120 -120v-234zM619 147v180h-397v-180h397z" />
|
||||
<glyph glyph-name="seven" unicode="7" horiz-adv-x="769"
|
||||
d="M694 592l-291 -291v-301h-147v354l228 227h-409v147h619v-136z" />
|
||||
<glyph glyph-name="eight" unicode="8" horiz-adv-x="841"
|
||||
d="M766 120l-120 -120h-451l-120 120v197l47 47l-47 46v198l120 120h451l120 -120v-198l-46 -46l46 -47v-197zM619 437v144h-397v-144h397zM619 147v143h-397v-143h397z" />
|
||||
<glyph glyph-name="nine" unicode="9" horiz-adv-x="841"
|
||||
d="M766 120l-120 -120h-462v147h435v153l-45 -46h-379l-120 120v234l120 120h451l120 -120v-488zM619 401v180h-397v-180h397z" />
|
||||
<glyph glyph-name="colon" unicode=":" horiz-adv-x="297"
|
||||
d="M222 290h-147v147h147v-147zM222 0h-147v147h147v-147z" />
|
||||
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="297"
|
||||
d="M222 290h-147v147h147v-147zM222 -73h-63l-48 48v36l-36 36v100h147v-220z" />
|
||||
<glyph glyph-name="less" unicode="<" horiz-adv-x="478"
|
||||
d="M403 109h-99l-229 229v52l229 229h99v-100l-155 -155l155 -156v-99z" />
|
||||
<glyph glyph-name="equal" unicode="=" horiz-adv-x="624"
|
||||
d="M549 399h-474v147h474v-147zM549 181h-474v147h474v-147z" />
|
||||
<glyph glyph-name="greater" unicode=">" horiz-adv-x="478"
|
||||
d="M403 338l-228 -229h-100v99l155 156l-155 155v100h100l228 -229v-52z" />
|
||||
<glyph glyph-name="question" unicode="?" horiz-adv-x="696"
|
||||
d="M621 410l-120 -120h-170v-72h-147v99l120 120h170v144h-399v147h426l120 -120v-198zM331 0h-147v147h147v-147z" />
|
||||
<glyph glyph-name="at" unicode="@" horiz-adv-x="769"
|
||||
d="M694 338l-157 -157h-161l-120 120v125l120 120h125l46 -45v80h-227l-98 -98v-238l98 -98h229v-147h-281l-193 193v342l193 193h306l120 -120v-270zM547 328v71h-144v-71h144z" />
|
||||
<glyph glyph-name="A" unicode="A"
|
||||
d="M839 0h-147v181h-470v-181h-147v390l338 338h88l338 -338v-390zM692 328v10l-235 235l-235 -235v-10h470z" />
|
||||
<glyph glyph-name="B" unicode="B"
|
||||
d="M839 120l-120 -120h-644v728h644l120 -120v-161l-83 -83l83 -83v-161zM692 499v82h-470v-144h409zM692 147v82l-61 61h-409v-143h470z" />
|
||||
<glyph glyph-name="C" unicode="C"
|
||||
d="M839 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-136h-147v109h-470v-434h470v109h147v-136z" />
|
||||
<glyph glyph-name="D" unicode="D"
|
||||
d="M839 120l-120 -120h-644v728h644l120 -120v-488zM692 147v434h-470v-434h470z" />
|
||||
<glyph glyph-name="E" unicode="E" horiz-adv-x="841"
|
||||
d="M766 0h-691v728h691v-147h-544v-144h544v-147h-544v-143h544v-147z" />
|
||||
<glyph glyph-name="F" unicode="F" horiz-adv-x="769"
|
||||
d="M694 290h-472v-290h-147v728h619v-147h-472v-144h472v-147z" />
|
||||
<glyph glyph-name="G" unicode="G"
|
||||
d="M839 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-136h-147v109h-470v-434h470v107h-218v147h365v-281z" />
|
||||
<glyph glyph-name="H" unicode="H"
|
||||
d="M839 0h-147v290h-470v-290h-147v728h147v-291h470v291h147v-728z" />
|
||||
<glyph glyph-name="I" unicode="I" horiz-adv-x="587"
|
||||
d="M512 0h-437v147h145v434h-145v147h437v-147h-145v-434h145v-147z" />
|
||||
<glyph glyph-name="J" unicode="J" horiz-adv-x="878"
|
||||
d="M803 120l-120 -120h-488l-120 120v136h147v-109h434v434h-182v147h329v-608z" />
|
||||
<glyph glyph-name="K" unicode="K" horiz-adv-x="878"
|
||||
d="M803 0h-136l-291 290h-154v-290h-147v728h147v-291h154l291 291h136v-64l-301 -300l301 -301v-63z" />
|
||||
<glyph glyph-name="L" unicode="L" horiz-adv-x="769"
|
||||
d="M694 0h-619v728h147v-581h472v-147z" />
|
||||
<glyph glyph-name="M" unicode="M" horiz-adv-x="950"
|
||||
d="M875 0h-147v517l-253 -253l-253 253v-517h-147v728h136l264 -265l264 265h136v-728z" />
|
||||
<glyph glyph-name="N" unicode="N" horiz-adv-x="950"
|
||||
d="M875 0h-136l-517 517v-517h-147v728h136l517 -518v518h147v-728z" />
|
||||
<glyph glyph-name="O" unicode="O"
|
||||
d="M839 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM692 147v434h-470v-434h470z" />
|
||||
<glyph glyph-name="P" unicode="P" horiz-adv-x="841"
|
||||
d="M766 301l-120 -120h-424v-181h-147v728h571l120 -120v-307zM619 328v253h-397v-253h397z" />
|
||||
<glyph glyph-name="Q" unicode="Q" horiz-adv-x="986"
|
||||
d="M911 -109h-135l-109 109h-472l-120 120v488l120 120h524l120 -120v-415l-83 -83l155 -156v-63zM692 147v434h-470v-434h470z" />
|
||||
<glyph glyph-name="R" unicode="R"
|
||||
d="M839 0h-136l-290 290h-191v-290h-147v728h644l120 -120v-198l-120 -120h-107l227 -227v-63zM692 437v144h-470v-144h470z" />
|
||||
<glyph glyph-name="S" unicode="S"
|
||||
d="M839 120l-120 -120h-524l-120 120v136h147v-109h470v143h-497l-120 120v198l120 120h524l120 -120v-136h-147v109h-470v-144h497l120 -120v-197z" />
|
||||
<glyph glyph-name="T" unicode="T" horiz-adv-x="878"
|
||||
d="M803 581h-291v-581h-147v581h-290v147h728v-147z" />
|
||||
<glyph glyph-name="U" unicode="U"
|
||||
d="M839 120l-120 -120h-524l-120 120v608h147v-581h470v581h147v-608z" />
|
||||
<glyph glyph-name="V" unicode="V" horiz-adv-x="878"
|
||||
d="M803 338l-338 -338h-52l-338 338v390h147v-338l217 -217l217 217v338h147v-390z" />
|
||||
<glyph glyph-name="W" unicode="W" horiz-adv-x="950"
|
||||
d="M875 84l-84 -84h-52l-264 264l-264 -264h-52l-84 84v644h147v-518l227 227h52l227 -227v518h147v-644z" />
|
||||
<glyph glyph-name="X" unicode="X" horiz-adv-x="841"
|
||||
d="M766 0h-147v84l-198 198l-199 -198v-84h-147v136l228 228l-228 228v136h147v-84l199 -199l198 199v84h147v-136l-228 -228l228 -228v-136z" />
|
||||
<glyph glyph-name="Y" unicode="Y" horiz-adv-x="878"
|
||||
d="M803 592l-291 -291v-301h-147v301l-290 291v136h147v-84l217 -217l217 217v84h147v-136z" />
|
||||
<glyph glyph-name="Z" unicode="Z" horiz-adv-x="805"
|
||||
d="M730 0h-655v136l445 445h-445v147h655v-136l-445 -445h445v-147z" />
|
||||
<glyph glyph-name="bracketleft" unicode="[" horiz-adv-x="406"
|
||||
d="M331 -109h-256v945h256v-146h-109v-652h109v-147z" />
|
||||
<glyph glyph-name="backslash" unicode="\" horiz-adv-x="805"
|
||||
d="M730 0h-147v84l-508 508v136h147v-84l508 -508v-136z" />
|
||||
<glyph glyph-name="bracketright" unicode="]" horiz-adv-x="406"
|
||||
d="M331 -109h-256v147h109v652h-109v146h256v-945z" />
|
||||
<glyph glyph-name="asciicircum" unicode="^" horiz-adv-x="515"
|
||||
d="M440 435h-64l-119 120l-119 -120h-63v136l156 157h52l157 -157v-136z" />
|
||||
<glyph glyph-name="underscore" unicode="_"
|
||||
d="M839 -109h-764v147h764v-147z" />
|
||||
<glyph glyph-name="grave" unicode="`" horiz-adv-x="762"
|
||||
d="M382 601h-136l-192 192v63h135q63 -64 193 -192v-63z" />
|
||||
<glyph glyph-name="a" unicode="a"
|
||||
d="M839 0h-63l-65 65l-65 -65h-451l-120 120v342l120 120h451l65 -64l65 64h63v-582zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="b" unicode="b"
|
||||
d="M839 120l-120 -120h-524l-120 120v680h147v-263l46 45h451l120 -120v-342zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="c" unicode="c" horiz-adv-x="841"
|
||||
d="M766 0h-571l-120 120v342l120 120h571v-147h-544v-288h544v-147z" />
|
||||
<glyph glyph-name="d" unicode="d"
|
||||
d="M839 0h-63l-65 65l-65 -65h-451l-120 120v342l120 120h451l46 -45v263h147v-800zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="e" unicode="e" horiz-adv-x="878"
|
||||
d="M803 0h-608l-120 120v342l120 120h488l120 -120v-244h-581v-71h581v-147zM656 365v70h-434v-70h434z" />
|
||||
<glyph glyph-name="f" unicode="f" horiz-adv-x="696"
|
||||
d="M621 435h-290v-435h-147v435h-109v147h109v98l120 120h317v-147h-290v-71h290v-147z" />
|
||||
<glyph glyph-name="g" unicode="g"
|
||||
d="M839 -98l-120 -120h-535v147h508v117l-46 -46h-451l-120 120v342l120 120h451l65 -64l65 64h63v-680zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="h" unicode="h" horiz-adv-x="878"
|
||||
d="M803 0h-147v435h-434v-435h-147v800h147v-263l46 45h415l120 -120v-462z" />
|
||||
<glyph glyph-name="i" unicode="i" horiz-adv-x="406"
|
||||
d="M222 653h-147v147h147v-147zM331 0h-136l-120 120v462h147v-435h109v-147z" />
|
||||
<glyph glyph-name="j" unicode="j" horiz-adv-x="297"
|
||||
d="M222 653h-147v147h147v-147zM222 -98l-120 -120h-245v147h218v653h147v-680z" />
|
||||
<glyph glyph-name="k" unicode="k" horiz-adv-x="841"
|
||||
d="M766 0h-135l-218 218h-191v-218h-147v800h147v-435h191l218 217h135v-63l-228 -228l228 -228v-63z" />
|
||||
<glyph glyph-name="l" unicode="l" horiz-adv-x="406"
|
||||
d="M331 0h-136l-120 120v680h147v-653h109v-147z" />
|
||||
<glyph glyph-name="m" unicode="m" horiz-adv-x="1168"
|
||||
d="M1093 0h-147v435h-289v-435h-147v435h-288v-435h-147v582h63l65 -64l65 64h269l65 -64l65 64h306l120 -120v-462z" />
|
||||
<glyph glyph-name="n" unicode="n" horiz-adv-x="878"
|
||||
d="M803 0h-147v435h-434v-435h-147v582h63l65 -64l65 64h415l120 -120v-462z" />
|
||||
<glyph glyph-name="o" unicode="o"
|
||||
d="M839 120l-120 -120h-524l-120 120v342l120 120h524l120 -120v-342zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="p" unicode="p"
|
||||
d="M839 120l-120 -120h-451l-46 46v-264h-147v800h63l65 -64l65 64h451l120 -120v-342zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="q" unicode="q"
|
||||
d="M839 -218h-147v264l-46 -46h-451l-120 120v342l120 120h524l120 -120v-680zM692 147v288h-470v-288h470z" />
|
||||
<glyph glyph-name="r" unicode="r" horiz-adv-x="660"
|
||||
d="M585 435h-363v-435h-147v582h63l65 -64l65 64h317v-147z" />
|
||||
<glyph glyph-name="s" unicode="s" horiz-adv-x="841"
|
||||
d="M766 120l-120 -120h-571v147h544v71h-424l-120 120v124l120 120h571v-147h-544v-70h424l120 -120v-125z" />
|
||||
<glyph glyph-name="t" unicode="t" horiz-adv-x="769"
|
||||
d="M694 0h-390l-120 120v315h-109v147h109v146h147v-146h363v-147h-363v-288h363v-147z" />
|
||||
<glyph glyph-name="u" unicode="u" horiz-adv-x="878"
|
||||
d="M803 0h-64l-64 65l-65 -65h-415l-120 120v462h147v-435h434v435h147v-582z" />
|
||||
<glyph glyph-name="v" unicode="v" horiz-adv-x="878"
|
||||
d="M803 338l-338 -338h-52l-338 338v244h147v-192l217 -217l217 217v192h147v-244z" />
|
||||
<glyph glyph-name="w" unicode="w" horiz-adv-x="1168"
|
||||
d="M1093 120l-120 -120h-306l-65 65l-65 -65h-342l-120 120v462h147v-435h288v435h147v-435h289v435h147v-462z" />
|
||||
<glyph glyph-name="x" unicode="x" horiz-adv-x="841"
|
||||
d="M766 0h-135l-210 210l-210 -210h-136v63l228 228l-228 228v63h136l210 -209l210 209h135v-63l-228 -228l228 -228v-63z" />
|
||||
<glyph glyph-name="y" unicode="y" horiz-adv-x="878"
|
||||
d="M803 -98l-120 -120h-499v147h472v117l-46 -46h-415l-120 120v462h147v-435h434v435h147v-680z" />
|
||||
<glyph glyph-name="z" unicode="z" horiz-adv-x="841"
|
||||
d="M766 0h-691v245l120 120h424v70h-544v147h691v-244l-120 -120h-424v-71h544v-147z" />
|
||||
<glyph glyph-name="braceleft" unicode="{" horiz-adv-x="478"
|
||||
d="M403 -109h-135l-120 120v254l-73 73v52l73 72v254l120 120h135v-146h-108v-243l-73 -73v-20l73 -73v-243h108v-147z" />
|
||||
<glyph glyph-name="bar" unicode="|" horiz-adv-x="297"
|
||||
d="M222 0h-147v764h147v-764z" />
|
||||
<glyph glyph-name="braceright" unicode="}" horiz-adv-x="478"
|
||||
d="M403 338l-72 -73v-254l-120 -120h-136v147h109v243l72 73v20l-72 73v243h-109v146h136l120 -120v-254l72 -72v-52z" />
|
||||
<glyph glyph-name="asciitilde" unicode="~" horiz-adv-x="769"
|
||||
d="M694 374l-120 -120h-161l-138 137l-137 -137h-63v136l120 120h161l137 -137l138 137h63v-136z" />
|
||||
<glyph glyph-name="DEL" horiz-adv-x="290"
|
||||
/>
|
||||
<glyph glyph-name="Adieresis" unicode="Ä" horiz-adv-x="935"
|
||||
d="M860 0h-147v181h-470v-181h-147v390l338 338h89l337 -338v-390zM713 328v10l-235 235l-235 -235v-10h470zM657 746h-147v147h147v-147zM403 746h-147v147h147v-147z" />
|
||||
<glyph glyph-name="Aring" unicode="Å" horiz-adv-x="935"
|
||||
d="M860 0h-147v181h-470v-181h-147v390l338 338h89l337 -338v-390zM713 328v10l-235 235l-235 -235v-10h470zM657 830l-120 -121h-161l-120 121v124l120 120h161l120 -120v-124zM521 892l-64 64l-64 -64l64 -64z" />
|
||||
<glyph glyph-name="Ccedilla" unicode="Ç"
|
||||
d="M839 120l-120 -120h-143l45 -46v-124l-84 -84h-197l-47 47v100h110v-36h82l18 17l-65 65v61h-243l-120 120v488l120 120h524l120 -120v-136h-147v109h-470v-434h470v109h147v-136z" />
|
||||
<glyph glyph-name="Eacute" unicode="É" horiz-adv-x="863"
|
||||
d="M788 0h-692v728h692v-147h-545v-144h545v-147h-545v-143h545v-147zM657 938l-192 -192h-136v63l193 193h135v-64z" />
|
||||
<glyph glyph-name="Ntilde" unicode="Ñ" horiz-adv-x="972"
|
||||
d="M897 0h-136l-518 517v-517h-147v728h136l518 -518v518h147v-728zM730 866l-120 -120h-125l-119 119l-119 -119h-63v136l120 120h125l119 -119l119 119h63v-136z" />
|
||||
<glyph glyph-name="Odieresis" unicode="Ö" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM713 147v434h-470v-434h470zM657 746h-147v147h147v-147zM403 746h-147v147h147v-147z" />
|
||||
<glyph glyph-name="Udieresis" unicode="Ü" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v608h147v-581h470v581h147v-608zM657 746h-147v147h147v-147zM403 746h-147v147h147v-147z" />
|
||||
<glyph glyph-name="aacute" unicode="á" horiz-adv-x="935"
|
||||
d="M860 0h-63l-65 65l-64 -65h-452l-120 120v342l120 120h452l64 -64l65 64h63v-582zM713 147v288h-470v-288h470zM657 793l-192 -192h-136v63l193 192h135v-63z" />
|
||||
<glyph glyph-name="agrave" unicode="à" horiz-adv-x="935"
|
||||
d="M860 0h-63l-65 65l-64 -65h-452l-120 120v342l120 120h452l64 -64l65 64h63v-582zM713 147v288h-470v-288h470zM549 601h-136l-193 192v63h136q63 -64 193 -192v-63z" />
|
||||
<glyph glyph-name="acircumflex" unicode="â" horiz-adv-x="935"
|
||||
d="M860 0h-63l-65 65l-64 -65h-452l-120 120v342l120 120h452l64 -64l65 64h63v-582zM713 147v288h-470v-288h470zM585 601h-100l-64 64l-65 -64h-100v99l120 120h89l120 -120v-99z" />
|
||||
<glyph glyph-name="adieresis" unicode="ä" horiz-adv-x="935"
|
||||
d="M860 0h-63l-65 65l-64 -65h-452l-120 120v342l120 120h452l64 -64l65 64h63v-582zM713 147v288h-470v-288h470zM621 601h-147v147h147v-147zM367 601h-147v147h147v-147z" />
|
||||
<glyph glyph-name="atilde" unicode="ã" horiz-adv-x="935"
|
||||
d="M860 0h-63l-65 65l-64 -65h-452l-120 120v342l120 120h452l64 -64l65 64h63v-582zM713 147v288h-470v-288h470zM730 721l-120 -120h-125l-119 119l-119 -119h-63v135l120 120h125l119 -119l119 119h63v-135z" />
|
||||
<glyph glyph-name="aring" unicode="å" horiz-adv-x="935"
|
||||
d="M860 0h-63l-65 65l-64 -65h-452l-120 120v342l120 120h452l64 -64l65 64h63v-582zM713 147v288h-470v-288h470zM657 721l-120 -120h-161l-120 120v124l120 120h161l120 -120v-124zM521 783l-64 64l-64 -64l64 -64z" />
|
||||
<glyph glyph-name="ccedilla" unicode="ç" horiz-adv-x="841"
|
||||
d="M766 0h-190l45 -46v-124l-84 -84h-197l-47 47v100h110v-36h82l18 17l-65 65v61h-243l-120 120v342l120 120h571v-147h-544v-288h544v-147z" />
|
||||
<glyph glyph-name="eacute" unicode="é" horiz-adv-x="899"
|
||||
d="M824 0h-608l-120 120v342l120 120h488l120 -120v-244h-581v-71h581v-147zM677 365v70h-434v-70h434zM657 793l-192 -192h-136v63l193 192h135v-63z" />
|
||||
<glyph glyph-name="egrave" unicode="è" horiz-adv-x="899"
|
||||
d="M824 0h-608l-120 120v342l120 120h488l120 -120v-244h-581v-71h581v-147zM677 365v70h-434v-70h434zM549 601h-136l-193 192v63h136q63 -64 193 -192v-63z" />
|
||||
<glyph glyph-name="ecircumflex" unicode="ê" horiz-adv-x="899"
|
||||
d="M824 0h-608l-120 120v342l120 120h488l120 -120v-244h-581v-71h581v-147zM677 365v70h-434v-70h434zM621 601h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="edieresis" unicode="ë" horiz-adv-x="899"
|
||||
d="M824 0h-608l-120 120v342l120 120h488l120 -120v-244h-581v-71h581v-147zM677 365v70h-434v-70h434zM657 601h-147v147h147v-147zM403 601h-147v147h147v-147z" />
|
||||
<glyph glyph-name="iacute" unicode="í" horiz-adv-x="478"
|
||||
d="M352 0h-136l-120 120v462h147v-435h109v-147zM403 793l-192 -192h-136v63l193 192h135v-63z" />
|
||||
<glyph glyph-name="igrave" unicode="ì" horiz-adv-x="500"
|
||||
d="M425 0h-136l-120 120v462h147v-435h109v-147zM403 601h-135l-193 192v63h136q62 -64 192 -192v-63z" />
|
||||
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="500"
|
||||
d="M425 0h-136l-120 120v462h147v-435h109v-147zM403 601h-99l-65 64l-64 -64h-100v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="idieresis" unicode="ï" horiz-adv-x="551"
|
||||
d="M461 0h-136l-120 120v462h147v-435h109v-147zM476 601h-147v147h147v-147zM222 601h-147v147h147v-147z" />
|
||||
<glyph glyph-name="ntilde" unicode="ñ" horiz-adv-x="899"
|
||||
d="M824 0h-147v435h-434v-435h-147v582h64l64 -64l65 64h415l120 -120v-462zM803 721l-120 -120h-125l-119 119l-119 -119h-64v135l120 120h125l119 -119l119 119h64v-135z" />
|
||||
<glyph glyph-name="oacute" unicode="ó" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v342l120 120h524l120 -120v-342zM713 147v288h-470v-288h470zM657 793l-192 -192h-136v63l193 192h135v-63z" />
|
||||
<glyph glyph-name="ograve" unicode="ò" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v342l120 120h524l120 -120v-342zM713 147v288h-470v-288h470zM549 601h-136l-193 192v63h136q63 -64 193 -192v-63z" />
|
||||
<glyph glyph-name="ocircumflex" unicode="ô" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v342l120 120h524l120 -120v-342zM713 147v288h-470v-288h470zM621 601h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="odieresis" unicode="ö" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v342l120 120h524l120 -120v-342zM713 147v288h-470v-288h470zM657 601h-147v147h147v-147zM403 601h-147v147h147v-147z" />
|
||||
<glyph glyph-name="otilde" unicode="õ" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v342l120 120h524l120 -120v-342zM713 147v288h-470v-288h470zM730 721l-120 -120h-125l-119 119l-119 -119h-63v135l120 120h125l119 -119l119 119h63v-135z" />
|
||||
<glyph glyph-name="uacute" unicode="ú" horiz-adv-x="899"
|
||||
d="M824 0h-63l-65 65l-65 -65h-415l-120 120v462h147v-435h434v435h147v-582zM657 793l-192 -192h-136v63l193 192h135v-63z" />
|
||||
<glyph glyph-name="ugrave" unicode="ù" horiz-adv-x="899"
|
||||
d="M824 0h-63l-65 65l-65 -65h-415l-120 120v462h147v-435h434v435h147v-582zM549 601h-136l-193 192v63h136q63 -64 193 -192v-63z" />
|
||||
<glyph glyph-name="ucircumflex" unicode="û" horiz-adv-x="899"
|
||||
d="M824 0h-63l-65 65l-65 -65h-415l-120 120v462h147v-435h434v435h147v-582zM621 601h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="udieresis" unicode="ü" horiz-adv-x="899"
|
||||
d="M824 0h-63l-65 65l-65 -65h-415l-120 120v462h147v-435h434v435h147v-582zM657 601h-147v147h147v-147zM403 601h-147v147h147v-147z" />
|
||||
<glyph glyph-name="dagger" unicode="†" horiz-adv-x="660"
|
||||
d="M585 363h-182v-363h-147v363h-181v147h181v181h147v-181h182v-147z" />
|
||||
<glyph glyph-name="degree" unicode="°" horiz-adv-x="515"
|
||||
d="M440 483l-120 -120h-125l-120 120v125l120 120h125l120 -120v-125zM293 510v71h-71v-71h71z" />
|
||||
<glyph glyph-name="cent" unicode="¢" horiz-adv-x="878"
|
||||
d="M803 193l-120 -120h-171v-109h-147v109h-170l-120 120v342l120 120h170v109h147v-109h171l120 -120v-100h-147v73h-434v-288h434v72h147v-99z" />
|
||||
<glyph glyph-name="sterling" unicode="£" horiz-adv-x="841"
|
||||
d="M766 0h-691v147h109v143h-109v147h109v171l120 120h353v-147h-326v-144h218v-147h-218v-143h435v-147z" />
|
||||
<glyph glyph-name="section" unicode="§"
|
||||
d="M839 84l-120 -120h-535v147h508v70h-497l-120 120v125l47 47l-47 46v125l120 120h535v-147h-508v-71h497l120 -120v-125l-47 -46l47 -47v-124zM692 328v71h-470v-71h470z" />
|
||||
<glyph glyph-name="bullet" unicode="•" horiz-adv-x="515"
|
||||
d="M440 301l-120 -120h-125l-120 120v125l120 120h125l120 -120v-125z" />
|
||||
<glyph glyph-name="paragraph" unicode="¶" horiz-adv-x="732"
|
||||
d="M657 0h-147v399h-70v-399h-147v399h-98l-120 120v89l120 120h462v-728zM510 546v35h-70v-35h70zM293 546v35h-71v-35h71z" />
|
||||
<glyph glyph-name="germandbls" unicode="ß"
|
||||
d="M839 120l-120 -120h-426v147h399v82l-61 61h-338v147h338l61 62v82h-470v-690h-147v717l120 120h524l120 -120v-161l-83 -83l83 -83v-161z" />
|
||||
<glyph glyph-name="registered" unicode="®"
|
||||
d="M839 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM692 147v434h-470v-434h470zM657 181h-135l-109 109h-10v-109h-147v365h318l83 -84v-88l-64 -65l64 -64v-64zM510 401v34h-107v-34h107z" />
|
||||
<glyph glyph-name="copyright" unicode="©"
|
||||
d="M839 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM692 147v434h-470v-434h470zM657 181h-281l-120 120v125l120 120h281v-147h-254v-71h254v-147z" />
|
||||
<glyph glyph-name="trademark" unicode="™" horiz-adv-x="1241"
|
||||
d="M1166 218h-147v299l-119 -118h-52l-118 118v-299h-147v510h136l155 -156l156 156h136v-510zM585 581h-182v-363h-147v363h-181v147h510v-147z" />
|
||||
<glyph glyph-name="acute" unicode="´" horiz-adv-x="762"
|
||||
d="M382 793l-193 -192h-135v63l192 192h136v-63z" />
|
||||
<glyph glyph-name="dieresis" unicode="¨" horiz-adv-x="726"
|
||||
d="M491 746h-147v147h147v-147zM237 746h-147v147h147v-147z" />
|
||||
<glyph glyph-name="notequal" unicode="≠" horiz-adv-x="823"
|
||||
d="M748 619l-100 -100v-120h-84l-70 -71h154v-147h-301l-73 -72h-199l100 99v120h120l70 71h-190v147h301l73 73h199z" />
|
||||
<glyph glyph-name="AE" unicode="Æ" horiz-adv-x="1146"
|
||||
d="M1071 0h-561v181h-288v-181h-147v354l374 374h622v-147h-414v-144h414v-147h-414v-143h414v-147zM510 328v253h-9l-252 -253h261z" />
|
||||
<glyph glyph-name="Oslash" unicode="Ø"
|
||||
d="M839 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM692 147v334l-334 -334h334zM556 581h-334v-335z" />
|
||||
<glyph glyph-name="infinity" unicode="∞" horiz-adv-x="878"
|
||||
d="M803 229l-120 -120h-198l-46 46l-47 -46h-197l-120 120v270l120 120h197l47 -47l46 47h198l120 -120v-270zM656 256v216h-144v-216h144zM365 256v216h-143v-216h143z" />
|
||||
<glyph glyph-name="plusminus" unicode="±" horiz-adv-x="587"
|
||||
d="M512 290h-145v-145h-147v145h-145v147h145v145h147v-145h145v-147zM512 0h-437v147h437v-147z" />
|
||||
<glyph glyph-name="lessequal" unicode="≤" horiz-adv-x="587"
|
||||
d="M440 181h-136l-156 157v52l156 156h136v-99l-83 -83l83 -83v-100zM512 0h-437v147h437v-147z" />
|
||||
<glyph glyph-name="greaterequal" unicode="≥" horiz-adv-x="587"
|
||||
d="M440 338l-157 -157h-135v100l82 83l-82 83v99h135l157 -156v-52zM512 0h-437v147h437v-147z" />
|
||||
<glyph glyph-name="yen" unicode="¥" horiz-adv-x="878"
|
||||
d="M803 628l-291 -290v-10h254v-147h-254v-181h-147v181h-254v147h254v10l-290 290v100h100l264 -265l264 265h100v-100z" />
|
||||
<glyph glyph-name="mu" unicode="µ"
|
||||
d="M839 0h-63l-65 65l-65 -65h-378l-46 46v-264h-147v800h147v-435h470v435h147v-582z" />
|
||||
<glyph glyph-name="mu" unicode="μ"
|
||||
d="M839 0h-63l-65 65l-65 -65h-378l-46 46v-264h-147v800h147v-435h470v435h147v-582z" />
|
||||
<glyph glyph-name="partialdiff" unicode="∂"
|
||||
d="M839 120l-120 -120h-524l-120 120v197l120 120h361l-227 227v64h172l338 -338v-270zM692 147v143h-470v-143h470z" />
|
||||
<glyph glyph-name="summation" unicode="∑" horiz-adv-x="805"
|
||||
d="M730 0h-535l-120 120v125l119 119l-119 119v125l120 120h535v-147h-508v-46l98 -98h265v-147h-265l-98 -97v-46h508v-147z" />
|
||||
<glyph glyph-name="product" unicode="∏" horiz-adv-x="732"
|
||||
d="M657 581h-108v-581h-147v581h-71v-581h-147v581h-109v147h582v-147z" />
|
||||
<glyph glyph-name="pi" unicode="π" horiz-adv-x="732"
|
||||
d="M657 435h-108v-435h-147v435h-71v-435h-147v435h-109v147h582v-147z" />
|
||||
<glyph glyph-name="integral" unicode="∫" horiz-adv-x="732"
|
||||
d="M657 581h-217v-570l-120 -120h-245v147h218v570l120 120h244v-147z" />
|
||||
<glyph glyph-name="ordfeminine" unicode="ª"
|
||||
d="M839 145h-63l-65 65l-65 -65h-451l-120 120v343l120 120h451l65 -65l65 65h63v-583zM692 292v289h-470v-289h470z" />
|
||||
<glyph glyph-name="ordmasculine" unicode="º"
|
||||
d="M839 265l-120 -120h-524l-120 120v343l120 120h524l120 -120v-343zM692 292v289h-470v-289h470z" />
|
||||
<glyph glyph-name="Omega" unicode="Ω"
|
||||
d="M839 0h-136l-120 120v125l109 109v227h-470v-227l109 -109v-125l-120 -120h-136v147h109v46l-109 108v307l120 120h524l120 -120v-307l-109 -108v-46h109v-147z" />
|
||||
<glyph glyph-name="Omega" unicode="Ω"
|
||||
d="M839 0h-136l-120 120v125l109 109v227h-470v-227l109 -109v-125l-120 -120h-136v147h109v46l-109 108v307l120 120h524l120 -120v-307l-109 -108v-46h109v-147z" />
|
||||
<glyph glyph-name="ae" unicode="æ" horiz-adv-x="1095"
|
||||
d="M1020 0h-825l-120 120v342l120 120h306l47 -46l46 46h306l120 -120v-244h-399v-71h399v-147zM873 365v70h-252v-70h252zM474 147v288h-252v-288h252z" />
|
||||
<glyph glyph-name="oslash" unicode="ø" horiz-adv-x="878"
|
||||
d="M803 120l-120 -120h-488l-120 120v342l120 120h488l120 -120v-342zM656 147v262l-262 -262h262zM484 435h-262v-261z" />
|
||||
<glyph glyph-name="questiondown" unicode="¿" horiz-adv-x="696"
|
||||
d="M512 472h-147v147h147v-147zM621 -109h-426l-120 120v197l120 120h170v73h147v-100l-120 -120h-170v-143h399v-147z" />
|
||||
<glyph glyph-name="exclamdown" unicode="¡" horiz-adv-x="297"
|
||||
d="M222 472h-147v147h147v-147zM222 -109h-147v510h147v-510z" />
|
||||
<glyph glyph-name="logicalnot" unicode="¬" horiz-adv-x="624"
|
||||
d="M549 181h-147v109h-327v147h474v-256z" />
|
||||
<glyph glyph-name="radical" unicode="√" horiz-adv-x="805"
|
||||
d="M730 0h-535l-120 120v125l119 119l-119 119v125l120 120h535v-147h-508v-46l98 -98h410v-147h-410l-98 -97v-46h508v-147z" />
|
||||
<glyph glyph-name="florin" unicode="ƒ" horiz-adv-x="732"
|
||||
d="M657 327h-217v-316l-120 -120h-245v147h218v289h-109v147h109v134l120 120h244v-147h-217v-107h217v-147z" />
|
||||
<glyph glyph-name="approxequal" unicode="≈" horiz-adv-x="769"
|
||||
d="M694 592l-157 -157h-124l-119 120l-119 -120h-100v100l156 156h125l119 -119l119 119h100v-99zM694 301l-157 -156h-124l-119 119l-119 -119h-100v100l156 156h125l119 -119l119 119h100v-100z" />
|
||||
<glyph glyph-name="approxequal" unicode="⋲" horiz-adv-x="769"
|
||||
d="M694 592l-157 -157h-124l-119 120l-119 -120h-100v100l156 156h125l119 -119l119 119h100v-99zM694 301l-157 -156h-124l-119 119l-119 -119h-100v100l156 156h125l119 -119l119 119h100v-100z" />
|
||||
<glyph glyph-name="Delta" unicode="Δ"
|
||||
d="M839 0h-764v208l338 338h88l338 -338v-208zM701 147l-244 244l-244 -244h488z" />
|
||||
<glyph glyph-name="Delta" unicode="∆"
|
||||
d="M839 0h-764v208l338 338h88l338 -338v-208zM701 147l-244 244l-244 -244h488z" />
|
||||
<glyph glyph-name="guillemotleft" unicode="«" horiz-adv-x="696"
|
||||
d="M621 181h-99l-157 157v52l157 156h99v-99l-83 -83l83 -83v-100zM440 109h-136l-229 229v52l229 229h136v-100l-156 -155l156 -156v-99z" />
|
||||
<glyph glyph-name="guillemotright" unicode="»" horiz-adv-x="696"
|
||||
d="M621 338l-229 -229h-136v99l156 156l-156 155v100h136l229 -229v-52zM331 338l-156 -157h-100v100l83 83l-83 83v99h100l156 -156v-52z" />
|
||||
<glyph glyph-name="ellipsis" unicode="…" horiz-adv-x="732"
|
||||
d="M657 0h-147v147h147v-147zM440 0h-147v147h147v-147zM222 0h-147v147h147v-147z" />
|
||||
<glyph glyph-name="nonbreakingspace" unicode=" " horiz-adv-x="290"
|
||||
/>
|
||||
<glyph glyph-name="Agrave" unicode="À" horiz-adv-x="935"
|
||||
d="M860 0h-147v181h-470v-181h-147v390l338 338h89l337 -338v-390zM713 328v10l-235 235l-235 -235v-10h470zM549 746h-136l-193 192v64h136q63 -64 193 -193v-63z" />
|
||||
<glyph glyph-name="Atilde" unicode="Ã" horiz-adv-x="935"
|
||||
d="M860 0h-147v181h-470v-181h-147v390l338 338h89l337 -338v-390zM713 328v10l-235 235l-235 -235v-10h470zM694 866l-120 -120h-125l-119 119l-119 -119h-63v136l120 120h124l119 -119l120 119h63v-136z" />
|
||||
<glyph glyph-name="Otilde" unicode="Õ" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM713 147v434h-470v-434h470zM730 866l-120 -120h-125l-119 119l-119 -119h-63v136l120 120h125l119 -119l119 119h63v-136z" />
|
||||
<glyph glyph-name="OE" unicode="Œ" horiz-adv-x="1095"
|
||||
d="M1020 0h-825l-120 120v488l120 120h825v-147h-399v-144h399v-147h-399v-143h399v-147zM474 147v434h-252v-434h252z" />
|
||||
<glyph glyph-name="oe" unicode="œ" horiz-adv-x="1095"
|
||||
d="M1020 0h-426l-46 47l-47 -47h-306l-120 120v342l120 120h306l47 -46l46 46h306l120 -120v-244h-399v-71h399v-147zM873 365v70h-252v-70h252zM474 147v288h-252v-288h252z" />
|
||||
<glyph glyph-name="endash" unicode="–" horiz-adv-x="805"
|
||||
d="M730 290h-655v147h655v-147z" />
|
||||
<glyph glyph-name="emdash" unicode="—" horiz-adv-x="950"
|
||||
d="M875 290h-800v147h800v-147z" />
|
||||
<glyph glyph-name="quotedblleft" unicode="“" horiz-adv-x="478"
|
||||
d="M403 628l-46 -46l10 -11v-63h-63l-48 48v172h147v-100zM222 628l-47 -46l11 -11v-63h-64l-47 48v172h147v-100z" />
|
||||
<glyph glyph-name="quotedblright" unicode="”" horiz-adv-x="478"
|
||||
d="M403 556l-47 -48h-63v63l10 11l-47 46v100h147v-172zM222 556l-47 -48h-64v63l11 11l-47 46v100h147v-172z" />
|
||||
<glyph glyph-name="quoteleft" unicode="‘" horiz-adv-x="297"
|
||||
d="M222 628l-47 -47h-45l14 32l42 -42v-63h-64l-47 48v172h147v-100z" />
|
||||
<glyph glyph-name="quoteright" unicode="’" horiz-adv-x="297"
|
||||
d="M222 556l-47 -48h-64v63l11 11l-47 46v100h147v-172z" />
|
||||
<glyph glyph-name="divide" unicode="÷" horiz-adv-x="515"
|
||||
d="M331 508h-147v147h147v-147zM440 290h-365v147h365v-147zM331 73h-147v147h147v-147z" />
|
||||
<glyph glyph-name="lozenge" unicode="◊" horiz-adv-x="732"
|
||||
d="M657 338l-228 -229h-125l-229 229v52l229 229h125l228 -229v-52zM484 364l-118 118l-118 -118l118 -118z" />
|
||||
<glyph glyph-name="ydieresis" unicode="ÿ" horiz-adv-x="899"
|
||||
d="M824 -98l-120 -120h-499v147h472v117l-46 -46h-415l-120 120v462h147v-435h434v435h147v-680zM657 601h-147v147h147v-147zM403 601h-147v147h147v-147z" />
|
||||
<glyph glyph-name="Ydieresis" unicode="Ÿ" horiz-adv-x="935"
|
||||
d="M860 592l-290 -291v-301h-147v301l-290 291v136h147v-84l217 -217l216 217v84h147v-136zM694 782h-147v147h147v-147zM440 782h-147v147h147v-147z" />
|
||||
<glyph glyph-name="fraction" unicode="⁄" horiz-adv-x="769"
|
||||
d="M694 592l-472 -472v-120h-147v172l472 472v120h147v-172z" />
|
||||
<glyph glyph-name="currency" unicode="¤" horiz-adv-x="986"
|
||||
d="M911 120l-120 -120h-523l-120 120v98h-73v292h73v98l120 120h523l120 -120v-136h-146v109h-470v-71h217v-292h-217v-71h470v109h146v-136z" />
|
||||
<glyph glyph-name="guilsinglleft" unicode="‹" horiz-adv-x="406"
|
||||
d="M331 181h-100l-156 157v52l156 156h100v-99l-83 -83l83 -83v-100z" />
|
||||
<glyph glyph-name="guilsinglright" unicode="›" horiz-adv-x="406"
|
||||
d="M331 338l-156 -157h-100v100l83 83l-83 83v99h100l156 -156v-52z" />
|
||||
<glyph glyph-name="fi" unicode="" horiz-adv-x="986"
|
||||
d="M911 0h-135l-120 120v462h147v-435h108v-147zM803 581h-472v-107h326v-147h-326v-327h-147v327h-109v147h109v134l120 120h499v-147z" />
|
||||
<glyph glyph-name="fl" unicode="" horiz-adv-x="986"
|
||||
d="M911 0h-135l-120 120v461h-325v-107h326v-147h-326v-327h-147v327h-109v147h109v134l120 120h499v-581h108v-147z" />
|
||||
<glyph glyph-name="daggerdbl" unicode="‡" horiz-adv-x="660"
|
||||
d="M585 145h-182v-145h-147v145h-181v147h181v71h-181v147h181v109h147v-109h182v-147h-182v-71h182v-147z" />
|
||||
<glyph glyph-name="periodcentered" unicode="·" horiz-adv-x="297"
|
||||
d="M222 290h-147v147h147v-147z" />
|
||||
<glyph glyph-name="periodcentered" unicode="∙" horiz-adv-x="297"
|
||||
d="M222 290h-147v147h147v-147z" />
|
||||
<glyph glyph-name="quotesinglbase" unicode="‚" horiz-adv-x="297"
|
||||
d="M222 -25l-47 -48h-64v64l11 10l-47 46v100h147v-172z" />
|
||||
<glyph glyph-name="quotedblbase" unicode="„" horiz-adv-x="478"
|
||||
d="M403 -25l-47 -48h-63v64l10 10l-47 46v100h147v-172zM222 -25l-47 -48h-64v64l11 10l-47 46v100h147v-172z" />
|
||||
<glyph glyph-name="perthousand" unicode="‰" horiz-adv-x="1241"
|
||||
d="M1166 120l-121 -120h-124l-120 120v125l120 120h124l121 -120v-125zM766 592l-508 -508v-84h-147v136l508 508v84h147v-136zM803 120l-120 -120h-125l-120 120v125l120 120h125l120 -120v-125zM440 483l-120 -120h-125l-120 120v125l120 120h125l120 -120v-125zM1055 172
|
||||
v21l-62 61h-20l-62 -61v-21l62 -61h20zM329 535v21l-61 61h-21l-61 -61v-21l61 -61h21zM692 172v21l-61 61h-21l-61 -61v-21l61 -61h21z" />
|
||||
<glyph glyph-name="Acircumflex" unicode="Â" horiz-adv-x="935"
|
||||
d="M860 0h-147v181h-470v-181h-147v390l338 338h89l337 -338v-390zM713 328v10l-235 235l-235 -235v-10h470zM621 746h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="Ecircumflex" unicode="Ê" horiz-adv-x="863"
|
||||
d="M788 0h-692v728h692v-147h-545v-144h545v-147h-545v-143h545v-147zM585 746h-100l-64 64l-65 -64h-100v99l120 120h89l120 -120v-99z" />
|
||||
<glyph glyph-name="Aacute" unicode="Á" horiz-adv-x="935"
|
||||
d="M860 0h-147v181h-470v-181h-147v390l338 338h89l337 -338v-390zM713 328v10l-235 235l-235 -235v-10h470zM657 938l-192 -192h-136v63l193 193h135v-64z" />
|
||||
<glyph glyph-name="Edieresis" unicode="Ë" horiz-adv-x="863"
|
||||
d="M788 0h-692v728h692v-147h-545v-144h545v-147h-545v-143h545v-147zM621 746h-147v147h147v-147zM367 746h-147v147h147v-147z" />
|
||||
<glyph glyph-name="Egrave" unicode="È" horiz-adv-x="863"
|
||||
d="M788 0h-692v728h692v-147h-545v-144h545v-147h-545v-143h545v-147zM585 746h-136l-193 192v64h136q63 -64 193 -193v-63z" />
|
||||
<glyph glyph-name="Iacute" unicode="Í" horiz-adv-x="645"
|
||||
d="M570 0h-437v147h145v434h-145v147h437v-147h-145v-434h145v-147zM512 938l-192 -192h-136v63l192 193h136v-64z" />
|
||||
<glyph glyph-name="Icircumflex" unicode="Î" horiz-adv-x="645"
|
||||
d="M570 0h-437v147h145v434h-145v147h437v-147h-145v-434h145v-147zM512 746h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="Idieresis" unicode="Ï" horiz-adv-x="645"
|
||||
d="M570 0h-437v147h145v434h-145v147h437v-147h-145v-434h145v-147zM549 746h-147v147h147v-147zM295 746h-147v147h147v-147z" />
|
||||
<glyph glyph-name="Igrave" unicode="Ì" horiz-adv-x="645"
|
||||
d="M570 0h-437v147h145v434h-145v147h437v-147h-145v-434h145v-147zM440 746h-136l-193 192v64h136q63 -64 193 -193v-63z" />
|
||||
<glyph glyph-name="Oacute" unicode="Ó" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM713 147v434h-470v-434h470zM657 938l-192 -192h-136v63l193 193h135v-64z" />
|
||||
<glyph glyph-name="Ocircumflex" unicode="Ô" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM713 147v434h-470v-434h470zM621 746h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="apple" unicode="" horiz-adv-x="716"
|
||||
d="M641 655l-14 -41l12 8l-10 -33l1 1v-64l-57 -74l-27 26l82 63v-58l-17 -23l-17 -23l-25 28q28 16 30 17v0l31 18l-8 -46l17 9l-28 -61l21 8l-30 -61l-5 -28l20 2l-40 -40l40 -6l-65 -28l15 -7l-47 -21l13 -15h-71l-9 3l-14 -14l-8 32l61 -21l-31 -19l11 -8h3l4 2l7 17
|
||||
l27 14l21 -22l15 -29l-1 -12l3 -19l-11 -12l-3 -13l-31 -43l-10 29l-12 12l-9 -7h-3l-1 -9l10 -21l-57 14l-16 15l-7 24l14 23l-4 3l-21 11l-17 17l32 19l13 -37l8 -27l-15 -17l5 -22l-3 -83l-29 27l-26 -64l-26 64l-29 -27l-3 83l5 22l-15 17l2 7l-6 -5l-5 -8l-12 29l31 -6
|
||||
l15 -26l-7 -24l-15 -15l-57 -14l10 21l-2 9h-3l-16 11l-4 18l15 -10l5 4l-5 -12l-15 -16l-11 -29l-31 43l-3 13l-11 12l4 19l-2 12l15 29l22 22l26 -14l7 -17l4 -2h4l10 8l-31 19l32 11l-5 4l29 10l7 21l25 -24l-58 -22h-71l13 15l-47 21l15 7l-65 28l40 6l-40 40l20 -2
|
||||
l-5 28l-30 61l21 -8l-27 61l16 -9l-7 46l30 -18v0l30 -17l-25 -28l-17 23l-17 23v41l-2 2v64l1 -1l-10 33l12 -8l-14 41l73 -57l38 -41l1 16l113 -145l26 -68l-21 -15l-1 -5q-6 0 -11 2l-9 -9l15 34l2 13l-5 15l13 19h3l1 5l20 -22l-15 -1l-14 11l-8 19l-6 9l-17 17l4 4
|
||||
q-4 7 -32 103l65 -73l15 -10l16 -14l8 -25l-38 -7l-1 16l-5 5l-26 -2l10 37l16 22l24 3l9 -2l4 2l20 -9l20 -18l14 -6l36 7l-8 -53l-7 -6l5 -10l6 -48h-4l1 -5l5 -14l14 -9l-12 -24l-9 -7l-6 24l-2 -6l-4 18l-21 15l26 68l113 145l1 -16l39 41z" />
|
||||
<glyph glyph-name="Ograve" unicode="Ò" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v488l120 120h524l120 -120v-488zM713 147v434h-470v-434h470zM549 746h-136l-193 192v64h136q63 -64 193 -193v-63z" />
|
||||
<glyph glyph-name="Uacute" unicode="Ú" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v608h147v-581h470v581h147v-608zM657 938l-192 -192h-136v63l193 193h135v-64z" />
|
||||
<glyph glyph-name="Ucircumflex" unicode="Û" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v608h147v-581h470v581h147v-608zM621 746h-99l-65 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="Ugrave" unicode="Ù" horiz-adv-x="935"
|
||||
d="M860 120l-120 -120h-524l-120 120v608h147v-581h470v581h147v-608zM549 746h-136l-193 192v64h136q63 -64 193 -193v-63z" />
|
||||
<glyph glyph-name="dotlessi" unicode="ı" horiz-adv-x="406"
|
||||
d="M331 0h-136l-120 120v462h147v-435h109v-147z" />
|
||||
<glyph glyph-name="circumflex" unicode="ˆ" horiz-adv-x="435"
|
||||
d="M382 601h-100l-64 64l-65 -64h-99v99l120 120h88l120 -120v-99z" />
|
||||
<glyph glyph-name="tilde" unicode="˜" horiz-adv-x="653"
|
||||
d="M600 721l-120 -120h-125l-119 119l-119 -119h-63v135l120 120h124l119 -119l119 119h64v-135z" />
|
||||
<glyph glyph-name="macron" unicode="¯" horiz-adv-x="726"
|
||||
d="M418 710h-364v146h364v-146z" />
|
||||
<glyph glyph-name="macron" unicode="ˉ" horiz-adv-x="726"
|
||||
d="M418 710h-364v146h364v-146z" />
|
||||
<glyph glyph-name="breve" unicode="˘" horiz-adv-x="581"
|
||||
d="M527 757l-120 -120h-233l-120 120v99h110v-47l25 -25h202l25 25v47h111v-99z" />
|
||||
<glyph glyph-name="dotaccent" unicode="˙" horiz-adv-x="254"
|
||||
d="M200 746h-146v147h146v-147z" />
|
||||
<glyph glyph-name="ring" unicode="˚" horiz-adv-x="871"
|
||||
d="M455 721l-121 -120h-160l-120 120v124l120 120h160l121 -120v-124zM318 783l-64 64l-64 -64l64 -64z" />
|
||||
<glyph glyph-name="cedilla" unicode="¸" horiz-adv-x="871"
|
||||
d="M418 -150l-84 -84h-197l-47 47v100h110v-36h82l18 17l-65 65v99h99l84 -84v-124z" />
|
||||
<glyph glyph-name="hungarumlaut" unicode="˝" horiz-adv-x="762"
|
||||
d="M600 938l-193 -192h-136v63l193 193h136v-64zM382 938l-193 -192h-135v63l192 193h136v-64z" />
|
||||
<glyph glyph-name="ogonek" unicode="˛" horiz-adv-x="871"
|
||||
d="M527 -187l-47 -47h-198l-83 84v124l47 48h136v-63l-47 -47l36 -35h45v36h111v-100z" />
|
||||
<glyph glyph-name="caron" unicode="ˇ" horiz-adv-x="399"
|
||||
d="M382 866l-120 -120h-88l-120 120v99h99l65 -64l64 64h100v-99z" />
|
||||
<hkern u1="A" u2="Y" k="100" />
|
||||
<hkern u1="A" u2="T" k="100" />
|
||||
<hkern u1="L" u2="Y" k="100" />
|
||||
<hkern u1="L" u2="T" k="200" />
|
||||
<hkern u1="T" u2="J" k="200" />
|
||||
<hkern u1="T" u2="A" k="100" />
|
||||
<hkern u1="Y" u2="A" k="100" />
|
||||
<hkern u1="g" u2="j" k="-100" />
|
||||
<hkern u1="j" u2="j" k="-100" />
|
||||
<hkern u1="y" u2="j" k="-100" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,11 @@
|
|||
import {createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import store from "./store";
|
||||
|
||||
// Vue.config.productionTip = false;
|
||||
|
||||
let app = createApp(App);
|
||||
app.use(store);
|
||||
app.mount("#app");
|
||||
|
||||
store.dispatch("check_user");
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import { createStore } from 'vuex'
|
||||
|
||||
export const store = createStore({
|
||||
state: {
|
||||
user: null,
|
||||
},
|
||||
mutations: {
|
||||
set_user(state, user) {
|
||||
state.user = user;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async check_user({ commit }) {
|
||||
let u = await fetch("/is_authenticated/", { Accept: "application/json" });
|
||||
let j = await u.json();
|
||||
if (j.user === null) {
|
||||
window.location = "/login/?next=/frontend/";
|
||||
} else {
|
||||
commit("set_user", j.user);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
<template>
|
||||
<div class="container">
|
||||
<template v-if="$store.state.user">
|
||||
Benvenuto {{ $store.state.user }}!
|
||||
</template>
|
||||
<template v-else>Non sei loggato!</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
const WebpackObfuscator = require("webpack-obfuscator");
|
||||
//const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
|
||||
// .BundleAnalyzerPlugin;
|
||||
|
||||
let plugins = [
|
||||
//new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
//new BundleAnalyzerPlugin(),
|
||||
];
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
plugins.push(
|
||||
new WebpackObfuscator(
|
||||
{
|
||||
rotateStringArray: true,
|
||||
},
|
||||
["**/chunk-vendors.*.js"]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
configureWebpack: {
|
||||
devtool: process.env.NODE_ENV === "production" ? "none" : "eval-source-map",
|
||||
plugins: plugins,
|
||||
},
|
||||
runtimeCompiler: false,
|
||||
lintOnSave: true,
|
||||
publicPath: "",
|
||||
};
|
||||
Loading…
Reference in New Issue