ADD Lien vers les conversations (pas fini)
authorGreg Burri <greg.burri@gmail.com>
Thu, 17 Apr 2008 21:14:57 +0000 (21:14 +0000)
committerGreg Burri <greg.burri@gmail.com>
Thu, 17 Apr 2008 21:14:57 +0000 (21:14 +0000)
css/1/pageMinichat.css
js/euphorik.js
js/pageMinichat.js
modules/erl/euphorik_minichat.erl
modules/erl/euphorik_minichat_conversation.erl
modules/erl/euphorik_protocole.erl

index e24092c..3a02bf9 100755 (executable)
 \r
 #page.minichat div.message a {\r
        font-weight: bold;\r
 \r
 #page.minichat div.message a {\r
        font-weight: bold;\r
+}
+
+#page.minichat div.message .lienConv {
+       color: #db960f;
+       font-weight: bold;
+       cursor: pointer
+}
+
+#page.minichat div.message .lienConv:hover {
+       color: #f1c060
 }\r
 \r
 #page.minichat .date {\r
 }\r
 \r
 #page.minichat .date {\r
        display: none;
 }
 
        display: none;
 }
 
+#page.minichat #conversations .titre .lien {
+       float: right
+}
+
+#page.minichat #conversations .titre .lien,
 #page.minichat #conversations .titre .next,
 #page.minichat #conversations .titre .prev,
 #page.minichat #conversations .titre .numPage {
 #page.minichat #conversations .titre .next,
 #page.minichat #conversations .titre .prev,
 #page.minichat #conversations .titre .numPage {
        padding-left: 5px;
 }
 
        padding-left: 5px;
 }
 
+#page.minichat #conversations .titre .lien:hover,
 #page.minichat #conversations .titre .next:hover,
 #page.minichat #conversations .titre .prev:hover,
 #page.minichat #conversations .titre .numPage:hover {
        background-color: #7c6e2e
 }
 #page.minichat #conversations .titre .next:hover,
 #page.minichat #conversations .titre .prev:hover,
 #page.minichat #conversations .titre .numPage:hover {
        background-color: #7c6e2e
 }
-
 \r
 #page.minichat #pages {\r
        margin-top: 10px;\r
 \r
 #page.minichat #pages {\r
        margin-top: 10px;\r
