ContactBridge

Log | Files | Refs | README

commit 7767aa14e055f5e8e6428502140b9e7af32f1189
parent 9a642663cde612e797a13540d9b73063249500de
Author: William Lindholm <william_lindholm@outlook.com>
Date:   Sun,  5 Nov 2023 22:44:54 +0100

Added pagination for tables.

Diffstat:
MWebAPI/routes.py | 2+-
MWebInterface/routes.py | 32+++++++-------------------------
MWebInterface/tableBuilder.py | 57+++++++++++++++++++++++++++++++++++++++++----------------
AWebInterface/tableFactory.py | 37+++++++++++++++++++++++++++++++++++++
Mdbrepository.py | 25+++++++++++++++++++++----
Mstatic/css/main.css | 4++++
Mtemplates/table.html | 33++++++++++++++-------------------
7 files changed, 125 insertions(+), 65 deletions(-)

diff --git a/WebAPI/routes.py b/WebAPI/routes.py @@ -44,7 +44,7 @@ class contact(Resource): @api.route('/messages') class Messages(Resource): def get(self): - messages = db_repo.fetch_messages() + messages = db_repo.get_all_messages() formatted_messages = [ { "id": message[0], diff --git a/WebInterface/routes.py b/WebInterface/routes.py @@ -5,6 +5,7 @@ from flask import Flask, request, redirect, url_for, render_template, session from dbrepository import DatabaseRepository from . import web_interface from .tableBuilder import TableBuilder +from .tableFactory import TableFactory db = DatabaseRepository() @@ -15,7 +16,7 @@ def home(): if not session.get('logged_in'): return redirect(url_for('web_interface.login')) - messages = db.fetch_messages() + messages = db.get_all_messages() formatted_messages = [ { @@ -35,31 +36,12 @@ def home(): @web_interface.route('/integrations') def integrations(): - # Define headers and rows for the messages table - headers = ["ID", "Message", "Date", "Delete"] - rows = [ - [1, "Hello World!", "2023-11-01"], - [2, "Another Message", "2023-11-02"], - ] + page_number = request.args.get('page', 1, type=int) + + tables = TableFactory() + message_table = tables.get_message_table(page_number) - def delete_link(row_data): - # Assuming row_data is a dictionary that contains an 'id' key - id = row_data[0] - # Return a string of HTML. The 'material-icons' class is used for Material Icons - return f'<a href="/message/delete/{id}" class="delete-icon"><i class="material-icons">delete</i></a>' - - # Initialize TableBuilder and configure the table - table_builder = TableBuilder() - table_builder.set_headers(headers) - table_builder.add_rows(rows) - table_builder.set_pagination(enabled=True, page_size=5) - table_builder.set_sortable(["ID", "Date"]) - table_builder.add_callback_column(delete_link) - table_builder.set_on_click("/message/{0}") - - # Build the TableInstance - table_instance = table_builder.build() - return render_template('integrations.html', page_title="Integrations", table=table_instance) + return render_template('integrations.html', page_title="Integrations", table=message_table) @web_interface.route('/login', methods=['GET', 'POST']) def login(): diff --git a/WebInterface/tableBuilder.py b/WebInterface/tableBuilder.py @@ -1,4 +1,4 @@ -class TableInstance: +class TableBuilder: def __init__(self): self.headers = [] self.rows = [] @@ -6,53 +6,79 @@ class TableInstance: self.pagination_enabled = False self.page_size = 10 self.current_page = 1 - self.callback_column = None + self.total_pages = 0 + self.callback_columns = [] self.row_click_url_template = "" def add_header(self, header): self.headers.append(header) + return self def add_row(self, row): self.rows.append(row) + return self def enable_pagination(self, page_size=10): self.pagination_enabled = True self.page_size = page_size + return self def set_sortable_columns(self, columns): self.sortable_columns = columns + return self def set_callback_column(self, callback): self.callback_column = callback + return self def set_row_click_url_template(self, url_template): self.row_click_url_template = url_template - - -class TableBuilder: - def __init__(self): - self.table_instance = TableInstance() + return self def set_headers(self, headers): for header in headers: - self.table_instance.add_header(header) + self.add_header(header) + return self def add_rows(self, rows): for row in rows: - self.table_instance.add_row(row) + self.add_row(row) + return self def set_pagination(self, enabled=True, page_size=10): if enabled: - self.table_instance.enable_pagination(page_size) + self.enable_pagination(page_size) + return self + + def set_total_pages(self, total_pages): + self.total_pages = total_pages + return self + + def set_current_page(self, page): + self.current_page = page + return self def set_sortable(self, sortable_columns): - self.table_instance.set_sortable_columns(sortable_columns) + self.set_sortable_columns(sortable_columns) + return self def add_callback_column(self, callback): - self.table_instance.set_callback_column(callback) + self.callback_columns.append(callback) + return self def set_on_click(self, url_template): - self.table_instance.set_row_click_url_template(url_template) + self.set_row_click_url_template(url_template) + return self - def build(self): - return self.table_instance -\ No newline at end of file + def get_table_data(self): + return { + "headers": self.headers, + "rows": self.rows, + "sortable_columns": self.sortable_columns, + "pagination_enabled": self.pagination_enabled, + "page_size": self.page_size, + "current_page": self.current_page, + "total_pages": self.total_pages, + "callback_columns": self.callback_columns, + "row_click_url_template": self.row_click_url_template + } diff --git a/WebInterface/tableFactory.py b/WebInterface/tableFactory.py @@ -0,0 +1,36 @@ +from WebInterface.tableBuilder import TableBuilder +from dbrepository import DatabaseRepository + + +class TableFactory: + + def __init__(self): + self.db = DatabaseRepository() + + @staticmethod + def delete_link(row_data): + return f'<a href="/message/delete/{row_data[0]}" class="delete-icon"><i class="material-icons">delete</i></a>' + + def get_message_table(self, page=0, page_size=10): + headers = [ + ("ID", "8%"), + ("Sender", "10%"), + ("Relevance", "10%"), + ("Message", "67%"), + ("Delete", "5%") + ] + + messages, total_pages = self.db.get_messages(page, page_size) + + table_data = (TableBuilder() + .set_headers(headers) + .add_rows(messages) + .set_pagination(enabled=True, page_size=page_size) + .set_total_pages(total_pages) + .set_current_page(page) + .set_sortable(["ID"]) + .set_on_click("/message/{0}") + .add_callback_column(self.delete_link) + .get_table_data()) + + return table_data +\ No newline at end of file diff --git a/dbrepository.py b/dbrepository.py @@ -1,5 +1,7 @@ +import math import sqlite3 + class DatabaseRepository: DATABASE_FILE = 'messages.db' @@ -37,10 +39,26 @@ class DatabaseRepository: conn.commit() conn.close() - def fetch_messages(self): + def get_all_messages(self): conn = sqlite3.connect(self.DATABASE_FILE) cursor = conn.cursor() - cursor.execute("SELECT * FROM messages ORDER BY timestamp DESC") + cursor.execute("SELECT id, email, relevance, message_content FROM messages ORDER BY timestamp DESC") messages = cursor.fetchall() conn.close() - return messages -\ No newline at end of file + return messages + + def get_messages(self, page, page_size): + conn = sqlite3.connect(self.DATABASE_FILE) + cursor = conn.cursor() + + total_messages = cursor.execute('SELECT COUNT(*) FROM messages').fetchone()[0] + offset = (page - 1) * page_size + total_pages = math.ceil(total_messages / page_size) + + paginated_messages = cursor.execute( + 'SELECT id, email, relevance, message_content FROM messages ORDER BY timestamp DESC LIMIT ? OFFSET ?', + (page_size, offset) + ).fetchall() + + conn.close() + return paginated_messages, total_pages diff --git a/static/css/main.css b/static/css/main.css @@ -83,4 +83,8 @@ h1.mobile { .delete-icon { color: red; +} + +td, td { + min-width: 100px; } \ No newline at end of file diff --git a/templates/table.html b/templates/table.html @@ -1,42 +1,37 @@ -<table id="table-instance" class="highlight"> +<table style="table-layout: fixed;" id="table-instance" class="highlight"> <thead> <tr> - <!-- Headers and sortable logic will be inserted here --> - {% for header in table.headers %} - <th> - {{ header }} - {% if header in table.sortable_columns %} - <!-- Add sorting logic/link here --> + {% for header, width in table.headers %} + <th style="width: {{ width }}"> + {{ header }} + {% if header in table.sortable_columns %} <a href="?sort_by={{ header }}&order=asc">↑</a> <a href="?sort_by={{ header }}&order=desc">↓</a> - {% endif %} + {% endif %} </th> {% endfor %} </tr> </thead> <tbody> - <!-- Rows and Data will be inserted here --> {% for row in table.rows %} <tr onclick="window.location.href='{{ table.row_click_url_template.format(row[0]) }}';"> {% for cell in row %} - <td>{{ cell }}</td> + <td><p class="truncate">{{ cell }}</p></td> + {% endfor %} + {% for callback_column in table.callback_columns %} + <td>{{ callback_column(row) | safe }}</td> {% endfor %} - <!-- Callback action buttons if any --> - {% if table.callback_column %} - <td>{{ table.callback_column(row) | safe }}</td> - {% endif %} </tr> {% endfor %} </tbody> </table> {% if table.pagination_enabled %} - <ul class="pagination"> - {% set total_pages = ((table.rows|length / table.page_size) | round(0, 'ceil')) | int %} - {% for i in range(1, total_pages + 1) %} +<ul class="pagination"> + {% for i in range(1, table.total_pages + 1) %} <li class="{% if table.current_page == i %}active{% else %}waves-effect{% endif %}"> - <a href="?page={{ i }}">{{ i }}</a> + <a href="?page={{ i }}">{{ i }}</a> </li> {% endfor %} - </ul> +</ul> {% endif %} \ No newline at end of file