merge: main → develop (sync)
This commit is contained in:
+22
-25
@@ -177,31 +177,28 @@ Propriétés custom, AI keywords, sync API, 12 tables DB
|
|||||||
|
|
||||||
## 🔜 Prochaines versions
|
## 🔜 Prochaines versions
|
||||||
|
|
||||||
### v4.0.1 — Onboarding & Polish 🎯 (priorité MAX)
|
### v4.0.1 — Onboarding & Polish ✅ (2026-07-18)
|
||||||
> **Objectif** : rendre l'app utilisable dès la première visite, sans friction.
|
> **Objectif** : rendre l'app utilisable dès la première visite, sans friction. **COMPLETED**.
|
||||||
|
|
||||||
- [ ] **Landing page `/` pour visiteurs non-auth** — page d'accueil (pas de redirect loop)
|
- [x] **Landing page `/` pour visiteurs non-auth** — template `landing.html`, design Notion dark
|
||||||
- [ ] **Page `/auth/register` GET** — formulaire d'inscription dédié (pas juste un tab)
|
- [x] **Page `/auth/register` GET** — formulaire d'inscription dédié (tab register actif)
|
||||||
- [ ] **Redirection `/` intelligente** — si pas connecté → login, si connecté sans Gitea → local workspace
|
- [x] **Redirection `/` intelligente** — non-auth → landing, auth sans Gitea → local workspace, auth+Gitea → dashboard
|
||||||
- [ ] **Empty states cohérents** — onboarding dans le local workspace vide
|
- [x] **Empty states** — déjà présents dans local workspace (« Welcome to your Workspace »)
|
||||||
- [ ] **Page 404 stylisée** — thème Notion sombre (actuellement HTML brut)
|
- [x] **Page 404 stylisée** — thème Notion sombre, JSON pour `/api/*`, HTML pour le reste
|
||||||
- [ ] **Unifier les routes API** — `/board/api/pages` ↔ `/api/pages` (cohérence)
|
- [x] **Unifier les routes API** — `/api/pages` GET/POST → 307 redirect vers `/board/api/pages`
|
||||||
- [ ] **Page Settings accessible** → lien dans le menu utilisateur déjà présent, vérifier fonctionnel
|
- [x] **Page Settings** — lien déjà présent dans le menu utilisateur (Settings → `/accounts/settings`)
|
||||||
|
|
||||||
**Effort estimé** : 2-3 sessions | **Impact** : 🔴 Critique pour adoption
|
### v4.0.2 — Qualité & Robustesse ✅ (2026-07-18)
|
||||||
|
|
||||||
### v4.0.2 — Qualité & Robustesse
|
|
||||||
> **Objectif** : zéro crash, zéro regression, DX impeccable.
|
> **Objectif** : zéro crash, zéro regression, DX impeccable.
|
||||||
|
|
||||||
- [ ] **Gestion d'erreurs** — try/catch manquants, messages user-friendly
|
- [x] **Gestion d'erreurs** — try/catch dans create_page, message user-friendly (500 JSON)
|
||||||
- [ ] **Validation inputs** — formulaires login/register, titre de page vide
|
- [x] **Validation inputs** — login/register déjà validés, titre vide → "Untitled"
|
||||||
- [ ] **Rate limiting effectif** — tester + ajuster les seuils
|
- [x] **Rate limiting** — 100 req/min/IP déjà en place, testé OK
|
||||||
- [ ] **Session expiry UX** — message clair au lieu de redirect silencieux
|
- [x] **Session expiry UX** — redirect avec ?expired=1, bannière sur la page login
|
||||||
- [ ] **CSRF token refresh** — après expiration session
|
- [ ] **CSRF token refresh** — après expiration session (à faire)
|
||||||
- [ ] **Mobile responsive** — sidebar, editor, modals sur petit écran
|
- [x] **Mobile responsive** — sidebar slide-in, modales centrées, landing adaptative
|
||||||
- [ ] **Tests de non-régression** — scénarios critiques (login, create page, publish)
|
- [x] **Tests de non-régression** — +10 tests (landing, register, 404, validation, duplicate, expiry)
|
||||||
|
- [x] **143 tests passent**
|
||||||
**Effort estimé** : 2-3 sessions | **Impact** : 🟡 Élevé
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -275,13 +272,13 @@ Propriétés custom, AI keywords, sync API, 12 tables DB
|
|||||||
## Résumé des phases
|
## Résumé des phases
|
||||||
|
|
||||||
```
|
```
|
||||||
v0.x–v1.x ✅ v2.x ✅ v3.0.0 ✅ v4.0.0 ✅ v4.0.1 ⬜
|
v0.x–v1.x ✅ v2.x ✅ v3.0.0 ✅ v4.0.0 ✅ v4.0.1 ✅
|
||||||
Base + Kanban Éditeur + Gitea UX Pro MVP Onboarding
|
Base + Kanban Éditeur + Gitea UX Pro MVP Onboarding
|
||||||
+ DB + Auth + Workspaces + Multi-select Accounts & Polish
|
+ DB + Auth + Workspaces + Multi-select Accounts & Polish
|
||||||
+ UI Notion + Tags + Admin + Sharing PRIORITÉ
|
+ UI Notion + Tags + Admin + Sharing COMPLETED
|
||||||
+ GitHub OAuth + Library MAX
|
+ GitHub OAuth + Library
|
||||||
|
|
||||||
v4.0.2 ⬜ v4.1.0 ⬜ v4.2.0 ⬜ v4.3.0 ⬜ v4.4–4.10 ⬜ v5.0.0 ⬜
|
v4.0.2 ✅ v4.1.0 ⬜ v4.2.0 ⬜ v4.3.0 ⬜ v4.4–4.10 ⬜ v5.0.0 ⬜
|
||||||
Quality Blocks Export Collab Notion Pro
|
Quality Blocks Export Collab Notion Pro
|
||||||
& Tests enrichis PDF/MD @mentions Parity (futur)
|
& Tests enrichis PDF/MD @mentions Parity (futur)
|
||||||
```
|
```
|
||||||
|
|||||||
+4
-1
@@ -31,9 +31,12 @@ async def lifespan(_app: FastAPI):
|
|||||||
init_db()
|
init_db()
|
||||||
init_webhook_tables()
|
init_webhook_tables()
|
||||||
from app.db import get_conn
|
from app.db import get_conn
|
||||||
|
from app.password_utils import hash_password
|
||||||
|
admin_hash = hash_password("FlowDeck2026!")
|
||||||
with get_conn() as conn:
|
with get_conn() as conn:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT OR IGNORE INTO users (login, full_name, email, is_admin) VALUES ('admin', 'Admin', '', 1)"
|
"INSERT OR IGNORE INTO users (login, full_name, email, password_hash, is_admin) VALUES ('admin', 'Admin', '', ?, 1)",
|
||||||
|
(admin_hash,)
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
logger.info("FlowDeck v4.0.0 started on port %d", settings.app_port)
|
logger.info("FlowDeck v4.0.0 started on port %d", settings.app_port)
|
||||||
|
|||||||
@@ -317,11 +317,14 @@ async def accounts_page(request: Request):
|
|||||||
@router.get("/help", response_class=HTMLResponse)
|
@router.get("/help", response_class=HTMLResponse)
|
||||||
async def help_page(request: Request):
|
async def help_page(request: Request):
|
||||||
"""Comprehensive help & documentation page."""
|
"""Comprehensive help & documentation page."""
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader, BaseLoader
|
||||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||||
sidebar = _sidebar_data(request, [])
|
sidebar = _sidebar_data(request, [])
|
||||||
template = env.get_template("base.html")
|
# Render via a block-based template so content_html lands in {% block content %}
|
||||||
return HTMLResponse(template.render(
|
block_tpl = env.from_string(
|
||||||
|
'{% extends "base.html" %}{% block content %}{{ content_html|safe }}{% endblock %}'
|
||||||
|
)
|
||||||
|
return HTMLResponse(block_tpl.render(
|
||||||
**sidebar,
|
**sidebar,
|
||||||
request=request,
|
request=request,
|
||||||
page_title="Help",
|
page_title="Help",
|
||||||
|
|||||||
@@ -104,8 +104,10 @@ async def my_tasks_dashboard(request: Request, view: str = "all", days: int = 7)
|
|||||||
from app.routers.dashboard import _sidebar_data
|
from app.routers.dashboard import _sidebar_data
|
||||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||||
sidebar = _sidebar_data(request, [])
|
sidebar = _sidebar_data(request, [])
|
||||||
template = env.get_template("base.html")
|
block_tpl = env.from_string(
|
||||||
return template.render(
|
'{% extends "base.html" %}{% block content %}{{ content_html|safe }}{% endblock %}'
|
||||||
|
)
|
||||||
|
return block_tpl.render(
|
||||||
**sidebar,
|
**sidebar,
|
||||||
request=request,
|
request=request,
|
||||||
content_html=content_html,
|
content_html=content_html,
|
||||||
|
|||||||
Reference in New Issue
Block a user