2025-03-03 15:35:24 -03:00
|
|
|
{% extends "base.html" %}
|
|
|
|
|
2025-03-05 14:10:33 -03:00
|
|
|
{% block title %}Proyecto: {{ project.descripcion }}{% endblock %}
|
2025-03-03 15:35:24 -03:00
|
|
|
|
|
|
|
{% block styles %}
|
|
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/projects.css') }}">
|
|
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/documents.css') }}">
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
{% block page_title %}Proyecto: {{ project.descripcion }}{% endblock %}
|
|
|
|
|
|
|
|
{% block content %}
|
2025-03-05 14:10:33 -03:00
|
|
|
<div class="container mt-4">
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
|
|
<h2>Detalles del Proyecto</h2>
|
|
|
|
<div>
|
|
|
|
<a href="{{ url_for('projects.edit', project_id=project.codigo) }}" class="btn btn-outline-primary me-1" title="Editar proyecto">
|
|
|
|
<i class="fas fa-edit fa-lg"></i>
|
|
|
|
</a>
|
|
|
|
<a href="{{ url_for('projects.list') }}" class="btn btn-outline-secondary" title="Volver a la lista">
|
|
|
|
<i class="fas fa-arrow-left fa-lg"></i>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-light">
|
|
|
|
<h3>{{ project.descripcion }}</h3>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<p><strong>Código:</strong> {{ project.codigo }}</p>
|
|
|
|
<p><strong>Cliente:</strong> {{ project.cliente }}</p>
|
|
|
|
<p><strong>Destinación:</strong> {{ project.destinacion or 'No especificada' }}</p>
|
|
|
|
<p><strong>Estado:</strong> <span class="badge {{ 'bg-success' if project.estado == 'activo' else 'bg-secondary' }}">{{ project.estado|capitalize }}</span></p>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
<div class="col-md-6">
|
|
|
|
<p><strong>Esquema:</strong> {{ project.esquema }}</p>
|
|
|
|
<p><strong>Proyecto Padre:</strong> {{ project.proyecto_padre or 'Ninguno' }}</p>
|
|
|
|
<p><strong>Año Creación:</strong> {{ project.ano_creacion }}</p>
|
|
|
|
<p><strong>Fecha Creación:</strong> {{ project.fecha_creacion|default('No disponible', true) }}</p>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
|
|
|
|
<div class="row mt-3">
|
|
|
|
<div class="col">
|
|
|
|
<p><strong>Creado por:</strong> {{ project.creado_por }}</p>
|
|
|
|
<p><strong>Última modificación:</strong> {{ project.ultima_modificacion|default('No modificado', true) }}</p>
|
|
|
|
<p><strong>Modificado por:</strong> {{ project.modificado_por|default('No modificado', true) }}</p>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
|
|
|
|
<!-- Proyectos Hijos -->
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
|
|
<h4 class="mb-0">Proyectos Relacionados</h4>
|
|
|
|
<a href="{{ url_for('projects.create') }}" class="btn btn-outline-success" title="Nuevo proyecto relacionado">
|
|
|
|
<i class="fas fa-plus fa-lg"></i>
|
|
|
|
</a>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
<div class="card-body">
|
|
|
|
{% if children %}
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Código</th>
|
|
|
|
<th>Descripción</th>
|
|
|
|
<th>Cliente</th>
|
|
|
|
<th>Estado</th>
|
|
|
|
<th width="100">Acciones</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for child in children %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ child.codigo }}</td>
|
|
|
|
<td>{{ child.descripcion }}</td>
|
|
|
|
<td>{{ child.cliente }}</td>
|
|
|
|
<td><span class="badge {{ 'bg-success' if child.estado == 'activo' else 'bg-secondary' }}">{{ child.estado|capitalize }}</span></td>
|
|
|
|
<td>
|
|
|
|
<div class="btn-group btn-group-sm">
|
|
|
|
<a href="{{ url_for('projects.view', project_id=child.codigo) }}" class="btn btn-outline-info" title="Ver detalles">
|
|
|
|
<i class="fas fa-eye fa-lg"></i>
|
|
|
|
</a>
|
|
|
|
<a href="{{ url_for('projects.edit', project_id=child.codigo) }}" class="btn btn-outline-primary" title="Editar">
|
|
|
|
<i class="fas fa-edit fa-lg"></i>
|
|
|
|
</a>
|
|
|
|
<button type="button" class="btn btn-outline-danger" title="Eliminar"
|
|
|
|
onclick="confirmDelete('{{ child.codigo }}', '{{ child.descripcion }}')">
|
|
|
|
<i class="fas fa-trash-alt fa-lg"></i>
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
{% else %}
|
|
|
|
<p class="text-muted">No hay proyectos relacionados.</p>
|
|
|
|
{% endif %}
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-03-05 14:10:33 -03:00
|
|
|
<!-- Documentos -->
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
|
|
<h4 class="mb-0">Documentos ({{ document_count }})</h4>
|
|
|
|
<a href="{{ url_for('documents.upload', project_id=project.codigo) }}" class="btn btn-outline-success" title="Subir documento">
|
|
|
|
<i class="fas fa-upload fa-lg"></i>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div id="documents-container">
|
|
|
|
{% if document_count > 0 %}
|
|
|
|
<div class="text-center">
|
2025-03-03 15:35:24 -03:00
|
|
|
<div class="spinner-border text-primary" role="status">
|
|
|
|
<span class="visually-hidden">Cargando...</span>
|
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
<p>Cargando documentos...</p>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
{% else %}
|
|
|
|
<p class="text-muted">No hay documentos en este proyecto.</p>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{% if document_count > 0 %}
|
|
|
|
<div class="mt-3">
|
|
|
|
<a href="{{ url_for('documents.list', project_id=project.codigo) }}" class="btn btn-outline-primary">
|
|
|
|
<i class="fas fa-list fa-lg"></i> Ver todos los documentos
|
|
|
|
</a>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
2025-03-05 14:10:33 -03:00
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Modal de confirmación para eliminar -->
|
|
|
|
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
|
|
|
<div class="modal-dialog">
|
|
|
|
<div class="modal-content">
|
|
|
|
<div class="modal-header">
|
|
|
|
<h5 class="modal-title" id="deleteModalLabel">Confirmar eliminación</h5>
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
|
|
¿Está seguro de que desea eliminar el proyecto <span id="projectToDelete"></span>?
|
|
|
|
<p class="text-danger mt-2">Esta acción no se puede deshacer.</p>
|
|
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
|
|
|
<form id="deleteForm" method="POST">
|
|
|
|
{{ csrf_token() }}
|
|
|
|
<button type="submit" class="btn btn-danger">Eliminar</button>
|
|
|
|
</form>
|
2025-03-03 15:35:24 -03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
{% block scripts %}
|
|
|
|
<script src="{{ url_for('static', filename='js/projects.js') }}"></script>
|
|
|
|
<script>
|
|
|
|
// Cargar documentos del proyecto mediante AJAX
|
|
|
|
$(document).ready(function() {
|
|
|
|
$.ajax({
|
2025-03-05 14:10:33 -03:00
|
|
|
url: "{{ url_for('documents.api_list', project_id=project.codigo) }}",
|
2025-03-03 15:35:24 -03:00
|
|
|
type: "GET",
|
|
|
|
dataType: "json",
|
|
|
|
success: function(data) {
|
|
|
|
displayDocuments(data);
|
|
|
|
},
|
|
|
|
error: function() {
|
|
|
|
$("#documents-container").html(
|
|
|
|
'<div class="alert alert-danger">Error al cargar los documentos.</div>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
function displayDocuments(documents) {
|
|
|
|
if (documents.length === 0) {
|
|
|
|
$("#documents-container").html(
|
|
|
|
'<div class="alert alert-info">No hay documentos en este proyecto.</div>'
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let html = '<div class="table-responsive">' +
|
|
|
|
'<table class="table table-hover table-striped">' +
|
|
|
|
'<thead class="table-light">' +
|
|
|
|
'<tr>' +
|
|
|
|
'<th>Nombre</th>' +
|
|
|
|
'<th>Tipo</th>' +
|
|
|
|
'<th>Última versión</th>' +
|
|
|
|
'<th>Creado por</th>' +
|
|
|
|
'<th>Acciones</th>' +
|
|
|
|
'</tr>' +
|
|
|
|
'</thead>' +
|
|
|
|
'<tbody>';
|
|
|
|
|
|
|
|
documents.forEach(function(doc) {
|
|
|
|
// Obtener la última versión
|
|
|
|
let latestVersion = doc.versions.reduce((prev, current) =>
|
|
|
|
(prev.version > current.version) ? prev : current
|
|
|
|
);
|
|
|
|
|
|
|
|
// Determinar ícono según tipo MIME
|
|
|
|
let icon = '<i class="bi bi-file-earmark"></i>';
|
|
|
|
if (latestVersion.mime_type.includes('pdf')) {
|
|
|
|
icon = '<i class="bi bi-file-earmark-pdf"></i>';
|
|
|
|
} else if (latestVersion.mime_type.includes('image')) {
|
|
|
|
icon = '<i class="bi bi-file-earmark-image"></i>';
|
|
|
|
} else if (latestVersion.mime_type.includes('zip')) {
|
|
|
|
icon = '<i class="bi bi-file-earmark-zip"></i>';
|
|
|
|
} else if (latestVersion.mime_type.includes('text')) {
|
|
|
|
icon = '<i class="bi bi-file-earmark-text"></i>';
|
|
|
|
}
|
|
|
|
|
|
|
|
html += '<tr>' +
|
|
|
|
'<td>' + icon + ' ' + doc.original_filename + '</td>' +
|
|
|
|
'<td>' + latestVersion.mime_type + '</td>' +
|
|
|
|
'<td>v' + latestVersion.version + ' (' + latestVersion.created_at.replace('T', ' ').replace('Z', '') + ')</td>' +
|
|
|
|
'<td>' + latestVersion.created_by + '</td>' +
|
|
|
|
'<td>' +
|
|
|
|
'<div class="btn-group btn-group-sm">' +
|
2025-03-05 14:10:33 -03:00
|
|
|
'<a href="/documents/' + project.codigo + '/' + doc.id + '" class="btn btn-primary" title="Ver versiones">' +
|
2025-03-03 15:35:24 -03:00
|
|
|
'<i class="bi bi-eye"></i>' +
|
|
|
|
'</a>' +
|
2025-03-05 14:10:33 -03:00
|
|
|
'<a href="/documents/' + project.codigo + '/' + doc.id + '/download/' + latestVersion.version + '" class="btn btn-success" title="Descargar última versión">' +
|
2025-03-03 15:35:24 -03:00
|
|
|
'<i class="bi bi-download"></i>' +
|
|
|
|
'</a>' +
|
|
|
|
'</div>' +
|
|
|
|
'</td>' +
|
|
|
|
'</tr>';
|
|
|
|
});
|
|
|
|
|
|
|
|
html += '</tbody></table></div>';
|
|
|
|
|
|
|
|
$("#documents-container").html(html);
|
|
|
|
}
|
2025-03-05 14:10:33 -03:00
|
|
|
|
|
|
|
// Configurar modal de eliminación
|
|
|
|
function confirmDelete(projectId, projectName) {
|
|
|
|
document.getElementById('projectToDelete').textContent = projectName;
|
|
|
|
document.getElementById('deleteForm').action = "{{ url_for('projects.delete', project_id='PLACEHOLDER') }}".replace('PLACEHOLDER', projectId);
|
|
|
|
|
|
|
|
// Mostrar modal usando Bootstrap
|
|
|
|
var myModal = new bootstrap.Modal(document.getElementById('deleteModal'));
|
|
|
|
myModal.show();
|
|
|
|
}
|
2025-03-03 15:35:24 -03:00
|
|
|
</script>
|
|
|
|
{% endblock %}
|