From 380551d26c25ff599d510789b43de73321e29edb Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Wed, 19 Jul 2017 12:44:46 +0200
Subject: [PATCH] Add QR Codes page

---
 app/main/views.py           | 14 ++++++++++++++
 app/templates/_helpers.html |  3 +++
 app/templates/base.html     |  3 +++
 app/templates/qrcodes.html  | 22 ++++++++++++++++++++++
 app/utils.py                | 14 ++++++++++++++
 5 files changed, 56 insertions(+)
 create mode 100644 app/templates/_helpers.html
 create mode 100644 app/templates/qrcodes.html

diff --git a/app/main/views.py b/app/main/views.py
index 4697866..5faf01d 100644
--- a/app/main/views.py
+++ b/app/main/views.py
@@ -12,6 +12,7 @@ This module implements the main blueprint.
 from flask import (Blueprint, render_template, jsonify)
 from flask_login import login_required
 from ..extensions import db
+from ..models import Action, Vendor, Model, Location, Status
 from .. import utils
 
 bp = Blueprint('main', __name__)
@@ -54,3 +55,16 @@ def retrieve_items():
 @login_required
 def index():
     return render_template('index.html')
+
+
+@bp.route('/qrcodes')
+@login_required
+def qrcodes():
+    codes = {}
+    for model in (Action, Vendor, Model, Location, Status):
+        items = db.session.query(model).order_by(model.name)
+        images = [{'name': item.name,
+                   'data': utils.image_to_base64(item.image())}
+                  for item in items]
+        codes[model.__name__] = images
+    return render_template('qrcodes.html', codes=codes)
diff --git a/app/templates/_helpers.html b/app/templates/_helpers.html
new file mode 100644
index 0000000..efe2ae6
--- /dev/null
+++ b/app/templates/_helpers.html
@@ -0,0 +1,3 @@
+{% macro nav_li(active) -%}
+<li {% if active %}class="active"{% endif %}>
+{%- endmacro %}
diff --git a/app/templates/base.html b/app/templates/base.html
index 0bb69b5..4c13148 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -1,5 +1,6 @@
 {%- extends "bootstrap/base.html" %}
 {% import "bootstrap/utils.html" as utils %}
+{% from "_helpers.html" import nav_li %}
 
 {% block head %}
   <meta charset="utf-8">
@@ -32,6 +33,8 @@
       <div class="navbar-collapse collapse">
         <ul class="nav navbar-nav">
           {% set path = request.path %}
+          {{ nav_li(path in ("/", "/index", "/index/")) }}<a href="{{ url_for('main.index') }}">Index</a></li>
+	  {{ nav_li(path == "/qrcodes") }}<a href="{{ url_for('main.qrcodes') }}">QR Codes</a></li>
           {% if current_user.is_authenticated and current_user.is_admin %}
             <li><a href="{{ url_for('admin.index') }}">Admin</a></li>
           {% endif %}
diff --git a/app/templates/qrcodes.html b/app/templates/qrcodes.html
new file mode 100644
index 0000000..de29285
--- /dev/null
+++ b/app/templates/qrcodes.html
@@ -0,0 +1,22 @@
+{%- extends "base.html" %}
+{% import "bootstrap/wtf.html" as wtf %}
+
+{% block title %}QR Codes{% endblock %}
+
+{% block main %}
+  {% for name, images in codes.items() %}
+  <div class="row">
+    <h2>{{ name }} codes</h2>
+    {% for image in images %}
+    <div class="col-md-3">
+      <div class="thumbnail">
+        <img src="data:image/png;base64,{{ image.data }}"/>
+        <div class="caption">
+          <h3>{{ image.name }}</h3>
+        </div>
+      </div>
+    </div>
+    {% endfor %}
+  </div>
+  {% endfor %}
+{%- endblock %}
diff --git a/app/utils.py b/app/utils.py
index b93c5ba..779a6f5 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -9,6 +9,8 @@ This module implements utility functions.
 :license: BSD 2-Clause, see LICENSE for more details.
 
 """
+import base64
+import io
 import hashlib
 import uuid
 
@@ -39,3 +41,15 @@ class InventoryError(Exception):
 def compute_hash(string):
     md5 = hashlib.md5(string.encode()).hexdigest()
     return uuid.UUID(md5)
+
+
+def image_to_base64(img, format='PNG'):
+    """Convert a Pillow image to a base64 string
+
+    :param img: Pillow image
+    :param format: format of the image to use
+    :returns str: image as base64 string
+    """
+    buf = io.BytesIO()
+    img.save(buf, format=format)
+    return base64.b64encode(buf.getvalue()).decode('ascii')
-- 
GitLab