From c4ccf8af5f82c359bbe79538d8e745e21f17f06a Mon Sep 17 00:00:00 2001
From: Andrea Lepori <alepori@student.ethz.ch>
Date: Sun, 7 Aug 2022 11:05:03 +0200
Subject: add qr code to pdf approve, direct approval page

---
 client/templates/client/approve_doc_pdf.html    | 20 +++++-
 client/views.py                                 |  3 +-
 server/templates/server/approve_doc_direct.html | 93 +++++++++++++++++++++++++
 server/urls.py                                  |  1 +
 server/views.py                                 | 74 ++++++++++++++++++++
 templates/registration/base_client.html         |  2 +
 version.txt                                     |  2 +-
 7 files changed, 192 insertions(+), 3 deletions(-)
 create mode 100644 server/templates/server/approve_doc_direct.html

diff --git a/client/templates/client/approve_doc_pdf.html b/client/templates/client/approve_doc_pdf.html
index 244bc20..0cf4944 100644
--- a/client/templates/client/approve_doc_pdf.html
+++ b/client/templates/client/approve_doc_pdf.html
@@ -8,7 +8,12 @@
 </head>
 <body style="background: white;">
   <main style="margin-left: 10px;margin-right: 10px;margin-top: 10px; background: white;">
-    <br><br><br><br>
+    <div style="position: absolute; top: 10px; left: 10px;">
+      <div id="qrcode"></div>
+    </div>
+    <div class="row center">
+      <svg id="barcode"></svg>
+    </div>
     <br><br>
     <div class="row">
       <p class="center">{{doc.user.first_name}} {{doc.user.last_name}} ({{doc.user.username}})</p>
@@ -55,4 +60,17 @@
   </main>
 </body>
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
+<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/barcodes/JsBarcode.code128.min.js"></script>
+<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
+<script type="text/javascript">
+  JsBarcode("#barcode", {{doc.code}}, {width: 3, height: 40, displayValue: false});
+  var qrcode = new QRCode(document.getElementById("qrcode"), {
+    text: "{{ uri }}",
+    width: 128,
+    height: 128,
+    colorDark : "#000000",
+    colorLight : "#ffffff",
+    correctLevel : QRCode.CorrectLevel.H
+  });
+</script>
 </html>
\ No newline at end of file
diff --git a/client/views.py b/client/views.py
index 86142ef..3ddc417 100644
--- a/client/views.py
+++ b/client/views.py
@@ -1,5 +1,6 @@
 from django.db.models.expressions import OuterRef, Subquery
 from django.template.loader import get_template
+from django.urls import reverse
 from client.models import GroupSettings, UserCode, Keys, DocumentType, Document, PersonalData, KeyVal, MedicalData
 from django.db.models import Q
 from django.http import HttpResponse, HttpResponseRedirect, FileResponse
@@ -57,7 +58,7 @@ def index(request):
         if request.POST["action"][0] == 'f':
             # generate approve pdf
             template = get_template('client/approve_doc_pdf.html')
-            context = {'doc': document}
+            context = {'doc': document, 'uri': request.build_absolute_uri(reverse('approve_direct')) + "?code=" + str(document.code)}
             html = template.render(context)
             pdf = pdfkit.from_string(html, False)
             result = BytesIO(pdf)
