Ajout de 2 fonctionnalitées principales : import PDF que ce soit pour les règles ou les campagnes directement.
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m28s
Build & Push Images / build (core) (push) Successful in 1m40s
Build & Push Images / build-switcher (push) Successful in 19s
Build & Push Images / build (web) (push) Successful in 1m46s

Fonctionnalité de comparaison PDF / campagne pour faire un mix et demander des conseils à l'IA
This commit is contained in:
2026-06-04 13:55:27 +02:00
parent 79a68bc27b
commit 439f43875b
78 changed files with 5250 additions and 183 deletions

View File

@@ -8,7 +8,19 @@
<ng-container *ngIf="!isCollapsed">
<h2 class="sidebar-title">{{ title }}</h2>
<button
*ngIf="titleRoute; else staticTitle"
type="button"
class="sidebar-title sidebar-title--link"
[class.active]="isTitleActive()"
title="Retour à l'accueil de la campagne"
(click)="clickTitle()">
<lucide-icon [img]="Home" [size]="14" class="sidebar-title-icon"></lucide-icon>
<span class="sidebar-title-text">{{ title }}</span>
</button>
<ng-template #staticTitle>
<h2 class="sidebar-title">{{ title }}</h2>
</ng-template>
<div class="actions-row" *ngIf="createActions.length">
<button

View File

@@ -77,6 +77,35 @@
text-overflow: ellipsis;
}
// Variante cliquable : le titre devient un bouton "retour à l'accueil".
.sidebar-title--link {
display: flex;
align-items: center;
gap: 0.4rem;
width: 100%;
background: none;
border: none;
text-align: left;
cursor: pointer;
border-radius: 6px;
padding: 0.3rem 0.5rem;
transition: background 0.15s;
.sidebar-title-icon {
flex-shrink: 0;
color: #a78bfa;
}
.sidebar-title-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&:hover { background: rgba(255, 255, 255, 0.07); }
&.active { background: rgba(108, 99, 255, 0.18); }
}
.actions-row {
display: flex;
gap: 0.4rem;

View File

@@ -1,7 +1,7 @@
import { Component, Input, Output, EventEmitter, HostListener, OnDestroy, ElementRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router } from '@angular/router';
import { LucideAngularModule, ChevronRight, ChevronDown, PanelLeftClose, PanelLeftOpen, Plus, FolderPlus, FilePlus, LucideIconData } from 'lucide-angular';
import { LucideAngularModule, ChevronRight, ChevronDown, PanelLeftClose, PanelLeftOpen, Plus, FolderPlus, FilePlus, Home, LucideIconData } from 'lucide-angular';
import { TreeItem, TreeCreateAction, SidebarAction, BottomPanel, BottomPanelItem, LayoutService } from '../../services/layout.service';
import { resolveIcon } from '../../lore/lore-icons';
@@ -14,6 +14,8 @@ import { resolveIcon } from '../../lore/lore-icons';
})
export class SecondarySidebarComponent implements OnDestroy {
@Input() title = '';
/** Si défini, le titre est cliquable et navigue vers cette route (accueil de section). */
@Input() titleRoute: string | null = null;
@Input() createActions: SidebarAction[] = [];
@Input() bottomPanel: BottomPanel | null = null;
@Output() collapsedChange = new EventEmitter<boolean>();
@@ -28,6 +30,7 @@ export class SecondarySidebarComponent implements OnDestroy {
readonly Plus = Plus;
readonly FolderPlus = FolderPlus;
readonly FilePlus = FilePlus;
readonly Home = Home;
isCollapsed = false;
@@ -114,6 +117,19 @@ export class SecondarySidebarComponent implements OnDestroy {
if (action.route) { this.router.navigate([action.route]); }
}
/** Clic sur le titre cliquable : retour à l'accueil de la section (ex: campagne). */
clickTitle(): void {
if (this.titleRoute) { this.router.navigate([this.titleRoute]); }
}
/** True si on est déjà sur la route du titre (surligne le titre comme actif). */
isTitleActive(): boolean {
if (!this.titleRoute) return false;
return this.router.isActive(this.titleRoute, {
paths: 'exact', queryParams: 'ignored', fragment: 'ignored', matrixParams: 'ignored'
});
}
clickItem(item: TreeItem): void {
if (item.route) { this.router.navigate([item.route]); return; }
this.toggleItem(item.id);