Skip to content

Commit 8b70926

Browse files
authored
Merge pull request #68 from RGBOARD/history-page
View Upload History
2 parents c7f8723 + fb788c3 commit 8b70926

14 files changed

Lines changed: 605 additions & 190 deletions

File tree

app.py

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,18 @@ def update_design_image(design_id):
136136
)
137137

138138

139+
# @app.route("/design/<int:design_id>", methods=['GET'])
140+
# @jwt_required()
141+
# def get_design():
142+
# handler = Design(email=get_jwt_identity())
143+
# return handler.get_design(design_id=request.form.get('design_id'))
144+
139145
@app.route("/design/<int:design_id>", methods=['GET'])
140146
@jwt_required()
141-
def get_design():
147+
def get_design(design_id):
142148
handler = Design(email=get_jwt_identity())
143-
return handler.get_design(design_id=request.form.get('design_id'))
144-
149+
# Use the URL param, not request.form
150+
return handler.get_design(design_id=design_id)
145151

146152
@app.route("/designs", methods=['GET'])
147153
@jwt_required()
@@ -293,28 +299,38 @@ def update_item_order(queue_id):
293299
return handler.update_item_order(queue_id=queue_id, new_order=new_order)
294300

295301

296-
@app.route("/queue_item", methods=['GET', 'POST'])
297-
def handleQueueItem():
298-
if request.method == 'GET':
299-
handler = QueueItem()
300-
return handler.getAllQueueItem()
301-
else:
302-
try:
303-
data = request.json
304-
if not data:
305-
return jsonify("No data provided"), 400
306-
307-
valid_keys = {'design_id', 'start_time', 'end_time', 'display_duration',
308-
'scheduled', 'scheduled_at'}
309-
if not any(key in data for key in valid_keys):
310-
return jsonify("Missing a key"), 400
311302

312-
handler = QueueItem()
313-
return handler.addNewQueueItem(data)
314-
except Exception as e:
315-
print("Error processing request:", e)
316-
return jsonify("Invalid JSON data provided:"), 400
303+
# ————— GET all queue items (public) —————
304+
@app.route("/queue_item", methods=['GET'])
305+
def handleGetQueueItems():
306+
handler = QueueItem()
307+
items = handler.getAllQueueItem()
308+
return jsonify(items), 200
317309

310+
# ————— Create a new queue item (auth required) —————
311+
@app.route("/queue_item", methods=['POST'])
312+
@jwt_required()
313+
def handleCreateQueueItem():
314+
data = request.get_json() or {}
315+
required_keys = {
316+
'design_id',
317+
'start_time',
318+
'end_time',
319+
'display_duration',
320+
'scheduled',
321+
'scheduled_at'
322+
}
323+
324+
if not required_keys.issubset(data):
325+
return jsonify("Missing one of required keys"), 400
326+
327+
handler = QueueItem()
328+
try:
329+
new_item = handler.addNewQueueItem(data)
330+
return jsonify(new_item), 201
331+
except Exception as e:
332+
print("Error processing request:", e)
333+
return jsonify("Invalid JSON data provided"), 400
318334

319335
@app.route("/queue_item/<int:queue_id>", methods=['GET', 'PUT', 'DELETE'])
320336
def handleQueueItemById(queue_id):
@@ -349,35 +365,23 @@ def handleQueueItemById(queue_id):
349365
@app.route("/queue_item/scheduled", methods=['GET'])
350366
@jwt_required()
351367
def get_scheduled_designs():
352-
# If needed, you can also pass the identity to restrict results
353-
# For example: identity = get_jwt_identity()
354-
handler = QueueItem() # Assumes your QueueItem controller exists similarly to Design.
368+
369+
handler = QueueItem()
355370
scheduled_items = handler.getScheduledDesigns()
356371
return jsonify(scheduled_items), 200
357372

358373

359374
# UploadHistory-----------------------------------------------------------------------------------------------------------
360-
@app.route("/upload_history", methods=['GET', 'POST'])
361-
def handleUploadHistory():
362-
if request.method == 'GET':
363-
handler = UploadHistory()
364-
return handler.getAllUploadHistory()
365-
else: # POST
366-
try:
367-
data = request.json
368-
if not data:
369-
return jsonify("No data provided"), 400
370375

371-
valid_keys = {'design_id', 'attempt_time', 'file_size', 'status'}
372-
if not any(key in data for key in valid_keys):
373-
return jsonify("Missing a key"), 400
374-
375-
handler = UploadHistory()
376-
return handler.addNewUploadHistory(data)
377-
except Exception as e:
378-
print("Error processing request:", e)
379-
return jsonify("Invalid JSON data provided"), 400
376+
@app.route("/upload_history", methods=['GET'])
377+
@jwt_required()
378+
def get_upload_history_for_current_user():
379+
return jsonify(UploadHistory().getAllUploadHistory()), 200
380380

381+
@app.route("/upload_history/pagination", methods=['GET'])
382+
@jwt_required()
383+
def get_upload_history_paginated():
384+
return UploadHistory().getAllUploadHistoryPaginated()
381385

