Add new list templates toolbar
Add the new generic list and generic list items toolbar which allow switching the list display mode. This toolbar also includes a stylized button to select and deselect all items emulating the check-all checkbox. Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
@@ -301,9 +301,23 @@ class MayanApp {
|
|||||||
app.lastChecked = null;
|
app.lastChecked = null;
|
||||||
|
|
||||||
$('body').on('click', '.check-all', function (event) {
|
$('body').on('click', '.check-all', function (event) {
|
||||||
|
var $this = $(this);
|
||||||
var checked = $(event.target).prop('checked');
|
var checked = $(event.target).prop('checked');
|
||||||
var $checkBoxes = $('.check-all-slave');
|
var $checkBoxes = $('.check-all-slave');
|
||||||
|
|
||||||
|
if (checked === undefined) {
|
||||||
|
checked = $this.data('checked');
|
||||||
|
checked = !checked;
|
||||||
|
$this.data('checked', checked);
|
||||||
|
console.log($this.data('icon-checked'));
|
||||||
|
|
||||||
|
if (checked) {
|
||||||
|
$this.find('[data-fa-i2svg]').addClass($this.data('icon-checked')).removeClass($this.data('icon-unchecked'));
|
||||||
|
} else {
|
||||||
|
$this.find('[data-fa-i2svg]').addClass($this.data('icon-unchecked')).removeClass($this.data('icon-checked'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$checkBoxes.prop('checked', checked);
|
$checkBoxes.prop('checked', checked);
|
||||||
$checkBoxes.trigger('change');
|
$checkBoxes.trigger('change');
|
||||||
});
|
});
|
||||||
@@ -353,6 +367,7 @@ class MayanApp {
|
|||||||
setupPanelSelection () {
|
setupPanelSelection () {
|
||||||
var app = this;
|
var app = this;
|
||||||
|
|
||||||
|
// Setup panel highlighting on check
|
||||||
$('body').on('change', '.check-all-slave', function (event) {
|
$('body').on('change', '.check-all-slave', function (event) {
|
||||||
var checked = $(event.target).prop('checked');
|
var checked = $(event.target).prop('checked');
|
||||||
if (checked) {
|
if (checked) {
|
||||||
@@ -366,9 +381,10 @@ class MayanApp {
|
|||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
var targetSrc = $(event.target).prop('src');
|
var targetSrc = $(event.target).prop('src');
|
||||||
var targetHref = $(event.target).prop('href');
|
var targetHref = $(event.target).prop('href');
|
||||||
|
var targetIsButton = event.target.tagName === 'BUTTON';
|
||||||
var lastChecked = null;
|
var lastChecked = null;
|
||||||
|
|
||||||
if ((targetSrc === undefined) && (targetHref === undefined)) {
|
if ((targetSrc === undefined) && (targetHref === undefined) && (targetIsButton === false)) {
|
||||||
var $checkbox = $this.find('.check-all-slave');
|
var $checkbox = $this.find('.check-all-slave');
|
||||||
var checked = $checkbox.prop('checked');
|
var checked = $checkbox.prop('checked');
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
{% include 'appearance/no_results.html' %}
|
{% include 'appearance/no_results.html' %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
{% if page_obj %}
|
{% if page_obj %}
|
||||||
{% if page_obj.paginator.num_pages != 1 %}
|
{% if page_obj.paginator.num_pages != 1 %}
|
||||||
@@ -24,17 +23,23 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</h4>
|
</h4>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="well center-block">
|
<div class="well center-block">
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="pull-right">
|
|
||||||
<form action="{% url 'common:multi_object_action_view' %}" class="form-multi-object-action" method="get">
|
|
||||||
{% if object_list %}
|
{% if object_list %}
|
||||||
{% if not hide_multi_item_actions %}
|
{% if not hide_multi_item_actions %}
|
||||||
{% get_multi_item_links_form object_list %}
|
{% get_multi_item_links_form object_list %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include 'appearance/list_toolbar.html' %}
|
||||||
|
|
||||||
|
<div class="pull-right">
|
||||||
|
<form action="{% url 'common:multi_object_action_view' %}" class="form-multi-object-action" method="get">
|
||||||
|
{% if object_list %}
|
||||||
{% if multi_item_actions %}
|
{% if multi_item_actions %}
|
||||||
<fieldset style="margin-top: -10px;">
|
<fieldset style="margin-top: -10px;">
|
||||||
<input class="check-all" type="checkbox"/>
|
|
||||||
{{ multi_item_form }}
|
{{ multi_item_form }}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -65,15 +70,14 @@
|
|||||||
|
|
||||||
<span style="color: white; word-break: break-all; overflow-wrap: break-word;">
|
<span style="color: white; word-break: break-all; overflow-wrap: break-word;">
|
||||||
{% if not hide_object %}
|
{% if not hide_object %}
|
||||||
{% if main_object %}
|
{% if not hide_link %}
|
||||||
{% with object|object_property:main_object as object %}
|
<a href="{{ object.get_absolute_url }}">{{ object }}</a>
|
||||||
{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}
|
{{ object }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% source_column_resolve column=object|get_source_columns:"only_identifier" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,10 +85,9 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
|
||||||
{% if not hide_columns %}
|
{% if not hide_columns %}
|
||||||
{% for column in object|get_source_columns %}
|
{% for column in object|get_source_columns:"exclude_identifier" %}
|
||||||
<div class="text-center" style="">{% source_column_resolve column=column %}{{ column_result }}</div>
|
<div class="text-center" style="">{% source_column_resolve column=column as column_value %}{% if column_value != '' %}{{ column.label }}: {{ column_value }}{% endif %}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,18 @@
|
|||||||
|
|
||||||
<div class="well center-block">
|
<div class="well center-block">
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="pull-right">
|
|
||||||
<form action="{% url 'common:multi_object_action_view' %}" class="form-multi-object-action" method="get">
|
|
||||||
{% if object_list %}
|
{% if object_list %}
|
||||||
{% if not hide_multi_item_actions %}
|
{% if not hide_multi_item_actions %}
|
||||||
{% get_multi_item_links_form object_list %}
|
{% get_multi_item_links_form object_list %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include 'appearance/list_toolbar.html' %}
|
||||||
|
|
||||||
|
<div class="pull-right">
|
||||||
|
<form action="{% url 'common:multi_object_action_view' %}" class="form-multi-object-action" method="get">
|
||||||
|
{% if object_list %}
|
||||||
{% if multi_item_actions %}
|
{% if multi_item_actions %}
|
||||||
<fieldset style="margin-top: -10px; margin-bottom: 10px;">
|
<fieldset style="margin-top: -10px; margin-bottom: 10px;">
|
||||||
{{ multi_item_form }}
|
{{ multi_item_form }}
|
||||||
@@ -42,13 +48,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if object_list %}
|
||||||
|
<hr style="border-bottom: 1px solid lightgrey;">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-condensed table-striped">
|
<table class="table table-condensed table-striped">
|
||||||
<tbody>
|
<thead>
|
||||||
{% if not hide_header %}
|
{% if not hide_header %}
|
||||||
<tr>
|
<tr>
|
||||||
{% if multi_item_actions %}
|
{% if multi_item_actions %}
|
||||||
<th class="first"><input class="checkbox check-all" type="checkbox" /></th>
|
<th class="first"></th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not hide_object %}
|
{% if not hide_object %}
|
||||||
@@ -70,6 +80,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% for object in object_list %}
|
{% for object in object_list %}
|
||||||
<tr>
|
<tr>
|
||||||
{% if multi_item_actions %}
|
{% if multi_item_actions %}
|
||||||
@@ -82,13 +94,7 @@
|
|||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not hide_object %}
|
{% if not hide_object %}
|
||||||
{% if main_object %}
|
|
||||||
{% with object|object_property:main_object as object %}
|
|
||||||
<td>{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}</td>
|
<td>{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}</td>
|
||||||
{% endwith %}
|
|
||||||
{% else %}
|
|
||||||
<td>{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}</td>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not hide_columns %}
|
{% if not hide_columns %}
|
||||||
{% for column in object|get_source_columns %}
|
{% for column in object|get_source_columns %}
|
||||||
|
|||||||
16
mayan/apps/appearance/templates/appearance/list_toolbar.html
Normal file
16
mayan/apps/appearance/templates/appearance/list_toolbar.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="pull-left">
|
||||||
|
<div class="btn-toolbar" role="toolbar">
|
||||||
|
<div class="btn-group">
|
||||||
|
{% if multi_item_actions %}
|
||||||
|
<a class="btn btn-default btn-sm check-all" data-checked=false data-icon-checked="fa fa-check-square" data-icon-unchecked="far fa-square" title="{% trans 'Select/Deselect all' %}">
|
||||||
|
<i class="far fa-square"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<a class="btn btn-default btn-sm" href="?_list_mode={% if list_as_items %}list{% else %}items{% endif %}" title="{% trans 'Toggle list display mode' %}">
|
||||||
|
<i class="fa {% if list_as_items %}fa-list{% else %}fa-th-large{% endif %}"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
<script src="{% static 'appearance/node_modules/select2/dist/js/select2.min.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/select2/dist/js/select2.min.js' %}" type="text/javascript"></script>
|
||||||
<script src="{% static 'appearance/node_modules/toastr/build/toastr.min.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/toastr/build/toastr.min.js' %}" type="text/javascript"></script>
|
||||||
<script src="{% static 'appearance/node_modules/jquery-match-height/dist/jquery.matchHeight-min.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/jquery-match-height/dist/jquery.matchHeight-min.js' %}" type="text/javascript"></script>
|
||||||
<script src="{% static 'appearance/node_modules/@fortawesome/fontawesome-free/js/all.min.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/@fortawesome/fontawesome-free/js/all.min.js' %}" data-auto-replace-svg="nest" type="text/javascript"></script>
|
||||||
<script src="{% static 'appearance/node_modules/urijs/src/IPv6.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/urijs/src/IPv6.js' %}" type="text/javascript"></script>
|
||||||
<script src="{% static 'appearance/node_modules/urijs/src/punycode.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/urijs/src/punycode.js' %}" type="text/javascript"></script>
|
||||||
<script src="{% static 'appearance/node_modules/urijs/src/SecondLevelDomains.js' %}" type="text/javascript"></script>
|
<script src="{% static 'appearance/node_modules/urijs/src/SecondLevelDomains.js' %}" type="text/javascript"></script>
|
||||||
|
|||||||
@@ -498,6 +498,18 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(SingleObjectListView, self).get_context_data(**kwargs)
|
||||||
|
if context.get('list_as_items'):
|
||||||
|
default_mode = 'items'
|
||||||
|
else:
|
||||||
|
default_mode = 'list'
|
||||||
|
|
||||||
|
list_mode = self.request.GET.get('_list_mode', default_mode)
|
||||||
|
|
||||||
|
context.update({'list_as_items': list_mode=='items'})
|
||||||
|
return context
|
||||||
|
|
||||||
def get_paginate_by(self, queryset):
|
def get_paginate_by(self, queryset):
|
||||||
return setting_paginate_by.value
|
return setting_paginate_by.value
|
||||||
|
|
||||||
|
|||||||
@@ -495,34 +495,46 @@ class SourceColumn(object):
|
|||||||
return sorted(columns, key=lambda x: x.order)
|
return sorted(columns, key=lambda x: x.order)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_for_source(cls, source):
|
def get_for_source(cls, source, exclude_identifier=False, only_identifier=False):
|
||||||
try:
|
try:
|
||||||
return SourceColumn.sort(columns=cls._registry[source])
|
result = SourceColumn.sort(columns=cls._registry[source])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
try:
|
||||||
# Try it as a queryset
|
# Try it as a queryset
|
||||||
return SourceColumn.sort(columns=cls._registry[source.model])
|
result = SourceColumn.sort(columns=cls._registry[source.model])
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
try:
|
try:
|
||||||
# It seems to be an instance, try its class
|
# It seems to be an instance, try its class
|
||||||
return SourceColumn.sort(columns=cls._registry[source.__class__])
|
result = SourceColumn.sort(columns=cls._registry[source.__class__])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
try:
|
||||||
# Special case for queryset items produced from
|
# Special case for queryset items produced from
|
||||||
# .defer() or .only() optimizations
|
# .defer() or .only() optimizations
|
||||||
return SourceColumn.sort(columns=cls._registry[list(source._meta.parents.items())[0][0]])
|
result = SourceColumn.sort(columns=cls._registry[list(source._meta.parents.items())[0][0]])
|
||||||
except (AttributeError, KeyError, IndexError):
|
except (AttributeError, KeyError, IndexError):
|
||||||
return ()
|
result = ()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# unhashable type: list
|
# unhashable type: list
|
||||||
return ()
|
result = ()
|
||||||
|
|
||||||
def __init__(self, source, label=None, attribute=None, func=None, order=None):
|
if exclude_identifier:
|
||||||
|
return [item for item in result if not item.is_identifier]
|
||||||
|
else:
|
||||||
|
if only_identifier:
|
||||||
|
for item in result:
|
||||||
|
if item.is_identifier:
|
||||||
|
return item
|
||||||
|
else:
|
||||||
|
return result
|
||||||
|
|
||||||
|
def __init__(self, source, label=None, attribute=None, func=None, kwargs=None, order=None, is_identifier=False):
|
||||||
self.source = source
|
self.source = source
|
||||||
self._label = label
|
self._label = label
|
||||||
self.attribute = attribute
|
self.attribute = attribute
|
||||||
self.func = func
|
self.func = func
|
||||||
|
self.kwargs = kwargs or {}
|
||||||
self.order = order or 0
|
self.order = order or 0
|
||||||
|
self.is_identifier = is_identifier
|
||||||
self.__class__._registry.setdefault(source, [])
|
self.__class__._registry.setdefault(source, [])
|
||||||
self.__class__._registry[source].append(self)
|
self.__class__._registry[source].append(self)
|
||||||
|
|
||||||
@@ -543,9 +555,12 @@ class SourceColumn(object):
|
|||||||
|
|
||||||
def resolve(self, context):
|
def resolve(self, context):
|
||||||
if self.attribute:
|
if self.attribute:
|
||||||
result = resolve_attribute(context['object'], self.attribute)
|
result = resolve_attribute(
|
||||||
|
obj=context['object'], attribute=self.attribute,
|
||||||
|
kwargs=self.kwargs
|
||||||
|
)
|
||||||
elif self.func:
|
elif self.func:
|
||||||
result = self.func(context=context)
|
result = self.func(context=context, **self.kwargs)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
4
mayan/apps/navigation/literals.py
Normal file
4
mayan/apps/navigation/literals.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
TEXT_ONLY_IDENTIFIER = 'only_identifier'
|
||||||
|
TEXT_EXCLUDE_IDENTIFIER = 'exclude_identifier'
|
||||||
@@ -4,6 +4,7 @@ from django.template import Library
|
|||||||
|
|
||||||
from ..classes import Link, Menu, SourceColumn
|
from ..classes import Link, Menu, SourceColumn
|
||||||
from ..forms import MultiItemForm
|
from ..forms import MultiItemForm
|
||||||
|
from ..literals import TEXT_EXCLUDE_IDENTIFIER, TEXT_ONLY_IDENTIFIER
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
|
|
||||||
@@ -48,7 +49,15 @@ def get_multi_item_links_form(context, object_list):
|
|||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def get_source_columns(source):
|
def get_source_columns(source, args=None):
|
||||||
|
exclude_identifier = False
|
||||||
|
only_identifier = False
|
||||||
|
|
||||||
|
if args == TEXT_EXCLUDE_IDENTIFIER:
|
||||||
|
exclude_identifier = True
|
||||||
|
elif args == TEXT_ONLY_IDENTIFIER:
|
||||||
|
only_identifier = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Is it a query set?
|
# Is it a query set?
|
||||||
source = source.model
|
source = source.model
|
||||||
@@ -67,7 +76,10 @@ def get_source_columns(source):
|
|||||||
# It a list and it's empty
|
# It a list and it's empty
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return SourceColumn.get_for_source(source)
|
return SourceColumn.get_for_source(
|
||||||
|
source=source, exclude_identifier=exclude_identifier,
|
||||||
|
only_identifier=only_identifier
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
@@ -78,5 +90,8 @@ def resolve_link(context, link):
|
|||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def source_column_resolve(context, column):
|
def source_column_resolve(context, column):
|
||||||
context['column_result'] = column.resolve(context=context)
|
if column:
|
||||||
|
result = column.resolve(context=context)
|
||||||
|
return result
|
||||||
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
Reference in New Issue
Block a user