Merge branch 'aureplop/kfet-sticky_thead' into 'master'

kfet -- Tables are sortable

Closes #171

See merge request cof-geek/gestioCOF!277
This commit is contained in:
Martin Pepin 2018-04-07 13:47:55 +02:00
commit 9d7486585b
20 changed files with 6331 additions and 149 deletions

View file

@ -75,6 +75,10 @@ ul {
padding:8px !important;
}
.table thead .sm-padding {
padding:3px !important;
}
.table tr.section {
background: #c63b52 !important;
color:#fff;

View file

@ -3,6 +3,7 @@
/* Libs customizations */
@import url("libs/jconfirm-kfet.css");
@import url("libs/jquery-tablesorter-kfet.css");
@import url("libs/multiple-select-kfet.css");
/* Base */
@ -54,6 +55,11 @@
color: #C81022;
}
.table thead .glyphicon {
font-size: 12px;
opacity: 0.8;
}
/*
* Pages tableaux seuls
@ -82,6 +88,11 @@
border-radius: 0;
}
.table td.small-width {
/* Header still extends the width of the column, but it will be minimal. */
width: 30px;
}
.auth-form {
padding: 15px 0;
background: #d86c7e;

View file

@ -235,3 +235,77 @@ function submit_url(el) {
let url = $(el).data('url');
create_form(url).appendTo($('body')).submit();
}
/**
* jquery-tablesorter
* https://mottie.github.io/tablesorter/docs/
*
* Known bugs (v2.29.0):
* - Sort order icons in sticky headers are not updated.
* Status: Fixed in next release.
*
* TODO:
* - Handle i18n.
*/
function registerBoolParser(id, true_str, false_str) {
$.tablesorter.addParser({
id: id,
format: function(s) {
return s.toLowerCase()
.replace(true_str, 1)
.replace(false_str, 0);
},
type: 'numeric'
});
}
// Parsers for the text representations of boolean.
registerBoolParser('yesno', 'oui', 'non');
registerBoolParser('article__is_sold', 'en vente', 'non vendu');
registerBoolParser('article__hidden', 'caché', 'affiché');
// https://mottie.github.io/tablesorter/docs/index.html#variable-defaults
$.extend(true, $.tablesorter.defaults, {
headerTemplate: '{content} {icon}',
cssIconAsc : 'glyphicon glyphicon-chevron-up',
cssIconDesc : 'glyphicon glyphicon-chevron-down',
cssIconNone : 'glyphicon glyphicon-resize-vertical',
// Only four-digits format year is handled by the builtin parser
// 'shortDate'.
dateFormat: 'ddmmyyyy',
// Accented characters are replaced with their non-accented one.
sortLocaleCompare: true,
// French format: 1 234,56
usNumberFormat: false,
widgets: ['stickyHeaders'],
widgetOptions: {
stickyHeaders_offset: '.navbar',
}
});
// https://mottie.github.io/tablesorter/docs/index.html#variable-language
$.extend($.tablesorter.language, {
sortAsc : 'Trié par ordre croissant, ',
sortDesc : 'Trié par ordre décroissant, ',
sortNone : 'Non trié, ',
sortDisabled : 'tri désactivé et/ou non-modifiable',
nextAsc : 'cliquer pour trier par ordre croissant',
nextDesc : 'cliquer pour trier par ordre décroissant',
nextNone : 'cliquer pour retirer le tri'
});
$( function() {
$('.sortable').tablesorter();
});

File diff suppressed because it is too large Load diff

View file

@ -37,13 +37,16 @@
<section>
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(trigramme,asc)] #}
data-sortlist="[[0,0]]">
<thead>
<tr>
<td class="text-center">Tri.</td>
<td>Nom</td>
<td class="text-right">Balance</td>
<td class="text-center">COF</td>
<td class="text-center" data-sorter="yesno">COF</td>
<td>Dpt</td>
<td class="text-center">Promo</td>
</tr>

View file

