v3.0.1: qualité & stabilité — tests, sécurité, UX consolidée
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

🧪 Tests: 73 → 130 (+57 tests)
- Upload API, labels sync, commit history (401/400/502/cached)
- File create/update (sha=null, sha=abc)
- Admin delete cascade (12 tests: oauth, tags, workspaces, pages…)
- Gitea status (linked/unlinked/disconnect)
- OAuth link mode (session, redirect, callback)

🔒 Sécurité
- ContentSecurityPolicyMiddleware (CSP headers)
- RateLimitMiddleware (100 req/min/IP)
- Pydantic models: ErrorResponse, SuccessResponse
- Input validation upload (10MB, allowed extensions)
- Pydantic request models

🎨 UX
- static/css/design-tokens.css (500 lines, thèmes + skeletons)
- Toast system: 16 alert() remplacés par toast()
- 59 lignes CSS dupliquées retirées (6 templates)
- Skeletons cohérents sur toutes les vues

⚡ Performance
- Cache TTL sur get_file_commits (consistant avec les autres méthodes)
This commit is contained in:
2026-07-13 23:08:53 -04:00
parent e04b3a38a4
commit de40c2d83e
12 changed files with 1679 additions and 88 deletions
+3 -7
View File
@@ -152,10 +152,6 @@
/* Inline rename */
.inline-rename-input{background:var(--bg);border:1px solid var(--accent);border-radius:4px;color:var(--text);font-size:13px;padding:2px 6px;outline:none;min-width:100px;}
/* Loading skeleton */
.skeleton{background:linear-gradient(90deg,var(--bg-tertiary) 25%,var(--bg-hover) 50%,var(--bg-tertiary) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:4px;height:16px;margin:4px 0;}
@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
/* Drag count badge */
.drag-badge{position:fixed;pointer-events:none;z-index:999;background:var(--accent);color:#fff;font-size:12px;font-weight:700;padding:2px 8px;border-radius:10px;transform:translate(-50%,-50%);}
@@ -1267,7 +1263,7 @@ window._wsInitData = (function() {
if (targetId) {
window.location = '/local-workspace?folder=' + targetId;
} else {
alert('Path not found: ' + parts.join('/'));
window.showToast('Path not found: ' + parts.join('/'), 'error');
}
},
_findFolderByPath(nodes, parts, idx) {
@@ -1807,10 +1803,10 @@ window._wsInitData = (function() {
if (r.ok) {
this._reloadAfterAction();
} else {
alert('Move failed');
window.showToast('Move failed', 'error');
}
} catch(e) {
alert('Move failed: ' + e.message);
window.showToast('Move failed: ' + e.message, 'error');
}
},