index dfd398d..5ce9357 100755 (executable)
@@ -299,7 +299,24 @@ Formateur.prototype.getSmilesHTML = function()
 
 Formateur.prototype.traitementComplet = function(M, pseudo)
 {
 
 Formateur.prototype.traitementComplet = function(M, pseudo)
 {
-   return this.traiterSmiles(this.traiterURL(this.remplacerBalisesHTML(M), pseudo))
+   return this.traiterLiensConv(this.traiterSmiles(this.traiterURL(this.remplacerBalisesHTML(M), pseudo)))
+}
+
+/**
+  * Transforme les liens en entités clickables.
+  * Un lien vers une conversation permet d'ouvrire celle ci, elle se marque comme ceci dans un message :
+  * "{5F}" ou 5F est la racine de la conversation.
+  * Ce lien sera transformer en <span class="lienConv">{5F}</span> pouvant être clické pour créer la conv 5F.
+  */
+Formateur.prototype.traiterLiensConv = function(M)
+{
+   return M.replace(
+      /\{\w+\}/g,
+      function(lien)
+      {
+         return "<span class=\"lienConv\">" + lien + "</span>"
+      }
+   )
 }
 \r
 /**\r
 }
 \r
 /**\r
index ed1a46c..454b357 100755 (executable)
@@ -132,7 +132,7 @@ PageMinichat.prototype.getXMLMessage = function(pseudo, message, repondA)
       {
          var nodeReponse = XMLDocument.createElement("reponse")
          nodeReponse.setAttribute("id", repondA[i])
       {
          var nodeReponse = XMLDocument.createElement("reponse")
          nodeReponse.setAttribute("id", repondA[i])
-         nodeReponses.appendChild(nodeReponse)      
+         nodeReponses.appendChild(nodeReponse)
       }
    }
    
       }
    }
    
@@ -291,7 +291,7 @@ Message.prototype.getConversation = function(messages)
   * @param numConv le numéro (appelé id) de la conversation
   * @param formateur outil permettant la mise en forme du texte des messages
   */
   * @param numConv le numéro (appelé id) de la conversation
   * @param formateur outil permettant la mise en forme du texte des messages
   */
-function Conversation(num, util, formateur, funFermer)
+function Conversation(num, util, formateur)
 {
    var thisConversation = this
 
 {
    var thisConversation = this
 
@@ -306,7 +306,7 @@ function Conversation(num, util, formateur, funFermer)
    jQuery("#conversations").append(
       '<div id="' + this.getId() + '" class="conversation">\
       <div class="titre">' +
    jQuery("#conversations").append(
       '<div id="' + this.getId() + '" class="conversation">\
       <div class="titre">' +
-         (funFermer == undefined ? '' : '<div class="fermer">x</div>') +
+         (num == 0 ? '' : '<div class="fermer">x</div><div class="lien">c</div>') +
          '<span class="next">&lt;</span><span class="numPage">1</span><span class="prev">&gt;</span>\
          </div>\
       </div>'
          '<span class="next">&lt;</span><span class="numPage">1</span><span class="prev">&gt;</span>\
          </div>\
       </div>'
@@ -321,15 +321,6 @@ function Conversation(num, util, formateur, funFermer)
          thisConversation.messageOver = null
       }
    )
          thisConversation.messageOver = null
       }
    )
-   
-   // suppression de la conversation
-   if (funFermer != undefined)
-      jQuery("#conversations #" + this.getId() + " .titre .fermer").click(
-         function()
-         {
-            funFermer(thisConversation.num)
-         }
-      )
 }
 
 /**
 }
 
 /**
@@ -337,13 +328,43 @@ function Conversation(num, util, formateur, funFermer)
   * @pageCourante la page courante
   * @dernierePage true si c'est la dernière page sinon false
   */
   * @pageCourante la page courante
   * @dernierePage true si c'est la dernière page sinon false
   */
-Conversation.prototype.setPage = function(pageCourante, dernierePage)
+Conversation.prototype.eventsPage = function(pageCourante, dernierePage)
 {
    jQuery("#conversations #" + this.getId() + " .numPage").text(pageCourante)
    jQuery("#conversations #" + this.getId() + " .next").css("display", pageCourante == 1 ? "none" : "inline")
    jQuery("#conversations #" + this.getId() + " .prev").css("display", dernierePage ? "none" : "inline")
 }
 
 {
    jQuery("#conversations #" + this.getId() + " .numPage").text(pageCourante)
    jQuery("#conversations #" + this.getId() + " .next").css("display", pageCourante == 1 ? "none" : "inline")
    jQuery("#conversations #" + this.getId() + " .prev").css("display", dernierePage ? "none" : "inline")
 }
 
+/**
+  * Evenement déclanché lors de l'insertion du lien de la conversation dans le message courant.
+  */
+Conversation.prototype.eventLien = function(fun)
+{
+   var thisConversation = this
+   
+   jQuery("#conversations #" + this.getId() + " .titre .lien").click(
+      function()
+      {
+         fun(thisConversation.num)
+      }
+   )
+}
+
+/**
+  * Evenement déclanché lors de la fermeture de la conversation.
+  */
+Conversation.prototype.eventFermer = function(fun)
+{
+   var thisConversation = this
+   
+   jQuery("#conversations #" + this.getId() + " .titre .fermer").click(
+      function()
+      {
+         fun(thisConversation.num)
+      }
+   )
+}
+
 /**
   * @funNext appelé lorsque l'on passe à la page suivante (de 2 à 1 par exemple)
   * @funPrev appelé lorsque l'on passe à la page précédente (de 1 à 2 par exemple)
 /**
   * @funNext appelé lorsque l'on passe à la page suivante (de 2 à 1 par exemple)
   * @funPrev appelé lorsque l'on passe à la page précédente (de 1 à 2 par exemple)
@@ -391,13 +412,14 @@ Conversation.prototype.viderMessages = function()
   * d'afficher les messages non-affichés.
   * @param funClickExtract fonction (fun(numMess)) appellée lors du clic sur un bouton "extraire"
   */
   * d'afficher les messages non-affichés.
   * @param funClickExtract fonction (fun(numMess)) appellée lors du clic sur un bouton "extraire"
   */
