diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-02-26 20:14:22 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-04-24 19:38:57 +0200 |
commit | c33e49777af11ad8cadc311833136cbaf5872962 (patch) | |
tree | c644209eb81804406bfc5f014713dc1f62bc5ad4 | |
parent | 01945a4aeca368458236cf022b64be2b3539e66b (diff) | |
download | Ishtar-c33e49777af11ad8cadc311833136cbaf5872962.tar.bz2 Ishtar-c33e49777af11ad8cadc311833136cbaf5872962.zip |
QR code: QR code export, display on ODT and PDF
-rw-r--r-- | archaeological_context_records/models.py | 4 | ||||
-rw-r--r-- | archaeological_finds/models_finds.py | 6 | ||||
-rw-r--r-- | archaeological_finds/templates/ishtar/sheet_find.html | 2 | ||||
-rw-r--r-- | archaeological_operations/models.py | 8 | ||||
-rw-r--r-- | archaeological_operations/tests.py | 36 | ||||
-rw-r--r-- | archaeological_warehouse/models.py | 4 | ||||
-rw-r--r-- | example_project/settings.py | 4 | ||||
-rw-r--r-- | ishtar_common/models.py | 3 | ||||
-rw-r--r-- | ishtar_common/static/media/style_basic.css | 14 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/blocks/window_nav.html | 9 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/sheet.html | 31 | ||||
-rw-r--r-- | ishtar_common/urls.py | 2 | ||||
-rw-r--r-- | ishtar_common/views.py | 31 | ||||
-rw-r--r-- | ishtar_common/views_item.py | 3 |
14 files changed, 127 insertions, 30 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index cd2b5f382..6dad4f600 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -271,8 +271,10 @@ class CRBulkView(object): class ContextRecord(BulkUpdatedItem, BaseHistorizedItem, QRCodeItem, GeoItem, OwnPerms, ValueGetter, ShortMenuItem, RelationItem): - SHOW_URL = 'show-contextrecord' SLUG = 'contextrecord' + APP = "archaeological-context-records" + MODEL = "context-record" + SHOW_URL = 'show-contextrecord' EXTERNAL_ID_KEY = 'context_record_external_id' EXTERNAL_ID_DEPENDENCIES = ['base_finds'] TABLE_COLS = ['label', 'operation__common_name', 'town__name', diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 084e2b8d7..e93580418 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -702,9 +702,11 @@ def query_loan(is_true=True): class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, QRCodeItem, OwnPerms, MainItem): - EXTERNAL_ID_KEY = 'find_external_id' - SHOW_URL = 'show-find' SLUG = 'find' + APP = "archaeological-finds" + MODEL = "find" + SHOW_URL = 'show-find' + EXTERNAL_ID_KEY = 'find_external_id' TABLE_COLS = ['external_id', 'label', 'base_finds__context_record__town__name', 'base_finds__context_record__operation__common_name', diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html index 1b383e4e5..7644acb60 100644 --- a/archaeological_finds/templates/ishtar/sheet_find.html +++ b/archaeological_finds/templates/ishtar/sheet_find.html @@ -27,6 +27,7 @@ {% with can_view_documents=permission_view_own_document|or_:permission_view_document %} {% with display_documents=can_view_documents|and_:item.documents.count %} +{% if output != "ODT" and output != "PDF"%} <ul class="nav nav-tabs" id="{{window_id}}-tabs" role="tablist"> <li class="nav-item"> <a class="nav-link active" id="{{window_id}}-basefind-tab" @@ -79,6 +80,7 @@ </li> {% endif %} </ul> +{% endif %} <div class="tab-content" id="{{window_id}}-tab-content"> diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index a09798f1f..aa1e2dcb4 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -109,9 +109,11 @@ post_delete.connect(post_save_cache, sender=RecordQualityType) class ArchaeologicalSite(BaseHistorizedItem, QRCodeItem, GeoItem, OwnPerms, ValueGetter, ShortMenuItem): + SLUG = 'site' + APP = "archaeological-operations" + MODEL = "archaeological-site" SHOW_URL = 'show-site' TABLE_COLS = ['reference', 'name', 'towns_label', 'periods', 'remains'] - SLUG = 'site' LONG_SLUG = 'archaeologicalsite' BASE_SEARCH_VECTORS = [ @@ -511,10 +513,12 @@ class OperationManager(models.GeoManager): class Operation(ClosedItem, BaseHistorizedItem, QRCodeItem, GeoItem, OwnPerms,\ ValueGetter, ShortMenuItem, DashboardFormItem, RelationItem): + SLUG = 'operation' + APP = "archaeological-operations" + MODEL = "operation" SHOW_URL = 'show-operation' TABLE_COLS = ['year', 'towns_label', 'common_name', 'operation_type', 'start_date', 'excavation_end_date', 'remains'] - SLUG = 'operation' # search parameters BOOL_FIELDS = ['end_date__isnull', 'virtual_operation', diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index 01418141d..14577e119 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -2547,3 +2547,39 @@ class SiteTest(TestCase, OperationInitTest): search = {'search_vector': 'reference="reference*"'} response = c.get(reverse('get-site'), search) self.assertEqual(json.loads(response.content)['recordsTotal'], 1) + + +class GenerateQRCode(OperationInitTest, TestCase): + fixtures = FILE_FIXTURES + + def setUp(self): + self.username, self.password, self.user = create_superuser() + self.operation = self.create_operation(self.user)[0] + + def test_display(self): + if self.operation.qrcode.name: + self.operation.qrcode = None + self.operation.save() + operation = models.Operation.objects.get(pk=self.operation.pk) + self.assertIn(operation.qrcode.name, ["", None]) + c = Client() + url = reverse('qrcode-item', args=[ + 'archaeological-operations', 'operation', operation.pk]) + response = c.get(url) + self.assertEqual(response.status_code, 302) + c.login(username=self.username, password=self.password) + response = c.get(url) + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], "image/png") + operation = models.Operation.objects.get(pk=self.operation.pk) + self.assertIsNotNone(operation.qrcode.name) + + def test_generation(self): + self.assertIsNone(self.operation.qrcode.name) + self.operation.generate_qrcode() + self.assertIsNotNone(self.operation.qrcode.name) + self.assertTrue( + self.operation.qrcode.name.startswith( + "operation/2010/OP2010-1/qrcode" + ) + ) diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 115f0d7ea..6e2df520e 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -50,6 +50,8 @@ post_delete.connect(post_save_cache, sender=WarehouseType) class Warehouse(Address, GeoItem, QRCodeItem, DashboardFormItem, OwnPerms, ShortMenuItem): SLUG = 'warehouse' + APP = "archaeological-warehouse" + MODEL = "warehouse" SHOW_URL = 'show-warehouse' TABLE_COLS = ['name', 'warehouse_type'] BASE_SEARCH_VECTORS = ['name', 'warehouse_type__label', "external_id", @@ -325,6 +327,8 @@ post_delete.connect(post_save_cache, sender=ContainerType) class Container(LightHistorizedItem, QRCodeItem, GeoItem, OwnPerms): SLUG = 'container' + APP = "archaeological-warehouse" + MODEL = "container" SHOW_URL = 'show-container' TABLE_COLS = ['reference', 'container_type__label', 'cached_location', 'cached_division', 'old_reference'] diff --git a/example_project/settings.py b/example_project/settings.py index 9c742eedf..54872e3ec 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -231,8 +231,8 @@ USE_BACKGROUND_TASK = False # Ishtar custom ISHTAR_MAP_MAX_ITEMS = 50000 -ISHTAR_QRCODE_VERSION = 10 # density of the QR code -ISHTAR_QRCODE_SCALE = 3 # scale of the QR code +ISHTAR_QRCODE_VERSION = 8 # density of the QR code +ISHTAR_QRCODE_SCALE = 2 # scale of the QR code SRID = 27572 SURFACE_SRID = 2154 diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 9b5185be4..247ab4f61 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1572,6 +1572,7 @@ class FixAssociated(object): class QRCodeItem(models.Model, ImageContainerModel): + HAS_QR_CODE = True qrcode = models.ImageField(upload_to=get_image_path, blank=True, null=True, max_length=255) @@ -1582,7 +1583,7 @@ class QRCodeItem(models.Model, ImageContainerModel): url = self.get_absolute_url() site = Site.objects.get_current() if request: - scheme = self.request.scheme + scheme = request.scheme else: if secure: scheme = "https" diff --git a/ishtar_common/static/media/style_basic.css b/ishtar_common/static/media/style_basic.css index bfd89dfca..051543ea9 100644 --- a/ishtar_common/static/media/style_basic.css +++ b/ishtar_common/static/media/style_basic.css @@ -54,10 +54,18 @@ td{ margin:0; padding:0; padding-top:4px; - text-align:right; + text-align: right; border:1px solid #EEE; border-top:none; font-size:0.9em; + background-color: #ddd; +} + +.window-table-head td{ + text-align: left; + border:0 solid transparent; + font-size: 1em; + background-color: transparent; } .link{ @@ -92,10 +100,6 @@ p{ margin:0.2em; } -td{ - background-color: #ddd; -} - #pdffooter, #pdfheader{ text-align:center; } diff --git a/ishtar_common/templates/ishtar/blocks/window_nav.html b/ishtar_common/templates/ishtar/blocks/window_nav.html index a53e62b0d..92fa15352 100644 --- a/ishtar_common/templates/ishtar/blocks/window_nav.html +++ b/ishtar_common/templates/ishtar/blocks/window_nav.html @@ -71,15 +71,18 @@ aria-labelledby="dropdown-sheet-export-{{window_id}}"> <a class="dropdown-item" href='{% url show_url item.pk "odt" %}' title='{% trans "Export as OpenOffice.org file"%}'> - ODT <i class="fa fa-file-word-o" aria-hidden="true"></i> + <i class="fa fa-file-word-o" aria-hidden="true"></i> ODT </a> <a class="dropdown-item" href='{% url show_url item.pk "pdf" %}' title='{% trans "Export as PDF file"%}'> - PDF <i class="fa fa-file-pdf-o" aria-hidden="true"></i> + <i class="fa fa-file-pdf-o" aria-hidden="true"></i> PDF </a>{% for template_name, template_url in extra_templates %} <a class="dropdown-item" href='{{template_url}}'> - {{template_name}} <i class="fa fa-file-word-o" aria-hidden="true"></i> + <i class="fa fa-file-word-o" aria-hidden="true"></i> {{template_name}} </a>{% endfor %} + {% if item.HAS_QR_CODE %}<a class="dropdown-item" href='{% url "qrcode-item" item.APP item.MODEL item.pk %}' target="_blank"> + <i class="fa fa-qrcode" aria-hidden="true"></i> {% trans "QR Code" %} + </a>{% endif %} </div> </div> diff --git a/ishtar_common/templates/ishtar/sheet.html b/ishtar_common/templates/ishtar/sheet.html index e937f1474..6b9c97948 100644 --- a/ishtar_common/templates/ishtar/sheet.html +++ b/ishtar_common/templates/ishtar/sheet.html @@ -8,28 +8,37 @@ </head> <body> {% endblock %} - <div class="card sheet" id="{{window_id}}"> + + {% if output != "ODT" and output != "PDF" %} <div class="card-header" data-sheet-id="{{sheet_id}}" role="tab" id='head-{{window_id}}'> <div class="row"> <div class="col-9"> - {% if output != "ODT" and output != "PDF"%} <h5 class="mb-0"> <a class="card-label" data-toggle="collapse" href="#collapse-{{window_id}}" aria-expanded="true" aria-controls="collapse-{{window_id}}"> - {% else %} - <h2> - {% endif %} + {% else %} + {% if item.qrcode.name %} + <table class="window-table-head"> + <tr> + <td> <img class="qrcode" src="{{BASE_URL}}{{item.qrcode.url}}"> </td> + <td> + {% endif %} + <h2> + {% endif %} {% block head_title %}{% endblock %} - {% if output == "ODT" or output == "PDF"%} - </h2> - {% else %} + {% if output == "ODT" or output == "PDF" %} + </h2> + {% if item.qrcode.name %} + </td> + </tr> + </table> + {% endif %} + {% else %} </a> </h5> - {% endif %} </div> - {% if output != "ODT" and output != "PDF"%} <div class='col-2 text-center'> <a href='#' class='previous_page'> <span class="fa-stack"> @@ -53,8 +62,8 @@ </span> </a> </div> - {% endif %} </div> + {% endif %} {% block header_title %}{% endblock %} </div> diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index aea419d08..957b1bfb3 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -40,6 +40,8 @@ urlpatterns = [ url(r'shortcut_menu/', views.shortcut_menu, name='shortcut-menu'), url(r'display/(?P<item_type>\w+)/(?P<pk>\d+)/', views.DisplayItemView.as_view(), name='display-item'), + url(r'qrcode/(?P<app>[-a-z]+)/(?P<model_name>[-a-z]+)/(?P<pk>\d+)/', + views.QRCodeView.as_view(), name='qrcode-item'), url(r'person_search/(?P<step>.+)?$', check_rights(['add_person'])( views.person_search_wizard), name='person_search'), diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 61bae69e2..5f5b0be42 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -19,12 +19,14 @@ import csv import datetime +import importlib import json import logging -import importlib +import os +import unicodecsv import unicodedata -import unicodecsv +from django.apps import apps from django.conf import settings from django.contrib.auth import logout from django.contrib.auth.decorators import login_required @@ -38,7 +40,7 @@ from django.http import HttpResponse, Http404, HttpResponseRedirect, \ from django.shortcuts import redirect, render from django.utils.decorators import method_decorator from django.utils.translation import ugettext, ugettext_lazy as _ -from django.views.generic import ListView, UpdateView, TemplateView +from django.views.generic import ListView, TemplateView, View from django.views.generic.edit import CreateView, DeleteView, FormView, \ UpdateView from extra_views import ModelFormSetView @@ -1010,6 +1012,29 @@ class DisplayItemView(IshtarMixin, LoginRequiredMixin, TemplateView): return data +class QRCodeView(IshtarMixin, LoginRequiredMixin, View): + def get(self, request, *args, **kwargs): + model_name = "".join( + [part.capitalize() for part in kwargs.get('model_name').split('-')] + ) + app = kwargs.get('app').replace('-', "_") + try: + model = apps.get_model(app, model_name) + item = model.objects.get(pk=kwargs.get("pk")) + assert hasattr(item, 'qrcode') + except (LookupError, model.DoesNotExist, AssertionError): + raise Http404() + + if not item.qrcode or not item.qrcode.name: + item.generate_qrcode(request=self.request) + + if not item.qrcode or not item.qrcode.name: # generation has failed + raise Http404() + + with open(settings.MEDIA_ROOT + os.sep + item.qrcode.name, "rb") as f: + return HttpResponse(f.read(), content_type="image/png") + + class GlobalVarEdit(IshtarMixin, AdminLoginRequiredMixin, ModelFormSetView): template_name = 'ishtar/formset.html' model = models.GlobalVar diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index ffbbbb936..16128feba 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -218,6 +218,9 @@ def show_item(model, name, extra_dct=None, model_for_perms=None): item.history_date = historized[0].history_date if len(historized) > 1: dct['previous'] = historized[1].history_date + if doc_type in ("odt", "pdf") and hasattr(item, 'qrcode') \ + and (not item.qrcode or not item.qrcode.name): + item.generate_qrcode(request=request) dct['item'], dct['item_name'] = item, name # add context if extra_dct: |