fix(vwb): noms workflows lisibles + bibliothèque captures persistante
Some checks failed
security-audit / Bandit (scan statique) (push) Successful in 11s
security-audit / pip-audit (CVE dépendances) (push) Successful in 11s
security-audit / Scan secrets (grep) (push) Successful in 8s
tests / Lint (ruff + black) (push) Successful in 14s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped

CSS : le dropdown héritait color:white du header → forcé #212121
sur .workflow-dropdown et .dropdown-item .item-name

Bibliothèque : migration localStorage → backend (capture_library.json)
- GET/POST /api/v3/capture/library (max 50 captures)
- loadLibraryAsync() charge depuis backend, fallback localStorage
- saveLibrary() écrit dans les deux (localStorage + backend)
- capture_library.json gitignored

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-04-19 00:04:30 +02:00
parent 95fddeebb3
commit e3efef2fe7
7 changed files with 205 additions and 38 deletions

View File

@@ -5,10 +5,13 @@ Gestion des captures d'écran et création d'ancres visuelles
POST /api/v3/capture/screen → Capture écran
POST /api/v3/capture/select → Crée ancre depuis sélection
GET /api/v3/anchor/{id}/image → Image de l'ancre
GET /api/v3/capture/library → Charge la bibliothèque de captures
POST /api/v3/capture/library → Sauvegarde la bibliothèque de captures
"""
from flask import jsonify, request, send_file
from datetime import datetime
import json
import uuid
import os
import base64
@@ -22,6 +25,10 @@ from db.models import db, Step, VisualAnchor, get_session_state
ANCHORS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data', 'anchors')
os.makedirs(ANCHORS_DIR, exist_ok=True)
# Fichier pour la bibliothèque de captures (persistance disque)
DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data')
CAPTURE_LIBRARY_PATH = os.path.join(DATA_DIR, 'capture_library.json')
def generate_id(prefix: str) -> str:
"""Génère un ID unique"""
@@ -316,3 +323,75 @@ def get_anchor_base64(anchor_id: str):
'success': False,
'error': str(e)
}), 500
# ── Bibliothèque de captures (persistance disque) ────────────────────────
@api_v3_bp.route('/capture/library', methods=['GET'])
def get_capture_library():
"""
Charge la bibliothèque de captures depuis le disque.
Response:
{
"success": true,
"library": [ { id, capture, timestamp, sessionId, favorite }, ... ]
}
"""
try:
if os.path.exists(CAPTURE_LIBRARY_PATH):
with open(CAPTURE_LIBRARY_PATH, 'r', encoding='utf-8') as f:
library = json.load(f)
else:
library = []
return jsonify({
'success': True,
'library': library
})
except Exception as e:
print(f"⚠️ [CaptureLibrary] Erreur lecture: {e}")
return jsonify({
'success': True,
'library': []
})
@api_v3_bp.route('/capture/library', methods=['POST'])
def save_capture_library():
"""
Sauvegarde la bibliothèque de captures sur disque.
Request:
{
"library": [ { id, capture, timestamp, sessionId, favorite }, ... ]
}
Response:
{
"success": true,
"count": 5
}
"""
try:
data = request.get_json() or {}
library = data.get('library', [])
# Limiter à 50 captures pour éviter un fichier trop gros
library = library[:50]
with open(CAPTURE_LIBRARY_PATH, 'w', encoding='utf-8') as f:
json.dump(library, f, ensure_ascii=False)
return jsonify({
'success': True,
'count': len(library)
})
except Exception as e:
print(f"⚠️ [CaptureLibrary] Erreur écriture: {e}")
return jsonify({
'success': False,
'error': str(e)
}), 500