@ -35,16 +35,19 @@
{% block main %}
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(trigramme,asc)] #}
data-sortlist="[[0,0]]">
<thead>
<tr>
<td class="text-center">Tri.</td>
<td>Nom</td>
<td class="text-right">Balance</td>
<td class="text-right">Réelle</td>
<td>Début</td>
<td data-sorter="shortDate">Début</td>
<td>Découvert autorisé</td>
<td>Jusqu'au</td>
<td data-sorter="shortDate">Jusqu'au</td>
<td>Balance offset</td>
</tr>
</thead>
@ -63,9 +66,13 @@
{{ neg.account.real_balance|floatformat:2 }}€
{% endif %}
</td>
<td>{{ neg.start|date:'d/m/Y H:i:s'}}</td>
<td title="{{ neg.start }}">
{{ neg.start|date:'d/m/Y H:i'}}
</td>
<td>{{ neg.authz_overdraft_amount|default_if_none:'' }}</td>
<td>{{ neg.authz_overdrafy_until|default_if_none:'' }}</td>
<td title="{{ neg.authz_overdraft_until }}">
{{ neg.authz_overdraft_until|date:'d/m/Y H:i' }}
</td>
<td>{{ neg.balance_offset|default_if_none:'' }}</td>
</tr>
{% endfor %}

View file

@ -26,40 +26,50 @@
{% block main %}
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(is_sold,desc), (name,asc)] #}
data-sortlist="[[3,1], [0,0]]">
<thead>
<tr>
<td>Nom</td>
<td class="text-right">Prix</td>
<td class="text-right">Stock</td>
<td class="text-right">En vente</td>
<td class="text-right">Affiché</td>
<td class="text-right">Dernier inventaire</td>
<td class="text-right" data-sorter="article__is_sold">En vente</td>
<td class="text-right" data-sorter="article__hidden">Affiché</td>
<td class="text-right" data-sorter="shortDate">Dernier inventaire</td>
</tr>
</thead>
<tbody>
{% for article in articles %}
{% ifchanged article.category %}
<tr class="section">
<td colspan="6">{{ article.category.name }}</td>
</tr>
{% endifchanged %}
<tr>
<td>
<a href="{% url 'kfet.article.read' article.pk %}">
{{ article.name }}
</a>
</td>
<td class="text-right">{{ article.price }}€</td>
<td class="text-right">{{ article.stock }}</td>
<td class="text-right">{{ article.is_sold | yesno:"En vente,Non vendu"}}</td>
<td class="text-right">{{ article.hidden | yesno:"Caché,Affiché" }}</td>
<td class="text-right">{{ article.inventory.0.at }}</td>
</tr>
{% endfor %}
</tbody>
{% regroup articles by category as category_list %}
{% for category in category_list %}
<tbody class="tablesorter-no-sort">
<tr class="section">
<td colspan="6">{{ category.grouper }}</td>
</tr>
</tbody>
<tbody>
{% for article in category.list %}
<tr>
<td>
<a href="{% url 'kfet.article.read' article.pk %}">
{{ article.name }}
</a>
</td>
<td class="text-right">{{ article.price }}€</td>
<td class="text-right">{{ article.stock }}</td>
<td class="text-right">{{ article.is_sold | yesno:"En vente,Non vendu"}}</td>
<td class="text-right">{{ article.hidden | yesno:"Caché,Affiché" }}</td>
{% with last_inventory=article.inventory.0 %}
<td class="text-right" title="{{ last_inventory.at }}">
{{ last_inventory.at|date:'d/m/Y H:i' }}
</td>
{% endwith %}
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
</div>
{% endblock %}

View file

@ -1,7 +1,10 @@
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(inventory.at,desc)] #}
data-sortlist="[[0,1]]">
<thead>
<tr>
<td>Date</td>
<td data-sorter="shortDate">Date</td>
<td>Stock</td>
<td>Erreur</td>
</tr>
@ -9,9 +12,9 @@
<tbody>
{% for inventoryart in inventoryarts %}
<tr>
<td>
<td title="{{ inventoryart.inventory.at }}">
<a href="{% url "kfet.inventory.read" inventoryart.inventory.pk %}">
{{ inventoryart.inventory.at }}
{{ inventoryart.inventory.at|date:'d/m/Y H:i' }}
</a>
</td>
<td>{{ inventoryart.stock_new }}</td>

View file

