error pages
This commit is contained in:
Binary file not shown.
37
app.py
37
app.py
@@ -53,6 +53,15 @@ def create_app():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return dict(config=app.config, site_settings=site_settings)
|
return dict(config=app.config, site_settings=site_settings)
|
||||||
|
|
||||||
|
@app.context_processor
|
||||||
|
def inject_unread_notifications():
|
||||||
|
from flask_login import current_user
|
||||||
|
from utils import get_unread_count
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
unread_count = get_unread_count(current_user.id)
|
||||||
|
return {'unread_notifications': unread_count}
|
||||||
|
return {'unread_notifications': 0}
|
||||||
|
|
||||||
@app.template_filter('asset_version')
|
@app.template_filter('asset_version')
|
||||||
def asset_version_filter(filename):
|
def asset_version_filter(filename):
|
||||||
"""Template filter to get version hash for static assets"""
|
"""Template filter to get version hash for static assets"""
|
||||||
@@ -134,6 +143,34 @@ def create_app():
|
|||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
||||||
|
@app.errorhandler(404)
|
||||||
|
def page_not_found(e):
|
||||||
|
from flask import render_template
|
||||||
|
return render_template('common/404.html'), 404
|
||||||
|
|
||||||
|
@app.errorhandler(403)
|
||||||
|
def forbidden(e):
|
||||||
|
from flask import render_template
|
||||||
|
return render_template('common/403.html'), 403
|
||||||
|
|
||||||
|
@app.errorhandler(401)
|
||||||
|
def unauthorized(e):
|
||||||
|
from flask import render_template
|
||||||
|
return render_template('common/401.html'), 401
|
||||||
|
|
||||||
|
@app.errorhandler(400)
|
||||||
|
def bad_request(e):
|
||||||
|
from flask import render_template
|
||||||
|
return render_template('common/400.html'), 400
|
||||||
|
|
||||||
|
@app.errorhandler(500)
|
||||||
|
def internal_server_error(e):
|
||||||
|
from flask import render_template
|
||||||
|
import traceback
|
||||||
|
error_details = f"{str(e)}\n\n{traceback.format_exc()}"
|
||||||
|
app.logger.error(f"500 error: {error_details}")
|
||||||
|
return render_template('common/500.html', error=error_details), 500
|
||||||
|
|
||||||
@app.route('/uploads/profile_pics/<filename>')
|
@app.route('/uploads/profile_pics/<filename>')
|
||||||
def profile_pic(filename):
|
def profile_pic(filename):
|
||||||
return send_from_directory('/app/uploads/profile_pics', filename)
|
return send_from_directory('/app/uploads/profile_pics', filename)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
19
templates/common/400.html
Normal file
19
templates/common/400.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends "common/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Bad Request - 400{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container mx-auto px-4 py-16 text-center">
|
||||||
|
<h1 class="display-1 fw-bold" style="color: var(--primary-color);">400</h1>
|
||||||
|
<h2 class="mb-4">Bad Request</h2>
|
||||||
|
<p class="mb-4 text-muted">Sorry, the request could not be processed. Please check your input and try again.</p>
|
||||||
|
<div class="d-flex justify-content-center gap-3">
|
||||||
|
<a href="{{ url_for('main.dashboard') }}" class="btn btn-primary">
|
||||||
|
<i class="fas fa-home me-2"></i>Back to Dashboard
|
||||||
|
</a>
|
||||||
|
<button onclick="window.history.back()" class="btn btn-outline-primary">
|
||||||
|
<i class="fas fa-arrow-left me-2"></i>Go Back
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
19
templates/common/401.html
Normal file
19
templates/common/401.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends "common/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Authentication Required - 401{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container mx-auto px-4 py-16 text-center">
|
||||||
|
<h1 class="display-1 fw-bold" style="color: var(--primary-color);">401</h1>
|
||||||
|
<h2 class="mb-4">Authentication Required</h2>
|
||||||
|
<p class="mb-4 text-muted">Please log in to access this resource.</p>
|
||||||
|
<div class="d-flex justify-content-center gap-3">
|
||||||
|
<a href="{{ url_for('auth.login') }}" class="btn btn-primary">
|
||||||
|
<i class="fas fa-sign-in-alt me-2"></i>Log In
|
||||||
|
</a>
|
||||||
|
<button onclick="window.history.back()" class="btn btn-outline-primary">
|
||||||
|
<i class="fas fa-arrow-left me-2"></i>Go Back
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
19
templates/common/403.html
Normal file
19
templates/common/403.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends "common/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Access Denied - 403{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container mx-auto px-4 py-16 text-center">
|
||||||
|
<h1 class="display-1 fw-bold" style="color: var(--primary-color);">403</h1>
|
||||||
|
<h2 class="mb-4">Access Denied</h2>
|
||||||
|
<p class="mb-4 text-muted">Sorry, you don't have permission to access this resource.</p>
|
||||||
|
<div class="d-flex justify-content-center gap-3">
|
||||||
|
<a href="{{ url_for('main.dashboard') }}" class="btn btn-primary">
|
||||||
|
<i class="fas fa-home me-2"></i>Back to Dashboard
|
||||||
|
</a>
|
||||||
|
<button onclick="window.history.back()" class="btn btn-outline-primary">
|
||||||
|
<i class="fas fa-arrow-left me-2"></i>Go Back
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
15
templates/common/404.html
Normal file
15
templates/common/404.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% extends "common/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Page Not Found - 404{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container mx-auto px-4 py-16 text-center">
|
||||||
|
<h1 class="display-1 fw-bold" style="color: var(--primary-color);">404</h1>
|
||||||
|
<h2 class="mb-4">Page Not Found</h2>
|
||||||
|
<p class="mb-4 text-muted">Sorry, the page you are looking for does not exist or has been moved.</p>
|
||||||
|
<p class="mb-4 text-muted">If you were trying to access a room, conversation, or file, it may have been deleted by an administrator.</p>
|
||||||
|
<a href="{{ url_for('main.dashboard') }}" class="btn btn-primary">
|
||||||
|
<i class="fas fa-home me-2"></i>Back to Dashboard
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
55
templates/common/500.html
Normal file
55
templates/common/500.html
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{% extends "common/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Server Error - 500{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container mx-auto px-4 py-16 text-center">
|
||||||
|
<h1 class="display-1 fw-bold" style="color: var(--primary-color);">500</h1>
|
||||||
|
<h2 class="mb-4">Internal Server Error</h2>
|
||||||
|
<p class="mb-4 text-muted">Sorry, something went wrong on our end. Our team has been notified and we're working to fix it.</p>
|
||||||
|
<div class="d-flex justify-content-center gap-3 mb-4">
|
||||||
|
<a href="{{ url_for('main.dashboard') }}" class="btn btn-primary">
|
||||||
|
<i class="fas fa-home me-2"></i>Back to Dashboard
|
||||||
|
</a>
|
||||||
|
<button onclick="window.location.reload()" class="btn btn-outline-primary">
|
||||||
|
<i class="fas fa-sync-alt me-2"></i>Try Again
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Error Details Section -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<button class="btn btn-link text-muted" type="button" data-bs-toggle="collapse" data-bs-target="#errorDetails" aria-expanded="false" aria-controls="errorDetails">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>Show Error Details
|
||||||
|
</button>
|
||||||
|
<div class="collapse mt-3" id="errorDetails">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||||
|
<h6 class="card-subtitle text-muted">Error Details</h6>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" onclick="copyErrorDetails()">
|
||||||
|
<i class="fas fa-copy me-1"></i>Copy
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<pre class="text-start mb-0" style="font-size: 0.875rem; max-height: 200px; overflow-y: auto;" id="errorText">{{ error }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block extra_js %}
|
||||||
|
<script>
|
||||||
|
function copyErrorDetails() {
|
||||||
|
const errorText = document.getElementById('errorText').textContent;
|
||||||
|
navigator.clipboard.writeText(errorText).then(() => {
|
||||||
|
const copyBtn = document.querySelector('#errorDetails .btn');
|
||||||
|
const originalText = copyBtn.innerHTML;
|
||||||
|
copyBtn.innerHTML = '<i class="fas fa-check me-1"></i>Copied!';
|
||||||
|
setTimeout(() => {
|
||||||
|
copyBtn.innerHTML = originalText;
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user