382386
@app.route("/upload_history/<int:history_id>", methods=['GET', 'PUT', 'DELETE'])
383387
def handleUploadHistoryById(history_id):
@@ -391,7 +395,7 @@ def handleUploadHistoryById(history_id):
391395
return jsonify("No data provided"), 400
392396

393397
# For partial updates, you might remove this check or adapt it
394-
valid_keys = {'design_id', 'attempt_time', 'file_size', 'status'}
398+
valid_keys = {'design_id', 'attempt_time', 'status'}
395399
if not any(key in data for key in valid_keys):
396400
return jsonify("Missing a key"), 400
397401

controller/queue_item.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
from flask import jsonify
2+
from flask_jwt_extended import jwt_required, get_jwt_identity
3+
4+
from controller.upload_history import UploadHistory
25
from controller.user import User
36
from model.queue_item import QueueItemDAO
7+
from datetime import datetime
8+
49

510

611
class QueueItem:
@@ -51,9 +56,20 @@ def addNewQueueItem(self, data):
5156
display_duration = data['display_duration']
5257
scheduled = data['scheduled']
5358
scheduled_at = data['scheduled_at']
59+
5460
dao = QueueItemDAO()
55-
queue_item = dao.addNewQueueItem(design_id, start_time, end_time, display_duration, scheduled, scheduled_at)
61+
queue_item = dao.addNewQueueItem(
62+
design_id, start_time, end_time,
63+
display_duration, scheduled, scheduled_at
64+
)
5665
result = self.make_json_one(queue_item)
66+
67+
UploadHistory().addNewUploadHistory({
68+
'design_id': design_id,
69+
'attempt_time': datetime.utcnow().isoformat(),
70+
'status': 'successful'
71+
})
72+
5773
return result
5874

