mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Removed a bunch of stuff thats not needed anymore with the new gui.
This commit is contained in:
		| @@ -1,204 +0,0 @@ | ||||
| from django.contrib import messages | ||||
| from django.contrib.admin import helpers | ||||
| from django.contrib.admin.utils import model_ngettext | ||||
| from django.core.exceptions import PermissionDenied | ||||
| from django.template.response import TemplateResponse | ||||
|  | ||||
| from documents.classifier import DocumentClassifier | ||||
| from documents.models import Correspondent, DocumentType, Tag | ||||
|  | ||||
|  | ||||
| def select_action( | ||||
|         modeladmin, request, queryset, title, action, modelclass, | ||||
|         success_message="", document_action=None, queryset_action=None): | ||||
|  | ||||
|     opts = modeladmin.model._meta | ||||
|     app_label = opts.app_label | ||||
|  | ||||
|     if not modeladmin.has_change_permission(request): | ||||
|         raise PermissionDenied | ||||
|  | ||||
|     if request.POST.get("post"): | ||||
|         n = queryset.count() | ||||
|         selected_object = modelclass.objects.get(id=request.POST.get("obj_id")) | ||||
|         if n: | ||||
|             for document in queryset: | ||||
|                 if document_action: | ||||
|                     document_action(document, selected_object) | ||||
|                 document_display = str(document) | ||||
|                 modeladmin.log_change(request, document, document_display) | ||||
|             if queryset_action: | ||||
|                 queryset_action(queryset, selected_object) | ||||
|  | ||||
|             modeladmin.message_user(request, success_message % { | ||||
|                 "selected_object": selected_object.name, | ||||
|                 "count": n, | ||||
|                 "items": model_ngettext(modeladmin.opts, n) | ||||
|             }, messages.SUCCESS) | ||||
|  | ||||
|         # Return None to display the change list page again. | ||||
|         return None | ||||
|  | ||||
|     context = dict( | ||||
|         modeladmin.admin_site.each_context(request), | ||||
|         title=title, | ||||
|         queryset=queryset, | ||||
|         opts=opts, | ||||
|         action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, | ||||
|         media=modeladmin.media, | ||||
|         action=action, | ||||
|         objects=modelclass.objects.all(), | ||||
|         itemname=model_ngettext(modelclass, 1) | ||||
|     ) | ||||
|  | ||||
|     request.current_app = modeladmin.admin_site.name | ||||
|  | ||||
|     return TemplateResponse( | ||||
|         request, | ||||
|         "admin/{}/{}/select_object.html".format(app_label, opts.model_name), | ||||
|         context | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def simple_action( | ||||
|         modeladmin, request, queryset, success_message="", | ||||
|         document_action=None, queryset_action=None): | ||||
|  | ||||
|     if not modeladmin.has_change_permission(request): | ||||
|         raise PermissionDenied | ||||
|  | ||||
|     n = queryset.count() | ||||
|     if n: | ||||
|         for document in queryset: | ||||
|             if document_action: | ||||
|                 document_action(document) | ||||
|             document_display = str(document) | ||||
|             modeladmin.log_change(request, document, document_display) | ||||
|         if queryset_action: | ||||
|             queryset_action(queryset) | ||||
|         modeladmin.message_user(request, success_message % { | ||||
|             "count": n, "items": model_ngettext(modeladmin.opts, n) | ||||
|         }, messages.SUCCESS) | ||||
|  | ||||
|     # Return None to display the change list page again. | ||||
|     return None | ||||
|  | ||||
|  | ||||
| def add_tag_to_selected(modeladmin, request, queryset): | ||||
|     return select_action( | ||||
|         modeladmin=modeladmin, | ||||
|         request=request, | ||||
|         queryset=queryset, | ||||
|         title="Add tag to multiple documents", | ||||
|         action="add_tag_to_selected", | ||||
|         modelclass=Tag, | ||||
|         success_message="Successfully added tag %(selected_object)s to " | ||||
|                         "%(count)d %(items)s.", | ||||
|         document_action=lambda doc, tag: doc.tags.add(tag) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def remove_tag_from_selected(modeladmin, request, queryset): | ||||
|     return select_action( | ||||
|         modeladmin=modeladmin, | ||||
|         request=request, | ||||
|         queryset=queryset, | ||||
|         title="Remove tag from multiple documents", | ||||
|         action="remove_tag_from_selected", | ||||
|         modelclass=Tag, | ||||
|         success_message="Successfully removed tag %(selected_object)s from " | ||||
|                         "%(count)d %(items)s.", | ||||
|         document_action=lambda doc, tag: doc.tags.remove(tag) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def set_correspondent_on_selected(modeladmin, request, queryset): | ||||
|  | ||||
|     return select_action( | ||||
|         modeladmin=modeladmin, | ||||
|         request=request, | ||||
|         queryset=queryset, | ||||
|         title="Set correspondent on multiple documents", | ||||
|         action="set_correspondent_on_selected", | ||||
|         modelclass=Correspondent, | ||||
|         success_message="Successfully set correspondent %(selected_object)s " | ||||
|                         "on %(count)d %(items)s.", | ||||
|         queryset_action=lambda qs, corr: qs.update(correspondent=corr) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def remove_correspondent_from_selected(modeladmin, request, queryset): | ||||
|     return simple_action( | ||||
|         modeladmin=modeladmin, | ||||
|         request=request, | ||||
|         queryset=queryset, | ||||
|         success_message="Successfully removed correspondent from %(count)d " | ||||
|                         "%(items)s.", | ||||
|         queryset_action=lambda qs: qs.update(correspondent=None) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def set_document_type_on_selected(modeladmin, request, queryset): | ||||
|     return select_action( | ||||
|         modeladmin=modeladmin, | ||||
|         request=request, | ||||
|         queryset=queryset, | ||||
|         title="Set document type on multiple documents", | ||||
|         action="set_document_type_on_selected", | ||||
|         modelclass=DocumentType, | ||||
|         success_message="Successfully set document type %(selected_object)s " | ||||
|                         "on %(count)d %(items)s.", | ||||
|         queryset_action=lambda qs, document_type: qs.update( | ||||
|             document_type=document_type) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def remove_document_type_from_selected(modeladmin, request, queryset): | ||||
|     return simple_action( | ||||
|         modeladmin=modeladmin, | ||||
|         request=request, | ||||
|         queryset=queryset, | ||||
|         success_message="Successfully removed document type from %(count)d " | ||||
|                         "%(items)s.", | ||||
|         queryset_action=lambda qs: qs.update(document_type=None) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def run_document_classifier_on_selected(modeladmin, request, queryset): | ||||
|     clf = DocumentClassifier() | ||||
|     try: | ||||
|         clf.reload() | ||||
|         return simple_action( | ||||
|             modeladmin=modeladmin, | ||||
|             request=request, | ||||
|             queryset=queryset, | ||||
|             success_message="Successfully applied document classifier to " | ||||
|                             "%(count)d %(items)s.", | ||||
|             document_action=lambda doc: clf.classify_document( | ||||
|                 doc, | ||||
|                 classify_correspondent=True, | ||||
|                 classify_tags=True, | ||||
|                 classify_document_type=True) | ||||
|         ) | ||||
|     except FileNotFoundError: | ||||
|         modeladmin.message_user( | ||||
|             request, | ||||
|             "Classifier model file not found.", | ||||
|             messages.ERROR | ||||
|         ) | ||||
|         return None | ||||
|  | ||||
|  | ||||
| add_tag_to_selected.short_description = "Add tag to selected documents" | ||||
| remove_tag_from_selected.short_description = \ | ||||
|     "Remove tag from selected documents" | ||||
| set_correspondent_on_selected.short_description = \ | ||||
|     "Set correspondent on selected documents" | ||||
| remove_correspondent_from_selected.short_description = \ | ||||
|     "Remove correspondent from selected documents" | ||||
| set_document_type_on_selected.short_description = \ | ||||
|     "Set document type on selected documents" | ||||
| remove_document_type_from_selected.short_description = \ | ||||
|     "Remove document type from selected documents" | ||||
| run_document_classifier_on_selected.short_description = \ | ||||
|     "Run document classifier on selected" | ||||
| @@ -13,16 +13,6 @@ from django.utils.http import urlquote | ||||
| from django.utils.safestring import mark_safe | ||||
| from djangoql.admin import DjangoQLSearchMixin | ||||
|  | ||||
| from documents.actions import ( | ||||
|     add_tag_to_selected, | ||||
|     remove_correspondent_from_selected, | ||||
|     remove_tag_from_selected, | ||||
|     set_correspondent_on_selected, | ||||
|     set_document_type_on_selected, | ||||
|     remove_document_type_from_selected, | ||||
|     run_document_classifier_on_selected | ||||
| ) | ||||
|  | ||||
| from .models import Correspondent, Document, DocumentType, Log, Tag | ||||
|  | ||||
|  | ||||
| @@ -91,27 +81,6 @@ class FinancialYearFilter(admin.SimpleListFilter): | ||||
|                                created__lte=self._fy_end(end)) | ||||
|  | ||||
|  | ||||
| class RecentCorrespondentFilter(admin.RelatedFieldListFilter): | ||||
|     """ | ||||
|     If PAPERLESS_RECENT_CORRESPONDENT_YEARS is set, we limit the available | ||||
|     correspondents to documents sent our way over the past ``n`` years. | ||||
|     """ | ||||
|  | ||||
|     def field_choices(self, field, request, model_admin): | ||||
|  | ||||
|         years = settings.PAPERLESS_RECENT_CORRESPONDENT_YEARS | ||||
|         correspondents = Correspondent.objects.all() | ||||
|  | ||||
|         if years and years > 0: | ||||
|             self.title = "Correspondent (Recent)" | ||||
|             days = 365 * years | ||||
|             correspondents = correspondents.filter( | ||||
|                 documents__created__gte=datetime.now() - timedelta(days=days) | ||||
|             ).distinct() | ||||
|  | ||||
|         return [(c.id, c.name) for c in correspondents] | ||||
|  | ||||
|  | ||||
| class CommonAdmin(admin.ModelAdmin): | ||||
|     list_per_page = settings.PAPERLESS_LIST_PER_PAGE | ||||
|  | ||||
| @@ -196,12 +165,12 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | ||||
|  | ||||
|     search_fields = ("correspondent__name", "title", "content", "tags__name") | ||||
|     readonly_fields = ("added", "file_type", "storage_type",) | ||||
|     list_display = ("title", "created", "added", "thumbnail", "correspondent", | ||||
|     list_display = ("title", "created", "added", "correspondent", | ||||
|                     "tags_", "archive_serial_number", "document_type") | ||||
|     list_filter = ( | ||||
|         "document_type", | ||||
|         "tags", | ||||
|         ("correspondent", RecentCorrespondentFilter), | ||||
|         "correspondent", | ||||
|         FinancialYearFilter | ||||
|     ) | ||||
|  | ||||
| @@ -209,22 +178,8 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | ||||
|  | ||||
|     ordering = ["-created", "correspondent"] | ||||
|  | ||||
|     actions = [ | ||||
|         add_tag_to_selected, | ||||
|         remove_tag_from_selected, | ||||
|         set_correspondent_on_selected, | ||||
|         remove_correspondent_from_selected, | ||||
|         set_document_type_on_selected, | ||||
|         remove_document_type_from_selected, | ||||
|         run_document_classifier_on_selected | ||||
|     ] | ||||
|  | ||||
|     date_hierarchy = "created" | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.document_queue = [] | ||||
|  | ||||
|     def has_add_permission(self, request): | ||||
|         return False | ||||
|  | ||||
| @@ -232,81 +187,6 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | ||||
|         return obj.created.date().strftime("%Y-%m-%d") | ||||
|     created_.short_description = "Created" | ||||
|  | ||||
|     def changelist_view(self, request, extra_context=None): | ||||
|  | ||||
|         response = super().changelist_view( | ||||
|             request, | ||||
|             extra_context=extra_context | ||||
|         ) | ||||
|  | ||||
|         if request.method == "GET": | ||||
|             cl = self.get_changelist_instance(request) | ||||
|             self.document_queue = [doc.id for doc in cl.queryset] | ||||
|  | ||||
|         return response | ||||
|  | ||||
|     def change_view(self, request, object_id=None, form_url='', | ||||
|                     extra_context=None): | ||||
|  | ||||
|         extra_context = extra_context or {} | ||||
|         doc = Document.objects.get(id=object_id) | ||||
|         extra_context["download_url"] = doc.download_url | ||||
|         extra_context["file_type"] = doc.file_type | ||||
|  | ||||
|         if self.document_queue and object_id: | ||||
|             if int(object_id) in self.document_queue: | ||||
|                 # There is a queue of documents | ||||
|                 current_index = self.document_queue.index(int(object_id)) | ||||
|                 if current_index < len(self.document_queue) - 1: | ||||
|                     # ... and there are still documents in the queue | ||||
|                     extra_context["next_object"] = self.document_queue[ | ||||
|                         current_index + 1 | ||||
|                     ] | ||||
|  | ||||
|         return super(DocumentAdmin, self).change_view( | ||||
|             request, | ||||
|             object_id, | ||||
|             form_url, | ||||
|             extra_context=extra_context, | ||||
|         ) | ||||
|  | ||||
|     def response_change(self, request, obj): | ||||
|  | ||||
|         # This is mostly copied from ModelAdmin.response_change() | ||||
|         opts = self.model._meta | ||||
|         preserved_filters = self.get_preserved_filters(request) | ||||
|  | ||||
|         msg_dict = { | ||||
|             "name": opts.verbose_name, | ||||
|             "obj": format_html( | ||||
|                 '<a href="{}">{}</a>', | ||||
|                 urlquote(request.path), | ||||
|                 obj | ||||
|             ), | ||||
|         } | ||||
|         if "_saveandeditnext" in request.POST: | ||||
|             msg = format_html( | ||||
|                 'The {name} "{obj}" was changed successfully. ' | ||||
|                 'Editing next object.', | ||||
|                 **msg_dict | ||||
|             ) | ||||
|             self.message_user(request, msg, messages.SUCCESS) | ||||
|             redirect_url = reverse( | ||||
|                 "admin:{}_{}_change".format(opts.app_label, opts.model_name), | ||||
|                 args=(request.POST["_next_object"],), | ||||
|                 current_app=self.admin_site.name | ||||
|             ) | ||||
|             redirect_url = add_preserved_filters( | ||||
|                 { | ||||
|                     "preserved_filters": preserved_filters, | ||||
|                     "opts": opts | ||||
|                 }, | ||||
|                 redirect_url | ||||
|             ) | ||||
|             return HttpResponseRedirect(redirect_url) | ||||
|  | ||||
|         return super().response_change(request, obj) | ||||
|  | ||||
|     @mark_safe | ||||
|     def thumbnail(self, obj): | ||||
|         return self._html_tag( | ||||
| @@ -314,7 +194,7 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | ||||
|             self._html_tag( | ||||
|                 "img", | ||||
|                 src=reverse("fetch", kwargs={"kind": "thumb", "pk": obj.pk}), | ||||
|                 width=180, | ||||
|                 height=100, | ||||
|                 alt="Thumbnail of {}".format(obj.file_name), | ||||
|                 title=obj.file_name | ||||
|             ), | ||||
| @@ -327,16 +207,8 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | ||||
|         for tag in obj.tags.all(): | ||||
|             colour = tag.get_colour_display() | ||||
|             r += self._html_tag( | ||||
|                 "a", | ||||
|                 tag.slug, | ||||
|                 **{ | ||||
|                     "class": "tag", | ||||
|                     "style": "background-color: {};".format(colour), | ||||
|                     "href": "{}?tags__id__exact={}".format( | ||||
|                         reverse("admin:documents_document_changelist"), | ||||
|                         tag.pk | ||||
|                     ) | ||||
|                 } | ||||
|                 "span", | ||||
|                 tag.slug + ", " | ||||
|             ) | ||||
|         return r | ||||
|  | ||||
| @@ -381,5 +253,5 @@ admin.site.register(Log, LogAdmin) | ||||
|  | ||||
|  | ||||
| # Unless we implement multi-user, these default registrations don't make sense. | ||||
| admin.site.unregister(Group) | ||||
| admin.site.unregister(User) | ||||
| #admin.site.unregister(Group) | ||||
| #admin.site.unregister(User) | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| image.png | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 30 KiB | 
| @@ -1 +0,0 @@ | ||||
| image.png | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 4.5 KiB | 
| @@ -1 +0,0 @@ | ||||
| image.png | ||||
| @@ -1 +0,0 @@ | ||||
| image.png | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										41660
									
								
								src/documents/static/documents/js/pdf.worker.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										41660
									
								
								src/documents/static/documents/js/pdf.worker.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -1,66 +0,0 @@ | ||||
| // The following jQuery snippet will add a small square next to the selection | ||||
| // drop-down on the `Add tag` page that will update to show the selected tag | ||||
| // color as the drop-down value is changed. | ||||
|  | ||||
| django.jQuery(document).ready(function(){ | ||||
|  | ||||
|   if (django.jQuery("#id_colour").length) { | ||||
|  | ||||
|     let colour; | ||||
|     let colour_num; | ||||
|  | ||||
|     colour_num = django.jQuery("#id_colour").val() - 1; | ||||
|     colour = django.jQuery('#id_colour')[0][colour_num].text; | ||||
|     django.jQuery('#id_colour').after('<div class="colour_square"></div>'); | ||||
|  | ||||
|     django.jQuery('.colour_square').css({ | ||||
|       'float': 'left', | ||||
|       'width': '20px', | ||||
|       'height': '20px', | ||||
|       'margin': '5px', | ||||
|       'border': '1px solid rgba(0, 0, 0, .2)', | ||||
|       'background': colour | ||||
|     }); | ||||
|  | ||||
|     django.jQuery('#id_colour').change(function () { | ||||
|       colour_num = django.jQuery("#id_colour").val() - 1; | ||||
|       colour = django.jQuery('#id_colour')[0][colour_num].text; | ||||
|       django.jQuery('.colour_square').css({'background': colour}); | ||||
|     }); | ||||
|  | ||||
|   } else if (django.jQuery("select[id*='colour']").length) { | ||||
|  | ||||
|     django.jQuery('select[id*="-colour"]').each(function (index, element) { | ||||
|       let id; | ||||
|       let loop_colour_num; | ||||
|       let loop_colour; | ||||
|  | ||||
|       id = "colour_square_" + index; | ||||
|       django.jQuery(element).after('<div class="colour_square" id="' + id + '"></div>'); | ||||
|  | ||||
|       loop_colour_num = django.jQuery(element).val() - 1; | ||||
|       loop_colour = django.jQuery(element)[0][loop_colour_num].text; | ||||
|  | ||||
|       django.jQuery("<style type='text/css'>\ | ||||
|                         .colour_square{ \ | ||||
|                             float: left; \ | ||||
|                             width: 20px; \ | ||||
|                             height: 20px; \ | ||||
|                             margin: 5px; \ | ||||
|                             border: 1px solid rgba(0,0,0,.2); \ | ||||
|                         } </style>").appendTo("head"); | ||||
|       django.jQuery('#' + id).css({'background': loop_colour}); | ||||
|  | ||||
|       console.log(id, loop_colour_num, loop_colour); | ||||
|  | ||||
|       django.jQuery(element).change(function () { | ||||
|         loop_colour_num = django.jQuery(element).val() - 1; | ||||
|         loop_colour = django.jQuery(element)[0][loop_colour_num].text; | ||||
|         django.jQuery('#' + id).css({'background': loop_colour}); | ||||
|         console.log('#' + id, loop_colour) | ||||
|       }); | ||||
|     }) | ||||
|  | ||||
|   } | ||||
|  | ||||
| }); | ||||
| @@ -1,36 +0,0 @@ | ||||
| th.column-document, | ||||
| td.field-document { | ||||
|   text-align: center; | ||||
| } | ||||
|  | ||||
| td a.tag { | ||||
|   padding: 0 0.5em; | ||||
|   color: #ffffff; | ||||
|   border-radius: 0.2em; | ||||
|   margin: 1px; | ||||
|   display: inline-block; | ||||
| } | ||||
|  | ||||
| #result_list th.column-note { | ||||
|   text-align: right; | ||||
| } | ||||
| #result_list td.field-note { | ||||
|   text-align: right; | ||||
| } | ||||
| #result_list td textarea { | ||||
|   width: 90%; | ||||
|   height: 5em; | ||||
| } | ||||
|  | ||||
| #change_form_twocolumn_parent { | ||||
|   display: flex; | ||||
| } | ||||
| #change_form_form_parent { | ||||
|   flex:50%; | ||||
|   margin-right: 10px; | ||||
| } | ||||
| #change_form_viewer_parent { | ||||
|   flex:50%; | ||||
|   margin-left: 10px; | ||||
|   text-align: center; | ||||
| } | ||||
| @@ -1,93 +0,0 @@ | ||||
| {% extends 'admin/base_site.html' %} | ||||
|  | ||||
| {# NOTE: This should probably be extending base.html.  See CSS comment below details. #} | ||||
|  | ||||
|  | ||||
| {% load static %} | ||||
| {% load custom_css from customisation %} | ||||
| {% load custom_js from customisation %} | ||||
|  | ||||
|  | ||||
| {% block extrahead %} | ||||
| 	<link rel="icon" type="image/x-icon" href="{% url 'favicon' %}" /> | ||||
| 	<style> | ||||
| 		#header { | ||||
| 			background-color: #90a9b7; | ||||
| 			line-height: inherit; | ||||
| 			height: auto; | ||||
| 		} | ||||
| 		#branding h1 { | ||||
| 			font-weight: inherit; | ||||
| 			font-size: inherit; | ||||
| 		} | ||||
| 		.button, | ||||
| 		.button:active, | ||||
| 		.button:focus, | ||||
| 		.button:hover, | ||||
| 		a.button, | ||||
| 		.submit-row input, | ||||
| 		input[type="submit"], | ||||
| 		input[type="submit"]:active, | ||||
| 		input[type="submit"]:focus, | ||||
| 		input[type="submit"]:hover, | ||||
| 		input[type="button"], | ||||
| 		input[type="button"]:active, | ||||
| 		input[type="button"]:focus, | ||||
| 		input[type="button"]:hover { | ||||
| 			background-color: #074f57; | ||||
| 		} | ||||
| 		.module h2, | ||||
| 		.module caption, | ||||
| 		.inline-group h2 { | ||||
| 			background-color: #90a9b7; | ||||
| 		} | ||||
| 		div.breadcrumbs { | ||||
| 			background-color: #077187; | ||||
| 		} | ||||
| 		.module h2, | ||||
| 		.module caption, | ||||
| 		.inline-group h2 { | ||||
| 			background-color: #077187; | ||||
| 		} | ||||
| 	</style> | ||||
| {% endblock %} | ||||
|  | ||||
|  | ||||
| {% block branding %} | ||||
| <h1 id="site-name"> | ||||
| 	<a href="{% url 'admin:index' %}"><img src="{% static 'paperless/img/logo-light.png' %}" alt="Paperless" /></a> | ||||
| </h1> | ||||
| {% endblock %} | ||||
|  | ||||
|  | ||||
| {% block blockbots %} | ||||
|  | ||||
| 	{% comment %} | ||||
| 		This really should be extending `extrastyle`, but the the | ||||
| 		django-flat-responsive package decided that it wanted to put its CSS in | ||||
| 		this block, so to make sure that overrides are in fact overriding | ||||
| 		everything else, we have to do the Wrong Thing here. | ||||
|  | ||||
| 		Once we switch to Django 2.x and drop django-flat-responsive, we should | ||||
| 		switch this to `extrastyle` where it should be. | ||||
| 	{% endcomment %} | ||||
|  | ||||
| 	{{ block.super }} | ||||
|  | ||||
| 	{% custom_css %} | ||||
|  | ||||
| {% endblock blockbots %} | ||||
|  | ||||
|  | ||||
| {% block footer %} | ||||
|  | ||||
| 	{% comment %} | ||||
| 		The Django admin doesn't have a block for Javascript you'd want placed in | ||||
| 		the footer, so we have to use this one instead. | ||||
| 	{% endcomment %} | ||||
|  | ||||
| 	{{ block.super }} | ||||
|  | ||||
| 	{% custom_js %} | ||||
|  | ||||
| {% endblock footer %} | ||||
| @@ -1,94 +0,0 @@ | ||||
| {% extends 'admin/change_form.html' %} | ||||
|  | ||||
| {% block object-tools-items %} | ||||
|   <li> | ||||
|     <a href="{{download_url}}"> | ||||
|      Download file | ||||
|     </a> | ||||
|   </li> | ||||
|   {{ block.super }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| {{ block.super }} | ||||
| <div class="side-preview"> | ||||
|   <h2>Preview</h2> | ||||
|   <object data="/fetch/preview/{{object_id}}"></object> | ||||
| </div> | ||||
|  | ||||
| {% if file_type in "pdf jpg png" %} | ||||
|  | ||||
| 	<div id="change_form_twocolumn_parent"> | ||||
| 		<div id="change_form_form_parent"></div> | ||||
| 		<div id="change_form_viewer_parent"> | ||||
| 			{% if file_type == "pdf" %} | ||||
| 				{% include "admin/documents/document/viewers/viewer_pdf.html" %} | ||||
| 			{% endif %} | ||||
| 			{% if file_type in "jpg png" %} | ||||
| 				{% include "admin/documents/document/viewers/viewer_image.html" %} | ||||
| 			{% endif %} | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | ||||
| 	<script> | ||||
| 		django.jQuery("#change_form_form_parent").append(django.jQuery("#document_form")); | ||||
| 		django.jQuery("#content-main").append(django.jQuery("#change_form_twocolumn_parent")); | ||||
| 	</script> | ||||
|  | ||||
| {% endif %} | ||||
|  | ||||
| {% if next_object %} | ||||
| 	<script type="text/javascript">//<![CDATA[ | ||||
| 		(function($){ | ||||
| 			$('<input type="submit" value="Save and edit next" name="_saveandeditnext" />') | ||||
| 			.prependTo('div.submit-row'); | ||||
| 			$('<input type="hidden" value="{{next_object}}" name="_next_object" />') | ||||
| 			.prependTo('div.submit-row'); | ||||
| 		})(django.jQuery); | ||||
| 	//]]></script> | ||||
| {% endif %} | ||||
|  | ||||
| {% endblock content %} | ||||
|  | ||||
| {% block extrastyle %} | ||||
| {{ block.super }} | ||||
| <style> | ||||
| .side-preview { | ||||
|     width: 100%; | ||||
|     height: 800px; | ||||
|     clear: both; | ||||
| } | ||||
|  | ||||
| .side-preview object { | ||||
|     height: 100%; | ||||
|     width: 100%; | ||||
| } | ||||
|  | ||||
| @media screen and (min-width: 1500px) { | ||||
|     #content-main { | ||||
|         width: 50%; | ||||
|     } | ||||
|     #footer { | ||||
|         padding: 0; | ||||
|     } | ||||
|     .side-preview { | ||||
|         float: right; | ||||
|         width: 40%; | ||||
|         height: 80vh; | ||||
|         clear: none; | ||||
|     } | ||||
| } | ||||
| </style> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block footer %} | ||||
|  | ||||
| 	{{ block.super }} | ||||
|  | ||||
| 	{# Hack to force Django to make the created date a date input rather than `text` (the default) #} | ||||
| 	<script> | ||||
| 		django.jQuery(".field-created input").first().attr("type", "date") | ||||
| 	</script> | ||||
|  | ||||
| {% endblock footer %} | ||||
| @@ -1,12 +0,0 @@ | ||||
| {% extends 'admin/change_list.html' %} | ||||
|  | ||||
|  | ||||
| {% load admin_actions from admin_list%} | ||||
| {% load result_list from hacks %} | ||||
|  | ||||
|  | ||||
| {% block result_list %} | ||||
| 	{% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %} | ||||
| 	{% result_list cl %} | ||||
| 	{% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %} | ||||
| {% endblock %} | ||||
| @@ -1,228 +0,0 @@ | ||||
| {% load i18n %} | ||||
|  | ||||
| <style> | ||||
|   .grid *, .grid *:after, .grid *:before { | ||||
|     -webkit-box-sizing: border-box; | ||||
|     -moz-box-sizing: border-box; | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|   .grid { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     margin: 10px 0px 10px 10px; | ||||
|   } | ||||
|   .box { | ||||
|     width: 12.5%; | ||||
|     padding-right: 10px; | ||||
|     padding-bottom: 15px; | ||||
|     opacity: 0.8; | ||||
|     transition: all 0.5s; | ||||
|   } | ||||
|   .box:hover { | ||||
|     opacity: 1; | ||||
|     transition: all 0.5s; | ||||
|   } | ||||
|   .result { | ||||
|     border: 1px solid #cccccc; | ||||
|     border-radius: 2%; | ||||
|     overflow: hidden; | ||||
|     height: 350px; | ||||
|     position: relative; | ||||
|     box-shadow: 1px 1px 4px #cccccc; | ||||
|   } | ||||
|   .result .header { | ||||
|     padding: 5px; | ||||
|     background-color: #90a9b7; | ||||
|     position: relative; | ||||
|   } | ||||
|   .result .header .checkbox { | ||||
|     width: 5%; | ||||
|     float: left; | ||||
|     position: absolute; | ||||
|     z-index: 2; | ||||
|   } | ||||
|   .result .header .info { | ||||
|     margin-left: 10%; | ||||
|     position: relative; | ||||
|   } | ||||
|   .headerLink { | ||||
|     cursor: pointer; | ||||
|     opacity: 0; | ||||
|     z-index: 1; | ||||
|     position: absolute; | ||||
|     top: 0; | ||||
|     left: 0; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|   } | ||||
|   .header > a { | ||||
|     z-index: 2; | ||||
|     margin-left: 10%; | ||||
|     position: relative; | ||||
|   } | ||||
|   .result .header a, | ||||
|   .result a.tag { | ||||
|     color: #ffffff; | ||||
|   } | ||||
|   .result .documentType { | ||||
|     padding: 5px; | ||||
|     background-color: #eeeeee; | ||||
|     text-align: center; | ||||
|   } | ||||
|   .result .date { | ||||
|     padding: 5px; | ||||
|   } | ||||
|   .result .tags { | ||||
|     float: left; | ||||
|   } | ||||
|   .result .tags a.tag { | ||||
|     padding: 2px 5px; | ||||
|     border-radius: 2px; | ||||
|     display: inline-block; | ||||
|     margin: 2px; | ||||
|   } | ||||
|   .result .date { | ||||
|     float: right; | ||||
|     color: #cccccc; | ||||
|   } | ||||
|   .result .image img { | ||||
|     width: 100%; | ||||
|   } | ||||
|   .result .footer { | ||||
|     position: absolute; | ||||
|     bottom: 0; | ||||
|     right: 0; | ||||
|     border-left: 1px solid #cccccc; | ||||
|     border-top: 1px solid #cccccc; | ||||
|     padding: 4px 10px 4px 10px; | ||||
|     background: white; | ||||
|   } | ||||
|  | ||||
|   .grid:after { | ||||
|     content: ""; | ||||
|     display: table; | ||||
|     clear: both; | ||||
|   } | ||||
|  | ||||
|   @media (max-width: 1600px) { | ||||
|     .box { | ||||
|       width: 25% | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @media (max-width: 991px) { | ||||
|     .grid { | ||||
|       margin-right: 220px; | ||||
|     } | ||||
|     .box { | ||||
|       width: 50% | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @media (max-width: 767px) { | ||||
|     .grid { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @media (max-width: 500px) { | ||||
|     .box { | ||||
|       width: 100% | ||||
|     } | ||||
|   } | ||||
|  | ||||
| </style> | ||||
|  | ||||
|  | ||||
| {# This is just copypasta from the parent change_list_results.html file #} | ||||
|  | ||||
| {% if result_hidden_fields %} | ||||
| <div class="hiddenfields">{# DIV for HTML validation #} | ||||
| {% for item in result_hidden_fields %}{{ item }}{% endfor %} | ||||
| </div> | ||||
| {% endif %} | ||||
|  | ||||
| {% if results %} | ||||
| <div class="results"> | ||||
| <table id="result_list"> | ||||
| <thead> | ||||
| <tr> | ||||
| {% for header in result_headers %} | ||||
| <th scope="col" {{ header.class_attrib }}> | ||||
|    {% if header.sortable %} | ||||
|      {% if header.sort_priority > 0 %} | ||||
|        <div class="sortoptions"> | ||||
|          <a class="sortremove" href="{{ header.url_remove }}" title="{% trans "Remove from sorting" %}"></a> | ||||
|          {% if num_sorted_fields > 1 %}<span class="sortpriority" title="{% blocktrans with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktrans %}">{{ header.sort_priority }}</span>{% endif %} | ||||
|          <a href="{{ header.url_toggle }}" class="toggle {% if header.ascending %}ascending{% else %}descending{% endif %}" title="{% trans "Toggle sorting" %}"></a> | ||||
|        </div> | ||||
|      {% endif %} | ||||
|    {% endif %} | ||||
|    <div class="text">{% if header.sortable %}<a href="{{ header.url_primary }}">{{ header.text|capfirst }}</a>{% else %}<span>{{ header.text|capfirst }}</span>{% endif %}</div> | ||||
|    <div class="clear"></div> | ||||
| </th>{% endfor %} | ||||
| </tr> | ||||
| </thead> | ||||
| </table> | ||||
| {% endif %} | ||||
|  | ||||
| {# /copypasta #} | ||||
|  | ||||
|  | ||||
| <div class="grid"> | ||||
|   {% for result in results %} | ||||
|     {# 0: Checkbox #} | ||||
|     {# 1: Title #} | ||||
|     {# 2: Date #} | ||||
|     {# 3: Added #} | ||||
|     {# 4: Image #} | ||||
|     {# 5: Correspondent #} | ||||
|     {# 6: Tags #} | ||||
|     {# 7: Archive serial number #} | ||||
|     {# 8: Document type #} | ||||
|     {# 9: Document edit url #} | ||||
|     <div class="box"> | ||||
|       <div class="result"> | ||||
|         <div class="header"> | ||||
|           {% comment %} | ||||
|             The purpose of 'headerLink' is to make the whole header | ||||
|             background clickable. | ||||
|             We use an onclick handler here instead of a native link ('<a>') | ||||
|             to allow selecting (and copying) the overlying doc title text | ||||
|             with the mouse cursor. | ||||
|             If the title link were layered upon another link ('<a>'), title text | ||||
|             selection would not be possible with mouse click + drag. Instead, | ||||
|             the underlying link would be dragged. | ||||
|           {% endcomment %} | ||||
|           <div class="headerLink" onclick="location.href='{{ result.9 }}';"></div> | ||||
|           <div class="checkbox">{{ result.0 }}</div> | ||||
|           <div class="info"> | ||||
|             {{ result.5 }} | ||||
|           </div> | ||||
|           {{ result.1 }} | ||||
|           <div style="clear: both;"></div> | ||||
|         </div> | ||||
|         {% if '>-<' not in result.8 %}<div class="documentType">{{ result.8 }}</div>{% endif %} | ||||
|         <div class="tags">{{ result.6 }}</div> | ||||
|         <div class="date">{{ result.2 }}</div> | ||||
|         <div style="clear: both;"></div> | ||||
|         <div class="image">{{ result.4 }}</div> | ||||
|         {# Only show the archive serial number if it is set on the document. #} | ||||
|         {# checking for >-< (i.e., will a dash be displayed) doesn't feel like a very good solution to me. #} | ||||
|         {% if '>-<' not in result.7 %}<div class="footer">#{{ result.7 }}</div>{% endif %} | ||||
|       </div> | ||||
|     </div> | ||||
|   {% endfor %} | ||||
| </div> | ||||
|  | ||||
|  | ||||
| <script> | ||||
|   // We need to re-build the select-all functionality as the old logic pointed | ||||
|   // to a table and we're using divs now. | ||||
|   django.jQuery("#action-toggle").on("change", function(){ | ||||
|     django.jQuery(".grid .box .result .checkbox input") | ||||
|       .prop("checked", this.checked); | ||||
|   }); | ||||
| </script> | ||||
|  | ||||
| </div> | ||||
| @@ -1,50 +0,0 @@ | ||||
| {% extends "admin/base_site.html" %} | ||||
|  | ||||
|  | ||||
| {% load i18n l10n admin_urls static %} | ||||
| {% load staticfiles %} | ||||
|  | ||||
|  | ||||
| {% block extrahead %} | ||||
| 	{{ block.super }} | ||||
| 	{{ media }} | ||||
| 	<script type="text/javascript" src="{% static 'admin/js/cancel.js' %}"></script> | ||||
| {% endblock %} | ||||
|  | ||||
|  | ||||
| {% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation delete-selected-confirmation{% endblock %} | ||||
|  | ||||
|  | ||||
| {% block breadcrumbs %} | ||||
| 	<div class="breadcrumbs"> | ||||
| 		<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a> | ||||
| 		› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a> | ||||
| 		› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a> | ||||
| 		› {{ title }} | ||||
| 	</div> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
| 	<p>Please select the {{itemname}}.</p> | ||||
| 	<form method="post">{% csrf_token %} | ||||
| 		<div> | ||||
| 			{% for obj in queryset %} | ||||
| 			<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}"/> | ||||
| 			{% endfor %} | ||||
| 			<p> | ||||
| 				<select name="obj_id"> | ||||
| 					{% for obj in objects %} | ||||
| 					<option value="{{ obj.id }}">{{ obj.name }}</option> | ||||
| 					{% endfor %} | ||||
| 				</select> | ||||
| 			</p> | ||||
|  | ||||
| 			<input type="hidden" name="action" value="{{ action }}"/> | ||||
| 			<input type="hidden" name="post" value="yes" /> | ||||
| 			<p> | ||||
| 				<input type="submit" value="{% trans 'Confirm' %}" /> | ||||
| 				<a href="#" class="button cancel-link">{% trans "Go back" %}</a> | ||||
| 			</p> | ||||
| 		</div> | ||||
| 	</form> | ||||
| {% endblock %} | ||||
| @@ -1 +0,0 @@ | ||||
| <img src="{{download_url}}" style="max-width: 100%"> | ||||
| @@ -1,130 +0,0 @@ | ||||
| {% load static %} | ||||
|  | ||||
| <div> | ||||
|     <input id="prev" value="Previous" class="default" type="button"> | ||||
|     <input id="next" value="Next" class="default" type="button"> | ||||
|         | ||||
|     <span>Page: <span id="page_num"></span> / <span id="page_count"></span></span> | ||||
|         | ||||
|     <input id="zoomin" value="+" class="default" type="button"> | ||||
|     <input id="zoomout" value="-" class="default" type="button"> | ||||
| </div> | ||||
|  | ||||
| <div style="width: 100%; overflow: auto;"> | ||||
|     <canvas id="the-canvas"></canvas> | ||||
| </div> | ||||
| <script type="text/javascript" src="{% static 'documents/js/pdf.js' %}"></script> | ||||
| <script type="text/javascript" src="{% static 'documents/js/pdf.worker.js' %}"></script> | ||||
|  | ||||
| {# Load and display PDF document#} | ||||
| <script> | ||||
| var pdfjsLib = window['pdfjs-dist/build/pdf']; | ||||
|  | ||||
| var pdfDoc = null, | ||||
|     pageNum = 1, | ||||
|     pageRendering = false, | ||||
|     pageNumPending = null, | ||||
|     scale = 1.44, | ||||
|     canvas = document.getElementById('the-canvas'), | ||||
|     ctx = canvas.getContext('2d'); | ||||
|  | ||||
| /** | ||||
|  * Get page info from document, resize canvas accordingly, and render page. | ||||
|  * @param num Page number. | ||||
|  */ | ||||
| function renderPage(num) { | ||||
|     pageRendering = true; | ||||
|     // Using promise to fetch the page | ||||
|     pdfDoc.getPage(num).then(function(page) { | ||||
|         var viewport = page.getViewport(scale); | ||||
|         canvas.height = viewport.height; | ||||
|         canvas.width = viewport.width; | ||||
|         // Render PDF page into canvas context | ||||
|         var renderContext = { | ||||
|             canvasContext: ctx, | ||||
|             viewport: viewport | ||||
|         }; | ||||
|         var renderTask = page.render(renderContext); | ||||
|         // Wait for rendering to finish | ||||
|         renderTask.promise.then(function () { | ||||
|             pageRendering = false; | ||||
|             if (pageNumPending !== null) { | ||||
|                 // New page rendering is pending | ||||
|                 renderPage(pageNumPending); | ||||
|                 pageNumPending = null; | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
|     // Update page counters | ||||
|     document.getElementById('page_num').textContent = num; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * If another page rendering in progress, waits until the rendering is | ||||
|  * finised. Otherwise, executes rendering immediately. | ||||
|  */ | ||||
| function queueRenderPage(num) { | ||||
|     if (pageRendering) { | ||||
|         pageNumPending = num; | ||||
|     } else { | ||||
|         renderPage(num); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Displays previous page. | ||||
|  */ | ||||
| function onPrevPage() { | ||||
|     if (pageNum <= 1) { | ||||
|         return; | ||||
|     } | ||||
|     pageNum--; | ||||
|     queueRenderPage(pageNum); | ||||
| } | ||||
|  | ||||
| document.getElementById('prev').addEventListener('click', onPrevPage); | ||||
|  | ||||
| /** | ||||
|  * Displays next page. | ||||
|  */ | ||||
| function onNextPage() { | ||||
|     if (pageNum >= pdfDoc.numPages) { | ||||
|         return; | ||||
|     } | ||||
|     pageNum++; | ||||
|     queueRenderPage(pageNum); | ||||
| } | ||||
|  | ||||
| document.getElementById('next').addEventListener('click', onNextPage); | ||||
|  | ||||
| /** | ||||
|  * Displays next page. | ||||
|  */ | ||||
| function onZoomIn() { | ||||
|     scale *= 1.2; | ||||
|     queueRenderPage(pageNum); | ||||
| } | ||||
|  | ||||
| document.getElementById('zoomin').addEventListener('click', onZoomIn); | ||||
|  | ||||
| /** | ||||
|  * Displays next page. | ||||
|  */ | ||||
| function onZoomOut() { | ||||
|     scale /= 1.2; | ||||
|     queueRenderPage(pageNum); | ||||
| } | ||||
|  | ||||
| document.getElementById('zoomout').addEventListener('click', onZoomOut); | ||||
|  | ||||
| /** | ||||
|  * Asynchronously downloads PDF. | ||||
|  */ | ||||
| pdfjsLib.getDocument("{{download_url}}").then(function (pdfDoc_) { | ||||
|     pdfDoc = pdfDoc_; | ||||
|     document.getElementById('page_count').textContent = pdfDoc.numPages; | ||||
|     // Initial/first page rendering | ||||
|     renderPage(pageNum); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| @@ -1,57 +0,0 @@ | ||||
| {% extends "admin/index.html" %} | ||||
|  | ||||
|  | ||||
| {% load i18n static %} | ||||
|  | ||||
|  | ||||
| {# This block adds a search form on the admin start page and on the module start page so that #} | ||||
| {# the user can quickly search for documents #} | ||||
| {% block pretitle %} | ||||
| <div> | ||||
|     <h3>{% trans 'Search documents' %}</h3> | ||||
|  | ||||
|     <div id="toolbar"><form id="changelist-search" method="get" action="{% url 'admin:documents_document_changelist' %}"> | ||||
|             <div><!-- DIV needed for valid HTML --> | ||||
|                 <label for="searchbar"><img src="{% static "admin/img/search.svg" %}" alt="Search"></label> | ||||
|                 <input type="text" size="40" name="q" value="" id="searchbar" autofocus=""> | ||||
|                 <input type="submit" value="{% trans 'Search' %}"> | ||||
|             </div> | ||||
|         </form> | ||||
|     </div> | ||||
| </div> | ||||
| {% endblock %} | ||||
|  | ||||
|  | ||||
| {# This whole block is here just to override the `get_admin_log` line so #} | ||||
| {# that the log entries aren't limited to the current user #} | ||||
| {% block sidebar %} | ||||
| <div id="content-related"> | ||||
|     <div class="module" id="recent-actions-module"> | ||||
|         <h2>{% trans 'Recent actions' %}</h2> | ||||
|         <h3>{% trans 'My actions' %}</h3> | ||||
|             {% load log %} | ||||
|             {% get_admin_log 10 as admin_log %} | ||||
|             {% if not admin_log %} | ||||
|             <p>{% trans 'None available' %}</p> | ||||
|             {% else %} | ||||
|             <ul class="actionlist"> | ||||
|             {% for entry in admin_log %} | ||||
|             <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}"> | ||||
|                 {% if entry.is_deletion or not entry.get_admin_url %} | ||||
|                     {{ entry.object_repr }} | ||||
|                 {% else %} | ||||
|                     <a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a> | ||||
|                 {% endif %} | ||||
|                 <br/> | ||||
|                 {% if entry.content_type %} | ||||
|                     <span class="mini quiet">{% filter capfirst %}{{ entry.content_type }}{% endfilter %}</span> | ||||
|                 {% else %} | ||||
|                     <span class="mini quiet">{% trans 'Unknown content' %}</span> | ||||
|                 {% endif %} | ||||
|             </li> | ||||
|             {% endfor %} | ||||
|             </ul> | ||||
|             {% endif %} | ||||
|     </div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| @@ -1,37 +0,0 @@ | ||||
| import os | ||||
|  | ||||
| from django import template | ||||
| from django.conf import settings | ||||
| from django.utils.safestring import mark_safe | ||||
|  | ||||
| register = template.Library() | ||||
|  | ||||
|  | ||||
| @register.simple_tag() | ||||
| def custom_css(): | ||||
|     theme_path = os.path.join( | ||||
|         settings.MEDIA_ROOT, | ||||
|         "overrides.css" | ||||
|     ) | ||||
|     if os.path.exists(theme_path): | ||||
|         return mark_safe( | ||||
|             '<link rel="stylesheet" type="text/css" href="{}" />'.format( | ||||
|                 os.path.join(settings.MEDIA_URL, "overrides.css") | ||||
|             ) | ||||
|         ) | ||||
|     return "" | ||||
|  | ||||
|  | ||||
| @register.simple_tag() | ||||
| def custom_js(): | ||||
|     theme_path = os.path.join( | ||||
|         settings.MEDIA_ROOT, | ||||
|         "overrides.js" | ||||
|     ) | ||||
|     if os.path.exists(theme_path): | ||||
|         return mark_safe( | ||||
|             '<script src="{}"></script>'.format( | ||||
|                 os.path.join(settings.MEDIA_URL, "overrides.js") | ||||
|             ) | ||||
|         ) | ||||
|     return "" | ||||
| @@ -1,43 +0,0 @@ | ||||
| import re | ||||
|  | ||||
| from django.contrib.admin.templatetags.admin_list import ( | ||||
|     result_headers, | ||||
|     result_hidden_fields, | ||||
|     results | ||||
| ) | ||||
| from django.template import Library | ||||
|  | ||||
|  | ||||
| EXTRACT_URL = re.compile(r'href="(.*?)"') | ||||
|  | ||||
| register = Library() | ||||
|  | ||||
|  | ||||
| @register.inclusion_tag("admin/documents/document/change_list_results.html") | ||||
| def result_list(cl): | ||||
|     """ | ||||
|     Copy/pasted from django.contrib.admin.templatetags.admin_list just so I can | ||||
|     modify the value passed to `.inclusion_tag()` in the decorator here.  There | ||||
|     must be a cleaner way... right? | ||||
|     """ | ||||
|     headers = list(result_headers(cl)) | ||||
|     num_sorted_fields = 0 | ||||
|     for h in headers: | ||||
|         if h['sortable'] and h['sorted']: | ||||
|             num_sorted_fields += 1 | ||||
|     return {'cl': cl, | ||||
|             'result_hidden_fields': list(result_hidden_fields(cl)), | ||||
|             'result_headers': headers, | ||||
|             'num_sorted_fields': num_sorted_fields, | ||||
|             'results': map(add_doc_edit_url, results(cl))} | ||||
|  | ||||
|  | ||||
| def add_doc_edit_url(result): | ||||
|     """ | ||||
|     Make the document edit URL accessible to the view as a separate item | ||||
|     """ | ||||
|     title = result[1] | ||||
|     match = re.search(EXTRACT_URL, title) | ||||
|     edit_doc_url = match.group(1) | ||||
|     result.append(edit_doc_url) | ||||
|     return result | ||||
		Reference in New Issue
	
	Block a user
	 Jonas Winkler
					Jonas Winkler