commit a6a036ba56805f8ad24fa295eb3f9114941b4550
parent 3757630acf1f0f1926deb0f3f2d39c2e0a5e0591
Author: William Lindholm <william_lindholm@outlook.com>
Date: Sun, 5 Nov 2023 19:04:19 +0100
Refactoring of web interface.
Diffstat:
8 files changed, 245 insertions(+), 45 deletions(-)
diff --git a/WebInterface/routes.py b/WebInterface/routes.py
@@ -4,6 +4,7 @@ from pathlib import Path
from flask import Flask, request, redirect, url_for, render_template, session
from dbrepository import DatabaseRepository
from . import web_interface
+from .tableBuilder import TableBuilder
db = DatabaseRepository()
@@ -32,6 +33,28 @@ def home():
return render_template('home.html', messages=formatted_messages, page_title="Messages")
+@web_interface.route('/integrations')
+def integrations():
+ # Define headers and rows for the messages table
+ headers = ["ID", "Message", "Date"]
+ rows = [
+ [1, "Hello World!", "2023-11-01"],
+ [2, "Another Message", "2023-11-02"],
+ # ... add more rows as needed
+ ]
+
+ # 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", "deleteMessage")
+
+ # Build the TableInstance
+ table_instance = table_builder.build()
+ return render_template('integrations.html', page_title="Integrations", table=table_instance)
+
@web_interface.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
diff --git a/WebInterface/tableBuilder.py b/WebInterface/tableBuilder.py
@@ -0,0 +1,58 @@
+class TableInstance:
+ def __init__(self):
+ self.headers = []
+ self.rows = []
+ self.sortable_columns = []
+ self.pagination_enabled = False
+ self.page_size = 10
+ self.current_page = 1
+ self.callback_column = None
+ self.row_click_url_template = ""
+
+ def add_header(self, header):
+ self.headers.append(header)
+
+ def add_row(self, row):
+ self.rows.append(row)
+
+ def enable_pagination(self, page_size=10):
+ self.pagination_enabled = True
+ self.page_size = page_size
+
+ def set_sortable_columns(self, columns):
+ self.sortable_columns = columns
+
+ def set_callback_column(self, callback):
+ self.callback_column = callback
+
+ 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()
+
+ def set_headers(self, headers):
+ for header in headers:
+ self.table_instance.add_header(header)
+
+ def add_rows(self, rows):
+ for row in rows:
+ self.table_instance.add_row(row)
+
+ def set_pagination(self, enabled=True, page_size=10):
+ if enabled:
+ self.table_instance.enable_pagination(page_size)
+
+ def set_sortable(self, sortable_columns):
+ self.table_instance.set_sortable_columns(sortable_columns)
+
+ def add_callback_column(self, name, callback):
+ self.table_instance.set_callback_column((name, callback))
+
+ def set_on_click(self, url_template):
+ self.table_instance.set_row_click_url_template(url_template)
+
+ def build(self):
+ return self.table_instance
+\ No newline at end of file
diff --git a/static/css/main.css b/static/css/main.css
@@ -47,7 +47,9 @@ h1 {
}
.content {
+ max-width: 100%;
margin-left: var(--content-margin);
+ overflow: auto;
}
@media only screen and (max-width : 992px) {
@@ -67,6 +69,13 @@ h1 {
flex-shrink: 0;
}
+.sidenav-content {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ height: 100%;
+}
+
h1.mobile {
text-align: center;
flex-grow: 1;
diff --git a/templates/home.html b/templates/home.html
@@ -1,7 +1,5 @@
{% extends 'base.html' %}
-{% block title %}Child Page Title{% endblock %}
-
{% block content %}
<br>
<table class="highlight">
diff --git a/templates/integrations.html b/templates/integrations.html
@@ -0,0 +1,5 @@
+{% extends 'base.html' %}
+
+{% block content %}
+{% include 'table.html' %}
+{% endblock %}
+\ No newline at end of file
diff --git a/templates/login.html b/templates/login.html
@@ -1,38 +1,87 @@
-<!doctype html>
-<html lang="en">
+<!DOCTYPE html>
+<html>
+
<head>
<meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
- <title>Login</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>CB | {{ page_title }}</title>
+
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/materialize.min.css') }}">
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+ <script src="{{ url_for('static', filename='js/materialize.min.js') }}"></script>
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" rel="stylesheet">
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
+ <style>
+
+ body {
+ background-color: #f4f4f4;
+ }
+
+ .container .z-depth-1 {
+ background-color: #ffffff;
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
+ }
+
+ /* Existing styles for input fields */
+ .input-field input:focus {
+ border-bottom: 1px solid #2c3e50;
+ box-shadow: 0 1px 0 0 #2c3e50;
+ }
+
+ .input-field input:focus + label {
+ color: #2c3e50;
+ }
+
+ input:-webkit-autofill,
+ input:-webkit-autofill:hover,
+ input:-webkit-autofill:focus,
+ input:-webkit-autofill:active {
+ -webkit-box-shadow: 0 0 0 30px #f4f4f4 inset !important;
+ }
+</style>
</head>
-<body>
-<div class='container' style="margin-top:10%;">
- <div class='row justify-content-center align-items-center'>
- <div class='col-md-4'>
- <div class='card'>
- <div class='card-body'>
- <form method='post'>
- <div class='form-group'>
- <label for='UserName'>Username</label>
- <input type='text' class='form-control' id='UserName' name='username' placeholder='UserName' required>
+
+<body>
+ <main>
+ <center>
+ <div class="section"></div>
+ <div class="container">
+ <div class="z-depth-1 grey lighten-4 card-panel" style="max-width:350px; padding: 40px 30px 30px 30px; border: 1px solid #EEE;">
+ <form class="col s12" method="post">
+ <h5 class="login-label">Login</h5>
+ <div class='row'>
+ <div class='input-field col s12'>
+ <input class='validate' type='text' name='username' id='username' />
+ <label for='username'>Username</label>
+ </div>
+ </div>
+ <div class='row'>
+ <div class='input-field col s12'>
+ <input class='validate' type='password' name='password' id='password' />
+ <label for='password'>Password</label>
+ </div>
+ </div>
+ <div class='row'>
+ <button type='submit' name='btn_login' class='col s12 btn btn-large waves-effect indigo'>Login</button>
</div>
- <div class='form-group'>
- <label for='Password'>Password</label>
- <input type='password' class='form-control' id='Password' name='password' placeholder='Password' required>
+ <div class='row'>
+ Server:
+ <span id="domain-label"></span>
</div>
- <button type='submit' class='btn btn-primary'>Login</button>
</form>
- <!-- If there is an error message, it will be displayed here -->
- <!-- <div class='alert alert-danger mt-3' role='alert'>Error message here</div> -->
</div>
</div>
- </div>
- </div>
-</div>
-
-<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
-
+ </center>
+ </main>
+ <script>
+ document.addEventListener('DOMContentLoaded', function() {
+ var serverDomain = window.location.hostname;
+ document.getElementById('domain-label').textContent = serverDomain;
+ });
+ </script>
</body>
+
</html>
\ No newline at end of file
diff --git a/templates/nav.html b/templates/nav.html
@@ -1,16 +1,22 @@
-<li>
- <div class="user-view">
- <i class="material-icons medium" style="color: white;">account_circle</i>
- <a href="#name"><span class="white-text name">John Doe</span></a>
- <a href="#email"><span class="white-text email">jdandturk@gmail.com</span></a>
+<div class="sidenav-content">
+ <div>
+ <li>
+ <div class="user-view">
+ <i class="material-icons medium" style="color: white;">account_circle</i>
+ <a href="#name"><span class="white-text name">John Doe</span></a>
+ <a href="#email"><span class="white-text email">jdandturk@gmail.com</span></a>
+ </div>
+ </li>
+ <li><a class="waves-effect" href="/home"><i class="material-icons">message</i>Messages</a></li>
+ <li><a class="waves-effect" href="/integrations"><i class="material-icons">settings_ethernet</i>Integrations</a></li>
+ <li><a class="waves-effect" href="#!"><i class="material-icons">group</i>Users</a></li>
+ <li>
+ <div class="divider"></div>
+ </li>
+ <li><a class="subheader">Settings</a></li>
+ <li><a class="waves-effect" href="#!"><i class="material-icons">account_box</i>Account</a></li>
+ <li><a class="waves-effect" href="#!"><i class="material-icons">admin_panel_settings</i>Admin</a></li>
</div>
-</li>
-<li><a class="waves-effect" href="#!">Messages</a></li>
-<li><a class="waves-effect" href="#!">Integrations</a></li>
-<li><a class="waves-effect" href="#!">Users</a></li>
-<li>
- <div class="divider"></div>
-</li>
-<li><a class="subheader">Settings</a></li>
-<li><a class="waves-effect" href="#!">Account</a></li>
-<li><a class="waves-effect" href="#!">Admin</a></li>
-\ No newline at end of file
+
+ <li style="margin-top: auto;"><a class="waves-effect" href="/logout"><i class="material-icons">exit_to_app</i>Logout</a></li>
+</div>
+\ No newline at end of file
diff --git a/templates/table.html b/templates/table.html
@@ -0,0 +1,49 @@
+{% if table.pagination_enabled %}
+ <ul class="pagination">
+ <!-- Add Pagination Logic Here -->
+ {% set total_pages = ((table.rows|length / table.page_size) | round(0, 'ceil')) | int %}
+ {% for i in range(1, total_pages + 1) %}
+ <li class="{% if table.current_page == i %}active{% else %}waves-effect{% endif %}">
+ <a href="?page={{ i }}">{{ i }}</a>
+ </li>
+ {% endfor %}
+ </ul>
+{% endif %}
+
+<table 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 -->
+ <a href="?sort_by={{ header }}&order=asc">↑</a>
+ <a href="?sort_by={{ header }}&order=desc">↓</a>
+ {% endif %}
+ </th>
+ {% endfor %}
+ <!-- Additional header for callback actions if any -->
+ {% if table.callback_column %}
+ <th>{{ table.callback_column }}</th>
+ {% endif %}
+ </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>
+ {% endfor %}
+ <!-- Callback action buttons if any -->
+ {% if table.callback_column %}
+ <td>
+ <button onclick="{{ table.callback_column.function(row[0]) }}">{{ table.callback_column.name }}</button>
+ </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+\ No newline at end of file