This commit is contained in:
Anh-Thy04
2025-06-20 00:52:49 +02:00
parent 470a74388f
commit 378fcb0b93
6 changed files with 190 additions and 65 deletions

View File

@@ -1,14 +1,19 @@
from application import db, app from application import db, app
from application.dashboard.models import AllowedPlate, LoggedItem, datetime from application.dashboard.models import AllowedPlate, LoggedItem, datetime
from application.auth.models import User from application.auth.models import User
from datetime import datetime, timedelta
with app.app_context(): with app.app_context():
AllowedPlate.query.delete() AllowedPlate.query.delete()a
db.session.add(AllowedPlate("MUN389")) db.session.add(AllowedPlate("MUN389"))
db.session.commit() db.session.commit()
with app.app_context(): with app.app_context():
LoggedItem.query.delete() LoggedItem.query.delete()
custom_time = datetime.now() - timedelta(hours=1)
db.session.add(LoggedItem("MUN389", custom_time, True))
db.session.add(LoggedItem("MUN389", datetime.now(), True))
db.session.add(LoggedItem("MUN389", datetime.now(), True)) db.session.add(LoggedItem("MUN389", datetime.now(), True))
db.session.add(LoggedItem("MUN389", datetime.now(), False)) db.session.add(LoggedItem("MUN389", datetime.now(), False))
db.session.commit() db.session.commit()

View File

@@ -33,16 +33,49 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title fs-4">Numberplates</h5> <h5 class="card-title fs-4 mb-0">Numberplates</h5>
<div class="mt-2 mb-3">
<form method="get" class="mb-0">
<div class="row g-2 align-items-center">
<div class="col">
<input type="text" name="npfilter" class="form-control" placeholder="Search numberplate..." value="{{ request.args.get('npfilter', '') }}">
</div>
<div class="col">
<input type="text" name="idfilter" class="form-control" placeholder="Search by ID..." value="{{ request.args.get('idfilter', '') }}">
</div>
<div class="col-auto d-flex gap-2">
<button type="submit" class="btn btn-secondary">Filter</button>
</div>
</div>
</form>
</div>
{% if request.args.get('npfilter') or request.args.get('idfilter') %}
<div class="mb-2">
<span class="me-2">Active filters:</span>
{% if request.args.get('npfilter') %}
<a href="{{ url_for('dash.dashboard', idfilter=request.args.get('idfilter', '')) }}" class="badge bg-secondary text-decoration-none">
Numberplate: {{ request.args.get('npfilter') }} &times;
</a>
{% endif %}
{% if request.args.get('idfilter') %}
<a href="{{ url_for('dash.dashboard', npfilter=request.args.get('npfilter', '')) }}" class="badge bg-secondary text-decoration-none">
ID: {{ request.args.get('idfilter') }} &times;
</a>
{% endif %}
</div>
{% endif %}
<div class="log-container" style="max-height: 250px; overflow-y: auto;"> <div class="log-container" style="max-height: 250px; overflow-y: auto;">
<table class="table table-sm table-hover" id="numberplatesTable"> <table class="table table-sm table-hover align-middle">
<thead> <thead>
<tr> <tr>
<th scope="col" class="fs-5">ID</th> <th scope="col" class="fs-5" style="width: 21%;">ID</th>
<th scope="col" class="fs-5">Numberplate</th> <th scope="col" class="fs-5" style="width: 42%;">Numberplate</th>
<th scope="col" class="fs-5">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody id="numberplatesBody"> <tbody>
{% for plate in plates %} {% for plate in plates %}
<tr> <tr>
<td><small class="fs-6">{{ plate.id }}</small></td> <td><small class="fs-6">{{ plate.id }}</small></td>

View File

