master e784a1866964 cached
46 files
61.1 KB
17.7k tokens
101 symbols
1 requests
Download .txt
Repository: hamzaavvan/library-management-system
Branch: master
Commit: e784a1866964
Files: 46
Total size: 61.1 KB

Directory structure:
gitextract_ihduwk7h/

├── .gitignore
├── App/
│   ├── Actor.py
│   ├── Admin.py
│   ├── Books.py
│   ├── User.py
│   └── __init__.py
├── Controllers/
│   ├── AdminManager.py
│   ├── BookManager.py
│   ├── UserManager.py
│   └── __init__.py
├── Misc/
│   └── functions.py
├── Models/
│   ├── AdminDAO.py
│   ├── BookDAO.py
│   ├── DAO.py
│   ├── DB.py
│   ├── DBDAO.py
│   ├── UserDAO.py
│   └── __init__.py
├── README.md
├── app.py
├── db/
│   └── lms.sql
├── info.md
├── requirements.txt
├── routes/
│   ├── __init__.py
│   ├── admin.py
│   ├── book.py
│   └── user.py
├── run
├── static/
│   ├── home.css
│   └── style.css
└── templates/
    ├── admin/
    │   ├── books/
    │   │   ├── add.html
    │   │   ├── book_view.html
    │   │   ├── edit.html
    │   │   └── views.html
    │   ├── home.html
    │   ├── signin.html
    │   └── users.html
    ├── book_view.html
    ├── books.html
    ├── home.html
    ├── profile.html
    ├── shared/
    │   ├── admin_layout.html
    │   └── layout.html
    ├── signin.html
    ├── signup.html
    └── welcome.html

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.fuse*
*.pyc
__*__

================================================
FILE: App/Actor.py
================================================
from functools import wraps
from flask import g, request, redirect, session

class Actor():
	sess_key = ""
	route_url = "/"

	def uid(self):
		if self.isLoggedIn():
			return session[self.sess_key]

		return "err"

	def set_session(self, session, g):
		g.user = 0

		if self.isLoggedIn():
			g.user = session[self.sess_key]

	def isLoggedIn(self):
		if self.sess_key in session and session[self.sess_key] and session[self.sess_key]>0:
			return True

		return False

	def login_required(self, f, path="signin"):
		@wraps(f)
		def decorated_function(*args, **kwargs):
			if self.sess_key not in session or session[self.sess_key] is None:
				print(path)
				return redirect(self.route_url+path)
			return f(*args, **kwargs)
		return decorated_function

	def redirect_if_login(self, f, path="/"):
		@wraps(f)
		def decorated_function(*args, **kwargs):
			if self.sess_key in session and session[self.sess_key] is not None:
			    return redirect(self.route_url+path)
			return f(*args, **kwargs)
		return decorated_function

	def signout(self):
		session[self.sess_key] = None

	def signin(self):
		pass

================================================
FILE: App/Admin.py
================================================
from App.Actor import Actor

class Admin(Actor):
	admin = {}
	
	def __init__(self, AdminDAO):
		self.sess_key = "admin"
		self.dao = AdminDAO
		self.route_url = "/admin/"

================================================
FILE: App/Books.py
================================================
class Books():
	id = 0
	name = ""
	edition = ""
	year = ""
	count = 0
	availability = False

	course = {}

	def __init__(self, BookDAO):
		self.dao = BookDAO

================================================
FILE: App/User.py
================================================
from App.Actor import Actor

class User(Actor):
	id = 0
	name = ""
	lock = False

	user = {}

	def __init__(self, UserDAO):
		self.dao = UserDAO
		self.sess_key = "user" # session key

================================================
FILE: App/__init__.py
================================================


================================================
FILE: Controllers/AdminManager.py
================================================
from App.Admin import Admin

class AdminManager():
	def __init__(self, DAO):
		self.admin = Admin(DAO.db.admin)
		self.user = DAO.db.user
		self.dao = self.admin.dao

	def signin(self, email, password):
		admin = self.dao.getByEmail(email)

		if admin is None:
			return False

		admin_pass = admin["password"] # admin pass at 
		if admin_pass != password:
			return False

		return admin
		
	def get(self, id):
		admin = self.dao.getById(id)

		return admin
		
	def getUsersList(self):
		admin = self.user.list()
		print(admin)

		return admin

	def signout(self):
		self.admin.signout()

	def user_list(self):
		return self.user.list()

================================================
FILE: Controllers/BookManager.py
================================================
from App.Books import Books

class BookManager():
	def __init__(self, DAO):
		self.misc = Books(DAO.db.book)
		self.dao = self.misc.dao

	def list(self, availability=1,user_id=None):
		if user_id!= None:
			book_list = self.dao.listByUser(user_id)
		else:
			book_list = self.dao.list(availability)

		return book_list

	def getReserverdBooksByUser(self, user_id):
		books = self.dao.getReserverdBooksByUser(user_id)

		return books

	def getBook(self, id):
		books = self.dao.getBook(id)

		return books

	def search(self, keyword, availability=1):
		books = self.dao.search_book(keyword, availability)

		return books

	def reserve(self, user_id, book_id):
		books = self.dao.reserve(user_id, book_id)

		return books

	def getUserBooks(self, user_id):
		books = self.dao.getBooksByUser(user_id)

		return books

	def getUserBooksCount(self, user_id):
		books = self.dao.getBooksCountByUser(user_id)

		return books

	def delete(self, id):
		self.dao.delete(id)

================================================
FILE: Controllers/UserManager.py
================================================
from App.User import User

class UserManager():
	def __init__(self, DAO):
		self.user = User(DAO.db.user)
		self.book = DAO.db.book
		self.dao = self.user.dao

	def list(self):
		user_list = self.dao.list()

		return user_list

	def signin(self, email, password):
		user = self.dao.getByEmail(email)

		if user is None:
			return False

		user_pass = user['password'] # user pass at 
		if user_pass != password:
			return False

		return user

	def signout(self):
		self.user.signout()
		
	def get(self, id):
		user = self.dao.getById(id)

		return user

	def signup(self, name, email, password):
		user = self.dao.getByEmail(email)

		if user is not None:
			return "already_exists"

		user_info = {"name": name, "email": email, "password": password}
		
		new_user = self.dao.add(user_info)

		return new_user
		
	def get(self, id):
		user = self.dao.getById(id)

		return user
		
	def update(self, name, email, password, bio, id):
		user_info = {"name": name, "email": email, "password": password, "bio":bio}
		
		user = self.dao.update(user_info, id)

		return user

	def getBooksList(self, id):
		return self.book.getBooksByUser(id)

	def getUsersByBook(self, book_id):
		return self.dao.getUsersByBook(book_id)

================================================
FILE: Controllers/__init__.py
================================================


================================================
FILE: Misc/functions.py
================================================
import hashlib, binascii
import timeago, datetime

salt=b'$#0x--.\'/\\98'
def hash(string):
    dk = hashlib.pbkdf2_hmac('sha256', b'password', salt, 100000)
    return binascii.hexlify(dk).decode("utf-8")

def b_hash(string):
    dk = hashlib.pbkdf2_hmac('sha256', b'password', salt, 100000)
    return binascii.hexlify(dk)
    
def ago(date):
    """
        Calculate a '3 hours ago' type string from a python datetime.
    """
    now = datetime.datetime.now() + datetime.timedelta(seconds = 60 * 3.4)

    return (timeago.format(date, now)) # will print x secs/hours/minutes ago

================================================
FILE: Models/AdminDAO.py
================================================
class AdminDAO():
	db = {}
	
	def __init__(self, DAO):
		self.db = DAO
		self.db.table = "admin"

	def getById(self, id):
		q = self.db.query("select * from @table where id='{}'".format(id))

		user = q.fetchone()

		return user

	def getByEmail(self, email):
		q = self.db.query("select * from @table where email='{}'".format(email))

		user = q.fetchone()

		return user

================================================
FILE: Models/BookDAO.py
================================================
class BookDAO():
	def __init__(self, DAO):
		self.db = DAO
		self.db.table = "books"

	def delete(self, id):
		q = self.db.query("DELETE FROM @table where id={}".format(id))
		self.db.commit()

		return q


	def reserve(self, user_id, book_id):
		if not self.available(book_id):
			return "err_out"

		q = self.db.query("INSERT INTO reserve (user_id, book_id) VALUES('{}', '{}');".format(user_id, book_id))
		
		self.db.query("UPDATE @table set count=count-1 where id={};".format(book_id))
		self.db.commit()

		return q

	def getBooksByUser(self, user_id):
		q = self.db.query("select * from @table left join reserve on reserve.book_id = @table.id where reserve.user_id={}".format(user_id))

		books = q.fetchall()

		print(books)
		return books

	def getBooksCountByUser(self, user_id):
		q = self.db.query("select count(reserve.book_id) as books_count from @table left join reserve on reserve.book_id = @table.id where reserve.user_id={}".format(user_id))

		books = q.fetchall()

		print(books)
		return books

	def getBook(self, id):
		q = self.db.query("select * from @table where id={}".format(id))

		book = q.fetchone()

		print(book)
		return book

	def available(self, id):
		book = self.getById(id)
		count = book['count']

		if count < 1:
			return False

		return True

	def getById(self, id):
		q = self.db.query("select * from @table where id='{}'".format(id))

		book = q.fetchone()

		return book

	def list(self, availability=1):
		query="select * from @table"
		# Usually when no-admin user query for book
		if availability==1: query= query+"  WHERE availability={}".format(availability)
		
		books = self.db.query(query)
		
		books = books.fetchall()


		return books

	def getReserverdBooksByUser(self, user_id):
		query="select concat(book_id,',') as user_books from reserve WHERE user_id={}".format(user_id)
		
		books = self.db.query(query)
		
		books = books.fetchone()


		return books

	def search_book(self, name, availability=1):
		query="select * from @table where name LIKE '%{}%'".format(name)

		# Usually when no-admin user query for book
		if availability==1: query= query+"  AND availability={}".format(availability)

		q = self.db.query(query)
		books = q.fetchall()
		
		return books

