Files
ninemine/templates/home/home.html.twig
2025-07-06 16:29:23 +02:00

309 lines
9.6 KiB
Twig
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends 'base.html.twig' %}
{% block localstyle %}
<style>
content {
padding:0px;
}
.containerScrum {
display:none;
}
.containerFiltre{
display:flex;
width:250px;
flex-direction:column;
background-color: var(--bs-dark);
}
.containerStatus{
display:flex;
width:10000px;
overflow-x:scrool;
}
.colStatus {
width:300px;
padding: 15px 10px 0px 10px;
}
h2 {
font-size:18px;
text-align: center;
}
.card {
margin-bottom:5px;
}
.versionCard {
background-color: var(--bs-gray-100);
padding: 5px 5px 0px 5px;
}
.versionBody {
min-height:60px;
}
h5 {
color: var(--bs-primary-text-emphasis);
font-size:16px;
padding-left:10px;
}
.issueCard {
padding:5px;
}
.issueHeader {
display: flex;
align-items: center;
}
.issueId{
padding: 0px 5px 0px 2px;
cursor: move;
}
.issueSubject{
zoom: 70%;
flex-grow: 1;
}
</style>
{% endblock %}
{% block body %}
<div class='containerScrum'>
<div class='containerFiltre'>
<label>Sprints</label>
<select id="sprintFilter" class="select2 form-select" multiple="true" tabindex="-1" aria-hidden="true">
<option value="None">Aucun</option>
{% for sprint in project.redmine.sprints|reverse %}
<option value="{{sprint.id}}">{{sprint.name}}</option>
{% endfor %}
</select>
<label>Versions</label>
<select id="versionFilter" class="select2 form-select" multiple="true" tabindex="-1" aria-hidden="true">
<option value="None">Aucune</option>
{% for version in project.redmine.versions|reverse %}
<option value="{{version.id}}">{{version.name}}</option>
{% endfor %}
</select>
<button id="toggleIssueBody" class="btn btn-secondary btn-sm mt-3">Afficher Détail</button>
</div>
<div class='containerStatus'>
{% for status in project.redmine.issue_statuses %}
<div class='colStatus'>
<h2>{{ status.name }}</h2>
{% for sprint in project.redmine.sprints|reverse %}
<div class='sprintCard sprintCard{{sprint.id}} card' style='margin-bottom:20px'>
<div class='card-header'>
Sprint = {{ sprint.name }}
</div>
{% for version in project.redmine.versions|reverse %}
<div class='versionCard versionCard{{version.id}} card-body'>
<h5>Version = {{ version.name }}</h5>
<div class='versionBody' data-id='{{status.id}}-{{sprint.id}}-{{version.name}}'></div>
</div>
{% endfor %}
<div class='versionCard versionCardNone card-body'>
<h5>Version = Aucune</h5>
<div class='versionBody' data-id='{{status.id}}-{{sprint.id}}-'></div>
</div>
</div>
{% endfor %}
<div class='sprintCard sprintCardNone card'>
<div class='card-header'>
Sprint Aucun
</div>
{% for version in project.redmine.versions|reverse %}
<div class='versionCard versionCard{{version.id}} card-body'>
<h5>Version = {{ version.name }}</h5>
<div class='versionBody' data-id='{{status.id}}--{{version.name}}'></div>
</div>
{% endfor %}
<div class='versionCard versionCardNone card-body'>
<h5>Version = Aucune</h5>
<div class='versionBody' data-id='{{status.id}}--'></div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class='viewIssue'>
</div>
{% for issue in project.issues %}
<div class="issueCard card" data-status='{{issue.redmine.status.id}}' data-sprint='{{issue.rowsprint}}' data-version='{{issue.rowversion}}'>
<div class='issueHeader'>
<div class='issueId'>#{{issue.id}}</div>
<div class='issueSubject'>{{issue.redmine.subject}}</div>
</div>
<div class='issueBody'>
sprint = {{issue.rowsprint}}<br>
version = {{issue.rowversion}}<br>
status = {{issue.redmine.status.name}}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block javascripts %}
<script>
let showIssuebody = false;
function showhide() {
// Sprint
selected = $('#sprintFilter').val();
if (!selected || selected.length === 0) {
$('.sprintCard').show();
}
else {
$('.sprintCard').hide();
selected.forEach(function (id) {
$('.sprintCard' + id).show();
});
}
// Version
selected = $('#versionFilter').val();
if (!selected || selected.length === 0) {
$('.versionCard').show();
}
else {
$('.versionCard').hide();
selected.forEach(function (id) {
$('.versionCard' + id).show();
});
}
}
function toogleIssueBody() {
if (showIssuebody) {
$('.issueBody').show();
$(this).text('Masquer Détail');
} else {
$('.issueBody').hide();
$(this).text('Afficher Détail');
}
showIssuebody=!showIssuebody;
}
$(document).ready(function () {
$('.issueCard').each(function () {
const id = $(this).data('status')+'-'+$(this).data('sprint')+'-'+$(this).data('version');
const $column = $(`[data-id='${id}']`);
if ($column.length) {
$column.append($(this));
}
else { console.log ('no ='+id);}
});
$('.containerScrum').css('display', 'flex');
// Filtre
$('#sprintFilter').on('change',showhide);
$('#versionFilter').on('change',showhide);
showhide();
// issueBody
$('#toggleIssueBody').on('click',toogleIssueBody);
toogleIssueBody();
});
$(function () {
let $sourceContainer = null;
let $movedItem = null;
let originalIndex = null;
$('.versionBody').sortable({
connectWith: '.versionBody',
items: '.issueCard',
handle: '.issueId',
placeholder: 'issue-placeholder',
forcePlaceholderSize: true,
start: function (event, ui) {
$sourceContainer = ui.item.parent();
$movedItem = ui.item;
originalIndex = ui.item.index();
},
update: function (event, ui) {
// ❗ Se déclenche même pour tri dans la même colonne
if (!event.originalEvent) return; // ← ignorer les appels indirects
const $targetContainer = $(this);
const sourceId = $sourceContainer.data('id');
const targetId = $targetContainer.data('id');
// Ne pas dupliquer l'appel si cest un vrai "receive"
if (ui.sender) return;
sendUpdate(sourceId, targetId, $sourceContainer, $targetContainer, $movedItem, originalIndex);
},
receive: function (event, ui) {
const $targetContainer = $(this);
const sourceId = $sourceContainer.data('id');
const targetId = $targetContainer.data('id');
sendUpdate(sourceId, targetId, $sourceContainer, $targetContainer, $movedItem, originalIndex);
}
});
function sendUpdate(sourceId, targetId, $sourceContainer, $targetContainer, $movedItem, originalIndex) {
const sourceIssues = $sourceContainer.find('.issueCard').map(function () {
return $(this).data('id');
}).get();
const targetIssues = $targetContainer.find('.issueCard').map(function () {
return $(this).data('id');
}).get();
$.ajax({
url: '/your/route/here', // 🔁 à adapter
method: 'POST',
data: {
sourceVersion: sourceId,
targetVersion: targetId,
sourceIssues: sourceIssues,
targetIssues: targetIssues
},
success: function (response) {
console.log('Déplacement réussi', response);
},
error: function (xhr) {
console.error('Erreur AJAX', xhr);
// Annuler le déplacement
if ($movedItem && $sourceContainer) {
const items = $sourceContainer.children();
if (originalIndex >= items.length) {
$sourceContainer.append($movedItem);
} else {
$movedItem.insertBefore(items.eq(originalIndex));
}
}
}
});
}
});
</script>
{% endblock %}