#5 Added more data to stats page and improved CSS
This commit is contained in:
		| @@ -46,7 +46,7 @@ class DatabaseController(ABC): | |||||||
|         for attr, value in with_fields.items(): |         for attr, value in with_fields.items(): | ||||||
|             try: |             try: | ||||||
|                 setattr(obj, attr, value) |                 setattr(obj, attr, value) | ||||||
|             except KeyError: |             except AttributeError: | ||||||
|                 return of(value) |                 return of(value) | ||||||
|         return obj |         return obj | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| from .database import DatabaseController | from .database import DatabaseController | ||||||
| from models.stats import Stats | from models.stats import Stats | ||||||
| from datetime import datetime | from datetime import datetime, timedelta | ||||||
| from utils.general_utils import is_within_x_days | from utils.general_utils import is_within_x_days | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -52,7 +52,7 @@ class StatsController(DatabaseController): | |||||||
|         return self.get_many(query, params) |         return self.get_many(query, params) | ||||||
|  |  | ||||||
|     def read_days(self, product_id: int, prev_days: int = 7 |     def read_days(self, product_id: int, prev_days: int = 7 | ||||||
|                   ) -> dict[int, list[Stats]] | None: |                   ) -> dict[datetime, list[Stats]] | None: | ||||||
|         """ Returns data from within the given number of days """ |         """ Returns data from within the given number of days """ | ||||||
|         data = self.read_product(product_id) |         data = self.read_product(product_id) | ||||||
|  |  | ||||||
| @@ -64,16 +64,19 @@ class StatsController(DatabaseController): | |||||||
|                 data |                 data | ||||||
|             )) |             )) | ||||||
|  |  | ||||||
|         day_views: dict[int, list[Stats]] = dict() |         day_views: dict[str, list[Stats]] = dict() | ||||||
|  |  | ||||||
|         for i in range(0, prev_days): |         for i in range(0, prev_days): | ||||||
|             day_views[i] = list() |             key = datetime.today() - timedelta(days=i) | ||||||
|  |             day_views[key.strftime('%b-%d')] = list() | ||||||
|  |  | ||||||
|  |         print(list(day_views)) | ||||||
|         # Organise data into distinct |         # Organise data into distinct | ||||||
|         for view in filtered_data: |         for view in filtered_data: | ||||||
|             diff = datetime.now()-view.viewDate |             key = datetime.today() - (datetime.today() - view.viewDate) | ||||||
|             day_views[diff.days].append(view) |             day_views[key.strftime('%b-%d')].append(view) | ||||||
|  |  | ||||||
|  |         print(list(day_views)) | ||||||
|         return day_views |         return day_views | ||||||
|  |  | ||||||
|     def read_product_views(self, id: int): |     def read_product_views(self, id: int): | ||||||
|   | |||||||
| @@ -31,14 +31,16 @@ def view_product_stats(id: int): | |||||||
|     prev_days: int = request.args.get('prev_days', 7, int) |     prev_days: int = request.args.get('prev_days', 7, int) | ||||||
|     data = db.read_days(id, prev_days) |     data = db.read_days(id, prev_days) | ||||||
|  |  | ||||||
|  |     # Recent Views | ||||||
|     product_view_frequency_data = dict(map( |     product_view_frequency_data = dict(map( | ||||||
|         lambda k, v: (k, random.randint(0, 100)), |         lambda k, v: (k, random.randint(70, 100)), | ||||||
|         # lambda k, v: (k, len(v)), |         # lambda k, v: (k, len(v)), | ||||||
|         data.keys(), |         data.keys(), | ||||||
|         data.values() |         data.values() | ||||||
|     )) |     )) | ||||||
|  |  | ||||||
|     print(db.read_product_views(id)) |     # Total Views | ||||||
|  |     total_views = db.read_product_views(id) | ||||||
|  |  | ||||||
|     db = ProductController() |     db = ProductController() | ||||||
|     product = db.read_id(id) |     product = db.read_id(id) | ||||||
| @@ -62,7 +64,7 @@ def view_product_stats(id: int): | |||||||
|         "age": time_since_posted, |         "age": time_since_posted, | ||||||
|         "ranking": 0, |         "ranking": 0, | ||||||
|         "views": { |         "views": { | ||||||
|             "total": 0, |             "total": total_views, | ||||||
|             "headings": list(reversed(product_view_frequency_data.keys())), |             "headings": list(reversed(product_view_frequency_data.keys())), | ||||||
|             "data": list(reversed(product_view_frequency_data.values())) |             "data": list(reversed(product_view_frequency_data.values())) | ||||||
|         }, |         }, | ||||||
| @@ -72,8 +74,7 @@ def view_product_stats(id: int): | |||||||
|     return render_template( |     return render_template( | ||||||
|         "index.html", |         "index.html", | ||||||
|         content="stats.html", |         content="stats.html", | ||||||
|         headings=list(reversed(product_view_frequency_data.keys())), |         data=data | ||||||
|         data=list(reversed(product_view_frequency_data.values())) |  | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -57,11 +57,11 @@ CREATE TABLE IF NOT EXISTS Views ( | |||||||
|     id INTEGER PRIMARY KEY, |     id INTEGER PRIMARY KEY, | ||||||
|     userID INTEGER |     userID INTEGER | ||||||
|         REFERENCES Users (id) |         REFERENCES Users (id) | ||||||
|         ON DELETE NO ACTION |         ON DELETE CASCADE | ||||||
|         ON UPDATE NO ACTION, |         ON UPDATE NO ACTION, | ||||||
|     productID INTEGER NOT NULL |     productID INTEGER NOT NULL | ||||||
|         REFERENCES Users (id) |         REFERENCES Users (id) | ||||||
|         ON DELETE NO ACTION |         ON DELETE CASCADE | ||||||
|         ON UPDATE NO ACTION, |         ON UPDATE NO ACTION, | ||||||
|     viewDate TIMESTAMP NOT NULL |     viewDate TIMESTAMP NOT NULL | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								static/css/stats.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								static/css/stats.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | .stats { | ||||||
|  |     display: flex; | ||||||
|  |     justify-content: center; | ||||||
|  |     align-items: center; | ||||||
|  |     gap: 1rem; | ||||||
|  | } | ||||||
| @@ -1,10 +1,30 @@ | |||||||
| <link rel="stylesheet" href="{{ url_for('static', filename='css/products.css') }}"> | <link rel="stylesheet" href="{{ url_for('static', filename='css/products.css') }}"> | ||||||
|  | <link rel="stylesheet" href="{{ url_for('static', filename='css/stats.css') }}"> | ||||||
|   |   | ||||||
|  | <div class="stats"> | ||||||
| <div> |     <div> | ||||||
|     <canvas id="myChart" width="800px" height="500px"></canvas> |         <canvas id="myChart" width="800px" height="500px"></canvas> | ||||||
|  |         <br > | ||||||
|  |         <form method="GET"> | ||||||
|  |             <input type="radio" id="7days" name="prev_days" value=7> | ||||||
|  |             <label for="7days">7 Days</label><br> | ||||||
|  |             <input type="radio" id="31days" name="prev_days" value=31> | ||||||
|  |             <label for="31days">31 Days</label><br> | ||||||
|  |             <input type="radio" id="1year" name="prev_days" value=365> | ||||||
|  |             <label for="1year">1 Year</label> | ||||||
|  |             <input type="submit"> | ||||||
|  |         </form> | ||||||
|  |     </div> | ||||||
|  |     <div> | ||||||
|  |         <p>Age: {{data['age']}}</p> | ||||||
|  |         <p>Ranking: {{data['ranking']}}</p> | ||||||
|  |         <p>Stock Level: {{data['stocklevel']}}</p> | ||||||
|  |         <p>Total Views: {{data['views']['total']}}</p> | ||||||
|  |     </div> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| @@ -13,10 +33,10 @@ | |||||||
|     new Chart(ctx, { |     new Chart(ctx, { | ||||||
|         type: 'line', |         type: 'line', | ||||||
|         data: { |         data: { | ||||||
|             labels: {{headings}}, |             labels: {{data['views']['headings']|safe}}, | ||||||
|             datasets: [{ |             datasets: [{ | ||||||
|                 label: '# of Views', |                 label: '# of Views', | ||||||
|                 data: {{data}}, |                 data: {{data['views']['data']}}, | ||||||
|                 borderWidth: 1 |                 borderWidth: 1 | ||||||
|             }] |             }] | ||||||
|         }, |         }, | ||||||
| @@ -39,10 +59,3 @@ | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <div class="product-container"> |  | ||||||
|     {% if data != None %} |  | ||||||
|         {% for stat in data %} |  | ||||||
|         {% endfor %} |  | ||||||
|     {% endif %} |  | ||||||
| </div> |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user