-Conversation.prototype.flush = function(funClickExtract)
+Conversation.prototype.flush = function(funClickExtract, funClickLienConv)
 {
    var thisConversation = this
 
    var idDernierMessageAffiche = jQuery("#conversations #" + this.getId() + " div:first").attr("id")
    if (idDernierMessageAffiche == undefined) idDernierMessageAffiche = "0"
       
 {
    var thisConversation = this
 
    var idDernierMessageAffiche = jQuery("#conversations #" + this.getId() + " div:first").attr("id")
    if (idDernierMessageAffiche == undefined) idDernierMessageAffiche = "0"
       
+   // construction de l'XHTML des messages
    var XHTML = ""
    for (var i = this.messages.length - 1; i >= 0; i--)
       if (parseInt(this.messages[i].id, 36) > parseInt(idDernierMessageAffiche, 36))
    var XHTML = ""
    for (var i = this.messages.length - 1; i >= 0; i--)
       if (parseInt(this.messages[i].id, 36) > parseInt(idDernierMessageAffiche, 36))
@@ -405,13 +427,13 @@ Conversation.prototype.flush = function(funClickExtract)
          var message = this.messages[i]
          var XHTMLrepondA = ""
          for (var id in message.repondA)
          var message = this.messages[i]
          var XHTMLrepondA = ""
          for (var id in message.repondA)
-            XHTMLrepondA += this.formateur.traitementComplet(message.repondA[id].pseudo) + "> "
+            XHTMLrepondA += this.formateur.traitementComplet(message.repondA[id].pseudo) + "&gt; "
          XHTMLrepondA = "<span class=\"repondA\">" + XHTMLrepondA + "</span>"
          
          XHTML += 
             "<div id=\"" + message.id + "\" class=\"" + (parseInt(message.id, 36) % 2 == 0 ? "messagePair" : "messageImpair") + " message" +
                (this.messages[i].appartientAuClient ? " proprietaire" : "")  + (this.messages[i].clientARepondu ? " repondu" : "") + (this.messages[i].estUneReponse ? " reponse" : "") + (this.messages[i].systeme ? " systeme" : "") +
          XHTMLrepondA = "<span class=\"repondA\">" + XHTMLrepondA + "</span>"
          
          XHTML += 
             "<div id=\"" + message.id + "\" class=\"" + (parseInt(message.id, 36) % 2 == 0 ? "messagePair" : "messageImpair") + " message" +
                (this.messages[i].appartientAuClient ? " proprietaire" : "")  + (this.messages[i].clientARepondu ? " repondu" : "") + (this.messages[i].estUneReponse ? " reponse" : "") + (this.messages[i].systeme ? " systeme" : "") +
-            "\" &gt;" +
+            "\">" +
                "<div class=\"extraire\">&gt;</div>" +
                "[<span class=\"date\">" + message.date + "</span>]" +
                "<span class=\"pseudo\">" + this.formateur.traitementComplet(message.pseudo) + "</span>:" +
                "<div class=\"extraire\">&gt;</div>" +
                "[<span class=\"date\">" + message.date + "</span>]" +
                "<span class=\"pseudo\">" + this.formateur.traitementComplet(message.pseudo) + "</span>:" +
@@ -426,6 +448,7 @@ Conversation.prototype.flush = function(funClickExtract)
    if (myLightbox != null)
       myLightbox.updateImageList()
    
    if (myLightbox != null)
       myLightbox.updateImageList()
    
+   // enlève les messages exedentaires
    var nbMessagesAffiche = jQuery("#conversations #" + this.getId() + " .message").size()
    if (nbMessagesAffiche > this.nbMessageMax)
       jQuery("#conversations #" + this.getId() + " .message").slice(this.nbMessageMax, nbMessagesAffiche).empty();
    var nbMessagesAffiche = jQuery("#conversations #" + this.getId() + " .message").size()
    if (nbMessagesAffiche > this.nbMessageMax)
       jQuery("#conversations #" + this.getId() + " .message").slice(this.nbMessageMax, nbMessagesAffiche).empty();
@@ -434,6 +457,16 @@ Conversation.prototype.flush = function(funClickExtract)
    jQuery("#conversations #" + this.getId() + " .message").filter(function(){return parseInt(jQuery(this).attr("id"), 36) > parseInt(idDernierMessageAffiche, 36)}).each(
       function()
       {
    jQuery("#conversations #" + this.getId() + " .message").filter(function(){return parseInt(jQuery(this).attr("id"), 36) > parseInt(idDernierMessageAffiche, 36)}).each(
       function()
       {
+         jQuery(".lienConv", this).click(
+            function(event)
+            {          
+               // FIXME : ya pas mieux ?
+               var racine = jQuery(event.target).text()
+               funClickLienConv(racine.substring(1, racine.length - 1))
+               return false
+            }
+         )
+         
          jQuery(this).click(
             function(event)
             {
          jQuery(this).click(
             function(event)
             {
@@ -515,6 +548,8 @@ Conversation.prototype.supprimer = function()
   */
 function Messages(client, formateur, util)
 {
   */
 function Messages(client, formateur, util)
 {
+   var thisMessages = this
+
    this.client = client
    this.formateur = formateur
    this.util = util
    this.client = client
    this.formateur = formateur
    this.util = util
@@ -604,6 +639,13 @@ Messages.prototype.ajouterMessage = function(element, numConversation)
          function(num) // fermeture de la conversation
          {
             thisMessages.supprimerConversation(num)
          function(num) // fermeture de la conversation
          {
             thisMessages.supprimerConversation(num)
+         },
+         function(num) // insertion du lien vers la conversation
+         {
+               thisPage.util.replaceSelection(
+                  jQuery("form input.message")[0],
+                  "{" + thisMessages.client.conversations[num-1].racine + "}"
+               )
          }
       )
    }
          }
       )
    }
@@ -611,11 +653,15 @@ Messages.prototype.ajouterMessage = function(element, numConversation)
    this.conversations[numConversation].ajouterMessage(message)
 }
 
    this.conversations[numConversation].ajouterMessage(message)
 }
 
-Messages.prototype.nouvelleConversation = function(num, funFermer)
+Messages.prototype.nouvelleConversation = function(num, funFermer, funLien)
 {
    var thisMessages = this
 
 {
    var thisMessages = this
 
-   this.conversations[num] = new Conversation(num, this.util, this.formateur, funFermer)
+   this.conversations[num] = new Conversation(num, this.util, this.formateur)
+   if (funFermer != undefined)
+      this.conversations[num].eventFermer(funFermer)
+   if (funLien != undefined)
+      this.conversations[num].eventLien(funLien)
 
    this.conversations[num].setFunPage(
       function(num) // page suivante
 
    this.conversations[num].setFunPage(
       function(num) // page suivante
@@ -684,13 +730,17 @@ Messages.prototype.flush = function(numConv)
 {
    var thisMessages = this
 
 {
    var thisMessages = this
 
-   this.conversations[numConv].flush
-   (
+   this.conversations[numConv].flush(
       // fonction appelée lors de la demande d'extraction d'une conversation
       function(idMess)
       {
          if (thisMessages.client.ajouterConversation(idMess))
             thisMessages.rafraichirMessages(true)
       // fonction appelée lors de la demande d'extraction d'une conversation
       function(idMess)
       {
          if (thisMessages.client.ajouterConversation(idMess))
             thisMessages.rafraichirMessages(true)
+      },
+      function(racine) // appelé lorsqu'un utilisateur click sur un lien vers une conversation
+      {
+         if (thisMessages.client.ajouterConversation(racine))
+            thisMessages.rafraichirMessages(true)
       }
    )
 }
       }
    )
 }
@@ -721,7 +771,7 @@ Messages.prototype.rafraichirMessages = function(vider)
    if (vider)
       this.idDernierMessage = null\r
       
    if (vider)
       this.idDernierMessage = null\r
       
-   //this.util.xmlVersAction(this.getXMLrafraichirMessages()).action.dump()
+   this.util.xmlVersAction(this.getXMLrafraichirMessages()).action.dump("Client")
    this.attenteCourante = jQuery.ajax({
          type: "POST",
          url: "request",
    this.attenteCourante = jQuery.ajax({
          type: "POST",
          url: "request",
@@ -730,7 +780,7 @@ Messages.prototype.rafraichirMessages = function(vider)
          success:
             function(data)
             {            \r
          success:
             function(data)
             {            \r
-               //thisMessages.util.serializer.serializeToString(data).dump()\r
+               thisMessages.util.serializer.serializeToString(data).dump("Serveur")\r
             
                if (vider)
                   thisMessages.viderMessages()
             
                if (vider)
                   thisMessages.viderMessages()
@@ -751,7 +801,7 @@ Messages.prototype.rafraichirMessages = function(vider)
                      
                      thisMessages.ajouterMessages(messages, numConv)
                      
                      
                      thisMessages.ajouterMessages(messages, numConv)
                      
-                     thisMessages.conversations[numConv].setPage(
+                     thisMessages.conversations[numConv].eventsPage(
                         numConv == 0 ? thisMessages.client.pagePrincipale : thisMessages.client.conversations[numConv - 1].page,
                         jQuery("autresPages", this).text() != "true"
                      )
                         numConv == 0 ? thisMessages.client.pagePrincipale : thisMessages.client.conversations[numConv - 1].page,
                         jQuery("autresPages", this).text() != "true"
                      )
index 4268fef..92f5922 100755 (executable)
@@ -13,6 +13,7 @@
    messages/3,
    message_by_id/1,
    messages_by_ids/1,
    messages/3,
    message_by_id/1,
    messages_by_ids/1,
+   message_existe/1,
    reponses/0,
    repond_a/1,
    nb_page/1,
    reponses/0,
    repond_a/1,
    nb_page/1,
@@ -364,7 +365,15 @@ messages_by_ids(Ids) ->
          %io:format("~s~n", [qlc:info(Query)]),
          qlc:e(Query)
       end
          %io:format("~s~n", [qlc:info(Query)]),
          qlc:e(Query)
       end
-   )).\r
+   )).
+   
+
+% Est-ce qu'un message existe ? Renvoie un boolean.
+% TODO : ya pas plus simple ?
+message_existe(Id) ->
+   resultat_transaction(mnesia:transaction(fun() ->
+      length(qlc:e(qlc:q([E#minichat.id || E <- mnesia:table(minichat), E#minichat.id =:= Id]))) =:= 1
+   end)).\r
   
    
 % Renvoie le nombre de page total en fonction du nombre de message par page N 
   
    
 % Renvoie le nombre de page total en fonction du nombre de message par page N 
index abe4368..d455d94 100755 (executable)
@@ -27,7 +27,7 @@
 % Message est le message de type #minichat et Parents une liste d'Id.
 % Plus est un bool. Si Plus vaut true alors il y a encore des messages.
 % Si il n'y a pas de nouveaux message alors la fonction est bloquante et attend un nouveau message.
 % Message est le message de type #minichat et Parents une liste d'Id.
 % Plus est un bool. Si Plus vaut true alors il y a encore des messages.
 % Si il n'y a pas de nouveaux message alors la fonction est bloquante et attend un nouveau message.
-% @spec conversations([{integer(), integer()}, integer(), integer(), integer()) -> [Conversation()]
+% @spec conversations([{integer(), integer()}], integer(), integer(), integer()) -> [Conversation()]
 conversations(Racines, N, D, P) ->
    % écoute des nouveaux messages
    case subscribe(minichat, 2) of
 conversations(Racines, N, D, P) ->
    % écoute des nouveaux messages
    case subscribe(minichat, 2) of
@@ -113,14 +113,19 @@ mise_en_forme_conversations([{Principale, Plus_principale} | Conversations]) ->
 % Ajoute les parents de chaque message.
 % @spec mise_en_forme_conversation([integer()]) -> [{integer(), [integer()]}]
 mise_en_forme_conversation(Messages) ->
 % Ajoute les parents de chaque message.
 % @spec mise_en_forme_conversation([integer()]) -> [{integer(), [integer()]}]
 mise_en_forme_conversation(Messages) ->
-   map(
-      fun(Id) ->
-         {ok, Message} = euphorik_minichat:message_by_id(Id),
-         {Message, parents(Id)}
+   lists:foldl(
+      fun(Id, Acc) ->
+         case euphorik_minichat:message_by_id(Id) of
+            {ok, Message} ->
+               [{Message, parents(Id)} | Acc];
+            _ ->
+               Acc
+         end
       end,
       end,
+      [],
       Messages
    ).
       Messages
    ).
-   
+      
    
 % Renvoie une liste de conversations, le première élément correspond à la conversation principale.
 % Les autres éléments sont des tuples {C, Cn, X}, voir conversation/4 pour plus d'infos.
    
 % Renvoie une liste de conversations, le première élément correspond à la conversation principale.
 % Les autres éléments sont des tuples {C, Cn, X}, voir conversation/4 pour plus d'infos.
index f56a335..dba48e2 100755 (executable)
@@ -83,12 +83,20 @@ profile(Action) ->
             Email = case xmerl_xpath:string("email", Action) of [#xmlElement{content = [#xmlText{value = E}]}] -> E; _ -> undefined end,
             Css = case xmerl_xpath:string("css", Action) of [#xmlElement{content = [#xmlText{value = C}]}] -> C; _ -> undefined end,
             Page_principale = case xmerl_xpath:string("pagePrincipale", Action) of [#xmlElement{content = [#xmlText{value = P3}]}] -> list_to_integer(P3); _ -> undefined end,
             Email = case xmerl_xpath:string("email", Action) of [#xmlElement{content = [#xmlText{value = E}]}] -> E; _ -> undefined end,
             Css = case xmerl_xpath:string("css", Action) of [#xmlElement{content = [#xmlText{value = C}]}] -> C; _ -> undefined end,
             Page_principale = case xmerl_xpath:string("pagePrincipale", Action) of [#xmlElement{content = [#xmlText{value = P3}]}] -> list_to_integer(P3); _ -> undefined end,
-            Conversations = lists:map(
-               fun(Conv) ->
+            Conversations = lists:foldl(
+               fun(Conv, Acc) ->
                   [#xmlElement{content = [#xmlText{value = Id_racine_str}]}] = xmerl_xpath:string("racine", Conv),
                   [#xmlElement{content = [#xmlText{value = Page_conv_str}]}] = xmerl_xpath:string("page", Conv), 
                   [#xmlElement{content = [#xmlText{value = Id_racine_str}]}] = xmerl_xpath:string("racine", Conv),
                   [#xmlElement{content = [#xmlText{value = Page_conv_str}]}] = xmerl_xpath:string("page", Conv), 
-                  {erlang:list_to_integer(Id_racine_str, 36), list_to_integer(Page_conv_str)}
+                  Message_id = erlang:list_to_integer(Id_racine_str, 36),
+                  % vérification de la validité de l'id
+                  Message_existe = euphorik_minichat:message_existe(Message_id),
+                  if  Message_existe ->
+                        [{Message_id, list_to_integer(Page_conv_str)} | Acc];
+                     true ->
+                        Acc
+                  end
                end,
                end,
+               [],
                xmerl_xpath:string("conversation", Action)
             ),
             case euphorik_minichat:set_profile(Cookie, Login, Password, Pseudo, Email, Css, Page_principale, Conversations) of
                xmerl_xpath:string("conversation", Action)
             ),
             case euphorik_minichat:set_profile(Cookie, Login, Password, Pseudo, Email, Css, Page_principale, Conversations) of