add 404/403 pages
This commit is contained in:
1 parent
c645c722d5
commit
34f03860a6
5 files changed
+137
-2
No files matched your search
@@ -2,7 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import click
|
||||
from flask import Flask
|
||||
from flask import Flask, render_template
|
||||
|
||||
from auth import current_user_id, is_logged_in
|
||||
from config import Config
|
||||
@@ -42,6 +42,14 @@ def create_app(config_overrides: dict | None = None) -> Flask:
|
||||
app.register_blueprint(account_bp)
|
||||
app.register_blueprint(leagues_bp)
|
||||
|
||||
@app.errorhandler(404)
|
||||
def not_found(e):
|
||||
return render_template("404.html"), 404
|
||||
|
||||
@app.errorhandler(403)
|
||||
def forbidden(e):
|
||||
return render_template("403.html"), 403
|
||||
|
||||
@app.cli.command("init-db")
|
||||
def init_db_command() -> None:
|
||||
if not database_extensions_available() or db is None:
|
||||
|
||||
@@ -9,7 +9,7 @@ DATA_PATH = BASE_DIR / "data" / "entries.csv"
|
||||
DEFAULT_DATABASE_URL = f"sqlite:///{BASE_DIR / 'data' / 'boker-dev.sqlite3'}"
|
||||
|
||||
ELIGIBLE_MIN_SESSIONS = 3
|
||||
APP_VERSION = "2.5.10"
|
||||
APP_VERSION = "2.5.11"
|
||||
|
||||
|
||||
def load_local_env(env_path: Path) -> None:
|
||||
|
||||
@@ -5604,6 +5604,91 @@ select.control { cursor: pointer; }
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
ERROR PAGES (404, 403)
|
||||
================================================================ */
|
||||
.page--error {
|
||||
padding: 0;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.error-pg {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 62px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(ellipse 90% 70% at 50% 60%, #1c0e3e 0%, #100820 55%, var(--bg) 100%),
|
||||
radial-gradient(ellipse 50% 40% at 80% 20%, rgba(155,140,240,.07) 0%, transparent 55%);
|
||||
}
|
||||
|
||||
/* large suit watermark */
|
||||
.error-pg__suit {
|
||||
position: absolute;
|
||||
font-size: clamp(320px, 46vw, 660px);
|
||||
color: rgba(155,140,240,.065);
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: none;
|
||||
}
|
||||
.error-pg--403 .error-pg__suit {
|
||||
color: rgba(155,140,240,.06);
|
||||
}
|
||||
|
||||
.error-pg__body {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
gap: 0;
|
||||
padding: clamp(32px, 5vw, 64px) clamp(24px, 5vw, 48px);
|
||||
}
|
||||
|
||||
.error-pg__code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: clamp(80px, 13vw, 148px);
|
||||
font-weight: 900;
|
||||
letter-spacing: -.04em;
|
||||
line-height: 1;
|
||||
background: linear-gradient(135deg, var(--accent) 0%, rgba(155,140,240,.35) 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.error-pg__title {
|
||||
font-size: clamp(28px, 4vw, 52px);
|
||||
font-weight: 800;
|
||||
color: var(--text);
|
||||
letter-spacing: -.04em;
|
||||
margin: 0 0 16px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.error-pg__sub {
|
||||
font-size: clamp(14px, 1.3vw, 16px);
|
||||
color: rgba(255,255,255,.42);
|
||||
max-width: 40ch;
|
||||
line-height: 1.68;
|
||||
margin: 0 0 28px;
|
||||
}
|
||||
|
||||
.error-pg__actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
LANDING — hero kicker (replaces pill eyebrow in hero only)
|
||||
================================================================ */
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}403 · Access Denied · myboker.org{% endblock %}
|
||||
{% block page_class %}page--error{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div class="error-pg error-pg--403">
|
||||
<div class="error-pg__suit" aria-hidden="true">♣</div>
|
||||
<div class="error-pg__body">
|
||||
<span class="error-pg__code">403</span>
|
||||
<h1 class="error-pg__title">Access denied.</h1>
|
||||
<p class="error-pg__sub">You don't have permission to view this page. If you think this is a mistake, contact your league owner.</p>
|
||||
<div class="error-pg__actions">
|
||||
<a class="btn btn--primary btn--lg" href="{{ url_for('public.home') }}">Go home →</a>
|
||||
{% if not is_logged_in %}
|
||||
<a class="btn btn--ghost btn--lg" href="{{ url_for('account.login') }}">Sign in</a>
|
||||
{% else %}
|
||||
<a class="btn btn--ghost btn--lg" href="javascript:history.back()">Go back</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}404 · Page Not Found · myboker.org{% endblock %}
|
||||
{% block page_class %}page--error{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div class="error-pg">
|
||||
<div class="error-pg__suit" aria-hidden="true">♠</div>
|
||||
<div class="error-pg__body">
|
||||
<span class="error-pg__code">404</span>
|
||||
<h1 class="error-pg__title">Page not found.</h1>
|
||||
<p class="error-pg__sub">That URL doesn't exist or the page has been moved. Double-check the address or head back to safety.</p>
|
||||
<div class="error-pg__actions">
|
||||
<a class="btn btn--primary btn--lg" href="{{ url_for('public.home') }}">Go home →</a>
|
||||
<a class="btn btn--ghost btn--lg" href="javascript:history.back()">Go back</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
Reference in new issue
Block a user