Commit a06a6b84 authored by Praibait's avatar Praibait

Refonte complète du fonctionnement de la validation/dévalitions des transactions.

La validation/dévalidation est désormais gérée par le JavaScript et communique avec le serveur par des requêtes POST. On a donc un affichage dynamique
de l'action.
J'ai du par contre changer la façon dont apparraissent les messages de retours (success, pasladroit, 404,...)  afin de bien les voir (et vu qu'on
ne recharge pas la page). Le design est encore à peaufiner et le code est assez dégueulasse par bien des endroits (ce qui ralentit probablement le JS) d'où la nécessité
de créer une nouvelle branche.

A noter que rien n'a du être changer côté backend.
parent f895e9b9
......@@ -258,4 +258,33 @@ def do_transfert(request):
return HttpResponse(json.dumps(out))
else:
return HttpResponse(u'"Erreur"')
""""""
@csrf_exempt
def toggle_transaction(request):
"""Gestion de la requête AJAJ pour la (dé)validation d'une transaction.
Reçoit en POST une chaîne "idtransaction,devalider" où
* ``idtransaction`` : id de la transaction à toggle (str)
* ``devalider`` = ``"true"`` si on veut dévalider, ``"false"`` sinon.
"""
if (request.method == "GET") or (request.session.get("logged", None) != "ok"):
return HttpResponse("Get the fuck out of here", status=444)
else:
try:
data = request.POST["data"].split(",")
idtransaction, devalidate = int(data[0]), (data[1] == "true")
except:
return HttpResponse(u'"Bad request"', status=400)
success, sock_ou_response = nk.socket_still_alive(request)
if success:
sock = sock_ou_response
variables = {}
cmd = "%svalider_transaction" % ("de" if devalidate else "")
sock.write(json.dumps([cmd, idtransaction]))
out = nk.full_read(sock)
return HttpResponse(json.dumps(out))
else:
return HttpResponse(u'"Erreur"')
......@@ -5,6 +5,16 @@ Template de rendering d'historique de consos
{% load note_templatetags %}
{% load i18n %}
{% block additional_stylesheets %}
<style>
a {cursor:pointer;}
</style>
{% endblock %}
{% block additionaljavascript %}
{% if not page_consos %}<script src="{{ STATIC_URL }}js/custom/getXMLHttpRequest.js"></script>{% endif %}
<script src="{{ STATIC_URL }}js/custom/toggle_transactions.js"></script>
{% endblock %}
<div class="panel panel-default table-responsive" id="historique">
<div class="panel-heading text-center lead">
......@@ -15,7 +25,7 @@ Template de rendering d'historique de consos
{% endif %}
</div>
{% include "note/template_pagination.html" %}
<table class="table table-condensed table-hover table-bordered historique">
<table class="table table-condensed table-hover table-bordered historique" id="histo_tab">
{% if historique %}
<thead>
<tr>
......@@ -39,7 +49,7 @@ Template de rendering d'historique de consos
<td>{{transaction.quantite}}</td>
<td>{% euro transaction.montant %}</td>
<td>{{transaction.description}}</td>
<td class="bg-{{ transaction.valide|yesno:"success,danger" }}"><a href="{{ NOTE_ROOT_URL }}consos/{% if transaction.valide %}de{% endif %}valider_transaction/{{ transaction.id }}?coming_from={{ NOTE_ROOT_URL }}{% if page_consos %}consos{% if double_stack_mode %}-double{% endif %}{% else %}comptes/{{ compte.idbde }}/historique/{{ num_page }}{% endif %}/"><span class="glyphicon glyphicon-{{ transaction.valide|yesno:"ok,remove" }}" aria-hidden="true"></span></a></td>
<td class="bg-{{ transaction.valide|yesno:"success,danger" }}"><a id="{{transaction.id}}" onclick="validedevalide(this);"><span class="glyphicon glyphicon-{{ transaction.valide|yesno:"ok,remove" }}" aria-hidden="true"></span></a></td>
</tr>
{% endfor %}
</tbody>
......
......@@ -20,7 +20,6 @@ urlpatterns = patterns('note.views',
url(ur'^i18n/', include('django.conf.urls.i18n')),
# consos
url(ur'^/consos(?P<double>-double)?/*$', 'consos'),
url(ur'^/consos(?:-double)?/(?P<de>de)?valider_transaction/(?P<idtransaction>[^/]*)$', 'toggle_transaction'),
# dons
url(ur'^/(?:virements|dons)/*', 'dons'),
# les activités et invitations
......@@ -91,6 +90,7 @@ urlpatterns += patterns('note.ajaj',
url(ur'^/do_conso/*$', 'do_conso'),
url(ur'^/do_(?P<action>credit|retrait)/*$', 'do_credit_retrait'),
url(ur'^/do_transfert/*$', 'do_transfert'),
url(ur'^/consos/toggle_transaction/*$', 'toggle_transaction'),
)
......
......@@ -439,30 +439,6 @@ def del_invite(request, sock, kwargs):
messages.add_error(request, out["errmsg"])
return HttpResponseRedirect(u"%sactivites/%s/%s" % (settings.NOTE_ROOT_URL, idact, "admin/" * admin))
@standard_page
def toggle_transaction(request, sock, kwargs):
"""Valider/Dévalider une transaction.
Dans ``kwargs`` :
* ``idtransaction`` : id de la transaction à toggle
* ``de`` = ``"de"`` si on veut dévalider, ``""`` sinon.
"""
devalidate = (kwargs["de"] == "de")
idtransaction = kwargs["idtransaction"]
variables = {}
cmd = "%svalider_transaction" % ("de" if devalidate else "")
sock.write(json.dumps([cmd, idtransaction]))
out = nk.full_read(sock)
if out["retcode"] == 404:
messages.add_error(request, messages.ERRMSG_IDTRANSACTION_FAIL % (idtransaction))
elif nk._is_success_code(out["retcode"]):
succmsg = messages.SUCCMSG_DEVALIDATE_TRANSACTION if devalidate else messages.SUCCMSG_VALIDATE_TRANSACTION
messages.add_success(request, succmsg)
else:
messages.add_error(request, out["errmsg"])
redirect = request.GET.get("coming_from", u"%sconsos/" % settings.NOTE_ROOT_URL)
return HttpResponseRedirect(redirect)
@standard_page_withignores(["idbde"])
def comptes(request, sock, kwargs):
"""La page de recherche d'un compte ou qui l'affiche.
......
/* Fonction qui appelle la fonction de (dé)validation pour changer l'état de la BDD.
Elle prend en paramètre button qui est la balise <a> qui correspond à la transaction concernée.
Elle envoie l'id de la transaction et la nature de l'action (validation dévalidation) et récupère les retours : messages, code de retour, messages
d'erreurs */
function validedevalide(button) {
// On récupère dans les deux autres éléments de la case
var fond = button.parentNode,
icone = button.firstChild;
// Si elle est déjà valide, il faut la dévalider
var devalider = (fond.className == "bg-success");
var xhr = getXMLHttpRequest(); // Préparation de la requête
xhr.onreadystatechange = (function () {
if (xhr.readyState == XMLHttpRequest.DONE) { // Quand la requête est terminée
if (xhr.status == 200 || xhr.status == 0) { // Si tout s'est bien passé
var rep = JSON.parse(xhr.responseText); // On parse le retour
var msg = rep["msg"], retcode = rep["retcode"], errmsg = rep["errmsg"]; // On récupère les données
if (retcode == 0) { // Si le serveur a réussi à (dé)valider la transation
toggleIcone(fond, icone, devalider); // On change l'affichage
affmessage(button, true, msg);
} else { // Sinon on affiche la raison
console.log(retcode + " " + errmsg);
affmessage(button, false, errmsg);
}
} else { // Si il y a eu un pb dans la requête on affiche un problème serveur (c'est la faute des devs)
console.log(xhr.status + ": " + xhr.statusText);
affmessage(button, false, xhr.status + ": " + xhr.statusText);
}
}
});
data = button.id + "," + devalider; // Encodage de la requête POST
xhr.open("POST", NOTE_ROOT_URL + "consos/toggle_transaction", true); // Page AJAJ qui va s'occupper de traiter la requête
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-CSRFToken", csrftoken);
xhr.send("data=" + encodeURIComponent(data)); // On envoie les données
};
/* Fonction qui sert simplement à modifier l'affichage de l'état de validation d'une transaction */
function toggleIcone (fond, icone, devalider) {
if (devalider) {
fond.className = "bg-danger";
icone.className = "glyphicon glyphicon-remove";
} else {
fond.className = "bg-success";
icone.className = "glyphicon glyphicon-ok";
}
};
var idmessages = []
function affmessage(button, reussite, message) {
var tableau = button.parentNode.parentNode.parentNode.parentNode,
tab = tableau.rows,
fin = parseFloat(tab[1].lastElementChild.firstChild.id);
var ligne = fin - parseFloat(button.id) +1 ;
if (idmessages) {
var compteur = 0;
for (var i=0; i<idmessages.length; i++) {
if (idmessages[i]<ligne) { compteur++; }
}
}
idmessages.push(ligne);
var newrow = tableau.insertRow(ligne + compteur + 1);
var colonnes = []
for (var i=0; i<8; i++) {
colonnes.push(newrow.insertCell(i));
colonnes[i].style.border = "0px";
}
colonnes[6].style.opacity = "0.1";
colonnes[6].style.fontSize = "0px";
colonnes[6].textContent = message;
colonnes[0].style.opacity = "0.1";
colonnes[0].style.fontSize = "0px";
colonnes[0].innerHTML = '<a class="glyphicon glyphicon-remove" aria-hidden="true"></a>';
colonnes[0].firstChild.onclick = function () {
clearTimeout(timer_fadeout);
fadeouttext();
};
newrow.style.backgroundColor = (reussite ? "#7ecc5e" : "#b45555");
newrow.style.height = "0px";
newrow.style.opacity = "0.1";
function fadeout () {
var opa = parseFloat(newrow.style.opacity);
if (opa > 0.1) {
newrow.style.opacity = opa - 0.1;
newrow.style.height = opa*40 + "px";
setTimeout(fadeout,100);
} else {
if (idmessages) {
var compteur = 0;
for (var i=0; i<idmessages.length; i++) {
if (idmessages[i]<ligne) { compteur++; }
}
}
tableau.deleteRow(ligne + compteur + 1 );
delete idmessages[idmessages.indexOf(ligne)];
}
};
function fadeouttext() {
var opa = parseFloat(colonnes[6].style.opacity);
if (opa > 0.1) {
colonnes[6].style.opacity = opa - 0.3;
colonnes[0].style.opacity = opa - 0.3;
setTimeout(fadeouttext,10);
} else {
fadeout();
}
};
function fadeintext() {
var opa = parseFloat(colonnes[6].style.opacity);
if (opa < 1) {
colonnes[6].style.opacity = opa + 0.3;
colonnes[0].style.opacity = opa + 0.3;
setTimeout(fadeintext,10);
} else {
timer_fadeout = setTimeout(fadeouttext, (reussite ? 1000 : 5000));
}
};
(function fadeinligne () {
var opa = parseFloat(newrow.style.opacity);
if (opa < 1) {
newrow.style.opacity = opa + 0.1;
newrow.style.height = opa*40 + "px";
setTimeout(fadeinligne,5);
} else {
colonnes[6].style.fontSize = "14px";
colonnes[0].style.fontSize = "14px";
fadeintext();
}
})();
};
  • J'ai oublié de préciser que ça tourne bien sauf sur la page historique perso où j'ai un souci avec les notifs.

    Edited by Praibait
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment