From 5790c374341c5e542ff17a8f245bb5aa43af1d58 Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Fri, 6 Jun 2008 15:34:22 +0000 Subject: [PATCH] --- css/1/pageMinichat.css | 51 ++++--- .../couleurs entetes messages css1.svg | 132 ++++++++++++++++++ js/euphorik.js | 30 ++-- js/pageAdmin.js | 104 ++++++++------ js/pageMinichat.js | 127 ++++++++++------- modules/erl/euphorik_common.erl | 36 +++++ modules/erl/euphorik_daemon.erl | 2 +- modules/erl/euphorik_protocole.erl | 2 +- 8 files changed, 359 insertions(+), 125 deletions(-) create mode 100644 doc/graphiques/couleurs entetes messages css1.svg create mode 100644 modules/erl/euphorik_common.erl diff --git a/css/1/pageMinichat.css b/css/1/pageMinichat.css index d555074..2cc07be 100755 --- a/css/1/pageMinichat.css +++ b/css/1/pageMinichat.css @@ -114,15 +114,6 @@ float: left; width: 100%; } -#page.minichat #conversations div.message { - border-left-width: 5px; - border-left-style: solid; - border-color: transparent; - padding-right: 5px; - cursor: pointer; - min-height: 18px; - line-height: 18px; -} #page.minichat #conversations div.messageImpair { background-color: #fbeede; } @@ -136,18 +127,6 @@ filter: alpha(opacity = 30); zoom: 1 } -#page.minichat #conversations div.reponse { - border-color: #bd7a11 -} -#page.minichat #conversations div.repondu { - border-color: #b711bd -} -#page.minichat #conversations div.proprietaire { - border-color: #bd1129 -} -#page.minichat #conversations div.systeme { - background-color: #f0df95 -} #page.minichat #conversations .titre { text-align: center; padding-right: 8px; @@ -196,6 +175,36 @@ } /***** Les messages *****/ +#page.minichat #conversations div.message { + padding-right: 5px; + cursor: pointer; + min-height: 18px; + line-height: 18px; +} +#page.minichat #conversations div.message.reponse .entete { + background-color: #bf2911 +} +#page.minichat #conversations div.message.reponse .delimitationEntete, +#page.minichat #conversations div.message.reponse .repondA { + background-image: url(../../img/css1/fleche_reponse.png); +} +#page.minichat #conversations div.message.repondu .entete { + background-color: #84196c +} +#page.minichat #conversations div.message.repondu .delimitationEntete, +#page.minichat #conversations div.message.repondu .repondA { + background-image: url(../../img/css1/fleche_repondu.png); +} +#page.minichat #conversations div.message.proprietaire .entete { + background-color: #31732f +} +#page.minichat #conversations div.message.proprietaire .delimitationEntete, +#page.minichat #conversations div.message.proprietaire .repondA { + background-image: url(../../img/css1/fleche_proprietaire.png); +} +#page.minichat #conversations div.message.systeme { + background-color: #f0df95 +} #page.minichat div.message a { font-weight: bold; } diff --git a/doc/graphiques/couleurs entetes messages css1.svg b/doc/graphiques/couleurs entetes messages css1.svg new file mode 100644 index 0000000..98d261e --- /dev/null +++ b/doc/graphiques/couleurs entetes messages css1.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + référence + réponse + mon message + répondu + + diff --git a/js/euphorik.js b/js/euphorik.js index 825e4c3..f330209 100755 --- a/js/euphorik.js +++ b/js/euphorik.js @@ -994,6 +994,16 @@ Client.prototype.kick = function(userId, raison) /** * classe permettant de gérer les événements (push serveur). + * l'information envoyé est sous la forme : + * { + * "action" : "wait_event" + * "page" : + * [..] + * } + * l'information reçu est sous la forme : + * { + * "reply" : + * } * @page la page */ function PageEvent(page, util) @@ -1024,9 +1034,11 @@ PageEvent.prototype.stopAttenteCourante = function() /** * Attend un événement lié à la page. * @funSend une fonction renvoyant les données json à envoyer - * @funReceive une fonction qui accepte un paramètre correspondant au données reçues + * @funsReceive est un objet comprenant les fonctions à appeler en fonction du "reply" + * les fonctions acceptent un paramètre correspondant au données reçues. + * exemple : {"new_message" : function(data){ ... }} */ -PageEvent.prototype.waitEvent = function(funSend, funReceive) +PageEvent.prototype.waitEvent = function(funSend, funsReceive) { this.stopAttenteCourante() @@ -1050,22 +1062,24 @@ PageEvent.prototype.waitEvent = function(funSend, funReceive) this.attenteCourante = jQuery.ajax({ type: "POST", url: "request", - dataType: "json", + dataType: "json", + timeout: 300000, // timeout de 5min. Gros HACK pas beau. FIXME problème décrit ici : http://groups.google.com/group/jquery-en/browse_thread/thread/8724e64af3333a76 data: this.util.jsonVersAction(dataToSend), success: function(data) { ;; dumpObj(data) - funReceive(data) + funsReceive[data["reply"]](data) // rappel de la fonction dans 100 ms - setTimeout(function(){ thisPageEvent.waitEvent2(funSend, funReceive) }, 100) + setTimeout(function(){ thisPageEvent.waitEvent2(funSend, funsReceive) }, 100) }, error: function(XMLHttpRequest, textStatus, errorThrown) { - setTimeout(function(){ thisPageEvent.waitEvent2(funSend, funReceive) }, 1000) + ;; console.log("Connexion perdue dans waitEvent") + setTimeout(function(){ thisPageEvent.waitEvent2(funSend, funsReceive) }, 1000) } }) } @@ -1073,11 +1087,11 @@ PageEvent.prototype.waitEvent = function(funSend, funReceive) /** * Si un stopAttenteCourante survient un peu n'importe quand il faut imédiatement arreter de boucler. */ -PageEvent.prototype.waitEvent2 = function(funSend, funReceive) +PageEvent.prototype.waitEvent2 = function(funSend, funsReceive) { if (this.stop) return - this.waitEvent(funSend, funReceive) + this.waitEvent(funSend, funsReceive) } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/js/pageAdmin.js b/js/pageAdmin.js index 97c0243..db50c4b 100644 --- a/js/pageAdmin.js +++ b/js/pageAdmin.js @@ -1,20 +1,22 @@ -// coding: utf-8 -// Copyright 2008 Grégory Burri -// -// This file is part of Euphorik. -// -// Euphorik is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Euphorik is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License +// coding: utf-8 +// Copyright 2008 Grégory Burri +// +// This file is part of Euphorik. +// +// Euphorik is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Euphorik is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License // along with Euphorik. If not, see . +// +// La page d'administation, ne peut être accédée que par les ekMaster (admins) function PageAdmin(client, formateur, util) { @@ -26,12 +28,17 @@ function PageAdmin(client, formateur, util) this.pageEvent = new PageEvent("admin", this.util) + // le timer qui rappelle periodiquement le rafraichissement des IP bannies this.timeoutIDmajIPs = null } +/** + * Interface des pages. + */ PageAdmin.prototype.contenu = function() { - return '

Trolls

\ + return '\ +

Trolls

\

Un troll est un sujet à débat, en général une question, affiché sur la page principale.

\

Chaque semaine un troll est choisi au hasard parmis les trolls proposés et devient le troll de la semaine.

\
\ @@ -45,13 +52,18 @@ PageAdmin.prototype.contenu = function()
' } +/** + * Interface des pages. + */ PageAdmin.prototype.charger = function() { $("#page form#nouveauTroll").submit(function(){return false}) var thisPage = this + // la liste des trolls proposés par les ekMasters this.trolls = new Trolls(this.client, this.util, this.formateur) + this.waitEvent() this.majIPs() @@ -66,11 +78,21 @@ PageAdmin.prototype.charger = function() ) } +/** + * Interface des pages. + */ PageAdmin.prototype.decharger = function() { this.pageEvent.stopAttenteCourante() + + // supprime le rafraichissement période des ips + if (this.timeoutIDmajIPs) + clearTimeout(this.timeoutIDmajIPs) } +/** + * Post un troll, le contenu est lu à partir de "input.troll". + */ PageAdmin.prototype.posterTroll = function() { var thisPageAdmin = this @@ -195,13 +217,16 @@ PageAdmin.prototype.majIPs = function() } // rafraichissement toutes les minutes (je sais c'est mal) - // le problème est le rafraichissement des temps restant de bannissement qui doit êtrew fait du coté client + // le problème est le rafraichissement des temps restant de bannissement qui doit être fait du coté client thisPageAdmin.timeoutIDmajIPs = setTimeout(function(){ thisPageAdmin.majIPs() }, 60 * 1000) } } ) } +/** + * Débannie une ip donnée. + */ PageAdmin.prototype.deban = function(ip) { var thisPageAdmin = this @@ -224,54 +249,43 @@ PageAdmin.prototype.deban = function(ip) function(data) { ;; dumpObj(data) - switch(data["reply"]) + if(data["reply"] == "error") { - case "error" : - thisPageAdmin.util.messageDialogue(data["error_message"]) - break - case "ok" : - // obsolète : plus besoin - /* thisPageAdmin.majIPs() */ - break + thisPageAdmin.util.messageDialogue(data["error_message"]) } } } ) } +/** + * Attente d'événement de la part du serveur. + */ PageAdmin.prototype.waitEvent = function() { var thisPageAdmin = this this.pageEvent.waitEvent( function() { return { "last_troll" : thisPageAdmin.trolls.dernierTroll }}, - function(data) { - switch (data["reply"]) - { - case "troll_added" : - thisPageAdmin.trolls.ajouterTrollEvent(data) - break - case "troll_modified" : - thisPageAdmin.trolls.modifierTrollEvent(data) - break - case "troll_deleted" : - thisPageAdmin.trolls.supprimerTrollEvent(data) - break - case "banned_ips_refresh" : - thisPageAdmin.majIPs() - break - case "error" : + "troll_added" : function(data){ thisPageAdmin.trolls.ajouterTrollEvent(data) }, + "troll_modified" : function(data){ thisPageAdmin.trolls.modifierTrollEvent }, + "troll_deleted" : function(data){ thisPageAdmin.trolls.supprimerTrollEvent }, + "banned_ips_refresh" : function(data){ thisPageAdmin.majIPs() }, + "error" : + function(data) + { thisTrolls.util.messageDialogue(data["error_message"]) - break - } + } } ) } /////////////////////////////////////////////////////////////////////////////////////////////////// - +/** + * Représente un troll, pas grand chose finalement. + */ function Troll(content, author) { this.content = content diff --git a/js/pageMinichat.js b/js/pageMinichat.js index 53f4ab2..03024bc 100755 --- a/js/pageMinichat.js +++ b/js/pageMinichat.js @@ -301,20 +301,24 @@ Message.prototype.setRepondA = function(repondAJSON) /** * Renvoie les messages faisant partie d'une conversation. * @param messages l'ensemble des messages de la conversation - * @return les id des messages qui ont été mis en evidence sous la forme d'un hash (object) {id => bool} + * @return les id des messages qui ont été mis en evidence sous la forme + * d'un hash (object) {id => 0 | 1 | 2 | 3}. 1 : proprietaire, 2 : reponse directe, 3 : message repondu */ Message.prototype.getConversation = function(messages) { + var thisMessage = this + // les messages faisant partie de la conversation var messagesEnEvidence = {} - messagesEnEvidence[this.id] = true + messagesEnEvidence[this.id] = 1 // recherche les réponses (O(n)) for (var i = 0; i < messages.messages.length; i++) if (messages.messages[i].repondA.hasOwnProperty(this.id)) - messagesEnEvidence[messages.messages[i].id] = true + messagesEnEvidence[messages.messages[i].id] = messages.messages[i].auteurId == this.auteurId ? 1 : 2 + var premierNiveau = true var f = function(tabIds) { for(var id in tabIds) @@ -322,7 +326,8 @@ Message.prototype.getConversation = function(messages) var message = messages.messagesParId[id] if (message != undefined) { - messagesEnEvidence[id] = true + messagesEnEvidence[id] = message.auteurId == thisMessage.auteurId ? 1 : ( premierNiveau ? 3 : 0 ) + premierNiveau = false f (message.repondA) } } @@ -345,7 +350,6 @@ function Conversation(num, util, formateur, client) this.num = num // peut changer au cours de la vie de la conversation this.id = Math.floor(Math.random() * 1000000).toString(36) - this.messageOver = null // le message sur lequel se trouve le curseur this.util = util this.formateur = formateur this.client = client @@ -371,15 +375,6 @@ function Conversation(num, util, formateur, client) this.util.infoBulle("Créer un lien vers la conversation", $("#conversations #" + this.getId() + " .lien")) this.util.infoBulle("Fermer la conversation", $("#conversations #" + this.getId() + " .fermer")) } - - // enlève la mise en évidence pour la conversation - $("#conversations #" + this.getId()).hover( - function(){}, - function(event) - { - thisConversation.enleverMiseEnEvidence() - } - ) } /** @@ -388,7 +383,33 @@ function Conversation(num, util, formateur, client) Conversation.prototype.enleverMiseEnEvidence = function() { $("#conversations .message").removeClass("cache") - this.messageOver = null +} + +Conversation.prototype.colorerEntetes = function() +{ + var messagesReponse = "" + var messagesRepondu = "" + var messagesProprietaire = "" + for (var i = 0; i < this.messages.length; i++) + { + if (this.messages[i].appartientAuClient) + messagesProprietaire += "#mess" + this.messages[i].id.toString(36) + "," + else if (this.messages[i].estUneReponse) + messagesReponse += "#mess" + this.messages[i].id.toString(36) + "," + else if (this.messages[i].clientARepondu) + messagesRepondu += "#mess" + this.messages[i].id.toString(36) + "," + } + $(messagesReponse).addClass("reponse") + $(messagesRepondu).addClass("repondu") + $(messagesProprietaire).addClass("proprietaire") +} + +Conversation.prototype.decolorerEntetes = function() +{ + $("#" + this.getId() + " .message") + .removeClass("reponse") + .removeClass("repondu") + .removeClass("proprietaire") } /** @@ -625,25 +646,21 @@ Conversation.prototype.flush = function(funClickOuvrirConv) $("input.message").val(tag + " " + valCourant) thisConversation.util.setCaretToEnd($("form input.message")[0]) } - ) - - // Q : pourquoi pas un .hover ? - // R : simplement pour éviter que lorsqu'un message arrive cela n'affecte la conversation actuellement mise en évidence (uniquement pour Firefox) - $(".entete", this).mousemove( - function(e) + ) + + // mise en évidence de la conversation + $(".entete", this).hover( + function() { - if (this !== thisConversation.messageOver) - { - thisConversation.afficherConversation(idMess) - thisConversation.messageOver = this - } - } - ).hover( - function(){}, + thisConversation.decolorerEntetes() + thisConversation.afficherConversation(idMess) + }, // quand on sort de l'entête du message la mise en évidence est enlevée function() { - thisConversation.enleverMiseEnEvidence() + thisConversation.enleverMiseEnEvidence() + thisConversation.decolorerEntetes() + thisConversation.colorerEntetes() } ) } @@ -676,10 +693,25 @@ Conversation.prototype.afficherConversation = function(id) function() { var jq = $(this) - if (!mess.hasOwnProperty(parseInt(jq.attr("id").substr(4), 36))) + var statut = mess[parseInt(jq.attr("id").substr(4), 36)] + if (statut == undefined) jq.addClass("cache") - else + else + { jq.removeClass("cache") + switch (statut) + { + case 1 : + jq.addClass("proprietaire") + break; + case 2 : + jq.addClass("reponse") + break; + case 3 : + jq.addClass("repondu") + break; + } + } } ) } @@ -936,18 +968,10 @@ Messages.prototype.rafraichirMessages = function(vider) this.pageEvent.waitEvent( function() { return thisMessages.getJSONrafraichirMessages() }, - function(data) - { - if (vider) - { - thisMessages.viderMessages() - vider = false - } - - // en fonction du message - switch(data["reply"]) - { - case "new_troll" : + { + "new_troll" : + function(data) + { thisMessages.trollIdCourant = data["troll_id"] $("#trollCourant .troll").html(thisMessages.formateur.traitementComplet(data["content"])).unbind("click").click( function() @@ -957,9 +981,15 @@ Messages.prototype.rafraichirMessages = function(vider) ) $("#trollCourant .troll a[@rel*=lightbox]").lightBox() - break - - case "new_messages" : + }, + "new_messages" : + function(data) + { + if (vider) + { + thisMessages.viderMessages() + vider = false + } // ajoute les messages reçus à leur conversation respective for (var numConv = 0; numConv < data["conversations"].length; numConv++) { @@ -969,8 +999,7 @@ Messages.prototype.rafraichirMessages = function(vider) thisMessages.client.supprimerConversation(numConv - 1) } } - break - } + } } ) } diff --git a/modules/erl/euphorik_common.erl b/modules/erl/euphorik_common.erl new file mode 100644 index 0000000..12ac9cb --- /dev/null +++ b/modules/erl/euphorik_common.erl @@ -0,0 +1,36 @@ +% coding: utf-8 +% Copyright 2008 Grégory Burri +% +% This file is part of Euphorik. +% +% Euphorik is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% Euphorik is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with Euphorik. If not, see . +% +% Module avec plein de bordel utile à l'intérieur +% @author G.Burri + +-module(euphorik_common). +-export([serialize_ip/1, unserialize_ip/1]). + + +serialize_ip(undefined) -> + ""; +serialize_ip(IP) -> + lists:flatten(io_lib:format("~w.~w.~w.~w", tuple_to_list(IP))). + + +unserialize_ip(IP) -> + case io_lib:fread("~d.~d.~d.~d", IP) of + {ok, [A, B, C, D], []} -> {A, B, C, D}; + _ -> erreur + end. diff --git a/modules/erl/euphorik_daemon.erl b/modules/erl/euphorik_daemon.erl index be3b39c..dc33a7f 100755 --- a/modules/erl/euphorik_daemon.erl +++ b/modules/erl/euphorik_daemon.erl @@ -33,7 +33,7 @@ start(_A) -> loop() -> - % on attend une minute de plus pour prevenir une dérive nétive + % on attend une minute de plus pour prevenir une dérive négative timer:sleep(1000 * trunc(temps_prochaine_election() + 60)), euphorik_bd:elire_troll(), euphorik_daemon:loop(). diff --git a/modules/erl/euphorik_protocole.erl b/modules/erl/euphorik_protocole.erl index ae79d84..72a9157 100755 --- a/modules/erl/euphorik_protocole.erl +++ b/modules/erl/euphorik_protocole.erl @@ -318,7 +318,7 @@ wait_event_bd_page_chat() -> % Après 60 minutes de connexion, le client doit donc reétablir une connexion after 1000 * 60 * 60 -> timeout - end. + end. % Attent un événement concernant la page admin -- 2.45.2