================================================
FILE: Models/DAO.py
================================================
from Models.DBDAO import DBDAO

class DAO():
	def __init__(self, app):
		self.db = DBDAO(app)

================================================
FILE: Models/DB.py
================================================
from flaskext.mysql import MySQL
from pymysql.cursors import DictCursor


class DB(object):
	"""Initialize mysql database """
	host = "localhost"
	user = "root"
	password = ""
	db = "lms"
	table = ""

	def __init__(self, app):
		app.config["MYSQL_DATABASE_HOST"] = self.host;
		app.config["MYSQL_DATABASE_USER"] = self.user;
		app.config["MYSQL_DATABASE_PASSWORD"] = self.password;
		app.config["MYSQL_DATABASE_DB"] = self.db;

		self.mysql = MySQL(app, cursorclass=DictCursor)

	def cur(self):
		return self.mysql.get_db().cursor()

	def query(self, q):
		h = self.cur()
	
		if (len(self.table)>0):
			q = q.replace("@table", self.table)

		h.execute(q)

		return h

	def commit(self):
		self.query("COMMIT;")

================================================
FILE: Models/DBDAO.py
================================================
from copy import copy

from Models.BookDAO import BookDAO
from Models.UserDAO import UserDAO
from Models.AdminDAO import AdminDAO

from Models.DB import DB

class DBDAO(DB):
	def __init__(self, app):
		super(DBDAO, self).__init__(app)

		self.book = BookDAO(copy(self))
		self.user = UserDAO(copy(self))
		self.admin = AdminDAO(copy(self))


================================================
FILE: Models/UserDAO.py
================================================
class UserDAO():
	def __init__(self, DAO):
		self.db = DAO
		self.db.table = "users"


	def list(self):
		users = self.db.query("select @table.id,@table.name,@table.email,@table.bio,@table.mob,@table.lock,@table.created_at,count(reserve.book_id) as books_owned from @table LEFT JOIN reserve ON reserve.user_id=@table.id GROUP BY reserve.user_id").fetchall()

		return users

	def getById(self, id):
		q = self.db.query("select * from @table where id='{}'".format(id))

		user = q.fetchone()

		return user

	def getUsersByBook(self, book_id):
		q = self.db.query("select * from @table LEFT JOIN reserve ON reserve.user_id = @table.id WHERE reserve.book_id={}".format(book_id))

		user = q.fetchall()

		return user

	def getByEmail(self, email):
		q = self.db.query("select * from @table where email='{}'".format(email))

		user = q.fetchone()

		return user

	def add(self, user):
		name = user['name']
		email = user['email']
		password = user['password']

		q = self.db.query("INSERT INTO @table (name, email, password) VALUES('{}', '{}', '{}');".format(name, email, password))
		self.db.commit()
		
		return q


	def update(self, user, _id):
		name = user['name']
		email = user['email']
		password = user['password']
		bio = user['bio']

		q = self.db.query("UPDATE @table SET name = '{}', email='{}', password='{}', bio='{}' WHERE id={}".format(name, email, password, bio, _id))
		self.db.commit()
		
		return q


================================================
FILE: Models/__init__.py
================================================


================================================
FILE: README.md
================================================
# Library Management System
A simple flask app to manage users along with mysql service