5975
def getQueueItemById(self, queue_id):
@@ -102,7 +118,6 @@ def deleteQueueItemById(self, queue_id):
102118
def getScheduledDesigns(self):
103119
dao = QueueItemDAO()
104120
rows = dao.getScheduledDesigns()
105-
# Build a list of dicts, merging fields from both tables
106121
result = []
107122
for row in rows:
108123
item = {
@@ -153,3 +168,25 @@ def get_all_items_paginated(self, page, page_size):
153168
return jsonify(error="Unauthorized. Not admin."), 401
154169

155170
return jsonify(error="Unauthorized. No token."), 401
171+
172+
@jwt_required()
173+
def getUserHistory(self):
174+
user_email = get_jwt_identity()
175+
176+
rows = QueueItemDAO().getByUserEmail(user_email)
177+
178+
result = []
179+
for (history_id, design_id, created_at,
180+
display_duration, display_order, status,
181+
title, pixel_data) in rows:
182+
result.append({
183+
'history_id': history_id,
184+
'design_id': design_id,
185+
'created_at': created_at,
186+
'display_duration': display_duration,
187+
'display_order': display_order,
188+
'status': 'scheduled' if status else 'pending',
189+
'title': title,
190+
'pixel_data': pixel_data,
191+
})
192+
return result

controller/upload_history.py

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,88 @@
1-
from flask import jsonify
1+
import math
2+
3+
from flask import jsonify, request
4+
from flask_jwt_extended import jwt_required, get_jwt_identity
25
from model.upload_history import UploadHistoryDAO
36

47
class UploadHistory:
58
def make_json(self, tuples):
6-
79
result = []
810
for t in tuples:
9-
D = {}
10-
D['history_id'] = t[0]
11-
D['design_id'] = t[1]
12-
D['attempt_time'] = t[2]
13-
D['file_size'] = t[3]
14-
D['status'] = t[4]
11+
D = {
12+
'history_id': t[0],
13+
'design_id': t[1],
14+
'attempt_time': t[2],
15+
'status': t[3],
16+
'title': t[4],
17+
'pixel_data': t[5]
18+
}
1519
result.append(D)
1620
return result
1721

1822
def make_json_one(self, row):
23+
return {
24+
'history_id': row[0],
25+
'design_id': row[1],
26+
'attempt_time': row[2],
27+
'status': row[3],
28+
'title': row[4],
29+
'pixel_data': row[5]
30+
}
1931

20-
result = {}
21-
result['history_id'] = row[0]
22-
result['design_id'] = row[1]
23-
result['attempt_time'] = row[2]
24-
result['file_size'] = row[3]
25-
result['status'] = row[4]
26-
return result
27-
32+
@jwt_required()
2833
def getAllUploadHistory(self):
34+
email = get_jwt_identity()
2935
dao = UploadHistoryDAO()
30-
rows = dao.getAllUploadHistory()
36+
rows = dao.getByUserEmail(email)
3137
return self.make_json(rows)
3238

3339
def addNewUploadHistory(self, data):
34-
3540
design_id = data['design_id']
3641
attempt_time = data['attempt_time']
37-
file_size = data['file_size']
3842
status = data['status']
39-
4043
dao = UploadHistoryDAO()
41-
row = dao.addNewUploadHistory(design_id, attempt_time, file_size, status)
44+
row = dao.addNewUploadHistory(design_id, attempt_time, status)
4245
return self.make_json_one(row)
4346

4447
def getUploadHistoryById(self, history_id):
4548
dao = UploadHistoryDAO()
4649
record = dao.getUploadHistoryById(history_id)
4750
if not record:
4851
return jsonify("Not Found"), 404
49-
else:
50-
return self.make_json_one(record)
52+
return self.make_json_one(record)
5153

5254
def updateUploadHistoryById(self, history_id, data):
5355
dao = UploadHistoryDAO()
5456
record = dao.updateUploadHistoryById(history_id, data)
5557
if not record:
5658
return jsonify("Not Found"), 404
57-
else:
58-
return self.make_json_one(record)
59+
return self.make_json_one(record)
5960

6061
def deleteUploadHistoryById(self, history_id):
6162
dao = UploadHistoryDAO()
6263
deleted_id = dao.deleteUploadHistoryById(history_id)
6364
if not deleted_id:
6465
return jsonify("Not Found"), 404
65-
else:
66-
return jsonify("Successfully deleted UploadHistory with ID " + str(deleted_id) + "!"), 200
66+
return jsonify(f"Successfully deleted UploadHistory with ID {deleted_id}!"), 200
67+
68+
@jwt_required()
69+
def getAllUploadHistoryPaginated(self):
70+
try:
71+
email = get_jwt_identity()
72+
page = int(request.args.get('page', 1))
73+
size = int(request.args.get('size', 6))
74+
dao = UploadHistoryDAO()
75+
76+
total = dao.countByUserEmail(email)
77+
rows = dao.getByUserEmailPaginated(email, page, size)
78+
items = self.make_json(rows)
79+
pages = math.ceil(total / size) if size > 0 else 0
80+
81+
return jsonify({
82+
'items': items,
83+
'page': page,
84+
'pages': pages
85+
}), 200
86+
except Exception as e:
87+
print(f"Error in paginated upload history: {e}")
88+
return jsonify({'error': 'Failed to fetch paginated upload history'}), 500

model/queue_item.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,26 @@ def getQueueItemById(self, queue_id):
3636
cursor.close()
3737
return result
3838

39-
def addNewQueueItem(self, design_id, start_time, end_time, display_duration, scheduled, scheduled_at):
4039

40+
def addNewQueueItem(self, design_id, start_time, end_time,
41+
display_duration, scheduled, scheduled_at):
4142
cursor = self.conn.cursor()
43+
cursor.execute("SELECT COUNT(*) FROM queue_item;")
44+
display_order = cursor.fetchone()[0] + 1
4245

43-
count_query = """ SELECT COUNT(*)
44-
FROM queue_item"""
45-
cursor.execute(count_query)
46-
items = cursor.fetchone()[0]
47-
display_order = items + 1
46+
cursor.execute("""
47+
INSERT INTO queue_item
48+
(design_id, start_time, end_time, display_duration, display_order, scheduled, scheduled_at)
49+
VALUES (?, ?, ?, ?, ?, ?, ?);
50+
""", (design_id, start_time, end_time, display_duration,
51+
display_order, scheduled, scheduled_at))
4852

49-
query = "insert into queue_item (design_id, start_time, end_time, display_duration, display_order, scheduled, scheduled_at) values (?, ?, ?, ?, ?, ?, ?);"
50-
cursor.execute(query,
51-
(design_id, start_time, end_time, display_duration, display_order, scheduled, scheduled_at))
5253
self.conn.commit()
53-
query = "select * from queue_item order by queue_id desc limit 1"
54-
cursor.execute(query)
55-
result = cursor.fetchone()
54+
55+
cursor.execute("SELECT * FROM queue_item ORDER BY queue_id DESC LIMIT 1;")
56+
row = cursor.fetchone()
5657
cursor.close()
57-
return result
58+
return row
5859

5960
def updateQueueItemById(self, queue_id, data):
6061
cursor = self.conn.cursor()
@@ -223,6 +224,32 @@ def get_all_items_paginated(self, page, page_size):
223224
"error": str(e)
224225
}
225226

227+
228+
def getByUserEmail(self, email):
229+
cursor = self.conn.cursor()
230+
query = """
231+
SELECT
232+
qi.queue_id AS history_id,
233+
qi.design_id,
234+
qi.created_at AS created_at,
235+
qi.display_duration,
236+
qi.display_order,
237+
qi.scheduled AS status,
238+
d.title,
239+
d.pixel_data
240+
FROM queue_item qi
241+
JOIN design d
242+
ON d.design_id = qi.design_id
243+
JOIN user u
244+
ON u.user_id = d.user_id
245+
WHERE u.email = ?
246+
ORDER BY qi.start_time DESC;
247+
"""
248+
cursor.execute(query, (email,))
249+
rows = cursor.fetchall()
250+
cursor.close()
251+
return rows
252+
226253
def is_design_in_queue(self, design_id):
227254
cursor = self.conn.cursor()
228255
query = "SELECT 1 FROM queue_item WHERE design_id = ?"
@@ -245,3 +272,4 @@ def is_design_scheduled(self, design_id):
245272
return False
246273
finally:
247274
cursor.close()
275+

0 commit comments

Comments
 (0)