From 30412e47034adbf936bc4ea988808270fd0a32f3 Mon Sep 17 00:00:00 2001 From: Tyler Lightwood Date: Fri, 9 Feb 2024 11:29:56 +0000 Subject: [PATCH] Started working on new UI - Began using tabulate to give the ui a bit more depth for the terminal version, currently testing and will be modifying and finishing over the next few days - Using ctypes to give the terminal window the application title for aesthetics --- N_P_P.py | 25 +++++++++++++++-------- login.py | 3 ++- notifications.py | 51 ++++++++++++++++++++++++++++++++++++++++++++-- requirements.txt | 8 ++++++++ sudo_user_login.py | 7 ++++--- tables.py | 30 +++++++++++++-------------- view_animals.py | 30 ++++++++++++++++++--------- 7 files changed, 114 insertions(+), 40 deletions(-) diff --git a/N_P_P.py b/N_P_P.py index 16b970d..c9e5fc0 100644 --- a/N_P_P.py +++ b/N_P_P.py @@ -8,6 +8,7 @@ from login import login from client_database import client_database from pymongo import MongoClient +from tabulate import tabulate get_mongodb_uri() @@ -37,8 +38,8 @@ def logout(): # Main menu def display_menu(options): - for i, option in enumerate(options, 1): - print(f"{i}. {option}") + table_data = [[i, option] for i, option in enumerate(options, 1)] + print(tabulate(table_data, tablefmt='fancy_grid')) def handle_option(option, functions): try: @@ -52,14 +53,19 @@ def handle_option(option, functions): print(Fore.RED + "\nInvalid option. Please try again." + Style.RESET_ALL) time.sleep(2) +from tabulate import tabulate + def main_menu(): options = [Fore.GREEN + "Login" + Style.RESET_ALL, Fore.YELLOW + "Exit" + Style.RESET_ALL] functions = [login, exit] while True: clear_screen() - print(Fore.CYAN + "\nšŸ• Welcome to Nexus Pet Portal! šŸˆ\n" + Style.RESET_ALL) - display_menu(options) - choice = input("\nPlease select an option: ") + welcome_table = [[Fore.CYAN + "šŸ• Welcome to Nexus Pet Portal! šŸˆ" + Style.RESET_ALL]] + options_table = [[f"{i}. {option}"] for i, option in enumerate(options, 1)] + options_table.append(["Please select an option:"]) + print(tabulate(welcome_table, tablefmt='fancy_grid')) + print(tabulate(options_table, tablefmt='fancy_grid')) + choice = input("\n> ") user_details = handle_option(choice, functions) if user_details is not None: user_menu(user_details[0], user_details[1]) @@ -82,9 +88,12 @@ def user_menu(current_user, user_level): functions.append(logout) while True: clear_screen() - print(Fore.CYAN + "\nšŸ“– Main Menu šŸ“–\n" + Style.RESET_ALL) - display_menu(options) - choice = input("\nPlease select an option: ") + menu_table = [[Fore.CYAN + "šŸ“– Main Menu šŸ“–" + Style.RESET_ALL]] + options_table = [[f"{i}. {option}"] for i, option in enumerate(options, 1)] + options_table.append(["Please select an option:"]) + print(tabulate(menu_table, tablefmt='fancy_grid')) + print(tabulate(options_table, tablefmt='fancy_grid')) + choice = input("\n> ") # Logout option if choice == str(len(options)): log_action(current_user, "Logged out") diff --git a/login.py b/login.py index 1e8fa86..1cf3ee2 100644 --- a/login.py +++ b/login.py @@ -1,6 +1,7 @@ import getpass import time from colorama import Fore, Style +from tabulate import tabulate from common_functions import clear_screen, log_action, hash_password, verify_password, get_mongodb_uri from admin_dashboard import admin_dashboard from pymongo import MongoClient @@ -98,7 +99,7 @@ def login(): # Continuous loop for login while attempts < MAX_ATTEMPTS: # Display login prompt - print("\nšŸ‘¤ User Login šŸ‘¤") + print(tabulate([["\nšŸ‘¤ User Login šŸ‘¤"]], tablefmt='fancy_grid')) username = input("\nEnter your username: ") password = getpass.getpass("Enter your password: ") diff --git a/notifications.py b/notifications.py index 26c2348..362ebef 100644 --- a/notifications.py +++ b/notifications.py @@ -1,5 +1,52 @@ import time +from tabulate import tabulate +from colorama import Fore, Style +from common_functions import clear_screen def notifications(): - print("\nThis is the notifications feature. It is currently under construction. Please come back later.") - time.sleep(2) \ No newline at end of file + notifications = [ + {"id": 1, "text": "Notification 1", "read": False}, + {"id": 2, "text": "Notification 2", "read": False}, + {"id": 3, "text": "Notification 3", "read": False}, + ] + + while True: + clear_screen() + + print("\nNotifications:") + table = [[notif['id'], notif['text'], 'Read' if notif['read'] else 'Unread'] for notif in notifications] + print(tabulate(table, headers=['ID', 'Text', 'Status'], tablefmt='pretty')) + + print("\nOptions:") + print(Fore.CYAN + "1. Read a notification") + print(Fore.CYAN + "2. Delete a notification") + print(Fore.CYAN + "3. Clear read notifications") + print(Fore.CYAN + "4. Exit" + Style.RESET_ALL) + + option = input("\nPlease select an option: ") + + if option == '1': + clear_screen() + notif_id = int(input("\nEnter the ID of the notification you want to read: ")) + for notification in notifications: + if notification['id'] == notif_id: + notification['read'] = True + print(Fore.GREEN + f"\n{notification['text']}" + Style.RESET_ALL) + break + else: + print(Fore.RED + "Notification not found." + Style.RESET_ALL) + elif option == '2': + clear_screen() + notif_id = int(input("\nEnter the ID of the notification you want to delete: ")) + notifications = [notification for notification in notifications if notification['id'] != notif_id] + elif option == '3': + notifications = [notification for notification in notifications if not notification['read']] + elif option == '4': + break + else: + print(Fore.RED + "Invalid option. Please try again." + Style.RESET_ALL) + time.sleep(2) + clear_screen() + + time.sleep(2) + diff --git a/requirements.txt b/requirements.txt index c8159ac..d0b9011 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,13 @@ altgraph==0.17.4 annotated-types==0.6.0 +ansicon==1.89.0 anyio==4.2.0 argon2-cffi==23.1.0 argon2-cffi-bindings==21.2.0 asttokens==2.4.1 Babel==2.14.0 beautifulsoup4==4.12.2 +blessed==1.20.0 blinker==1.7.0 bottle==0.12.25 bottle-websocket==0.2.9 @@ -26,6 +28,7 @@ deep-translator==1.11.4 distro==1.9.0 dlib==19.24.2 dnspython==2.5.0 +editor==1.6.6 Eel==0.16.0 emoji==2.9.0 executing==2.0.1 @@ -54,6 +57,7 @@ ipython==8.17.2 itsdangerous==2.1.2 jedi==0.19.1 Jinja2==3.1.3 +jinxed==1.2.1 langdetect==1.0.9 lz4==4.3.3 MarkupSafe==2.1.3 @@ -88,8 +92,10 @@ pypiwin32==223 pyttsx3==2.90 pywin32==306 pywin32-ctypes==0.2.2 +readchar==4.0.5 requests==2.31.0 rsa==4.9 +runs==1.2.2 setuptools==69.0.3 six==1.16.0 sniffio==1.3.0 @@ -97,6 +103,7 @@ sounddevice==0.4.6 soupsieve==2.5 SpeechRecognition==3.10.1 stack-data==0.6.3 +tabulate==0.9.0 tkcalendar==1.6.1 tqdm==4.66.1 traitlets==5.13.0 @@ -108,5 +115,6 @@ wcwidth==0.2.9 Werkzeug==3.0.1 wheel==0.42.0 whichcraft==0.6.1 +xmod==1.8.1 zope.event==5.0 zope.interface==6.1 diff --git a/sudo_user_login.py b/sudo_user_login.py index 6d1590f..f2d641d 100644 --- a/sudo_user_login.py +++ b/sudo_user_login.py @@ -1,6 +1,7 @@ import time import sys import getpass +from tabulate import tabulate from common_functions import clear_screen, verify_password, log_action from colorama import Fore, Style @@ -19,7 +20,7 @@ def login(self): MAX_ATTEMPTS = 2 for attempts in range(MAX_ATTEMPTS): - print(Fore.LIGHTMAGENTA_EX + "\nšŸ‘¤ Sudo Login šŸ‘¤" + Style.RESET_ALL) + print(tabulate([[Fore.LIGHTMAGENTA_EX + "šŸ‘¤ Sudo Login šŸ‘¤" + Style.RESET_ALL]], tablefmt='fancy_grid')) print(enter_credentials) username, password = self.get_credentials() @@ -106,7 +107,7 @@ class SudoUserLevel1(SudoUser): def login(self): for attempts in range(self.MAX_ATTEMPTS): clear_screen() - print(Fore.LIGHTMAGENTA_EX + "\nšŸ‘¤ Sudo Login šŸ‘¤" + Style.RESET_ALL) + print(tabulate([[Fore.LIGHTMAGENTA_EX + "šŸ‘¤ Sudo Login šŸ‘¤" + Style.RESET_ALL]], tablefmt='fancy_grid')) print(enter_credentials) username, password = self.get_credentials() @@ -151,7 +152,7 @@ class SudoAdmin(SudoUser): def login(self): for attempts in range(self.MAX_ATTEMPTS): clear_screen() - print(Fore.LIGHTMAGENTA_EX + "\nšŸ‘¤ ADMIN Sudo Login šŸ‘¤" + Style.RESET_ALL) + print(tabulate([[Fore.LIGHTMAGENTA_EX + "šŸ‘¤ ADMIN Sudo Login šŸ‘¤" + Style.RESET_ALL]], tablefmt='fancy_grid')) print(enter_credentials) username, password = self.get_credentials() diff --git a/tables.py b/tables.py index b71e95f..d9e20d2 100644 --- a/tables.py +++ b/tables.py @@ -1,30 +1,28 @@ from colorama import Fore, Style from common_functions import clear_screen +from tabulate import tabulate -basic_animal_table = ("+-------------------------------------------------------------------------------------------+") animal_table_with_index = ("+---------------------------------------------------------------------------------+") # Function to print the table of animals def print_animal_table(animals): # Print table header - print("\nšŸ¾ " + Fore.CYAN + "List of Animals" + Style.RESET_ALL + " šŸ¾") - print(basic_animal_table) - print("| " + Fore.YELLOW + "Name".ljust(20) + Style.RESET_ALL + "| " + Fore.YELLOW + "Species".ljust(8) + Style.RESET_ALL + "| " + Fore.YELLOW + "Breed".ljust(25) + Style.RESET_ALL + "| " + Fore.YELLOW + "Gender".ljust(15) + Style.RESET_ALL + "| " + Fore.YELLOW + "Age".ljust(1) + Style.RESET_ALL + " | " + Fore.YELLOW + "Adopted".ljust(7) + Style.RESET_ALL + " |") - print(basic_animal_table) + print("\nšŸ¾ " + Fore.CYAN + "List of Animals" + Style.RESET_ALL + " šŸ¾\n") - # Print each animal's data row by row + # Prepare table data + table_data = [] for animal in animals: - name_column = f"| {animal['name'].ljust(20)}" - species_column = f"| {animal['species'].ljust(8)}" - breed_column = f"| {animal['breed'].ljust(25)}" - gender_column = f"| {animal['gender'].ljust(15)}" - age_column = f"| {str(animal['age']).ljust(3)}" - adopted_column = f"| {str(animal['adopted']).ljust(7)} |" - print(name_column + species_column + breed_column + gender_column + age_column + adopted_column) - - # Print table footer - print(basic_animal_table) + row = [animal['name'], animal['species'], animal['breed'], animal['gender'], animal['age'], animal['adopted']] + table_data.append(row) + + # Print table with tabulate + headers = [Fore.YELLOW + "Name", "Species", "Breed", "Gender", "Age", "Adopted" + Style.RESET_ALL] + print(tabulate(table_data, headers=headers, tablefmt='fancy_grid')) + +# presto +# pretty +# psql # Function to print the table of animals with index numbers def print_animal_table_with_index(animals): diff --git a/view_animals.py b/view_animals.py index a1e0a32..941187a 100644 --- a/view_animals.py +++ b/view_animals.py @@ -1,5 +1,7 @@ import time +import ctypes from colorama import Fore, Style +from tabulate import tabulate from common_functions import clear_screen, load_animal_data, log_action, get_mongodb_uri, sanitize_input from view_animal_profile import view_animals_full from sudo_user_login import SudoUserLevel1, SudoUser @@ -8,6 +10,11 @@ from tables import print_animal_table from pymongo import MongoClient +# Get console window +ctypes.windll.kernel32.GetConsoleWindow() +# Set console title +ctypes.windll.kernel32.SetConsoleTitleW("šŸ¾ Nexus Pet Portal šŸ¾") + # Connect to MongoDB uri = get_mongodb_uri() client = MongoClient(uri) @@ -287,9 +294,6 @@ def view_animals(): animals = load_animal_data(animals_collection) current_user = SudoUserLevel1(users_collection.database).login() - # Load animal data - print_animal_table(animals) - while True: print_options(current_user) user_input = input(select_option) @@ -310,16 +314,22 @@ def view_animals(): # Print options for the user def print_options(current_user): - print(Fore.CYAN + "\nāš™ļø Options āš™ļø" + Style.RESET_ALL) - print("\n1. " + Fore.GREEN + "Search for animal" + Style.RESET_ALL) - print("2. " + Fore.GREEN + "Sort/Filter Animals" + Style.RESET_ALL) + options = [ + ["1. ", Fore.GREEN + "šŸ” Search for animal" + Style.RESET_ALL], + ["2. ", Fore.GREEN + "šŸ”¼ Sort/Filter Animals" + Style.RESET_ALL] + ] if current_user['level'] >= 2: - print("3. " + Fore.GREEN + "View animal profile" + Style.RESET_ALL) - print("4. " + Fore.GREEN + "Modify Database" + Style.RESET_ALL) - print("5. " + Fore.YELLOW + "Exit" + Style.RESET_ALL) + options.extend([ + ["3. ", Fore.GREEN + "šŸ¾ View animal profile" + Style.RESET_ALL], + ["4. ", Fore.GREEN + "šŸ“‹ Modify Database" + Style.RESET_ALL], + ["5. ", Fore.YELLOW + "ā† Back" + Style.RESET_ALL] + ]) else: - print("3. " + Fore.YELLOW + "Exit" + Style.RESET_ALL) + options.append(["3. ", Fore.YELLOW + "Exit" + Style.RESET_ALL]) + + print(tabulate([[Fore.CYAN + "ā˜° Options ā˜°" + Style.RESET_ALL]], tablefmt='fancy_grid')) + print(tabulate(options, tablefmt='fancy_grid')) # Search the database def search_database(animals, current_user):