feat(domain,application,infrastructure,backend,web-server,app-tauri,frontend): lot utilisateur #325 #326 — icônes projet avec watermark CLI custom et localisation FR/EN (QA verte)
Lot en un seul commit: les deux features partagent les mêmes contrats (domain/settings.rs, DTO, commandes Tauri/HTTP, web-server) et les mêmes surfaces UI — la séparation par fichiers était impossible sans chirurgie de hunks risquant des états intermédiaires non compilables (convention lot des batches #310-#313 et #315). #325 — icône configurable par projet, watermark CLI custom: - domaine: ProjectIconSet (devicon, simple-icons, lucide, idea), ProjectIconRef validé (nom ASCII 1..=64, -_. internes), champ icon optionnel sur ProjectSettings; sérialisation camelCase et try_from strict - application: UpdateProjectSettings.execute accepte un patch theme_color OU icon (absent = inchangé, null = défaut produit), tests in-dependants avec store mémoire - backend/app-tauri/web-server: ProjectIconRefDto, UpdateProjectSettingsRequestDto avec icon optionnel (désérialisation additive), commandes update_project_settings alignées Tauri/HTTP, tests DTO et HTTP (défaut null, set, clear, nom invalide rejeté) - frontend: catalogue projectIcons (recherche EN), ProjectIconPicker en grille multi-lignes dans Paramètres projet, affichage de l'icône dans ProjectTabs et watermark grand format à faible opacité en fond de CLI custom; ports ProjectSettings.icon, Partial<ProjectSettings>, adapters tauri/mock/http et tests alignés #326 — localisation FR/EN et traduction des textes IdeA: - domaine: IdeaLanguage (fr | en), champ language optionnel sur IdeaUserSettings (absence = défaut produit, série additive validée) - backend/web-server: UserSettingsDto.language, update_user_settings accepte language, tests HTTP alignés; fixtures structured_launch_d3 mises à jour - frontend: i18n/ (catalogue FR/EN, I18nProvider, scan anti-régression des sources visibles), GeneralSettings avec sélecteur de langue dans les paramètres, setupI18n dans vitest; migration de l'ensemble des textes hardcodés vers le catalogue sur toutes les surfaces (agents, layout, projets, tickets, sprints, web, plugins, permissions, git, templates, skills, mémoire, model servers, embedder, first-run, devices, scheduled tasks, workstate, dialogs), FR conservé par défaut; recherche d'icônes #325 en anglais conformément au ticket QA verte sur feature/batch-325-326-project-icons-localisation. Aucun push.
This commit is contained in:
@ -12,6 +12,7 @@
|
||||
|
||||
import type { TabItem } from "@/shared";
|
||||
import { Button, Tabs, cn } from "@/shared";
|
||||
import { useI18n } from "@/i18n";
|
||||
import type { ProjectActivityStatus } from "./projectActivity";
|
||||
import { accessibleProjectAccent } from "./projectTheme";
|
||||
|
||||
@ -41,6 +42,7 @@ export function ProjectTabs({
|
||||
themeColorByProjectId = {},
|
||||
className,
|
||||
}: ProjectTabsProps) {
|
||||
const { tr } = useI18n();
|
||||
const tabs = items.map((item) => ({
|
||||
...item,
|
||||
themeColor: themeColorByProjectId[item.id] ?? null,
|
||||
@ -63,7 +65,7 @@ export function ProjectTabs({
|
||||
)}
|
||||
>
|
||||
{items.length === 0 ? (
|
||||
<p className="px-2 text-sm text-muted">No open tabs.</p>
|
||||
<p className="px-2 text-sm text-muted">{tr("Aucun onglet ouvert.", "No open tabs.")}</p>
|
||||
) : (
|
||||
<Tabs
|
||||
items={tabs}
|
||||
@ -80,9 +82,9 @@ export function ProjectTabs({
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
onClick={onOpenProjectsPanel}
|
||||
aria-label="open projects panel"
|
||||
aria-label={tr("ouvrir le panneau des projets", "open projects panel")}
|
||||
aria-pressed={projectsPanelOpen}
|
||||
title="Ajouter un projet"
|
||||
title={tr("Ajouter un projet", "Add a project")}
|
||||
className={cn(
|
||||
"shrink-0",
|
||||
projectsPanelOpen && "ring-1 ring-border-strong",
|
||||
@ -101,10 +103,11 @@ function ProjectActivityDot({
|
||||
status: ProjectActivityStatus;
|
||||
label: string;
|
||||
}) {
|
||||
const { tr } = useI18n();
|
||||
const title =
|
||||
status === "busy"
|
||||
? `${label} : Échange en cours`
|
||||
: `${label} : Prêt`;
|
||||
? tr(`${label} : échange en cours`, `${label}: conversation in progress`)
|
||||
: tr(`${label} : prêt`, `${label}: ready`);
|
||||
return (
|
||||
<span
|
||||
data-testid={`project-activity-${label}`}
|
||||
|
||||
Reference in New Issue
Block a user