diff --git a/HISTORY.rst b/HISTORY.rst index fac2320fb6..2c240ce5e5 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -8,6 +8,7 @@ Add COMMON_PRODUCTION_ERROR_LOG_PATH to control path of log file. Defaults to mayan/error.log. - Add support logging request exceptions. +- Add document list item view. 2.5.2 (2017-07-08) ================== diff --git a/mayan/apps/appearance/static/appearance/css/base.css b/mayan/apps/appearance/static/appearance/css/base.css index eb94b6c3f8..2e6aa4e596 100644 --- a/mayan/apps/appearance/static/appearance/css/base.css +++ b/mayan/apps/appearance/static/appearance/css/base.css @@ -235,12 +235,22 @@ a i { } } -/* Metadata */ -.metadata-display { - display: inline-block; - min-width: 200px; - padding-right: 10px; - width: 49%; +/* List item view */ + +.panel-item { + box-shadow: 2px 2px 18px rgba(0, 0, 0, .2); +} + +.panel-item > .panel-heading { + padding: 1px 10px; +} + +.panel-item > .panel-body { + padding: 10px; +} + +.list-extra-column-label { + font-weight: bold; } /* Content */ @@ -249,3 +259,15 @@ a i { width: 95%; } } + +/* Document widget */ +.spinner-container { + margin: auto; + width: 100%; + border: 1px solid lightgray; +} + +.spinner-container > .spinner-icon { + margin-left: 4px; + margin-top: 3px; +} diff --git a/mayan/apps/appearance/static/appearance/js/base.js b/mayan/apps/appearance/static/appearance/js/base.js index 83ac822c96..1adda6e22b 100644 --- a/mayan/apps/appearance/static/appearance/js/base.js +++ b/mayan/apps/appearance/static/appearance/js/base.js @@ -197,6 +197,8 @@ MayanImage.prototype.load = function () { }); this.element.attr('src', this.element.attr('data-url')); + $.fn.matchHeight._update(); + $.fn.matchHeight._maintainScroll = true; }; jQuery(document).ready(function() { diff --git a/mayan/apps/appearance/templates/appearance/base.html b/mayan/apps/appearance/templates/appearance/base.html index 06b1b9e218..58f3a5fa53 100644 --- a/mayan/apps/appearance/templates/appearance/base.html +++ b/mayan/apps/appearance/templates/appearance/base.html @@ -168,6 +168,7 @@ + {% endcompress %} diff --git a/mayan/apps/appearance/templates/appearance/generic_list.html b/mayan/apps/appearance/templates/appearance/generic_list.html index 285f62c18c..3ad3138c75 100644 --- a/mayan/apps/appearance/templates/appearance/generic_list.html +++ b/mayan/apps/appearance/templates/appearance/generic_list.html @@ -12,6 +12,10 @@
{% endif %} - {% include 'appearance/generic_list_subtemplate.html' %} -{% endblock %} + {% if list_as_items %} + {% include 'appearance/generic_list_items_subtemplate.html' %} + {% else %} + {% include 'appearance/generic_list_subtemplate.html' %} + {% endif %} +{% endblock content %} diff --git a/mayan/apps/appearance/templates/appearance/generic_list_items_subtemplate.html b/mayan/apps/appearance/templates/appearance/generic_list_items_subtemplate.html new file mode 100644 index 0000000000..41a5f0fee1 --- /dev/null +++ b/mayan/apps/appearance/templates/appearance/generic_list_items_subtemplate.html @@ -0,0 +1,212 @@ +{% load i18n %} +{% load static %} + +{% load common_tags %} +{% load navigation_tags %} + + + +
+
+

+ {% if page_obj %} + {% if page_obj.paginator.num_pages != 1 %} + {% blocktrans with page_obj.start_index as start and page_obj.end_index as end and page_obj.paginator.object_list|length as total and page_obj.number as page_number and page_obj.paginator.num_pages as total_pages %}Total ({{ start }} - {{ end }} out of {{ total }}) (Page {{ page_number }} of {{ total_pages }}){% endblocktrans %} + {% else %} + {% blocktrans with page_obj.paginator.object_list|length as total %}Total: {{ total }}{% endblocktrans %} + {% endif %} + {% else %} + {% blocktrans with object_list|length as total %}Total: {{ total }}{% endblocktrans %} + {% endif %} +

+
+ +
+ +
+ {% if object_list %} + {% if not hide_multi_item_actions %} + {% get_multi_item_links_form object_list %} + {% endif %} + {% if multi_item_actions %} +
+ {{ multi_item_form }} +   +
+ {% endif %} + {% endif %} + +
+ {% if scrollable_content %} +
+ {% endif %} + + + +
+ {% for object in object_list %} +
+
+
+ + +
+
+ +
+
+ + + + +
+
+ + {% if not hide_columns %} + {% for column in object|get_source_columns %} +
{% source_column_resolve column=column %}{{ column_result }}
+ {% endfor %} + {% endif %} + + {% for column in extra_columns %} +
{{ column.name }}: {{ object|object_property:column.attribute }}
+ {% endfor %} + + {% if not hide_links %} +

+ {% get_menu_links 'object menu' source=object as resolved_links %} + {% for object_navigation_links in resolved_links %} + {% with 'true' as horizontal %} + {% include 'navigation/generic_navigation.html' %} + {% endwith %} + {% endfor %} +

+ {% endif %} + + +
+
+
+ {% empty %} +

{% trans 'No results' %}

+ + {% endfor %} +
+ +{% comment %} +
+ + + {% if not hide_header %} + + {% if multi_item_actions %} + + {% endif %} + + {% if not hide_object %} + + {% endif %} + + {% if not hide_columns %} + {% for column in object_list|get_source_columns %} + + {% endfor %} + {% endif %} + + {% for column in extra_columns %} + + {% endfor %} + + {% if not hide_links %} + + {% endif %} + + {% endif %} + {% for object in object_list %} + + + {% if multi_item_actions %} + + {% endif %} + {% if not hide_object %} + {% if main_object %} + {% with object|object_property:main_object as object %} + + {% endwith %} + {% else %} + + {% endif %} + {% endif %} + {% if not hide_columns %} + {% for column in object|get_source_columns %} + + {% endfor %} + {% endif %} + {% for column in extra_columns %} + + {% endfor %} + {% if not hide_links %} + + {% endif %} + + {% empty %} + + {% endfor %} + +
{% trans 'Identifier' %}{{ column.label }}{{ column.name }} 
+ {% if multi_select_item_properties %} + + {% else %} + + {% endif %} + {% if not hide_link %}{{ object }}{% else %}{{ object }}{% endif %}{% if not hide_link %}{{ object }}{% else %}{{ object }}{% endif %}{% source_column_resolve column=column %}{{ column_result }}{{ object|object_property:column.attribute }} + {% get_menu_links 'object menu' source=object as resolved_links %} + {% for object_navigation_links in resolved_links %} + {% with 'true' as horizontal %} + {% include 'navigation/generic_navigation.html' %} + {% endwith %} + {% endfor %} +
{% trans 'No results' %}
+
+{% endcomment %} + {% if scrollable_content %} +
+ {% endif %} +
+ {% include 'pagination/pagination.html' %} +
+
+
diff --git a/mayan/apps/cabinets/templates/cabinets/cabinet_details.html b/mayan/apps/cabinets/templates/cabinets/cabinet_details.html index 65098d5b34..3fc1a242f2 100644 --- a/mayan/apps/cabinets/templates/cabinets/cabinet_details.html +++ b/mayan/apps/cabinets/templates/cabinets/cabinet_details.html @@ -17,14 +17,18 @@
{% endif %}
-
+

{% trans 'Navigation:' %}

-
+
{% with document_list as object_list %} - {% include 'appearance/generic_list_subtemplate.html' %} + {% if list_as_items %} + {% include 'appearance/generic_list_items_subtemplate.html' %} + {% else %} + {% include 'appearance/generic_list_subtemplate.html' %} + {% endif %} {% endwith %}
diff --git a/mayan/apps/cabinets/views.py b/mayan/apps/cabinets/views.py index 012b28c3a4..d51b3d95ca 100644 --- a/mayan/apps/cabinets/views.py +++ b/mayan/apps/cabinets/views.py @@ -107,6 +107,7 @@ class CabinetDetailView(TemplateView): ), 'document_list': self.get_document_queryset(), 'hide_links': True, + 'list_as_items': True, 'object': cabinet, 'title': _('Details of cabinet: %s') % cabinet.get_full_path(), } diff --git a/mayan/apps/checkouts/views.py b/mayan/apps/checkouts/views.py index 71a4ed1e8b..1e512650c2 100644 --- a/mayan/apps/checkouts/views.py +++ b/mayan/apps/checkouts/views.py @@ -71,34 +71,38 @@ class CheckoutDocumentView(SingleObjectCreateView): class CheckoutListView(DocumentListView): - extra_context = { - 'title': _('Documents checked out'), - 'hide_links': True, - 'extra_columns': ( - { - 'name': _('User'), - 'attribute': encapsulate( - lambda document: document.checkout_info().user.get_full_name() or document.checkout_info().user - ) - }, - { - 'name': _('Checkout time and date'), - 'attribute': encapsulate( - lambda document: document.checkout_info().checkout_datetime - ) - }, - { - 'name': _('Checkout expiration'), - 'attribute': encapsulate( - lambda document: document.checkout_info().expiration_datetime - ) - }, - ), - } - def get_document_queryset(self): return DocumentCheckout.objects.checked_out_documents() + def get_extra_context(self): + context = super(CheckoutListView, self).get_extra_context() + context.update( + { + 'title': _('Documents checked out'), + 'extra_columns': ( + { + 'name': _('User'), + 'attribute': encapsulate( + lambda document: document.checkout_info().user.get_full_name() or document.checkout_info().user + ) + }, + { + 'name': _('Checkout time and date'), + 'attribute': encapsulate( + lambda document: document.checkout_info().checkout_datetime + ) + }, + { + 'name': _('Checkout expiration'), + 'attribute': encapsulate( + lambda document: document.checkout_info().expiration_datetime + ) + }, + ), + } + ) + return context + class CheckoutDetailView(SingleObjectDetailView): form_class = DocumentCheckoutDefailForm diff --git a/mayan/apps/document_indexing/templates/document_indexing/node_details.html b/mayan/apps/document_indexing/templates/document_indexing/node_details.html index b20d8fc17f..aff1e25cff 100644 --- a/mayan/apps/document_indexing/templates/document_indexing/node_details.html +++ b/mayan/apps/document_indexing/templates/document_indexing/node_details.html @@ -13,12 +13,16 @@ {% endif %}
-
+
{{ navigation }}
-
- {% include 'appearance/generic_list_subtemplate.html' %} +
+ {% if list_as_items %} + {% include 'appearance/generic_list_items_subtemplate.html' %} + {% else %} + {% include 'appearance/generic_list_subtemplate.html' %} + {% endif %}
diff --git a/mayan/apps/document_indexing/views.py b/mayan/apps/document_indexing/views.py index 87dbcd84b5..3a5ca04e7f 100644 --- a/mayan/apps/document_indexing/views.py +++ b/mayan/apps/document_indexing/views.py @@ -261,21 +261,28 @@ class IndexInstanceNodeView(DocumentListView): return self.index_instance_node.documents.all() def get_extra_context(self): - context = { - 'hide_links': True, - 'object': self.index_instance_node, - 'navigation': mark_safe( - _('Navigation: %s') % node_tree( - node=self.index_instance_node, user=self.request.user - ) - ), - 'title': _( - 'Contents for index: %s' - ) % self.index_instance_node.get_full_path(), - } + context = super(IndexInstanceNodeView, self).get_extra_context() + context.update( + { + 'object': self.index_instance_node, + 'navigation': mark_safe( + _('Navigation: %s') % node_tree( + node=self.index_instance_node, user=self.request.user + ) + ), + 'title': _( + 'Contents for index: %s' + ) % self.index_instance_node.get_full_path(), + } + ) if self.index_instance_node and not self.index_instance_node.index_template_node.link_documents: - context.update({'hide_object': True}) + context.update( + { + 'hide_object': True, + 'list_as_items': False, + } + ) return context diff --git a/mayan/apps/document_states/views.py b/mayan/apps/document_states/views.py index fd0ed0898e..4cbc79af5e 100644 --- a/mayan/apps/document_states/views.py +++ b/mayan/apps/document_states/views.py @@ -433,11 +433,14 @@ class WorkflowDocumentListView(DocumentListView): return Document.objects.filter(workflows__workflow=self.workflow) def get_extra_context(self): - return { - 'hide_links': True, - 'object': self.workflow, - 'title': _('Documents with the workflow: %s') % self.workflow - } + context = super(WorkflowDocumentListView, self).get_extra_context() + context.update( + { + 'object': self.workflow, + 'title': _('Documents with the workflow: %s') % self.workflow + } + ) + return context class WorkflowStateDocumentListView(DocumentListView): @@ -446,19 +449,22 @@ class WorkflowStateDocumentListView(DocumentListView): def get_extra_context(self): workflow_state = self.get_workflow_state() - return { - 'hide_links': True, - 'object': workflow_state, - 'navigation_object_list': ('object', 'workflow'), - 'workflow': WorkflowRuntimeProxy.objects.get( - pk=workflow_state.workflow.pk - ), - 'title': _( - 'Documents in the workflow "%s", state "%s"' - ) % ( - workflow_state.workflow, workflow_state - ) - } + context = super(WorkflowStateDocumentListView, self).get_extra_context() + context.update( + { + 'object': workflow_state, + 'navigation_object_list': ('object', 'workflow'), + 'workflow': WorkflowRuntimeProxy.objects.get( + pk=workflow_state.workflow.pk + ), + 'title': _( + 'Documents in the workflow "%s", state "%s"' + ) % ( + workflow_state.workflow, workflow_state + ) + } + ) + return context def get_workflow_state(self): workflow_state = get_object_or_404( diff --git a/mayan/apps/documents/settings.py b/mayan/apps/documents/settings.py index b298254dbf..88ad8d8cd7 100644 --- a/mayan/apps/documents/settings.py +++ b/mayan/apps/documents/settings.py @@ -21,7 +21,7 @@ setting_print_size = namespace.add_setting( global_name='DOCUMENTS_PRINT_SIZE', default='3600' ) setting_thumbnail_size = namespace.add_setting( - global_name='DOCUMENTS_THUMBNAIL_SIZE', default='50x50' + global_name='DOCUMENTS_THUMBNAIL_SIZE', default='300' ) setting_recent_count = namespace.add_setting( global_name='DOCUMENTS_RECENT_COUNT', default=40, diff --git a/mayan/apps/documents/views/document_type_views.py b/mayan/apps/documents/views/document_type_views.py index c9658ec06f..de853710df 100644 --- a/mayan/apps/documents/views/document_type_views.py +++ b/mayan/apps/documents/views/document_type_views.py @@ -32,11 +32,14 @@ class DocumentTypeDocumentListView(DocumentListView): return self.get_document_type().documents.all() def get_extra_context(self): - return { - 'hide_links': True, - 'object': self.get_document_type(), - 'title': _('Documents of type: %s') % self.get_document_type() - } + context = super(DocumentTypeDocumentListView, self).get_extra_context() + context.update( + { + 'object': self.get_document_type(), + 'title': _('Documents of type: %s') % self.get_document_type() + } + ) + return context class DocumentTypeListView(SingleObjectListView): diff --git a/mayan/apps/documents/views/document_views.py b/mayan/apps/documents/views/document_views.py index b7cd65315d..4734944d75 100644 --- a/mayan/apps/documents/views/document_views.py +++ b/mayan/apps/documents/views/document_views.py @@ -50,16 +50,18 @@ logger = logging.getLogger(__name__) class DocumentListView(SingleObjectListView): - extra_context = { - 'hide_links': True, - 'title': _('All documents'), - } - object_permission = permission_document_view def get_document_queryset(self): return Document.objects.defer('description', 'uuid', 'date_added', 'language', 'in_trash', 'deleted_date_time').all() + def get_extra_context(self): + return { + 'hide_links': True, + 'list_as_items': True, + 'title': _('All documents'), + } + def get_queryset(self): self.queryset = self.get_document_queryset().filter(is_stub=False) return super(DocumentListView, self).get_queryset() @@ -68,17 +70,21 @@ class DocumentListView(SingleObjectListView): class DeletedDocumentListView(DocumentListView): object_permission = None - extra_context = { - 'hide_link': True, - 'title': _('Documents in trash'), - } - def get_document_queryset(self): return AccessControlList.objects.filter_by_access( permission_document_view, self.request.user, queryset=DeletedDocument.trash.all() ) + def get_extra_context(self): + context = super(DeletedDocumentListView, self).get_extra_context() + context.update( + { + 'title': _('Documents in trash'), + } + ) + return context + class DeletedDocumentDeleteView(ConfirmView): extra_context = { @@ -186,6 +192,16 @@ class DocumentDuplicatesListView(DocumentListView): def get_document(self): return get_object_or_404(Document, pk=self.kwargs['pk']) + def get_extra_context(self): + context = super(DocumentDuplicatesListView, self).get_extra_context() + context.update( + { + 'object': self.get_document(), + 'title': _('Duplicates for document: %s') % self.get_document(), + } + ) + return context + def get_queryset(self): try: return DuplicatedDocument.objects.get( @@ -194,13 +210,6 @@ class DocumentDuplicatesListView(DocumentListView): except DuplicatedDocument.DoesNotExist: return Document.objects.none() - def get_extra_context(self): - return { - 'hide_links': True, - 'object': self.get_document(), - 'title': _('Duplicates for document: %s') % self.get_document(), - } - class DocumentEditView(SingleObjectEditView): form_class = DocumentForm @@ -374,14 +383,18 @@ class EmptyTrashCanView(ConfirmView): class RecentDocumentListView(DocumentListView): - extra_context = { - 'hide_links': True, - 'title': _('Recent documents'), - } - def get_document_queryset(self): return RecentDocument.objects.get_for_user(self.request.user) + def get_extra_context(self): + context = super(RecentDocumentListView, self).get_extra_context() + context.update( + { + 'title': _('Recent documents'), + } + ) + return context + class DocumentDownloadFormView(FormView): form_class = DocumentDownloadForm @@ -762,24 +775,28 @@ class DocumentPrint(FormView): class DuplicatedDocumentListView(DocumentListView): - extra_context = { - 'extra_columns': ( - { - 'name': _('Duplicates'), - 'attribute': encapsulate( - lambda document: DuplicatedDocument.objects.get( - document=document - ).documents.count() - ) - }, - ), - 'hide_links': True, - 'title': _('Duplicated documents') - } - def get_document_queryset(self): return Document.objects.filter( pk__in=DuplicatedDocument.objects.values_list( 'document_id', flat=True ) ) + + def get_extra_context(self): + context = super(DuplicatedDocumentListView, self).get_extra_context() + context.update( + { + 'extra_columns': ( + { + 'name': _('Duplicates'), + 'attribute': encapsulate( + lambda document: DuplicatedDocument.objects.get( + document=document + ).documents.count() + ) + }, + ), + 'title': _('Duplicated documents') + } + ) + return context diff --git a/mayan/apps/documents/widgets.py b/mayan/apps/documents/widgets.py index f4382dd695..d23de77c09 100644 --- a/mayan/apps/documents/widgets.py +++ b/mayan/apps/documents/widgets.py @@ -225,13 +225,13 @@ class InstanceImageWidget(object): ) result.append( - '
' - '' + '
' + '' '' '' '' '
' - ' '.format( width=self.width or '32', height=self.height or '32', diff --git a/mayan/apps/linking/views.py b/mayan/apps/linking/views.py index 2f82f757b9..c2201be3c4 100644 --- a/mayan/apps/linking/views.py +++ b/mayan/apps/linking/views.py @@ -75,11 +75,14 @@ class ResolvedSmartLinkView(DocumentListView): 'smart_link': self.smart_link.label, } - return { - 'hide_links': True, - 'object': self.document, - 'title': title, - } + context = super(ResolvedSmartLinkView, self).get_extra_context() + context.update( + { + 'object': self.document, + 'title': title, + } + ) + return context class SetupSmartLinkDocumentTypesView(AssignRemoveView): diff --git a/mayan/apps/tags/views.py b/mayan/apps/tags/views.py index 133a6caf68..a31e80437a 100644 --- a/mayan/apps/tags/views.py +++ b/mayan/apps/tags/views.py @@ -197,11 +197,14 @@ class TagTaggedItemListView(DocumentListView): return self.get_tag().documents.all() def get_extra_context(self): - return { - 'title': _('Documents with the tag: %s') % self.get_tag(), - 'hide_links': True, - 'object': self.get_tag(), - } + context = super(TagTaggedItemListView, self).get_extra_context() + context.update( + { + 'object': self.get_tag(), + 'title': _('Documents with the tag: %s') % self.get_tag(), + } + ) + return context class DocumentTagListView(TagListView):