Commit 65cc5ef7 authored by Wazen Shbair's avatar Wazen Shbair

dashboard

parent 9a54e9ff
...@@ -8,7 +8,7 @@ from flask_security.utils import encrypt_password ...@@ -8,7 +8,7 @@ from flask_security.utils import encrypt_password
import flask_admin import flask_admin
from flask_admin.contrib import sqla from flask_admin.contrib import sqla
from flask_admin import helpers as admin_helpers from flask_admin import helpers as admin_helpers
from flask_admin import BaseView, expose from flask_admin import BaseView, expose, AdminIndexView
import sqlite3 import sqlite3
import json import json
from flask import request, jsonify, render_template from flask import request, jsonify, render_template
...@@ -16,6 +16,7 @@ from flask_security.forms import RegisterForm ...@@ -16,6 +16,7 @@ from flask_security.forms import RegisterForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, SelectField from wtforms import StringField, PasswordField, BooleanField, SubmitField, SelectField
from wtforms.validators import * from wtforms.validators import *
from flask_admin.contrib.sqla import ModelView from flask_admin.contrib.sqla import ModelView
from sqlalchemy import text
# Create Flask application # Create Flask application
app = Flask(__name__) app = Flask(__name__)
...@@ -30,7 +31,9 @@ roles_users = db.Table( ...@@ -30,7 +31,9 @@ roles_users = db.Table(
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')) db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
) )
#///////////////////////////////////////////////////////////////////////////////////////
# Classes
#///////////////////////////////////////////////////////////////////////////////////////
class Role(db.Model, RoleMixin): class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True) id = db.Column(db.Integer(), primary_key=True)
...@@ -40,7 +43,6 @@ class Role(db.Model, RoleMixin): ...@@ -40,7 +43,6 @@ class Role(db.Model, RoleMixin):
def __str__(self): def __str__(self):
return self.name return self.name
class User(db.Model, UserMixin): class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(255)) first_name = db.Column(db.String(255))
...@@ -57,7 +59,18 @@ class User(db.Model, UserMixin): ...@@ -57,7 +59,18 @@ class User(db.Model, UserMixin):
def __str__(self): def __str__(self):
return self.email return self.email
#/////////////////////////////////////////////////////////////////////////////////////// class Receipts(db.Model):
id = db.Column(db.Integer, primary_key=True)
receipt_number = db.Column(db.String(255))
json = db.Column(db.Text)
receipt_hash = db.Column(db.String(255), unique=True)
fidelity_card = db.Column(db.String(255))
store_name = db.Column(db.String(255))
user_id =db.Column(db.Integer)
def __str__(self):
return self.id
class ExtendedRegisterForm(RegisterForm): class ExtendedRegisterForm(RegisterForm):
first_name = StringField('First Name', [DataRequired()]) first_name = StringField('First Name', [DataRequired()])
last_name = StringField('Last Name', [DataRequired()]) last_name = StringField('Last Name', [DataRequired()])
...@@ -65,14 +78,17 @@ class ExtendedRegisterForm(RegisterForm): ...@@ -65,14 +78,17 @@ class ExtendedRegisterForm(RegisterForm):
phone_number = StringField( 'Phone number') phone_number = StringField( 'Phone number')
store_name= SelectField('Store name', choices=[ ('none', 'Select one'), ('cactus', 'Cactus'), ('auchanlu', 'Auchan Luxembourg'), ('coralu', 'Cora Luxembourg'), ('other','Other')]) store_name= SelectField('Store name', choices=[ ('none', 'Select one'), ('cactus', 'Cactus'), ('auchanlu', 'Auchan Luxembourg'), ('coralu', 'Cora Luxembourg'), ('other','Other')])
#///////////////////////////////////////////////////////////////////////////////////////
# View models
#///////////////////////////////////////////////////////////////////////////////////////
class MyHomeView(AdminIndexView):
@expose('/')
def index(self):
sql = text('select COUNT(*) from receipts')
result = db.engine.execute(sql)
receiptNumber = [row[0] for row in result]
return self.render('admin/index.html', arg1=receiptNumber[0])
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore, register_form=ExtendedRegisterForm)
# Create customized model view class
class MyModelView(sqla.ModelView): class MyModelView(sqla.ModelView):
def is_accessible(self): def is_accessible(self):
...@@ -113,13 +129,6 @@ class UserView(MyModelView): ...@@ -113,13 +129,6 @@ class UserView(MyModelView):
column_filters = column_editable_list column_filters = column_editable_list
class CustomView(BaseView):
@expose('/')
def index(self):
return self.render('admin/custom_index.html')
#///////////////////////////////////////////////////////////////////////////////////////
class ClientReceiptsView(BaseView): class ClientReceiptsView(BaseView):
@expose('/') @expose('/')
def index(self): def index(self):
...@@ -135,25 +144,20 @@ class ClientReceiptsView(BaseView): ...@@ -135,25 +144,20 @@ class ClientReceiptsView(BaseView):
return self.render('admin/all-receipts.html', dict=results) return self.render('admin/all-receipts.html', dict=results)
class Receipts(db.Model):
id = db.Column(db.Integer, primary_key=True)
receipt_number = db.Column(db.String(255))
json = db.Column(db.Text)
receipt_hash = db.Column(db.String(255), unique=True)
fidelity_card = db.Column(db.String(255))
store_name = db.Column(db.String(255))
user_id =db.Column(db.Integer)
def __str__(self):
return self.id
class ReceiptView(MyModelView): class ReceiptView(MyModelView):
column_editable_list = ['id', 'receipt_number', 'json'] column_editable_list = ['id', 'receipt_number', 'json']
column_searchable_list = column_editable_list column_searchable_list = column_editable_list
column_filters = column_editable_list column_filters = column_editable_list
class CustomView(BaseView):
@expose('/')
def index(self):
return self.render('admin/custom_index.html')
#//////////////////////////////////////////////////////////////////////////////////////////////
# Routes
#//////////////////////////////////////////////////////////////////////////////////////////////
# Flask views # Flask views
@app.route('/') @app.route('/')
def index(): def index():
...@@ -163,76 +167,23 @@ def index(): ...@@ -163,76 +167,23 @@ def index():
def home(): def home():
return render_template('index.html') return render_template('index.html')
#//////////////////////////////////////////////////////////////////////////////////////////////
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
###############################################################################################
# API Request
###############################################################################################
@app.route('/api/v1/resources/receipts/recent', methods=['GET'])
def recent_receipt():
conn = sqlite3.connect('old_db.sqlite')
conn.row_factory = dict_factory
cur = conn.cursor()
receipt = cur.execute('SELECT json FROM tickets1 ORDER BY id DESC LIMIT 1;').fetchall()
conn.close()
receiptHash = json.loads(receipt[0]['json'])['ticket_hash']
Total = json.loads(receipt[0]['json'])['Total']
items_number= len(json.loads(receipt[0]['json'])['Order_items'])
result={'hash': receiptHash, 'total':Total, 'items_number':items_number}
return jsonify(result)
# A route to return all of the available receipts .
@app.route('/api/v1/resources/receipts/all', methods=['GET'])
def api_all():
conn = sqlite3.connect('old_db.sqlite')
conn.row_factory = dict_factory
cur = conn.cursor()
all_tickets = cur.execute('SELECT ticket_number,json,hash FROM tickets1;').fetchall()
conn.close()
return jsonify(all_tickets)
#//////////////////////////////////////////////////////////////////////////////////////////////
@app.route('/api/v1/resources/receipts', methods=['GET'])
def api_id():
# Check if an hash was provided as part of the URL.
# If hash is provided, assign it to a variable.
# If no hash is provided, display an error in the browser.
if 'hash' in request.args:
hash = request.args['hash']
else:
return "Error: No hash field provided. Please specify an hash."
# Create an empty list for our results
results = []
conn = sqlite3.connect('db.sqlite')
conn.row_factory = dict_factory
cur = conn.cursor()
query='SELECT ticket_number,json,hash FROM tickets1 WHERE hash=?'
ticket = cur.execute(query,(hash,)).fetchall()
if len(ticket)==0:
return "<p>The resource could not be found.</p>", 404
return jsonify(ticket)
#//////////////////////////////////////////////////////////////////////////////////////////////
@app.route('/api/v1/resources/printer_uri', methods=['GET'])
def printer_uri():
with open('printer.json') as json_file:
data = json.load(json_file)
return data['uri']
#////////////////////////////////////////////////////////////////////////////////////////////// #//////////////////////////////////////////////////////////////////////////////////////////////
# Setup Flask-Security
#//////////////////////////////////////////////////////////////////////////////////////////////
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore, register_form=ExtendedRegisterForm)
# Create admin # Create admin
admin = flask_admin.Admin( admin = flask_admin.Admin(
app, app,
'Dashboard', 'Dashboard',
base_template='my_master.html', base_template='my_master.html',
template_mode='bootstrap3', template_mode='bootstrap3',
index_view=AdminIndexView(
name='Home',
template='admin/index.html',
url='/'
)
) )
# Add model views # Add model views
...@@ -241,6 +192,7 @@ admin.add_view(UserView(User, db.session, menu_icon_type='fa', menu_icon_value=' ...@@ -241,6 +192,7 @@ admin.add_view(UserView(User, db.session, menu_icon_type='fa', menu_icon_value='
admin.add_view(CustomView(name="Custom view", endpoint='custom', menu_icon_type='fa', menu_icon_value='fa-connectdevelop',)) admin.add_view(CustomView(name="Custom view", endpoint='custom', menu_icon_type='fa', menu_icon_value='fa-connectdevelop',))
admin.add_view(ReceiptView(Receipts, db.session, menu_icon_type='fa', menu_icon_value='fa-archive',)) admin.add_view(ReceiptView(Receipts, db.session, menu_icon_type='fa', menu_icon_value='fa-archive',))
admin.add_view(ClientReceiptsView(name="My Receipts", endpoint='my_receipts', menu_icon_type='fa', menu_icon_value='fa-archive')) admin.add_view(ClientReceiptsView(name="My Receipts", endpoint='my_receipts', menu_icon_type='fa', menu_icon_value='fa-archive'))
admin.add_view(MyHomeView(name='Home', endpoint='home'))
# define a context processor for merging flask-admin's template context into the # define a context processor for merging flask-admin's template context into the
...@@ -254,6 +206,9 @@ def security_context_processor(): ...@@ -254,6 +206,9 @@ def security_context_processor():
get_url=url_for get_url=url_for
) )
#//////////////////////////////////////////////////////////////////////////////////////////////
# Functions
#//////////////////////////////////////////////////////////////////////////////////////////////
def build_sample_db(): def build_sample_db():
""" """
Populate a small db with some example entries. Populate a small db with some example entries.
...@@ -304,17 +259,21 @@ def build_sample_db(): ...@@ -304,17 +259,21 @@ def build_sample_db():
db.session.commit() db.session.commit()
return return
if __name__ == '__main__': def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
#//////////////////////////////////////////////////////////////////////////////////////////////
# Entry point
#//////////////////////////////////////////////////////////////////////////////////////////////
if __name__ == '__main__':
# Build a sample db on the fly, if one does not exist yet. # Build a sample db on the fly, if one does not exist yet.
app_dir = os.path.realpath(os.path.dirname(__file__)) app_dir = os.path.realpath(os.path.dirname(__file__))
database_path = os.path.join(app_dir, app.config['DATABASE_FILE']) database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path): if not os.path.exists(database_path):
build_sample_db() build_sample_db()
# Start app # Start app
app.run(debug=False) app.run(debug=False)
\ No newline at end of file
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
background: transparent; background: transparent;
} }
.wrapper { .wrapper {
background-color: whitesmoke; background-color: #1a2226;
} }
.skin-green .skin-green .main-sidebar, .skin-green .skin-green .main-sidebar,
.skin-green .left-side { .skin-green .left-side {
......
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
<!-- Theme style --> <!-- Theme style -->
<link href="{{url_for('static',filename='css/AdminLTE.css')}}" rel="stylesheet"></link> <link href="{{url_for('static',filename='css/AdminLTE.css')}}" rel="stylesheet"></link>
<!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. --> <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. -->
<link href="{{url_for('static',filename='css/skins/_all-skins.css')}}" rel="stylesheet"></link> <link href="{{url_for('static',filename='css/skins/skin-green.css')}}" rel="stylesheet"></link>
<!-- iCheck --> <!-- iCheck -->
<link href="{{url_for('static',filename='plugins/iCheck/flat/blue.css')}}" rel="stylesheet"></link> <link href="{{url_for('static',filename='plugins/iCheck/flat/green.css')}}" rel="stylesheet"></link>
<!-- Morris chart --> <!-- Morris chart -->
<link href="{{url_for('static',filename='plugins/morris/morris.css')}}" rel="stylesheet"></link> <link href="{{url_for('static',filename='plugins/morris/morris.css')}}" rel="stylesheet"></link>
<!-- jvectormap --> <!-- jvectormap -->
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
{% endblock head_tail%} {% endblock head_tail%}
</head> </head>
<body class="hold-transition skin-blue sidebar-mini"> <body class="hold-transition skin-green sidebar-mini">
<header id="header"> <header id="header">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
...@@ -93,17 +93,14 @@ ...@@ -93,17 +93,14 @@
</div> </div>
<div class="collapse navbar-collapse"> <div class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li class="active"><a href="../">Home</a></li> <li class="active"><a href="/">Home</a></li>
<li class="dropdown"><a href="#">Receipts <i class="fa fa-angle-down"></i></a> <li class="dropdown"><a href="#">Receipts <i class="fa fa-angle-down"></i></a>
<ul role="menu" class="sub-menu"> <ul role="menu" class="sub-menu">
<li><a href="all-receipts">List all receipts</a></li> <li><a href="all-receipts">List all receipts</a></li>
</ul> </ul>
</li> </li>
<li class="dropdown"><a href="#">Blog <i class="fa fa-angle-down"></i></a></li> <li class="dropdown"><a href="#">Blog <i class="fa fa-angle-down"></i></a></li>
<li class="dropdown"><a href="/admin">LOGIN </a></li> <li class="dropdown"><a href="/admin"> User Space </a></li>
</ul> </ul>
</div> </div>
<div class="search"> <div class="search">
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<!-- small box --> <!-- small box -->
<div class="small-box bg-aqua"> <div class="small-box bg-aqua">
<div class="inner"> <div class="inner">
<h3>150</h3> <h3>{{arg1}}</h3>
<p>Purchases</p> <p>Purchases</p>
</div> </div>
<div class="icon"> <div class="icon">
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
<div class="inner"> <div class="inner">
<h3>120</h3> <h3>120</h3>
<p>XRP</p> <p>XRP (ECO Token)</p>
</div> </div>
<div class="icon"> <div class="icon">
<i class="fa fa-btc"></i> <i class="fa fa-btc"></i>
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
<script src="js/respond.min.js"></script> <script src="js/respond.min.js"></script>
<![endif]--> <![endif]-->
<link rel="shortcut icon" href="{{ url_for('static', filename=' ') }} images/ico/favicon.ico"> <link rel="shortcut icon" href="{{ url_for('static', filename=' ') }} images/ico/favicon.ico">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ url_for('static', filename='images/ico/apple-touch-icon-144-precomposed.png') }} "> <link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ url_for('static', filename='images/ico/apple-touch-icon-144-precomposed.png') }} ">
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="{{ url_for('static', filename='images/ico/apple-touch-icon-114-precomposed.png') }} "> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="{{ url_for('static', filename='images/ico/apple-touch-icon-114-precomposed.png') }} ">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment