Commit ·
d96f137
1
Parent(s): 722ee06
update file 015
Browse files- app.py +64 -24
- templates/tickets.html +14 -0
app.py
CHANGED
|
@@ -6,6 +6,10 @@ from datetime import datetime
|
|
| 6 |
import os
|
| 7 |
import uuid
|
| 8 |
import sqlite3
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
app = Flask(__name__)
|
| 11 |
|
|
@@ -130,30 +134,66 @@ def download_pdf(session_id):
|
|
| 130 |
|
| 131 |
@app.route("/tickets")
|
| 132 |
def view_tickets():
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
|
| 159 |
if __name__ == "__main__":
|
|
|
|
| 6 |
import os
|
| 7 |
import uuid
|
| 8 |
import sqlite3
|
| 9 |
+
import csv
|
| 10 |
+
import zipfile
|
| 11 |
+
from flask import Response, send_from_directory
|
| 12 |
+
from io import BytesIO
|
| 13 |
|
| 14 |
app = Flask(__name__)
|
| 15 |
|
|
|
|
| 134 |
|
| 135 |
@app.route("/tickets")
|
| 136 |
def view_tickets():
|
| 137 |
+
from_date = request.args.get("from")
|
| 138 |
+
to_date = request.args.get("to")
|
| 139 |
+
priority = request.args.get("priority")
|
| 140 |
+
search = request.args.get("search", "").lower()
|
| 141 |
+
page = int(request.args.get("page", 1))
|
| 142 |
+
per_page = 10
|
| 143 |
+
|
| 144 |
+
conn = sqlite3.connect("tickets.db")
|
| 145 |
+
c = conn.cursor()
|
| 146 |
+
|
| 147 |
+
query = "SELECT * FROM tickets WHERE 1=1"
|
| 148 |
+
params = []
|
| 149 |
+
|
| 150 |
+
if from_date and to_date:
|
| 151 |
+
query += " AND date BETWEEN ? AND ?"
|
| 152 |
+
params.extend([from_date, to_date])
|
| 153 |
+
if priority:
|
| 154 |
+
query += " AND LOWER(priority) = ?"
|
| 155 |
+
params.append(priority.lower())
|
| 156 |
+
|
| 157 |
+
query += " ORDER BY date DESC"
|
| 158 |
+
c.execute(query, params)
|
| 159 |
+
rows = c.fetchall()
|
| 160 |
+
conn.close()
|
| 161 |
+
|
| 162 |
+
# Filter search
|
| 163 |
+
filtered = [r for r in rows if search in r[1].lower() or search in r[2].lower() or search in r[3].lower()]
|
| 164 |
+
total = len(filtered)
|
| 165 |
+
pages = (total + per_page - 1) // per_page
|
| 166 |
+
start = (page - 1) * per_page
|
| 167 |
+
paginated = filtered[start:start + per_page]
|
| 168 |
+
|
| 169 |
+
return render_template("tickets.html", tickets=paginated, page=page, pages=pages, total=total)
|
| 170 |
+
|
| 171 |
+
@app.route("/export/csv")
|
| 172 |
+
def export_csv():
|
| 173 |
+
conn = sqlite3.connect("tickets.db")
|
| 174 |
+
c = conn.cursor()
|
| 175 |
+
c.execute("SELECT * FROM tickets")
|
| 176 |
+
rows = c.fetchall()
|
| 177 |
+
conn.close()
|
| 178 |
+
|
| 179 |
+
output = BytesIO()
|
| 180 |
+
writer = csv.writer(output)
|
| 181 |
+
writer.writerow(["ID", "First Name", "Last Name", "Email", "Issue", "Priority", "Date", "Filename"])
|
| 182 |
+
writer.writerows(rows)
|
| 183 |
+
|
| 184 |
+
output.seek(0)
|
| 185 |
+
return Response(output, mimetype="text/csv", headers={"Content-Disposition": "attachment;filename=tickets.csv"})
|
| 186 |
+
|
| 187 |
+
@app.route("/export/zip")
|
| 188 |
+
def export_zip():
|
| 189 |
+
zip_io = BytesIO()
|
| 190 |
+
with zipfile.ZipFile(zip_io, 'w') as zipf:
|
| 191 |
+
for file in os.listdir("pdfs"):
|
| 192 |
+
zipf.write(os.path.join("pdfs", file), arcname=file)
|
| 193 |
+
|
| 194 |
+
zip_io.seek(0)
|
| 195 |
+
return send_file(zip_io, mimetype="application/zip", as_attachment=True, download_name="tickets.zip")
|
| 196 |
+
|
| 197 |
|
| 198 |
|
| 199 |
if __name__ == "__main__":
|
templates/tickets.html
CHANGED
|
@@ -34,6 +34,20 @@
|
|
| 34 |
</head>
|
| 35 |
<body>
|
| 36 |
<h2>📋 Submitted Tickets</h2>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
<table>
|
| 38 |
<thead>
|
| 39 |
<tr>
|
|
|
|
| 34 |
</head>
|
| 35 |
<body>
|
| 36 |
<h2>📋 Submitted Tickets</h2>
|
| 37 |
+
<form method="get" action="/tickets" style="display:flex;gap:10px;flex-wrap:wrap;">
|
| 38 |
+
<input type="date" name="from">
|
| 39 |
+
<input type="date" name="to">
|
| 40 |
+
<select name="priority">
|
| 41 |
+
<option value="">All Priorities</option>
|
| 42 |
+
<option value="high">High</option>
|
| 43 |
+
<option value="medium">Medium</option>
|
| 44 |
+
<option value="low">Low</option>
|
| 45 |
+
</select>
|
| 46 |
+
<input type="text" name="search" placeholder="Search name/email/issue">
|
| 47 |
+
<button type="submit">Filter</button>
|
| 48 |
+
<a href="/export/csv"><button type="button">Export CSV</button></a>
|
| 49 |
+
<a href="/export/zip"><button type="button">Download ZIP</button></a>
|
| 50 |
+
</form>
|
| 51 |
<table>
|
| 52 |
<thead>
|
| 53 |
<tr>
|