Now handles uploading new tempaltes!!1

Just point your browser to /zetikettes/newtikette.html
Password is in web.py
This commit is contained in:
Paul Mathieu 2023-06-28 23:17:03 +02:00
parent c4e03c9550
commit f3c2a2f725
7 changed files with 352 additions and 286 deletions

View File

@ -27,10 +27,7 @@ docker run -d --rm -p 8000:8000 -v /var/lib/zetikettes/templates:/data zetikette
Change available templates Change available templates
-------------------------- --------------------------
1. make or update templates 1. go to /zetikettes/newtikette.html
1. add them to tempaltes/ 1. add the newtikette
1. update static/zetikettes.js 1. still no need to restart the container (magic!)
1. git commit && git push
1. update /var/lib/zetikettes
1. no need to restart the container (magic!)
2. profit. 2. profit.

View File

@ -3,7 +3,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>zetikettes 0.1</title> <title>zetikettes 0.2</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Compiled and minified CSS --> <!-- Compiled and minified CSS -->

45
static/newtikette.html Normal file
View File

@ -0,0 +1,45 @@
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>zetikettes 0.2</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="config.js"></script>
<script src="newtikette.js"></script>
<style>
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1 0 auto;
}
</style>
</head>
<body>
<header class="container center orange-text">
<h1>Zétikwett's</h1>
</header>
<main class="container row">
<div class="col m6 offset-m3 s12">
<div id="appbody" class="container"></div>
</div>
</main>
<footer class="page-footer">
<div class="container row">
<span class="col right">displayed with recycled electrons.</span>
</div>
</footer>
</body>
</html>

130
static/newtikette.js Normal file
View File

@ -0,0 +1,130 @@
const backend_api = {
'prod': '/zetikettes/srv/',
'dev': '/zetikettes.dev/srv/',
}[config];
const params = [
['dluo', 'DLUO', true],
['lot', 'Nº de lot', true],
['qty', 'Poids net (g)', true],
['teneur', 'Teneur en fruits (%)', false],
['fruit', 'Quantité de fruits pour 100g (g)', false],
]
function post() {
const lemot = $('input[type=password]').val();
const formdata = new FormData($('form')[0]);
formdata.append('lemotdepasse', lemot);
$.ajax({
url: backend_api + `newtikette`,
type: 'POST',
data: formdata,
contentType: false,
processData: false,
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
// For handling the progress of the upload
myXhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
$('progress').attr({
value: e.loaded,
max: e.total,
});
}
}, false);
}
return myXhr;
}
})
.then(data => {
console.log(data);
})
.catch(err => {
console.log(err);
if (err.status == 403) {
M.toast({html: 'access denied'});
} else if (err.status == 500) {
M.toast({html: 'server error'});
}
})
.always(() => {
$('.progress').hide();
$('.btn').removeClass('disabled');
});
}
$(document).ready(async () => {
const appbody = $("#appbody");
const block = $('<form class="section">');
block.append($(`<div class="input-field"><label class="active">Title</label>
<input type="text" name="title" value="Gelée de brandade aux cêpes biou">`));
block.append($(`<div class="input-field"><label class="active">
<input type="checkbox" name="landscape"><span>landscape</span></label>`));
const subst = $('<div class="section"><label class="active">Substitutions</label><p></p>');
for (let param of params) {
subst.append($(`<div><label class="active"><input type="checkbox" name="${param}" ${param[2] ? 'checked': ''}>
<span>\${${param[0]}}: ${param[1]}</span></label>`));
}
block.append(subst);
block.append(`<div class="file-field input-field">
<div class="btn">
<span>File</span>
<input type="file" name="sticker" accept=".svg">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Template .svg file">
</div>
`)
const loader = $('<div class="progress"><div class="determinate"></div></div>')
.hide();
let setup = false;
const action = $('<div class="section">')
.append($('<a class="btn">add newtikette<a>')
.click(() => {
if (!setup) {
setup = true;
$('input[type=password]').on('keydown', e => {
if (e.keyCode == 13 && !e.repeat) {
$('.modal').modal('close');
post();
}
});
$("#pushgo").click(() => { post(); });
}
$('.modal').modal('open');
$('input[type=password]').focus();
loader.show();
$('.btn').addClass("disabled");
$('.modal-close').removeClass("disabled");
})
.append(loader));
const lemotdepasse = $(`
<div id="modal1" class="modal">
<div class="modal-content">
<h4>A lemotdepasse is needed</h4>
<div class="input-field"><label class="active">lemotdepasse</label>
<input type="password">
</div>
<div class="modal-footer">
<a class="btn modal-close" id="pushgo">go</a>
</div>
`);
appbody
.append(lemotdepasse)
.append(block)
.append(action);
$(".modal").modal();
});

