fix(admin): resolver pantalla en blanco al editar ficha de usuario (GET /admin/users/edit/:id)
This commit is contained in:
@@ -345,6 +345,20 @@ def create_user():
|
|||||||
'user': user.to_dict()
|
'user': user.to_dict()
|
||||||
}), 201
|
}), 201
|
||||||
|
|
||||||
|
@api_admin_bp.route('/users/<int:id>', methods=['GET'])
|
||||||
|
@jwt_required
|
||||||
|
def get_user_by_id(id):
|
||||||
|
user = User.query.get_or_404(id)
|
||||||
|
d = user.to_dict()
|
||||||
|
d['role_obj'] = {
|
||||||
|
'id': user.role_obj.id,
|
||||||
|
'name': user.role_obj.name
|
||||||
|
} if user.role_obj else {'id': 1, 'name': user.role or 'Admin'}
|
||||||
|
return jsonify({
|
||||||
|
'status': 'success',
|
||||||
|
'user': d
|
||||||
|
}), 200
|
||||||
|
|
||||||
@api_admin_bp.route('/users/<int:id>', methods=['PUT'])
|
@api_admin_bp.route('/users/<int:id>', methods=['PUT'])
|
||||||
@jwt_required
|
@jwt_required
|
||||||
def update_user(id):
|
def update_user(id):
|
||||||
|
|||||||
@@ -382,28 +382,63 @@ const handleUserAdd = async (req, res) => {
|
|||||||
title: 'Nuevo Usuario — Edu-Space Admin',
|
title: 'Nuevo Usuario — Edu-Space Admin',
|
||||||
user: null,
|
user: null,
|
||||||
roles,
|
roles,
|
||||||
document_types
|
document_types,
|
||||||
|
error: req.query.error || null,
|
||||||
|
msg: req.query.msg || null
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error in user add:', err.message);
|
console.error('Error in user add:', err.message);
|
||||||
res.render('admin/users/form', { title: 'Nuevo Usuario', user: null, roles: MOCK_ROLES, document_types: [] });
|
res.render('admin/users/form', {
|
||||||
|
title: 'Nuevo Usuario — Edu-Space Admin',
|
||||||
|
user: null,
|
||||||
|
roles: MOCK_ROLES,
|
||||||
|
document_types: [],
|
||||||
|
error: req.query.error || null,
|
||||||
|
msg: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUserEdit = async (req, res) => {
|
const handleUserEdit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { users, roles, document_types } = await fetchUsersAndRoles(req.apiClient);
|
|
||||||
const userId = req.params.id || req.query.id;
|
const userId = req.params.id || req.query.id;
|
||||||
const targetUser = (userId ? users.find(u => String(u.id) === String(userId)) : null) || users[0] || MOCK_USERS[0];
|
const { users, roles, document_types } = await fetchUsersAndRoles(req.apiClient);
|
||||||
|
let targetUser = userId ? users.find(u => String(u.id) === String(userId)) : null;
|
||||||
|
|
||||||
|
// Si no se encontró en la lista general y hay userId, intentar fetch individual
|
||||||
|
if (!targetUser && userId && req.apiClient) {
|
||||||
|
try {
|
||||||
|
const singleRes = await req.apiClient.get(`/users/${userId}`);
|
||||||
|
if (singleRes.data && (singleRes.data.user || singleRes.data.data)) {
|
||||||
|
targetUser = singleRes.data.user || singleRes.data.data;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`User ${userId} not found via single endpoint:`, e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetUser = targetUser || (userId ? null : users[0]) || MOCK_USERS[0];
|
||||||
|
|
||||||
|
const userName = targetUser ? (targetUser.name || `${targetUser.first_name || ''} ${targetUser.last_name || ''}`.trim() || targetUser.email || `Usuario #${targetUser.id}`) : 'Usuario';
|
||||||
|
|
||||||
res.render('admin/users/form', {
|
res.render('admin/users/form', {
|
||||||
title: `Editar Usuario: ${targetUser.name} — Edu-Space Admin`,
|
title: `Editar Usuario: ${userName} — Edu-Space Admin`,
|
||||||
user: targetUser,
|
user: targetUser,
|
||||||
roles,
|
roles,
|
||||||
document_types
|
document_types,
|
||||||
|
error: req.query.error || null,
|
||||||
|
msg: req.query.msg || null
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error in user edit:', err.message);
|
console.error('Error in user edit:', err.message);
|
||||||
res.render('admin/users/form', { title: 'Editar Usuario', user: MOCK_USERS[0], roles: MOCK_ROLES, document_types: [] });
|
res.render('admin/users/form', {
|
||||||
|
title: 'Editar Usuario — Edu-Space Admin',
|
||||||
|
user: MOCK_USERS[0],
|
||||||
|
roles: MOCK_ROLES,
|
||||||
|
document_types: [],
|
||||||
|
error: 'No se pudo cargar la información del usuario.',
|
||||||
|
msg: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{% set auth_user = current_user if (current_user and current_user.is_authenticated) else user %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ current_lang }}" data-bs-theme="dark">
|
<html lang="{{ current_lang }}" data-bs-theme="dark">
|
||||||
<head>
|
<head>
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
<!-- Script Anti-Flicker para Modo Claro / Oscuro -->
|
<!-- Script Anti-Flicker para Modo Claro / Oscuro -->
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
let userTheme = "{{ user.theme_preference if (user and user.is_authenticated) else '' }}";
|
let userTheme = "{{ auth_user.theme_preference if (auth_user and auth_user.is_authenticated) else '' }}";
|
||||||
let theme = userTheme;
|
let theme = userTheme;
|
||||||
if (!theme || theme === 'auto') {
|
if (!theme || theme === 'auto') {
|
||||||
const storedTheme = localStorage.getItem('theme');
|
const storedTheme = localStorage.getItem('theme');
|
||||||
@@ -570,8 +571,8 @@
|
|||||||
|
|
||||||
{% block extra_css %}{% endblock %}
|
{% block extra_css %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body data-user-authenticated="{{ 'true' if (user and user.is_authenticated) else 'false' }}">
|
<body data-user-authenticated="{{ 'true' if (auth_user and auth_user.is_authenticated) else 'false' }}">
|
||||||
{% if user.is_authenticated %}
|
{% if auth_user and auth_user.is_authenticated %}
|
||||||
|
|
||||||
<div class="app-wrapper">
|
<div class="app-wrapper">
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
@@ -591,7 +592,7 @@
|
|||||||
|
|
||||||
<div class="sidebar-body flex-grow-1 overflow-y-auto p-2">
|
<div class="sidebar-body flex-grow-1 overflow-y-auto p-2">
|
||||||
<ul class="sidebar-nav" id="sidebarNav">
|
<ul class="sidebar-nav" id="sidebarNav">
|
||||||
{% set user_role = role if role else 'admin' %}
|
{% set user_role = role if role else (auth_user.role if auth_user else 'admin') %}
|
||||||
{% if user_role == 'admin' %}
|
{% if user_role == 'admin' %}
|
||||||
<!-- ADMIN -->
|
<!-- ADMIN -->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@@ -700,15 +701,15 @@
|
|||||||
<div class="dropdown dropup">
|
<div class="dropdown dropup">
|
||||||
<a href="#" class="d-flex align-items-center text-decoration-none dropdown-toggle text-body w-100" data-bs-toggle="dropdown" aria-expanded="false">
|
<a href="#" class="d-flex align-items-center text-decoration-none dropdown-toggle text-body w-100" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<div class="user-avatar-small bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width:32px; height:32px; font-weight:bold; flex-shrink:0;">
|
<div class="user-avatar-small bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width:32px; height:32px; font-weight:bold; flex-shrink:0;">
|
||||||
{{ user.name[0]|upper if user.name else 'U' }}
|
{{ auth_user.name[0]|upper if auth_user.name else 'U' }}
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-2 sidebar-footer-text text-truncate flex-grow-1" style="min-width:0;">
|
<div class="ms-2 sidebar-footer-text text-truncate flex-grow-1" style="min-width:0;">
|
||||||
<small class="d-block fw-semibold text-truncate">{{ user.first_name }}</small>
|
<small class="d-block fw-semibold text-truncate">{{ auth_user.first_name or auth_user.name }}</small>
|
||||||
<small class="text-muted d-block text-truncate" style="font-size:0.7rem;">{{ user.role_badge_display.label }}</small>
|
<small class="text-muted d-block text-truncate" style="font-size:0.7rem;">{{ auth_user.role_badge_display.label if (auth_user and auth_user.role_badge_display) else (auth_user.role|capitalize if auth_user else 'Usuario') }}</small>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu shadow-sm border-0 mb-2">
|
<ul class="dropdown-menu shadow-sm border-0 mb-2">
|
||||||
<li><h6 class="dropdown-header">{{ user.email }}</h6></li>
|
<li><h6 class="dropdown-header">{{ auth_user.email if auth_user else '' }}</h6></li>
|
||||||
<li><a class="dropdown-item" href="/auth/profile"><i class="bi bi-person me-2"></i>Mi Perfil</a></li>
|
<li><a class="dropdown-item" href="/auth/profile"><i class="bi bi-person me-2"></i>Mi Perfil</a></li>
|
||||||
<li><a class="dropdown-item" href="/auth/change_password"><i class="bi bi-key me-2"></i>Cambiar Contraseña</a></li>
|
<li><a class="dropdown-item" href="/auth/change_password"><i class="bi bi-key me-2"></i>Cambiar Contraseña</a></li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
|||||||
Reference in New Issue
Block a user