- Updated `docker-compose.yml` to include `ADMIN_PASSWORD` environment variable for enhanced security. - Modified `index.js` to allow checkout requests to capture user names and improved email notifications with detailed information. - Added a new endpoint to fetch books currently on loan, providing better tracking of borrowed items. - Implemented a `list_books_on_loan` function in `libraryManager.py` to display books on loan in a formatted table. - Updated `models.js` to include an `approved` column in the `Checkout` model for tracking approval status. - Enhanced the user interface in `public/index.html` with a dark mode toggle and improved checkout request handling. - Updated styles in `public/styles.css` to support dark mode and improve overall aesthetics.
149 lines
5.3 KiB
Python
149 lines
5.3 KiB
Python
import requests
|
|
from rich.console import Console
|
|
from rich.prompt import Prompt
|
|
from rich.table import Table
|
|
from fuzzywuzzy import process
|
|
from requests.auth import HTTPBasicAuth
|
|
|
|
API_BASE_URL = "https://localhost:3000" # Replace with your actual API base URL
|
|
console = Console()
|
|
|
|
# Use environment variables or a secure method to store credentials
|
|
USERNAME = 'admin'
|
|
PASSWORD = 'library@123' # Replace with your actual password
|
|
|
|
def list_books():
|
|
response = requests.get(f"{API_BASE_URL}/api/books-with-images", verify=False)
|
|
if response.status_code == 200:
|
|
books = response.json()
|
|
table = Table(title="Books")
|
|
table.add_column("ISBN", justify="right", style="cyan", no_wrap=True)
|
|
table.add_column("Title", style="magenta")
|
|
table.add_column("Authors", style="green")
|
|
for book in books:
|
|
table.add_row(book['isbn'], book['title'], book['authors'])
|
|
console.print(table)
|
|
else:
|
|
console.print("Failed to fetch books.", style="bold red")
|
|
|
|
def add_book():
|
|
isbn = Prompt.ask("Enter ISBN")
|
|
title = Prompt.ask("Enter Title")
|
|
authors = Prompt.ask("Enter Authors")
|
|
data = {
|
|
"isbn": isbn,
|
|
"title": title,
|
|
"authors": authors
|
|
}
|
|
response = requests.post(
|
|
f"{API_BASE_URL}/store-book",
|
|
json=data,
|
|
verify=False,
|
|
auth=HTTPBasicAuth(USERNAME, PASSWORD)
|
|
)
|
|
if response.status_code == 200:
|
|
console.print("Book added successfully.", style="bold green")
|
|
else:
|
|
console.print("Failed to add book.", style="bold red")
|
|
|
|
def remove_book():
|
|
isbn = Prompt.ask("Enter ISBN of the book to remove")
|
|
response = requests.delete(
|
|
f"{API_BASE_URL}/book/{isbn}",
|
|
verify=False,
|
|
auth=HTTPBasicAuth(USERNAME, PASSWORD)
|
|
)
|
|
if response.status_code == 200:
|
|
console.print("Book removed successfully.", style="bold green")
|
|
else:
|
|
console.print("Failed to remove book.", style="bold red")
|
|
|
|
def change_book_status():
|
|
isbn = Prompt.ask("Enter ISBN of the book to change status")
|
|
status = Prompt.ask("Enter new status (e.g., Available, Checked Out)")
|
|
data = {"status": status}
|
|
response = requests.put(
|
|
f"{API_BASE_URL}/book/{isbn}",
|
|
json=data,
|
|
verify=False,
|
|
auth=HTTPBasicAuth(USERNAME, PASSWORD)
|
|
)
|
|
if response.status_code == 200:
|
|
console.print("Book status updated successfully.", style="bold green")
|
|
else:
|
|
console.print("Failed to update book status.", style="bold red")
|
|
|
|
def search_books():
|
|
query = Prompt.ask("Enter search query")
|
|
response = requests.get(f"{API_BASE_URL}/api/books-with-images", verify=False)
|
|
if response.status_code == 200:
|
|
books = response.json()
|
|
book_titles = [book['title'] for book in books]
|
|
matches = process.extract(query, book_titles, limit=5)
|
|
|
|
if matches:
|
|
table = Table(title="Search Results")
|
|
table.add_column("ISBN", justify="right", style="cyan", no_wrap=True)
|
|
table.add_column("Title", style="magenta")
|
|
table.add_column("Authors", style="green")
|
|
table.add_column("Score", justify="right", style="yellow")
|
|
|
|
for match in matches:
|
|
title, score = match
|
|
book = next(book for book in books if book['title'] == title)
|
|
table.add_row(book['isbn'], book['title'], book['authors'], str(score))
|
|
|
|
console.print(table)
|
|
else:
|
|
console.print("No matches found.", style="bold red")
|
|
else:
|
|
console.print("Failed to fetch books.", style="bold red")
|
|
|
|
def list_books_on_loan():
|
|
response = requests.get(f"{API_BASE_URL}/api/books-on-loan", verify=False)
|
|
if response.status_code == 200:
|
|
loans = response.json()
|
|
table = Table(title="Books on Loan")
|
|
table.add_column("ISBN", justify="right", style="cyan", no_wrap=True)
|
|
table.add_column("Title", style="magenta")
|
|
table.add_column("User Name", style="blue")
|
|
table.add_column("Checkout Date", style="green")
|
|
table.add_column("Return Date", style="yellow")
|
|
|
|
for loan in loans:
|
|
table.add_row(loan['isbn'], loan['title'], loan['name'], loan['checkout_date'], loan['return_date'])
|
|
|
|
console.print(table)
|
|
else:
|
|
console.print("Failed to fetch books on loan.", style="bold red")
|
|
|
|
def main():
|
|
while True:
|
|
console.print("\n[bold]Admin Console[/bold]")
|
|
console.print("1. List Books")
|
|
console.print("2. Add Book")
|
|
console.print("3. Remove Book")
|
|
console.print("4. Change Book Status")
|
|
console.print("5. Search Books")
|
|
console.print("6. List Books on Loan")
|
|
console.print("7. Exit")
|
|
choice = Prompt.ask("Choose an option", choices=["1", "2", "3", "4", "5", "6", "7"], default="7")
|
|
|
|
if choice == "1":
|
|
list_books()
|
|
elif choice == "2":
|
|
add_book()
|
|
elif choice == "3":
|
|
remove_book()
|
|
elif choice == "4":
|
|
change_book_status()
|
|
elif choice == "5":
|
|
search_books()
|
|
elif choice == "6":
|
|
list_books_on_loan()
|
|
elif choice == "7":
|
|
console.print("Exiting...", style="bold yellow")
|
|
break
|
|
|
|
if __name__ == "__main__":
|
|
main() |