summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/models.py4
-rw-r--r--archaeological_finds/models_finds.py6
-rw-r--r--archaeological_finds/templates/ishtar/sheet_find.html2
-rw-r--r--archaeological_operations/models.py8
-rw-r--r--archaeological_operations/tests.py36
-rw-r--r--archaeological_warehouse/models.py4
-rw-r--r--example_project/settings.py4
-rw-r--r--ishtar_common/models.py3
-rw-r--r--ishtar_common/static/media/style_basic.css14
-rw-r--r--ishtar_common/templates/ishtar/blocks/window_nav.html9
-rw-r--r--ishtar_common/templates/ishtar/sheet.html31
-rw-r--r--ishtar_common/urls.py2
-rw-r--r--ishtar_common/views.py31
-rw-r--r--ishtar_common/views_item.py3
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: