Correctifs UI workflow — specs + implémentation (8 chantiers) (#6)
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Suite à l'arrivée des workflows, correction des régressions UI et améliorations UX mail/modales (reviews Lucile Schnödt, Tristan Schnödtin). **Specs & décisions :** `docs/superpowers/specs/2026-05-20-workflow-ui-fixes-design.md` **Plan d'implémentation :** `docs/superpowers/plans/2026-05-21-workflow-ui-fixes.md` Cette PR contient désormais **les specs ET l'implémentation complète**. ## Chantiers livrés | # | Chantier | Détail | |---|----------|--------| | 2 | Sélecteur de statut filtré par workflow | `statusOptions` dérivé de `project.workflow.statuses`, statut courant conservé s'il est hors workflow | | 1 | Drag & drop « Mes tâches » | handlers `@dragover/@drop` ; résolution par workflow/catégorie (0→refus, 1→PATCH, ≥2→popover `StatusPickerPopover`) | | 4 | Couleurs | (a) migration Doctrine remettant les hex classiques sur le workflow Standard ; (b) entêtes kanban teintées via `STATUS_CATEGORY_COLOR` + contraste auto ; (c) couleur par défaut par catégorie dans `WorkflowDrawer` | | 5 | Suppression du bouton « Lier un mail » | + retrait de `MailPickerModal` et i18n associée | | 6 | Création de tâche depuis un mail | back : `assigneeId` + `statusId` (défaut = 1er statut du workflow), priorité retirée (TDD) ; front : `MailCreateTaskModal` sur `AppModal` + sélecteurs user/statut | | 7 | Modale réutilisable | nouveau `components/ui/AppModal.vue` (footer sticky) ; footer de `TaskModal` sorti du form scrollable | | 3 | Cartes responsive | badges en `flex-wrap` pleine taille (plus aucun débordement) | | 8 | (dette) Sélecteur de catégorie en `MalioSelect` | la lib supporte les valeurs `string` ; note CLAUDE.md corrigée | ## Vérifications - Build frontend OK ; PHPUnit **34 tests verts** (nouveau test fonctionnel TDD sur `create-task`). - Vérif navigateur (Chrome MCP) sur **données prod importées en local** : #2, #3, #4, #5, #6, #7 confirmés. - Revue de code finale : **APPROVED_WITH_NITS**. ## À noter - ⚠️ **#1 (D&D)** : le drag & drop HTML5 natif n'est pas auto-testable → **test manuel requis**. - 🗄️ **#4 (migration)** : `migrations/Version20260521094948.php` s'appliquera en **prod au prochain `make migration-migrate`**. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
@@ -4,7 +4,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Mail;
|
||||
|
||||
use App\Entity\MailFolder;
|
||||
use App\Entity\MailMessage;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Task;
|
||||
use App\Entity\User;
|
||||
use DateTimeImmutable;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
/**
|
||||
@@ -69,4 +74,67 @@ class MailTaskIntegrationControllerTest extends WebTestCase
|
||||
|
||||
self::assertResponseStatusCodeSame(401);
|
||||
}
|
||||
|
||||
public function testCreateTaskAppliesStatusAndAssigneeAndIgnoresPriority(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$container = static::getContainer();
|
||||
$em = $container->get('doctrine.orm.entity_manager');
|
||||
|
||||
$admin = $em->getRepository(User::class)->findOneBy(['username' => 'admin']);
|
||||
$client->loginUser($admin);
|
||||
|
||||
$project = $em->getRepository(Project::class)->findOneBy([]);
|
||||
self::assertNotNull($project);
|
||||
$status = $project->getWorkflow()->getStatuses()->first();
|
||||
self::assertNotFalse($status);
|
||||
|
||||
// Create a mail folder + message in the test DB (none in fixtures)
|
||||
$folder = new MailFolder();
|
||||
$folder->setDisplayName('Boîte de réception');
|
||||
$folder->setUnreadCount(0);
|
||||
$folder->setTotalCount(0);
|
||||
$em->persist($folder);
|
||||
|
||||
$rand = random_int(100000, 999999);
|
||||
$folder->setPath('INBOX.'.$rand);
|
||||
|
||||
$message = new MailMessage();
|
||||
$message->setMessageId('test-'.$rand.'@example.com');
|
||||
$message->setFolder($folder);
|
||||
$message->setUid($rand);
|
||||
$message->setFromAddress('sender@example.com');
|
||||
$message->setToAddresses([]);
|
||||
$message->setSentAt(new DateTimeImmutable());
|
||||
$message->setIsRead(false);
|
||||
$message->setIsFlagged(false);
|
||||
$message->setHasAttachments(false);
|
||||
$message->setSyncedAt(new DateTimeImmutable());
|
||||
$message->setSubject('Sujet de test');
|
||||
$em->persist($message);
|
||||
$em->flush();
|
||||
|
||||
$client->request(
|
||||
'POST',
|
||||
'/api/mail/messages/'.$message->getId().'/create-task',
|
||||
[],
|
||||
[],
|
||||
['CONTENT_TYPE' => 'application/json'],
|
||||
json_encode([
|
||||
'projectId' => $project->getId(),
|
||||
'assigneeId' => $admin->getId(),
|
||||
'statusId' => $status->getId(),
|
||||
'priorityId' => 999, // doit être ignoré
|
||||
])
|
||||
);
|
||||
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
$payload = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$em->clear();
|
||||
$task = $em->getRepository(Task::class)->find($payload['taskId']);
|
||||
self::assertSame($status->getId(), $task->getStatus()?->getId());
|
||||
self::assertSame($admin->getId(), $task->getAssignee()?->getId());
|
||||
self::assertNull($task->getPriority());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user