commit d73b492cf240201e1516864932a5ab9dc880820e Author: Paul Mathieu Date: Tue Jul 12 12:04:38 2022 +0200 first!1! diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..968ef11 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM alpine + +RUN apk --no-cache add python3 inkscape bash imagemagick + +ADD . /root/zetikettes + +RUN apk --no-cache add ttf-opensans && cp /root/zetikettes/Karumbi.ttf /usr/share/fonts/TTF/ && fc-cache -fv + +# the script will look for templates in /data +WORKDIR /root/zetikettes +CMD /usr/bin/python3 web.py diff --git a/Karumbi.ttf b/Karumbi.ttf new file mode 100644 index 0000000..83150ad Binary files /dev/null and b/Karumbi.ttf differ diff --git a/makeplanche.py b/makeplanche.py new file mode 100755 index 0000000..c0639d9 --- /dev/null +++ b/makeplanche.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +import argparse +from pathlib import Path +from string import Template +import sys + +DEFAULT_SHEET_TEMPLATE = Path(__file__).parent / 'planche.svg.in' + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Make a sheet with 12 stickers') + parser.add_argument('--template', + '-t', + default=DEFAULT_SHEET_TEMPLATE, + help='path to the sheet template') + parser.add_argument('--out', + '-o', + default=sys.stdout, + type=argparse.FileType('w'), + help='output path (default: stdout)') + parser.add_argument('sticker', + type=argparse.FileType('r'), + default=sys.stdin, + nargs='?', + help='path to the sticker SVG (default: stdin)') + + return parser.parse_args() + + +def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE): + with open(template) as tpl: + tpl_data = tpl.read() + + lines = sticker.readlines() + if lines[0].startswith('{}".format(sticker_data) + + out.write(Template(sticker_data).substitute(subs)) + + +if __name__ == "__main__": + args = vars(parse_args()) + subs = { + 'dluo': args.pop('dluo'), + 'lot': args.pop('lot'), + 'teneur': args.pop('teneur'), + 'fruit': args.pop('fruit'), + 'qty': args.pop('quantite'), + 'size': args.pop('size'), + } + args['subs'] = subs + makesticker(**args) diff --git a/mkjam.sh b/mkjam.sh new file mode 100755 index 0000000..3afbaf0 --- /dev/null +++ b/mkjam.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +DEFAULT_DPI=300 +LARGE='370' # Large container (370g) +SMALL='220' # Small container (220g) + +SIZE=$LARGE +DLUO='décembre 2023' +LOT='0722-2' +TENEUR='50%' +FRUIT='80g' +STICKER='Gelée - Cassis.svg' + +PDF="`basename \"${STICKER}\" .svg` - ${LOT} (${SIZE}g).pdf" + +./makesticker.py --landscape --dluo "$DLUO" --lot "$LOT" --teneur "$TENEUR" --fruit "$FRUIT" --size "$SIZE" -o out.svg "$STICKER" && \ +./makeplanche.py -o pout.svg -t planche.svg.in out.svg && \ +rm out.svg && \ +inkscape --export-type="png" --export-dpi=$DEFAULT_DPI pout.svg && \ +rm pout.svg && \ +convert pout.png "$PDF" diff --git a/planche.svg.in b/planche.svg.in new file mode 100644 index 0000000..7fa6d85 --- /dev/null +++ b/planche.svg.in @@ -0,0 +1,24 @@ + + + + + $right0 + $right1 + $right2 + $right3 + $right4 + $right5 + + + $left0 + $left1 + $left2 + $left3 + $left4 + $left5 + + + diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..f9b24b6 --- /dev/null +++ b/static/index.html @@ -0,0 +1,44 @@ + + + + + + zetikettes 0.1 + + + + + + + + + + + + + +
+

Zétikwett's

