From 13c9c8bd3dd98e53962ed9a85deeea46c0844caf Mon Sep 17 00:00:00 2001 From: afornerot Date: Fri, 15 Mar 2024 15:44:29 +0100 Subject: [PATCH] websocket init --- .env | 4 +- config/routes.yaml | 7 +- config/services.yaml | 9 +- docker-compose.yml | 5 +- misc/script/reconfigure.sh | 2 + src/Controller/ScrumController.php | 2 + src/Controller/ScrumissueController.php | 9 ++ src/Entity/Scrumissue.php | 43 ++++++++ src/Entity/User.php | 39 +++++++- src/Entity/Userpoker.php | 82 ++++++++++++++++ src/Repository/ScrumRepository.php | 8 ++ templates/Include/javascript.js.twig | 2 + templates/Scrum/table.html.twig | 125 +++++++++++++++++++++--- templates/Websocket/sample.html.twig | 16 ++- templates/base.html.twig | 4 + 15 files changed, 332 insertions(+), 25 deletions(-) create mode 100644 src/Entity/Userpoker.php diff --git a/.env b/.env index b9f88d3..467eed5 100644 --- a/.env +++ b/.env @@ -40,9 +40,9 @@ MAILER_NOREPLY=noreply@noreply.fr # WEBSOCKET -WSS_USE=0 +WSS_USE=1 WSS_PORT=5588 - +WSS_URL=ws://localhost:5588 # Proxy PROXY_USE=0 diff --git a/config/routes.yaml b/config/routes.yaml index ac6b046..54b7586 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -69,7 +69,7 @@ app_sonde: #== Wss ================================================================================================================== app_wss_sample: - path: /user/wss/sampble + path: /user/wss/sample defaults: { _controller: App\Controller\WebsocketController:sample } #== Crop ================================================================================================================= @@ -345,3 +345,8 @@ app_scrumissue_ctrlchange: app_scrumissue_view: path: /user/scrumissue/view/{id} defaults: { _controller: App\Controller\ScrumissueController:view } + +#== Poker ============================================================================================================= +app_poker_get: + path: /user/poker/{userid}/{issueid} + defaults: { _controller: App\Controller\ScrumissueController:getpoker } diff --git a/config/services.yaml b/config/services.yaml index 329d12c..094281e 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -34,7 +34,7 @@ parameters: wssuse: '%env(resolve:WSS_USE)%' wssport: '%env(resolve:WSS_PORT)%' - wssurl: 'wss://%env(resolve:APP_WEBURL)%/wss%env(resolve:APP_ALIAS)%' + wssurl: '%env(resolve:WSS_URL)%' proxyUse: '%env(resolve:PROXY_USE)%' proxyHost: '%env(resolve:PROXY_HOST)%' @@ -104,4 +104,9 @@ services: app.gieta.service: public: true class: App\Service\giteaService - arguments: ["@session","%giteaUrl%"] \ No newline at end of file + arguments: ["@session","%giteaUrl%"] + + App\Websocket\MessageHandler: + public: true + arguments: + - "@service_container" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index df00e4c..1807f2a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,14 +22,15 @@ services: container_name: ninegitea-app image: reg.cadoles.com/envole/ninegitea ports: - - "8005:80" + - "8005:80" + - "5588:5588" volumes: - ./src:/app/src:delegated - ./templates:/app/templates:delegated - ./config:/app/config:delegated - ./.env:/app/.env:delegated - - ./.env.local:/app/.env.local:delegated - ./public/uploads:/app/public/uploads:delegated + - ./misc:/app/misc:delegated adminer: image: adminer diff --git a/misc/script/reconfigure.sh b/misc/script/reconfigure.sh index f872628..069e496 100755 --- a/misc/script/reconfigure.sh +++ b/misc/script/reconfigure.sh @@ -12,4 +12,6 @@ composer install --no-interaction bin/console d:s:u --force --complete +bin/console app:Websocket & + exec $@ \ No newline at end of file diff --git a/src/Controller/ScrumController.php b/src/Controller/ScrumController.php index 66e0cf0..6f95abd 100755 --- a/src/Controller/ScrumController.php +++ b/src/Controller/ScrumController.php @@ -424,6 +424,7 @@ class ScrumController extends AbstractController { $em = $this->getDoctrine()->getManager(); $fgcsv = $request->get("fgcsv"); + $fgpoker = $request->get("fgpoker"); // Récupérer les repos de gitea $scrum=$em->getRepository("App:Scrum")->findOneBy(["id"=>$id]); @@ -594,6 +595,7 @@ class ScrumController extends AbstractController "filterexcludes" => $filterexcludes, "filterassignees" => $filterassignees, "showfilters" => $showfilters, + "fgpoker" => $fgpoker, ]); } diff --git a/src/Controller/ScrumissueController.php b/src/Controller/ScrumissueController.php index fc40f9a..83ce8cd 100755 --- a/src/Controller/ScrumissueController.php +++ b/src/Controller/ScrumissueController.php @@ -280,4 +280,13 @@ class ScrumissueController extends AbstractController return new JsonResponse(false); } + + public function getpoker($userid,$issueid,Request $request) { + return new Response(0); + + } + + public function setpoker($userid,$issueid,Request $request) { + + } } diff --git a/src/Entity/Scrumissue.php b/src/Entity/Scrumissue.php index 0abea4f..efb57a3 100644 --- a/src/Entity/Scrumissue.php +++ b/src/Entity/Scrumissue.php @@ -2,6 +2,8 @@ namespace App\Entity; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -85,6 +87,16 @@ class Scrumissue */ private $scrumsprint; + /** + * @ORM\OneToMany(targetEntity="Userpoker", mappedBy="scrumissue", cascade={"persist"}, orphanRemoval=true) + */ + private $userpokers; + + public function __construct() + { + $this->userpokers = new ArrayCollection(); + } + public function getId(): ?int { return $this->id; @@ -234,6 +246,37 @@ class Scrumissue return $this; } + /** + * @return Collection|Userpoker[] + */ + public function getUserpokers(): Collection + { + return $this->userpokers; + } + + public function addUserpoker(Userpoker $userpoker): self + { + if (!$this->userpokers->contains($userpoker)) { + $this->userpokers[] = $userpoker; + $userpoker->setScrumissue($this); + } + + return $this; + } + + public function removeUserpoker(Userpoker $userpoker): self + { + if ($this->userpokers->contains($userpoker)) { + $this->userpokers->removeElement($userpoker); + // set the owning side to null (unless already changed) + if ($userpoker->getScrumissue() === $this) { + $userpoker->setScrumissue(null); + } + } + + return $this; + } + } \ No newline at end of file diff --git a/src/Entity/User.php b/src/Entity/User.php index 90b4d4b..accc419 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -85,6 +85,11 @@ class User implements UserInterface, \Serializable */ private $preference; + /** + * @ORM\OneToMany(targetEntity="Userpoker", mappedBy="user", cascade={"persist"}, orphanRemoval=true) + */ + private $userpokers; + /** * @ORM\ManyToMany(targetEntity="Group", inversedBy="users", cascade={"persist"}) * @ORM\JoinTable(name="usergroupe", @@ -107,6 +112,7 @@ class User implements UserInterface, \Serializable { $this->groups = new ArrayCollection(); $this->scrums = new ArrayCollection(); + $this->userpokers = new ArrayCollection(); } public function getUsername(): ?string @@ -172,7 +178,7 @@ class User implements UserInterface, \Serializable public function getDisplayname() { - return $this->firstname." ".$this->lastname; + return $this->username; } public function setId(int $id): self @@ -336,4 +342,35 @@ class User implements UserInterface, \Serializable return $this; } + + /** + * @return Collection|Userpoker[] + */ + public function getUserpokers(): Collection + { + return $this->userpokers; + } + + public function addUserpoker(Userpoker $userpoker): self + { + if (!$this->userpokers->contains($userpoker)) { + $this->userpokers[] = $userpoker; + $userpoker->setUser($this); + } + + return $this; + } + + public function removeUserpoker(Userpoker $userpoker): self + { + if ($this->userpokers->contains($userpoker)) { + $this->userpokers->removeElement($userpoker); + // set the owning side to null (unless already changed) + if ($userpoker->getUser() === $this) { + $userpoker->setUser(null); + } + } + + return $this; + } } diff --git a/src/Entity/Userpoker.php b/src/Entity/Userpoker.php new file mode 100644 index 0000000..f494ee2 --- /dev/null +++ b/src/Entity/Userpoker.php @@ -0,0 +1,82 @@ +id; + } + + public function getNb(): ?int + { + return $this->nb; + } + + public function setNb(int $nb): self + { + $this->nb = $nb; + + return $this; + } + + public function getScrumissue(): ?Scrumissue + { + return $this->scrumissue; + } + + public function setScrumissue(?Scrumissue $scrumissue): self + { + $this->scrumissue = $scrumissue; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): self + { + $this->user = $user; + + return $this; + } + +} \ No newline at end of file diff --git a/src/Repository/ScrumRepository.php b/src/Repository/ScrumRepository.php index 4ed4498..e7d9913 100644 --- a/src/Repository/ScrumRepository.php +++ b/src/Repository/ScrumRepository.php @@ -265,6 +265,14 @@ class ScrumRepository extends ServiceEntityRepository } $scrumissue->setGiteajson(json_decode(json_encode($giteaissue), true)); + // Si le ticket est lié à un sprint on s'assure que ce sprint est bien lié au milestone du ticket + if($scrumissue->getScrumsprint()) { + if($scrumissue->getScrumsprint()->getGiteamilestone()!=$scrumissue->getGiteamilestone()) { + $scrumissue->setScrumsprint(null); + } + } + + $this->_em->persist($scrumissue); $this->_em->flush(); diff --git a/templates/Include/javascript.js.twig b/templates/Include/javascript.js.twig index a2dfc95..3ff6fe2 100644 --- a/templates/Include/javascript.js.twig +++ b/templates/Include/javascript.js.twig @@ -33,6 +33,8 @@ function ModalLoad(idmodal,title,path) { } {% if wssuse %} + console.log("pouet"); + function subscribe(channeltype,channelkey,userkey) { console.log("== SUBSCRIBE "+channeltype+"-"+channelkey+" with userkey "+userkey); conn.send(JSON.stringify({ diff --git a/templates/Scrum/table.html.twig b/templates/Scrum/table.html.twig index 2547fba..c4f37ec 100644 --- a/templates/Scrum/table.html.twig +++ b/templates/Scrum/table.html.twig @@ -32,6 +32,10 @@ {% block body %}
+ {% if fgpoker %} +
+ {% endif %} +
@@ -124,7 +128,7 @@ {% endif %} {% endfor %} -
+
@@ -149,12 +153,17 @@ Type N° Titre + {% if (not wssuse or not fgpoker) %} Equipe Priorité - Poid Affecté à - Statut Etiquettes + {% else %} + Poker + {% endif %} + Statut + Poid + @@ -183,7 +192,7 @@ {% set types = "" %} {% set datateams = "" %} {% set datatypes = "" %} - {% set prioritys = ''~giteaprioritys|last~'' %} + {% set prioritys = (not giteaprioritys?'':''~giteaprioritys|last~'') %} {% set dataprioritys = ','~giteaprioritys|last %} {% set labels = "" %} {% set datalabels = "" %} @@ -210,7 +219,7 @@ {% set dataassignees=dataassignees~','~assignee.username %} {% endfor %} - + @@ -225,15 +234,11 @@ {{ giteaissue.title }} + + {% if (not wssuse or not fgpoker) %} {{ teams|raw }} {{ prioritys|raw }} - - - - {% set dataorder="" %} {% for assignee in giteaissue.assignees %} {% set dataorder=dataorder~assignee.username %} @@ -244,8 +249,19 @@ {% endfor %} - {{ statut }} {{ labels|raw }} + {% else %} + +
+ + {% endif %} + + {{ statut }} + + + {% endif %} {% endfor %} @@ -846,4 +862,89 @@ $("#mycontent").show(); }); + + {% if wssuse and fgpoker %} + var conn; + + function connect() { + conn = new WebSocket("{{wssurl}}"); + + conn.onopen = function(e) { + console.log("== CONNECT"); + {% set userkey = "" %} + {% if app.user %} + {% set userkey = app.user.apikey %} + {%endif%} + + subscribe("home",{{id}},"{{userkey}}"); + sendMessage({command: "alive"}); + }; + + conn.onmessage = function(e) { + ret=JSON.parse(e.data); + console.log("MESSAGE REU ="+ret.command); + + switch(ret.command) { + case "alive" : + if(!$('#online'+ret.from.id).length) { + img=''; + $("#online").append(img); + + $("tr").each(function(){ + line=$(this); + issueid=$(this).data("id"); + url="{{path("app_poker_get",{userid:"xxx",issueid:"yyy"})}}"; + url=url.replace("xxx",ret.from.id); + url=url.replace("yyy",issueid); + $.ajax({ + method: "POST", + url: url, + async: false, + success: function(data) { + html ='
'; + html+=''; + html+=''; + html+='
'; + line.find(".pokertd").append(html); + }, + }); + + }) + } + + if(ret.from.id!={{app.user.id}}) { + console.log("meto"); + sendMessage({command: "meto"}); + } + break; + + case "adead" : + $('#online'+ret.from.id).remove(); + $('[data-user='+ret.from.id+']').remove(); + break; + + case "meto" : + if(!$('#online'+ret.from.id).length) { + html=''; + $("#online").append(html); + $(".pokertd").append(html); + } + break; + } + }; + + conn.onclose = function(e) { + console.log("== DISCONNECT"); + $('#online img').remove(); + console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason); + setTimeout(function() { connect(); }, 1000); + }; + } + + connect(); + + $("body").on("input", ".pokervalue", function () { + console.log($(this).val()); + }); + {% endif %} {% endblock %} \ No newline at end of file diff --git a/templates/Websocket/sample.html.twig b/templates/Websocket/sample.html.twig index a74146d..6bd9e9b 100644 --- a/templates/Websocket/sample.html.twig +++ b/templates/Websocket/sample.html.twig @@ -1,15 +1,20 @@ +{% extends 'base.html.twig' %} + +{% block body %} +{{wssurl}}
online
+{% endblock %} +{% block localjavascript %} {% if wssuse %} - -{% endif %} \ No newline at end of file +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/templates/base.html.twig b/templates/base.html.twig index 4178bae..001fed7 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -152,6 +152,10 @@ {% endblock %} + +