initial work of the arcline tickets

This commit is contained in:
Blake Ridgway
2026-07-13 20:44:57 -05:00
parent 28e38916f2
commit 7807a674b3
13 changed files with 1199 additions and 372 deletions

150
app.py Normal file
View File

@@ -0,0 +1,150 @@
"""Flask-based ticketing system web application."""
from flask import Flask, redirect, render_template, request, url_for
from models import Ticket, TicketPriority, TicketStatus
from store import get_store
app = Flask(__name__)
# ── helper ───────────────────────────────────────────────────────
def _priorities() -> list[tuple[str, str]]:
return [(p.value, p.name.replace("_", " ").title()) for p in TicketPriority]
def _statuses() -> list[tuple[str, str]]:
return [(s.value, s.name.replace("_", " ").title()) for s in TicketStatus]
def _ticket_from_form() -> Ticket:
return Ticket(
title=request.form.get("title", "").strip(),
description=request.form.get("description", "").strip(),
priority=TicketPriority(request.form.get("priority", "medium")),
status=TicketStatus(request.form.get("status", "open")),
assignee=request.form.get("assignee", "").strip(),
project=request.form.get("project", "").strip(),
)
# ── routes ───────────────────────────────────────────────────────
@app.route("/")
def index() -> str:
store = get_store()
status_filter = request.args.get("status", "")
priority_filter = request.args.get("priority", "")
project_filter = request.args.get("project", "")
search = request.args.get("search", "")
tickets = store.list_tickets(
status=status_filter or None,
priority=priority_filter or None,
search=search or None,
project=project_filter or None,
)
counts = store.count_by_status()
projects = store.get_projects()
return render_template(
"index.html",
tickets=tickets,
status_filter=status_filter,
priority_filter=priority_filter,
project_filter=project_filter,
search=search,
counts=counts,
priorities=_priorities(),
statuses=_statuses(),
projects=projects,
)
@app.route("/tickets/new", methods=["GET", "POST"])
def create_ticket() -> str:
if request.method == "POST":
ticket = _ticket_from_form()
if not ticket.title:
return render_template(
"create.html",
priorities=_priorities(),
statuses=_statuses(),
ticket=ticket,
error="Title is required.",
)
store = get_store()
store.create_ticket(ticket)
return redirect(url_for("index"))
return render_template(
"create.html",
priorities=_priorities(),
statuses=_statuses(),
ticket=None,
)
@app.route("/tickets/<int:ticket_id>")
def view_ticket(ticket_id: int) -> str:
store = get_store()
ticket = store.get_ticket(ticket_id)
if ticket is None:
return "Ticket not found", 404
return render_template(
"detail.html",
ticket=ticket,
priorities=_priorities(),
statuses=_statuses(),
)
@app.route("/tickets/<int:ticket_id>/edit", methods=["GET", "POST"])
def edit_ticket(ticket_id: int) -> str:
store = get_store()
ticket = store.get_ticket(ticket_id)
if ticket is None:
return "Ticket not found", 404
if request.method == "POST":
title = request.form.get("title", "").strip()
if not title:
return render_template(
"edit.html",
ticket=ticket,
priorities=_priorities(),
statuses=_statuses(),
error="Title is required.",
)
updates = {
"title": title,
"description": request.form.get("description", "").strip(),
"priority": TicketPriority(request.form.get("priority", "medium")),
"status": TicketStatus(request.form.get("status", "open")),
"assignee": request.form.get("assignee", "").strip(),
"project": request.form.get("project", "").strip(),
}
store.update_ticket(ticket_id, updates)
return redirect(url_for("view_ticket", ticket_id=ticket_id))
return render_template(
"edit.html",
ticket=ticket,
priorities=_priorities(),
statuses=_statuses(),
)
@app.route("/tickets/<int:ticket_id>/delete", methods=["POST"])
def delete_ticket(ticket_id: int) -> str:
store = get_store()
store.delete_ticket(ticket_id)
return redirect(url_for("index"))
# ── entrypoint ───────────────────────────────────────────────────
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=5000)