[#6] Zoom categorie + AddKeywordDialog (scope limite) #74
Labels
No labels
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#74
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Objectif
Implémenter le zoom catégorie (remplace l'ancien tableau croisé dynamique) + l'édition contextuelle des mots-clés via clic droit, limitée à
CategoryTransactionsTabledans cette issue. La propagation du clic droit aux autres tables est traitée en Issue #75 (follow-up).Cette issue porte l'essentiel des garanties de sécurité identifiées par le review expert.
Spec :
spec-refonte-rapports.mdDépend de #70 (parallélisable avec #71, #72, #73)
Tâches — Zoom catégorie
Service avec cycle guard obligatoire
reportService.getCategoryZoom(categoryId, from, to, includeSubcategories)via CTE SQLite récursive bornée :{ rollupTotal, byChild: { id, name, color, total }[], monthlyEvolution: { month, total }[], transactions: Transaction[] }depth < 5Hook
src/hooks/useCategoryZoom.ts: state{ categoryId, includeSubcategories, data, loading, error }Composants (plat dans
src/components/reports/)CategoryZoomHeader.tsx— combobox catégorie + toggleinclure sous-catégories(activé par défaut)CategoryDonutChart.tsx— template de démarrage :src/components/dashboard/CategoryPieChart.tsxlignes 81–90 (déjà un<Pie innerRadius={35} outerRadius={75}>avec patterns)CategoryEvolutionChart.tsx— AreaChart sur la période, patterns SVGCategoryTransactionsTable.tsx— sortable, filtrable, exposeonContextMenusur chaque lignePage
src/pages/ReportsCategoryPage.tsxViewModeTogglepartagé, storage keyreports-viewmode-categoryTâches — Édition contextuelle des mots-clés
Export depuis
categorizationServicesrc/services/categorizationService.ts:normalizeDescription,buildKeywordRegex,compileKeywords(actuellement privés)AddKeywordDialog— emplacement :src/components/categories/AddKeywordDialog.tsx(Pas dans
components/reports/: c'est un composant du domaine édition mot-clé, utilisé aussi depuis/transactionsplus tard.)Garanties de sécurité (non négociables) :
.trim(), rejet whitespace-only, messages i18nreports.keyword.tooShort/tooLong. Prévient ReDoS (CWE-1333)SELECT ... FROM transactions WHERE description LIKE ?1— jamais d'interpolation de chaîne. Puis filtrage en mémoire avec le regex compilé parbuildKeywordRegex. Prévient SQL injection (CWE-89)tauri-plugin-sql:BEGIN; INSERT keywords; UPDATE transactions; COMMIT;avec rollback + toast erreur en cas d'échec (CWE-662)UPDATE keywords SET category_id=? WHERE keyword=?+ re-run de la catégorisation uniquement sur les matches visibles cochés (jamais rétroactif sur l'historique complet). Afficherreports.keyword.alreadyExistsavant validation{tx.description}) — jamaisdangerouslySetInnerHTML, troncature CSS uniquement (CWE-79)Branchement clic droit (scope limité)
ContextMenugénérique (créé en #69) avec un item « Ajouter comme mot-clé » qui ouvreAddKeywordDialogCategoryTransactionsTabledans cette issueHighlightsTopMoversTable,ComparePeriodTable, etc.) seront branchées en Issue #75i18n
reports.category.*(selectCategory, includeSubcategories, directOnly, breakdown, evolution, transactions)reports.keyword.*(addFromTransaction, dialogTitle, willMatch,nMatches_one,nMatches_other, applyAndRecategorize, tooShort, tooLong, alreadyExists)_one/_other(pas_plural)Vérifications
/reports/categoryaffiche le zoom complet avec rollup auto/categoriesgrep -n "dangerouslySetInnerHTML" src/components/categories/AddKeywordDialog.tsxretourne videnpm run build+cargo check+npm testvertsCritères d'acceptation
/reports/categoryaffiche donut + evolution + table pour une catégorie sélectionnée, avec rollupgetCategoryZoomtermine avec fixture cyclique (test unitaire vert)AddKeywordDialogrespecte TOUTES les 7 garanties de sécurité listées ci-dessusCategoryTransactionsTable_one/_other