View File

@ -3,275 +3,6 @@ const backend_api = {
'dev': '/zetikettes.dev/srv/', 'dev': '/zetikettes.dev/srv/',
}[config]; }[config];
const zetikettes = [
{
'title': 'Aromate herbes de Provence',
'sticker': 'Aromate - Herbes de Provence.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': false,
},
{
'title': 'Aromate herbes de Provence avec romarin',
'sticker': 'Aromate - Herbes de Provence avec romarin.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': false,
},
{
'title': 'Aromate thym',
'sticker': 'Aromate - Thym.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': false,
},
{
'title': 'Chocolat lavande',
'sticker': 'Chocolat - Lavande.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '100',
},
'landscape': false,
},
{
'title': 'Confiture de Mirabelle - non bio',
'sticker': 'Confiture - Mirabelle.svg',
'subs': {
'dluo': 'germinal 9999',
'fruit': '80',
'teneur': '50',
'lot': '0000-0',
'qty': '370',
},
'landscape': true,
},
{
'title': 'Gelée Extra de groseille',
'sticker': 'Gelée Extra - Groseille.svg',
'subs': {
'dluo': 'germinal 9999',
'fruit': '80',
'teneur': '50',
'lot': '0000-0',
'qty': '370',
},
'landscape': true,
},
{
'title': 'Gelée Extra de groseille au basilic',
'sticker': 'Gelée Extra - Groseille Basilic.svg',
'subs': {
'dluo': 'germinal 9999',
'fruit': '80',
'teneur': '50',
'lot': '0000-0',
'qty': '370',
},
'landscape': true,
},
{
'title': 'Gelée Extra de cassis',
'sticker': 'Gelée Extra - Cassis.svg',
'subs': {
'dluo': 'germinal 9999',
'fruit': '80',
'teneur': '50',
'lot': '0000-0',
'qty': '370',
},
'landscape': true,
},
{
'title': 'Pesto ail des ours',
'sticker': 'Pesto - Ail des Ours - 100% Olive.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '150',
},
'landscape': true,
},
{
'title': 'Sel grillade et légumes',
'sticker': 'Sel - Grillade.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': true,
},
{
'title': 'Sel herbes de Provence',
'sticker': 'Sel - Herbes de Provence.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': true,
},
{
'title': 'Sel viande blanche et poisson',
'sticker': 'Sel - Poisson et Viande Blanche.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': true,
},
{
'title': 'Sel salade',
'sticker': 'Sel - Salade.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': true,
},
{
'title': 'Sel salade sans basilic',
'sticker': 'Sel - Salade - Sans Basilic.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '40',
},
'landscape': true,
},
{
'title': 'Sirop de sureau',
'sticker': 'Sirop - Sureau.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '75',
},
},
{
'title': 'Sirop de lavande',
'sticker': 'Sirop - Lavande.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '75',
},
},
{
'title': 'Sirop de cassis',
'sticker': 'Sirop - Cassis.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '75',
},
'landscape': false,
},
{
'title': 'Sirop de thym',
'sticker': 'Sirop - Thym.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '75',
},
'landscape': false,
},
{
'title': 'Sirop de mélisse',
'sticker': 'Sirop - Melisse.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '75',
},
'landscape': false,
},
{
'title': 'Sirop de menthe verte',
'sticker': 'Sirop - Menthe Verte.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '75',
},
'landscape': false,
},
{
'title': 'Tisane Hiver',
'sticker': 'Tisane - Hiver.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '25',
},
'landscape': false,
},
{
'title': 'Tisane Joie de Vivre',
'sticker': 'Tisane - Joie de Vivre.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '25',
},
'landscape': false,
},
{
'title': 'Tisane Réconfort de la Gorge (Origan, Thym, Agastache, Mauve)',
'sticker': 'Tisane - Reconfort de la Gorge - Origan Thym Agastache Mauve.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '25',
},
'landscape': false,
},
{
'title': 'Tisane Nuit Étoilée (Mélisse, Lavande, Aubépine)',
'sticker': 'Tisane - Nuit Etoilee - Melisse Lavande Aubepine.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '25',
},
'landscape': false,
},
{
'title': 'Tisane Détox (Menthe, Sarriette, Basilic, Souci)',
'sticker': 'Tisane - Detox - Menthe Sarriette Basilic Souci.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '25',
},
'landscape': false,
},
{
'title': 'Tisane digestion',
'sticker': 'Tisane - Digestion.svg',
'subs': {
'dluo': 'germinal 9999',
'lot': '0000-0',
'qty': '25',
},
'landscape': false,
},
];
const params = { const params = {
'dluo': 'DLUO', 'dluo': 'DLUO',
'lot': 'Nº de lot', 'lot': 'Nº de lot',
@ -281,7 +12,7 @@ const params = {
'fruit': 'Quantité de fruits pour 100g (g)', 'fruit': 'Quantité de fruits pour 100g (g)',
} }
$(document).ready(() => { function loadAll(zetikettes) {
const appbody = $("#appbody"); const appbody = $("#appbody");
for (let zett of zetikettes) { for (let zett of zetikettes) {
const block = $('<div class="section">'); const block = $('<div class="section">');
@ -331,4 +62,18 @@ $(document).ready(() => {
} }
$('.collapsible').collapsible(); $('.collapsible').collapsible();
}
$(document).ready(async () => {
try {
const resp = await $.ajax({
url: backend_api + 'list',
timeout: 1000,
});
loadAll(resp.tikettes);
} catch(e) {
const appbody = $("#appbody");
appbody.append(`<li>Could not reach backend server`);
throw e;
}
}); });

1
tikettes.json Normal file
View File

@ -0,0 +1 @@
[{"title":"Aromate herbes de Provence","sticker":"Aromate - Herbes de Provence.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":false},{"title":"Aromate herbes de Provence avec romarin","sticker":"Aromate - Herbes de Provence avec romarin.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":false},{"title":"Aromate thym","sticker":"Aromate - Thym.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":false},{"title":"Chocolat lavande","sticker":"Chocolat - Lavande.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"100"},"landscape":false},{"title":"Confiture de Mirabelle - non bio","sticker":"Confiture - Mirabelle.svg","subs":{"dluo":"germinal 9999","fruit":"80","teneur":"50","lot":"0000-0","qty":"370"},"landscape":true},{"title":"Gelée Extra de groseille","sticker":"Gelée Extra - Groseille.svg","subs":{"dluo":"germinal 9999","fruit":"80","teneur":"50","lot":"0000-0","qty":"370"},"landscape":true},{"title":"Gelée Extra de groseille au basilic","sticker":"Gelée Extra - Groseille Basilic.svg","subs":{"dluo":"germinal 9999","fruit":"80","teneur":"50","lot":"0000-0","qty":"370"},"landscape":true},{"title":"Gelée Extra de cassis","sticker":"Gelée Extra - Cassis.svg","subs":{"dluo":"germinal 9999","fruit":"80","teneur":"50","lot":"0000-0","qty":"370"},"landscape":true},{"title":"Pesto ail des ours","sticker":"Pesto - Ail des Ours - 100% Olive.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"150"},"landscape":true},{"title":"Sel grillade et légumes","sticker":"Sel - Grillade.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":true},{"title":"Sel herbes de Provence","sticker":"Sel - Herbes de Provence.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":true},{"title":"Sel viande blanche et poisson","sticker":"Sel - Poisson et Viande Blanche.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":true},{"title":"Sel salade","sticker":"Sel - Salade.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":true},{"title":"Sel salade sans basilic","sticker":"Sel - Salade - Sans Basilic.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"40"},"landscape":true},{"title":"Sirop de sureau","sticker":"Sirop - Sureau.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"75"}},{"title":"Sirop de lavande","sticker":"Sirop - Lavande.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"75"}},{"title":"Sirop de cassis","sticker":"Sirop - Cassis.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"75"},"landscape":false},{"title":"Sirop de thym","sticker":"Sirop - Thym.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"75"},"landscape":false},{"title":"Sirop de mélisse","sticker":"Sirop - Melisse.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"75"},"landscape":false},{"title":"Sirop de menthe verte","sticker":"Sirop - Menthe Verte.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"75"},"landscape":false},{"title":"Tisane Hiver","sticker":"Tisane - Hiver.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"25"},"landscape":false},{"title":"Tisane Joie de Vivre","sticker":"Tisane - Joie de Vivre.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"25"},"landscape":false},{"title":"Tisane Réconfort de la Gorge (Origan, Thym, Agastache, Mauve)","sticker":"Tisane - Reconfort de la Gorge - Origan Thym Agastache Mauve.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"25"},"landscape":false},{"title":"Tisane Nuit Étoilée (Mélisse, Lavande, Aubépine)","sticker":"Tisane - Nuit Etoilee - Melisse Lavande Aubepine.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"25"},"landscape":false},{"title":"Tisane Détox (Menthe, Sarriette, Basilic, Souci)","sticker":"Tisane - Detox - Menthe Sarriette Basilic Souci.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"25"},"landscape":false},{"title":"Tisane digestion","sticker":"Tisane - Digestion.svg","subs":{"dluo":"germinal 9999","lot":"0000-0","qty":"25"},"landscape":false}]