![Libray Management App - Flask](https://github.com/hamzaavvan/library-management-system/blob/master/ss/ss2.JPG?raw=true)


## Installation

To run the app flawlessly, satisfy the requirements
```bash
$ pip install -r requirements.txt
```

## Set Environment Variables
```bash
$ export FLASK_APP=app.py
$ export FLASk_ENV=development
```

## Start Server
```bash
$ flask run
```

Or run this command 
```bash
$ python -m flask run
```


================================================
FILE: app.py
================================================
from flask import Flask, g, escape, session, redirect, render_template, request, jsonify, Response
from Misc.functions import *

app = Flask(__name__)
app.secret_key = '#$ab9&^BB00_.'

# Setting DAO Class
from Models.DAO import DAO

DAO = DAO(app)

# Registering blueprints
from routes.user import user_view
from routes.book import book_view
from routes.admin import admin_view

# Registering custom functions to be used within templates
app.jinja_env.globals.update(
    ago=ago,
    str=str,
)

app.register_blueprint(user_view)
app.register_blueprint(book_view)
app.register_blueprint(admin_view)

================================================
FILE: db/lms.sql
================================================
-- phpMyAdmin SQL Dump
-- version 4.8.5
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Feb 06, 2022 at 01:24 PM
-- Server version: 10.1.38-MariaDB
-- PHP Version: 7.3.3

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `lms`
--

-- --------------------------------------------------------

--
-- Table structure for table `admin`
--

CREATE TABLE `admin` (
  `id` int(11) NOT NULL,
  `email` varchar(255) NOT NULL,
  `password` varchar(1000) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `admin`
--

INSERT INTO `admin` (`id`, `email`, `password`) VALUES
(1, 'hamza@gmail.com', '025db420560617303c2ba988d050ec62562343bc0fb0358d31d2f0bae8dbede8');

-- --------------------------------------------------------

--
-- Table structure for table `books`
--

CREATE TABLE `books` (
  `id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `desc` longtext NOT NULL,
  `author` varchar(255) NOT NULL,
  `availability` tinyint(1) NOT NULL,
  `edition` varchar(255) NOT NULL,
  `count` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `books`
--

INSERT INTO `books` (`id`, `name`, `desc`, `author`, `availability`, `edition`, `count`) VALUES
(1, '101 Ways To Be A Software Engineer', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut repudiandae assumenda distinctio quas tempore, voluptatibus accusamus dolores temporibus, recusandae eligendi similique. Optio, eius? Sint vel nemo, quisquam architecto fugit odio!', 'Mr. Johnny Test', 1, '1', 3),
(2, 'JAVA For Absolute Beginners', 'Step into the basics of java programmming along with globally famed programmer', '', 1, '1', 5);

-- --------------------------------------------------------

--
-- Table structure for table `reserve`
--

CREATE TABLE `reserve` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `book_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `reserve`
--

INSERT INTO `reserve` (`id`, `user_id`, `book_id`) VALUES
(1, 1, 1),
(2, 6, 1);

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE `users` (
  `id` int(11) NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `email` varchar(255) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `password` varchar(1000) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `bio` longtext COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `mob` varchar(255) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `lock` tinyint(1) NOT NULL,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

--
-- Dumping data for table `users`
--

INSERT INTO `users` (`id`, `name`, `email`, `password`, `bio`, `mob`, `lock`, `created_at`) VALUES
(1, 'Hamza', 'hamza@gmail.com', '025db420560617303c2ba988d050ec62562343bc0fb0358d31d2f0bae8dbede8', 'They watch you from the shelf while you sleep 👀. Are you dreaming of them, they wonder, in that wistful mood books are prone to at night when they’re bored and there’s nothing else to do but tease the cat.?', '', 0, '2021-11-09 00:00:00'),
(6, 'Naveed Ali', 'naveed@gmail.com', '025db420560617303c2ba988d050ec62562343bc0fb0358d31d2f0bae8dbede8', 'Hi :)! Long time no see ❤️', '', 0, '2021-11-18 23:07:53');

--
-- Indexes for dumped tables
--

--
-- Indexes for table `admin`
--
ALTER TABLE `admin`
  ADD PRIMARY KEY (`id`);

--
-- Indexes for table `books`
--
ALTER TABLE `books`
  ADD PRIMARY KEY (`id`);

--
-- Indexes for table `reserve`
--
ALTER TABLE `reserve`
  ADD PRIMARY KEY (`id`);

--
-- Indexes for table `users`
--
ALTER TABLE `users`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `admin`
--
ALTER TABLE `admin`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;

--
-- AUTO_INCREMENT for table `books`
--
ALTER TABLE `books`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

--
-- AUTO_INCREMENT for table `reserve`
--
ALTER TABLE `reserve`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;


================================================
FILE: info.md
================================================
http://www.utm.mx/~caff/doc/OpenUPWeb/openup/guidances/guidelines/entity_control_boundary_pattern_C4047897.html

An example of an entity for a customer service application is a Customer entity that manages all information about a customer. **A design element for this entity would include data about the customer, behavior to manage the data, behavior to validate customer information and to perform other business calculations, such as "Is this customer allowed to purchase product X?"**

================================================
FILE: requirements.txt
================================================
flask==2.3.2
flask-mysql==1.5.2
timeago==1.0.15

================================================
FILE: routes/__init__.py
================================================


================================================
FILE: routes/admin.py
================================================
from flask import Blueprint, g, escape, session, redirect, render_template, request, jsonify, Response
from app import DAO
from Misc.functions import *

from Controllers.AdminManager import AdminManager
from Controllers.BookManager import BookManager
from Controllers.UserManager import UserManager

admin_view = Blueprint('admin_routes', __name__, template_folder='../templates/admin/', url_prefix='/admin')

book_manager = BookManager(DAO)
user_manager = UserManager(DAO)
admin_manager = AdminManager(DAO)


@admin_view.route('/', methods=['GET'])
@admin_manager.admin.login_required
def home():
	admin_manager.admin.set_session(session, g)

	return render_template('admin/home.html', g=g)


@admin_view.route('/signin/', methods=['GET', 'POST'])
@admin_manager.admin.redirect_if_login
def signin():
	g.bg = 1
	
	if request.method == 'POST':
		_form = request.form
		email = str(_form["email"])
		password = str(_form["password"])

		if len(email)<1 or len(password)<1:
			return render_template('admin/signin.html', error="Email and password are required")

		d = admin_manager.signin(email, hash(password))

		if d and len(d)>0:
			session['admin'] = int(d["id"])

			return redirect("/admin")

		return render_template('admin/signin.html', error="Email or password incorrect")

	return render_template('admin/signin.html')


@admin_view.route('/signout/', methods=['GET'])
@admin_manager.admin.login_required
def signout():
	admin_manager.signout()

	return redirect("/admin/", code=302)


@admin_view.route('/users/view/', methods=['GET'])
@admin_manager.admin.login_required
def users_view():
	admin_manager.admin.set_session(session, g)

	id = int(admin_manager.admin.uid())
	admin = admin_manager.get(id)
	myusers = admin_manager.getUsersList()

	return render_template('users.html', g=g, admin=admin, users=myusers)



@admin_view.route('/books/', methods=['GET'])
@admin_manager.admin.login_required
def books():
	admin_manager.admin.set_session(session, g)

	id = int(admin_manager.admin.uid())
	admin = admin_manager.get(id)
	mybooks = book_manager.list(availability=0)

	return render_template('books/views.html', g=g, books=mybooks, admin=admin)

@admin_view.route('/books/<int:id>')
@admin_manager.admin.login_required
def view_book(id):
	admin_manager.admin.set_session(session, g)

	if id != None:
		b = book_manager.getBook(id)
		users = user_manager.getUsersByBook(id)

		print('----------------------------')
		print(users)
		
		if b and len(b) <1:
			return render_template('books/book_view.html', error="No book found!")

		return render_template("books/book_view.html", books=b, books_owners=users, g=g)


@admin_view.route('/books/add', methods=['GET', 'POST'])
@admin_manager.admin.login_required
def book_add():
	admin_manager.admin.set_session(session, g)
	
	return render_template('books/add.html', g=g)


@admin_view.route('/books/edit/<int:id>', methods=['GET', 'POST'])
@admin_manager.admin.login_required
def book_edit(id):
	admin_manager.admin.set_session(session, g)

	if id != None:
		b = book_manager.getBook(id)

		if b and len(b) <1:
			return render_template('edit.html', error="No book found!")

		return render_template("books/edit.html", book=b, g=g)
	
	return redirect('/books')

@admin_view.route('/books/delete/<int:id>', methods=['GET'])
@admin_manager.admin.login_required
def book_delete(id):
	id = int(id)

	if id is not None:
		book_manager.delete(id)
	
	return redirect('/admin/books/')


@admin_view.route('/books/search', methods=['GET'])
def search():
	admin_manager.admin.set_session(session, g)

	if "keyword" not in request.args:
		return render_template("books/view.html")

	keyword = request.args["keyword"]

	if len(keyword)<1:
		return redirect('/admin/books')

	id = int(admin_manager.admin.uid())
	admin = admin_manager.get(id)

	d=book_manager.search(keyword, 0)

	if len(d) >0:
		return render_template("books/views.html", search=True, books=d, count=len(d), keyword=escape(keyword), g=g, admin=admin)

	return render_template('books/views.html', error="No books found!", keyword=escape(keyword))



================================================
FILE: routes/book.py
================================================
from flask import Blueprint, g, escape, session, redirect, render_template, request, jsonify, Response
from app import DAO

from Controllers.UserManager import UserManager
from Controllers.BookManager import BookManager

book_view = Blueprint('book_routes', __name__, template_folder='/templates')

book_manager = BookManager(DAO)
user_manager = UserManager(DAO)

@book_view.route('/books/', defaults={'id': None})
@book_view.route('/books/<int:id>')
def home(id):
	user_manager.user.set_session(session, g)

	if id != None:
		b = book_manager.getBook(id)

		print('----------------------------')
		print(b)

		user_books={}
		if user_manager.user.isLoggedIn():
			user_books = book_manager.getReserverdBooksByUser(user_id=user_manager.user.uid())['user_books'].split(',')
		
		if b and len(b) <1:
			return render_template('book_view.html', error="No book found!")

		return render_template("book_view.html", books=b, g=g, user_books=user_books)
	else:
		b = book_manager.list()

		user_books=[]
		if user_manager.user.isLoggedIn():
			reserved_books = book_manager.getReserverdBooksByUser(user_id=user_manager.user.uid())
			
			if reserved_books is not None:
				user_books = reserved_books['user_books'].split(',')
		
		print("---------------------------------------")
		print(user_books)

		if b and len(b) <1:
			return render_template('books.html', error="No books found!")
	
		return render_template("books.html", books=b, g=g, user_books=user_books)


	return render_template("books.html", books=b, g=g)


@book_view.route('/books/add/<id>', methods=['GET'])
@user_manager.user.login_required
def add(id):
	user_id = user_manager.user.uid()
	book_manager.reserve(user_id, id)

	b = book_manager.list()
	user_manager.user.set_session(session, g)
	
	return render_template("books.html", msg="Book reserved", books=b, g=g)


@book_view.route('/books/search', methods=['GET'])
def search():
	user_manager.user.set_session(session, g)

	if "keyword" not in request.args:
		return render_template("search.html")

	keyword = request.args["keyword"]

	if len(keyword)<1:
		return redirect('/books')

	d=book_manager.search(keyword)

	if len(d) >0:
		return render_template("books.html", search=True, books=d, count=len(d), keyword=escape(keyword), g=g)

	return render_template('books.html', error="No books found!", keyword=escape(keyword))



================================================
FILE: routes/user.py
================================================
from flask import Blueprint, g, escape, session, redirect, render_template, request, jsonify, Response, flash
from app import DAO
from Misc.functions import *

from Controllers.UserManager import UserManager

user_view = Blueprint('user_routes', __name__, template_folder='/templates')

user_manager = UserManager(DAO)

@user_view.route('/', methods=['GET'])
def home():
	g.bg = 1

	user_manager.user.set_session(session, g)
	print(g.user)

	return render_template('home.html', g=g)


@user_view.route('/signin', methods=['GET', 'POST'])
@user_manager.user.redirect_if_login
def signin():
	if request.method == 'POST':
		_form = request.form
		email = str(_form["email"])
		password = str(_form["password"])

		if len(email)<1 or len(password)<1:
			return render_template('signin.html', error="Email and password are required")

		d = user_manager.signin(email, hash(password))

		if d and len(d)>0:
			session['user'] = int(d['id'])

			return redirect("/")

		return render_template('signin.html', error="Email or password incorrect")


	return render_template('signin.html')


@user_view.route('/signup', methods=['GET', 'POST'])
@user_manager.user.redirect_if_login
def signup():
	if request.method == 'POST':
		name = request.form.get('name')
		email = request.form.get('email')
		password = request.form.get('password')

		if len(name) < 1 or len(email)<1 or len(password)<1:
			return render_template('signup.html', error="All fields are required")

		new_user = user_manager.signup(name, email, hash(password))

		if new_user == "already_exists":
			return render_template('signup.html', error="User already exists with this email")


		return render_template('signup.html', msg = "You've been registered!")


	return render_template('signup.html')


@user_view.route('/signout/', methods=['GET'])
@user_manager.user.login_required
def signout():
	user_manager.signout()

	return redirect("/", code=302)

@user_view.route('/user/', methods=['GET'])
@user_manager.user.login_required
def show_user(id=None):
	user_manager.user.set_session(session, g)
	
	if id is None:
		id = int(user_manager.user.uid())

	d = user_manager.get(id)
	mybooks = user_manager.getBooksList(id)

	return render_template("profile.html", user=d, books=mybooks, g=g)

@user_view.route('/user', methods=['POST'])
@user_manager.user.login_required
def update():
	user_manager.user.set_session(session, g)
	
	_form = request.form
	name = str(_form["name"])
	email = str(_form["email"])
	password = str(_form["password"])
	bio = str(_form["bio"])

	user_manager.update(name, email, hash(password), bio, user_manager.user.uid())

	flash('Your info has been updated!')
	return redirect("/user/")

================================================
FILE: run
================================================
#!/bin/bash

export FLASK_APP=app.py
export FLASK_ENV=development

service mysql start

flask run

================================================
FILE: static/home.css
================================================
.welcome {
	    margin: 0 auto;
}

.welcome h1 {
	font-size: 3.5em;
}

================================================
FILE: static/style.css
================================================
@import url('https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@100&family=Montserrat:wght@100;300&display=swap');/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */

/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */

html, h1,h2,h3,h3,h5,h6 {
font-family: 'Montserrat', sans-serif;
font-family: sans-serif;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4 {
    -webkit-font-smoothing: antialiased;
}

.home {
	background-image: url("/static/images/bg.jpg");
	background-repeat: no-repeat;
	background-size: cover;
	background-position: 0 9.5em;
}

.book {
	width: 18rem;
	display: inline-block;
	margin-right: 15px;
    margin-bottom: 25px !important;
}

.book .card-title {
	font-family: inherit !important;
}

#photo {
	margin: 0 auto;
    display: block;
}

.pwrapper {
	margin-top: 5em;
}

.pwrapper div {
	box-shadow: 0px 0px 0px #666;
}

.mwrapper {
	padding: 0 !important;
}

.bwrapper.card {
	border: 0 !important;
}

.profile.container {
	max-width: 1181px !important;
}

.bookdesc{
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
}

================================================
FILE: templates/admin/books/add.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Manage Books - Add{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container">
		<div class="back" style="font-size: 1.5em;position: absolute;">
			<a href="javascript:history.back()"><i class="bi bi-arrow-left"></i></a>
		</div>
		<div class="d-flex justify-content-center">
			<form action="/books/add" method="GET" class="col-md-5 ">
			<h3>Add Book</h3>
			<div class="form-group">
				<label for="title">Title</label>
				<input type="text" name="title" class="form-control" id="title" required  placeholder="Enter book title">
				<small class="form-text text-muted">Members will be able to search using title!</small>
			</div>
			<div class="form-group">
				<label for="qty">Quantity</label>
				<input type="number" name="qty" class="form-control" id="qty" required  placeholder="E.g 2">
			</div>
			<div class="form-group form-check">
				<input type="checkbox" name="avaliable" class="form-check-input" id="avaliable" required >
				<label class="form-check-label" for="avaliable">Avaliable</label>
				<small class="form-text text-muted">Book will not be shown to members if unchecked!</small>
			</div>
			
			<div class="platforms mt-3 mb-3">
				<label class="form-check-label" for="avaliable">Platforms</label>
				<div style="font-size: 2.1em;">
					<i class="bi bi-xbox" style="color: green;"></i>
					<i class="bi bi-youtube ml-2" style="color: red;"></i>
					<i class="bi bi-windows ml-2" style="color: rgb(39, 144, 185);"></i>
					<i class="bi bi-github ml-2" style=""></i>
				</div>
			</div>
			<div class="form-group">
				<label for="desc">Description</label>
				<textarea id="desc" name="desc" class="form-control"></textarea>
			</div>
			
			<div class="form-group col-12">
				<button type="submit" class="btn btn-primary">Add</button>
			</div>
			</form>
		</div>
	</div>
{% endblock %}


================================================
FILE: templates/admin/books/book_view.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Book - {{books['name']}} {% endblock %}

{% block content %}
<div class="container">
    <div style="width:100%; margin-top: 3em;margin-bottom: 2em;">
        {% if msg %}
            <div class="alert alert-success">{{msg}}</div>
        {% endif %}
        <form action="/books/search" method="GET">
          <div class="form-group">
            <div style="width: 100%">
            <div style="width: 90%; display: inline-block;">
            <input type="search" name="keyword" autofocus class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" value="{{keyword}}" placeholder="Search for books...">
            </div>
            <button type="submit" style="margin-left: 5px;" class="btn btn-primary">Search</button>
            </div>
          </div>
        </form>
    </div>

    {% if books %}
            <div class="row">
                <div class="col-md-12">
                    <div class="card  book" style="width:100%">
                        <div class="card-body">
                            <div class="row">
                            <div class="col-md-5">
                                <img src="/static/images/bg.jpg" style="height: 250px; width: auto; 
                                margin: 0 auto;
                                display: block;" class="card-img-top" alt="{{books[1]}}">
								<a href="edit/{{books['id']}}" class="btn ml-3 mt-3 btn-outline-primary"><i class="bi bi-pen-fill"></i> Edit</a>
								<a href="delete/{{books['id']}}" class="btn ml-3 mt-3 btn-outline-danger"><i class="bi bi-trash"></i> Delete</a>

                                <div class="platforms mt-3 ml-3">
                                    <h4 class="font-weight-light" style="margin-bottom: 0;">Avaliable On:</h4>
                                    <div style="font-size: 2.1em;">
                                        <i class="bi bi-xbox" style="color: green;"></i>
                                        <i class="bi bi-youtube ml-2" style="color: red;"></i>
                                        <i class="bi bi-windows ml-2" style="color: rgb(39, 144, 185);"></i>
                                        <i class="bi bi-github ml-2" style=""></i>
                                    </div>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <h2>{{books['name']}}</h2>
                                {% if books['availability'] < 1 %}
                                <span class="badge badge-warning" style="margin-bottom: 5px;">Assigned</span>
                                {% endif %}
                                <p class="card-text">{{books['desc']}}</p>
                                <p class="card-text font-weight-light"><b>Author:</b> {{books['author']}}</p>
            
                                <p class="card-text">
                                <span class="badge badge-{{ 'primary' if books['count'] > 0 else 'secondary' }}" style="margin-bottom: 5px;">
                                    {% if books['count'] > 0%}
                                        Books Left: {{books['count']}}
                                    {% else %}
                                        All gone
                                    {% endif %}
                                </span>
                                </p>

								{% if books_owners %}
								<hr class="mt-5 mb-4">
									<h4 class="font-weight-light">Book Owner(s)</h4>
									<div class="row">
									{% for user in books_owners %}
										<div class="owner col-md-3" style="padding-left: 0;">
											<img style="height: auto !important; display: block;" class="mr-auto ml-auto" src="/static/images/avatar.jpg">
											<p class="text-center">{{user['name']}}</p>
										</div>
									{% endfor %}
								</div>
								{% endif %}
                            </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

        {% else %}
            <div class="card bwrapper">
                <div class="card-body">
                    <div class="text-center mb-4" style="
                    margin-top: 21px !important;"><i class="text-center mt-4 bi-book" style="
                        font-size: 6em; "></i></div>
                    <p class="text-center mb-4">No Book Found!</p>
                </div>
            </div>
        {% endif %}	
</div>
{% endblock %}


================================================
FILE: templates/admin/books/edit.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Manage Books - Edit {{book['name']}}{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container">
		<div class="back" style="font-size: 1.5em;position: absolute;">
			<a href="javascript:history.back()"><i class="bi bi-arrow-left"></i></a>
		</div>
		<div class="d-flex justify-content-center">
			<form action="/admin/books/edit/{{book['id']}}" method="POST" class="col-md-5 ">
			<h2 style="display: inline-block;">Edit </h2> <h4 style="display: inline;"><b><i>"{{book['name']}}"</i></b></h4>
			<div style="margin-top: 2em;" class="form-group">
				<label for="title">Title</label>
				<input type="text" name="title" class="form-control" value="{{book['name']}}" id="title" required  placeholder="Enter book title">
				<small class="form-text text-muted">Members will be able to search using title!</small>
			</div>
			<div class="form-group">
				<label for="qty">Quantity</label>
				<input type="number" name="qty" class="form-control" id="qty" value="{{book['count']}}" required  placeholder="E.g 2">
			</div>
			<div class="form-group form-check">
				<input type="checkbox" name="avaliable" value="{{book['availability']}}" {{'checked' if book['availability']==1 else''}} class="form-check-input" id="avaliable">
				<label class="form-check-label" for="avaliable">Avaliable</label>
				<small class="form-text text-muted">Book will not be shown to members if unchecked!</small>
			</div>
			
			<div class="platforms mt-3 mb-3">
				<label class="form-check-label" for="avaliable">Platforms</label>
				<div style="font-size: 2.1em;">
					<i class="bi bi-xbox" style="color: green;"></i>
					<i class="bi bi-youtube ml-2" style="color: red;"></i>
					<i class="bi bi-windows ml-2" style="color: rgb(39, 144, 185);"></i>
					<i class="bi bi-github ml-2" style=""></i>
				</div>
			</div>
			<div class="form-group">
				<label for="desc">Description</label>
				<textarea id="desc" name="desc" class="form-control">{{book['desc']}}</textarea>
			</div>
			
			<div class="form-group">
				<button type="submit" class="btn btn-primary">Update</button>
			</div>
			</form>
		</div>
	</div>
{% endblock %}


================================================
FILE: templates/admin/books/views.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Manage Books - View {% endblock %}

{% block content %}
	<div class="container">	
		<div style="width:100%; margin-top: 3em;">
			{% if msg %}
				<div class="alert alert-success">{{msg}}</div>
			{% endif %}
			<form action="/admin/books/search" method="GET">
			  <div class="form-group">
			    <div style="width: 100%">
			    <div style="width: 90%; display: inline-block;">
			    <input type="search" name="keyword" autofocus class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" value="{{keyword}}" placeholder="Search for books...">
			    </div>
				<button type="submit" style="margin-left: 5px;" class="btn btn-primary">Search</button>
			    </div>
			  </div>
			</form>
		</div>

		<div>
			<h2>Manage Books</h2>
			{% if books %}
				{% for book in books %}
				<div class="card book">
				  <img src="/static/images/bg.jpg" class="card-img-top" alt="{{book[1]}}">
				  <div class="card-body">
				    <h5 class="card-title"><a href="{{book['id']}}">{{book['name']}}</a></h5>
				    {% if book["availability"] < 1 %}
				    	<span class="badge badge-warning" style="margin-bottom: 5px;">Assigned</span>
				    {% endif %}
				    <p class="card-text bookdesc">{{book["desc"]}}</p>

				    <p class="card-text">
				    <span class="badge badge-{{ 'success' if book['availability'] > 0 else 'danger' }}" style="margin-bottom: 5px;">
				    	{% if book["count"] > 0%}
				    	  Books Left: {{book['count']}}
				    	{% else %}
				    	  All gone
				    	{% endif %}
				    </span>
					</p>
					<form method="get" action="">
						<a href="edit/{{book['id']}}" class="btn btn-outline-primary">
							<i class="bi bi-pen-fill"></i> Edit
						</a>
						<a href="delete/{{book['id']}}" class="btn btn-outline-danger">
							<i class="bi bi-trash"></i> Delete
						</a>
					</form>
				  </div>
				</div>
				{% endfor %}
			{% else %}
				<p>No Books In Stash!</p>
			{% endif %}	
		</div>
	</div>
{% endblock %}


================================================
FILE: templates/admin/home.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Admin Home{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container d-flex h-75">
	    <div class="row justify-content-center align-self-center welcome">
	    	<h3>WELCOME</h3>
			<div style="width:100%">
			<form action="/admin/books/search" method="GET">
			  <div class="form-group">
			    <label for="exampleInputEmail1">Search</label>
			    <input type="search" name="keyword" autofocus class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Search for books...">
			    <small id="emailHelp" class="form-text text-muted">Available books will be shown to members.</small>
			  </div>
			  <button type="submit" class="btn btn-primary">Search</button>
			</form>
			</div>
	    </div>
	</div>
{% endblock %}


================================================
FILE: templates/admin/signin.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Admin Signin{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container d-flex h-75">
	    <div class="row justify-content-center align-self-center welcome">

			<div style="width:100%">
			<h4>ADMIN SIGNIN</h4>
			{% if error %}
				<div class="alert alert-danger">
					{{error}}
				</div>
			{% endif %}

			<form action="/admin/signin/" method="POST">
			  <div class="form-group">
			    <label for="exampleInputEmail1">Email address</label>
			    <input type="email" class="form-control" name="email" aria-describedby="emailHelp" placeholder="Enter email">
			    <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
			  </div>
			  <div class="form-group">
			    <label for="exampleInputPassword1">Password</label>
			    <input type="password" class="form-control" id="password" name="password" placeholder="Password">
			  </div>

			  <button type="submit" class="btn btn-primary">Signin</button>
			</form>
			</div>
	    </div>
	</div>
{% endblock %}


================================================
FILE: templates/admin/users.html
================================================
{%extends "/shared/admin_layout.html" %}

{% block title %}Manage Users {% endblock %}

{% block content %}
	
	<div class="container">
		<div>
			<h2>Manage Users</h2>
			<br>
			
			{% if users %}
				{% for user in users %}
					<div class="list-group">
					  <a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
					    <div class="d-flex w-100 justify-content-between">
							<div>
								<img style="height: auto !important;" src="/static/images/avatar.jpg">
							</div>
							<div class="col-md-11">
								<h5 class="mb-1">{{user['name']}}</h5>
								<form style="display: inline;" method="POST" action="../delete/{{user['id']}}"><button style="border-radius: 100%; padding: 10px;" class="btn btn-outline-danger float-right"><i class="bi bi-trash"></i></button></form>
								<small class="font-weight-light" style="display: block;font-size: 15px;width: 90%;">{{user['bio']}}</small>
								<p class="mb-1 font-weight-light">{{user['email']}}</p>
								<p class="mb-1 font-weight-light"><span class="badge badge-warning">Books Owned: {{user['books_owned']}}</span></p>
							</div>
						</div>
					    <small>{{ "Locked" if user['lock']>0 else ""}}</small>
					    <small class="float-right">{{ ago(user['created_at']) }}</small>
					  </a>
					</div>
				{% endfor %}
			{% else %}
				<p>No Users Found!</p>
			{% endif %}	
		</div>
	</div>

	<script>

	</script>
{% endblock %}


================================================
FILE: templates/book_view.html
================================================
{%extends "/shared/layout.html" %}

{% block title %}Book - {{books['name']}} {% endblock %}

{% block content %}
<div class="container">
    <div style="width:100%; margin-top: 3em;margin-bottom: 2em;">
        {% if msg %}
            <div class="alert alert-success">{{msg}}</div>
        {% endif %}
        <form action="/books/search" method="GET">
          <div class="form-group">
            <div style="width: 100%">
            <div style="width: 90%; display: inline-block;">
            <input type="search" name="keyword" autofocus class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" value="{{keyword}}" placeholder="Search for books...">
            </div>
            <button type="submit" style="margin-left: 5px;" class="btn btn-primary">Search</button>
            </div>
          </div>
        </form>
    </div>

    {% if books %}
            <div class="row">
                <div class="col-md-12">
                    <div class="card  book" style="width:100%">
                        <div class="card-body">
                            <div class="row">
                            <div class="col-md-5">
                                <img src="/static/images/bg.jpg" style="height: 250px; width: auto; 
                                margin: 0 auto;
                                display: block;" class="card-img-top" alt="{{books[1]}}">
                                <a href="/books/add/{{books['id']}}" class="btn btn-outline-warning ml-3 mt-3  {{ 'disabled' if str(books['id']) in user_books else '' }}"><i class="bi bi-journal-plus"></i> {{ 'Added' if str(books['id']) in user_books else 'Add' }}</a>

                                <div class="platforms mt-3 ml-3">
                                    <h4 class="font-weight-light" style="margin-bottom: 0;">Avaliable On:</h4>
                                    <div style="font-size: 2.1em;">
                                        <i class="bi bi-xbox" style="color: green;"></i>
                                        <i class="bi bi-youtube ml-2" style="color: red;"></i>
                                        <i class="bi bi-windows ml-2" style="color: rgb(39, 144, 185);"></i>
                                        <i class="bi bi-github ml-2" style=""></i>
                                    </div>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <h2>{{books['name']}}</h2>
                                {% if books['availability'] < 1 %}
                                <span class="badge badge-warning" style="margin-bottom: 5px;">Assigned</span>
                                {% endif %}
                                <p class="card-text">{{books['desc']}}</p>
                                <p class="card-text font-weight-light"><b>Author:</b> {{books['author']}}</p>
            
                                <p class="card-text">
                                <span class="badge badge-{{ 'primary' if books['count'] > 0 else 'secondary' }}" style="margin-bottom: 5px;">
                                    {% if books['count'] > 0%}
                                        Books Left: {{books['count']}}
                                    {% else %}
                                        All gone
                                    {% endif %}
                                </span>
                                </p>
                            </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

        {% else %}
            <div class="card bwrapper">
                <div class="card-body">
                    <div class="text-center mb-4" style="
                    margin-top: 21px !important;"><i class="text-center mt-4 bi-book" style="
                        font-size: 6em; "></i></div>
                    <p class="text-center mb-4">No Book Found!</p>
                </div>
            </div>
        {% endif %}	
</div>
{% endblock %}


================================================
FILE: templates/books.html
================================================
{%extends "/shared/layout.html" %}

{% block title %}Books{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container h-75">	
		<div style="width:100%; margin-top: 3em;">
			{% if msg %}
				<div class="alert alert-success">{{msg}}</div>
			{% endif %}
			<form action="/books/search" method="GET">
			  <div class="form-group">
			    <div style="width: 100%">
			    <div style="width: 90%; display: inline-block;">
			    <input type="search" name="keyword" autofocus class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" value="{{keyword}}" placeholder="Search for books...">
			    </div>
				<button type="submit" style="margin-left: 5px;" class="btn btn-primary">Search</button>
			    </div>
			  </div>
			</form>
		</div>

		<div style="width:100%; margin-top: 3em;">
			{% if books %}
				{% if search %}
				<h4>Search Found ({{count}})</h4>
				{% endif %}
				{% for book in books %}
				<div class="card book">
				  <img src="/static/images/bg.jpg" class="card-img-top" alt="{{book[1]}}">
				  <div class="card-body">
				    <h5 class="card-title"><a href="/books/{{book['id']}}">{{book['name']}}</a></h5>
				    {% if book['availability'] < 1 %}
				    	<span class="badge badge-warning" style="margin-bottom: 5px;">Assigned</span>
				    {% endif %}
				    <p class="card-text bookdesc">{{book['desc']}}</p>

				    <p class="card-text">
				    <span class="badge badge-{{ 'primary' if book['count'] > 0 else 'secondary' }}" style="margin-bottom: 5px;">
				    	{% if book['count'] > 0%}
				    	  Books Left: {{book['count']}}
				    	{% else %}
				    	  All gone
				    	{% endif %}
				    </span>
					</p>

				    {% if book['count'] > 0 %}
				    <a href="/books/add/{{book['id']}}" {{ 'disabled' if user_books!=None and str(book['id']) in user_books else '' }} class="btn btn-outline-warning {{ 'disabled' if str(book['id']) in user_books else '' }}"><i class="bi bi-journal-plus"></i> {{ 'Added' if str(book['id']) in user_books else 'Add' }}</a>
				    {% endif %}
				  </div>
				</div>
				{% endfor %}
			{% else %}
				<h4>No Books Found!</h4>
				<p>Please contact the librarian</p>
			{% endif %}
		</div>
	</div>
{% endblock %}

================================================
FILE: templates/home.html
================================================
{%extends "/shared/layout.html" %}

{% block title %}Home{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container d-flex h-75">
	    <div class="row justify-content-center align-self-center welcome">
	    	<h3>WELCOME</h3>
			<div style="width:100%">
			<form action="/books/search" method="GET">
			  <div class="form-group">
			    <label for="exampleInputEmail1">Search</label>
			    <input type="search" autocomplete="false" name="keyword" autofocus class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Search for books...">
			    <small id="emailHelp" class="form-text text-muted">Available books will be shown to members.</small>
			  </div>
			  <button type="submit" class="btn btn-primary">Search</button>
			</form>
			</div>
	    </div>
	</div>
{% endblock %}


================================================
FILE: templates/profile.html
================================================
{%extends "/shared/layout.html" %}

{% block title %}Profile - {{user['name']}} {% endblock %}

{% block content %}
	<div class="profile container">
		{% with messages = get_flashed_messages() %}
			{% if messages %}
				<div class="alert alert-success">
					{% for message in messages %}
						<span>{{ message }}</span>
					{% endfor %}
				</div>
			{% endif %}
		{% endwith %}
		<div class="">

            <div class="card-body">
                <div class="row d-flex justify-content-between">
                    <div class="col-md-4 pt-4 card" style="height: fit-content;">
                        <div class="card-body">
                            <div class="form-group">
                                <div class="profile-pic-div m-auto">
                                    <img src="/static/images/avatar.jpg" id="photo">
                                    <!-- <input type="file" id="file">
                                    <label for="file" id="uploadBtn" style="display: none;">Choose Photo</label> -->
									<div class="text-center mt-4">{{user['name']}}</div>
                                </div>
                            </div>
                            <hr>
                            <p class="lead">
                                {{user['bio']}}
                            </p>
							<hr/>
							<p class="lead">Joined: <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-activity" viewBox="0 0 16 16">
								<path fill-rule="evenodd" d="M6 2a.5.5 0 0 1 .47.33L10 12.036l1.53-4.208A.5.5 0 0 1 12 7.5h3.5a.5.5 0 0 1 0 1h-3.15l-1.88 5.17a.5.5 0 0 1-.94 0L6 3.964 4.47 8.171A.5.5 0 0 1 4 8.5H.5a.5.5 0 0 1 0-1h3.15l1.88-5.17A.5.5 0 0 1 6 2Z"/>
							  </svg> {{ago(user['created_at'])}}</p>
                        </div>
                    </div>
                    <div class="card col-md-7 mwrapper">

						<ul class="nav nav-tabs" id="myTab" role="tablist">
							<li class="nav-item">
							  <a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Your Books</a>
							</li>
							<li class="nav-item">
							  <a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
							</li>
						  </ul>

						  <div class="col-md-12 ">
							<div class="tab-content" id="myTabContent">
								<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
								<div class="">
									{% if books %}
										<!-- <h2 class="text-center mt-4" style="margin-bottom: 0.5em;">Your Books</h2> -->
										<div class="text-center mb-4 mt-4"><i class="text-center mt-4 bi-book" style="
											font-size: 6em; "></i></div>
										{% for book in books %}
											<div class="card book">
												<img src="/static/images/bg.jpg" class="card-img-top" alt="{{book[1]}}">
												<div class="card-body">
				    								<h5 class="card-title"><a href="/books/{{book['id']}}">{{book['name']}}</a></h5>
													{% if book['availability'] < 1 %}
														<span class="badge badge-warning" style="margin-bottom: 5px;">Assigned</span>
													{% endif %}
													<!-- <p class="card-text bookdesc">{{book['desc']}}</p> -->

													<p class="card-text">Author: <span class="font-weight-light">{{book['author']}}</span></p>
												</div>
											</div>
										{% endfor %}
										{% else %}
											<div class="card bwrapper">
												<div class="card-body">
													<h4 class="text-center mt-4">Manage Books</h4>
													<div class="text-center mb-4" style="margin-top: 21px !important;">
														<!-- <i class="text-center mt-4 bi-book" style="font-size: 6em; "></i> -->
														<svg xmlns="http://www.w3.org/2000/svg" width="6em" height="6em" fill="currentColor" class="bi bi-activity" viewBox="0 0 16 16">
														<path fill-rule="evenodd" d="M6 2a.5.5 0 0 1 .47.33L10 12.036l1.53-4.208A.5.5 0 0 1 12 7.5h3.5a.5.5 0 0 1 0 1h-3.15l-1.88 5.17a.5.5 0 0 1-.94 0L6 3.964 4.47 8.171A.5.5 0 0 1 4 8.5H.5a.5.5 0 0 1 0-1h3.15l1.88-5.17A.5.5 0 0 1 6 2Z"/>
														</svg>
													</div>
													<p class="text-center mb-4">No Books You Reserved!</p>
												</div>
											</div>
										{% endif %}	
										</div>
								</div>
								<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">
									<div class="card-body">
										<h4 class="text-center mt-4">Manage Account</h4>
										<p class="text-center mb-4">One Account For Everything</p>

										<form method="POST" action="/user">
											<div class="row">
												<div class="col-sm-12">
													<div class="form-group">
														<label for="inputFirstName" class="form-label">Your Name</label>
														<input type="text" placeholder="Enter Your Name" name="name" value="{{user['name']}}" class="form-control" id="inputFirstName">
													</div>
												</div>
											</div>
											<div class="row">
												<div class="col-sm-6">
													<div class="form-group">
													<label for="inputEmail3" class="form-label">Email</label>
													<input type="email" placeholder="Email" value="{{user['email']}}" name="email" class="form-control" id="inputEmail3">
													</div>
												</div>
												<div class="col-sm-6">
														<div class="form-group">
														<label for="password" class="form-label">Password</label>
														<input type="password" placeholder="Password" class="form-control" id="password" name="password">
													</div>
												</div>
											</div>
											<div class="form-group">
												<label for="inpBio" class="form-label">Bio</label>
												<textarea class="form-control" rows="3" name="bio" id="inpBio">{{user['bio']}}</textarea>
											</div>
											<div class="form-group">
												<button type="submit" class="btn btn-block btn-primary">Save Changes</button>
											</div>
										</form>	
									</div>
								</div>
							</div>
						  </div>

                    </div>

                </div>
            </form>
        </div>
	</div>
{% endblock %}


================================================
FILE: templates/shared/admin_layout.html
================================================
<html>
<!-- What the page is called in the tab bar  -->
<!-- We will add out stylsheet here later -->
<head>
	{%block head %}
	<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <title>{% block title %}{% endblock %}</title>
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">

	 <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
	<!-- JavaScript Bundle with Popper -->
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  
    <link rel="stylesheet" href="/static/bootstrap.min.css" />
    <link rel="stylesheet" href="/static/style.css" />
    {% endblock %}
</head>
<!-- Put some text on the page -->
<body {{"class=home" if g and g.bg==1 else ""}}>
	<div class="container-fluid">
		<div class="navbar justify-content-end">
			<ul class="nav">
			  {% if g and g.user %}
				  <li class="nav-item">
				    <a class="nav-link active" href="/admin/">Home</a>
				  </li>
				  <li class="nav-item dropdown">
				    <a class="nav-link dropdown-toggle" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" href="#">Manage Books</a>
					<div class="dropdown-menu" aria-labelledby="navbarDropdown">
					  <a class="dropdown-item" href="/admin/books"><i class="bi bi-view-list"></i> View Books</a>
					  <a class="dropdown-item" href="/admin/books/add"><i class="bi bi-journal-plus"></i> Add Book</a>
					</div>
				  </li>
				  <li class="nav-item">
				    <a class="nav-link" href="/admin/users/view/">Manage Users</a>
				  </li>
				  <li class="nav-item">
				    <a class="nav-link active" href="/admin/signout">Sign out</a>
				  </li>
				  <!-- <li class="nav-item">
				    <a class="nav-link" href="/user/">Profile</a>
				  </li> -->
			  {% endif %}
			</ul>
		</div>


		{%block content %}{% endblock %}
	</div>
</body>
</html>

================================================
FILE: templates/shared/layout.html
================================================
<html>
<!-- What the page is called in the tab bar  -->
<!-- We will add out stylsheet here later -->
<head>
	{%block head %}
	<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="/static/bootstrap.min.css" />
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
	
    <link rel="stylesheet" href="/static/style.css" />
	
	<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    {% endblock %}
</head>
<!-- Put some text on the page -->
<body {{"class=home" if g and g.bg==1 else ""}}>
	<div class="container-fluid">
		<div class="navbar justify-content-end mb-5">
			<ul class="nav">
			  <li class="nav-item">
			    <a class="nav-link active" href="/">Home</a>
			  </li>
			  <li class="nav-item">
			    <a class="nav-link" href="/books">Books</a>
			  </li>
			  {% if g and g.user %}
				  <li class="nav-item">
				    <a class="nav-link" href="/user/">Profile</a>
				  </li>
				  <li class="nav-item">
				    <a class="nav-link" href="/signout/">Signout</a>
				  </li>
			  {% else %}
				  <li class="nav-item">
				    <a class="nav-link" href="/signin">Signin</a>
				  </li>
				  <li class="nav-item">
				    <a class="nav-link" href="/signup">Signup</a>
				  </li>
			  {% endif %}
			</ul>
		</div>

		{%block content %}{% endblock %}
	</div>
</body>
</html>

================================================
FILE: templates/signin.html
================================================
{%extends "/shared/layout.html" %}

{% block title %}Signin{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container d-flex h-75">
	    <div class="row justify-content-center align-self-center welcome">
			<h4>SIGNIN</h4>

			<div style="width:90%">
			{% if error %}
				<div class="alert alert-danger">
					{{error}}
				</div>
			{% endif %}
			<form action="/signin" method="POST">
			  <div class="form-group">
			    <label for="exampleInputEmail1">Email address</label>
			    <input type="email" class="form-control" name="email" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
			    <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
			  </div>
			  <div class="form-group">
			    <label for="exampleInputPassword1">Password</label>
			    <input type="password" class="form-control" name="password" id="exampleInputPassword1" placeholder="Password">
			  </div>

			  <div class="form-group">
			  	<a href="/signup">Join us now!</a>
			  </div>

			  <button type="submit" class="btn btn-primary">Signin</button>
			  	<!-- <a style="margin-left: 10px" href="/signup">Or join us now!</a> -->
			</form>
			</div>
	    </div>
	</div>
{% endblock %}


================================================
FILE: templates/signup.html
================================================
{%extends "/shared/layout.html" %}

{% block title %}Signup{% endblock %}

{% block head %}
	{{ super() }}

    <link rel="stylesheet" href="/static/home.css" />
{% endblock %}

{% block content %}
	<div class="container d-flex h-75">
	    <div class="row justify-content-center align-self-center welcome">
			<h4>SIGNUP</h4>

			<div style="width:90%">
			{% if msg %}
				<div class="alert alert-success">
					{{msg}}
				</div>
			{% endif %}
			{% if error %}
				<div class="alert alert-danger">
					{{error}}
				</div>
			{% endif %}
			<form action="/signup" method="POST">
			  <div class="form-group">
			    <label for="name">Name</label>
			    <input type="text" class="form-control" id="name" name="name" aria-describedby="name" placeholder="Your name">
			  </div>
			  <div class="form-group">
			    <label for="email">Email address</label>
			    <input type="email" class="form-control" id="email" name="email" aria-describedby="emailHelp" placeholder="Enter email address">
			    <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
			  </div>
			  <div class="form-group">
			    <label for="password">Password</label>
			    <input type="password" class="form-control" id="password" name="password" placeholder="Password">
			  </div>

			  <button type="submit" class="btn btn-primary">Signup</button>
			  	<!-- <a style="margin-left: 10px" href="/signup">Or join us now!</a> -->
			</form>
			</div>
	    </div>
	</div>
{% endblock %}


================================================
FILE: templates/welcome.html
================================================
welcome.html
Download .txt
gitextract_ihduwk7h/

├── .gitignore
├── App/
│   ├── Actor.py
│   ├── Admin.py
│   ├── Books.py
│   ├── User.py
│   └── __init__.py
├── Controllers/
│   ├── AdminManager.py
│   ├── BookManager.py
│   ├── UserManager.py
│   └── __init__.py
├── Misc/
│   └── functions.py
├── Models/
│   ├── AdminDAO.py
│   ├── BookDAO.py
│   ├── DAO.py
│   ├── DB.py
│   ├── DBDAO.py
│   ├── UserDAO.py
│   └── __init__.py
├── README.md
├── app.py
├── db/
│   └── lms.sql
├── info.md
├── requirements.txt
├── routes/
│   ├── __init__.py
│   ├── admin.py
│   ├── book.py
│   └── user.py
├── run
├── static/
│   ├── home.css
│   └── style.css
└── templates/
    ├── admin/
    │   ├── books/
    │   │   ├── add.html
    │   │   ├── book_view.html
    │   │   ├── edit.html
    │   │   └── views.html
    │   ├── home.html
    │   ├── signin.html
    │   └── users.html
    ├── book_view.html
    ├── books.html
    ├── home.html
    ├── profile.html
    ├── shared/
    │   ├── admin_layout.html
    │   └── layout.html
    ├── signin.html
    ├── signup.html
    └── welcome.html
Download .txt
SYMBOL INDEX (101 symbols across 18 files)

FILE: App/Actor.py
  class Actor (line 4) | class Actor():
    method uid (line 8) | def uid(self):
    method set_session (line 14) | def set_session(self, session, g):
    method isLoggedIn (line 20) | def isLoggedIn(self):
    method login_required (line 26) | def login_required(self, f, path="signin"):
    method redirect_if_login (line 35) | def redirect_if_login(self, f, path="/"):
    method signout (line 43) | def signout(self):
    method signin (line 46) | def signin(self):

FILE: App/Admin.py
  class Admin (line 3) | class Admin(Actor):
    method __init__ (line 6) | def __init__(self, AdminDAO):

FILE: App/Books.py
  class Books (line 1) | class Books():
    method __init__ (line 11) | def __init__(self, BookDAO):

FILE: App/User.py
  class User (line 3) | class User(Actor):
    method __init__ (line 10) | def __init__(self, UserDAO):

FILE: Controllers/AdminManager.py
  class AdminManager (line 3) | class AdminManager():
    method __init__ (line 4) | def __init__(self, DAO):
    method signin (line 9) | def signin(self, email, password):
    method get (line 21) | def get(self, id):
    method getUsersList (line 26) | def getUsersList(self):
    method signout (line 32) | def signout(self):
    method user_list (line 35) | def user_list(self):

FILE: Controllers/BookManager.py
  class BookManager (line 3) | class BookManager():
    method __init__ (line 4) | def __init__(self, DAO):
    method list (line 8) | def list(self, availability=1,user_id=None):
    method getReserverdBooksByUser (line 16) | def getReserverdBooksByUser(self, user_id):
    method getBook (line 21) | def getBook(self, id):
    method search (line 26) | def search(self, keyword, availability=1):
    method reserve (line 31) | def reserve(self, user_id, book_id):
    method getUserBooks (line 36) | def getUserBooks(self, user_id):
    method getUserBooksCount (line 41) | def getUserBooksCount(self, user_id):
    method delete (line 46) | def delete(self, id):

FILE: Controllers/UserManager.py
  class UserManager (line 3) | class UserManager():
    method __init__ (line 4) | def __init__(self, DAO):
    method list (line 9) | def list(self):
    method signin (line 14) | def signin(self, email, password):
    method signout (line 26) | def signout(self):
    method get (line 29) | def get(self, id):
    method signup (line 34) | def signup(self, name, email, password):
    method get (line 46) | def get(self, id):
    method update (line 51) | def update(self, name, email, password, bio, id):
    method getBooksList (line 58) | def getBooksList(self, id):
    method getUsersByBook (line 61) | def getUsersByBook(self, book_id):

FILE: Misc/functions.py
  function hash (line 5) | def hash(string):
  function b_hash (line 9) | def b_hash(string):
  function ago (line 13) | def ago(date):

FILE: Models/AdminDAO.py
  class AdminDAO (line 1) | class AdminDAO():
    method __init__ (line 4) | def __init__(self, DAO):
    method getById (line 8) | def getById(self, id):
    method getByEmail (line 15) | def getByEmail(self, email):

FILE: Models/BookDAO.py
  class BookDAO (line 1) | class BookDAO():
    method __init__ (line 2) | def __init__(self, DAO):
    method delete (line 6) | def delete(self, id):
    method reserve (line 13) | def reserve(self, user_id, book_id):
    method getBooksByUser (line 24) | def getBooksByUser(self, user_id):
    method getBooksCountByUser (line 32) | def getBooksCountByUser(self, user_id):
    method getBook (line 40) | def getBook(self, id):
    method available (line 48) | def available(self, id):
    method getById (line 57) | def getById(self, id):
    method list (line 64) | def list(self, availability=1):
    method getReserverdBooksByUser (line 76) | def getReserverdBooksByUser(self, user_id):
    method search_book (line 86) | def search_book(self, name, availability=1):

FILE: Models/DAO.py
  class DAO (line 3) | class DAO():
    method __init__ (line 4) | def __init__(self, app):

FILE: Models/DB.py
  class DB (line 5) | class DB(object):
    method __init__ (line 13) | def __init__(self, app):
    method cur (line 21) | def cur(self):
    method query (line 24) | def query(self, q):
    method commit (line 34) | def commit(self):

FILE: Models/DBDAO.py
  class DBDAO (line 9) | class DBDAO(DB):
    method __init__ (line 10) | def __init__(self, app):

FILE: Models/UserDAO.py
  class UserDAO (line 1) | class UserDAO():
    method __init__ (line 2) | def __init__(self, DAO):
    method list (line 7) | def list(self):
    method getById (line 12) | def getById(self, id):
    method getUsersByBook (line 19) | def getUsersByBook(self, book_id):
    method getByEmail (line 26) | def getByEmail(self, email):
    method add (line 33) | def add(self, user):
    method update (line 44) | def update(self, user, _id):

FILE: db/lms.sql
  type `admin` (line 31) | CREATE TABLE `admin` (
  type `books` (line 50) | CREATE TABLE `books` (
  type `reserve` (line 74) | CREATE TABLE `reserve` (
  type `users` (line 94) | CREATE TABLE `users` (

FILE: routes/admin.py
  function home (line 18) | def home():
  function signin (line 26) | def signin():
  function signout (line 51) | def signout():
  function users_view (line 59) | def users_view():
  function books (line 72) | def books():
  function view_book (line 83) | def view_book(id):
  function book_add (line 101) | def book_add():
  function book_edit (line 109) | def book_edit(id):
  function book_delete (line 124) | def book_delete(id):
  function search (line 134) | def search():

FILE: routes/book.py
  function home (line 14) | def home(id):
  function add (line 55) | def add(id):
  function search (line 66) | def search():

FILE: routes/user.py
  function home (line 12) | def home():
  function signin (line 23) | def signin():
  function signup (line 47) | def signup():
  function signout (line 70) | def signout():
  function show_user (line 77) | def show_user(id=None):
  function update (line 90) | def update():
Condensed preview — 46 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (72K chars).
[
  {
    "path": ".gitignore",
    "chars": 18,
    "preview": ".fuse*\n*.pyc\n__*__"
  },
  {
    "path": "App/Actor.py",
    "chars": 1101,
    "preview": "from functools import wraps\nfrom flask import g, request, redirect, session\n\nclass Actor():\n\tsess_key = \"\"\n\troute_url = "
  },
  {
    "path": "App/Admin.py",
    "chars": 170,
    "preview": "from App.Actor import Actor\n\nclass Admin(Actor):\n\tadmin = {}\n\t\n\tdef __init__(self, AdminDAO):\n\t\tself.sess_key = \"admin\"\n"
  },
  {
    "path": "App/Books.py",
    "chars": 157,
    "preview": "class Books():\n\tid = 0\n\tname = \"\"\n\tedition = \"\"\n\tyear = \"\"\n\tcount = 0\n\tavailability = False\n\n\tcourse = {}\n\n\tdef __init__"
  },
  {
    "path": "App/User.py",
    "chars": 183,
    "preview": "from App.Actor import Actor\n\nclass User(Actor):\n\tid = 0\n\tname = \"\"\n\tlock = False\n\n\tuser = {}\n\n\tdef __init__(self, UserDA"
  },
  {
    "path": "App/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Controllers/AdminManager.py",
    "chars": 637,
    "preview": "from App.Admin import Admin\n\nclass AdminManager():\n\tdef __init__(self, DAO):\n\t\tself.admin = Admin(DAO.db.admin)\n\t\tself.u"
  },
  {
    "path": "Controllers/BookManager.py",
    "chars": 963,
    "preview": "from App.Books import Books\n\nclass BookManager():\n\tdef __init__(self, DAO):\n\t\tself.misc = Books(DAO.db.book)\n\t\tself.dao "
  },
  {
    "path": "Controllers/UserManager.py",
    "chars": 1215,
    "preview": "from App.User import User\n\nclass UserManager():\n\tdef __init__(self, DAO):\n\t\tself.user = User(DAO.db.user)\n\t\tself.book = "
  },
  {
    "path": "Controllers/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Misc/functions.py",
    "chars": 583,
    "preview": "import hashlib, binascii\nimport timeago, datetime\n\nsalt=b'$#0x--.\\'/\\\\98'\ndef hash(string):\n    dk = hashlib.pbkdf2_hmac"
  },
  {
    "path": "Models/AdminDAO.py",
    "chars": 372,
    "preview": "class AdminDAO():\n\tdb = {}\n\t\n\tdef __init__(self, DAO):\n\t\tself.db = DAO\n\t\tself.db.table = \"admin\"\n\n\tdef getById(self, id)"
  },
  {
    "path": "Models/BookDAO.py",
    "chars": 2222,
    "preview": "class BookDAO():\n\tdef __init__(self, DAO):\n\t\tself.db = DAO\n\t\tself.db.table = \"books\"\n\n\tdef delete(self, id):\n\t\tq = self."
  },
  {
    "path": "Models/DAO.py",
    "chars": 93,
    "preview": "from Models.DBDAO import DBDAO\n\nclass DAO():\n\tdef __init__(self, app):\n\t\tself.db = DBDAO(app)"
  },
  {
    "path": "Models/DB.py",
    "chars": 710,
    "preview": "from flaskext.mysql import MySQL\nfrom pymysql.cursors import DictCursor\n\n\nclass DB(object):\n\t\"\"\"Initialize mysql databas"
  },
  {
    "path": "Models/DBDAO.py",
    "chars": 340,
    "preview": "from copy import copy\n\nfrom Models.BookDAO import BookDAO\nfrom Models.UserDAO import UserDAO\nfrom Models.AdminDAO import"
  },
  {
    "path": "Models/UserDAO.py",
    "chars": 1418,
    "preview": "class UserDAO():\n\tdef __init__(self, DAO):\n\t\tself.db = DAO\n\t\tself.db.table = \"users\"\n\n\n\tdef list(self):\n\t\tusers = self.d"
  },
  {
    "path": "Models/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "README.md",
    "chars": 524,
    "preview": "# Library Management System\nA simple flask app to manage users along with mysql service\n\n![Libray Management App - Flask"
  },
  {
    "path": "app.py",
    "chars": 599,
    "preview": "from flask import Flask, g, escape, session, redirect, render_template, request, jsonify, Response\nfrom Misc.functions i"
  },
  {
    "path": "db/lms.sql",
    "chars": 4780,
    "preview": "-- phpMyAdmin SQL Dump\n-- version 4.8.5\n-- https://www.phpmyadmin.net/\n--\n-- Host: 127.0.0.1\n-- Generation Time: Feb 06,"
  },
  {
    "path": "info.md",
    "chars": 488,
    "preview": "http://www.utm.mx/~caff/doc/OpenUPWeb/openup/guidances/guidelines/entity_control_boundary_pattern_C4047897.html\n\nAn exam"
  },
  {
    "path": "requirements.txt",
    "chars": 47,
    "preview": "flask==2.3.2\nflask-mysql==1.5.2\ntimeago==1.0.15"
  },
  {
    "path": "routes/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "routes/admin.py",
    "chars": 4064,
    "preview": "from flask import Blueprint, g, escape, session, redirect, render_template, request, jsonify, Response\nfrom app import D"
  },
  {
    "path": "routes/book.py",
    "chars": 2344,
    "preview": "from flask import Blueprint, g, escape, session, redirect, render_template, request, jsonify, Response\nfrom app import D"
  },
  {
    "path": "routes/user.py",
    "chars": 2672,
    "preview": "from flask import Blueprint, g, escape, session, redirect, render_template, request, jsonify, Response, flash\nfrom app i"
  },
  {
    "path": "run",
    "chars": 97,
    "preview": "#!/bin/bash\n\nexport FLASK_APP=app.py\nexport FLASK_ENV=development\n\nservice mysql start\n\nflask run"
  },
  {
    "path": "static/home.css",
    "chars": 69,
    "preview": ".welcome {\n\t    margin: 0 auto;\n}\n\n.welcome h1 {\n\tfont-size: 3.5em;\n}"
  },
  {
    "path": "static/style.css",
    "chars": 1303,
    "preview": "@import url('https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@100&family=Montserrat:wght@100;300&display=swap'"
  },
  {
    "path": "templates/admin/books/add.html",
    "chars": 1988,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Manage Books - Add{% endblock %}\n\n{% block head %}\n\t{{ super("
  },
  {
    "path": "templates/admin/books/book_view.html",
    "chars": 4592,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Book - {{books['name']}} {% endblock %}\n\n{% block content %}\n"
  },
  {
    "path": "templates/admin/books/edit.html",
    "chars": 2283,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Manage Books - Edit {{book['name']}}{% endblock %}\n\n{% block "
  },
  {
    "path": "templates/admin/books/views.html",
    "chars": 2022,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Manage Books - View {% endblock %}\n\n{% block content %}\n\t<div"
  },
  {
    "path": "templates/admin/home.html",
    "chars": 909,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Admin Home{% endblock %}\n\n{% block head %}\n\t{{ super() }}\n\n  "
  },
  {
    "path": "templates/admin/signin.html",
    "chars": 1181,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Admin Signin{% endblock %}\n\n{% block head %}\n\t{{ super() }}\n\n"
  },
  {
    "path": "templates/admin/users.html",
    "chars": 1445,
    "preview": "{%extends \"/shared/admin_layout.html\" %}\n\n{% block title %}Manage Users {% endblock %}\n\n{% block content %}\n\t\n\t<div clas"
  },
  {
    "path": "templates/book_view.html",
    "chars": 4111,
    "preview": "{%extends \"/shared/layout.html\" %}\n\n{% block title %}Book - {{books['name']}} {% endblock %}\n\n{% block content %}\n<div c"
  },
  {
    "path": "templates/books.html",
    "chars": 2301,
    "preview": "{%extends \"/shared/layout.html\" %}\n\n{% block title %}Books{% endblock %}\n\n{% block head %}\n\t{{ super() }}\n\n    <link rel"
  },
  {
    "path": "templates/home.html",
    "chars": 912,
    "preview": "{%extends \"/shared/layout.html\" %}\n\n{% block title %}Home{% endblock %}\n\n{% block head %}\n\t{{ super() }}\n\n    <link rel="
  },
  {
    "path": "templates/profile.html",
    "chars": 6306,
    "preview": "{%extends \"/shared/layout.html\" %}\n\n{% block title %}Profile - {{user['name']}} {% endblock %}\n\n{% block content %}\n\t<di"
  },
  {
    "path": "templates/shared/admin_layout.html",
    "chars": 2402,
    "preview": "<html>\n<!-- What the page is called in the tab bar  -->\n<!-- We will add out stylsheet here later -->\n<head>\n\t{%block he"
  },
  {
    "path": "templates/shared/layout.html",
    "chars": 2012,
    "preview": "<html>\n<!-- What the page is called in the tab bar  -->\n<!-- We will add out stylsheet here later -->\n<head>\n\t{%block he"
  },
  {
    "path": "templates/signin.html",
    "chars": 1354,
    "preview": "{%extends \"/shared/layout.html\" %}\n\n{% block title %}Signin{% endblock %}\n\n{% block head %}\n\t{{ super() }}\n\n    <link re"
  },
  {
    "path": "templates/signup.html",
    "chars": 1517,
    "preview": "{%extends \"/shared/layout.html\" %}\n\n{% block title %}Signup{% endblock %}\n\n{% block head %}\n\t{{ super() }}\n\n    <link re"
  },
  {
    "path": "templates/welcome.html",
    "chars": 12,
    "preview": "welcome.html"
  }
]

About this extraction

This page contains the full source code of the hamzaavvan/library-management-system GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 46 files (61.1 KB), approximately 17.7k tokens, and a symbol index with 101 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!