feat: add "Derniers fichiers ouverts" widget to main dashboard
- Replace welcome message with a professional dashboard widget displaying the last opened files. - Implement configurable file limit via existing settings. - Design includes responsive grid layout and various UI states (loading, empty, error). - Introduce new JavaScript module `DashboardRecentWidget` for handling file loading and rendering. - Ensure accessibility compliance and responsive design breakpoints.
This commit is contained in:
parent
0bbd793e97
commit
4afa0ab5f9
1873
frontend/app.js
1873
frontend/app.js
File diff suppressed because it is too large
Load Diff
@ -350,10 +350,33 @@
|
|||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<main class="content-area" id="content-area" aria-label="Contenu principal">
|
<main class="content-area" id="content-area" aria-label="Contenu principal">
|
||||||
<div class="welcome" id="welcome" role="status">
|
<div id="dashboard-home" class="dashboard-home" role="region" aria-label="Derniers fichiers ouverts">
|
||||||
<i data-lucide="library" style="width:48px;height:48px;color:var(--text-muted)"></i>
|
<div class="dashboard-header">
|
||||||
<h2>ObsiGate</h2>
|
<div class="dashboard-title-row">
|
||||||
<p>Sélectionnez un fichier dans la sidebar ou utilisez la recherche pour commencer.</p>
|
<i data-lucide="clock" class="dashboard-icon"></i>
|
||||||
|
<h2>Derniers fichiers ouverts</h2>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-filter-row">
|
||||||
|
<select id="dashboard-vault-filter" class="dashboard-select">
|
||||||
|
<option value="">Tous les vaults</option>
|
||||||
|
</select>
|
||||||
|
<span class="dashboard-count" id="dashboard-count"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="dashboard-recent-grid" class="dashboard-recent-grid"></div>
|
||||||
|
<div id="dashboard-loading" class="dashboard-loading">
|
||||||
|
<div class="skeleton-card"></div>
|
||||||
|
<div class="skeleton-card"></div>
|
||||||
|
<div class="skeleton-card"></div>
|
||||||
|
<div class="skeleton-card"></div>
|
||||||
|
<div class="skeleton-card"></div>
|
||||||
|
<div class="skeleton-card"></div>
|
||||||
|
</div>
|
||||||
|
<div id="dashboard-recent-empty" class="dashboard-recent-empty hidden">
|
||||||
|
<i data-lucide="inbox"></i>
|
||||||
|
<span>Aucun fichier récent</span>
|
||||||
|
<p>Ouvrez un fichier pour le voir apparaître ici</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
161
plans/SPEC_Dashboard_RecentFiles.md
Normal file
161
plans/SPEC_Dashboard_RecentFiles.md
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
# SPEC: Widget "Derniers fichiers ouverts" sur la page principale
|
||||||
|
|
||||||
|
## 1. Objectif
|
||||||
|
|
||||||
|
Remplacer le message d'accueil actuel (`#welcome`) par un widget dashboard professionnel affichant les **XX derniers fichiers ouverts**. Le nombre de fichiers affichés sera configurable via les paramètres existants (`cfg-recent-limit`).
|
||||||
|
|
||||||
|
## 2. Architecture du composant
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A["#content-area"] --> B["#dashboard-home"]
|
||||||
|
B --> C["En-tête: Logo + Titre"]
|
||||||
|
B --> D["Sélecteur vault filter"]
|
||||||
|
B --> E["#dashboard-recent-grid"]
|
||||||
|
B --> F["#dashboard-recent-empty"]
|
||||||
|
|
||||||
|
E --> G["Carte 1: fichier récent"]
|
||||||
|
E --> H["Carte 2: fichier récent"]
|
||||||
|
E --> I["..."]
|
||||||
|
|
||||||
|
G --> G1["Icône fichier"]
|
||||||
|
G --> G2["Titre"]
|
||||||
|
G --> G3["Chemin breadcrumb"]
|
||||||
|
G --> G4["Tags"]
|
||||||
|
G --> G5["Horodatage"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Design UI/UX
|
||||||
|
|
||||||
|
### 3.1 Structure HTML (dans `#content-area`)
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="dashboard-home" class="dashboard-home">
|
||||||
|
<div class="dashboard-header">
|
||||||
|
<div class="dashboard-title-row">
|
||||||
|
<i data-lucide="clock" class="dashboard-icon"></i>
|
||||||
|
<h2>Derniers fichiers ouverts</h2>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-filter-row">
|
||||||
|
<select id="dashboard-vault-filter">
|
||||||
|
<option value="">Tous les vaults</option>
|
||||||
|
</select>
|
||||||
|
<span class="dashboard-count" id="dashboard-count"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="dashboard-recent-grid" class="dashboard-recent-grid"></div>
|
||||||
|
<div id="dashboard-recent-empty" class="dashboard-recent-empty hidden">
|
||||||
|
<i data-lucide="inbox"></i>
|
||||||
|
<span>Aucun fichier récent</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Layout Grid
|
||||||
|
|
||||||
|
- **Desktop (>1024px)**: Grid 3 colonnes
|
||||||
|
- **Tablet (768-1024px)**: Grid 2 colonnes
|
||||||
|
- **Mobile (<768px)**: Grid 1 colonne
|
||||||
|
|
||||||
|
### 3.3 Style des cartes (`.dashboard-card`)
|
||||||
|
|
||||||
|
| Élément | Style |
|
||||||
|
|---------|-------|
|
||||||
|
| Container | `border-radius: 12px`, `padding: 16px`, fond `var(--bg-secondary)` |
|
||||||
|
| Hover | Légère élévation avec `box-shadow`, bordure accent |
|
||||||
|
| Icône | 32x32px, couleur accent |
|
||||||
|
| Titre | `font-weight: 600`, `font-size: 14px`, truncation avec ellipsis |
|
||||||
|
| Chemin | `font-size: 11px`, `color: var(--text-muted)` |
|
||||||
|
| Tags | Pills compacts, même style que sidebar |
|
||||||
|
| Horodatage | Badge discret avec icône clock |
|
||||||
|
| Badge vault | Position absolute en haut-droit |
|
||||||
|
|
||||||
|
### 3.4 États
|
||||||
|
|
||||||
|
| État | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| **Chargement** | Skeleton cards animées (pulse) |
|
||||||
|
| **Données** | Grid de cartes |
|
||||||
|
| **Vide** | Icône + message centré |
|
||||||
|
| **Erreur** | Toast notification |
|
||||||
|
|
||||||
|
## 4. Interactions
|
||||||
|
|
||||||
|
| Action | Comportement |
|
||||||
|
|--------|--------------|
|
||||||
|
| **Clic sur carte** | Ouvre le fichier (`openFile(vault, path)`) |
|
||||||
|
| **Changement filter vault** | Recharge les données avec filtre |
|
||||||
|
| **Hover carte** | Élévation visuelle, curseur pointer |
|
||||||
|
| **Fermeture fichier** | Affiche le dashboard (si plus de fichier ouvert) |
|
||||||
|
|
||||||
|
## 5. Intégration JavaScript
|
||||||
|
|
||||||
|
### 5.1 Nouveau module `DashboardRecentWidget`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const DashboardRecentWidget = {
|
||||||
|
async load(vaultFilter) { /* Charge via /api/recent */ },
|
||||||
|
render(files) { /* Génère le HTML des cartes */ },
|
||||||
|
showEmpty() { /* Affiche état vide */ },
|
||||||
|
showLoading() { /* Affiche skeletons */ },
|
||||||
|
init() { /* Bind events, charge initial */ }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Points d'intégration
|
||||||
|
|
||||||
|
- **Au démarrage**: `DashboardRecentWidget.init()` dans `DOMContentLoaded`
|
||||||
|
- **Ouverture fichier**: Dashboard masqué automatiquement
|
||||||
|
- **Fermeture fichier**: Dashboard affiché si `activeEditor === null`
|
||||||
|
- **Filtre vault**: Recharge via `loadRecentFiles` de la sidebar (partage du cache)
|
||||||
|
|
||||||
|
### 5.3 Partage avec sidebar "Recent"
|
||||||
|
|
||||||
|
Le widget réutilisera `_recentFilesCache` et `renderRecentList` mais avec un **template de carte différent** pour le dashboard.
|
||||||
|
|
||||||
|
## 6. Fichiers à modifier
|
||||||
|
|
||||||
|
| Fichier | Modification |
|
||||||
|
|---------|--------------|
|
||||||
|
| `frontend/index.html` | Remplacer `#welcome` par `#dashboard-home` |
|
||||||
|
| `frontend/style.css` | Ajouter `.dashboard-home`, `.dashboard-card`, skeleton, animations |
|
||||||
|
| `frontend/app.js` | Ajouter `DashboardRecentWidget`, modifier `showWelcome()`, intégration hooks |
|
||||||
|
|
||||||
|
## 7. Paramètres configurables
|
||||||
|
|
||||||
|
| Paramètre | Source | Description |
|
||||||
|
|-----------|--------|-------------|
|
||||||
|
| `recent_files_limit` | Backend config | Nombre max de fichiers (5-100, défaut: 20) |
|
||||||
|
|
||||||
|
## 8. Accessibilité
|
||||||
|
|
||||||
|
- Rôles ARIA appropriés (`role="region"`, `aria-label`)
|
||||||
|
- Navigation clavier fonctionnelle
|
||||||
|
- Contraste des couleurs conforme WCAG 2.1 AA
|
||||||
|
- Support screen reader pour les états vides/chargement
|
||||||
|
|
||||||
|
## 9. Responsive breakpoints
|
||||||
|
|
||||||
|
```css
|
||||||
|
.dashboard-recent-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
/* Mobile first */
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Animations
|
||||||
|
|
||||||
|
| Événement | Animation |
|
||||||
|
|-----------|-----------|
|
||||||
|
| Entrée cartes | Fade-in + slide-up staggeré (50ms entre cartes) |
|
||||||
|
| Hover carte | Scale 1.02 + shadow |
|
||||||
|
| Skeleton loading | Pulse animation |
|
||||||
|
| Transition vault filter | Fade out/in des cartes |
|
||||||
Loading…
x
Reference in New Issue
Block a user