From a379e52dea2609fd5daf0f030de3f3be4e0f8cfd Mon Sep 17 00:00:00 2001 From: afornerot Date: Fri, 12 Jun 2020 14:02:19 +0200 Subject: [PATCH] =?UTF-8?q?gestion=20de=20r=C3=A9ponse=20=C3=A0=20msg=20de?= =?UTF-8?q?=20chat=20(ref=20#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/ninegate-websocket.sh | 2 +- .../Resources/views/Page/pages.html.twig | 12 +- .../Resources/views/Page/viewurl.html.twig | 2 +- .../Controller/ChatController.php | 38 +++- .../WebsocketBundle/Entity/Message.php | 68 +++++++ .../Resources/views/Chat/client.html.twig | 171 +++++++++++++++++- .../WebsocketBundle/Topic/WebsocketTopic.php | 34 ++++ 7 files changed, 311 insertions(+), 16 deletions(-) diff --git a/src/ninegate-1.0/scripts/ninegate-websocket.sh b/src/ninegate-1.0/scripts/ninegate-websocket.sh index eeafe2ee..2f8fc83b 100755 --- a/src/ninegate-1.0/scripts/ninegate-websocket.sh +++ b/src/ninegate-1.0/scripts/ninegate-websocket.sh @@ -19,7 +19,7 @@ if [ "$1" == "restartifdown" ] && [ -n "${pid}" ] ; then restart="no" fi -if [[ "$restart" == "yes" ]]; then +if [ "$restart" == "yes" ] && [ "$1" != "stop" ] ; then echo WEBSOCKET = START cd /var/www/html/ninegate bin/console gos:websocket:server --port $websocket_portinterne -a $websocket_url --no-debug -n -q --env=prod & disown diff --git a/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/pages.html.twig b/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/pages.html.twig index a2518162..1d42fada 100644 --- a/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/pages.html.twig +++ b/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/pages.html.twig @@ -386,7 +386,7 @@ else { var myclass=""; if(forcereload) myclass="pageframereload"; - $("#pagecontainer").append(""); + $("#pagecontainer").append(""); } resizeFrame(); @@ -428,7 +428,7 @@ else { var myclass=""; if(forcereload) myclass="pageframereload"; - $("#pagecontainer").append(""); + $("#pagecontainer").append(""); } // Détruire le badge associé car normalement de fait on a lu les notif @@ -436,7 +436,6 @@ $("#badge-"+groupid).remove() } - // Cacher les actions possibles sur la page $("#menuupdate").hide(); $("#menushare").hide(); @@ -456,14 +455,17 @@ if(usage=="group") $("#menuwidgetgroup").show(); } - + // On resize les frame resizeFrame(); + + // Mettre le focus dans la frame + //$("#page-"+id).contentWindow.focus(); } // Affichages des pages function showGoto(url) { - $("#pagecontainer").append(""); + $("#pagecontainer").append(""); // On resize les frame resizeFrame(); diff --git a/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/viewurl.html.twig b/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/viewurl.html.twig index f24dc29e..e4882547 100644 --- a/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/viewurl.html.twig +++ b/src/ninegate-1.0/src/Cadoles/PortalBundle/Resources/views/Page/viewurl.html.twig @@ -22,7 +22,7 @@ {% endif %}
- +
{% endblock %} diff --git a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Controller/ChatController.php b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Controller/ChatController.php index a245ce2a..c67e5c85 100644 --- a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Controller/ChatController.php +++ b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Controller/ChatController.php @@ -55,8 +55,8 @@ class ChatController extends Controller } - // Récupération des message du groupe - $messages=$em->getRepository("CadolesWebsocketBundle:Message")->findBy(["group"=>$group],["submitdate"=>"DESC"],30); + // Récupération des message parent du groupe + $messages=$em->getRepository("CadolesWebsocketBundle:Message")->findBy(["group"=>$group,"parent"=>null],["submitdate"=>"DESC"],30); foreach($messages as $message) { $haveread = ($message->getReaders()->contains($user)); $havesee = ($message->getSees()->contains($user)); @@ -69,6 +69,20 @@ class ChatController extends Controller $em->persist($message); $em->flush(); } + + foreach($message->getChilds() as $child) { + $haveread = ($child->getReaders()->contains($user)); + $havesee = ($child->getSees()->contains($user)); + + $child->setHaveread($haveread); + $child->setHavesee($havesee); + + if(!$haveread) { + $child->addReader($this->getUser()); + $em->persist($child); + $em->flush(); + } + } } // Création du formulaire @@ -141,8 +155,8 @@ class ChatController extends Controller $usergroup=$em->getRepository("CadolesCoreBundle:UserGroup")->findOneBy(["group"=>$group,"user"=>$user]); if(!$usergroup) die(); - // On récupere les messages - $messages=$em->getRepository("CadolesWebsocketBundle:Message")->findBy(["group"=>$group],["submitdate"=>"DESC"],10); + // On récupere les messages parent + $messages=$em->getRepository("CadolesWebsocketBundle:Message")->findBy(["group"=>$group,"parent"=>null],["submitdate"=>"DESC"],10); foreach($messages as $message) { $tmp=[]; @@ -150,9 +164,21 @@ class ChatController extends Controller $tmp["message"]=$message->getTopic(); $tmp["submitdate"]=$message->getSubmitdate(); $tmp["userid"]=$message->getUser()->getId(); - $tmp["userlastname"]=$message->getUser()->getLastname(); - $tmp["userfirstname"]=$message->getUser()->getFirstname(); + $tmp["userlastname"]=$message->getUser()->getLastname()." ".$message->getUser()->getFirstname(); $tmp["useravatar"]=$message->getUser()->getAvatar(); + $tmp["childs"]=[]; + + foreach($message->getChilds() as $child) { + $tmpchild=[]; + $tmpchild["id"]=$child->getId(); + $tmpchild["message"]=$child->getTopic(); + $tmpchild["submitdate"]=$child->getSubmitdate(); + $tmpchild["userid"]=$child->getUser()->getId(); + $tmpchild["userlastname"]=$child->getUser()->getLastname()." ".$child->getUser()->getFirstname(); + $tmpchild["useravatar"]=$child->getUser()->getAvatar(); + + array_push($tmp["childs"],$tmpchild); + } array_push($output,$tmp); } diff --git a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Entity/Message.php b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Entity/Message.php index e9b692a2..801ede44 100644 --- a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Entity/Message.php +++ b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Entity/Message.php @@ -40,6 +40,16 @@ class Message */ private $group; + /** + * @ORM\ManyToOne(targetEntity="Cadoles\WebsocketBundle\Entity\message", inversedBy="childs") + */ + private $parent; + + /** + * @ORM\OneToMany(targetEntity="Cadoles\WebsocketBundle\Entity\Message", mappedBy="parent", cascade={"persist"}, orphanRemoval=true) + */ + protected $childs; + /** * @ORM\ManyToMany(targetEntity="Cadoles\CoreBundle\Entity\User", inversedBy="messagereaders", cascade={"persist"}) * @ORM\JoinTable(name="messageuserread", @@ -265,4 +275,62 @@ class Message { return $this->sees; } + + /** + * Set parent + * + * @param \Cadoles\WebsocketBundle\Entity\message $parent + * + * @return Message + */ + public function setParent(\Cadoles\WebsocketBundle\Entity\message $parent = null) + { + $this->parent = $parent; + + return $this; + } + + /** + * Get parent + * + * @return \Cadoles\WebsocketBundle\Entity\message + */ + public function getParent() + { + return $this->parent; + } + + /** + * Add child + * + * @param \Cadoles\WebsocketBundle\Entity\Message $child + * + * @return Message + */ + public function addChild(\Cadoles\WebsocketBundle\Entity\Message $child) + { + $this->childs[] = $child; + + return $this; + } + + /** + * Remove child + * + * @param \Cadoles\WebsocketBundle\Entity\Message $child + */ + public function removeChild(\Cadoles\WebsocketBundle\Entity\Message $child) + { + $this->childs->removeElement($child); + } + + /** + * Get childs + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getChilds() + { + return $this->childs; + } } diff --git a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Resources/views/Chat/client.html.twig b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Resources/views/Chat/client.html.twig index 316a5315..79163199 100644 --- a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Resources/views/Chat/client.html.twig +++ b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Resources/views/Chat/client.html.twig @@ -46,6 +46,33 @@ line-height: 12px; margin-bottom: 10px; } + .msgreplys { + margin-bottom:10px; + } + .messagereply { + padding:0px; + border-top: 1px solid #{{ colorbodyfont }}; + font-size:12px; + } + + .btnreplymessage { + padding: 5px; + background-color: #{{ colorbodyfont }}; + color : #{{ colorbodyback }}; + border-radius:5px; + cursor:pointer; + } + .btnreplymessage:hover { + color : #{{ colorbodyback }}; + } + .replymessage { display:none} + .replymessage textarea { + width:100%; + margin:20px 0px 5px 0px; + height:150px; + } + .sendreply { width:100%} + .bootstrap-switch{ margin-top:5px; } @@ -104,6 +131,39 @@ {{message.submitdate|date('d/m/Y H:i')}}
{{message.topic | raw}}
+ +
+ {% for child in message.childs | reverse %} + {% set classread="" %} + {% if not child.haveread %} + {% set classread="message-toread" %} + {% endif %} + + {% set classsee="" %} + {% if child.havesee %} + {% set classsee="message-see" %} + {% endif %} + +
+ {{child.topic | raw | nl2br }} + +
{{ child.user.lastname }} {{ child.user.firstname }}
+ {{child.submitdate|date('d/m/Y H:i')}} + {% if fgmanager or child.user == app.user %} + + {% endif %} + {% if not child.havesee %} + + {% endif %} +
+ {% endfor %} +
+ + Répondre +
+ + Envoyer +
{% endfor %} @@ -316,6 +376,12 @@ html+="
" html+="
"+payload.msg.lastname+"
"+new Date(payload.msg.submitdate.date).toLocaleDateString("fr-FR", dateoptions)+"
"; html+="
"+payload.msg.message+"
"; + html+="
"; + html+="Répondre"; + html+="
"; + html+=""; + html+="Envoyer"; + html+="
"; html+="
"; html+=""; $(".mychat").prepend(html); @@ -323,6 +389,24 @@ //console.log("Received message by "+payload.msg.userid+" = ",payload.msg); } + if(payload.msgreply) { + // Si on reçoit une réponse forcement le parent est de nouveau visible + $("#message-"+payload.msgreply.parent).removeClass ("message-see"); + + // On ajout la réponse + html ="
"; + html+=nl2br(payload.msgreply.message); + html+="
"+payload.msgreply.lastname+"
"; + html+=""+new Date(payload.msgreply.submitdate.date).toLocaleDateString("fr-FR", dateoptions)+""; + if(payload.msgreply.userid=={{app.user.id}} || '{{ fgmanager }}'=='1') { + html+=""; + } + html+=""; + html+="
"; + + $("#msgreplys-"+payload.msgreply.parent).prepend(html); + } + if(payload.log) { console.log("Received message", payload.log); } @@ -366,7 +450,15 @@ isdeco=true; }); } - + + function nl2br (str, is_xhtml) { + if (typeof str === 'undefined' || str === null) { + return ''; + } + var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '
' : '
'; + return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); + } + function switchsee() { $(".message-see").hide(); if($("#unsee").bootstrapSwitch('state')) { @@ -515,8 +607,52 @@ } } }); - } + + $(document).on('click', '.btnreplymessage', function(){ + btnreplymessage($(this).data("id")); + }); + + function btnreplymessage(id) { + $("#replymessage-"+id).toggle(); + $("#replymessage-"+id+" textarea").focus(); + } + + $(document).on('click', '.sendreply', function(){ + sendreply($(this).data("id")); + }); + + function sendreply(id) { + try { + // Flager que l'envoit c'est fait + tosend=false; + $("#replymessage-"+id+" a").html("Envoyer"); + $("#replymessage-"+id+" a").removeClass("btn-danger"); + $("#replymessage-"+id+" a").css('cursor','auto'); + + // Push envent sur le websocket + var data = "

