Merge branch 'dev'

This commit is contained in:
Jonas Winkler 2018-09-13 14:15:33 +02:00
commit 8371c2399f
9 changed files with 121 additions and 105 deletions

View File

@ -43,14 +43,12 @@ def select_action(modeladmin, request, queryset, title, action, modelclass, succ
media=modeladmin.media, media=modeladmin.media,
action=action, action=action,
objects=modelclass.objects.all(), objects=modelclass.objects.all(),
itemname=model_ngettext(modelclass,1) itemname=model_ngettext(modelclass, 1)
) )
request.current_app = modeladmin.admin_site.name request.current_app = modeladmin.admin_site.name
return TemplateResponse(request, return TemplateResponse(request, "admin/%s/%s/select_object.html" % (app_label, opts.model_name), context)
"admin/%s/%s/select_object.html" % (app_label, opts.model_name)
, context)
def simple_action(modeladmin, request, queryset, success_message="", document_action=None, queryset_action=None): def simple_action(modeladmin, request, queryset, success_message="", document_action=None, queryset_action=None):
@ -70,6 +68,7 @@ def simple_action(modeladmin, request, queryset, success_message="", document_ac
"count": n, "items": model_ngettext(modeladmin.opts, n) "count": n, "items": model_ngettext(modeladmin.opts, n)
}, messages.SUCCESS) }, messages.SUCCESS)
# Return None to display the change list page again.
return None return None
@ -99,7 +98,7 @@ def set_correspondent_on_selected(modeladmin, request, queryset):
action="set_correspondent_on_selected", action="set_correspondent_on_selected",
modelclass=Correspondent, modelclass=Correspondent,
success_message="Successfully set correspondent %(selected_object)s on %(count)d %(items)s.", success_message="Successfully set correspondent %(selected_object)s on %(count)d %(items)s.",
queryset_action=lambda queryset, correspondent: queryset.update(correspondent=correspondent)) queryset_action=lambda qs, correspondent: qs.update(correspondent=correspondent))
set_correspondent_on_selected.short_description = "Set correspondent on selected documents" set_correspondent_on_selected.short_description = "Set correspondent on selected documents"
@ -116,7 +115,7 @@ def set_document_type_on_selected(modeladmin, request, queryset):
action="set_document_type_on_selected", action="set_document_type_on_selected",
modelclass=DocumentType, modelclass=DocumentType,
success_message="Successfully set document type %(selected_object)s on %(count)d %(items)s.", success_message="Successfully set document type %(selected_object)s on %(count)d %(items)s.",
queryset_action=lambda queryset, document_type: queryset.update(document_type=document_type)) queryset_action=lambda qs, document_type: qs.update(document_type=document_type))
set_document_type_on_selected.short_description = "Set document type on selected documents" set_document_type_on_selected.short_description = "Set document type on selected documents"

View File

