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

## 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
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
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.