changement des notes légers: rendu le pipeline plus fluide et ai effacé des pages redondantes ou encombrantes
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: test
|
||||
description: Describe what this custom agent does and when to use it.
|
||||
argument-hint: The inputs this agent expects, e.g., "a task to implement" or "a question to answer".
|
||||
# tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed.
|
||||
---
|
||||
|
||||
<!-- Tip: Use /create-agent in chat to generate content with agent assistance -->
|
||||
|
||||
Define what this custom agent does, including its behavior, capabilities, and any specific instructions for its operation.
|
||||
Binary file not shown.
Binary file not shown.
+64
-5
@@ -8,7 +8,7 @@ import os
|
||||
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file
|
||||
from flask_login import login_required, current_user
|
||||
from extensions import db, hash_password
|
||||
from models import User, ROLES, ESPORT_GAMES, PlayerDisponibility, UserGamertag, GAME_PLATFORMS, Contract, OrgTeam, CoachAvailability, TeamNote, PersonalNote, OneOnOneRequest, Match, Team, TeamMember, MatchParticipant, Tryout
|
||||
from models import User, ROLES, ESPORT_GAMES, PlayerDisponibility, UserGamertag, GAME_PLATFORMS, Contract, OrgTeam, CoachAvailability, TeamNote, PersonalNote, OneOnOneRequest, Match, Team, TeamMember, MatchParticipant, Tryout, TryoutRegistration
|
||||
from werkzeug.utils import secure_filename
|
||||
from datetime import datetime, timedelta, date as date_type
|
||||
import requests
|
||||
@@ -1132,6 +1132,60 @@ def manage_personal_notes():
|
||||
org_team=org_team)
|
||||
|
||||
|
||||
@users_bp.route('/notes', methods=['GET'])
|
||||
@login_required
|
||||
def notes_dashboard():
|
||||
"""Unified notes dashboard for coaches.
|
||||
|
||||
GET: Render the combined notes management page with both team and personal notes forms.
|
||||
|
||||
Returns:
|
||||
Response: Rendered notes dashboard template.
|
||||
"""
|
||||
if current_user.role != 'coach':
|
||||
flash('Only coaches can manage notes.', 'danger')
|
||||
return redirect(url_for('main.dashboard'))
|
||||
|
||||
# Get the coach's team
|
||||
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
|
||||
players = []
|
||||
if org_team:
|
||||
players = User.query.filter_by(role='player', team_id=org_team.id).order_by(User.full_name).all()
|
||||
|
||||
# Get existing team notes
|
||||
team_notes = []
|
||||
latest_team_note = None
|
||||
if org_team:
|
||||
team_notes = TeamNote.query.filter_by(org_team_id=org_team.id).order_by(TeamNote.created_at.desc()).all()
|
||||
latest_team_note = team_notes[0] if team_notes else None
|
||||
|
||||
# Get all personal notes for players on this team
|
||||
personal_notes = []
|
||||
if org_team:
|
||||
personal_notes = PersonalNote.query.filter(
|
||||
PersonalNote.player_id.in_([p.id for p in players])
|
||||
).order_by(PersonalNote.created_at.desc()).all()
|
||||
|
||||
# Get available matches and tryouts for context
|
||||
matches = []
|
||||
tryouts = []
|
||||
teams = []
|
||||
if current_user.role == 'coach' and org_team:
|
||||
tryouts = Tryout.query.filter_by(target_org_team_id=org_team.id).order_by(Tryout.date.desc()).all()
|
||||
matches = Match.query.join(Tryout).filter(Tryout.target_org_team_id == org_team.id).order_by(Match.date.desc()).all()
|
||||
teams = Team.query.order_by(Team.name).all()
|
||||
|
||||
return render_template('pages/notes.html',
|
||||
org_team=org_team,
|
||||
players=players,
|
||||
team_notes=team_notes,
|
||||
latest_team_note=latest_team_note,
|
||||
personal_notes=personal_notes,
|
||||
matches=matches,
|
||||
tryouts=tryouts,
|
||||
teams=teams)
|
||||
|
||||
|
||||
# Note source types for filtering
|
||||
NOTE_SOURCE_MATCH = 'match'
|
||||
NOTE_SOURCE_TRYOUT = 'tryout'
|
||||
@@ -1256,7 +1310,7 @@ def add_personal_note():
|
||||
db.session.add(note)
|
||||
db.session.commit()
|
||||
flash('Personal note added successfully!', 'success')
|
||||
return redirect(url_for('users.my_notes'))
|
||||
return redirect(url_for('users.notes_dashboard'))
|
||||
|
||||
return render_template('pages/add_personal_note.html',
|
||||
players=players,
|
||||
@@ -1362,6 +1416,7 @@ def add_note_from_tryout(tryout_id):
|
||||
tryout = Tryout.query.get_or_404(tryout_id)
|
||||
|
||||
# Check permissions
|
||||
org_team = None
|
||||
if current_user.role == 'coach':
|
||||
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
|
||||
if not org_team or (tryout.target_org_team_id and tryout.target_org_team_id != org_team.id):
|
||||
@@ -1372,8 +1427,8 @@ def add_note_from_tryout(tryout_id):
|
||||
registrations = TryoutRegistration.query.filter_by(tryout_id=tryout_id).all()
|
||||
player_ids = [r.player_id for r in registrations]
|
||||
|
||||
# If coach, filter to only their team players
|
||||
if current_user.role == 'coach' and org_team:
|
||||
# If coach, filter to only their team players; otherwise include all
|
||||
if org_team:
|
||||
players = User.query.filter(User.id.in_(player_ids), User.team_id == org_team.id).order_by(User.full_name).all()
|
||||
else:
|
||||
players = User.query.filter(User.id.in_(player_ids)).order_by(User.full_name).all()
|
||||
@@ -1403,7 +1458,11 @@ def add_note_from_tryout(tryout_id):
|
||||
flash('Personal note added successfully!', 'success')
|
||||
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
|
||||
|
||||
# Allow pre-selecting a player via query parameter
|
||||
preselected_player_id = request.args.get('player_id', type=int)
|
||||
|
||||
return render_template('pages/add_note_from_tryout.html',
|
||||
tryout=tryout,
|
||||
players=players,
|
||||
team_notes=team_notes)
|
||||
team_notes=team_notes,
|
||||
preselected_player_id=preselected_player_id)
|
||||
|
||||
@@ -95,15 +95,9 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url_for('users.manage_team_notes') }}" class="{% if request.endpoint == 'users.manage_team_notes' %}active{% endif %}">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>Team Notes</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url_for('users.manage_personal_notes') }}" class="{% if request.endpoint == 'users.manage_personal_notes' %}active{% endif %}">
|
||||
<a href="{{ url_for('users.notes_dashboard') }}" class="{% if request.endpoint == 'users.notes_dashboard' or request.endpoint == 'users.manage_team_notes' or request.endpoint == 'users.manage_personal_notes' %}active{% endif %}">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
<span>Personal Notes</span>
|
||||
<span>Notes</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<select name="player_id" id="player_id" class="form-select" required>
|
||||
<option value="">-- Select a Player --</option>
|
||||
{% for player in players %}
|
||||
<option value="{{ player.id }}">{{ player.full_name }}</option>
|
||||
<option value="{{ player.id }}" {% if preselected_player_id == player.id %}selected{% endif %}>{{ player.full_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -127,6 +127,9 @@
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> {% if existing_eval %}Update Evaluation{% else %}Submit Evaluation{% endif %}
|
||||
</button>
|
||||
<a href="{{ url_for('users.notes_dashboard') }}" class="btn btn-outline" title="Add note for this player">
|
||||
<i class="fas fa-sticky-note"></i> Add Note
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Notes - TryoutPro{% endblock %}
|
||||
{% block page_title %}Notes{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Notes</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard-grid">
|
||||
<!-- Add Team Notes Section -->
|
||||
{% if org_team %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users"></i> Team Notes</h3>
|
||||
<span class="badge badge-esport">{{ org_team.name }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('users.manage_team_notes') }}" class="form" id="teamNotesForm">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="team_notes_content">Team Notes Content</label>
|
||||
<textarea name="content" id="team_notes_content" class="form-textarea" rows="4" placeholder="Enter improvement suggestions and notes for your team...">{{ latest_team_note.content if latest_team_note else '' }}</textarea>
|
||||
<p class="form-text">These notes will be visible to all players on your team.</p>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> {% if latest_team_note %}Update{% else %}Add{% endif %} Team Notes
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Add Personal Note Section -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-user-friends"></i> Add Personal Note</h3>
|
||||
{% if org_team %}
|
||||
<span class="badge badge-esport">{{ org_team.name }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('users.add_personal_note') }}" class="form" id="personalNoteForm">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="player_id">Select Player</label>
|
||||
<select name="player_id" id="player_id" class="form-select" required>
|
||||
<option value="">-- Select a Player --</option>
|
||||
{% for player in players %}
|
||||
<option value="{{ player.id }}">{{ player.full_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note_content">Note Content</label>
|
||||
<textarea name="content" id="note_content" class="form-textarea" rows="3" placeholder="Enter personal feedback or coaching tips for this player..." required></textarea>
|
||||
<p class="form-text">These notes will only be visible to the selected player.</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="context">Context (Optional)</label>
|
||||
<p class="form-text text-muted">Link this note to a specific match, tryout, or team for better organization.</p>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="note_match_id">Match</label>
|
||||
<select name="match_id" id="note_match_id" class="form-select">
|
||||
<option value="">-- Select Match --</option>
|
||||
{% for match in matches %}
|
||||
<option value="{{ match.id }}">{{ match.title }} - {{ match.date.strftime('%m/%d/%Y') }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="note_tryout_id">Tryout</label>
|
||||
<select name="tryout_id" id="note_tryout_id" class="form-select">
|
||||
<option value="">-- Select Tryout --</option>
|
||||
{% for tryout in tryouts %}
|
||||
<option value="{{ tryout.id }}">{{ tryout.title }} - {{ tryout.date.strftime('%m/%d/%Y') }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="note_team_id">Team</label>
|
||||
<select name="team_id" id="note_team_id" class="form-select">
|
||||
<option value="">-- Select Team --</option>
|
||||
{% for team in teams %}
|
||||
<option value="{{ team.id }}">{{ team.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> Add Note
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-grid mt-4">
|
||||
<!-- Team Notes History -->
|
||||
{% if org_team and team_notes %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-history"></i> Team Notes History</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Last Updated</th>
|
||||
<th>Content Preview</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for note in team_notes %}
|
||||
<tr>
|
||||
<td>{{ note.updated_at.strftime('%B %d, %Y at %I:%M %p') if note.updated_at else 'Unknown date' }}</td>
|
||||
<td>{{ note.content[:100] if note.content else '' }}{% if note.content and note.content|length > 100 %}...{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Personal Notes History -->
|
||||
{% if personal_notes %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-sticky-note"></i> Recent Personal Notes</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="detail-grid">
|
||||
{% for note in personal_notes %}
|
||||
<div class="detail-item full-width mb-4">
|
||||
<span class="detail-label">
|
||||
<i class="fas fa-user"></i> {{ note.player.full_name if note.player else 'Unknown Player' }} -
|
||||
<span class="text-muted">{{ note.created_at.strftime('%B %d, %Y') if note.created_at else 'Unknown date' }}</span>
|
||||
</span>
|
||||
<span class="detail-value">{{ note.content | nl2br if note.content else '' }}</span>
|
||||
<span class="detail-label text-muted small">From: {{ note.coach.full_name if note.coach else 'Unknown Coach' }}</span>
|
||||
{% if note.match_id or note.team_id or note.tryout_id %}
|
||||
<div class="mt-2">
|
||||
{% if note.match_id and note.match %}
|
||||
<span class="badge badge-info" title="From match"><i class="fas fa-futbol"></i> {{ note.match.title }}</span>
|
||||
{% endif %}
|
||||
{% if note.team_id and note.team %}
|
||||
<span class="badge badge-warning" title="From team"><i class="fas fa-users"></i> {{ note.team.name }}</span>
|
||||
{% endif %}
|
||||
{% if note.tryout_id and note.tryout %}
|
||||
<span class="badge badge-success" title="From tryout"><i class="fas fa-calendar-alt"></i> {{ note.tryout.title }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -66,6 +66,11 @@
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if current_user.role == 'coach' and team.coach_id == current_user.id %}
|
||||
<a href="{{ url_for('users.notes_dashboard') }}" class="btn btn-sm btn-primary" title="Add Notes">
|
||||
<i class="fas fa-sticky-note"></i> Notes
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
@@ -155,10 +155,13 @@
|
||||
<span class="badge badge-warning">Pending</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=p.id) }}" class="btn btn-sm btn-primary">
|
||||
<td class="eval-actions">
|
||||
<a href="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=p.id) }}" class="btn btn-sm btn-primary" title="Evaluate player">
|
||||
<i class="fas fa-edit"></i> {% if player_eval_status.get(p.id) %}Edit{% else %}Evaluate{% endif %}
|
||||
</a>
|
||||
<a href="{{ url_for('users.add_note_from_tryout', tryout_id=tryout.id) }}?player_id={{ p.id }}" class="btn btn-sm btn-outline" title="Add note for {{ p.full_name }}">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user