Backport panel selection and panel toolbar
Support selection by panel body clicking. Styling changes for highlighted panel. Self-display multiple item action list. New select all button. Fix fancybox click area on thumbnail display. Remove the multi item form processing view. Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -220,6 +220,18 @@ a i {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.panel-highlighted {
|
||||
box-shadow: 0px 0px 3px #18bc9c, 10px 10px 20px #000000;
|
||||
}
|
||||
|
||||
.panel-highlighted:hover {
|
||||
box-shadow: 0px 0px 3px #18bc9c, 10px 10px 20px #000000, 0px 0px 8px #000000;
|
||||
}
|
||||
|
||||
.panel-item:not(.panel-highlighted):hover {
|
||||
box-shadow: 0px 0px 8px #000000;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
@media (min-width:1200px) {
|
||||
.container-fluid {
|
||||
@@ -249,14 +261,6 @@ a i {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.thin_border {
|
||||
border: 1px solid black;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
.thin_border-thumbnail {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
@@ -266,6 +270,14 @@ a i {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* Must go after .thin_border-thumbnail */
|
||||
.thin_border {
|
||||
border: 1px solid black;
|
||||
display: inline;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
#ajax-spinner {
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
|
||||
@@ -6,7 +6,8 @@ var MayanAppClass = MayanApp;
|
||||
|
||||
var partialNavigation = new PartialNavigation({
|
||||
initialURL: initialURL,
|
||||
disabledAnchorClasses: ['disabled'],
|
||||
disabledAnchorClasses: [
|
||||
'btn-multi-item-action', 'disabled', 'pagination-disabled'
|
||||
],
|
||||
excludeAnchorClasses: ['fancybox', 'new_window', 'non-ajax'],
|
||||
formBeforeSerializeCallbacks: [MayanApp.MultiObjectFormProcess],
|
||||
});
|
||||
|
||||
@@ -17,30 +17,36 @@ class MayanApp {
|
||||
|
||||
// Class methods and variables
|
||||
|
||||
static MultiObjectFormProcess ($form, options) {
|
||||
/*
|
||||
* ajaxForm callback to add the external item checkboxes to the
|
||||
* submitted form
|
||||
*/
|
||||
static countChecked() {
|
||||
var checkCount = $('.check-all-slave:checked').length;
|
||||
|
||||
if ($form.hasClass('form-multi-object-action')) {
|
||||
// Turn form data into an object
|
||||
var formArray = $form.serializeArray().reduce(function (obj, item) {
|
||||
obj[item.name] = item.value;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
// Add all checked checkboxes to the form data
|
||||
$('.form-multi-object-action-checkbox:checked').each(function() {
|
||||
var $this = $(this);
|
||||
formArray[$this.attr('name')] = $this.attr('value');
|
||||
});
|
||||
|
||||
// Set the form data as the data to send
|
||||
options.data = formArray;
|
||||
if (checkCount) {
|
||||
$('#multi-item-title').hide();
|
||||
$('#multi-item-actions').show();
|
||||
} else {
|
||||
$('#multi-item-title').show();
|
||||
$('#multi-item-actions').hide();
|
||||
}
|
||||
}
|
||||
|
||||
static setupMultiItemActions () {
|
||||
$('body').on('change', '.check-all-slave', function () {
|
||||
MayanApp.countChecked();
|
||||
});
|
||||
|
||||
$('body').on('click', '.btn-multi-item-action', function (event) {
|
||||
var id_list = [];
|
||||
$('.check-all-slave:checked').each(function (index, value) {
|
||||
//Split the name (ie:"pk_200") and extract only the ID
|
||||
id_list.push(value.name.split('_')[1]);
|
||||
});
|
||||
event.preventDefault();
|
||||
partialNavigation.setLocation(
|
||||
$(this).attr('href') + '?id_list=' + id_list.join(',')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
static setupNavBarState () {
|
||||
$('body').on('click', '.a-main-menu-accordion-link', function (event) {
|
||||
console.log('ad');
|
||||
@@ -166,10 +172,10 @@ class MayanApp {
|
||||
var self = this;
|
||||
|
||||
this.setupAJAXSpinner();
|
||||
this.setupAutoSubmit();
|
||||
this.setupFormHotkeys();
|
||||
this.setupFullHeightResizing();
|
||||
this.setupItemsSelector();
|
||||
MayanApp.setupMultiItemActions();
|
||||
this.setupNavbarCollapse();
|
||||
MayanApp.setupNavBarState();
|
||||
this.setupNewWindowAnchor();
|
||||
@@ -177,6 +183,7 @@ class MayanApp {
|
||||
value.app = self;
|
||||
app.doRefreshAJAXMenu(value);
|
||||
});
|
||||
this.setupPanelSelection();
|
||||
partialNavigation.initialize();
|
||||
}
|
||||
|
||||
@@ -200,14 +207,6 @@ class MayanApp {
|
||||
});
|
||||
}
|
||||
|
||||
setupAutoSubmit () {
|
||||
$('body').on('change', '.select-auto-submit', function () {
|
||||
if ($(this).val()) {
|
||||
$(this.form).trigger('submit');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setupFormHotkeys () {
|
||||
$('body').on('keypress', '.form-hotkey-enter', function (e) {
|
||||
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
|
||||
@@ -238,9 +237,22 @@ class MayanApp {
|
||||
app.lastChecked = null;
|
||||
|
||||
$('body').on('click', '.check-all', function (event) {
|
||||
var $this = $(this);
|
||||
var checked = $(event.target).prop('checked');
|
||||
var $checkBoxes = $('.check-all-slave');
|
||||
|
||||
if (checked === undefined) {
|
||||
checked = $this.data('checked');
|
||||
checked = !checked;
|
||||
$this.data('checked', 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.trigger('change');
|
||||
});
|
||||
@@ -286,6 +298,58 @@ class MayanApp {
|
||||
});
|
||||
}
|
||||
|
||||
setupPanelSelection () {
|
||||
var app = this;
|
||||
|
||||
// Setup panel highlighting on check
|
||||
$('body').on('change', '.check-all-slave', function (event) {
|
||||
var checked = $(event.target).prop('checked');
|
||||
if (checked) {
|
||||
$(this).closest('.panel-item').addClass('panel-highlighted');
|
||||
} else {
|
||||
$(this).closest('.panel-item').removeClass('panel-highlighted');
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click', '.panel-item', function (event) {
|
||||
var $this = $(this);
|
||||
var targetSrc = $(event.target).prop('src');
|
||||
var targetHref = $(event.target).prop('href');
|
||||
var targetIsButton = event.target.tagName === 'BUTTON';
|
||||
var lastChecked = null;
|
||||
|
||||
if ((targetSrc === undefined) && (targetHref === undefined) && (targetIsButton === false)) {
|
||||
var $checkbox = $this.find('.check-all-slave');
|
||||
var checked = $checkbox.prop('checked');
|
||||
|
||||
if (checked) {
|
||||
$checkbox.prop('checked', '');
|
||||
$checkbox.trigger('change');
|
||||
} else {
|
||||
$checkbox.prop('checked', 'checked');
|
||||
$checkbox.trigger('change');
|
||||
}
|
||||
|
||||
if(!app.lastChecked) {
|
||||
app.lastChecked = $checkbox;
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
var $checkBoxes = $('.check-all-slave');
|
||||
|
||||
var start = $checkBoxes.index($checkbox);
|
||||
var end = $checkBoxes.index(app.lastChecked);
|
||||
|
||||
$checkBoxes.slice(
|
||||
Math.min(start, end), Math.max(start, end) + 1
|
||||
).prop('checked', app.lastChecked.prop('checked')).trigger('change');
|
||||
}
|
||||
app.lastChecked = $checkbox;
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setupScrollView () {
|
||||
$('.scrollable').scrollview();
|
||||
}
|
||||
|
||||
@@ -23,26 +23,20 @@
|
||||
{% endif %}
|
||||
</h4>
|
||||
<hr>
|
||||
|
||||
<div class="well center-block">
|
||||
<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 not hide_multi_item_actions %}
|
||||
{% get_multi_item_links_form object_list %}
|
||||
{% endif %}
|
||||
{% if multi_item_actions %}
|
||||
<fieldset style="margin-top: -10px;">
|
||||
<input class="check-all" type="checkbox"/>
|
||||
{{ multi_item_form }}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if object_list %}
|
||||
{% if not hide_multi_item_actions %}
|
||||
{% navigation_resolve_menu name='multi item' sort_results=True source=object_list.0 as links_multi_menus_results %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div class="clearfix">
|
||||
{% include 'appearance/list_toolbar.html' %}
|
||||
</div>
|
||||
|
||||
{% if links_multi_menus_results %}
|
||||
<hr style="border-bottom: 1px solid lightgrey;">
|
||||
{% endif %}
|
||||
|
||||
@@ -54,8 +48,8 @@
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label for="id_indexes_0">
|
||||
{% if multi_item_actions %}
|
||||
<input class="form-multi-object-action-checkbox check-all-slave checkbox" type="checkbox" name="pk_{{ object.pk }}" />
|
||||
{% if links_multi_menus_results %}
|
||||
<input class="form-multi-object-action-checkbox check-all-slave checkbox" name="pk_{{ object.pk }}" type="checkbox" />
|
||||
{% endif %}
|
||||
|
||||
<span style="color: white; word-break: break-all; overflow-wrap: break-word;">
|
||||
@@ -82,7 +76,6 @@
|
||||
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
{% if not hide_columns %}
|
||||
{% navigation_get_source_columns source=object exclude_identifier=True as source_columns %}
|
||||
{% for column in source_columns %}
|
||||
|
||||
@@ -25,30 +25,27 @@
|
||||
<hr>
|
||||
|
||||
<div class="well center-block">
|
||||
{% if object_list %}
|
||||
{% if not hide_multi_item_actions %}
|
||||
{% navigation_resolve_menu name='multi item' sort_results=True source=object_list.0 as links_multi_menus_results %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<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 not hide_multi_item_actions %}
|
||||
{% get_multi_item_links_form object_list %}
|
||||
{% endif %}
|
||||
{% if multi_item_actions %}
|
||||
<fieldset style="margin-top: -10px; margin-bottom: 10px;">
|
||||
{{ multi_item_form }}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
{% include 'appearance/list_toolbar.html' %}
|
||||
</div>
|
||||
|
||||
{% if links_multi_menus_results %}
|
||||
<hr style="border-bottom: 1px solid lightgrey;">
|
||||
{% endif %}
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed table-striped">
|
||||
<tbody>
|
||||
{% if not hide_header %}
|
||||
<tr>
|
||||
{% if multi_item_actions %}
|
||||
<th class="first"><input class="checkbox check-all" type="checkbox" /></th>
|
||||
{% if links_multi_menus_results %}
|
||||
<th class="first"></th>
|
||||
{% endif %}
|
||||
|
||||
{% if not hide_object %}
|
||||
@@ -99,9 +96,9 @@
|
||||
{% for object in object_list %}
|
||||
<tr>
|
||||
|
||||
{% if multi_item_actions %}
|
||||
{% if links_multi_menus_results %}
|
||||
<td>
|
||||
<input type="checkbox" class="form-multi-object-action-checkbox check-all-slave checkbox" name="pk_{{ object.pk }}" value="" />
|
||||
<input class="form-multi-object-action-checkbox check-all-slave checkbox" name="pk_{{ object.pk }}" type="checkbox" value="" />
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
|
||||
49
mayan/apps/appearance/templates/appearance/list_toolbar.html
Normal file
49
mayan/apps/appearance/templates/appearance/list_toolbar.html
Normal file
@@ -0,0 +1,49 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% load common_tags %}
|
||||
{% load navigation_tags %}
|
||||
|
||||
<div class="pull-left">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="btn-group">
|
||||
{% if links_multi_menus_results %}
|
||||
<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 %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if links_multi_menus_results %}
|
||||
<p class="pull-right" id="multi-item-title" style="margin-top: 4px;">{% trans 'Select items to activate bulk actions. Use Shift + click to select many.' %}</p>
|
||||
|
||||
<div class="pull-right btn-group" id="multi-item-actions" style="display: none;">
|
||||
<button aria-expanded="true" class="btn btn-danger btn-sm dropdown-toggle" data-toggle="dropdown" type="button">
|
||||
{% trans 'Bulk actions' %}
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">{% trans 'Toggle Dropdown' %}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
{% for multi_item_menu_results in links_multi_menus_results %}
|
||||
{% for link_group in multi_item_menu_results.link_groups %}
|
||||
{% with link_group.links as object_navigation_links %}
|
||||
{% with 'true' as as_li %}
|
||||
{% with 'true' as hide_active_anchor %}
|
||||
{% with 'btn-sm btn-multi-item-action' as link_classes %}
|
||||
{% include 'navigation/generic_navigation.html' %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
|
||||
{% endfor %}
|
||||
{% if not forloop.last and link_group %}
|
||||
<li class="divider"></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
{% endif %}
|
||||
@@ -10,7 +10,7 @@ from .views import (
|
||||
AboutView, CurrentUserLocaleProfileDetailsView,
|
||||
CurrentUserLocaleProfileEditView, FaviconRedirectView, HomeView,
|
||||
LicenseView, ObjectErrorLogEntryListClearView, ObjectErrorLogEntryListView,
|
||||
RootView, SetupListView, ToolsListView, multi_object_action_view
|
||||
RootView, SetupListView, ToolsListView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@@ -18,10 +18,6 @@ urlpatterns = [
|
||||
url(regex=r'^home/$', view=HomeView.as_view(), name='home'),
|
||||
url(regex=r'^about/$', view=AboutView.as_view(), name='about_view'),
|
||||
url(regex=r'^license/$', view=LicenseView.as_view(), name='license_view'),
|
||||
url(
|
||||
regex=r'^object/multiple/action/$', view=multi_object_action_view,
|
||||
name='multi_object_action_view'
|
||||
),
|
||||
url(regex=r'^setup/$', view=SetupListView.as_view(), name='setup_list'),
|
||||
url(regex=r'^tools/$', view=ToolsListView.as_view(), name='tools_list'),
|
||||
url(
|
||||
|
||||
@@ -220,67 +220,3 @@ class ToolsListView(SimpleView):
|
||||
'These modules are used to do system maintenance.'
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def multi_object_action_view(request):
|
||||
"""
|
||||
Proxy view called first when using a multi object action, which
|
||||
then redirects to the appropriate specialized view
|
||||
"""
|
||||
next = request.POST.get(
|
||||
'next', request.GET.get(
|
||||
'next', request.META.get(
|
||||
'HTTP_REFERER', reverse(setting_home_view.value)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
action = request.GET.get('action', None)
|
||||
id_list = ','.join(
|
||||
[key[3:] for key in request.GET.keys() if key.startswith('pk_')]
|
||||
)
|
||||
items_property_list = [
|
||||
(key[11:]) for key in request.GET.keys() if key.startswith('properties_')
|
||||
]
|
||||
|
||||
if not action:
|
||||
messages.error(
|
||||
message=_('No action selected.'), request=request
|
||||
)
|
||||
return HttpResponseRedirect(
|
||||
redirect_to=request.META.get(
|
||||
'HTTP_REFERER', reverse(setting_home_view.value)
|
||||
)
|
||||
)
|
||||
|
||||
if not id_list and not items_property_list:
|
||||
messages.error(
|
||||
message=_('Must select at least one item.'),
|
||||
request=request
|
||||
)
|
||||
return HttpResponseRedirect(
|
||||
redirect_to=request.META.get(
|
||||
'HTTP_REFERER', reverse(setting_home_view.value)
|
||||
)
|
||||
)
|
||||
|
||||
# Separate redirects to keep backwards compatibility with older
|
||||
# functions that don't expect a properties_list parameter
|
||||
if items_property_list:
|
||||
return HttpResponseRedirect(
|
||||
redirect_to='%s?%s' % (
|
||||
action,
|
||||
urlencode(
|
||||
{
|
||||
'items_property_list': dumps(items_property_list),
|
||||
'next': next
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
else:
|
||||
return HttpResponseRedirect(
|
||||
redirect_to='%s?%s' % (
|
||||
action, urlencode({'id_list': id_list, 'next': next})
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user