Commit 5abb637f authored by Vincent Le gallic's avatar Vincent Le gallic

Implémentation du mode double-stack

parent 1e73ab60
......@@ -10,7 +10,7 @@ urlpatterns = patterns('note.views',
url(ur'^/index/*$', 'index'),
url(ur'^/logout/*$', 'logout'),
# consos
url(ur'^/consos/*$', 'consos'),
url(ur'^/consos(?P<double>-double)?/*$', 'consos'),
# les activités et invitations
url(ur'^/(?:activite|invitation)s?(?P<admin>/admin)?/*$', 'activites'),
url(ur'^/(?:activite|invitation)s?/(?P<idact>[^/]*)/gestion(?P<validation>/validate|/invalidate|/delete)?/*$', 'activite_gestion'),
......
......@@ -586,7 +586,7 @@ def index(request):
response = sock_ou_response
return response
def consos(request):
def consos(request, double=None):
"""La page des consos"""
# On appelle la fonction standard
success, sock_ou_response, variables_standard = standard_page(request, socket=True)
......@@ -614,7 +614,8 @@ def consos(request):
# Le formulaire de Retrait
variables["retrait_form"] = CreditRetraitForm(prefix="retrait_form", label_suffix=" :")
variables.update(variables_standard)
return render_to_response('note/consos.html', variables, context_instance=RequestContext(request))
template = 'note/consos-double.html' if double else 'note/consos.html'
return render_to_response(template, variables, context_instance=RequestContext(request))
else:
# Une erreur a eu lieu
response = sock_ou_response
......
......@@ -26,3 +26,19 @@
min-height: 100%;
overflow: auto;
}
/*** Page de conso ***/
/* stack */
.liste_notes, .stack, .liste_categories, .liste_boutons
{
list-style-type: none;
}
div.stack, div.liste_notes
{
border: 1px solid black;
min-height: 12em;
}
div.current_selection
{
height: 200px;
}
......@@ -38,7 +38,7 @@ function getInfo(secondstack) {
targetid += "_2";
}
//display = true parce qu'on veut afficher les comptes sur un mouseover
return readData(oData, targetid, true);
return readData(oData, targetid, true, secondstack);
}
request(asked, readDataWrapper);
}
......@@ -57,12 +57,14 @@ function put_note(itself, affiche, idbde, nom, prenom, secondstack) {
var stack_used = stack;
var display_stack_used = display_stack;
}
if ((!double_stack_mode) && (!isEmpty(stack_button)))
{
//Il y a des consos dans le stack et on vient de cliquer sur une note
// il faut donc lancer les transactions
do_conso_many_boutons(idbde);
return
if (!double_stack_mode)
{ // On encastre les tests parce que stack_button n'existe pas forcément
if (!isEmpty(stack_button)) {
//Il y a des consos dans le stack et on vient de cliquer sur une note
// il faut donc lancer les transactions
do_conso_many_boutons(idbde);
return
}
}
var before = stack_used[idbde];
if (before == null)
......@@ -142,7 +144,7 @@ function refreshStack(secondstack) {
new_stack.setAttribute("id", ident);
new_stack.setAttribute("class", "stack");
var elmt, source_elmt;
for (var note in display_stack) {
for (var note in display_stack_used) {
elmt = document.createElement("li");
source_elmt = display_stack_used[note]["source"].cloneNode(true);
source_elmt.replaceChild(document.createTextNode(source_elmt.firstChild.nodeValue + " (x" + display_stack_used[note]["nb"] + ")"),
......@@ -154,21 +156,38 @@ function refreshStack(secondstack) {
old_stack.parentNode.replaceChild(new_stack, old_stack);
}
/* fonction pour vider le stack */
function emptyStack() {
stack = [];
display_stack = [];
refreshStack();
/* fonction pour vider les stacks */
function emptyStack(secondstack, buttons) {
if (secondstack) {
stack_2 = [];
display_stack_2 = [];
}
else {
stack = [];
display_stack = [];
}
refreshStack(secondstack);
if (buttons) {
stack_button = [];
refreshStackButton();
}
}
/* fonction appelée quand on clique sur un bouton */
function put_conso(label, idbut) {
if ((!double_stack_mode) && (!isEmpty(stack)))
{
//Il y a des notes dans le stack et on vient de cliquer sur une conso
// il faut donc lancer les transactions
do_conso_many_notes(idbut);
return
if (double_stack_mode) {
if (!isEmpty(stack_2)) {
//Il y avait des notes dans le stack_2. On le vide.
emptyStack(true);
}
}
else {
if (!isEmpty(stack)) {
//Il y a des notes dans le stack et on vient de cliquer sur une conso
// il faut donc lancer les transactions
do_conso_many_notes(idbut);
return
}
}
var before = stack_button[idbut]
if (before == null) {
......@@ -271,6 +290,8 @@ function do_conso_many_boutons(idbde) {
}
//et on rafraîchit le stack_button
refreshStackButton();
//et l'historique
refreshHistorique();
}
};
//On fabrique la requête en utilisant l'idbde et en parsant stack_button
......@@ -285,10 +306,9 @@ function do_conso_many_boutons(idbde) {
}
var post_data = "consodata=" + encodeURIComponent(consodata);
xhr.send(post_data);
refreshHistorique();
}
/* fonction qui fait une conso avec plusieurs notes et un seule bouton */
/* fonction qui fait une conso avec plusieurs notes et un seul bouton */
function do_conso_many_notes(idbut) {
//On se prépare à poster une requête
var xhr = getXMLHttpRequest();
......@@ -333,6 +353,8 @@ function do_conso_many_notes(idbut) {
}
//et on rafraîchit le stack
refreshStack();
//et l'historique
refreshHistorique();
}
};
//On fabrique la requête en utilisant l'idbut et en parsant stack
......@@ -347,11 +369,69 @@ function do_conso_many_notes(idbut) {
}
var post_data = "consodata=" + encodeURIComponent(consodata);
xhr.send(post_data);
refreshHistorique();
}
/* fonction qui fait des consos avec plusieurs notes et un plusieurs boutons */
function do_conso_multiples() {
//On se prépare à poster une requête
var xhr = getXMLHttpRequest();
//On définit ce qu'on fera quand on recevra la réponse = gestion de l'éventuelle erreur
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) {
var answer = JSON.parse(xhr.responseText);
//On enlève du stack les consos qui ont marché et si il y a eu des échecs on alerte
var errorhappened = false;
var errmsg = "Transaction échouée :\n";
for (var i_ans in answer) {
ans = answer[i_ans];
if (!isSuccessCode(ans[0])) {
errorhappened = true;
//Il faut trouver les noms de note correspondants
var nom = ""
for (var i_note in display_stack) {
note = display_stack[i_note];
if (note["idbde"] == ans[1][1]) {
if (nom != "") {
nom += " aka ";
}
nom += note["affiche"];
}
}
errmsg += nom + "\t" + ans[2] + "\n";
}
}
// On vide tous les stacks, parce que garder des transaction échouées n'aurait pas de sens ici
//stack & stack_button
emptyStack(false, true);
if (errorhappened) {
alert(errmsg);
}
//et on rafraîchit les stacks
refreshStack();
refreshStack(true);
//et l'historique
refreshHistorique();
}
};
//On fabrique la requête en parsant les deux stacks
xhr.open("POST", "/note/do_conso/", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var consodata = ""
for (var i_button in stack_button) {
for (var i_compte in stack) {
if (consodata != "") {
consodata += ",";
}
consodata += "(" + i_button + "," + i_compte + "," + stack[i_compte]*stack_button[i_button]["nb"] + ")";
}
}
var post_data = "consodata=" + encodeURIComponent(consodata);
xhr.send(post_data);
}
/* fonction de mise à jour de l'historique */
function refreshHistorique() {
// $ = c'est du jQuery
$("#historique").load("/note/consos/ #historique");
}
......@@ -451,4 +531,4 @@ function crediter_ou_retirer(credit) {
}
);
}
\ No newline at end of file
}
/*******************************************************************************
Script consos en mode single stack
*******************************************************************************/
var double_stack_mode = true;
var stack = Array();
var stack_2 = Array();
var display_stack = Array();
var display_stack_2 = Array();
var stack_button = Array();
......@@ -5,6 +5,8 @@
var double_stack_mode = false;
var stack = Array();
var display_stack = Array();
var stack_button = Array();
\ No newline at end of file
var stack_button = Array();
/* Script JS qui permet d'afficher une liste dynamique
des notes en faisant un quick_search */
/** Il intéragit les éléments de la page.
/** Il intéragit avec les éléments de la page.
Repérés par leur i :
Repérés par leur id :
- "liste_notes" : l'élément (liste) qui sera remplacé par la liste des notes obtenue
Quand les données XMLHttpRequest sont reçue, il faut appeler dessus la fonction readData
Quand les données XMLHttpRequest sont reçues, il faut appeler dessus la fonction readData
en ajoutant un paramètre booléen.
- true si on veut que les notes appellent la fonction displayAccount sur un onMouseOver
- false sinon
......@@ -39,22 +39,20 @@ function request(asked, callback) {
var timer;
var timer_on;
/* fontion appelée quand le texte change (délenche le timer) */
function search_field_moved() {
if(timer_on == false) //si le timer n'est pas en cours, on le lance et on enregistre le fait qu'il tourne.
{
timer = setTimeout("getInfo()", 500);
timer_on = true;
}
else //On réinitialise le compteur.
{
clearTimeout(timer);
timer = setTimeout("getInfo()", 500);
}
function search_field_moved(secondfield) {
if (timer_on) //si le timer n'est pas en cours, on le lance et on enregistre le fait qu'il tourne.
{
clearTimeout(timer);
timer = setTimeout("getInfo(" + secondfield + ")", 500);
}
else //On réinitialise le compteur.
{
timer = setTimeout("getInfo(" + secondfield + ")", 500);
timer_on = true;
}
}
/* fonction qui traite les données retourner
(elle est wrappée par les scripts appelants pour lui fournir le 2ème paramètre */
/* fonction qui traite les données à leur retour
(elle est wrappée par les scripts appelants pour lui fournir les paramètre suivants) */
function readData(oData, targetid, display, tosecondstack) {
var gotlist = JSON.parse(oData);
var liste = document.createElement("ul");
......
......@@ -52,19 +52,17 @@ function getInfo() {
var timer;
var timer_on;
/* fontion appelée quand le texte change (délenche le timer) */
function search_field_moved() {
if(timer_on == false) //si le timer n'est pas en cours, on le lance et on enregistre le fait qu'il tourne.
{
timer = setTimeout("getInfo()", 500);
timer_on = true;
}
else //On réinitialise le compteur.
{
clearTimeout(timer);
timer = setTimeout("getInfo()", 500);
}
function search_field_moved(secondfield) {
if (timer_on) //si le timer n'est pas en cours, on le lance et on enregistre le fait qu'il tourne.
{
clearTimeout(timer);
timer = setTimeout("getInfo(" + secondfield + ")", 500);
}
else //On réinitialise le compteur.
{
timer = setTimeout("getInfo(" + secondfield + ")", 500);
timer_on = true;
}
}
/* wrapper pour readData */
function readDataNormal(oData) {
......
......@@ -8,8 +8,8 @@
{% endblock %}
{% block content %}
<p class="advanced_link">
<a href="/note/comptes_advanced/" class="advanced_link">Recherche avancée</a>
<p>
<a href="/note/comptes_advanced/">Recherche avancée</a>
</p>
<p class="search">
......
{% extends "note/base.html" %}
{% load note_templatetags %}
{% block title %}Consos{% endblock %}
{% block additional_javascript %}
<script type="text/javascript" src="{{ STATIC_URL }}js/custom/getXMLHttpRequest.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/custom/liste_dynamique_quick.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/custom/consos_base.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/custom/consos_double_stack.js"></script>
{% endblock %}
{# {% block mainstyle %}offset1 span10{% endblock %} #}
{% block mainstyle %}span12{% endblock %}
{% block content %}
<div class="row">
<div class="span12">
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active"><a href="#transfert" data-toggle="tab">Transfert</a></li>
<li><a href="#credit" data-toggle="tab">Crédit</a></li>
<li><a href="#retrait" data-toggle="tab">Retrait</a></li>
{% for categorie in categories %}
<li><a href="#{{categorie.lower}}" data-toggle="tab">{{categorie}}</a></li>
{% endfor %}
</ul>
<div class="tab-content">
<div class="tab-pane active" id="transfert">
<p>Transfert...</p>
</div>
<div class="tab-pane" id="credit">
<form onsubmit="crediter_ou_retirer(true); return false;"> {# true = crédit #}
<legend>Créditer <span id="credit_pseudo"><span></span></span> :</legend>
{{ credit_form.as_p }}
<input type="submit" class="btn btn-primary" value="Créditer"/>
</form>
</div>
<div class="tab-pane" id="retrait">
<form onsubmit="crediter_ou_retirer(false); return false;"> {# false = retrait #}
<legend>Retirer de l'argent à <span id="retrait_pseudo"><span></span></span> :</legend>
{{ retrait_form.as_p }}
<input type="submit" class="btn btn-primary" value="Retirer"/>
</form>
</div>
{% for categorie, listeboutons in boutons %}
<div class="tab-pane" id="{{categorie.lower}}">
{% for boutons in listeboutons|groupby:6 %}
<div class="row button-row">
{% for bouton in boutons %}
{% if bouton %}
<button class="btn span2"
onclick="put_conso('{{bouton.label}}', {{bouton.id}})"
onmouseover="displayButton('{{bouton.label}}', '{% euro bouton.montant %}')">
{{bouton.label}}
</button>
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
<div class="span6">
<div class="span4">
<div class="well current_selection">
<p id="current_selection">
<img src="http://placehold.it/106x160&text=Photo" alt="Photo">
</p>
</div>
</div>
</div>
<div class="span11">
<div class="row">
<div class="span5">
<div class="span3">
<p class="search_field">
<input type="text" name="Recherche" id="id_search_field" value="" autocomplete="off" onKeyUp="javascript:search_field_moved();return(false);"/></br>
<button class="btn" onclick="do_conso_multiples()">Consommer !</button>
</p>
</div>
<div class="span2">
<div class="liste_notes">
<ul id="liste_notes">
</ul>
</div>
</div>
<div class="span2">
<div class="stack">
<ul id="stack">
</ul>
</div>
</div>
</div>
<div class="span5 pull-right">
<div class="span3 pull-right">
<p class="search_field_2">
<input type="text" name="Recherche 2" id="id_search_field_2" value="" autocomplete="off" onKeyUp="javascript:search_field_moved(true);return(false);"/></br>
</p>
</div>
<div class="span2">
<div class="stack">
<ul id="stack_2">
</ul>
</div>
</div>
<div class="span2">
<div class="liste_notes">
<ul id="liste_notes_2">
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" id="historique">
<div class="span12">
<table class="table table-condensed table-striped">
{% if historique %}
<thead>
<caption>Historique des transactions récentes</caption>
<tr>
<th>Date</th>
<th>Émetteur</th>
<th>Destinataire</th>
<th>Type</th>
<th>Quantité</th>
<th>Montant</th>
<th>Description</th>
<th>Valide ?</th>
</tr>
</thead>
<tbody>
{% for transaction in historique %}
<tr>
<td>{% render_datetime transaction.date %}</td>
<td>{{transaction.emetteurpseudo}}</td>
<td>{{transaction.destinatairepseudo}}</td>
<td>{{transaction.type}}</td>
<td>{{transaction.quantite}}</td>
<td>{% euro transaction.montant %}</td>
<td>{{transaction.description}}</td>
<td>{% render_booleen transaction.valide %}</td>
</tr>
{% endfor %}
</tbody>
{% else %}
<thead>
<caption>Pas de transactions pour le moment</caption>
</thead>
{% endif %}
</table>
</div>
</div>
{% endblock %}
......@@ -10,32 +10,39 @@
<script type="text/javascript" src="{{ STATIC_URL }}js/custom/consos_single_stack.js"></script>
{% endblock %}
{% block mainstyle %}offset1 span10{% endblock %}
{% block mainstyle %}span12{% endblock %}
{% block content %}
<div class="row">
<div class="span4">
<div class="well">
<p id="current_selection">
<img src="http://placehold.it/106x160&text=Photo" alt="Photo">
</p>
<div class="span6">
<p>
<a href="/note/consos-double/">Mode double stack</a>
</p>
<div class="span4">
<div class="well current_selection">
<p id="current_selection">
<img src="http://placehold.it/106x160&text=Photo" alt="Photo">
</p>
</div>
</div>
<div class="blocks">
<div class="row">
<p class="search_field">
<input type="text" name="Recherche" id="id_search_field" value="" autocomplete="off" onKeyUp="javascript:search_field_moved();return(false);"/></br>
</p>
<div class="liste_notes">
<ul id="liste_notes">
</ul>
<div class="span3">
<div class="liste_notes">
<ul id="liste_notes">
</ul>
</div>
</div>
<div class="stack">
<ul id="stack">
</ul>
<div class="span3">
<div class="stack">
<ul id="stack">
</ul>
</div>
</div>
</div>
......@@ -92,7 +99,7 @@
</div>
<div class="row" id="historique">
<div class="offset1 span8">
<div class="offset1 span10">
<table class="table table-condensed table-striped">
{% if historique %}
<thead>
......
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