This commit is contained in:
2025-07-11 23:04:57 +02:00
parent 1e9cd2f75b
commit 056e3d7abc
8 changed files with 423 additions and 6 deletions

View File

@ -30,3 +30,35 @@ $(document).ready(function () {
}, 0);
});
});
$(document).ready(function () {
$('.select2').select2({
theme: 'bootstrap-5',
templateResult: function (data) {
if (!data.id) return data.text;
const $result = $('<span>').text(data.text);
const customClass = $(data.element).attr('class');
if (customClass) {
$result.addClass(customClass);
}
return $result;
},
templateSelection: function (data) {
if (!data.id) return data.text;
const $selection = $('<span>').text(data.text);
const customClass = $(data.element).attr('class');
if (customClass) {
$selection.addClass(customClass);
}
return $selection;
}
});
});

193
public/lib/app/selbg.css Normal file
View File

@ -0,0 +1,193 @@
/* ==== DARK THEMES ==== */
.selbg-darkblue {
background-color: #0d6efd;
color: #ffffff;
}
.selbg-darkindigo {
background-color: #6610f2;
color: #ffffff;
}
.selbg-darkpurple {
background-color: #6f42c1;
color: #ffffff;
}
.selbg-darkpink {
background-color: #d63384;
color: #ffffff;
}
.selbg-darkred {
background-color: #dc3545;
color: #ffffff;
}
.selbg-darkorange {
background-color: #fd7e14;
color: #000000;
}
.selbg-darkyellow {
background-color: #ffc107;
color: #000000;
}
.selbg-darkgreen {
background-color: #198754;
color: #ffffff;
}
.selbg-darkteal {
background-color: #20c997;
color: #000000;
}
.selbg-darkcyan {
background-color: #0dcaf0;
color: #000000;
}
.selbg-darkgray {
background-color: #343a40;
color: #ffffff;
}
.selbg-darkbrown {
background-color: #5c4033;
color: #ffffff;
}
.selbg-darknavy {
background-color: #001f3f;
color: #ffffff;
}
.selbg-darkmaroon {
background-color: #800000;
color: #ffffff;
}
.selbg-darkolive {
background-color: #3d9970;
color: #ffffff;
}
.selbg-darksteel {
background-color: #2f4f4f;
color: #ffffff;
}
.selbg-darkcharcoal {
background-color: #222222;
color: #ffffff;
}
.selbg-darksmoke {
background-color: #555555;
color: #ffffff;
}
.selbg-darkforest {
background-color: #228B22;
color: #ffffff;
}
.selbg-darkmidnight {
background-color: #191970;
color: #ffffff;
}
/* ==== LIGHT THEMES ==== */
.selbg-lightblue {
background-color: #cfe2ff;
color: #084298;
}
.selbg-lightindigo {
background-color: #e0ccff;
color: #52057f;
}
.selbg-lightpurple {
background-color: #e2d9f3;
color: #4c287b;
}
.selbg-lightpink {
background-color: #f7d6e6;
color: #6f042e;
}
.selbg-lightred {
background-color: #f8d7da;
color: #842029;
}
.selbg-lightorange {
background-color: #ffe5b4;
color: #7f3f00;
}
.selbg-lightyellow {
background-color: #fff3cd;
color: #664d03;
}
.selbg-lightgreen {
background-color: #d1e7dd;
color: #0f5132;
}
.selbg-lightteal {
background-color: #d2f4ea;
color: #0f625d;
}
.selbg-lightcyan {
background-color: #cff4fc;
color: #055160;
}
.selbg-lightgray {
background-color: #f8f9fa;
color: #212529;
}
.selbg-lightlinen {
background-color: #faf0e6;
color: #333333;
}
.selbg-lightbeige {
background-color: #f5f5dc;
color: #222222;
}
.selbg-lightmint {
background-color: #e6fff5;
color: #225e4c;
}
.selbg-lightlavender {
background-color: #e6e6fa;
color: #3f3f7f;
}
.selbg-lightsky {
background-color: #e0f7ff;
color: #004466;
}
.selbg-lightrose {
background-color: #ffe0e9;
color: #75002f;
}
.selbg-lightice {
background-color: #f0ffff;
color: #003b4d;
}

View File

