mypastebin/templates/user_dashboard.html
2025-06-08 15:44:54 +02:00

542 lines
24 KiB
HTML

{% extends "base.html" %}
{% block title %}User Dashboard{% endblock %}
<style>
/* Variables CSS para mayor flexibilidad */
:root {
--preview-text-font-size: 0.5rem; /* Ajusta este valor según necesites */
--dashboard-title-font-size: 1.5rem; /* Tamaño de títulos */
--dashboard-paragraph-font-size: 0.9rem; /* Tamaño de párrafos */
--table-font-size: 0.85rem; /* Tamaño de tablas */
}
/* Clase personalizada para la previsualización de texto */
#preview-text.custom-text-preview {
font-size: var(--preview-text-font-size) !important;
margin: 0 !important;
padding: 0 !important;
line-height: 1.2 !important;
white-space: pre-wrap !important;
word-wrap: break-word !important;
font-family: monospace !important;
}
/* Clases para otros elementos */
.custom-title {
font-size: var(--dashboard-title-font-size);
}
.custom-paragraph {
font-size: var(--dashboard-paragraph-font-size);
}
.custom-table {
font-size: var(--table-font-size);
}
</style>
{% block content %}
<body data-username="{{ current_user.username }}">
<div id="toast-container" class="position-fixed top-0 end-0 p-2" style="z-index: 1055;"></div>
<div id="image-preview" class="position-absolute z-1000 d-none" style="max-width: 160px; max-height: 90px;">
<img id="preview-image" style="width: 100%; height: 100%; object-fit: cover;" />
</div>
<div id="video-preview" class="position-absolute z-1000 d-none" style="width: 160px; height: 90px;">
<video id="preview-video" autoplay muted loop style="width: 100%; height: 100%; object-fit: cover;"></video>
</div>
<!-- Contenedor para Previsualización de Texto -->
<div id="text-preview" class="position-absolute z-1000 d-none p-1 border rounded" style="max-width: 160px; max-height: 90px; overflow-y: auto;">
<div id="preview-text" class="mb-0 custom-text-preview"></div>
</div>
<!-- Contenedor para Previsualización de PDF -->
<div id="pdf-preview" class="position-absolute z-1000 d-none" style="width: 160px; height: 90px;">
<canvas id="preview-pdf-canvas" style="width: 100%; height: 100%; border: none;"></canvas>
</div>
<div class="container-fluid mt-3" style="max-width: 800px;">
<h3 class="mb-3 custom-title">Welcome, {{ user.username }}</h3>
<!-- Información del Perfil -->
<div class="card mb-3">
<div class="card-header bg-info text-white p-2">
<h6 class="mb-0">User Profile</h6>
</div>
<div class="card-body p-2">
<p class="mb-1 custom-paragraph"><strong>Username:</strong> {{ user.username }}</p>
<p class="mb-1 custom-paragraph"><strong>Role:</strong> {{ user.role }}</p>
<!-- Botón para editar el perfil eliminado por requisitos legales -->
{# <a href="{{ url_for('edit_profile') }}" class="btn btn-primary btn-sm">Edit Profile</a> #}
</div>
</div>
<!-- Información de Almacenamiento -->
<div class="card mb-3">
<div class="card-header bg-warning text-dark p-2">
<h6 class="mb-0">Storage Information</h6>
</div>
<div class="card-body p-2">
{% if storage_limit > 0 %}
<p class="mb-1 custom-paragraph"><strong>Storage Used:</strong> {{ storage_used }} MB</p>
<p class="mb-1 custom-paragraph"><strong>Storage Available:</strong> {{ storage_available }} MB</p>
<div class="progress mb-2" style="height: 10px;">
{% set usage_percent = (storage_used / storage_limit * 100) if storage_limit > 0 else 0 %}
{% set progress_class = 'bg-success' if usage_percent < 50 else 'bg-warning' if usage_percent < 80 else 'bg-danger' %}
<div class="progress-bar {{ progress_class }}" role="progressbar" style="width: {{ usage_percent }}%;" aria-valuenow="{{ storage_used }}" aria-valuemin="0" aria-valuemax="{{ storage_limit }}">
{{ usage_percent | round(1) }}%
</div>
</div>
{% if storage_available < (0.1 * storage_limit) %}
<div class="alert alert-danger p-1" role="alert">
You're running low on storage! Consider deleting some pastes or upgrading your account.
</div>
{% elif storage_available < (0.25 * storage_limit) %}
<div class="alert alert-warning p-1" role="alert">
You're approaching your storage limit.
</div>
{% endif %}
{% else %}
<p class="mb-1 custom-paragraph"><strong>Storage Used:</strong> {{ storage_used }} MB</p>
<p class="mb-1 custom-paragraph"><strong>Storage Available:</strong> Unlimited</p>
<div class="progress" style="height: 10px;">
<div class="progress-bar bg-success" role="progressbar" style="width: 100%;" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
{% endif %}
</div>
</div>
<!-- Botón para crear nuevo paste -->
<a href="{{ url_for('create_paste_web') }}" class="btn btn-success btn-sm mb-3">Create New Paste</a>
<!-- Formulario de Búsqueda Avanzada -->
<div class="mb-3">
<h5>Advanced Search</h5>
<form method="GET" action="{{ url_for('search_pastes_web') }}">
<div class="row g-2">
<!-- Primera fila: Campos de texto -->
<div class="col-md-4">
<label for="query" class="form-label">Keyword</label>
<input type="text" id="query" name="q" class="form-control form-control-sm" placeholder="Enter keyword">
</div>
<div class="col-md-4">
<label for="content_type" class="form-label">Content Type</label>
<select id="content_type" name="content_type" class="form-select form-select-sm">
<option value="">Any</option>
<option value="text">Text</option>
<option value="image">Image</option>
<option value="video">Video</option>
<option value="audio">Audio</option>
<option value="other">Other</option>
</select>
</div>
<div class="col-md-4">
<label for="language" class="form-label">Language</label>
<input type="text" id="language" name="language" class="form-control form-control-sm" placeholder="Enter language">
</div>
</div>
<!-- Segunda fila: Botón -->
<div class="row mt-2">
<div class="col-md-12 d-flex justify-content-end">
<button type="submit" class="btn btn-primary btn-sm">Search</button>
</div>
</div>
</form>
</div>
<!-- Estadísticas -->
<h5>Your Paste Statistics:</h5>
<ul class="list-unstyled mb-3 custom-paragraph" style="font-size: var(--dashboard-paragraph-font-size);">
<li><strong>Total Pastes:</strong> {{ total_pastes }}</li>
<li><strong>Total Size:</strong> {{ total_size }} bytes</li>
</ul>
<!-- Filtro por fechas -->
<form method="GET" action="{{ url_for('user_stats', username=user.username) }}" class="row g-2 mb-3">
<div class="col-md-4">
<label for="start_date" class="form-label">Start Date:</label>
<input type="date" id="start_date" name="start_date" class="form-control form-control-sm" value="{{ start_date }}">
</div>
<div class="col-md-4">
<label for="end_date" class="form-label">End Date:</label>
<input type="date" id="end_date" name="end_date" class="form-control form-control-sm" value="{{ end_date }}">
</div>
<div class="col-md-4 d-flex align-items-end">
<button type="submit" class="btn btn-primary btn-sm w-100">Filter</button>
</div>
</form>
<!-- Metrics Cards -->
<div class="row mb-3">
<div class="col-md-3">
<div class="card text-white bg-primary mb-2 custom-table">
<div class="card-header p-2">Total Pastes</div>
<div class="card-body p-2">
<h6 id="total-pastes" class="card-title mb-0">{{ total_pastes }}</h6>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-2 custom-table">
<div class="card-header p-2">Text Pastes</div>
<div class="card-body p-2">
<h6 id="total-text-pastes" class="card-title mb-0">{{ total_text_pastes }}</h6>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-2 custom-table">
<div class="card-header p-2">File Pastes</div>
<div class="card-body p-2">
<h6 id="total-file-pastes" class="card-title mb-0">{{ total_file_pastes }}</h6>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-2 custom-table">
<div class="card-header p-2">Media Pastes</div>
<div class="card-body p-2">
<h6 id="total-media-pastes" class="card-title mb-0">{{ total_media_pastes }}</h6>
</div>
</div>
</div>
</div>
<!-- Chart de lenguajes -->
<div class="row mb-3">
<div class="col-12">
<h5 class="mb-2">Pastes by Language and Type</h5>
<canvas id="languageTypeChart" style="max-height: 200px;"></canvas>
</div>
</div>
<!-- Tabs para My Pastes, Favorites y Shared -->
<ul class="nav nav-tabs" id="dashboardTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="my-pastes-tab"
data-bs-toggle="tab" data-bs-target="#my-pastes"
type="button" role="tab" aria-controls="my-pastes"
aria-selected="true">
My Pastes
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="favorites-tab"
data-bs-toggle="tab" data-bs-target="#favorites"
type="button" role="tab" aria-controls="favorites"
aria-selected="false">
Favorites
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="shared-tab"
data-bs-toggle="tab" data-bs-target="#shared"
type="button" role="tab" aria-controls="shared"
aria-selected="false">
Shared
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="private-pastes-tab"
data-bs-toggle="tab" data-bs-target="#private-pastes"
type="button" role="tab" aria-controls="private-pastes"
aria-selected="false">
Private Pastes
</button>
</li>
</ul>
<div class="tab-content mt-2" id="dashboardTabsContent">
<!-- My Pastes -->
<div class="tab-pane fade show active" id="my-pastes" role="tabpanel" aria-labelledby="my-pastes-tab">
<h5>Your Pastes</h5>
{% if pastes|length > 0 %}
<table class="table table-bordered table-striped table-sm custom-table">
<thead>
<tr>
<th>ID</th>
<th>Filename</th>
<th>Type</th>
<th>Size (bytes)</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for paste in pastes %}
<tr id="paste-{{ paste.id }}">
<td>{{ paste.id }}</td>
<td>
<a href="{{ url_for('paste_settings', paste_id=paste.id) }}">
paste_{{ paste.id }}.{{ paste.get_extension() }}
</a>
</td>
<td>{{ paste.get_type() }}</td>
<td>{{ paste.size }}</td>
<td>{{ paste.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</td>
<td>
<a href="{{ url_for('get_paste', id=paste.id) }}"
class="btn btn-sm btn-secondary view-btn"
data-url="{{ url_for('serve_media', id=paste.id) }}"
data-type="{{ paste.content_type }}">
View
</a>
<button class="btn btn-sm btn-danger delete-paste"
data-id="{{ paste.id }}">Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>You do not have any pastes yet.</p>
{% endif %}
</div>
<!-- Nueva pestaña: Private Pastes -->
<div class="tab-pane fade" id="private-pastes" role="tabpanel" aria-labelledby="private-pastes-tab">
<h5>Your Private Pastes</h5>
{% if private_pastes.items %}
<table class="table table-bordered table-striped table-sm custom-table">
<thead>
<tr>
<th>ID</th>
<th>Filename</th>
<th>Type</th>
<th>Size (bytes)</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for paste in private_pastes.items %}
<tr id="paste-{{ paste.id }}">
<td>{{ paste.id }}</td>
<td>paste_{{ paste.id }}.{{ paste.get_extension() }}</td>
<td>{{ paste.get_type() }}</td>
<td>{{ paste.size }}</td>
<td>{{ paste.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</td>
<td>
<a href="{{ url_for('get_paste', id=paste.id) }}"
class="btn btn-sm btn-secondary view-btn"
data-url="{{ url_for('serve_media', id=paste.id) }}"
data-type="{{ paste.content_type }}">
View
</a>
<button class="btn btn-sm btn-danger delete-paste"
data-id="{{ paste.id }}">Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Paginación Private Pastes -->
{% if private_pastes.pages > 1 %}
<nav aria-label="Private Pastes pagination">
<ul class="pagination justify-content-center">
{% if private_pastes.has_prev %}
<li class="page-item">
<a class="page-link" href="{{ url_for('user_dashboard', private_page=private_pastes.prev_num) }}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% endif %}
{% for page_num in private_pastes.iter_pages(left_edge=2, right_edge=2, left_current=1, right_current=1) %}
{% if page_num %}
{% if page_num == private_pastes.page %}
<li class="page-item active"><span class="page-link">{{ page_num }}</span></li>
{% else %}
<li class="page-item">
<a class="page-link" href="{{ url_for('user_dashboard', private_page=page_num) }}">
{{ page_num }}
</a>
</li>
{% endif %}
{% else %}
<li class="page-item disabled"><span class="page-link"></span></li>
{% endif %}
{% endfor %}
{% if private_pastes.has_next %}
<li class="page-item">
<a class="page-link" href="{{ url_for('user_dashboard', private_page=private_pastes.next_num) }}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<p>You do not have any private pastes yet.</p>
{% endif %}
</div>
<!-- Favorites -->
<div class="tab-pane fade" id="favorites"
role="tabpanel" aria-labelledby="favorites-tab">
<h5>Your Favorites</h5>
{% if favorite_pastes %}
<table class="table table-bordered table-striped table-sm custom-table">
<thead>
<tr>
<th>ID</th>
<th>Filename</th>
<th>Type</th>
<th>Size (bytes)</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="favorites-body">
{% for fav in favorite_pastes %}
<tr id="favorite-{{ fav.id }}">
<td>{{ fav.id }}</td>
<td>{{ fav.filename if fav.filename else "Paste " ~ fav.id }}</td>
<td>{{ fav.get_type() }}</td>
<td>{{ fav.size }}</td>
<td>{{ fav.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</td>
<td>
<a href="{{ url_for('get_paste', id=fav.id) }}"
class="btn btn-sm btn-secondary view-btn"
data-url="{{ url_for('serve_media', id=fav.id) }}"
data-type="{{ fav.content_type }}">
View
</a>
<button class="btn btn-sm btn-danger unfavorite-btn" data-id="{{ fav.id }}">
Unfavorite
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Paginación Favorites -->
{% if favorite_pagination.pages > 1 %}
<nav aria-label="Favorites pagination">
<ul class="pagination justify-content-center">
{% if favorite_pagination.has_prev %}
<li class="page-item">
<a class="page-link" href="{{ url_for('user_dashboard', favorite_page=favorite_pagination.prev_num) }}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% endif %}
{% for page_num in favorite_pagination.iter_pages(left_edge=2, right_edge=2, left_current=1, right_current=1) %}
{% if page_num %}
{% if page_num == favorite_pagination.page %}
<li class="page-item active"><span class="page-link">{{ page_num }}</span></li>
{% else %}
<li class="page-item">
<a class="page-link" href="{{ url_for('user_dashboard', favorite_page=page_num) }}">
{{ page_num }}
</a>
</li>
{% endif %}
{% else %}
<li class="page-item disabled"><span class="page-link"></span></li>
{% endif %}
{% endfor %}
{% if favorite_pagination.has_next %}
<li class="page-item">
<a class="page-link" href="{{ url_for('user_dashboard', favorite_page=favorite_pagination.next_num) }}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<p>You don't have any favorites yet.</p>
{% endif %}
</div>
<!-- Shared Pastes -->
<div class="tab-pane fade" id="shared"
role="tabpanel" aria-labelledby="shared-tab">
<h5>Shared Pastes</h5>
{% if shared_pastes %}
<table class="table table-bordered table-striped table-sm custom-table">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>Title</th>
<th>Owner</th>
<th>Type</th>
<th>Size (bytes)</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for sp in shared_pastes %}
<tr id="shared-paste-{{ sp.id }}">
<td>{{ sp.id }}</td>
<td>{{ sp.title or "Untitled" }}</td>
<td>{{ sp.owner.username }}</td>
<td>{{ sp.get_type() }}</td>
<td>{{ sp.size }}</td>
<td>{{ sp.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</td>
<td>
<a href="{{ url_for('get_paste', id=sp.id) }}"
class="btn btn-sm btn-secondary view-btn"
data-url="{{ url_for('serve_media', id=sp.id) }}"
data-type="{{ sp.content_type }}">
View
</a>
{% if sp.has_edit_permission(current_user) %}
<a href="{{ url_for('edit_paste_web', id=sp.id) }}"
class="btn btn-sm btn-warning">Edit</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Paginación Shared (si es necesario) -->
{% if shared_pastes|length > 10 %}
<nav aria-label="Shared Pastes pagination">
<ul class="pagination justify-content-center">
<!-- Implementa la paginación similar a las secciones anteriores si es necesario -->
</ul>
</nav>
{% endif %}
{% else %}
<p>You don't have any shared pastes yet.</p>
{% endif %}
</div>
</div>
<h5 class="mt-4">Account Settings</h5>
<ul class="list-unstyled">
<li><a href="{{ url_for('change_password_form') }}" class="btn btn-secondary btn-sm">Change Password</a></li>
</ul>
</div>
<!-- JSON Data Embed -->
<script type="application/json" id="language-data">{{ languages | tojson | safe }}</script>
<script type="application/json" id="text-counts">{{ counts_text | tojson | safe }}</script>
<script type="application/json" id="file-counts">{{ counts_file | tojson | safe }}</script>
<script type="application/json" id="media-counts">{{ counts_media | tojson | safe }}</script>
<!-- Scripts Externos -->
<script src="https://cdn.priet.us/cdn/js/chart.js"></script>
<script src="https://cdn.priet.us/cdn/js/pdf.min.js"></script>
<script src="{{ url_for('static', filename='js/user_dashboard/toasts.js') }}"></script>
<script src="{{ url_for('static', filename='js/user_dashboard/charts.js') }}"></script>
<script src="{{ url_for('static', filename='js/user_dashboard/previews.js') }}"></script>
<script src="{{ url_for('static', filename='js/user_dashboard/actions.js') }}"></script>
{% endblock %}
{% block footer %}
{{ super() }} <!-- Esto conserva el contenido original del footer definido en base.html -->
{% endblock %}