Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
Wazen Shbair
EcoReceipt
Commits
65cc5ef7
Commit
65cc5ef7
authored
Jan 30, 2020
by
Wazen Shbair
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard
parent
9a54e9ff
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
65 additions
and
110 deletions
+65
-110
dashboard/app.py
dashboard/app.py
+57
-98
dashboard/static/css/skins/skin-green.css
dashboard/static/css/skins/skin-green.css
+1
-1
dashboard/templates/admin/base.html
dashboard/templates/admin/base.html
+5
-8
dashboard/templates/admin/index.html
dashboard/templates/admin/index.html
+2
-2
dashboard/templates/index.html
dashboard/templates/index.html
+0
-1
No files found.
dashboard/app.py
View file @
65cc5ef7
...
@@ -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
dashboard/static/css/skins/skin-green.css
View file @
65cc5ef7
...
@@ -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
{
...
...
dashboard/templates/admin/base.html
View file @
65cc5ef7
...
@@ -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"
>
...
...
dashboard/templates/admin/index.html
View file @
65cc5ef7
...
@@ -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>
...
...
dashboard/templates/index.html
View file @
65cc5ef7
...
@@ -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') }} "
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment