feat(api): fix lint

This commit is contained in:
Alejandro Vazquez
2026-03-27 14:52:16 -03:00
parent 192d1dd41c
commit 402f8e07a8
11 changed files with 361 additions and 55 deletions
+43 -43
View File
@@ -1,65 +1,65 @@
from flask import Flask
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_cors import CORS
from dotenv import load_dotenv
from flask_babel import Babel, gettext as _
from config.config import Config
import os
load_dotenv()
# Initialize extensions
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()
login_manager = LoginManager()
cors = CORS()
babel = Babel()
def create_app():
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
# Configuration
app.config.from_object(Config)
# Initialize extensions
# Initialize extensions with app
db.init_app(app)
login_manager.init_app(app)
migrate.init_app(app, db)
CORS(app)
login_manager.init_app(app)
cors.init_app(app)
# Login manager configuration
login_manager.login_view = 'auth.login'
login_manager.login_message = 'Please log in to access this page.'
@login_manager.user_loader
def load_user(user_id):
from app.models.user import User
return User.query.get(int(user_id))
login_manager.login_message = 'Por favor inicia sesión para acceder a esta página.'
login_manager.login_message_category = 'info'
# Register blueprints
from app.routes.auth import auth_bp
from app.routes.main import main_bp
from app.routes.classrooms import classrooms_bp
from app.routes.schedule import schedule_bp
from app.routes import auth_bp, classrooms_bp, main_bp, schedule_bp
app.register_blueprint(auth_bp)
app.register_blueprint(main_bp)
app.register_blueprint(classrooms_bp, url_prefix='/classrooms')
app.register_blueprint(schedule_bp, url_prefix='/schedule')
app.register_blueprint(auth_bp, url_prefix="/")
app.register_blueprint(classrooms_bp, url_prefix="/classrooms")
app.register_blueprint(main_bp, url_prefix="/")
app.register_blueprint(schedule_bp, url_prefix="/schedule")
# Create database tables
with app.app_context():
db.create_all()
# Babel language selector
@app.context_processor
def inject_conf_vars():
return dict(
languages=app.config['LANGUAGES'],
current_lang=request.session.get('language', request.accept_languages.best_match(app.config['LANGUAGES']) or app.config['BABEL_DEFAULT_LOCALE'])
)
# Language selector function
def get_locale():
# 1. Check if language is explicitly set in URL parameters
if request.args.get('lang'):
lang = request.args.get('lang')
if lang in app.config['LANGUAGES']:
return lang
# Create default admin user if not exists
from app.models.user import User
if not User.query.filter_by(email='admin@edu-space.com').first():
admin = User(
email='admin@edu-space.com',
name='System Administrator',
role='admin'
)
admin.set_password('admin123') # Change this in production
db.session.add(admin)
db.session.commit()
# 2. Check if language is stored in session
if 'language' in request.session:
return request.session['language']
# 3. Check browser language preference
return request.accept_languages.best_match(app.config['LANGUAGES']) or app.config['BABEL_DEFAULT_LOCALE']
# Configure Babel
babel.init_app(app, locale_selector=get_locale)
return app
+6
View File
@@ -0,0 +1,6 @@
from .auth import auth_bp
from .classrooms import classrooms_bp
from .main import main_bp
from .schedule import schedule_bp
__all__ = ['auth_bp', 'classrooms_bp', 'main_bp', 'schedule_bp']
+11 -2
View File
@@ -1,4 +1,4 @@
from flask import Blueprint, render_template, jsonify
from flask import Blueprint, render_template, jsonify, redirect, url_for, session, request
from flask_login import login_required, current_user
from app.models.reservation import Reservation
from app.models.classroom import Classroom
@@ -6,6 +6,7 @@ from app.models.subject import Subject
from app.models.subject import Commission
from datetime import datetime, timedelta
from sqlalchemy import func
from flask_babel import gettext as _
main_bp = Blueprint('main', __name__)
@@ -105,4 +106,12 @@ def dashboard_stats_api():
'today_reservations': today_reservations,
'week_reservations': week_reservations,
'monthly_data': list(reversed(monthly_data))
})
})
@main_bp.route('/set_language/<language>')
def set_language(language=None):
if language not in ['en', 'es']:
language = 'en'
session['language'] = language
return redirect(request.referrer or url_for('main.dashboard'))
+27 -2
View File
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<html lang="{{ session.language or request.accept_languages.best_match(['es', 'en']) or 'en' }}" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Edu-Space Admin{% endblock %}</title>
<title>{% block title %}{% trans %}Edu-Space Admin{% endtrans %}{% endblock %}</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
@@ -69,6 +69,31 @@
</ul>
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
<i class="bi bi-person-circle"></i> {{ current_user.first_name }} {{ current_user.last_name }}
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="{{ url_for('auth.profile') }}">
<i class="bi bi-person"></i> Profile
</a></li>
<li><a class="dropdown-item" href="{{ url_for('auth.change_password') }}">
<i class="bi bi-key"></i> Change Password
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="{{ url_for('auth.logout') }}">
<i class="bi bi-box-arrow-right"></i> Logout
</a></li>
</ul>
</li>
</ul>
<ul class="navbar-nav">
<!-- Language Switcher -->
<li class="nav-item">
{% include 'partials/language_switcher.html' %}
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
<i class="bi bi-person-circle"></i> {{ current_user.first_name }} {{ current_user.last_name }}
+7 -7
View File
@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}Dashboard - Edu-Space Admin{% endblock %}
{% block title %}{% trans %}Dashboard - Edu-Space Admin{% endtrans %}{% endblock %}
{% block content %}
{% if current_user.is_authenticated %}
@@ -9,8 +9,8 @@
<div class="row mb-4">
<div class="col-12">
<h1 class="h3 mb-0">
<i class="bi bi-speedometer2 text-primary"></i> Dashboard
<small class="text-muted ms-2">Overview</small>
<i class="bi bi-speedometer2 text-primary"></i> {% trans %}Dashboard{% endtrans %}
<small class="text-muted ms-2">{% trans %}Overview{% endtrans %}</small>
</h1>
</div>
</div>
@@ -22,7 +22,7 @@
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">Total Classrooms</h6>
<h6 class="text-muted mb-2">{% trans %}Total Classrooms{% endtrans %}</h6>
<h2 class="mb-0">{{ stats.total_classrooms }}</h2>
</div>
<div class="bg-primary bg-opacity-10 rounded-circle p-3">
@@ -38,7 +38,7 @@
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">Total Subjects</h6>
<h6 class="text-muted mb-2">{% trans %}Total Subjects{% endtrans %}</h6>
<h2 class="mb-0">{{ stats.total_subjects }}</h2>
</div>
<div class="bg-success bg-opacity-10 rounded-circle p-3">
@@ -54,7 +54,7 @@
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">Today's Reservations</h6>
<h6 class="text-muted mb-2">{% trans %}Today's Reservations{% endtrans %}</h6>
<h2 class="mb-0">{{ stats.today_reservations }}</h2>
</div>
<div class="bg-info bg-opacity-10 rounded-circle p-3">
@@ -70,7 +70,7 @@
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">This Week</h6>
<h6 class="text-muted mb-2">{% trans %}This Week{% endtrans %}</h6>
<h2 class="mb-0">{{ stats.week_reservations }}</h2>
</div>
<div class="bg-warning bg-opacity-10 rounded-circle p-3">
@@ -0,0 +1,27 @@
{% if config.LANGUAGES|length > 1 %}
<div class="dropdown language-switcher">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-globe"></i>
{% if session.language == 'es' or (session.language is none and request.accept_languages.best_match(['es', 'en']) == 'es') %}
Spanish
{% else %}
English
{% endif %}
</button>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="languageDropdown">
{% set current_lang = session.language or request.accept_languages.best_match(['es', 'en']) or 'en' %}
<li>
<a class="dropdown-item {% if current_lang == 'en' %}active{% endif %}"
href="{{ url_for('main.set_language', language='en') }}">
<i class="bi bi-check-circle-fill text-primary me-2"></i>English
</a>
</li>
<li>
<a class="dropdown-item {% if current_lang == 'es' %}active{% endif %}"
href="{{ url_for('main.set_language', language='es') }}">
<i class="bi bi-check-circle-fill text-primary me-2"></i>Español
</a>
</li>
</ul>
</div>
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.i18n
+7 -1
View File
@@ -12,4 +12,10 @@ class Config:
# Upload settings
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB max file size
UPLOAD_FOLDER = 'app/static/uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
# Internationalization
LANGUAGES = ['en', 'es']
BABEL_DEFAULT_LOCALE = 'en'
BABEL_DEFAULT_TIMEZONE = 'UTC'
BABEL_TRANSLATION_DIRECTORIES = 'translations'
+2
View File
@@ -4,6 +4,7 @@ Flask-Login==0.6.3
Flask-WTF==1.2.1
Flask-Migrate==4.0.5
Flask-CORS==6.0.2
Flask-Babel==4.0.0
WTForms==3.1.0
Werkzeug==3.0.1
SQLAlchemy==2.0.23
@@ -14,3 +15,4 @@ python-dateutil==2.8.2
Pillow==10.1.0
email_validator>=2.0.0
psycopg2-binary==2.9.9
Babel==2.14.0
+114
View File
@@ -0,0 +1,114 @@
# English (en) translations for Edu-Space Admin
#
msgid ""
msgstr ""
"Project-Id-Version: Edu-Space Admin 1.0\n"
"POT-Creation-Date: 2024-01-01 00:00+0000\n"
"PO-Revision-Date: 2024-01-01 00:00+0000\n"
"Last-Translator: Admin <admin@edu-space.com>\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pybabel\n"
#: app/templates/base.html:6
msgid "Edu-Space Admin"
msgstr "Edu-Space Admin"
#: app/templates/dashboard.html:3
msgid "Dashboard - Edu-Space Admin"
msgstr "Dashboard - Edu-Space Admin"
#: app/templates/dashboard.html:12
msgid "Dashboard"
msgstr "Dashboard"
#: app/templates/dashboard.html:13
msgid "Overview"
msgstr "Overview"
#: app/templates/dashboard.html:25
msgid "Total Classrooms"
msgstr "Total Classrooms"
#: app/templates/dashboard.html:41
msgid "Total Subjects"
msgstr "Total Subjects"
#: app/templates/dashboard.html:57
msgid "Today's Reservations"
msgstr "Today's Reservations"
#: app/templates/dashboard.html:73
msgid "This Week"
msgstr "This Week"
#: app/templates/dashboard.html:91
msgid "Monthly Reservations"
msgstr "Monthly Reservations"
#: app/templates/dashboard.html:105
msgid "Quick Actions"
msgstr "Quick Actions"
#: app/templates/dashboard.html:111
msgid "Add Classroom"
msgstr "Add Classroom"
#: app/templates/dashboard.html:114
msgid "New Reservation"
msgstr "New Reservation"
#: app/templates/dashboard.html:117
msgid "Today's Schedule"
msgstr "Today's Schedule"
#: app/templates/dashboard.html:120
msgid "View Calendar"
msgstr "View Calendar"
#: app/templates/dashboard.html:135
msgid "Upcoming Reservations (Next 7 Days)"
msgstr "Upcoming Reservations (Next 7 Days)"
#: app/templates/dashboard.html:138
msgid "View All"
msgstr "View All"
#: app/templates/dashboard.html:148
#: app/templates/dashboard.html:149
#: app/templates/dashboard.html:150
#: app/templates/dashboard.html:151
#: app/templates/dashboard.html:152
#: app/templates/dashboard.html:153
msgid "Date & Time"
msgstr "Date & Time"
#: app/templates/dashboard.html:149
msgid "Classroom"
msgstr "Classroom"
#: app/templates/dashboard.html:150
msgid "Subject"
msgstr "Subject"
#: app/templates/dashboard.html:151
msgid "Teacher"
msgstr "Teacher"
#: app/templates/dashboard.html:152
msgid "Status"
msgstr "Status"
#: app/templates/dashboard.html:153
msgid "Actions"
msgstr "Actions"
#: app/templates/dashboard.html:171
msgid "View"
msgstr "View"
#: app/templates/dashboard.html:182
msgid "No upcoming reservations in the next 7 days"
msgstr "No upcoming reservations in the next 7 days"
+114
View File
@@ -0,0 +1,114 @@
# Spanish (es) translations for Edu-Space Admin
#
msgid ""
msgstr ""
"Project-Id-Version: Edu-Space Admin 1.0\n"
"POT-Creation-Date: 2024-01-01 00:00+0000\n"
"PO-Revision-Date: 2024-01-01 00:00+0000\n"
"Last-Translator: Admin <admin@edu-space.com>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pybabel\n"
#: app/templates/base.html:6
msgid "Edu-Space Admin"
msgstr "Admin Edu-Space"
#: app/templates/dashboard.html:3
msgid "Dashboard - Edu-Space Admin"
msgstr "Panel - Admin Edu-Space"
#: app/templates/dashboard.html:12
msgid "Dashboard"
msgstr "Panel"
#: app/templates/dashboard.html:13
msgid "Overview"
msgstr "Resumen"
#: app/templates/dashboard.html:25
msgid "Total Classrooms"
msgstr "Total de Aulas"
#: app/templates/dashboard.html:41
msgid "Total Subjects"
msgstr "Total de Materias"
#: app/templates/dashboard.html:57
msgid "Today's Reservations"
msgstr "Reservas de Hoy"
#: app/templates/dashboard.html:73
msgid "This Week"
msgstr "Esta Semana"
#: app/templates/dashboard.html:91
msgid "Monthly Reservations"
msgstr "Reservas Mensuales"
#: app/templates/dashboard.html:105
msgid "Quick Actions"
msgstr "Acciones Rápidas"
#: app/templates/dashboard.html:111
msgid "Add Classroom"
msgstr "Agregar Aula"
#: app/templates/dashboard.html:114
msgid "New Reservation"
msgstr "Nueva Reserva"
#: app/templates/dashboard.html:117
msgid "Today's Schedule"
msgstr "Horario de Hoy"
#: app/templates/dashboard.html:120
msgid "View Calendar"
msgstr "Ver Calendario"
#: app/templates/dashboard.html:135
msgid "Upcoming Reservations (Next 7 Days)"
msgstr "Próximas Reservas (Próximos 7 Días)"
#: app/templates/dashboard.html:138
msgid "View All"
msgstr "Ver Todas"
#: app/templates/dashboard.html:148
#: app/templates/dashboard.html:149
#: app/templates/dashboard.html:150
#: app/templates/dashboard.html:151
#: app/templates/dashboard.html:152
#: app/templates/dashboard.html:153
msgid "Date & Time"
msgstr "Fecha y Hora"
#: app/templates/dashboard.html:149
msgid "Classroom"
msgstr "Aula"
#: app/templates/dashboard.html:150
msgid "Subject"
msgstr "Materia"
#: app/templates/dashboard.html:151
msgid "Teacher"
msgstr "Profesor"
#: app/templates/dashboard.html:152
msgid "Status"
msgstr "Estado"
#: app/templates/dashboard.html:153
msgid "Actions"
msgstr "Acciones"
#: app/templates/dashboard.html:171
msgid "View"
msgstr "Ver"
#: app/templates/dashboard.html:182
msgid "No upcoming reservations in the next 7 days"
msgstr "No hay próximas reservas en los próximos 7 días"