@ -94,9 +94,10 @@ class RecentCorrespondentFilter(admin.RelatedFieldListFilter):
def field_choices(self, field, request, model_admin): def field_choices(self, field, request, model_admin):
lookups = [] lookups = []
date_limit = datetime.now() - timedelta(days=365*settings.PAPERLESS_RECENT_CORRESPONDENT_YEARS) if settings.PAPERLESS_RECENT_CORRESPONDENT_YEARS and settings.PAPERLESS_RECENT_CORRESPONDENT_YEARS > 0:
for c in Correspondent.objects.filter(documents__created__gte = date_limit).distinct(): date_limit = datetime.now() - timedelta(days=365*settings.PAPERLESS_RECENT_CORRESPONDENT_YEARS)
lookups.append( (c.id, c.name) ) for c in Correspondent.objects.filter(documents__created__gte=date_limit).distinct():
lookups.append((c.id, c.name))
return lookups return lookups
@ -153,6 +154,7 @@ class DocumentTypeAdmin(CommonAdmin):
return obj.document_count return obj.document_count
document_count.admin_order_field = "document_count" document_count.admin_order_field = "document_count"
class DocumentAdmin(CommonAdmin): class DocumentAdmin(CommonAdmin):
class Media: class Media:
@ -199,10 +201,10 @@ class DocumentAdmin(CommonAdmin):
extra_context['download_url'] = doc.download_url extra_context['download_url'] = doc.download_url
extra_context['file_type'] = doc.file_type extra_context['file_type'] = doc.file_type
if self.document_queue and object_id and int(object_id) in self.document_queue: if self.document_queue and object_id and int(object_id) in self.document_queue:
#There is a queue of documents # There is a queue of documents
current_index = self.document_queue.index(int(object_id)) current_index = self.document_queue.index(int(object_id))
if current_index < len(self.document_queue) - 1: if current_index < len(self.document_queue) - 1:
#... and there are still documents in the queue # ... and there are still documents in the queue
extra_context['next_object'] = self.document_queue[current_index + 1] extra_context['next_object'] = self.document_queue[current_index + 1]
return super(DocumentAdmin, self).change_view( return super(DocumentAdmin, self).change_view(
request, object_id, form_url, extra_context=extra_context, request, object_id, form_url, extra_context=extra_context,

View File

@ -127,7 +127,7 @@ class DocumentClassifier(object):
def classify_document(self, document, classify_correspondent=False, classify_document_type=False, classify_tags=False, replace_tags=False): def classify_document(self, document, classify_correspondent=False, classify_document_type=False, classify_tags=False, replace_tags=False):
X = self.data_vectorizer.transform([preprocess_content(document.content)]) X = self.data_vectorizer.transform([preprocess_content(document.content)])
update_fields=() update_fields = ()
if classify_correspondent and self.correspondent_classifier is not None: if classify_correspondent and self.correspondent_classifier is not None:
y_correspondent = self.correspondent_classifier.predict(X) y_correspondent = self.correspondent_classifier.predict(X)

View File

@ -3,7 +3,7 @@ import os.path
import pickle import pickle
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from documents.classifier import DocumentClassifier from documents.classifier import DocumentClassifier
from paperless import settings from paperless import settings
from ...mixins import Renderable from ...mixins import Renderable

View File

@ -4,7 +4,7 @@
{{ block.super }} {{ block.super }}
{% if file_type in "pdf jpg png" %} {% if file_type in "asd" %}
<div id="change_form_twocolumn_parent"> <div id="change_form_twocolumn_parent">
<div id="change_form_form_parent"></div> <div id="change_form_form_parent"></div>
@ -23,16 +23,17 @@
django.jQuery("#content-main").append(django.jQuery("#change_form_twocolumn_parent")); django.jQuery("#content-main").append(django.jQuery("#change_form_twocolumn_parent"));
</script> </script>
{% if next_object %} {% endif %}
<script type="text/javascript">//<![CDATA[
(function($){ {% if next_object %}
$('<input type="submit" value="Save and edit next" name="_saveandeditnext" />') <script type="text/javascript">//<![CDATA[
.prependTo('div.submit-row'); (function($){
$('<input type="hidden" value="{{next_object}}" name="_next_object" />') $('<input type="submit" value="Save and edit next" name="_saveandeditnext" />')
.prependTo('div.submit-row'); .prependTo('div.submit-row');
})(django.jQuery); $('<input type="hidden" value="{{next_object}}" name="_next_object" />')
//]]></script> .prependTo('div.submit-row');
{% endif %} })(django.jQuery);
//]]></script>
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}

View File

@ -38,7 +38,7 @@
<input type="hidden" name="action" value="{{action}}"/> <input type="hidden" name="action" value="{{action}}"/>
<input type="hidden" name="post" value="yes"/> <input type="hidden" name="post" value="yes"/>
<p> <p>
<input type="submit" value="{% trans " Confirm" %}" /> <input type="submit" value="{% trans "Confirm" %}" />
<a href="#" class="button cancel-link">{% trans "Go back" %}</a> <a href="#" class="button cancel-link">{% trans "Go back" %}</a>
</p> </p>
</div> </div>

View File

@ -1,2 +1 @@
<img src="{{download_url}}" style="max-width: 100%"> <img src="{{download_url}}" style="max-width: 100%">

View File

@ -3,117 +3,128 @@
<div> <div>
<input id="prev" value="Previous" class="default" type="button"> <input id="prev" value="Previous" class="default" type="button">
<input id="next" value="Next" class="default" type="button"> <input id="next" value="Next" class="default" type="button">
&nbsp; &nbsp; &nbsp; &nbsp;
<span>Page: <span id="page_num"></span> / <span id="page_count"></span></span> <span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
&nbsp; &nbsp; &nbsp; &nbsp;
<input id="zoomin" value="+" class="default" type="button"> <input id="zoomin" value="+" class="default" type="button">
<input id="zoomout" value="-" class="default" type="button"> <input id="zoomout" value="-" class="default" type="button">
</div> </div>
<div style="width: 100%; overflow: auto;"> <div style="width: 100%; overflow: auto;">
<canvas id="the-canvas"></canvas> <canvas id="the-canvas"></canvas>
</div> </div>
<script type="text/javascript" src="{% static 'documents/js/pdf.js' %}"></script> <script type="text/javascript" src="{% static 'documents/js/pdf.js' %}"></script>
<script type="text/javascript" src="{% static 'documents/js/pdf.worker.js' %}"></script> <script type="text/javascript" src="{% static 'documents/js/pdf.worker.js' %}"></script>
{# Load and display PDF document#}
<script> {# Load and display PDF document#}
<script>
var pdfjsLib = window['pdfjs-dist/build/pdf']; var pdfjsLib = window['pdfjs-dist/build/pdf'];
var pdfDoc = null, var pdfDoc = null,
pageNum = 1, pageNum = 1,
pageRendering = false, pageRendering = false,
pageNumPending = null, pageNumPending = null,
scale = 1.0, scale = 1.0,
canvas = document.getElementById('the-canvas'), canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d'); ctx = canvas.getContext('2d');
/** /**
* Get page info from document, resize canvas accordingly, and render page. * Get page info from document, resize canvas accordingly, and render page.
* @param num Page number. * @param num Page number.
*/ */
function renderPage(num) { function renderPage(num) {
pageRendering = true; pageRendering = true;
// Using promise to fetch the page // Using promise to fetch the page
pdfDoc.getPage(num).then(function(page) { pdfDoc.getPage(num).then(function(page) {
var viewport = page.getViewport(scale); var viewport = page.getViewport(scale);
canvas.height = viewport.height; canvas.height = viewport.height;
canvas.width = viewport.width; canvas.width = viewport.width;
// Render PDF page into canvas context // Render PDF page into canvas context
var renderContext = { var renderContext = {
canvasContext: ctx, canvasContext: ctx,
viewport: viewport viewport: viewport
}; };
var renderTask = page.render(renderContext); var renderTask = page.render(renderContext);
// Wait for rendering to finish // Wait for rendering to finish
renderTask.promise.then(function () { renderTask.promise.then(function () {
pageRendering = false; pageRendering = false;
if (pageNumPending !== null) { if (pageNumPending !== null) {
// New page rendering is pending // New page rendering is pending
renderPage(pageNumPending); renderPage(pageNumPending);
pageNumPending = null; pageNumPending = null;
} }
}); });
}); });
// Update page counters // Update page counters
document.getElementById('page_num').textContent = num; document.getElementById('page_num').textContent = num;
} }
/**
* If another page rendering in progress, waits until the rendering is /**
* finised. Otherwise, executes rendering immediately. * If another page rendering in progress, waits until the rendering is
*/ * finised. Otherwise, executes rendering immediately.
function queueRenderPage(num) { */
function queueRenderPage(num) {
if (pageRendering) { if (pageRendering) {
pageNumPending = num; pageNumPending = num;
} else { } else {
renderPage(num); renderPage(num);
} }
} }
/**
* Displays previous page. /**
*/ * Displays previous page.
function onPrevPage() { */
function onPrevPage() {
if (pageNum <= 1) { if (pageNum <= 1) {
return; return;
} }
pageNum--; pageNum--;
queueRenderPage(pageNum); queueRenderPage(pageNum);
} }
document.getElementById('prev').addEventListener('click', onPrevPage);
/** document.getElementById('prev').addEventListener('click', onPrevPage);
* Displays next page.
*/ /**
function onNextPage() { * Displays next page.
*/
function onNextPage() {
if (pageNum >= pdfDoc.numPages) { if (pageNum >= pdfDoc.numPages) {
return; return;
} }
pageNum++; pageNum++;
queueRenderPage(pageNum); queueRenderPage(pageNum);
} }
document.getElementById('next').addEventListener('click', onNextPage);
/** document.getElementById('next').addEventListener('click', onNextPage);
* Displays next page.
*/ /**
function onZoomIn() { * Displays next page.
*/
function onZoomIn() {
scale *= 1.2; scale *= 1.2;
queueRenderPage(pageNum); queueRenderPage(pageNum);
} }
document.getElementById('zoomin').addEventListener('click', onZoomIn);
/** document.getElementById('zoomin').addEventListener('click', onZoomIn);
* Displays next page.
*/ /**
function onZoomOut() { * Displays next page.
*/
function onZoomOut() {
scale /= 1.2; scale /= 1.2;
queueRenderPage(pageNum); queueRenderPage(pageNum);
} }
document.getElementById('zoomout').addEventListener('click', onZoomOut);
/** document.getElementById('zoomout').addEventListener('click', onZoomOut);
* Asynchronously downloads PDF.
*/ /**
pdfjsLib.getDocument("{{download_url}}").then(function (pdfDoc_) { * Asynchronously downloads PDF.
*/
pdfjsLib.getDocument("{{download_url}}").then(function (pdfDoc_) {
pdfDoc = pdfDoc_; pdfDoc = pdfDoc_;
document.getElementById('page_count').textContent = pdfDoc.numPages; document.getElementById('page_count').textContent = pdfDoc.numPages;
// Initial/first page rendering // Initial/first page rendering
renderPage(pageNum); renderPage(pageNum);
}); });
</script> </script>

View File

@ -298,4 +298,8 @@ FY_END = os.getenv("PAPERLESS_FINANCIAL_YEAR_END")
# Specify the default date order (for autodetected dates) # Specify the default date order (for autodetected dates)
DATE_ORDER = os.getenv("PAPERLESS_DATE_ORDER", "DMY") DATE_ORDER = os.getenv("PAPERLESS_DATE_ORDER", "DMY")
PAPERLESS_RECENT_CORRESPONDENT_YEARS = int(os.getenv("PAPERLESS_RECENT_CORRESPONDENT_YEARS", 1)) # Specify for how many years a correspondent is considered recent. Recent
# correspondents will be shown in a separate "Recent correspondents" filter as
# well. Set to 0 to disable this filter.
PAPERLESS_RECENT_CORRESPONDENT_YEARS = int(os.getenv(
"PAPERLESS_RECENT_CORRESPONDENT_YEARS", 0))