@ -1,7 +1,10 @@
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(at,desc)] #}
data-sortlist="[[0,1]]">
<thead>
<tr>
<td>Date</td>
<td data-sorter="shortDate">Date</td>
<td>Fournisseur</td>
<td>HT</td>
<td>TVA</td>
@ -11,7 +14,9 @@
<tbody>
{% for supplierart in supplierarts %}
<tr>
<td>{{ supplierart.at }}</td>
<td title="{{ supplierart.at }}">
{{ supplierart.at|date:'d/m/Y' }}
</td>
<td>{{ supplierart.supplier.name }}</td>
<td>{{ supplierart.price_HT|default_if_none:"" }}</td>
<td>{{ supplierart.TVA|default_if_none:"" }}</td>

View file

@ -24,6 +24,7 @@
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script type="text/javascript" src="{% static 'kfet/js/jquery-ui.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/jquery-confirm.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/jquery-tablesorter/jquery.tablesorter.combined.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/reconnecting-websocket.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/moment.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/moment-fr.js' %}"></script>

View file

@ -17,12 +17,15 @@
{% block main %}
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(name,asc)] #}
data-sortlist="[[0,0]]">
<thead>
<tr>
<td>Nom</td>
<td class="text-right">Nombre d'articles</td>
<td class="text-right">Peut être majorée</td>
<td class="text-right" data-sorter="yesno">Peut être majorée</td>
</tr>
</thead>
<tbody>

View file

@ -24,13 +24,16 @@
{% block main %}
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(valid_to,desc)] #}
data-sortlist="[[3,1]]">
<thead>
<tr>
<td>Nom</td>
<td class="text-right">Balance</td>
<td class="text-right">Déb. valid.</td>
<td class="text-right">Fin valid.</td>
<td class="text-right" data-parser="shortDate">Déb. valid.</td>
<td class="text-right" data-parser="shortDate">Fin valid.</td>
<td class="text-right">Protégée</td>
</tr>
</thead>
@ -43,8 +46,12 @@
</a>
</td>
<td class="text-right">{{ checkout.balance}}€</td>
<td class="text-right">{{ checkout.valid_from }}</td>
<td class="text-right">{{ checkout.valid_to }}</td>
<td class="text-right" title="{{ checkout.valid_from }}">
{{ checkout.valid_from|date:'d/m/Y H:i' }}
</td>
<td class="text-right" title="{{ checkout.valid_to }}">
{{ checkout.valid_to|date:'d/m/Y H:i' }}
</td>
<td class="text-right">{{ checkout.is_protected|yesno }}</td>
</tr>
{% endfor %}

View file

@ -14,10 +14,13 @@
{% if not statements %}
Pas de relevé
{% else %}
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(at,desc)] #}
data-sortlist="[[0,1]]">
<thead>
<tr>
<td>Date/heure</td>
<td data-sorter="shortDate">Date/heure</td>
<td>Montant pris</td>
<td>Montant laissé</td>
<td>Erreur</td>
@ -25,9 +28,9 @@
<tbody>
{% for statement in statements %}
<tr>
<td>
<td title="{{ statement.at }}">
<a href="{% url 'kfet.checkoutstatement.update' checkout.pk statement.pk %}">
{{ statement.at }}
{{ statement.at|date:'d/m/Y H:i' }}
</a>
</td>
<td>{{ statement.amount_taken }}</td>

View file

@ -17,10 +17,13 @@
{% block main %}
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(at,desc)] #}
data-sortlist="[[0,1]]">
<thead>
<tr>
<td>Date</td>
<td data-sorter="shortDate">Date</td>
<td>Par</td>
<td>Nb articles</td>
</tr>
@ -28,9 +31,9 @@
<tbody>
{% for inventory in inventories %}
<tr>
<td>
<td title="{{ inventory.at }}">
<a href="{% url 'kfet.inventory.read' inventory.pk %}">
<span>{{ inventory.at }}</span>
{{ inventory.at|date:'d/m/Y H:i' }}
</a>
</td>
<td>{{ inventory.by }}</td>

View file