@@ -41,6 +41,16 @@
border: 1px solid #444 !important; border: 1px solid #444 !important;
} }
.dark-mode input::placeholder,
.dark-mode .form-control::placeholder {
color: #b0b0b0 !important;
opacity: 1 !important;
}
.dark-mode form select {
background-color: #23272b !important;
color: #e0e0e0 !important;
border: 1px solid #444 !important;
}
.dark-mode .btn { .dark-mode .btn {
background-color: #444 !important; background-color: #444 !important;
color: #e0e0e0 !important; color: #e0e0e0 !important;
@@ -94,6 +104,9 @@
<a class="nav-link active text-white" href="/dash/add"> <a class="nav-link active text-white" href="/dash/add">
Add numberplate Add numberplate
</a> </a>
<a class="nav-link active text-white" href="/dash/logs">
Edit Logs
</a>
</li> </li>
</ul> </ul>
<div class="d-flex justify-content-center mt-3"> <div class="d-flex justify-content-center mt-3">

View File

@@ -50,7 +50,39 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title fs-4">Numberplates</h5> <h5 class="card-title fs-4 mb-0">Numberplates</h5>
<div class="mt-2 mb-3">
<form method="get" class="mb-0">
<div class="row g-2 align-items-center">
<div class="col">
<input type="text" name="npfilter" class="form-control" placeholder="Search numberplate..." value="{{ request.args.get('npfilter', '') }}">
</div>
<div class="col">
<input type="text" name="idfilter" class="form-control" placeholder="Search by ID..." value="{{ request.args.get('idfilter', '') }}">
</div>
<div class="col-auto d-flex gap-2">
<button type="submit" class="btn btn-secondary">Filter</button>
</div>
</div>
</form>
</div>
{% if request.args.get('npfilter') or request.args.get('idfilter') %}
<div class="mb-2">
<span class="me-2">Active filters:</span>
{% if request.args.get('npfilter') %}
<a href="{{ url_for('dash.dashboard', idfilter=request.args.get('idfilter', '')) }}" class="badge bg-secondary text-decoration-none">
Numberplate: {{ request.args.get('npfilter') }} &times;
</a>
{% endif %}
{% if request.args.get('idfilter') %}
<a href="{{ url_for('dash.dashboard', npfilter=request.args.get('npfilter', '')) }}" class="badge bg-secondary text-decoration-none">
ID: {{ request.args.get('idfilter') }} &times;
</a>
{% endif %}
</div>
{% endif %}
<div class="log-container" style="max-height: 250px; overflow-y: auto;"> <div class="log-container" style="max-height: 250px; overflow-y: auto;">
<table class="table table-sm table-hover align-middle"> <table class="table table-sm table-hover align-middle">
<thead> <thead>

View File

@@ -1,30 +1,56 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<div class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="display-4 fw-bold" style="color: #313A4D;">Logs</h1>
</div>
<div class="col-md-12">
<div class="card mb-4"></div>
</div>
<div class="col-md-12"> <div class="col-md-12">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title fs-4">Numberplate Logs</h5> <h5 class="card-title fs-4">Logs</h5>
<form method="get" class="mb-3">
<div class="row g-2 align-items-center">
<div class="col-md-4">
<select name="order" class="form-select">
<option value="desc" {% if request.args.get('order', 'desc') == 'desc' %}selected{% endif %}>Newest First</option>
<option value="asc" {% if request.args.get('order') == 'asc' %}selected{% endif %}>Oldest First</option>
</select>
</div>
<div class="col-auto d-flex gap-2">
<button type="submit" class="btn btn-secondary">Sort</button>
</div>
</div>
</form>
<div class="log-container" style="max-height: 250px; overflow-y: auto;"> <div class="log-container" style="max-height: 250px; overflow-y: auto;">
<table class="table table-sm table-hover"> <table class="table table-sm table-hover">
<thead> <thead>
<tr> <tr>
<th scope="col" class="fs-5">Time</th> <th scope="col" class="fs-5" style="width: 21%">Time</th>
<th scope="col" class="fs-5">Numberplate</th> <th scope="col" class="fs-5" style="width: 42%">Numberplate</th>
<th scope="col" class="fs-5">Gate Status</th> <th scope="col" class="fs-5">Gate Status</th>
<th scope="col" class="fs-5">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for form in recent_logs %} {% for log in logs %}
<tr> <tr>
<td><small class="fs-6">{{ form.timestamp.strftime('%H:%M:%S') }}</small></td> <td><small class="fs-6">{{ log.dateLogged.strftime('%H:%M:%S') }}</small></td>
<td><small class="fs-6">{{ form.plate }}</small></td> <td><small class="fs-6">{{ log.plate }}</small></td>
<td> <td>
<span <span class="badge bg-secondary fs-6">
class="badge {% if log.status == 'success' %}bg-success{% elif log.status == 'warning' %}bg-warning{% elif log.status == 'error' %}bg-danger{% else %}bg-secondary{% endif %} fs-6"> {{ log.allowed }}
{{ form.allowed }}
</span> </span>
</td> </td>
<td>
<form method="POST" action="{{ url_for('dash.delete_log', id=log.id) }}" style="display:inline;" onsubmit="return confirm('Are you sure you want to delete this log entry?');">
<button type="submit" class="btn btn-sm btn-secondary">Delete</button>
</form>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@@ -33,5 +59,5 @@
</div> </div>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@@ -18,7 +18,14 @@ dash_blueprint = Blueprint("dash", __name__, template_folder="templates")
@dash_blueprint.route("/dashboard") @dash_blueprint.route("/dashboard")
# @login_required # @login_required
def dashboard(): def dashboard():
Plates = AllowedPlate.query.all() npfilter = request.args.get('npfilter', '')
idfilter = request.args.get('idfilter', '')
query = AllowedPlate.query
if npfilter:
query = query.filter(AllowedPlate.plate.contains(npfilter))
if idfilter:
query = query.filter(AllowedPlate.id == idfilter)
Plates = query.all()
logs = ( logs = (
LoggedItem.query.order_by(LoggedItem.dateLogged.desc()) # type: ignore LoggedItem.query.order_by(LoggedItem.dateLogged.desc()) # type: ignore
.limit(50) .limit(50)
@@ -33,6 +40,14 @@ def dashboard():
@dash_blueprint.route("/add", methods=["GET", "POST"]) @dash_blueprint.route("/add", methods=["GET", "POST"])
# @login_required # @login_required
def add(): def add():
npfilter = request.args.get('npfilter', '')
idfilter = request.args.get('idfilter', '')
query = AllowedPlate.query
if npfilter:
query = query.filter(AllowedPlate.plate.contains(npfilter))
if idfilter:
query = query.filter(AllowedPlate.id == idfilter)
form = npForm() form = npForm()
if form.validate_on_submit(): if form.validate_on_submit():
@@ -46,12 +61,20 @@ def add():
db.session.add(ap) db.session.add(ap)
db.session.commit() db.session.commit()
flash("Numberplate succesfully added") flash("Numberplate succesfully added")
# form wasn't valid Plates = query.all()
Plates = AllowedPlate.query.all()
return render_template( return render_template(
"add.html", form=npForm(formdata=None), plates=Plates "add.html", form=npForm(formdata=None), plates=Plates
) )
@dash_blueprint.route("/logs", methods=["GET", "POST"])
def log():
order = request.args.get('order', 'desc')
query = LoggedItem.query
if order == 'asc':
logs = query.order_by(LoggedItem.dateLogged.asc()).limit(50).all()
else:
logs = query.order_by(LoggedItem.dateLogged.desc()).limit(50).all()
return render_template("logs.html", logs=logs)
@dash_blueprint.route("/live", methods=["GET"]) @dash_blueprint.route("/live", methods=["GET"])
@login_required @login_required
@@ -70,13 +93,6 @@ def live_image():
) )
@dash_blueprint.route("/logs", methods=["GET", "POST"])
# @login_required
def logs():
form = LoggedItem.query.all()
return render_template("logs.html", form=form)
@dash_blueprint.route("/edit/<string:plate>", methods=["GET", "POST"]) @dash_blueprint.route("/edit/<string:plate>", methods=["GET", "POST"])
# login_required # login_required
def edit(plate: str): def edit(plate: str):