diff --git a/server/templates/server/approve_doc_direct.html b/server/templates/server/approve_doc_direct.html
new file mode 100644
index 0000000..2a6710b
--- /dev/null
+++ b/server/templates/server/approve_doc_direct.html
@@ -0,0 +1,93 @@
+{% extends 'registration/base_simple.html' %}
+
+{% block title %}Admin - Approva documento diretto{% endblock %}
+
+{% block style %}
+*{padding:0;margin:0}.wrapper{display:flex;justify-content:center;align-items:center;background-color:#fff}.checkmark__circle{stroke-dasharray: 166;stroke-dashoffset: 166;stroke-width: 2;stroke-miterlimit: 10;stroke: #7ac142;fill: none;animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards}.checkmark{width: 56px;height: 56px;border-radius: 50%;display: block;stroke-width: 2;stroke: #fff;stroke-miterlimit: 10;margin: 0;box-shadow: inset 0px 0px 0px #7ac142;animation: fill .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both}.checkmark__check{transform-origin: 50% 50%;stroke-dasharray: 48;stroke-dashoffset: 48;animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards}@keyframes stroke{100%{stroke-dashoffset: 0}}@keyframes scale{0%, 100%{transform: none}50%{transform: scale3d(1.1, 1.1, 1)}}@keyframes fill{100%{box-shadow: inset 0px 0px 0px 30px #7ac142}}
+{% endblock %}
+
+{% block content %}
+<form target="_blank" action="{% url 'docpreview' %}" method="post" id="preview_form">
+  {% csrf_token %}
+  <input type="hidden" name="preview" id="code_submit">
+</form>
+
+<div class="row">
+  <div class="col l4 offset-l4 m8 offset-m2 s12">
+    <div class="card">
+      {% if success %}
+        <div class="card-content">
+          <h5>{{doc.document_type.name}}</h5>
+          <h6>{{doc.user.first_name}} {{doc.user.last_name}} ({{doc.user.username}})</h6>
+          <h6>{{doc.code}}</h6>
+          <br>
+          <div class="row">
+            <div class="col s12">
+              <h6 class="center">Documento approvato</h6>
+            </div>
+          </div>
+          <div class="row">
+            <div class="col s12">
+              <div class="center wrapper">
+                <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
+                  <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none"/>
+                  <path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
+                </svg>
+              </div>
+            </div>
+          </div>
+        </div>
+      {% elif not error%}
+      <form id="form" action="{% url 'approve_direct'%}" method="post" enctype="multipart/form-data">
+        {% csrf_token %}
+        <input type="hidden" name="doc_code" value="{{doc.code}}">
+        <div class="card-content">
+          <div class="row">
+            <h5>{{doc.document_type.name}}</h5>
+            <h6>{{doc.user.first_name}} {{doc.user.last_name}} ({{doc.user.username}})</h6>
+            <h6>{{doc.code}}</h6>
+          </div>
+          <div class="hide-on-large-only">
+            <div class="row">
+              <a id="send_button_small" class="col s12 waves-effect waves-light btn {{color}}" href="#" onclick="confirm()">Approva</a>
+            </div>
+            <div class="row" style="margin-bottom: 0">
+              <a class="col s12 waves-effect waves-light btn {{color}}" onclick="send()">Anteprima</a>
+            </div>
+          </div>
+        </div>
+        <div class="card-action hide-on-med-and-down">
+          <a id="send_button" class="waves-effect waves-light btn {{color}}" href="#" onclick="confirm()">Approva</a>
+          <a class="right waves-effect waves-light btn {{color}}" onclick="send()">Anteprima</a>
+        </div>
+      </form>
+      {% else %}
+      <div class="card-content">
+        {{error}}
+      </div>
+      {% endif %}
+    </div>
+  </div>
+</div>
+
+{% endblock %}
+
+{% block script %}
+function confirm() {
+  var button = document.getElementById('send_button')
+  var button_small = document.getElementById('send_button_small')
+  button.innerHTML = "Sicuro?"
+  button.setAttribute('onclick', "document.getElementById('form').submit()")
+  button.setAttribute('class', "waves-effect waves-light btn green")
+  button_small.innerHTML = "Sicuro?"
+  button_small.setAttribute('onclick', "document.getElementById('form').submit()")
+  button_small.setAttribute('class', "col s12 waves-effect waves-light btn green")
+}
+
+function send() {
+  var form = document.getElementById('preview_form')
+  var action = document.getElementById('code_submit')
+  action.setAttribute('value', {{doc.code}});
+  form.submit()
+}
+{% endblock %}
\ No newline at end of file
diff --git a/server/urls.py b/server/urls.py
index 42bc0c8..d7974eb 100644
--- a/server/urls.py
+++ b/server/urls.py
@@ -16,6 +16,7 @@ urlpatterns = [
     path('docupload', views.upload_doc, name='docupload'),
     path('docpreview', views.docpreview, name='docpreview'),
     path('custom_parameters_preview', views.custom_parameters_preview, name='custom_parameters_preview'),
+    path('approve', views.approve_direct, name='approve_direct'),
     path('progress', views.get_progress, name='progress'),
     path('request', views.data_request, name='request'),
     path('media/<int:id>/<str:t>/<str:flag>', views.media_request, name='media'),
diff --git a/server/views.py b/server/views.py
index 96b8d9f..2b45caa 100644
--- a/server/views.py
+++ b/server/views.py
@@ -214,6 +214,13 @@ def docapprove(request):
                     messages.append(data[i] + " - Invalido")
                 else:
                     document = Document.objects.filter(code=data[i])[0]
+
+                    if document.group.name not in groups:
+                        return
+
+                    if document.status != 'wait' and document.status != 'ok':
+                        return
+
                     if document.status == 'ok':
                         # do nothing document already approved
                         messages.append(data[i] + " - Già approvato")
@@ -241,6 +248,12 @@ def docapprove(request):
                 # get document
                 document = Document.objects.filter(code=data)[0]
 
+                if document.group.name not in groups:
+                    return
+
+                if document.status != 'wait' and document.status != 'ok':
+                    return
+
                 # prepare success message
                 if document.status == 'ok':
                     success_text = "File caricato"
@@ -279,6 +292,67 @@ def docapprove(request):
 
     return render(request, 'server/approve_doc.html', context)
 
+@staff_member_required
+def approve_direct(request):
+    # get groups that the user is manager of
+    if request.user.is_staff:
+        groups = request.user.groups.values_list('name', flat=True)
+    else:
+        groups = request.user.groups.values_list('name', flat=True)[1:]
+
+    doc_code = -1
+
+    if request.method == "POST" and "doc_code" in request.POST:
+        # if user submitted the form to approve a document
+        doc_code = request.POST["doc_code"]
+        if doc_code.isdigit():
+            doc_code = int(doc_code)
+        else:
+            doc_code = -1
+
+        document = Document.objects.filter(code=doc_code)
+
+        # user modified manually the code
+        if len(document) != 1:
+            return
+
+        document = document[0]
+
+        # user modified the code to an invalid document
+        if document.status != "wait":
+            return
+
+        # check if user has permission to approve document
+        if document.group.name not in groups:
+            return
+
+        document.status = "ok"
+        document.save()
+        return render(request, 'server/approve_doc_direct.html', {"doc": document, "success": True})
+
+    # if the user just opened the page
+    if "code" in request.GET:
+        doc_code = request.GET["code"]
+        if doc_code.isdigit():
+            doc_code = int(doc_code)
+        else:
+            doc_code = -1
+
+    document = Document.objects.filter(code=doc_code)
+
+    if len(document) != 1:
+        return render(request, 'server/approve_doc_direct.html', {"error": "Codice del documento invalido, riscansionare il codice"})
+
+    document = document[0]
+
+    if document.status != "wait":
+        return render(request, 'server/approve_doc_direct.html', {"error": "Questo documento non è in attesa di approvazione"})
+
+    # check if user has permission to approve document
+    if document.group.name not in groups:
+        return render(request, 'server/approve_doc_direct.html', {"error": "Non hai il permesso di approvare questo documento"})
+
+    return render(request, 'server/approve_doc_direct.html', {"doc": document})
 
 @staff_member_required
 def ulist(request):
diff --git a/templates/registration/base_client.html b/templates/registration/base_client.html
index ff0b9d8..ad2fadc 100644
--- a/templates/registration/base_client.html
+++ b/templates/registration/base_client.html
@@ -99,6 +99,8 @@
      max-height: 90% !important;
    }
   }
+  {% block style %}
+  {% endblock %}
   </style>
   <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
   <meta charset="utf-8">
diff --git a/version.txt b/version.txt
index f8c6175..8d0a3e2 100644
--- a/version.txt
+++ b/version.txt
@@ -1,2 +1,2 @@
 version=0.5
-rev=38
+rev=39
-- 
cgit v1.2.1