first commit
This commit is contained in:
commit
e6c52820cd
227 changed files with 16156 additions and 0 deletions
111
modules/projects/routes.py
Normal file
111
modules/projects/routes.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
import os
|
||||
import json
|
||||
from typing import Dict, List
|
||||
from flask import Blueprint, render_template, request
|
||||
|
||||
from modules.projects.project_handler import ProjectHandler
|
||||
|
||||
projects_bp = Blueprint('projects', __name__)
|
||||
_handler = ProjectHandler()
|
||||
|
||||
def _project_root() -> str:
|
||||
# 3 niveaux au dessus de modules/projects/ = racine projet
|
||||
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
def _clients_dir() -> str:
|
||||
return os.path.join(_project_root(), 'Data', 'clients')
|
||||
|
||||
def _load_clients_index() -> Dict[str, str]:
|
||||
"""
|
||||
Retourne un dict {client_id: client_name lisible}
|
||||
client_id = nom de fichier sans extension dans Data/clients
|
||||
"""
|
||||
idx: Dict[str, str] = {}
|
||||
cdir = _clients_dir()
|
||||
if not os.path.isdir(cdir):
|
||||
return idx
|
||||
for fname in os.listdir(cdir):
|
||||
if not fname.endswith('.json'):
|
||||
continue
|
||||
client_id = os.path.splitext(fname)[0]
|
||||
path = os.path.join(cdir, fname)
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
name = data.get('client_name') or client_id.replace('_', ' ').title()
|
||||
idx[client_id] = name
|
||||
except Exception:
|
||||
idx[client_id] = client_id.replace('_', ' ').title()
|
||||
return idx
|
||||
|
||||
def _list_all_projects() -> List:
|
||||
"""
|
||||
Parcourt Data/projects/<client_id> et retourne la liste des objets Project.
|
||||
"""
|
||||
base = _handler.base_dir
|
||||
projects = []
|
||||
if os.path.isdir(base):
|
||||
for client_id in os.listdir(base):
|
||||
client_path = os.path.join(base, client_id)
|
||||
if os.path.isdir(client_path):
|
||||
projects.extend(_handler.list_projects(client_id))
|
||||
return projects
|
||||
|
||||
@projects_bp.route('/projects', methods=['GET'])
|
||||
def projects_index():
|
||||
clients_idx = _load_clients_index()
|
||||
selected_client = request.args.get('client_id', '').strip()
|
||||
query = request.args.get('q', '').strip().lower()
|
||||
|
||||
# Charger tous les projets
|
||||
projects = _list_all_projects()
|
||||
|
||||
# Filtre par client
|
||||
if selected_client:
|
||||
projects = [p for p in projects if p.client_id == selected_client]
|
||||
|
||||
# Recherche plein texte basique
|
||||
if query:
|
||||
def match(p) -> bool:
|
||||
hay = ' '.join([
|
||||
p.name or '',
|
||||
p.status or '',
|
||||
p.description or ''
|
||||
]).lower()
|
||||
return query in hay
|
||||
projects = [p for p in projects if match(p)]
|
||||
|
||||
# Tri par updated_at décroissante
|
||||
projects.sort(key=lambda p: p.updated_at or '', reverse=True)
|
||||
|
||||
# Transformer pour la vue (nom client)
|
||||
def client_name_for(pid: str) -> str:
|
||||
return clients_idx.get(pid, pid.replace('_', ' ').title())
|
||||
|
||||
view_projects = []
|
||||
for p in projects:
|
||||
view_projects.append({
|
||||
'id': p.id,
|
||||
'client_id': p.client_id,
|
||||
'client_name': client_name_for(p.client_id),
|
||||
'name': p.name,
|
||||
'status': p.status,
|
||||
'start_date': p.start_date,
|
||||
'end_date': p.end_date,
|
||||
'budget': p.budget,
|
||||
'updated_at': p.updated_at
|
||||
})
|
||||
|
||||
# Liste triée des clients pour le sélecteur
|
||||
clients_for_select = sorted(
|
||||
[{'id': cid, 'name': cname} for cid, cname in clients_idx.items()],
|
||||
key=lambda c: c['name'].lower()
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'projects/all_projects.html',
|
||||
projects=view_projects,
|
||||
clients=clients_for_select,
|
||||
selected_client=selected_client,
|
||||
q=request.args.get('q', '').strip()
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue