diff options
author | Prathamesh | 2023-12-27 14:44:20 +0530 |
---|---|---|
committer | Prathamesh | 2023-12-27 14:45:06 +0530 |
commit | fa1e7cf9320d8124efe70a9f4ab093d314acf178 (patch) | |
tree | 1f84320ba3d5382cffab71db6bdeaaea3da62c7a | |
parent | 7e6b8ebb54f3921f1aa28cbea69904b9737a8d69 (diff) | |
download | certificate-generation-fa1e7cf9320d8124efe70a9f4ab093d314acf178.tar.gz certificate-generation-fa1e7cf9320d8124efe70a9f4ab093d314acf178.tar.bz2 certificate-generation-fa1e7cf9320d8124efe70a9f4ab093d314acf178.zip |
Change UI
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | website/cgen/generator.py | 2 | ||||
-rw-r--r-- | website/cgen/models.py | 9 | ||||
-rw-r--r--[-rwxr-xr-x] | website/cgen/templates/base.html | 157 | ||||
-rw-r--r-- | website/cgen/templates/download.html | 53 | ||||
-rw-r--r-- | website/cgen/templates/index.html | 90 | ||||
-rwxr-xr-x | website/cgen/templates/verification.html | 55 | ||||
-rw-r--r-- | website/cgen/verification.py | 3 | ||||
-rw-r--r-- | website/cgen/views.py | 10 | ||||
-rw-r--r-- | website/website/settings.py | 5 |
10 files changed, 274 insertions, 111 deletions
@@ -3,3 +3,4 @@ __pycache__ local.py *.pyc *.swp +certificates diff --git a/website/cgen/generator.py b/website/cgen/generator.py index cd55f7f..b894c93 100644 --- a/website/cgen/generator.py +++ b/website/cgen/generator.py @@ -36,7 +36,7 @@ def get_details(certificate_id, email): info['serial_key'] = key info['qr_code'] = f'{DOMAIN}/certificates/verify/{key}/' certificate_details['info'] = info - path = f'{settings.BASE_DIR}/{certificate.id}' + path = f'{settings.BASE_DIR}/certificates/{certificate.id}' certificate_details['path'] = path if not os.path.exists(f"path/{{Makefile}}"): shutil.copy2(f'{settings.BASE_DIR}/Makefile', path) diff --git a/website/cgen/models.py b/website/cgen/models.py index 30bb762..e367ae3 100644 --- a/website/cgen/models.py +++ b/website/cgen/models.py @@ -1,6 +1,7 @@ from django.db import models, IntegrityError from django.utils import timezone from django.contrib.auth.models import User +from django.conf import settings import os import hashlib @@ -11,13 +12,13 @@ types = ( ) # Create your models here. - - def get_file_dir(instance, filename): - return os.sep.join((str(instance.id), filename)) + if not os.path.exists(settings.CERTIFICATES_PATH): + os.mkdir(settings.CERTIFICATES_PATH) + return os.sep.join(('certificates', str(instance.id), filename)) def get_certificate_dir(instance, filename): - return os.sep.join((str(instance.participant.certificate.id), str(instance.id), filename)) + return os.sep.join(('certificates', str(instance.participant.certificate.id), str(instance.id), filename)) class Event(models.Model): """ diff --git a/website/cgen/templates/base.html b/website/cgen/templates/base.html index 69190e8..4e6bd11 100755..100644 --- a/website/cgen/templates/base.html +++ b/website/cgen/templates/base.html @@ -1,57 +1,104 @@ -<html> -<link rel="icon" href="https://fossee.in/sites/all/themes/software_responsive_theme/favicon.ico" type="image/vnd.microsoft.icon"/> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> - <head> - <title> - {% block title %} - Certificates - {% endblock %} - </title> - {% block css %} - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> - {% endblock %} - {% block js %} - <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script> - <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> - {% endblock %} - {% block javascript %} - <!-- overide with custom javascript --> +<!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"> + <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="../../favicon.ico"> + + <title> + {% block title %} + Certificates {% endblock %} - </head> - <body> - <div class="container-full"> -<nav class="navbar navbar-dark bg-dark"> - <a class="navbar-brand" href="{% url 'events' %}">Events</a> -</nav> - <div class="row"> - - <div class="col-lg-12 text-center v-center"> - {% block header%} - - {% endblock %} - {% block content %} - {% endblock %} - </div> - - </div> <!-- /row --> - <hr> - <br> - <div id="footer-wrapper" class="container"> - <div id="footer-inner" class="col-lg-12 col-md-12 col-sm-12"> - <div class="pull-left"> - <!--[if lte IE 8]><span style="filter: FlipH; -ms-filter: "FlipH"; display: inline-block;"><![endif]--> - <span style="-moz-transform: scaleX(-1); -o-transform: scaleX(-1); -webkit-transform: scaleX(-1); transform: scaleX(-1); display: inline-block;"> - <!--<a href="http://www.gnu.org/copyleft/" target="_blank">©</a>--> - </span> - <!--[if lte IE 8]></span><![endif]--> - <!--2013 <a href="http://fossee.in" target="_blank">fossee.in</a>--> - </div> - <div class="pull-right"> - Developed at IIT Bombay - </div> - </div> <!-- /#footer-inner --> - </div> <!-- /#footer-wrapper --> - </div> <!-- /container full --> - </body> -</html> + </title> + + <!-- Bootstrap core CSS --> + {% block css %} + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> + {% endblock %} + {% block js %} + <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script> +<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script> + <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script> + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> + {% endblock %} + {% block javascript %} + <!-- overide with custom javascript --> + {% endblock %} + + {% block head %} + {% endblock %} + </head> + + <body> + +<header> + <div class="collapse bg-dark" id="navbarHeader"> + <div class="container"> + <div class="row"> + <div class="col-sm-8 col-md-7 py-4"> + <h4 class="text-white">About</h4> + <p class="text-muted"> Cgen is a certificate generator.<br>It allows you to download your certificates. </p> + </div> + <div class="col-sm-4 offset-md-1 py-4"> + <h4 class="text-white">Contact</h4> + <ul class="list-unstyled"> + <li><a href="#" class="text-white">Email me</a></li> + </ul> + </div> + </div> + </div> + </div> + <div class="navbar navbar-dark bg-dark shadow-sm"> + <div class="container"> + <a href="{% url 'events' %}" class="navbar-brand d-flex align-items-center"> + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="me-2" viewBox="0 0 24 24"><circle cx="12" cy="13" r="4"/></svg> + <strong>Cgen</strong> + </a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + </div> + </div> +</header> + +<main> + <section class="py-5 text-center container"> + <div class="row py-lg-5"> + <div class="col-lg-6 col-md-8 mx-auto"> + <h1 class="fw-light">{% block header %} {% endblock %}</h1> + <p class="lead text-muted">{% block header_content %} {% endblock %}</p> + </p> + </div> + </div> + </section> + + <div class="album py-5 bg-light"> + <div class="container"> + {% block content %} + {% endblock %} + </div> + </div> + </div> + +</main> + +<footer class="text-muted py-5"> + <div class="container"> + <p class="float-end mb-1"> + <a href="#">Back to top</a> + </p> + <p class="mb-1">Cgen created at © FOSSEE, IIT BOMBAY 2023</p> + </div> + <p></p> +</footer> + + + + + </body> +</html> diff --git a/website/cgen/templates/download.html b/website/cgen/templates/download.html index 11f3c2a..afa8117 100644 --- a/website/cgen/templates/download.html +++ b/website/cgen/templates/download.html @@ -1,30 +1,39 @@ {% extends 'base.html' %} {% block header%} - <h1>{{ certificate.event.name }} Certificates</h1> + {{ certificate.event.name }} Certificates {% endblock %} {% block content %} - <div class="modal fade" id="invalidModal" tabindex="-1" role="dialog" aria-labelledby="invalidModalLabel" aria-hidden="true"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> - <h4 class="modal-title" id="invalidModalLabel">Invalid Email</h4> - </div> - <div class="modal-body"> + + <form style="margin-right:200px; margin-left:200px" action="{% url 'certificate_download' certificate.id %}" method="post"> + {% csrf_token %} + <div class="mb-3"> + <label for="inputemail" class="form-label">Email address</label> + <input type="email" name="email" id="email" class="form-control" id="inputemail" aria-describedby="emailHelp"> + <div id="emailHelp" class="form-text"> Enter the registered email address.</div> + </div> + <button type="submit" class="btn btn-primary">Download</button> + </form> + + + <div class="modal" id="invalidModal" tabindex="-1"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title">Invalid Email</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onClick="$('#invalidModal').hide()"></button> + </div> + <div class="modal-body"> + <p> The requested certificate is unavailable for your email address. Please enter proper email and retry. - </div> - </div> + </p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onClick="$('#invalidModal').hide()">Close</button> </div> - </div> - <form class="col-lg-12" action="{% url 'certificate_download' certificate.id %}" method="post"> - {% csrf_token %} - {{ message }} - <div class="input-group" style="width:340px;text-align:center;margin:0 auto;"> - <input style="width:450;" class="form-control input-lg" placeholder="Enter the email address you used for registration" type="text" id="email" name=email> - <span class="input-group-btn"><button class="btn btn-lg btn-primary" type="submit">Download Certificate</button></span> </div> - </form> - <center><h4>Problem in downloading the certificate? Write to us at <a href="mailto:certificates@fossee.in">certificates[at]fossee[dot]in</a></h4> + </div> + </div> + <!--<center><h4>Problem in downloading the certificate? Write to us at <a href="mailto:certificates@fossee.in">certificates[at]fossee[dot]in</a></h4>--> {% endblock %} {% block javascript %} @@ -34,7 +43,7 @@ email = "" error = "{{ error }}" if(error == "True"){ - $("#invalidModal").modal(); + $("#invalidModal").show(); } if(value == "paper"){ $('#A').prop('checked', true) @@ -43,7 +52,7 @@ $('#email').val(email); notreg = "{{ notregistered }}"; if(notreg == "1"){ - $("#invalidModal").modal(); + $("#invalidModal").show(); } $("[name=type]").change(function(){ $("#paper").remove(); diff --git a/website/cgen/templates/index.html b/website/cgen/templates/index.html new file mode 100644 index 0000000..5dfdbf7 --- /dev/null +++ b/website/cgen/templates/index.html @@ -0,0 +1,90 @@ +{% extends 'base.html' %} + {% block head %} + + <style> + .bd-placeholder-img { + font-size: 1.125rem; + text-anchor: middle; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + } + + @media (min-width: 768px) { + .bd-placeholder-img-lg { + font-size: 3.5rem; + } + } + + .b-example-divider { + height: 3rem; + background-color: rgba(0, 0, 0, .1); + border: solid rgba(0, 0, 0, .15); + border-width: 1px 0; + box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15); + } + + .b-example-vr { + flex-shrink: 0; + width: 1.5rem; + height: 100vh; + } + + .bi { + vertical-align: -.125em; + fill: currentColor; + } + + .nav-scroller { + position: relative; + z-index: 2; + height: 2.75rem; + overflow-y: hidden; + } + + .nav-scroller .nav { + display: flex; + flex-wrap: nowrap; + padding-bottom: 1rem; + margin-top: -1px; + overflow-x: auto; + text-align: center; + white-space: nowrap; + -webkit-overflow-scrolling: touch; + } + </style> + {% endblock %} + +{% block header %} + Certificates available for download. +{% endblock %} + +{% block header_content %} + Certificates for the following events and courses are available. +{% endblock %} + +{% block content %} + <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3"> + {% for event in events %} + <div class="col"> + <div class="card shadow-sm"> + <svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">{{ event.name }}</text></svg> + + <div class="card-body"> + <p class="card-text">{{ event.name }}</p> + {% for certificate in event.certificate_set.all %} + <div class="d-flex justify-content-between align-items-center"> + <p>{{ certificate.description }} + <div class="btn-group"> + <a type="button" href="{% url 'certificate_download' certificate.id %}" class="btn btn-sm btn-outline-secondary">Download</a> + <a type="button" href="{% url 'verify' %}" class="btn btn-sm btn-outline-secondary">Verify</a> + </div> + </div> + <small class="text-muted">9 Downloads</small> + {% endfor %} + </div> + </div> + </div> + {% endfor %} + </div> +{% endblock %} diff --git a/website/cgen/templates/verification.html b/website/cgen/templates/verification.html index df33779..ad834a1 100755 --- a/website/cgen/templates/verification.html +++ b/website/cgen/templates/verification.html @@ -1,54 +1,57 @@ {% extends 'base.html' %} {% block header%} - <h1> Certificate Verification </h1> + Certificate Verification {% endblock %} {% block content %} - <div class="modal fade" id="invalidModal" tabindex="-1" role="dialog" aria-labelledby="invalidModalLabel" aria-hidden="true"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> - <h4 class="modal-title" id="invalidModalLabel">Invalid Serial Number</h4> - </div> - <div class="modal-body"> + <div class="modal" id="invalidModal" tabindex="-1"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title">Invalid Serial Key</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onClick="$('#invalidModal').hide()"></button> + </div> + <div class="modal-body"> + <p> Sorry ! The serial number you entered seems to be invalid. Please try again ! - </div> - </div> + </p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onClick="$('#invalidModal').hide()">Close</button> </div> + </div> </div> - <p><b> Enter the alphanumeric characters below the QR code<br> OR <br>Enter the serial number you received while scanning the QR code on certificate</p> - <hr> - <form action="{% url 'verify' %}" method="post"> + </div> + <div style="margin-right:200px; margin-left:200px"> + <p> Enter the alphanumeric characters below the QR code<br> OR <br>Enter the serial number you received while scanning the QR code on certificate</p> + <form style="margin-right:200px; margin-left:200px"action="{% url 'verify' %}" method="post"> {% csrf_token %} - <div class="input-group" style="width:340px;text-align:center;margin:0 auto;"> + <div class="input-group" > <input class="form-control input-lg" placeholder="Enter the serial number" type="text" name="key"> <span class="input-group-btn"><button class="btn btn-lg btn-primary" type="submit">Verify</button></span> </div> </form> - <hr> {% if has_details %} + <br> <div> - <table class="table table-bordered" align="center" style="width:50%"> - <caption>Details</caption> + <caption> Following are the details</caption> + <table class="table table-primary table-bordered" > <tbody> {% for key, value in details.items %} <tr> - <td>{{ key }}</td> + <td>{{ key | title }}</td> <td>{{ value }}</td> </tr> {% endfor %} </tbody> </table> - <div style="width:40%"><a href="{% url 'verify' %}" >< Back</a></div> - </div> - - <div align="left" style="width:50%" > + <div class="bg-white"> {{ description | safe }} + </div> </div> + {% endif %} - <hr> - <!--<center><h4>Problem in verifying the details ? write to us at <a href="mailto:certificates@fossee.in">certificates[at]fossee[dot]in</a></h4>--> + </div> {% endblock %} @@ -58,7 +61,7 @@ invalid_serial = {{ invalidserial }} $( document ).ready(function() { if(invalid_serial == 1) { - $("#invalidModal").modal(); + $("#invalidModal").show(); } }); </script> diff --git a/website/cgen/verification.py b/website/cgen/verification.py index 2cf026d..bc35078 100644 --- a/website/cgen/verification.py +++ b/website/cgen/verification.py @@ -4,7 +4,8 @@ from cgen.models import CertificateManager def verify(key): - details = OrderedDict() + details = OrderedDict() + description = None try: cm = CertificateManager.objects.get(serial_key_short=key) details['Authentic'] = True diff --git a/website/cgen/views.py b/website/cgen/views.py index f988e80..1343312 100644 --- a/website/cgen/views.py +++ b/website/cgen/views.py @@ -13,7 +13,7 @@ import csv def events(request): events = Event.objects.filter(is_published=True) context = {'events': events} - return render(request, 'events.html', context) + return render(request, 'index.html', context) # Create your views here. def certificate_download(request, certificate_id): @@ -36,13 +36,19 @@ def certificate_download(request, certificate_id): def verify(request, key=None): context = {} + if key is None and request.method == 'GET': + return render(request, 'verification.html', context) if key is not None: skey = key elif request.method == 'POST': skey = request.POST.get('key').strip() + details, description = verification.verify(skey) + if not details['Authentic']: + context['invalidserial'] = 1 + return render(request, 'verification.html', context) + context['details'] = details - context['has_details'] = True context['has_details'] = details['Authentic'] context['description'] = description return render(request, 'verification.html', context) diff --git a/website/website/settings.py b/website/website/settings.py index 1976128..d54ca4d 100644 --- a/website/website/settings.py +++ b/website/website/settings.py @@ -124,3 +124,8 @@ TIME_OUT = 15 # https://docs.djangoproject.com/en/3.0/howto/static-files/ STATIC_URL = '/static/' + +LOGO = "https://www.cep.iitb.ac.in/assets/img/IIT-Logo.png" + +CERTIFICATES_PATH = f"settings.BASE_DIR/certificates" + |