"+$("#replymessage-"+id+" textarea").val()+"

"; + event={mykey: "{{userkey}}", type: "reply", message: data, parent: id}; + session.publish("websocket/channel/{{groupid}}", event); + + $("#replymessage-"+id+" textarea").val(""); + $("#replymessage-"+id).hide(); + } + catch(error) { + // L'envoi ne s'est pas fait + console.log("Retry to send"); + + // On flag le fait de retenter l'envoit à la reconnexion + tosend=true; + + // On signal que l'envoi est en cours sur le bouton + $("#replymessage-"+id+" a").html("Envoi en cours"); + $("#replymessage-"+id+" a").addClass("btn-danger"); + $("#replymessage-"+id+" a").css('cursor','progress'); + } + + } + $(document).on('click', '#listtoavatar img', function(){ var mail = ";"+$(this).data("mail"); $("#mailto").val($("#mailto").val().replace(mail, "")); @@ -524,6 +660,8 @@ }); function recuplastmsg() { + console.log("recuplastmsg"); + $.ajax({ method: "POST", url: "{{ path('cadoles_websocket_message_list') }}", @@ -534,20 +672,47 @@ $.each(datas, function(i,data) { // Le message a-t-il été déposé durant la déconnexion ? if(!$("#message-"+data.id).length) { - html ="
"; + html ="
"; html+="
"; html+="
"; if(data.userid=={{app.user.id}} || '{{ fgmanager }}'=='1') { html+=""; } + if (!data.havesee) { + html+=""; + } html+="
"; html+="
" html+="
"+data.userlastname+"
"+new Date(data.submitdate.date).toLocaleDateString("fr-FR", dateoptions)+"
"; html+="
"+data.message+"
"; + html+="
"; + + html+="
"; + html+="Répondre"; + html+="
"; + html+=""; + html+="Envoyer"; + html+="
"; html+="
"; html+="
"; $(".mychat").prepend(html); } + + $.each(data.childs, function(i,child) { + if(!$("#message-"+child.id).length) { + html ="
"; + html+=nl2br(child.message); + html+="
"+child.userlastname+"
"; + html+=""+new Date(child.submitdate.date).toLocaleDateString("fr-FR", dateoptions)+""; + if(child.userid=={{app.user.id}} || '{{ fgmanager }}'=='1') { + html+=""; + } + html+=""; + html+="
"; + + $("#msgreplys-"+data.id).prepend(html); + } + }); }); } }); diff --git a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Topic/WebsocketTopic.php b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Topic/WebsocketTopic.php index 06463597..f9e800e4 100644 --- a/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Topic/WebsocketTopic.php +++ b/src/ninegate-1.0/src/Cadoles/WebsocketBundle/Topic/WebsocketTopic.php @@ -151,6 +151,40 @@ class WebsocketTopic implements TopicInterface $topic->broadcast(['msg' => $return]); } + if($event["type"]=="reply") { + $parent=$this->em->getRepository("CadolesWebsocketBundle:Message")->find($event["parent"]); + if($parent) { + $message=new Message(); + $message->setTopic($event["message"]); + $message->setUser($user); + $message->setGroup($group); + $message->setParent($parent); + $this->em->persist($message); + $this->em->flush(); + + // Si commentaire sur une message : il faut replacer le message en unsee pour tt le monde + foreach($parent->getSees() as $see) { + $parent->removeSee($see); + } + $this->em->persist($parent); + $this->em->flush(); + + + $return["id"]=$message->getId(); + $return["lastname"]=$user->getLastname()." ".$user->getFirstname(); + $return["avatar"]=$user->getAvatar(); + $return["submitdate"]=$message->getSubmitdate(); + $return["message"]=$event["message"]; + $return["userid"]=$user->getId(); + $return["parent"]=$event["parent"]; + + //this will broadcast the message to ALL subscribers of this topic. + $topic->broadcast(['msgreply' => $return]); + } + else + $topic->broadcast(['log' => "Message parent introuvable"]); + } + if($event["type"]=="del") { $message=$this->em->getRepository("CadolesWebsocketBundle:Message")->find($event["id"]); if($message&&($usergroup->getFgmanager()||$message->getUser()==$user||$user->getRole()=="ROLE_ADMIN"||$user->getRole()=="ROLE_MODO" )) {