weight in scrum view

This commit is contained in:
afornerot 2024-02-23 12:35:29 +01:00
parent c61312bc3d
commit 072afb2a1c
5 changed files with 189 additions and 113 deletions

View File

@ -599,23 +599,57 @@ class ScrumController extends AbstractController
public function stat($id,Request $request) public function stat($id,Request $request)
{ {
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$data=$em->getRepository($this->entity)->find($id); $scrum=$em->getRepository($this->entity)->find($id);
if(!$data) return $this->redirectToRoute($this->route); if(!$scrum) return $this->redirectToRoute($this->route);
$firstcolumn=$em->getRepository('App:Scrumcolumn')->findOneBy(["scrum"=>$data], ['rowid' => 'ASC']); $em->getRepository("App:Scrum")->getGitea($scrum,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels);
if(!$firstcolumn) return $this->redirectToRoute($this->route);
$em->getRepository("App:Scrum")->getGitea($data,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels);
// Préférences utilisateur // Préférences utilisateur
$filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id); $filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id);
$filtersprints = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtersprints",$id); $filtersprints = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtersprints",$id);
$filterbynumber = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterbynumber",$id); $filterbynumber = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterbynumber",$id);
$showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id); $showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id);
$tbestim=$this->getEstim($scrum);
return $this->render($this->render.'stat.html.twig', [
'useheader' => true,
'usesidebar' => false,
'usetitle' => $scrum->getName(),
'giteamilestones' => $giteamilestones,
'sprints' => $scrum->getScrumsprints(),
'filtermilestones' => $filtermilestones,
'filtersprints' => $filtersprints,
'filterbynumber' => $filterbynumber,
'showfilters' => $showfilters,
$this->data => $scrum,
'tbestim' => $tbestim,
]);
}
public function info($id,Request $request)
{
$em = $this->getDoctrine()->getManager();
$scrum=$em->getRepository($this->entity)->find($id);
if(!$scrum) return $this->redirectToRoute($this->route);
$em->getRepository("App:Scrum")->getGitea($scrum,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels);
$tbestim=$this->getEstim($scrum);
$output=[];
$output["tbestim"]=$tbestim;
return new JsonResponse($output);
}
private function getEstim($scrum) {
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$firstcolumn=$em->getRepository('App:Scrumcolumn')->findOneBy(["scrum"=>$scrum], ['rowid' => 'ASC']);
if(!$firstcolumn) return $this->redirectToRoute($this->route);
// Création du tableau des issues // Création du tableau des issues
$issues=$data->getScrumissues(); $issues=$scrum->getScrumissues();
$tbissues=[]; $tbissues=[];
$tbcols=[]; $tbcols=[];
$tbjals=[]; $tbjals=[];
@ -642,10 +676,15 @@ class ScrumController extends AbstractController
$nmjal=($issue->getGiteaMilestonename()?$issue->getGiteaMilestonename():"Aucun"); $nmjal=($issue->getGiteaMilestonename()?$issue->getGiteaMilestonename():"Aucun");
$nmspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():"Aucun"); $nmspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():"Aucun");
// Idgiteas
$gicol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteaid():$firstcolumn->getGiteaid());
$gijal=($issue->getGiteaMilestone()?$issue->getGiteaMilestone():-100);
if(!array_key_exists($idjal,$tbestim)) { if(!array_key_exists($idjal,$tbestim)) {
$tbestim[$idjal] = [ $tbestim[$idjal] = [
"rowjal" => $rowjal, "rowjal" => $rowjal,
"idjal" => $idjal, "idjal" => $idjal,
"gijal" => $gijal,
"nmjal" => $nmjal, "nmjal" => $nmjal,
"nbjrs" => 0, "nbjrs" => 0,
"nbiss" => 0, "nbiss" => 0,
@ -669,6 +708,7 @@ class ScrumController extends AbstractController
$tbestim[$idjal]["columns"][$idcol] = [ $tbestim[$idjal]["columns"][$idcol] = [
"rowcol" => $rowcol, "rowcol" => $rowcol,
"idcol" => $idcol, "idcol" => $idcol,
"gicol" => $gicol,
"nmcol" => $nmcol, "nmcol" => $nmcol,
"color" => ($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteajson()["color"]:$firstcolumn->getGiteajson()["color"]), "color" => ($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteajson()["color"]:$firstcolumn->getGiteajson()["color"]),
"nbjrs" => 0, "nbjrs" => 0,
@ -680,6 +720,7 @@ class ScrumController extends AbstractController
$tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol] = [ $tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol] = [
"rowcol" => $rowcol, "rowcol" => $rowcol,
"idcol" => $idcol, "idcol" => $idcol,
"gicol" => $gicol,
"nmcol" => $nmcol, "nmcol" => $nmcol,
"color" => ($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteajson()["color"]:$firstcolumn->getGiteajson()["color"]), "color" => ($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteajson()["color"]:$firstcolumn->getGiteajson()["color"]),
"nbjrs" => 0, "nbjrs" => 0,
@ -698,69 +739,20 @@ class ScrumController extends AbstractController
$tbestim[$idjal]["sprints"][$idspr]["nbiss"]++; $tbestim[$idjal]["sprints"][$idspr]["nbiss"]++;
$tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol]["nbiss"]++; $tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol]["nbiss"]++;
$this->formatDec($tbestim[$idjal]["nbjrs"]);
$this->formatDec($tbestim[$idjal]["columns"][$idcol]["nbjrs"]);
$this->formatDec($tbestim[$idjal]["sprints"][$idspr]["nbjrs"]);
$this->formatDec($tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol]["nbjrs"]);
} }
return $this->render($this->render.'stat.html.twig', [ return $tbestim;
'useheader' => true, }
'usesidebar' => false,
'usetitle' => $data->getName(),
'giteamilestones' => $giteamilestones,
'sprints' => $data->getScrumsprints(),
'filtermilestones' => $filtermilestones,
'filtersprints' => $filtersprints,
'filterbynumber' => $filterbynumber,
'showfilters' => $showfilters,
$this->data => $data,
'tbestim' => $tbestim,
]);
}
public function info($id,Request $request) private function formatDec(&$number) {
{ if(strpos(strval($number), '.') !== false) $number=number_format($number,1);
$em = $this->getDoctrine()->getManager(); else $number=intval($number);
$viewclosed = $request->getSession()->get("viewclosed");
// Rechercher du scrum en cours
$scrum=$em->getRepository("App:Scrum")->find($id);
if(!$scrum) return new JsonResponse(['message' => 'No Issue'], 403);
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
$weights=[];
foreach($giteaissues as $giteaissue) {
$scrumissue=$em->getRepository("App:Scrumissue")->findOneBy(["scrum"=>$scrum,"giteaid"=>$giteaissue->id]);
if($scrumissue) {
if($giteaissue->milestone) $milestoneid=$giteaissue->milestone->id;
else $milestoneid=-100;
if($scrumissue->getScrumsprint()) $sprintid=$milestoneid."-".$scrumissue->getScrumsprint()->getId();
else $sprintid=$milestoneid."-".-100;
if(!array_key_exists($milestoneid,$weights)) {
$weights[$milestoneid]=[
"id" => $milestoneid,
"weight"=>0,
"sprints"=>[],
];
}
if(!array_key_exists($sprintid,$weights[$milestoneid]["sprints"])) {
$weights[$milestoneid]["sprints"][$sprintid]=[
"id" => $sprintid,
"weight"=>0
];
}
$weights[$milestoneid]["weight"]+=$scrumissue->getWeight();
$weights[$milestoneid]["sprints"][$sprintid]["weight"]+=$scrumissue->getWeight();
//dump($weights[$milestoneid]["sprints"][$sprintid]["weight"]);
}
}
$output=[];
$output["weights"]=$weights;
return new JsonResponse($output);
} }
protected function getErrorForm($id,$form,$request,$data,$mode) { protected function getErrorForm($id,$form,$request,$data,$mode) {

View File

@ -158,6 +158,9 @@ class ScrumissueController extends AbstractController
$giteaissue->comments=$this->giteaservice->getIssueComments($repoowner,$reponame,$giteaissue->number); $giteaissue->comments=$this->giteaservice->getIssueComments($repoowner,$reponame,$giteaissue->number);
$giteaissue->statuslife=$issue->getScrumcolumn()->getName(); $giteaissue->statuslife=$issue->getScrumcolumn()->getName();
$giteaissue->weight=$issue->getWeight();
$giteaissue->nineid=$issue->getId();
$giteaissue->sprint=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():null); $giteaissue->sprint=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():null);
foreach($giteaissue->comments as $keycomment => $comment) { foreach($giteaissue->comments as $keycomment => $comment) {
$giteaissue->comments[$keycomment]->body=$this->giteaservice->markdown("/".$scrum->getGiteajson()["full_name"],"comment",$giteaissue->comments[$keycomment]->body); $giteaissue->comments[$keycomment]->body=$this->giteaservice->markdown("/".$scrum->getGiteajson()["full_name"],"comment",$giteaissue->comments[$keycomment]->body);

View File

@ -37,6 +37,7 @@
<div id='issuediv{{issue.number}}' class='d-flex'> <div id='issuediv{{issue.number}}' class='d-flex'>
<div class='issuecontent' class='d-flex flex-column'> <div class='issuecontent' class='d-flex flex-column'>
<div class="card mb-3"> <div class="card mb-3">
<div class="card-header d-flex"> <div class="card-header d-flex">
<div class="flex-grow-1">{{issue.user.login}}</div> <div class="flex-grow-1">{{issue.user.login}}</div>
@ -65,6 +66,14 @@
<div class='pl-3 issuedetail'> <div class='pl-3 issuedetail'>
<a target="_blank" class="btn btn-success w-100 mb-3" href="{{issue.html_url}}" style="zoom:120%">Modifier dans Gitea</a> <a target="_blank" class="btn btn-success w-100 mb-3" href="{{issue.html_url}}" style="zoom:120%">Modifier dans Gitea</a>
<div class="card mb-3">
<div class="modissu card-header d-flex" style="cursor:pointer">
<div class="flex-grow-1"><i class="fas fa-weight-hanging"></i></div>
<div>{{ issue.weight }}</div>
</div>
</div>
<div class='card mb-3'> <div class='card mb-3'>
<div class="card-header">Statut</div> <div class="card-header">Statut</div>
<div class="card-body"> <div class="card-body">
@ -192,5 +201,64 @@
</div> </div>
</div> </div>
<div id="mymodalissue" class="modal" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Estimation</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group ">
<label class="control-label required" for="issu_weight">
Poid
</label>
<input type="hidden" id="modal-issueid" name="modal-issueid" required="required" class=" form-control" value="">
<input type="number" placeholder="0.0" step="0.1" id="modal-issueweight" name="modal-issueweight" required="required" class=" form-control" value="">
</div>
<button id="issu_update" class="btn btn-success">Enregistrer</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block localjavascript %}
$(document).on('click','.modissu',function(){
$.ajax({
method: "POST",
url: "{{path("app_scrumissue_info")}}",
data: {
id:{{issue.nineid}},
},
success: function(data) {
$("#modal-issueweight").val(data.weight);
$("#mymodalissue").modal('show');
$("#modal-issueweight").focus();
},
});
});
$("#issu_update").click(function(){
$.ajax({
method: "POST",
url: "{{path("app_scrumissue_update")}}",
data: {
id:{{issue.nineid}},
weight:$("#modal-issueweight").val(),
},
success: function(data) {
parent.$(".issue{{issue.nineid}}-weight").html($("#modal-issueweight").val());
window.parent.refreshinfo();
location.reload();
},
error: function (request, status, error) {
$("#mymodalissue").modal('hide');
}
});
});
{% endblock %} {% endblock %}

View File

@ -68,7 +68,7 @@
<h1>{{ scrum.name }}</h1> <h1>{{ scrum.name }}</h1>
<div class="d-flex flex-column mt-4"> <div id="tbestim" class="d-flex flex-column mt-4">
{% for jalon in tbestim %} {% for jalon in tbestim %}
{% if jalon.nbjrs>0 %} {% if jalon.nbjrs>0 %}

View File

@ -139,23 +139,7 @@
</div> </div>
</div> </div>
<div style="" class="mt-5"> <div id="tbestim" class="mt-5">
{% for jalon in tbestim %}
<table style="color:var(--colorftbodydark);zoom:75%; width:100%; border:1px solid var(--colorbgbodylight)">
<tr>
<td class="pl-1">{{jalon.nmjal}}</td>
<td class="pr-1" style="width:30px;text-align:right;"><span id="totaljal{{jalon.gijal}}" class="totalweight">{{jalon.nbjrs}}</span></td>
</tr>
{% for sprint in jalon.sprints %}
{% if not loop.first or sprint.idspr!=-100 %}
<tr>
<td class="pl-1">{{sprint.nmspr}}</td>
<td class="pr-1" style="width:30px;text-align:right;"><span id="totalspr{{jalon.gijal}}-{{sprint.idspr}}" class="totalweight">{{sprint.nbjrs}}</span></td>
</tr>
{% endif %}
{% endfor %}
</table>
{% endfor %}
</div> </div>
</div> </div>
@ -180,12 +164,18 @@
{% for jalon in column.jalons %} {% for jalon in column.jalons %}
{% for sprint in jalon.sprints %} {% for sprint in jalon.sprints %}
<div class="card mb-3" data-column="{{column.gicol}}" data-milestone="{{jalon.gijal}}" data-sprint="{{sprint.idspr}}" data-millestonesprint="{{jalon.gijal~"-"~sprint.idspr}}"> <div class="card mb-3" data-column="{{column.gicol}}" data-milestone="{{jalon.gijal}}" data-sprint="{{sprint.idspr}}" data-millestonesprint="{{jalon.gijal~"-"~sprint.idspr}}">
<div class="card-header p-1" style="font-size:16px"> <div class="card-header p-1 d-flex" style="font-size:16px">
JALON = {{jalon.nmjal}} <div>
{% if sprint.idspr!=-100 %} JALON = {{jalon.nmjal}}
<br> {% if sprint.idspr!=-100 %}
SPRINT = {{sprint.nmspr}} <br>
{% endif %} SPRINT = {{sprint.nmspr}}
{% endif %}
</div>
<div class="ml-auto" data-weight="{{column.gicol~"-"~jalon.gijal~"-"~sprint.idspr}}">
</div>
</div> </div>
<div class="card-body p-1"> <div class="card-body p-1">
@ -562,25 +552,6 @@
$("#textfilters").html(textfilters); $("#textfilters").html(textfilters);
} }
function refreshinfo() {
$.ajax({
method: "POST",
url: "{{path("app_scrum_info",{id:scrum.id})}}",
success: function(data) {
$(".totalweight").html("0");
Object.entries(data.weights).forEach(entry => {
const [keyj, jalon] = entry;
$("#totaljal"+jalon.id).html(jalon.weight.toFixed(1).replace(/\.0$/, ''));
Object.entries(jalon.sprints).forEach(entry => {
const [keys, sprint] = entry;
$("#totalspr"+sprint.id).html(sprint.weight.toFixed(1).replace(/\.0$/, ''));
});
});
}
});
}
$(document).on('click','.modissu',function(){ $(document).on('click','.modissu',function(){
$(".modal-title").html("#"+$(this).data("giteaid")+" - "+$(this).data("giteatitle")); $(".modal-title").html("#"+$(this).data("giteaid")+" - "+$(this).data("giteatitle"));
$("#modal-issueid").val($(this).data("issue")); $("#modal-issueid").val($(this).data("issue"));
@ -897,8 +868,7 @@
start: function( event, ui ) { start: function( event, ui ) {
$(".submenu").hide(); $(".submenu").hide();
}, },
update: function( event, ui ) { stop: function( event, ui ) {
id=$(ui.item).data("issue"); id=$(ui.item).data("issue");
oldcolumn=$(ui.item).data("column"); oldcolumn=$(ui.item).data("column");
oldmilestone=$(ui.item).data("milestone"); oldmilestone=$(ui.item).data("milestone");
@ -974,6 +944,49 @@
}); });
function refreshinfo() {
$.ajax({
method: "POST",
url: "{{path("app_scrum_info",{id:scrum.id})}}",
success: function(data) {
html="";
$("[data-weight]").html("");
Object.entries(data.tbestim).forEach(entry => {
const [keyj, jalon] = entry;
html+='<table style="color:var(--colorftbodydark);zoom:75%; width:100%; border:1px solid var(--colorbgbodylight)">';
html+='<tr>';
html+='<td class="pl-1">'+jalon.nmjal+'</td>';
html+='<td class="pr-1" style="width:30px;text-align:right;">'+jalon.nbjrs+'</span></td>';
html+='</tr>';
nofirst=false;
Object.entries(jalon.sprints).forEach(entry => {
const [keys, sprint] = entry;
if(nofirst || sprint.idspr!=-100) {
html+='<tr>';
html+='<td class="pl-1">'+sprint.nmspr+'</td>';
html+='<td class="pr-1" style="width:30px;text-align:right;">'+sprint.nbjrs+'</span></td>';
html+='</tr>';
}
Object.entries(sprint.columns).forEach(entry => {
const [keys, column] = entry;
$("[data-weight="+column.gicol+"-"+jalon.gijal+"-"+sprint.idspr+"]").html(column.nbjrs);
});
nofirst=true;
});
html+='</table>';
});
$("#tbestim").html(html);
}
});
}
function issuhover(btn,idissu) { function issuhover(btn,idissu) {
$(".submenu").hide(); $(".submenu").hide();
$("#submenu"+idissu).css("display","flex"); $("#submenu"+idissu).css("display","flex");