160
web.py
View File

@ -1,5 +1,8 @@
import argparse
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
import io
import json import json
import logging
import os import os
import re import re
import string import string
@ -11,10 +14,22 @@ import traceback
from makesticker import makesticker from makesticker import makesticker
from makeplanche import makeplanche from makeplanche import makeplanche
# defaults
PORT = 8000 PORT = 8000
OUT_DIR = tempfile.gettempdir() OUT_DIR = tempfile.gettempdir()
TEMPLATE_DIR = '/data' DATA_DIR = '/data'
TEMPLATE_DIR = DATA_DIR
DEFAULT_DPI = 300 DEFAULT_DPI = 300
LEMOTDEPASSE = 'je veux ajouter une étiquette'
TIKETTES = os.path.join(DATA_DIR, 'tikettes.json')
config = {}
def tikettes_path():
return config.get('tikettes', TIKETTES)
def template_dir():
return config.get('template_dir', TEMPLATE_DIR)
def inkscapize(svg_in, pdf_out): def inkscapize(svg_in, pdf_out):
@ -31,7 +46,41 @@ def inkscapize(svg_in, pdf_out):
os.unlink(png_out) os.unlink(png_out)
def parse_request(request): def handle_newtikette(formdata):
with open(tikettes_path()) as f:
tikettes = json.load(f)
sticker = formdata['title'] + '.svg'
with open(os.path.join(template_dir(), sticker), 'w') as f:
f.write(formdata['sticker'])
known_subs = {
"dluo": "germinal 9999",
"fruit": "80",
"teneur": "50",
"lot": "0000-0",
"qty": "370",
"vol": "50",
}
newtikette = {
'title': formdata['title'],
'sticker': sticker,
'landscape': 'landscape' in formdata,
'subs': {k: v for k, v in known_subs.items() if k in formdata},
}
logging.info(f'adding newtikette: {newtikette}')
tikettes.append(newtikette)
with open(tikettes_path(), 'w') as f:
json.dump(tikettes, f, indent=2)
return json.dumps({'status': 'ok', 'message': 'newtikette added'})
def handle_generate(request):
request = json.loads(request) request = json.loads(request)
# fill in sticker details # fill in sticker details
@ -41,7 +90,7 @@ def parse_request(request):
with open(sticker_out, 'w') as stickout: with open(sticker_out, 'w') as stickout:
landscape = request.get('landscape', False) landscape = request.get('landscape', False)
print(f'landscape: {landscape}') print(f'landscape: {landscape}')
makesticker(os.path.join(TEMPLATE_DIR, request['sticker']), stickout, makesticker(os.path.join(template_dir(), request['sticker']), stickout,
request['subs'], landscape=landscape) request['subs'], landscape=landscape)
# make sticker sheet # make sticker sheet
@ -65,8 +114,68 @@ def parse_request(request):
os.unlink(planche_out) os.unlink(planche_out)
def parse_multipart(data, boundary):
logging.debug(f'parsing data with boundary: {boundary}')
f = io.StringIO(data)
out = []
if boundary not in f.readline():
return out
while True:
headers = []
while True:
h = f.readline().strip()
try:
k, v = re.findall(r'^([a-zA-Z-]+): (.*)$', h)[0]
except IndexError:
break
headers.append((k, v))
metadata = None
otherheaders = []
logging.debug(headers)
for k, v in headers:
if k == 'Content-Disposition':
parts = v.split('; ')
if parts[0] != 'form-data':
continue
d = dict(re.findall(r'([^=]+)="(.*)"$', p)[0] for p in parts[1:])
metadata = d
else:
otherheaders.append((k, v))
value = io.StringIO()
while True:
l = f.readline()
if not l:
break
if boundary in l:
# value.write(l.split(boundary)[0])
break
value.write(l)
if metadata is None:
break
logging.debug(f'({metadata}, {value.getvalue()[:-2]}, {otherheaders})')
out.append((metadata, value.getvalue()[:-2], otherheaders))
return out
class MyServer(BaseHTTPRequestHandler): class MyServer(BaseHTTPRequestHandler):
def do_GET(self): def do_GET(self):
logging.info(f'GET {self.path}')
if self.path == '/list':
self.send_response(200)
self.send_header("Content-type", "application/json")
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
with open(tikettes_path()) as f:
tikettes = json.load(f)
resp = {'status': 'ok', 'message': 'this is the way',
'tikettes': tikettes}
self.wfile.write(json.dumps(resp).encode())
return
match = re.match(r'/data/(\w+\.pdf)', self.path) match = re.match(r'/data/(\w+\.pdf)', self.path)
if match is not None: if match is not None:
pdf_path = os.path.join(OUT_DIR, match.groups()[0]) pdf_path = os.path.join(OUT_DIR, match.groups()[0])
@ -89,14 +198,37 @@ class MyServer(BaseHTTPRequestHandler):
self.wfile.write("<p>This is not the way.</p>".encode()) self.wfile.write("<p>This is not the way.</p>".encode())
self.wfile.write(b"</body></html>") self.wfile.write(b"</body></html>")
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
def do_POST(self): def do_POST(self):
logging.info(f'POST {self.path}')
try: try:
length = int(self.headers['content-length']) length = int(self.headers['content-length'])
req = self.rfile.read(length).decode() req = self.rfile.read(length).decode()
resp = parse_request(req).encode() if self.path == '/newtikette':
boundary = re.findall(r'boundary=(.*)$', self.headers['content-type'])[0]
formdata = {p['name']: v for p, v, _ in parse_multipart(req, boundary)}
logging.info({k: v[:100] for k, v in formdata.items()})
if formdata.get('lemotdepasse', None) != LEMOTDEPASSE:
logging.warning(f'wrong lemotdepasse')
self.send_response(403)
self.send_header("Content-type", "application/json")
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
self.wfile.write(json.dumps({'status': 'notok', 'message': 'bad lemotdepasse'}).encode())
return
resp = handle_newtikette(formdata).encode()
else:
resp = handle_generate(req).encode()
except: except:
self.send_response(500) self.send_response(500)
self.send_header("Content-type", "text/plain") self.send_header("Content-type", "text/plain")
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers() self.end_headers()
self.wfile.write(traceback.format_exc().encode()) self.wfile.write(traceback.format_exc().encode())
raise raise
@ -108,9 +240,25 @@ class MyServer(BaseHTTPRequestHandler):
self.wfile.write(resp) self.wfile.write(resp)
def parse_args():
parser = argparse.ArgumentParser(description='Zetikette backend')
parser.add_argument('--port', type=int, help=f'default: {PORT}')
parser.add_argument('--data-dir', help=f'default: {DATA_DIR}')
return parser.parse_args()
if __name__ == "__main__": if __name__ == "__main__":
webServer = HTTPServer(('', PORT), MyServer) logging.basicConfig(level=logging.INFO)
print(f"Server started on port {PORT}") args = parse_args()
config.update({
'tikettes': os.path.join(args.data_dir, 'tikettes.json'),
'template_dir': args.data_dir,
})
webServer = HTTPServer(('', args.port), MyServer)
print(f"Server started on port {args.port}")
try: try:
webServer.serve_forever() webServer.serve_forever()