Stack qualité CI (MegaLinter, Trivy, ESLint) et purge du backlog lint web
Some checks failed
Qualité & Sécurité / MegaLinter (PMD · Ruff · Bandit · gitleaks · hadolint) (push) Successful in 1m9s
Build & Push Images / build (brain) (push) Successful in 1m10s
Qualité & Sécurité / Trivy (CVE dépendances Maven / pip / npm) (push) Failing after 2m36s
Build & Push Images / build (web) (push) Successful in 1m48s
Build & Push Images / build-switcher (push) Successful in 20s
Build & Push Images / build (core) (push) Successful in 3m9s
Qualité & Sécurité / Web (ESLint · angular-eslint + sonarjs) (push) Successful in 38s
Some checks failed
Qualité & Sécurité / MegaLinter (PMD · Ruff · Bandit · gitleaks · hadolint) (push) Successful in 1m9s
Build & Push Images / build (brain) (push) Successful in 1m10s
Qualité & Sécurité / Trivy (CVE dépendances Maven / pip / npm) (push) Failing after 2m36s
Build & Push Images / build (web) (push) Successful in 1m48s
Build & Push Images / build-switcher (push) Successful in 20s
Build & Push Images / build (core) (push) Successful in 3m9s
Qualité & Sécurité / Web (ESLint · angular-eslint + sonarjs) (push) Successful in 38s
CI (Gitea Actions) : - Nouveau workflow quality.yml (séparé de ci.yml, non bloquant pour la release) : MegaLinter v9 (PMD, Ruff, Bandit, gitleaks, hadolint), ng lint (web) et Trivy (CVE des dépendances Maven/pip/npm), sur main + beta + PR - Trivy : préchargement du cache Maven avant le scan — sans ça Maven Central rate-limite l'IP du runner (429) en résolvant les BOMs du parent Spring Boot - upload-artifact v4 → v3 : l'API artifacts v4 n'est pas supportée par Gitea (corrige aussi l'upload du rapport Playwright de e2e.yml, cassé depuis toujours) - Ruleset PMD projet (java-pmd-ruleset.xml, auto-détecté par MegaLinter) orienté bugs réels, sans le style Lombok-hostile du défaut : 11 337 → 65 findings ; PMD en mode rapport (JAVA_PMD_DISABLE_ERRORS) le temps de purger ce backlog Web : - angular-eslint 21 + eslint-plugin-sonarjs : les règles Sonar vivent désormais dans ESLint (config web/eslint.config.js, réglages justifiés en commentaire) - tsconfig : skipLibCheck + types:[] + node_modules ré-exclu — répare les builds desktop Windows/Linux cassés par le conflit @types/eslint-scope vs ESLint 9 - Purge du backlog lint : 114 erreurs → 0 sur 66 fichiers (ngOnDestroy vides supprimés, any typés avec les vrais DTOs, outputs (close) → (closed), regex super-linéaires désamorcées, ternaires/fonctions imbriqués dépliés, intention documentée sur les catch/error volontairement vides) - Bug latent corrigé au passage : license.service.disconnect() émettait undefined au lieu de true en cas de succès (masqué par un double cast)
This commit is contained in:
@@ -92,7 +92,7 @@ export class CampaignGraphComponent implements OnInit, OnDestroy {
|
||||
private readonly DRAG_THRESHOLD = 4;
|
||||
|
||||
// Adjacence (ids de nœuds) — sert à recalculer les arêtes après un drag.
|
||||
private adjacency: Array<{ key: string; kind: NodeKind; a: string; b: string }> = [];
|
||||
private adjacency: { key: string; kind: NodeKind; a: string; b: string }[] = [];
|
||||
|
||||
// Disposition personnalisée : positions sauvegardées sur la campagne, sauvegarde
|
||||
// différée après un drag (évite un PUT par pixel déplacé).
|
||||
@@ -174,7 +174,10 @@ export class CampaignGraphComponent implements OnInit, OnDestroy {
|
||||
if (this.draggingId) return; // pas de changement de focus en plein drag
|
||||
this.hoveredId = node.id;
|
||||
this.hoverNeighbors = new Set(
|
||||
this.adjacency.flatMap(e => e.a === node.id ? [e.b] : e.b === node.id ? [e.a] : []));
|
||||
this.adjacency.flatMap(e => {
|
||||
if (e.a === node.id) return [e.b];
|
||||
return e.b === node.id ? [e.a] : [];
|
||||
}));
|
||||
}
|
||||
|
||||
onNodeLeave(): void {
|
||||
@@ -230,7 +233,7 @@ export class CampaignGraphComponent implements OnInit, OnDestroy {
|
||||
for (const [arcId, chapters] of Object.entries(treeData.chaptersByArc)) {
|
||||
for (const ch of chapters) arcOfChapter.set(ch.id!, arcId);
|
||||
}
|
||||
const linkedScenes: Array<{ scene: Scene; chapterId: string }> = [];
|
||||
const linkedScenes: { scene: Scene; chapterId: string }[] = [];
|
||||
if (!this.hiddenKinds.has('scene')) {
|
||||
for (const [chapterId, scenes] of Object.entries(treeData.scenesByChapter)) {
|
||||
if (!arcOfChapter.has(chapterId)) continue;
|
||||
@@ -268,7 +271,7 @@ export class CampaignGraphComponent implements OnInit, OnDestroy {
|
||||
|
||||
// Arêtes. Les liens page↔page sont dé-dupliqués par paire non-orientée
|
||||
// (A→B et B→A = un seul trait) ; les liens entité→page portent le type de l'entité.
|
||||
const adjacency: Array<{ key: string; kind: NodeKind; a: string; b: string }> = [];
|
||||
const adjacency: { key: string; kind: NodeKind; a: string; b: string }[] = [];
|
||||
const seenPairs = new Set<string>();
|
||||
for (const p of pages) {
|
||||
for (const targetId of p.relatedPageIds ?? []) {
|
||||
@@ -530,14 +533,16 @@ export class CampaignGraphComponent implements OnInit, OnDestroy {
|
||||
if (Math.abs(dx) >= needX || Math.abs(dy) >= needY) continue;
|
||||
const overlapX = needX - Math.abs(dx);
|
||||
const overlapY = needY - Math.abs(dy);
|
||||
// Départage déterministe quand les centres coïncident (dx/dy = 0).
|
||||
const tieBreak = i % 2 === 0 ? 1 : -1;
|
||||
if (overlapX / needX < overlapY / needY) {
|
||||
const shift = overlapX / 2 + 0.5;
|
||||
const sign = dx !== 0 ? Math.sign(dx) : (i % 2 === 0 ? 1 : -1);
|
||||
const sign = dx !== 0 ? Math.sign(dx) : tieBreak;
|
||||
a.x -= sign * shift;
|
||||
b.x += sign * shift;
|
||||
} else {
|
||||
const shift = overlapY / 2 + 0.5;
|
||||
const sign = dy !== 0 ? Math.sign(dy) : (i % 2 === 0 ? 1 : -1);
|
||||
const sign = dy !== 0 ? Math.sign(dy) : tieBreak;
|
||||
a.y -= sign * shift;
|
||||
b.y += sign * shift;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user