+
+
+
+
    +
    +
    + + + diff --git a/static/zetikettes.js b/static/zetikettes.js new file mode 100644 index 0000000..36d5c6c --- /dev/null +++ b/static/zetikettes.js @@ -0,0 +1,128 @@ +const backend_api = '/zetikettes/srv/'; + +const zetikettes = [ + { + 'title': 'Aromate thym', + 'sticker': 'Aromate - Thym.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'lot': '0722-2', + 'qty': '40', + }, + 'landscape': false, + }, + { + 'title': 'Chocolat lavande', + 'sticker': 'Chocolat - Lavande.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'lot': '0722-2', + 'qty': '100', + }, + 'landscape': false, + }, + { + 'title': 'Gelée de cassis', + 'sticker': 'Gelée - Cassis.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'fruit': '80g', + 'teneur': '50%', + 'lot': '0722-2', + 'qty': '370', + }, + 'landscape': true, + }, + { + 'title': 'Pesto ail des ours', + 'sticker': 'Pesto - Ail des Ours - 100% Olive.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'lot': '0722-2', + 'qty': '150', + }, + 'landscape': true, + }, + { + 'title': 'Sel salade sans basilic', + 'sticker': 'Sel - Salade - Sans Basilic.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'lot': '0722-2', + 'qty': '40', + }, + 'landscape': true, + }, + { + 'title': 'Sirop de cassis', + 'sticker': 'Sirop - Cassis.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'lot': '0722-2', + 'qty': '75', + }, + 'landscape': false, + }, + { + 'title': 'Tisane digestion', + 'sticker': 'Tisane - Digestion.svg', + 'subs': { + 'dluo': 'décembre 2023', + 'lot': '0722-2', + 'qty': '25', + }, + 'landscape': false, + }, +]; + +$(document).ready(() => { + const appbody = $("#appbody"); + for (let zett of zetikettes) { + const block = $('
    '); + for (let sub in zett.subs) { + block.append($(`
    `)); + } + const loader = $('
    ') + .hide(); + + const action = $('
    ') + .append($('generate') + .click(() => { + const subs = block.find(':text') + .toArray() + .reduce((obj, el) => ({...obj, [el.name]: el.value}), {}); + const req = { + sticker: zett.sticker, + subs, + landscape: zett.landscape, + }; + + loader.show(); + $('.btn').addClass("disabled"); + + $.post(backend_api, JSON.stringify(req)) + .then(data => { + console.log(data); + const pdfbtn = $(`open pdf`); + action.append(pdfbtn); + }) + .catch(err => { + console.log(err); + }) + .always(() => { + loader.hide(); + $('.btn').removeClass('disabled'); + }); + }) + .append(loader)); + + appbody + .append($('
  • ') + .append($(`
    ${zett.title}
    `)) + .append($('
    ') + .append(block) + .append(action))); + } + + $('.collapsible').collapsible(); +}); diff --git a/templates/Aromate - Thym.svg b/templates/Aromate - Thym.svg new file mode 100755 index 0000000..ed9c6a3 --- /dev/null +++ b/templates/Aromate - Thym.svg @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + ${qty}G + POIDS NET : + Culture et cueillette à la maindans les Alpes de Haute-Provence + + + + + Aromate Biologique des Monges + À conserver dans un endroit sec, à l'abri de la lumière.À consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + + COMPOSITION + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UTILISATION + + + + AROMATE + AROMATE + + + + + + + + Thym + LOT $lot + Thym* + Le roi des aromates, à utiliser en branche ou effeuillé, pour agrémenter vos grillades, plats en sauce, poêlées... + + diff --git a/templates/Chocolat - Lavande.svg b/templates/Chocolat - Lavande.svg new file mode 100755 index 0000000..0fd6497 --- /dev/null +++ b/templates/Chocolat - Lavande.svg @@ -0,0 +1,877 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + ${qty}G + POIDS NET : + À conserver dans un endroit sec, à l'abri de la lumière.À consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + + + COMPOSITION + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lavande + Culture et cueillette à la maindans les Alpes de Haute-Provence + Chocolataux plantes biologiques des Monges + + + + + + + + LOT $lot + Chocolat de couverture noir* (pâte de cacao*, sucre de canne*, beurre de cacao*; peut contenir : lait), crème entière* (crème de lait à 30% de matière grasse*, stabilisants : carraghénanes), lavande* + + diff --git a/templates/Gelée - Cassis.svg b/templates/Gelée - Cassis.svg new file mode 100755 index 0000000..7094ca6 --- /dev/null +++ b/templates/Gelée - Cassis.svg @@ -0,0 +1,983 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + Ingrédients :Cassis*, sucre de canne* + Préparé avec $fruit de fruits pour 100g de produit finiTeneur totale en sucre : $teneurÀ conserver au frais après ouverture.À consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Culture et cueilletteà la main dans les Monges + + + ${qty}G + POIDS NET : + LOT $lot + + + + + + + + Gelée Extra de Cassis + Cuite au chaudron de cuivre + + diff --git a/templates/Pesto - Ail des Ours - 100% Olive.svg b/templates/Pesto - Ail des Ours - 100% Olive.svg new file mode 100755 index 0000000..ba728a7 --- /dev/null +++ b/templates/Pesto - Ail des Ours - 100% Olive.svg @@ -0,0 +1,973 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + Ingrédients :huile d'olive*, ail des ours* (34%), amandes*, jus de citron*, sel + À conserver au frais après ouverture.Couvrir d'huile après chaque utilisation.À consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Culture et cueilletteà la main dans les Monges + + + ${qty}G + POIDS NET : + LOT $lot + + + + + + + + Pesto d'Ail des Ours + + diff --git a/templates/Sel - Salade - Sans Basilic.svg b/templates/Sel - Salade - Sans Basilic.svg new file mode 100755 index 0000000..fabdf2f --- /dev/null +++ b/templates/Sel - Salade - Sans Basilic.svg @@ -0,0 +1,809 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + Ingrédients :sel de guérande, menthe verte*,thym*, souci*, bleuet* + À consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Culture et cueilletteà la main dans les Monges + + + ${qty}G + POIDS NET : + LOT $lot + + + + + + + + Sel aux Herbes + Salade Fleurie + + diff --git a/templates/Sirop - Cassis.svg b/templates/Sirop - Cassis.svg new file mode 100755 index 0000000..5c27cb5 --- /dev/null +++ b/templates/Sirop - Cassis.svg @@ -0,0 +1,1058 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + ${qty}cL + VOLUME : + Culture et cueillette à la maindans les Alpes de Haute-Provence + Sirop Biologique des Monges + Conserver au frais après ouverture et consommer dans les 2 moisÀ consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + + COMPOSITION + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DOSAGE + + + + SIROP + SIROP + + + + + + + + + + + + Cassis + LOT $lot + Sucre* (55%), Jus de cassis*,Jus de citron* + Diluer dans 6 à 8 fois son volume d'eau + + diff --git a/templates/Tisane - Digestion.svg b/templates/Tisane - Digestion.svg new file mode 100755 index 0000000..e80cd45 --- /dev/null +++ b/templates/Tisane - Digestion.svg @@ -0,0 +1,1001 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + ${qty}G + POIDS NET : + Culture et cueillette à la maindans les Alpes de Haute-Provence + + + + + Infusion Biologique des Monges + À conserver dans un endroit sec, à l'abri de la lumière.À consommer de préférence avant : $dluo*Produits issus de l'agriculture biologique + + anne.brogi@gmail.com + + 06 95 96 61 08 + + Lieu-dit Lèbre, 04200, Authon + Anne Brogi - "Un Brin de Folie" + + + + + + COMPOSITION + + + + + PRÉPARATION + + + + 4-5mn + + 85°C + + 1 c. à c. par tasse + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + J'ai Bien Mangé... + LOT $lot + Thym*, Menthe Poivrée*, Sauge* + + diff --git a/web.py b/web.py new file mode 100644 index 0000000..a3de57a --- /dev/null +++ b/web.py @@ -0,0 +1,119 @@ +from http.server import BaseHTTPRequestHandler, HTTPServer +import json +import os +import re +import string +import subprocess +import tempfile +import time +import traceback + +from makesticker import makesticker +from makeplanche import makeplanche + +PORT = 8000 +OUT_DIR = '/data' +TEMPLATE_DIR = '/data' +DEFAULT_DPI = 300 + + +def inkscapize(svg_in, pdf_out): + png_out = tempfile.mktemp(suffix='.png') + try: + cmd = ['inkscape', '--export-type=png', f'--export-filename={png_out}', + f'--export-dpi={DEFAULT_DPI}', svg_in] + subprocess.check_call(cmd) + + cmd = ['convert', png_out, pdf_out] + subprocess.check_call(cmd) + finally: + if os.path.exists(png_out): + os.unlink(png_out) + + +def parse_request(request): + request = json.loads(request) + + # fill in sticker details + sticker_out = tempfile.mktemp(suffix='.svg') + + try: + with open(sticker_out, 'w') as stickout: + landscape = request.get('landscape', False) + print(f'landscape: {landscape}') + makesticker(os.path.join(TEMPLATE_DIR, request['sticker']), stickout, + request['subs'], landscape=landscape) + + # make sticker sheet + planche_out = tempfile.mktemp(suffix='.svg') + with open(sticker_out, 'r') as stickin: + with open(planche_out, 'w') as planchout: + makeplanche(stickin, planchout) + + # process to printable pdf + pdf_out = tempfile.mktemp(dir=OUT_DIR, suffix='.pdf') + inkscapize(planche_out, pdf_out) + + response = {'status': 'ok', 'file': os.path.basename(pdf_out), + 'message': 'this is the way'} + return json.dumps(response) + + finally: + if os.path.exists(sticker_out): + os.unlink(sticker_out) + if 'planche_out' in locals() and os.path.exists(planche_out): + os.unlink(planche_out) + + +class MyServer(BaseHTTPRequestHandler): + def do_GET(self): + if re.match(r'/data/\w+\.pdf', self.path) is not None: + if not os.path.exists(self.path): + self.send_response(404) + self.end_headers() + return + self.send_response(200) + self.send_header("Content-type", "application/pdf") + self.end_headers() + with open(self.path, 'rb') as f: + self.wfile.write(f.read()) + return + + self.send_response(200) + self.send_header("Content-type", "text/html; charset=UTF-8") + self.end_headers() + self.wfile.write(b"Zetikettes") + self.wfile.write(b"") + self.wfile.write("

    This is not the way.

    ".encode()) + self.wfile.write(b"") + + def do_POST(self): + try: + length = int(self.headers['content-length']) + req = self.rfile.read(length).decode() + resp = parse_request(req).encode() + except: + self.send_response(500) + self.send_header("Content-type", "text/plain") + self.end_headers() + self.wfile.write(traceback.format_exc().encode()) + raise + + self.send_response(200) + self.send_header("Content-type", "application/json") + self.send_header('Access-Control-Allow-Origin', '*') + self.end_headers() + self.wfile.write(resp) + + +if __name__ == "__main__": + webServer = HTTPServer(('', PORT), MyServer) + print(f"Server started on port {PORT}") + + try: + webServer.serve_forever() + except KeyboardInterrupt: + pass + + webServer.server_close() + print("Server stopped.")