@ -27,7 +27,10 @@
{% block main %}
<div class="table-responsive">
<table class="table table-condensed">
<table
class="table table-condensed table-hover table-striped sortable"
{# Initial sort: [(article.name,asc)] #}
data-sortlist="[[0,0]]">
<thead>
<tr>
<td>Article</td>
@ -36,25 +39,28 @@
<td>Erreur</td>
</tr>
</thead>
<tbody>
{% for inventoryart in inventoryarts %}
{% ifchanged inventoryart.article.category %}
<tr class="section">
<td colspan="4">{{ inventoryart.article.category.name }}</td>
</tr>
{% endifchanged %}
<tr>
<td>
<a href="{% url "kfet.article.read" inventoryart.article.id %}">
{{ inventoryart.article.name }}
</a>
</td>
<td>{{ inventoryart.stock_old }}</td>
<td>{{ inventoryart.stock_new }}</td>
<td>{{ inventoryart.stock_error }}</td>
{% regroup inventoryarts by article.category as category_list %}
{% for category in category_list %}
<tbody class="tablesorter-no-sort">
<tr class="section">
<td colspan="4">{{ category.grouper.name }}</td>
</tr>
{% endfor %}
</tbody>
</tbody>
<tbody>
{% for inventoryart in category.list %}
<tr>
<td>
<a href="{% url "kfet.article.read" inventoryart.article.id %}">
{{ inventoryart.article.name }}
</a>
</td>
<td>{{ inventoryart.stock_old }}</td>
<td>{{ inventoryart.stock_new }}</td>
<td>{{ inventoryart.stock_error }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>

View file

@ -55,11 +55,14 @@
<section>
<h2>Liste des commandes</h2>
<div class="table-responsive">
<table class="table table-hover table-condensed">
<table
class="table table-hover table-condensed sortable"
{# Initial sort: [(at,desc)] #}
data-sortlist="[[1,1]]">
<thead>
<tr>
<td></td>
<td>Date</td>
<td data-sorter="false"></td>
<td data-parser="shortDate">Date</td>
<td>Fournisseur</td>
<td>Inventaire</td>
</tr>
@ -74,9 +77,9 @@
</a>
{% endif %}
</td>
<td>
<td tile="{{ order.at }}">
<a href="{% url 'kfet.order.read' order.pk %}">
{{ order.at }}
{{ order.at|date:'d/m/Y H:i' }}
</a>
</td>
<td>{{ order.supplier }}</td>

View file

@ -11,60 +11,79 @@
<form action="" method="post">
{% csrf_token %}
<div class="table-responsive">
<table class="table table-hover table-condensed table-condensed-input text-center table-striped">
<table
class="table table-hover table-condensed table-condensed-input text-center table-striped sortable"
{# Initial sort: [(name,asc)] #}
data-sortlist="[[0,0]]">
<thead>
<tr>
<td rowspan="2">Article</td>
<td colspan="{{ scale|length }}">Ventes
<span class='glyphicon glyphicon-question-sign' title="Ventes des 5 dernières semaines" data-placement="bottom"></span>
</td>
<td rowspan="2">V. moy.<br>
<span class='glyphicon glyphicon-question-sign' title="Moyenne des ventes" data-placement="bottom"></span>
</td>
<td rowspan="2">E.T.<br>
<span class='glyphicon glyphicon-question-sign' title="Écart-type des ventes" data-placement="bottom"></span>
</td>
<td rowspan="2">Prév.<br>
<span class='glyphicon glyphicon-question-sign' title="Prévision de ventes" data-placement="bottom"></span>
</td>
<td colspan="{{ scale|length }}">
Ventes
<i class='glyphicon glyphicon-question-sign' title="Ventes des 5 dernières semaines" data-placement="bottom"></i>
</td>
<td rowspan="2">
V. moy.
<br>
<i class='glyphicon glyphicon-question-sign' title="Moyenne des ventes" data-placement="bottom"></i>
</td>
<td rowspan="2" data-sorter="false">
E.T.
<br>
<i class='glyphicon glyphicon-question-sign' title="Écart-type des ventes" data-placement="bottom"></i>
</td>
<td rowspan="2">
Prév.
<br>
<i class='glyphicon glyphicon-question-sign' title="Prévision de ventes" data-placement="bottom"></i>
</td>
<td rowspan="2">Stock</td>
<td rowspan="2">Box<br>
<span class='glyphicon glyphicon-question-sign' title="Capacité d'une boite" data-placement="bottom"></span>
</td>
<td rowspan="2">Rec.<br>
<span class='glyphicon glyphicon-question-sign' title="Quantité conseillée" data-placement="bottom"></span>
</td>
<td rowspan="2">Commande</td>
<td rowspan="2" data-sorter="false">
Box
<br>
<i class='glyphicon glyphicon-question-sign' title="Capacité d'une boite" data-placement="bottom"></i>
</td>
<td rowspan="2">
Rec.
<br>
<i class='glyphicon glyphicon-question-sign' title="Quantité conseillée" data-placement="bottom"></i>
</td>
<td rowspan="2" data-sorter="false" class="small-width">
Commande
</td>
</tr>
<tr>
{% for label in scale.get_labels %}
<td>{{ label }}</td>
<td class="sm-padding">{{ label }}</td>
{% endfor %}
</tr>
</thead>
<tbody>
{% for form in formset %}
{% ifchanged form.category %}
<tr class='section text-left'>
<td colspan="{{ scale|length|add:'8' }}">{{ form.category_name }}</td>
</tr>
{% endifchanged %}
<tr>
{{ form.article }}
<td class="text-left">{{ form.name }}</td>
{% for v_chunk in form.v_all %}
<td>{{ v_chunk }}</td>
{% endfor %}
<td>{{ form.v_moy }}</td>
<td>{{ form.v_et }}</td>
<td>{{ form.v_prev }}</td>
<td>{{ form.stock }}</td>
<td>{{ form.box_capacity|default:"" }}</td>
<td>{{ form.c_rec }}</td>
<td class="nopadding">{{ form.quantity_ordered | add_class:"form-control" }}</td>
{% regroup formset by category_name as category_list %}
{% for category in category_list %}
<tbody class="tablesorter-no-sort">
<tr class='section text-left'>
<td colspan="{{ scale|length|add:'8' }}">{{ category.grouper }}</td>
</tr>
{% endfor %}
</tbody>
</tbody>
<tbody>
{% for form in category.list %}
<tr>
{{ form.article }}
<td class="text-left">{{ form.name }}</td>
{% for v_chunk in form.v_all %}
<td>{{ v_chunk }}</td>
{% endfor %}
<td>{{ form.v_moy }}</td>
<td>{{ form.v_et }}</td>
<td>{{ form.v_prev }}</td>
<td>{{ form.stock }}</td>
<td>{{ form.box_capacity|default:"" }}</td>
<td>{{ form.c_rec }}</td>
<td class="nopadding">{{ form.quantity_ordered|add_class:"form-control" }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
{{ formset.management_form }}

View file

@ -42,7 +42,10 @@
<section>
<h2>Détails</h2>
<div class="table-responsive">
<table class="table table-condensed">
<table
class="table table-condensed table-hover table-striped sortable"
{# Initial sort: [(article.name,asc)] #}
data-sortlist="[[0,0]]">
<thead>
<tr>
<td>Article</td>
@ -51,32 +54,35 @@
<td>Reçu</td>
</tr>
</thead>
<tbody>
{% for orderart in orderarts %}
{% ifchanged orderart.article.category %}
<tr class="section">
<td colspan="4">{{ orderart.article.category.name }}</td>
</tr>
{% endifchanged %}
<tr>
<td>
<a href="{% url "kfet.article.read" orderart.article.id %}">
{{ orderart.article.name }}
</a>
</td>
<td>{{ orderart.quantity_ordered }}</td>
<td>
{% if orderart.article.box_capacity %}
{# c'est une division ! #}
{% widthratio orderart.quantity_ordered orderart.article.box_capacity 1 %}
{% endif %}
</td>
<td>
{{ orderart.quantity_received|default_if_none:'' }}
</td>
{% regroup orderarts by article.category as category_list %}
{% for category in category_list %}
<tbody class="tablesorter-no-sort">
<tr class="section">
<td colspan="4">{{ category.grouper.name }}</td>
</tr>
{% endfor %}
</tbody>
</tbody>
<tbody>
{% for orderart in category.list %}
<tr>
<td>
<a href="{% url "kfet.article.read" orderart.article.id %}">
{{ orderart.article.name }}
</a>
</td>
<td>{{ orderart.quantity_ordered }}</td>
<td>
{% if orderart.article.box_capacity %}
{# c'est une division ! #}
{% widthratio orderart.quantity_ordered orderart.article.box_capacity 1 %}
{% endif %}
</td>
<td>
{{ orderart.quantity_received|default_if_none:'' }}
</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
</section>

View file

@ -1835,7 +1835,7 @@ def order_create(request, pk):
else:
formset = cls_formset(initial=initial)
scale.label_fmt = "S -{rev_i}"
scale.label_fmt = "S-{rev_i}"
return render(request, 'kfet/order_create.html', {
'supplier': supplier,