@ -2,8 +2,10 @@
namespace App\Controller;
use App\Form\IssueType;
use App\Repository\IssueRepository;
use App\Service\RedmineService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\JsonResponse;
@ -37,6 +39,36 @@ class IssueController extends AbstractController
]);
}
#[Route('/user/issue/update/{id}', name: 'app_issue_update')]
public function updateIssue(int $id, Request $request, IssueRepository $issueRepository, EntityManagerInterface $em): Response
{
$issue = $issueRepository->find($id);
if (!$issue) {
throw new NotFoundHttpException('La ressource demandée est introuvable.');
}
if (!$issue->getProject()->getUsers()->contains($this->getUser())) {
throw new AccessDeniedException('Vous n\'avez pas accès à cette ressource.');
}
$form = $this->createForm(IssueType::class, $issue, ['mode' => 'update']);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->flush();
// return $this->redirectToRoute('app_admin_project');
}
return $this->render('issue/edit.html.twig', [
'usemenu' => true,
'usesidebar' => true,
'title' => $issue->getRedmine()['subject'],
'routecancel' => 'app_admin_project',
'routedelete' => 'app_admin_project_delete',
'mode' => 'update',
'form' => $form,
'issue' => $issue,
]);
}
#[Route('/user/issue/order/{id}', name: 'app_issue_order', methods: ['POST'])]
public function orderIssue(int $id, Request $request, IssueRepository $issueRepository): JsonResponse
{
@ -77,13 +109,9 @@ class IssueController extends AbstractController
];
$this->redmineService->updateIssue($id, $payload, $this->getUser()->getApikey());
} catch (\RuntimeException $e) {
// Récupère le message de l'exception
$errorMessage = $e->getMessage();
dump($e->getMessage());
// Par exemple, retour JSON d'erreur :
return new JsonResponse(['message' => $errorMessage], 400);
return new JsonResponse(['message' => $e->getMessage()], 400);
}
/*
$payload =
[

View File

@ -30,6 +30,9 @@ class Issue
#[ORM\Column(nullable: false)]
private int $rowissue = 0;
#[ORM\Column(nullable: true)]
private string $color = '';
#[ORM\ManyToOne(targetEntity: Project::class, inversedBy: 'issues')]
#[ORM\JoinColumn(nullable: false)]
private Project $project;
@ -125,6 +128,18 @@ class Issue
return $this;
}
public function getColor(): ?string
{
return $this->rowsprint;
}
public function setColor(?string $color): static
{
$this->color = $color;
return $this;
}
public function getProject(): Project
{
return $this->project;

33
src/Form/IssueType.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace App\Form;
use App\Entity\Issue;
use App\Form\Type\SelbgType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class IssueType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('submit', SubmitType::class, [
'label' => 'Valider',
'attr' => ['class' => 'btn btn-success no-print'],
])
->add('color', SelbgType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Issue::class,
'mode' => 'submit',
]);
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SelbgType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$choices = $this->loadCssClasses();
// clef => valeur
$choices = array_combine($choices, $choices);
$resolver->setDefaults([
'choices' => $choices,
'choice_attr' => function ($choice, $key, $value) {
return ['class' => $value];
},
'required' => false,
'placeholder' => 'Sélectionnez un thème…',
'label' => 'Thème de couleur',
'attr' => ['class' => 'select2'],
]);
}
public function getParent(): string
{
return ChoiceType::class;
}
private function loadCssClasses(): array
{
$path = __DIR__.'/../../../public/lib/app/selbg.css';
if (!is_readable($path)) {
return [];
}
$content = file_get_contents($path);
// match les classes du style `.selbg-xxx {`
preg_match_all('/\.selbg-[\w\-]+(?=\s*\{)/', $content, $matches);
// Supprime les points au début
return array_map(function ($class) {
return ltrim($class, '.');
}, $matches[0] ?? []);
}
}

View File

@ -16,6 +16,7 @@
<link rel="stylesheet" href="{{ asset('lib/imgareaselect/css/imgareaselect-default.css') }}">
<link rel="stylesheet" href="{{ asset('lib/app/app.css') }}">
<link rel="stylesheet" href="{{ asset('lib/app/selbg.css') }}">
<script src="{{ asset('lib/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('lib/bootstrap/js/bootstrap.bundle.min.js') }}"></script>

View File

@ -0,0 +1,62 @@
{% extends 'base.html.twig' %}
{% block localstyle %}
<style>
</style>
{% endblock %}
{% block title %}
Modification Issue = {{title}}
{% endblock %}
{% block body %}
<h1>
Modification Issue<br>
</h1>
<small class="text-muted" style="margin-top:-20px">{{title}}</small>
<br>
<br>
{{ form_start(form) }}
{{ form_widget(form.submit) }}
<a href="{{ path(routecancel) }}" class="btn btn-secondary ms-1">Annuler</a>
{% include('include/error.html.twig') %}
<div class="row">
<div class="col-md-6 mx-auto">
<div class="card mt-3">
<div class="card-header">Information</div>
<div class="card-body">
</div>
</div>
</div>
<div class="col-md-6 mx-auto">
<div class="card mt-3">
<div class="card-header">Permissions</div>
<div class="card-body">
</div>
</div>
{% if mode=="update" %}
<div class="card mt-3">
<div class="card-header">Détail Redmine</div>
<div class="card-body">
</div>
</div>
{% endif %}
</div>
</div>
{{ form_end(form) }}
{% endblock %}
{% block localscript %}
<script>
$(document).ready(function() {
$("#project_title").focus();
});
</script>
{% endblock %}