Initial commit
This commit is contained in:
parent
51d0a0a12a
commit
b3717683de
3
.gitignore
vendored
3
.gitignore
vendored
@ -63,3 +63,6 @@ target/
|
|||||||
.*.kate-swp
|
.*.kate-swp
|
||||||
.swp.*
|
.swp.*
|
||||||
|
|
||||||
|
|
||||||
|
# ---> Migrations
|
||||||
|
migrations/*
|
||||||
|
75
LBI_PiPy/__init__.py
Normal file
75
LBI_PiPy/__init__.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import mimetypes
|
||||||
|
|
||||||
|
from flask import Flask, request, session
|
||||||
|
from flask import url_for
|
||||||
|
from flask_admin import helpers as admin_helpers
|
||||||
|
from flask_babelex import Babel
|
||||||
|
from flask_security import Security, SQLAlchemyUserDatastore
|
||||||
|
from flask_uploads import patch_request_class
|
||||||
|
|
||||||
|
from LBI_PiPy.blueprints.admin import admin
|
||||||
|
from LBI_PiPy.blueprints.api import api, api_0_0_1
|
||||||
|
from LBI_PiPy.models import db, User, Role
|
||||||
|
from LBI_PiPy.views import main_bp
|
||||||
|
|
||||||
|
# Config mimetype
|
||||||
|
mimetypes.add_type('text/css', '.css')
|
||||||
|
mimetypes.add_type('text/javascript', '.js')
|
||||||
|
|
||||||
|
server = Flask(__name__)
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
server.config.from_object('LBI_PiPy.config')
|
||||||
|
|
||||||
|
# Create database
|
||||||
|
db.init_app(server)
|
||||||
|
with server.app_context():
|
||||||
|
db.create_all(app=server)
|
||||||
|
|
||||||
|
# Setup Flask-security
|
||||||
|
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
|
||||||
|
security = Security(server, user_datastore)
|
||||||
|
|
||||||
|
patch_request_class(server, 16 * 1024 * 1024)
|
||||||
|
|
||||||
|
# Setup babel
|
||||||
|
babel = Babel(server)
|
||||||
|
|
||||||
|
|
||||||
|
@babel.localeselector
|
||||||
|
def get_locale():
|
||||||
|
if request.args.get('lang'):
|
||||||
|
session['lang'] = request.args.get('lang')
|
||||||
|
return session.get('lang', 'fr')
|
||||||
|
|
||||||
|
|
||||||
|
@security.context_processor
|
||||||
|
def security_context_processor():
|
||||||
|
return dict(
|
||||||
|
admin_base_template=admin.base_template,
|
||||||
|
admin_view=admin.index_view,
|
||||||
|
h=admin_helpers,
|
||||||
|
get_url=url_for
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@server.context_processor
|
||||||
|
def utility_functions():
|
||||||
|
def print_in_console(message):
|
||||||
|
print(str(message))
|
||||||
|
|
||||||
|
return dict(mdebug=print_in_console)
|
||||||
|
|
||||||
|
|
||||||
|
# Register admin
|
||||||
|
admin.init_app(server)
|
||||||
|
|
||||||
|
# Register api
|
||||||
|
api.init_app(server)
|
||||||
|
api_0_0_1.init_app(server)
|
||||||
|
|
||||||
|
# Register main blueprint
|
||||||
|
server.register_blueprint(main_bp)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
server.run()
|
141
LBI_PiPy/blueprints/admin/__init__.py
Normal file
141
LBI_PiPy/blueprints/admin/__init__.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import wtforms as wtf
|
||||||
|
from flask import url_for, request
|
||||||
|
from flask_admin import Admin, AdminIndexView, expose
|
||||||
|
from flask_admin.contrib import sqla
|
||||||
|
from flask_admin.menu import MenuLink
|
||||||
|
from flask_security import current_user
|
||||||
|
from werkzeug.exceptions import abort
|
||||||
|
from werkzeug.utils import redirect
|
||||||
|
|
||||||
|
from LBI_PiPy.models import db, User, Module, ModuleVersion, Role
|
||||||
|
|
||||||
|
|
||||||
|
# from server.main import security
|
||||||
|
# Pour les fichiers
|
||||||
|
# def _imagename_uuid1_gen(obj, file_data):
|
||||||
|
# _, ext = os.path.splitext(file_data.filename)
|
||||||
|
# uid = uuid.uuid1()
|
||||||
|
# return secure_filename('{}{}'.format(uid, ext))
|
||||||
|
|
||||||
|
|
||||||
|
class BooleanField(wtf.BooleanField):
|
||||||
|
"""Boolean field without form-control class"""
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
# Adding `readonly` property to `input` field
|
||||||
|
kwargs.update({'class': kwargs.get('class', '').replace("form-control", "")})
|
||||||
|
return super(BooleanField, self).__call__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurableView(sqla.ModelView):
|
||||||
|
roles = []
|
||||||
|
details_modal = True
|
||||||
|
edit_modal = True
|
||||||
|
create_modal = True
|
||||||
|
|
||||||
|
def is_accessible(self):
|
||||||
|
if not current_user.is_active or not current_user.is_authenticated:
|
||||||
|
return False
|
||||||
|
if current_user.has_role("superadmin"):
|
||||||
|
return True
|
||||||
|
for role in self.roles:
|
||||||
|
if current_user.has_role(role):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _handle_view(self, name, **kwargs):
|
||||||
|
"""
|
||||||
|
Override builtin _handle_view in order to redirect users when a view is not accessible.
|
||||||
|
"""
|
||||||
|
if not self.is_accessible():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
# permission denied
|
||||||
|
abort(403)
|
||||||
|
else:
|
||||||
|
# login
|
||||||
|
return redirect(url_for('security.login', next=request.url))
|
||||||
|
|
||||||
|
|
||||||
|
class SuperUserView(ConfigurableView):
|
||||||
|
roles = []
|
||||||
|
# Affichage de la table
|
||||||
|
column_editable_list = ['active', 'username', 'email', ]
|
||||||
|
column_searchable_list = ['active', 'username', 'email', ]
|
||||||
|
column_filters = ['active', 'username', 'email', 'roles', ]
|
||||||
|
column_exclude_list = ['password', ]
|
||||||
|
# Formulaire
|
||||||
|
form_excluded_columns = ['password', ]
|
||||||
|
form_columns = ['username', 'email', 'roles', 'active', ]
|
||||||
|
form_overrides = {
|
||||||
|
"active": BooleanField,
|
||||||
|
}
|
||||||
|
# Details
|
||||||
|
column_details_exclude_list = ['password', ]
|
||||||
|
|
||||||
|
class RolesView(ConfigurableView):
|
||||||
|
roles = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleView(ConfigurableView):
|
||||||
|
inline_models = (
|
||||||
|
(
|
||||||
|
ModuleVersion,
|
||||||
|
{
|
||||||
|
'form_label': "Versions",
|
||||||
|
'form_columns': ('id', 'version',)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Index view
|
||||||
|
class IndexView(AdminIndexView):
|
||||||
|
@expose('/')
|
||||||
|
def index(self):
|
||||||
|
return self.render('admin/index.html')
|
||||||
|
|
||||||
|
|
||||||
|
admin = Admin( # server,
|
||||||
|
index_view=IndexView(menu_icon_type='fa',
|
||||||
|
menu_icon_value='fa-home', ),
|
||||||
|
name='LBI_PiPy',
|
||||||
|
template_mode='bootstrap4-left',
|
||||||
|
category_icon_classes={
|
||||||
|
'Jeu': 'fa fa-gamepad',
|
||||||
|
'Configuration': 'fa fa-tools',
|
||||||
|
},
|
||||||
|
endpoint='administration',
|
||||||
|
disconnect_route="security.logout",
|
||||||
|
connect_route="security.login"
|
||||||
|
)
|
||||||
|
|
||||||
|
admin.add_view(SuperUserView(
|
||||||
|
User,
|
||||||
|
db.session,
|
||||||
|
menu_icon_type='fa',
|
||||||
|
menu_icon_value='fa-users',
|
||||||
|
name="Administrateurs",
|
||||||
|
category="Administration",
|
||||||
|
endpoint="admin.users"
|
||||||
|
))
|
||||||
|
|
||||||
|
admin.add_view(RolesView(
|
||||||
|
Role,
|
||||||
|
db.session,
|
||||||
|
menu_icon_type='fa',
|
||||||
|
menu_icon_value='fa-users',
|
||||||
|
name="Roles",
|
||||||
|
category="Administration",
|
||||||
|
endpoint="admin.roles"
|
||||||
|
))
|
||||||
|
|
||||||
|
admin.add_view(ModuleView(
|
||||||
|
Module,
|
||||||
|
db.session,
|
||||||
|
menu_icon_type="fa",
|
||||||
|
menu_icon_value="fa-gears",
|
||||||
|
name="Modules",
|
||||||
|
category="Modules",
|
||||||
|
endpoint="admin.modules"
|
||||||
|
))
|
28
LBI_PiPy/blueprints/api/__init__.py
Normal file
28
LBI_PiPy/blueprints/api/__init__.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from flask_restful import Api
|
||||||
|
|
||||||
|
from LBI_PiPy.blueprints.api.download import ApiIndex, ApiModuleList, ApiModuleVersions, ApiModuleGet
|
||||||
|
|
||||||
|
# Current version
|
||||||
|
api = Api(prefix="/api/c")
|
||||||
|
|
||||||
|
api.add_resource(ApiIndex, '/',
|
||||||
|
endpoint='api.download.index')
|
||||||
|
api.add_resource(ApiModuleList, "/modules/",
|
||||||
|
endpoint="api.download.modules.list")
|
||||||
|
api.add_resource(ApiModuleVersions, "/modules/<string:module>/",
|
||||||
|
endpoint="api.download.modules.versions")
|
||||||
|
api.add_resource(ApiModuleGet, "/modules/<string:module>/<string:version>/",
|
||||||
|
endpoint="api.download.modules.get")
|
||||||
|
|
||||||
|
# Version 0.0.1
|
||||||
|
|
||||||
|
api_0_0_1 = Api(prefix="/api/v/0.0.1")
|
||||||
|
|
||||||
|
api_0_0_1.add_resource(ApiIndex, '/',
|
||||||
|
endpoint='api.0_0_1.download.index')
|
||||||
|
api_0_0_1.add_resource(ApiModuleList, "/modules/",
|
||||||
|
endpoint="api.0_0_1.download.modules.list")
|
||||||
|
api_0_0_1.add_resource(ApiModuleVersions, "/modules/<string:module>/",
|
||||||
|
endpoint="api.0_0_1.download.modules.versions")
|
||||||
|
api_0_0_1.add_resource(ApiModuleGet, "/modules/<string:module>/<string:version>/",
|
||||||
|
endpoint="api.0_0_1.download.modules.get")
|
42
LBI_PiPy/blueprints/api/download/__init__.py
Normal file
42
LBI_PiPy/blueprints/api/download/__init__.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from flask import send_from_directory
|
||||||
|
from flask_restful import Resource, abort
|
||||||
|
|
||||||
|
from LBI_PiPy.models import Module
|
||||||
|
|
||||||
|
|
||||||
|
class ApiIndex(Resource):
|
||||||
|
def get(self):
|
||||||
|
return {
|
||||||
|
"api version": "0.0.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ApiModuleList(Resource):
|
||||||
|
def get(self):
|
||||||
|
modules = Module.query.filter().all()
|
||||||
|
return {module.name: [version.version for version in module.versions] for module in modules}
|
||||||
|
|
||||||
|
|
||||||
|
class ApiModuleVersions(Resource):
|
||||||
|
def get(self, module):
|
||||||
|
module = Module.query.filter_by(name=module).first_or_404()
|
||||||
|
return {"versions": [version.version for version in module.versions]}
|
||||||
|
|
||||||
|
|
||||||
|
class ApiModuleGet(Resource):
|
||||||
|
def get(self, module, version):
|
||||||
|
module = Module.query.filter_by(name=module).first_or_404()
|
||||||
|
versions = [version.version for version in module.versions]
|
||||||
|
if version not in versions:
|
||||||
|
abort(404)
|
||||||
|
print(os.getcwd())
|
||||||
|
if not os.path.exists(os.path.join("modules", module.name, version + ".zip")):
|
||||||
|
shutil.make_archive(os.path.join("modules", module.name, version), 'zip',
|
||||||
|
os.path.join("modules", module.name, version))
|
||||||
|
return send_from_directory(
|
||||||
|
os.path.join("modules", module.name, ),
|
||||||
|
version + ".zip"
|
||||||
|
)
|
43
LBI_PiPy/config.py
Normal file
43
LBI_PiPy/config.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# ======================================================================================================================
|
||||||
|
# ===================================================== general ========================================================
|
||||||
|
# ======================================================================================================================
|
||||||
|
# Secret key for decode cookies, generate new one for prod server, never share it
|
||||||
|
SECRET_KEY = "SECRET_KEY"
|
||||||
|
# Enable debug mode
|
||||||
|
DEBUG = True
|
||||||
|
# ======================================================================================================================
|
||||||
|
# =================================================== sqlalchemy =======================================================
|
||||||
|
# ======================================================================================================================
|
||||||
|
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:sfkr4m37@localhost:3307/lbi_pipy'
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
|
||||||
|
# ======================================================================================================================
|
||||||
|
# ================================================= flask-security =====================================================
|
||||||
|
# ======================================================================================================================
|
||||||
|
# Protected urls
|
||||||
|
SECURITY_URL_PREFIX = "/admin"
|
||||||
|
|
||||||
|
# Pasword config
|
||||||
|
SECURITY_PASSWORD_HASH = "pbkdf2_sha512"
|
||||||
|
# Secret salt for password, generate new one for prod server, never share it
|
||||||
|
SECURITY_PASSWORD_SALT = "ATGUOHAELKiubahiughaerGOJAEGj"
|
||||||
|
|
||||||
|
# Urls for login/logout/register
|
||||||
|
SECURITY_LOGIN_URL = "/login/"
|
||||||
|
SECURITY_LOGOUT_URL = "/logout/"
|
||||||
|
SECURITY_REGISTER_URL = "/register/"
|
||||||
|
|
||||||
|
# Urls for page just after login/logout/register
|
||||||
|
SECURITY_POST_LOGIN_VIEW = "/admin/"
|
||||||
|
SECURITY_POST_LOGOUT_VIEW = "/admin/"
|
||||||
|
SECURITY_POST_REGISTER_VIEW = "/admin/"
|
||||||
|
|
||||||
|
# Features
|
||||||
|
SECURITY_REGISTERABLE = True
|
||||||
|
# todo: How can I activate that properly?
|
||||||
|
SECURITY_SEND_REGISTER_EMAIL = False
|
||||||
|
|
||||||
|
# ======================================================================================================================
|
||||||
|
# =================================================== flask-babel ======================================================
|
||||||
|
# ======================================================================================================================
|
||||||
|
BABEL_DEFAULT_LOCALE = "fr_FR"
|
54
LBI_PiPy/models.py
Normal file
54
LBI_PiPy/models.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from flask_security import RoleMixin, UserMixin
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
roles_users = db.Table(
|
||||||
|
'roles_users',
|
||||||
|
db.Column('user_id', db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE')),
|
||||||
|
db.Column('role_id', db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Role(db.Model, RoleMixin):
|
||||||
|
__tablename__ = "role"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(80), unique=True)
|
||||||
|
description = db.Column(db.String(255))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class Module(db.Model):
|
||||||
|
__tablename__ = "module"
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
name = db.Column(db.String(400))
|
||||||
|
versions = db.relationship('ModuleVersion', backref='module', lazy=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleVersion(db.Model):
|
||||||
|
__tablename__ = "moduleversion"
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
version = db.Column(db.String(10))
|
||||||
|
module_id = db.Column(db.Integer, db.ForeignKey('module.id'), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
class User(db.Model, UserMixin):
|
||||||
|
__tablename__ = "user"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
date_created = db.Column(db.DateTime, default=datetime.datetime.utcnow)
|
||||||
|
username = db.Column(db.String(400))
|
||||||
|
email = db.Column(db.String(400), unique=True)
|
||||||
|
password = db.Column(db.String(400))
|
||||||
|
active = db.Column(db.Boolean)
|
||||||
|
roles = db.relationship('Role', secondary=roles_users,
|
||||||
|
backref=db.backref('user', lazy='dynamic'))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self.username)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.username)
|
19
LBI_PiPy/modules/panic/0.0.1/__init__.py
Normal file
19
LBI_PiPy/modules/panic/0.0.1/__init__.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from modules.base import BaseClass
|
||||||
|
|
||||||
|
|
||||||
|
class MainClass(BaseClass):
|
||||||
|
name = "Panic"
|
||||||
|
help_active = True
|
||||||
|
help = {
|
||||||
|
"description": "Dans quel état est Nikola Tesla",
|
||||||
|
"commands": {
|
||||||
|
"`{prefix}{command}`": "Donne l'état actuel de Nikola Tesla",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
command_text = "panic"
|
||||||
|
|
||||||
|
async def command(self, message, args, kwargs):
|
||||||
|
temperature = 0
|
||||||
|
with open("/sys/class/thermal/thermal_zone0/temp") as f:
|
||||||
|
temperature = int(f.read().rstrip("\n")) / 1000
|
||||||
|
await message.channel.send("Nikola est à {temperature}°C".format(temperature=temperature))
|
10
LBI_PiPy/modules/panic/0.0.1/infos.json
Normal file
10
LBI_PiPy/modules/panic/0.0.1/infos.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "panic",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"requirement": {
|
||||||
|
"base": {
|
||||||
|
"min": "0.0.1",
|
||||||
|
"max": "0.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
LBI_PiPy/modules/panic/0.0.2.zip
Normal file
BIN
LBI_PiPy/modules/panic/0.0.2.zip
Normal file
Binary file not shown.
19
LBI_PiPy/modules/panic/0.0.2/__init__.py
Normal file
19
LBI_PiPy/modules/panic/0.0.2/__init__.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from modules.base import BaseClass
|
||||||
|
|
||||||
|
|
||||||
|
class MainClass(BaseClass):
|
||||||
|
name = "Panic"
|
||||||
|
help_active = True
|
||||||
|
help = {
|
||||||
|
"description": "Dans quel état est Nikola TeslaTOTOTOTOTOTOTOTOTOTOTOTOTOTOTOTOTOTOOTOTOTOTOTOTOTOTOT",
|
||||||
|
"commands": {
|
||||||
|
"`{prefix}{command}`": "Donne l'état actuel de Nikola Tesla",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
command_text = "panic"
|
||||||
|
|
||||||
|
async def command(self, message, args, kwargs):
|
||||||
|
temperature = 0
|
||||||
|
with open("/sys/class/thermal/thermal_zone0/temp") as f:
|
||||||
|
temperature = int(f.read().rstrip("\n")) / 1000
|
||||||
|
await message.channel.send("Nikola est à {temperature}°C".format(temperature=temperature))
|
10
LBI_PiPy/modules/panic/0.0.2/infos.json
Normal file
10
LBI_PiPy/modules/panic/0.0.2/infos.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "panic",
|
||||||
|
"version": "0.0.2",
|
||||||
|
"requirement": {
|
||||||
|
"base": {
|
||||||
|
"min": "0.0.2",
|
||||||
|
"max": "0.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
LBI_PiPy/static/admin/favicon.ico
Normal file
BIN
LBI_PiPy/static/admin/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
LBI_PiPy/static/favicon.ico
Normal file
BIN
LBI_PiPy/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
49
LBI_PiPy/templates/admin/index.html
Normal file
49
LBI_PiPy/templates/admin/index.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% block body %}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Tableau de bord
|
||||||
|
<small>Panneau de contrôle</small>
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#"><i class="fa fa-dashboard"></i> Tableau de bord</a></li>
|
||||||
|
<li class="active">Panneau de contrôle</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
{# todo: Fill index page #}
|
||||||
|
</section>
|
||||||
|
<!-- /.content -->
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<section class="content" style="color: white;text-align: center;height:100%;width: 50%;
|
||||||
|
margin: 0 auto;">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>LBI - PiPy</h1>
|
||||||
|
<p class="lead">
|
||||||
|
Connection
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Pour accéder à l'interface d'administration veuillez utiliser vos identifiants.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('security.login') }}">Connection</a>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary" href="/"><i class="glyphicon glyphicon-chevron-left"></i> Retour</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock body %}
|
1
LBI_PiPy/templates/admin/master.html
Normal file
1
LBI_PiPy/templates/admin/master.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% extends admin_base_template %}
|
484
LBI_PiPy/templates/admin_/base.html
Normal file
484
LBI_PiPy/templates/admin_/base.html
Normal file
@ -0,0 +1,484 @@
|
|||||||
|
{% import 'admin/layout.html' as layout with context -%}
|
||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{% block title %}{% if admin_view.category %}{{ admin_view.category }} - {% endif %}{{ admin_view.name }} -
|
||||||
|
{{ admin_view.admin.name }}{% endblock title %}</title>
|
||||||
|
|
||||||
|
{% block head_meta %}
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="Flask-Admin dashboard login template">
|
||||||
|
<meta name="author" content="Louis Chauvet">
|
||||||
|
{% endblock head_meta %}
|
||||||
|
|
||||||
|
{% block head_css %}
|
||||||
|
<!-- Favicon.ico -->
|
||||||
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
|
<!-- Bootstrap 3.3.6 -->
|
||||||
|
<link href="{{ url_for('static',filename='css/bootstrap.min.css') }}" rel="stylesheet">
|
||||||
|
<!-- Font Awesome -->
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css"
|
||||||
|
integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ"
|
||||||
|
crossorigin="anonymous">
|
||||||
|
<!-- Ionicons -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
|
||||||
|
<!-- Theme style -->
|
||||||
|
<link href="{{ url_for('static',filename='css/AdminLTE.min.css') }}" rel="stylesheet">
|
||||||
|
<!-- 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.min.css') }}" rel="stylesheet"/>
|
||||||
|
<!-- iCheck -->
|
||||||
|
<link href="{{ url_for('static',filename='plugins/iCheck/flat/blue.css') }}" rel="stylesheet"/>
|
||||||
|
<!-- Morris chart -->
|
||||||
|
<link href="{{ url_for('static',filename='plugins/morris.js/0.5.1/morris.css') }}" rel="stylesheet"/>
|
||||||
|
<!-- jvectormap -->
|
||||||
|
<link href="{{ url_for('static',filename='plugins/jvectormap/1.2.2/jquery-jvectormap-1.2.2.css') }}"
|
||||||
|
rel="stylesheet"/>
|
||||||
|
<!-- Date Picker -->
|
||||||
|
<link href="{{ url_for('static',filename='plugins/datepicker/datepicker3.css') }}" rel="stylesheet"/>
|
||||||
|
<!-- Daterange picker -->
|
||||||
|
<link href="{{ url_for('static',filename='plugins/daterangepicker/2.1.19/daterangepicker.css') }}"
|
||||||
|
rel="stylesheet"/>
|
||||||
|
<!-- bootstrap wysihtml5 - text editor -->
|
||||||
|
<link href="{{ url_for('static',filename='plugins/bootstrap-wysihtml5/0.4.15/bootstrap3-wysihtml5.min.css') }}"
|
||||||
|
rel="stylesheet"/>
|
||||||
|
<!-- Flask-admin admin styles -->
|
||||||
|
<link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css', v='1.1.1') }}" rel="stylesheet">
|
||||||
|
{% if admin_view.extra_css %}
|
||||||
|
{% for css_url in admin_view.extra_css %}
|
||||||
|
<link href="{{ css_url }}" rel="stylesheet">
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock head_css %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{% endblock head %}
|
||||||
|
|
||||||
|
{% block head_tail %}
|
||||||
|
{% endblock head_tail %}
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="hold-transition skin-black sidebar-mini">
|
||||||
|
|
||||||
|
{% block page_body %}
|
||||||
|
|
||||||
|
<!-- TOP NAVBAR -->
|
||||||
|
<div class="wrapper">
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<header class="main-header">
|
||||||
|
<!-- Logo -->
|
||||||
|
{% block brand %}
|
||||||
|
<a href="{{ admin_view.admin.url }}" class="logo">
|
||||||
|
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||||
|
<span class="logo-mini"><img src="{{ url_for('static', filename='favicon.ico') }}"
|
||||||
|
style="height:50px;display: block;"></span>
|
||||||
|
<!-- logo for regular state and mobile devices -->
|
||||||
|
<span class="logo-lg"><img src="{{ url_for('static', filename='favicon.ico') }}"
|
||||||
|
style="height:50px;display: block;float: left;"><b>Alerte 112</b></span>
|
||||||
|
</a>
|
||||||
|
{% endblock brand %}
|
||||||
|
|
||||||
|
<!-- Header Navbar: style can be found in header.less -->
|
||||||
|
<nav class="navbar navbar-static-top">
|
||||||
|
<!-- Sidebar toggle button-->
|
||||||
|
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||||
|
<span class="fa fa-bars"></span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<!-- Notifications: style can be found in dropdown.less -->
|
||||||
|
<li class="dropdown notifications-menu">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fa fa-bell"></i>
|
||||||
|
<span class="label label-warning">{# todo: Nombre de notifications #}</span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="header">Vous avez ...{# todo: Nombre de notifications #} notifications.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<!-- inner menu: contains the actual data -->
|
||||||
|
<ul class="menu">
|
||||||
|
{# todo: Remplir les notifications
|
||||||
|
notif.address -> Addresse au click sur la notif
|
||||||
|
notif.icon -> icone au format fontawesome
|
||||||
|
notif.color -> coleur au format bootstrap 3
|
||||||
|
{% for notif in notifs %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ notif.address }}">
|
||||||
|
<i class="fa {{ notif.icon }} {{ notif.color }}"></i> {{ notif.content }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %} #}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="footer"><a href="{# Lien vers la page avec toutes les notifications #}">Tout
|
||||||
|
voir</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown user user-menu">
|
||||||
|
{# todo: Remplir les informations d'un utilisateur #}
|
||||||
|
{% block access_control %}
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<!-- The user image in the navbar-->
|
||||||
|
<i class="fa fa-user-circle" style="color: white;;"></i>
|
||||||
|
<!-- hidden-xs hides the username on small devices so only the image appears. -->
|
||||||
|
{# todo: Voir pourquoi le nom de l'utilisateur s'affiche avec la classe hidden-xs #}
|
||||||
|
<!--<span class="hidden-xs">{{ current_user.username }}</span>-->
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<!-- The user image in the menu -->
|
||||||
|
<li class="user-header">
|
||||||
|
<i class="fa fa-user-circle" style="color: white; font-size: 2.5em"></i>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{{ current_user.username }}
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="user-footer">
|
||||||
|
<div class="pull-left">
|
||||||
|
<a href="{# {{ user.profilurl }} #}" class="btn btn-default btn-flat">Profil</a>
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<a href="{{ url_for('security.logout') }}"
|
||||||
|
class="btn btn-default btn-flat">{{ _("deconnection") }}</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
</li>
|
||||||
|
<!-- Control Sidebar Toggle Button -->
|
||||||
|
<li>
|
||||||
|
<a href="#" data-toggle="control-sidebar"><i class="fa fa-cog"></i></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% block menu_links %}
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
{{ layout.menu_links() }}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<!-- / TOP NAVBAR -->
|
||||||
|
|
||||||
|
<!-- LEFT MENU -->
|
||||||
|
<aside class="main-sidebar">
|
||||||
|
<!-- sidebar: style can be found in sidebar.less -->
|
||||||
|
<section class="sidebar">
|
||||||
|
<!-- Sidebar user panel -->
|
||||||
|
<div class="user-panel">
|
||||||
|
<div class="pull-left image">
|
||||||
|
<i class="fa fa-user-circle" style="color: white; font-size: 2.5em;"></i>
|
||||||
|
</div>
|
||||||
|
<div class="pull-left info">
|
||||||
|
<p>
|
||||||
|
{{ current_user.username }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- search form -->
|
||||||
|
<form action="{# {{ url_for('admin.search') }} #}" method="get" class="sidebar-form">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" name="q" class="form-control" placeholder="Rechercher...">
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button type="submit" name="search" id="search-btn" class="btn btn-flat">
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<!-- /.search form -->
|
||||||
|
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||||
|
<ul class="sidebar-menu">
|
||||||
|
<li class="header">{{ _("NAVIGATION") }}</li>
|
||||||
|
{% block main_menu %}
|
||||||
|
{{ layout.menu() }}
|
||||||
|
{% endblock %}
|
||||||
|
{# Exemples de menus:
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-envelope"></i> <span>Mailbox</span>
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<small class="label pull-right bg-yellow">12</small>
|
||||||
|
<small class="label pull-right bg-green">16</small>
|
||||||
|
<small class="label pull-right bg-red">5</small>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-share"></i> <span>Multilevel</span>
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
<li><a href="#"><i class="fa fa-circle-o"></i> Level One</a></li>
|
||||||
|
<li>
|
||||||
|
<a href="#"><i class="fa fa-circle-o"></i> Level One
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
<li><a href="#"><i class="fa fa-circle-o"></i> Level Two</a></li>
|
||||||
|
<li>
|
||||||
|
<a href="#"><i class="fa fa-circle-o"></i> Level Two
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
<li><a href="#"><i class="fa fa-circle-o"></i> Level Three</a></li>
|
||||||
|
<li><a href="#"><i class="fa fa-circle-o"></i> Level Three</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#"><i class="fa fa-circle-o"></i> Level One</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>#}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<!-- /.sidebar -->
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Content Wrapper. Contains page content color white-->
|
||||||
|
<div class="content-wrapper">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block messages %}
|
||||||
|
{{ layout.messages() }}
|
||||||
|
{% endblock messages %}
|
||||||
|
|
||||||
|
{# store the jinja2 context for form_rules rendering logic #}
|
||||||
|
{% set render_ctx = h.resolve_ctx() %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
{% endblock body %}
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- / Content Wrapper. color white -->
|
||||||
|
<!-- Control Sidebar -->
|
||||||
|
<aside class="control-sidebar control-sidebar-dark">
|
||||||
|
<!-- Create the tabs -->
|
||||||
|
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
|
||||||
|
<li><a href="#control-sidebar-settings-tab" data-toggle="tab"><i class="fa fa-cog"></i></a></li>
|
||||||
|
</ul>
|
||||||
|
<!-- Tab panes -->
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<!-- Stats tab content -->
|
||||||
|
<div class="tab-pane" id="control-sidebar-stats-tab">Stats Tab Content</div>
|
||||||
|
<!-- /.tab-pane -->
|
||||||
|
<!-- Settings tab content -->
|
||||||
|
|
||||||
|
<div class="tab-pane" id="control-sidebar-settings-tab">
|
||||||
|
{# Menu de droite, onglet Général
|
||||||
|
<form method="post">
|
||||||
|
<h3 class="control-sidebar-heading">General Settings</h3>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-sidebar-subheading">
|
||||||
|
Report panel usage
|
||||||
|
<input type="checkbox" class="pull-right" checked>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Some information about this general settings option
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-group -->
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-sidebar-subheading">
|
||||||
|
Allow mail redirect
|
||||||
|
<input type="checkbox" class="pull-right" checked>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Other sets of options are available
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-group -->
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-sidebar-subheading">
|
||||||
|
Expose author name in posts
|
||||||
|
<input type="checkbox" class="pull-right" checked>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Allow the user to show his name in blog posts
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-group -->
|
||||||
|
|
||||||
|
<h3 class="control-sidebar-heading">Chat Settings</h3>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-sidebar-subheading">
|
||||||
|
Show me as online
|
||||||
|
<input type="checkbox" class="pull-right" checked>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-group -->
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-sidebar-subheading">
|
||||||
|
Turn off notifications
|
||||||
|
<input type="checkbox" class="pull-right">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-group -->
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-sidebar-subheading">
|
||||||
|
Delete chat history
|
||||||
|
<a href="javascript:void(0)" class="text-red pull-right"><i
|
||||||
|
class="fa fa-trash-o"></i></a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-group -->
|
||||||
|
</form>
|
||||||
|
<h3 class="control-sidebar-heading">Recent Activity</h3>
|
||||||
|
<ul class="control-sidebar-menu">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)">
|
||||||
|
<i class="menu-icon fa fa-birthday-cake bg-red"></i>
|
||||||
|
|
||||||
|
<div class="menu-info">
|
||||||
|
<h4 class="control-sidebar-subheading">Langdon's Birthday</h4>
|
||||||
|
|
||||||
|
<p>Will be 23 on April 24th</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)">
|
||||||
|
<i class="menu-icon fa fa-envelope-o bg-light-blue"></i>
|
||||||
|
|
||||||
|
<div class="menu-info">
|
||||||
|
<h4 class="control-sidebar-subheading">Nora Joined Mailing List</h4>
|
||||||
|
|
||||||
|
<p>nora@example.com</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- /.control-sidebar-menu -->
|
||||||
|
|
||||||
|
<h3 class="control-sidebar-heading">Tasks Progress</h3>
|
||||||
|
<ul class="control-sidebar-menu">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)">
|
||||||
|
<h4 class="control-sidebar-subheading">
|
||||||
|
Custom Template Design
|
||||||
|
<span class="label label-danger pull-right">70%</span>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="progress progress-xxs">
|
||||||
|
<div class="progress-bar progress-bar-danger" style="width: 70%"></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)">
|
||||||
|
<h4 class="control-sidebar-subheading">
|
||||||
|
Update Resume
|
||||||
|
<span class="label label-success pull-right">95%</span>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="progress progress-xxs">
|
||||||
|
<div class="progress-bar progress-bar-success" style="width: 95%"></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul> #}
|
||||||
|
</div>
|
||||||
|
<!-- /.tab-pane -->
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<!-- /.control-sidebar -->
|
||||||
|
<!-- Add the sidebar's background. This div must be placed
|
||||||
|
immediately after the control sidebar -->
|
||||||
|
<div class="control-sidebar-bg"></div>
|
||||||
|
|
||||||
|
<footer class="main-footer">
|
||||||
|
<strong>Copyright © 2018 <a href="https://github.com/Fomys">Louis Chauvet</a></strong> -
|
||||||
|
<strong>Admin LTE Template <a href="http://almsaeedstudio.com">Almsaeed Studio</a>.</strong> All rights
|
||||||
|
reserved.
|
||||||
|
</footer>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- ./wrapper -->
|
||||||
|
|
||||||
|
{% endblock page_body %}
|
||||||
|
|
||||||
|
{% block tail_js %}
|
||||||
|
<!-- jQuery 2.2.3 -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/jQuery/jquery-2.2.3.min.js') }}"></script>
|
||||||
|
<!-- jQuery UI 1.11.4 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jQuery/ui/1.11.4/jquery-ui.min.js') }}"></script>
|
||||||
|
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
|
||||||
|
<script>
|
||||||
|
$.widget.bridge('uibutton', $.ui.button);
|
||||||
|
</script>
|
||||||
|
<!-- Bootstrap 3.3.6 -->
|
||||||
|
<script src="{{ url_for('static',filename='js/bootstrap.min.js') }}"></script>
|
||||||
|
<script src="{{ admin_static.url(filename='vendor/select2/select2.min.js', v='3.5.2') }}"
|
||||||
|
type="text/javascript"></script>
|
||||||
|
|
||||||
|
{% if admin_view.extra_js %}
|
||||||
|
{% for js_url in admin_view.extra_js %}
|
||||||
|
<script src="{{ js_url }}" type="text/javascript"></script>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Morris.js charts -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/raphael/2.1.0/raphael.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static',filename='plugins/morris.js/0.5.1/morris.min.js') }}"></script>
|
||||||
|
<!-- Sparkline -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/jquery.sparkline/2.1.2/jquery.sparkline.min.js') }}"></script>
|
||||||
|
<!-- jvectormap -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/jvectormap/1.2.2/jquery-jvectormap-1.2.2.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static',filename='plugins/jvectormap/1.2.2/jquery-jvectormap-world-mill-en.js') }}"></script>
|
||||||
|
<!-- jQuery Knob Chart -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/knob/1.2.13/jquery.knob.js') }}"></script>
|
||||||
|
<!-- daterangepicker -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/moment.js/2.11.2/moment.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static',filename='plugins/daterangepicker/2.1.19/daterangepicker.js') }}"></script>
|
||||||
|
<!-- datepicker -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/datepicker/bootstrap-datepicker.js') }}"></script>
|
||||||
|
<!-- Bootstrap WYSIHTML5 -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/bootstrap-wysihtml5/0.4.15/bootstrap3-wysihtml5.fontawesome.min.js') }}"></script>
|
||||||
|
<!-- Slimscroll -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/slimScroll/1.3.8/jquery.slimscroll.min.js') }}"></script>
|
||||||
|
<!-- FastClick -->
|
||||||
|
<script src="{{ url_for('static',filename='plugins/fastclick/fastclick.js') }}"></script>
|
||||||
|
<!-- AdminLTE App -->
|
||||||
|
<script src="{{ url_for('static',filename='js/app.min.js') }}"></script>
|
||||||
|
<!-- AdminLTE for demo purposes -->
|
||||||
|
<script src="{{ url_for('static',filename='js/demo.js') }}"></script>
|
||||||
|
{% if admin_view.name=="Home" %}
|
||||||
|
<script src="{{ url_for('static',filename='js/pages/dashboard.js') }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock tail_js %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{% endblock tail %}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
61
LBI_PiPy/templates/admin_/custom_index.html
Normal file
61
LBI_PiPy/templates/admin_/custom_index.html
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% block body %}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Custom View
|
||||||
|
<small>This is a custom view without DB model</small>
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
|
||||||
|
<li class="active">Custom</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- Left col -->
|
||||||
|
<section class="container">
|
||||||
|
|
||||||
|
Here you can place your custom data without a database dependence. <br>
|
||||||
|
Find this file in templates/admin/ as custom_index.html
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- /.Left col -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.row (main row) -->
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- /.content -->
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<section class="content" style="color: white;text-align: center;height:100%;width: 50%;
|
||||||
|
margin: 0 auto;">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>Alerte 112 - Administration</h1>
|
||||||
|
<p class="lead">
|
||||||
|
{{ _("Authentification") }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{_("Pour accéder à l'interface d'administration veuillez utiliser vos identifiants.")}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('security.login') }}">{{_("Connection")}}</a>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary" href="/"><i class="glyphicon glyphicon-chevron-left"></i> {{ _("Retour") }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock body %}
|
9
LBI_PiPy/templates/admin_/file/form.html
Normal file
9
LBI_PiPy/templates/admin_/file/form.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block header %}<h3>{{ header_text }}</h3>{% endblock %}
|
||||||
|
{% block fa_form %}
|
||||||
|
{{ lib.render_form(form, dir_url) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
189
LBI_PiPy/templates/admin_/file/list.html
Normal file
189
LBI_PiPy/templates/admin_/file/list.html
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% import 'admin/actions.html' as actionslib with context %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block breadcrums %}
|
||||||
|
<ul class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{{ get_dir_url('.index_view', path=None) }}">{{ _gettext('Root') }}</a>
|
||||||
|
</li>
|
||||||
|
{% for name, path in breadcrumbs[:-1] %}
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{{ get_dir_url('.index_view', path=path) }}">{{ name }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% if breadcrumbs %}
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{{ get_dir_url('.index_view', path=breadcrumbs[-1][1]) }}">{{ breadcrumbs[-1][0] }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block file_list_table %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{% block list_header scoped %}
|
||||||
|
{% if actions %}
|
||||||
|
<th class="list-checkbox-column">
|
||||||
|
<input type="checkbox" name="rowtoggle" class="action-rowtoggle" />
|
||||||
|
</th>
|
||||||
|
{% endif %}
|
||||||
|
{% for column in admin_view.column_list %}
|
||||||
|
<th>
|
||||||
|
{% if admin_view.is_column_sortable(column) %}
|
||||||
|
{% if sort_column == column %}
|
||||||
|
<a href="{{ sort_url(column, True) }}" title="{{ _gettext('Sort by %(name)s', name=column) }}">
|
||||||
|
{{ admin_view.column_label(column) }}
|
||||||
|
{% if sort_desc %}
|
||||||
|
<span class="fas fa-chevron-up"></span>
|
||||||
|
{% else %}
|
||||||
|
<span class="fas fa-chevron-down"></span>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ sort_url(column) }}" title="{{ _gettext('Sort by %(name)s', name=column) }}">{{ admin_view.column_label(column) }}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{{ _gettext(admin_view.column_label(column)) }}
|
||||||
|
{% endif %}
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for name, path, is_dir, size, date in items %}
|
||||||
|
<tr>
|
||||||
|
{% block list_row scoped %}
|
||||||
|
{% if actions %}
|
||||||
|
<td>
|
||||||
|
{% if not is_dir %}
|
||||||
|
<input type="checkbox" name="rowid" class="action-checkbox" value="{{ path }}" />
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
<td>
|
||||||
|
{% block list_row_actions scoped %}
|
||||||
|
{% if admin_view.can_rename and path and name != '..' %}
|
||||||
|
{%- if admin_view.rename_modal -%}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.rename', path=path, modal=True),
|
||||||
|
title=_gettext('Rename File'),
|
||||||
|
content='<i class="fa fa-pen"></i>') }}
|
||||||
|
{% else %}
|
||||||
|
<a class="icon" href="{{ get_url('.rename', path=path) }}" title="{{ _gettext('Rename File') }}">
|
||||||
|
<i class="fa fa-pen"></i>
|
||||||
|
</a>
|
||||||
|
{%- endif -%}
|
||||||
|
{% endif %}
|
||||||
|
{%- if admin_view.can_delete and path -%}
|
||||||
|
{% if is_dir %}
|
||||||
|
{% if name != '..' and admin_view.can_delete_dirs %}
|
||||||
|
<form class="icon" method="POST" action="{{ get_url('.delete') }}">
|
||||||
|
{{ delete_form.path(value=path) }}
|
||||||
|
{{ delete_form.csrf_token }}
|
||||||
|
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\' recursively?', name=name) }}')">
|
||||||
|
<i class="fas fa-times glyphicon glyphicon-remove"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<form class="icon" method="POST" action="{{ get_url('.delete') }}">
|
||||||
|
{{ delete_form.path(value=path) }}
|
||||||
|
{{ delete_form.csrf_token }}
|
||||||
|
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\'?', name=name) }}')">
|
||||||
|
<i class="fa fa-trash glyphicon glyphicon-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
{%- endif -%}
|
||||||
|
{% endblock %}
|
||||||
|
</td>
|
||||||
|
{% if is_dir %}
|
||||||
|
<td colspan="2">
|
||||||
|
<a href="{{ get_dir_url('.index_view', path)|safe }}">
|
||||||
|
<i class="fa fa-folder-o glyphicon glyphicon-folder-close"></i> <span>{{ name }}</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
{% else %}
|
||||||
|
<td>
|
||||||
|
{% if admin_view.can_download %}
|
||||||
|
{%- if admin_view.edit_modal and admin_view.is_file_editable(path) -%}
|
||||||
|
{{ lib.add_modal_button(url=get_file_url(path, modal=True)|safe,
|
||||||
|
btn_class='', content=name) }}
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ get_file_url(path)|safe }}">{{ name }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
{% else %}
|
||||||
|
{{ name }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% if admin_view.is_column_visible('size') %}
|
||||||
|
<td>
|
||||||
|
{{ size|filesizeformat }}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
{% if admin_view.is_column_visible('date') %}
|
||||||
|
<td>
|
||||||
|
{{ timestamp_format(date) }}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block toolbar %}
|
||||||
|
<div class="btn-toolbar">
|
||||||
|
{% if admin_view.can_upload %}
|
||||||
|
<div class="btn-group">
|
||||||
|
{%- if admin_view.upload_modal -%}
|
||||||
|
{{ lib.add_modal_button(url=get_dir_url('.upload', path=dir_path, modal=True),
|
||||||
|
btn_class="btn btn-secondary btn-large",
|
||||||
|
content=_gettext('Upload File')) }}
|
||||||
|
{% else %}
|
||||||
|
<a class="btn btn-secondary btn-large" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if admin_view.can_mkdir %}
|
||||||
|
<div class="btn-group">
|
||||||
|
{%- if admin_view.mkdir_modal -%}
|
||||||
|
{{ lib.add_modal_button(url=get_dir_url('.mkdir', path=dir_path, modal=True),
|
||||||
|
btn_class="btn btn-secondary btn-large",
|
||||||
|
content=_gettext('Create Directory')) }}
|
||||||
|
{% else %}
|
||||||
|
<a class="btn btn-secondary btn-large" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if actions %}
|
||||||
|
<div class="btn-group">
|
||||||
|
{{ actionslib.dropdown(actions, 'dropdown-toggle btn btn-secondary btn-large') }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block actions %}
|
||||||
|
{{ actionslib.form(actions, get_url('.action_view')) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{%- if admin_view.rename_modal or admin_view.mkdir_modal
|
||||||
|
or admin_view.upload_modal or admin_view.edit_modal -%}
|
||||||
|
{{ lib.add_modal_window() }}
|
||||||
|
{%- endif -%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ actionslib.script(_gettext('Please select at least one file.'),
|
||||||
|
actions,
|
||||||
|
actions_confirmation) }}
|
||||||
|
{% endblock %}
|
19
LBI_PiPy/templates/admin_/file/modals/form.html
Normal file
19
LBI_PiPy/templates/admin_/file/modals/form.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{# content added to modal-content #}
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
{% block header %}<h3>{{ header_text }}</h3>{% endblock %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% block fa_form %}
|
||||||
|
{{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/bs3_modal.js', v='1.0.0') }}"></script>
|
||||||
|
{% endblock %}
|
260
LBI_PiPy/templates/admin_/lib.html
Normal file
260
LBI_PiPy/templates/admin_/lib.html
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
|
||||||
|
{# ---------------------- Pager -------------------------- #}
|
||||||
|
{% macro pager(page, pages, generator) -%}
|
||||||
|
{% if pages > 1 %}
|
||||||
|
<ul class="pagination">
|
||||||
|
{% set min = page - 3 %}
|
||||||
|
{% set max = page + 3 + 1 %}
|
||||||
|
|
||||||
|
{% if min < 0 %}
|
||||||
|
{% set max = max - min %}
|
||||||
|
{% endif %}
|
||||||
|
{% if max >= pages %}
|
||||||
|
{% set min = min - max + pages %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if min < 0 %}
|
||||||
|
{% set min = 0 %}
|
||||||
|
{% endif %}
|
||||||
|
{% if max >= pages %}
|
||||||
|
{% set max = pages %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if min > 0 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(0) }}">«</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">«</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if page > 0 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page-1) }}"><</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)"><</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for p in range(min, max) %}
|
||||||
|
{% if page == p %}
|
||||||
|
<li class="active page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">{{ p + 1 }}</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(p) }}">{{ p + 1 }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if page + 1 < pages %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page + 1) }}">></a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if max < pages %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(pages - 1) }}">»</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">»</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% macro simple_pager(page, have_next, generator) -%}
|
||||||
|
<ul class="pagination">
|
||||||
|
{% if page > 0 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page - 1) }}"><</a>
|
||||||
|
</li class="page-item">
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="{{ generator(0) }}"><</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if have_next %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page + 1) }}">></a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page) }}">></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{# ---------------------- Modal Window ------------------- #}
|
||||||
|
{% macro add_modal_window(modal_window_id='fa_modal_window', modal_label_id='fa_modal_label') %}
|
||||||
|
<div class="modal fade" id="{{ modal_window_id }}" tabindex="-1" role="dialog"
|
||||||
|
aria-labelledby="{{ modal_label_id }}">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
{# bootstrap version > 3.1.0 required for this to work #}
|
||||||
|
<div class="modal-content">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro add_modal_button(url='', title='', content='', modal_window_id='fa_modal_window', btn_class='icon') %}
|
||||||
|
<a class="{{ btn_class }}" data-target="#{{ modal_window_id }}" title="{{ title }}" href="{{ url }}"
|
||||||
|
data-toggle="modal">
|
||||||
|
{{ content|safe }}
|
||||||
|
</a>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{# ---------------------- Forms -------------------------- #}
|
||||||
|
{% macro render_field(form, field, kwargs={}, caller=None) %}
|
||||||
|
{% set direct_error = h.is_field_error(field.errors) %}
|
||||||
|
<div class="form-group{{ ' has-error' if direct_error else '' }}">
|
||||||
|
<label for="{{ field.id }}" class="col-md-2 control-label">{{ field.label.text }}
|
||||||
|
{% if h.is_required_form_field(field) %}
|
||||||
|
<strong style="color: red">*</strong>
|
||||||
|
{%- else -%}
|
||||||
|
|
||||||
|
{%- endif %}
|
||||||
|
</label>
|
||||||
|
<div class="{{ kwargs.get('column_class', 'col-md-10') }}">
|
||||||
|
{% set _dummy = kwargs.setdefault('class', 'form-control') %}
|
||||||
|
{{ field(**kwargs)|safe }}
|
||||||
|
{% if field.description %}
|
||||||
|
<p class="help-block">{{ field.description|safe }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if direct_error %}
|
||||||
|
<ul class="help-block input-errors">
|
||||||
|
{% for e in field.errors if e is string %}
|
||||||
|
<li>{{ e }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% if caller %}
|
||||||
|
{{ caller(form, field, direct_error, kwargs) }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_header(form, text) %}
|
||||||
|
<h3>{{ text }}</h3>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_form_fields(form, form_opts=None) %}
|
||||||
|
{% if form.hidden_tag is defined %}
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
{% else %}
|
||||||
|
{% if csrf_token %}
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{% for f in form if f.widget.input_type == 'hidden' %}
|
||||||
|
{{ f }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if form_opts and form_opts.form_rules %}
|
||||||
|
{% for r in form_opts.form_rules %}
|
||||||
|
{{ r(form, form_opts=form_opts) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
{% for f in form if f.widget.input_type != 'hidden' %}
|
||||||
|
{% if form_opts %}
|
||||||
|
{% set kwargs = form_opts.widget_args.get(f.short_name, {}) %}
|
||||||
|
{% else %}
|
||||||
|
{% set kwargs = {} %}
|
||||||
|
{% endif %}
|
||||||
|
{{ render_field(form, f, kwargs) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form_tag(form=None, action=None) %}
|
||||||
|
<form action="{{ action or '' }}" method="POST" role="form" class="admin-form form-horizontal"
|
||||||
|
enctype="multipart/form-data">
|
||||||
|
{{ caller() }}
|
||||||
|
</form>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_form_buttons(cancel_url, extra=None, is_modal=False) %}
|
||||||
|
<hr>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-offset-2 col-md-10 submit-row">
|
||||||
|
<input type="submit" class="btn btn-primary" value="{{ _gettext('Save') }}"/>
|
||||||
|
{% if extra %}
|
||||||
|
{{ extra }}
|
||||||
|
{% endif %}
|
||||||
|
{% if cancel_url %}
|
||||||
|
<a href="{{ cancel_url }}" class="btn btn-danger" role="button"
|
||||||
|
{% if is_modal %}data-dismiss="modal"{% endif %}>{{ _gettext('Cancel') }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_form(form, cancel_url, extra=None, form_opts=None, action=None, is_modal=False) -%}
|
||||||
|
{% call form_tag(action=action) %}
|
||||||
|
{{ render_form_fields(form, form_opts=form_opts) }}
|
||||||
|
{{ render_form_buttons(cancel_url, extra, is_modal) }}
|
||||||
|
{% endcall %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form_css() %}
|
||||||
|
<link href="{{ admin_static.url(filename='vendor/select2/select2.css', v='3.5.2') }}" rel="stylesheet">
|
||||||
|
<link href="{{ admin_static.url(filename='vendor/select2/select2-bootstrap3.css', v='1.4.6') }}" rel="stylesheet">
|
||||||
|
<link href="{{ admin_static.url(filename='vendor/bootstrap-daterangepicker/daterangepicker-bs3.css', v='1.3.22') }}"
|
||||||
|
rel="stylesheet">
|
||||||
|
{% if config.MAPBOX_MAP_ID %}
|
||||||
|
<link href="{{ admin_static.url(filename='vendor/leaflet/leaflet.css', v='1.0.0') }}" rel="stylesheet">
|
||||||
|
<link href="{{ admin_static.url(filename='vendor/leaflet/leaflet.draw.css', v='0.3.2') }}" rel="stylesheet">
|
||||||
|
{% endif %}
|
||||||
|
{% if editable_columns %}
|
||||||
|
<link href="{{ admin_static.url(filename='vendor/x-editable/css/bootstrap3-editable.css', v='1.5.1.1') }}"
|
||||||
|
rel="stylesheet">
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form_js() %}
|
||||||
|
{% if config.MAPBOX_MAP_ID %}
|
||||||
|
<script>
|
||||||
|
window.MAPBOX_MAP_ID = "{{ config.MAPBOX_MAP_ID }}";
|
||||||
|
{% if config.MAPBOX_ACCESS_TOKEN %}
|
||||||
|
window.MAPBOX_ACCESS_TOKEN = "{{ config.MAPBOX_ACCESS_TOKEN }}";
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
<script src="{{ admin_static.url(filename='vendor/leaflet/leaflet.js', v='1.0.0') }}"></script>
|
||||||
|
<script src="{{ admin_static.url(filename='vendor/leaflet/leaflet.draw.js', v='0.3.2') }}"></script>
|
||||||
|
{% if config.MAPBOX_SEARCH %}
|
||||||
|
<script>
|
||||||
|
window.MAPBOX_SEARCH = "{{ config.MAPBOX_SEARCH }}";
|
||||||
|
</script>
|
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=places&key={{ config.get('GOOGLE_MAPS_API_KEY') }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
<script src="{{ admin_static.url(filename='vendor/bootstrap-daterangepicker/daterangepicker.js', v='1.3.22') }}"></script>
|
||||||
|
{% if editable_columns %}
|
||||||
|
<script src="{{ admin_static.url(filename='vendor/x-editable/js/bootstrap3-editable.min.js', v='1.5.1.1') }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/form.js', v='1.0.1') }}"></script>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro extra() %}
|
||||||
|
{% if admin_view.can_create %}
|
||||||
|
<input name="_add_another" type="submit" class="btn btn-secondary"
|
||||||
|
value="{{ _gettext('Save and Add Another') }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{% if admin_view.can_edit %}
|
||||||
|
<input name="_continue_editing" type="submit" class="btn btn-secondary"
|
||||||
|
value="{{ _gettext('Save and Continue Editing') }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
1
LBI_PiPy/templates/admin_/master.html
Normal file
1
LBI_PiPy/templates/admin_/master.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% extends admin_base_template %}
|
30
LBI_PiPy/templates/admin_/model/create.html
Normal file
30
LBI_PiPy/templates/admin_/model/create.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% from 'admin/lib.html' import extra with context %} {# backward compatible #}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_css() }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block navlinks %}
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ return_url }}">{{ _gettext('List') }}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active " href="javascript:void(0)">{{ _gettext('Create') }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block create_form %}
|
||||||
|
{{ lib.render_form(form, return_url, extra(), form_opts) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_js() }}
|
||||||
|
{% endblock %}
|
54
LBI_PiPy/templates/admin_/model/details.html
Normal file
54
LBI_PiPy/templates/admin_/model/details.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block navlinks %}
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ return_url }}">{{ _gettext('List') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- if admin_view.can_create -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ get_url('.create_view', url=return_url) }}">{{ _gettext('Create') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if admin_view.can_edit -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ get_url('.edit_view', id=request.args.get('id'), url=return_url) }}">{{ _gettext('Edit') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="javascript:void(0)">{{ _gettext('Details') }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block details_search %}
|
||||||
|
<div class="input-group fa_filter_container col-lg-6">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">{{ _gettext('Filter') }}</span>
|
||||||
|
</div>
|
||||||
|
<input id="fa_filter" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block details_table %}
|
||||||
|
<table class="table table-hover table-bordered searchable">
|
||||||
|
{% for c, name in details_columns %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<b>{{ name }}</b>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ get_value(model, c) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/details_filter.js', v='1.0.0') }}"></script>
|
||||||
|
{% endblock %}
|
40
LBI_PiPy/templates/admin_/model/edit.html
Normal file
40
LBI_PiPy/templates/admin_/model/edit.html
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% from 'admin/lib.html' import extra with context %} {# backward compatible #}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_css() }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block navlinks %}
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ return_url }}">{{ _gettext('List') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- if admin_view.can_create -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ get_url('.create_view', url=return_url) }}">{{ _gettext('Create') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active " href="javascript:void(0)">{{ _gettext('Edit') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- if admin_view.can_view_details -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ get_url('.details_view', id=request.args.get('id'), url=return_url) }}">{{ _gettext('Details') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block edit_form %}
|
||||||
|
{{ lib.render_form(form, return_url, extra(), form_opts) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_js() }}
|
||||||
|
{% endblock %}
|
15
LBI_PiPy/templates/admin_/model/inline_field_list.html
Normal file
15
LBI_PiPy/templates/admin_/model/inline_field_list.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{% import 'admin/model/inline_list_base.html' as base with context %}
|
||||||
|
|
||||||
|
{% macro render_field(field) %}
|
||||||
|
{{ field }}
|
||||||
|
|
||||||
|
{% if h.is_field_error(field.errors) %}
|
||||||
|
<ul class="help-block input-errors">
|
||||||
|
{% for e in field.errors if e is string %}
|
||||||
|
<li>{{ e }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{{ base.render_inline_fields(field, template, render_field, check) }}
|
4
LBI_PiPy/templates/admin_/model/inline_form.html
Normal file
4
LBI_PiPy/templates/admin_/model/inline_form.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
<div class="inline-form-field">
|
||||||
|
{{ lib.render_form_fields(field.form, form_opts=form_opts) }}
|
||||||
|
</div>
|
52
LBI_PiPy/templates/admin_/model/inline_list_base.html
Normal file
52
LBI_PiPy/templates/admin_/model/inline_list_base.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{% macro render_inline_fields(field, template, render, check=None) %}
|
||||||
|
<div class="inline-field" id="{{ field.id }}">
|
||||||
|
{# existing inline form fields #}
|
||||||
|
<div class="inline-field-list">
|
||||||
|
{% for subfield in field %}
|
||||||
|
<div id="{{ subfield.id }}" class="inline-field well well-sm">
|
||||||
|
{%- if not check or check(subfield) %}
|
||||||
|
<legend>
|
||||||
|
<small>
|
||||||
|
{{ field.label.text }} #{{ loop.index }}
|
||||||
|
<div class="pull-right">
|
||||||
|
{% if subfield.get_pk and subfield.get_pk() %}
|
||||||
|
<input type="checkbox" name="del-{{ subfield.id }}" id="del-{{ subfield.id }}"/>
|
||||||
|
<label for="del-{{ subfield.id }}"
|
||||||
|
style="display: inline">{{ _gettext('Delete?') }}</label>
|
||||||
|
{% else %}
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
value="{{ _gettext('Are you sure you want to delete this record?') }}"
|
||||||
|
class="inline-remove-field"><i
|
||||||
|
class="fa fa-times glyphicon glyphicon-remove"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</small>
|
||||||
|
</legend>
|
||||||
|
<div class='clearfix'></div>
|
||||||
|
{%- endif -%}
|
||||||
|
{{ render(subfield) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# template for new inline form fields #}
|
||||||
|
<div class="inline-field-template hide">
|
||||||
|
{% filter forceescape %}
|
||||||
|
<div class="inline-field well well-sm">
|
||||||
|
<legend>
|
||||||
|
<small>{{ _gettext('New') }} {{ field.label.text }}</small>
|
||||||
|
<div class="pull-right">
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
value="{{ _gettext('Are you sure you want to delete this record?') }}"
|
||||||
|
class="inline-remove-field"><span class="fa fa-times glyphicon glyphicon-remove"></span></a>
|
||||||
|
</div>
|
||||||
|
</legend>
|
||||||
|
<div class='clearfix'></div>
|
||||||
|
{{ render(template) }}
|
||||||
|
</div>
|
||||||
|
{% endfilter %}
|
||||||
|
</div>
|
||||||
|
<a id="{{ field.id }}-button" href="javascript:void(0)" class="btn btn-default"
|
||||||
|
onclick="faForm.addInlineField(this, '{{ field.id }}');">{{ _gettext('Add') }} {{ field.label.text }}</a>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
101
LBI_PiPy/templates/admin_/model/layout.html
Normal file
101
LBI_PiPy/templates/admin_/model/layout.html
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
{% macro filter_options(btn_class='dropdown-toggle') %}
|
||||||
|
<button class="btn {{ btn_class }}" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
{{ _gettext('Add Filter') }}
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu field-filters">
|
||||||
|
{% for k in filter_groups %}
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a href="javascript:void(0)" class="filter" onclick="return false;">{{ k }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro export_options(btn_class='dropdown-toggle') %}
|
||||||
|
{% if admin_view.export_types|length > 1 %}
|
||||||
|
<li class="dropdown">
|
||||||
|
<a class="{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
|
||||||
|
{{ _gettext('Export') }}<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu field-filters">
|
||||||
|
{% for export_type in admin_view.export_types %}
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a href="{{ get_url('.export', export_type=export_type, **request.args) }}" title="{{ _gettext('Export') }}">{{ _gettext('Export') + ' ' + export_type|upper }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ get_url('.export', export_type=admin_view.export_types[0], **request.args) }}" title="{{ _gettext('Export') }}">{{ _gettext('Export') }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro filter_form() %}
|
||||||
|
<form id="filter_form" method="GET" action="{{ return_url }}">
|
||||||
|
{% if sort_column is not none %}
|
||||||
|
<input type="hidden" name="sort" value="{{ sort_column }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if sort_desc %}
|
||||||
|
<input type="hidden" name="desc" value="{{ sort_desc }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if search %}
|
||||||
|
<input type="hidden" name="search" value="{{ search }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if page_size != default_page_size %}
|
||||||
|
<input type="hidden" name="page_size" value="{{ page_size }}">
|
||||||
|
{% endif %}
|
||||||
|
<div class="float-right">
|
||||||
|
<button type="submit" class="btn btn-primary" style="display: none">{{ _gettext('Apply') }}</button>
|
||||||
|
{% if active_filters %}
|
||||||
|
<a href="{{ clear_search_url }}" class="btn btn-secondary">{{ _gettext('Reset Filters') }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="filters"></table>
|
||||||
|
</form>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro search_form(input_class="") %}
|
||||||
|
<form method="GET" action="{{ return_url }}" class="form-inline" role="search">
|
||||||
|
{% for flt_name, flt_value in filter_args.items() %}
|
||||||
|
<input type="hidden" name="{{ flt_name }}" value="{{ flt_value }}">
|
||||||
|
{% endfor %}
|
||||||
|
{% if page_size != default_page_size %}
|
||||||
|
<input type="hidden" name="page_size" value="{{ page_size }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if sort_column is not none %}
|
||||||
|
<input type="hidden" name="sort" value="{{ sort_column }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if sort_desc %}
|
||||||
|
<input type="hidden" name="desc" value="{{ sort_desc }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if search %}
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" name="search" value="{{ search }}" class="{{ input_class }} form-control" placeholder="{{ _gettext('Search') }}">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<a href="{{ clear_search_url }}" class="input-group-text">
|
||||||
|
<span class="fas fa-times"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="search" value="" class="{{ input_class }} form-control" placeholder="{{ _gettext('Search') }}">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro page_size_form(generator, btn_class='dropdown-toggle') %}
|
||||||
|
<a class="{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
|
||||||
|
{{ page_size }} {{ _gettext('items') }}<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="dropdown-item"><a href="{{ generator(20) }}">20 {{ _gettext('items') }}</a></li>
|
||||||
|
<li class="dropdown-item"><a href="{{ generator(50) }}">50 {{ _gettext('items') }}</a></li>
|
||||||
|
<li class="dropdown-item"><a href="{{ generator(100) }}">100 {{ _gettext('items') }}</a></li>
|
||||||
|
</ul>
|
||||||
|
{% endmacro %}
|
228
LBI_PiPy/templates/admin_/model/list.html
Normal file
228
LBI_PiPy/templates/admin_/model/list.html
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
{% import 'admin/model/layout.html' as model_layout with context %}
|
||||||
|
{% import 'admin/actions.html' as actionlib with context %}
|
||||||
|
{% import 'admin/model/row_actions.html' as row_actions with context %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_css() }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block model_menu_bar %}
|
||||||
|
<ul class="nav nav-tabs actions-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="javascript:void(0)">
|
||||||
|
{{ _gettext('List') }}{% if count %} ({{ count }}){% endif %}</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{% if admin_view.can_create %}
|
||||||
|
<li class="nav-item">
|
||||||
|
{%- if admin_view.create_modal -%}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.create_view', url=return_url, modal=True), title=_gettext('Create New Record'), content=_gettext('Create')) }}
|
||||||
|
{% else %}
|
||||||
|
<a class="nav-link" href="{{ get_url('.create_view', url=return_url) }}"
|
||||||
|
title="{{ _gettext('Create New Record') }}">{{ _gettext('Create') }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if admin_view.can_export %}
|
||||||
|
{{ model_layout.export_options() }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block model_menu_bar_before_filters %}{% endblock %}
|
||||||
|
|
||||||
|
{% if filters %}
|
||||||
|
<li class="dropdown">
|
||||||
|
{{ model_layout.filter_options() }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if can_set_page_size %}
|
||||||
|
<li class="dropdown">
|
||||||
|
{{ model_layout.page_size_form(page_size_url) }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if actions %}
|
||||||
|
<li class="dropdown">
|
||||||
|
{{ actionlib.dropdown(actions) }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if search_supported %}
|
||||||
|
<li>
|
||||||
|
{{ model_layout.search_form() }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% block model_menu_bar_after_filters %}{% endblock %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% if filters %}
|
||||||
|
{{ model_layout.filter_form() }}
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block model_list_table %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-bordered table-hover model-list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{% block list_header scoped %}
|
||||||
|
{% if actions %}
|
||||||
|
<th class="list-checkbox-column">
|
||||||
|
<input type="checkbox" name="rowtoggle" class="action-rowtoggle"
|
||||||
|
title="{{ _gettext('Select all records') }}"/>
|
||||||
|
</th>
|
||||||
|
{% endif %}
|
||||||
|
{% block list_row_actions_header %}
|
||||||
|
{% if admin_view.column_display_actions %}
|
||||||
|
<th> </th>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% for c, name in list_columns %}
|
||||||
|
{% set column = loop.index0 %}
|
||||||
|
<th class="column-header col-{{ c }}">
|
||||||
|
{% if admin_view.is_sortable(c) %}
|
||||||
|
{% if sort_column == column %}
|
||||||
|
<a href="{{ sort_url(column, True) }}"
|
||||||
|
title="{{ _gettext('Sort by %(name)s', name=name) }}">
|
||||||
|
{{ name }}
|
||||||
|
{% if sort_desc %}
|
||||||
|
<span class="fa fa-chevron-up glyphicon glyphicon-chevron-up"></span>
|
||||||
|
{% else %}
|
||||||
|
<span class="fa fa-chevron-down glyphicon glyphicon-chevron-down"></span>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ sort_url(column) }}"
|
||||||
|
title="{{ _gettext('Sort by %(name)s', name=name) }}">{{ name }}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{{ name }}
|
||||||
|
{% endif %}
|
||||||
|
{% if admin_view.column_descriptions.get(c) %}
|
||||||
|
<a class="fa fa-question-circle glyphicon glyphicon-question-sign"
|
||||||
|
title="{{ admin_view.column_descriptions[c] }}"
|
||||||
|
href="javascript:void(0)" data-role="tooltip"
|
||||||
|
></a>
|
||||||
|
{% endif %}
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for row in data %}
|
||||||
|
<tr>
|
||||||
|
{% block list_row scoped %}
|
||||||
|
{% if actions %}
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="rowid" class="action-checkbox"
|
||||||
|
value="{{ get_pk_value(row) }}" title="{{ _gettext('Select record') }}"/>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
{% block list_row_actions_column scoped %}
|
||||||
|
{% if admin_view.column_display_actions %}
|
||||||
|
<td>
|
||||||
|
{% block list_row_actions scoped %}
|
||||||
|
{% for action in list_row_actions %}
|
||||||
|
{{ action.render_ctx(get_pk_value(row), row) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
</td>
|
||||||
|
{%- endif -%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% for c, name in list_columns %}
|
||||||
|
<td class="col-{{ c }}">
|
||||||
|
{% if admin_view.is_editable(c) %}
|
||||||
|
{% set form = list_forms[get_pk_value(row)] %}
|
||||||
|
{% if form.csrf_token %}
|
||||||
|
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=form.csrf_token._value()) }}
|
||||||
|
{% else %}
|
||||||
|
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c)) }}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{{ get_value(row, c) }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="999">
|
||||||
|
{% block empty_list_message %}
|
||||||
|
<div class="text-center">
|
||||||
|
{{ admin_view.get_empty_list_message() }}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% block list_pager %}
|
||||||
|
{% if num_pages is not none %}
|
||||||
|
{{ lib.pager(page, num_pages, pager_url) }}
|
||||||
|
{% else %}
|
||||||
|
{{ lib.simple_pager(page, data|length == page_size, pager_url) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block actions %}
|
||||||
|
{{ actionlib.form(actions, get_url('.action_view')) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{%- if admin_view.edit_modal or admin_view.create_modal or admin_view.details_modal -%}
|
||||||
|
{{ lib.add_modal_window() }}
|
||||||
|
{%- endif -%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/filters.js', v='1.0.0') }}"></script>
|
||||||
|
{{ lib.form_js() }}
|
||||||
|
|
||||||
|
{{ actionlib.script(_gettext('Please select at least one record.'),
|
||||||
|
actions,
|
||||||
|
actions_confirmation) }}
|
||||||
|
|
||||||
|
<script language="javascript">
|
||||||
|
(function ($) {
|
||||||
|
$('[data-role=tooltip]').tooltip({
|
||||||
|
html: true,
|
||||||
|
placement: 'bottom'
|
||||||
|
});
|
||||||
|
{% if filter_groups %}
|
||||||
|
var filter = new AdminFilters(
|
||||||
|
'#filter_form', '.field-filters',
|
||||||
|
{{ filter_groups|tojson|safe }},
|
||||||
|
{{ active_filters|tojson|safe }}
|
||||||
|
);
|
||||||
|
{% endif %}
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
// Catch exception when closing dialog with <esc> key
|
||||||
|
// and prevent accidental deletions.
|
||||||
|
function safeConfirm(msg) {
|
||||||
|
try {
|
||||||
|
var isconfirmed = confirm(msg);
|
||||||
|
if (isconfirmed == true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
32
LBI_PiPy/templates/admin_/model/modals/create.html
Normal file
32
LBI_PiPy/templates/admin_/model/modals/create.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{# store the jinja2 context for form_rules rendering logic #}
|
||||||
|
{% set render_ctx = h.resolve_ctx() %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||||
|
aria-hidden="true">×</span></button>
|
||||||
|
{% block header_text %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{# "save and add" button is removed from modal (it won't function properly) #}
|
||||||
|
{% block create_form %}
|
||||||
|
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
|
||||||
|
action=url_for('.create_view', url=return_url),
|
||||||
|
is_modal=True) }}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/bs3_modal.js', v='1.0.0') }}"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
// Apply flask-admin form styles after the modal is loaded
|
||||||
|
window.faForm.applyGlobalStyles(document);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
43
LBI_PiPy/templates/admin_/model/modals/details.html
Normal file
43
LBI_PiPy/templates/admin_/model/modals/details.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||||
|
aria-hidden="true">×</span></button>
|
||||||
|
{% block header_text %}
|
||||||
|
<h3>{{ _gettext('View Record') + ' #' + request.args.get('id') }}</h3>
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
{% block details_search %}
|
||||||
|
<div class="input-group fa_filter_container col-lg-6">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">{{ _gettext('Filter') }}</span>
|
||||||
|
</div>
|
||||||
|
<input id="fa_filter" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block details_table %}
|
||||||
|
<table class="table table-hover table-bordered searchable">
|
||||||
|
{% for c, name in details_columns %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<b>{{ name }}</b>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ get_value(model, c) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/details_filter.js', v='1.0.0') }}"></script>
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/bs3_modal.js', v='1.0.0') }}"></script>
|
||||||
|
{% endblock %}
|
34
LBI_PiPy/templates/admin_/model/modals/edit.html
Normal file
34
LBI_PiPy/templates/admin_/model/modals/edit.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{# store the jinja2 context for form_rules rendering logic #}
|
||||||
|
{% set render_ctx = h.resolve_ctx() %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||||
|
aria-hidden="true">×</span></button>
|
||||||
|
{% block header_text %}
|
||||||
|
<h3>{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}</h3>
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{# "save and continue" button is removed from modal (it won't function properly) #}
|
||||||
|
{% block edit_form %}
|
||||||
|
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
|
||||||
|
action=url_for('.edit_view', id=request.args.get('id'), url=return_url),
|
||||||
|
is_modal=True) }}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/bs3_modal.js', v='1.0.0') }}"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
// Apply flask-admin form styles after the modal is loaded
|
||||||
|
window.faForm.applyGlobalStyles(document);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
39
LBI_PiPy/templates/admin_/model/row_actions.html
Normal file
39
LBI_PiPy/templates/admin_/model/row_actions.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{% macro link(action, url, icon_class=None) %}
|
||||||
|
<a class="" href="{{ url }}" title="{{ action.title or '' }}">
|
||||||
|
<span class="{{ icon_class or action.icon_class }}"></span>
|
||||||
|
</a>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro view_row(action, row_id, row) %}
|
||||||
|
{{ link(action, get_url('.details_view', id=row_id, url=return_url), 'fa fa-eye glyphicon icon-eye-open') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro view_row_popup(action, row_id, row) %}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.details_view', id=row_id, url=return_url, modal=True), title=action.title, content='<span class="fa fa-eye glyphicon icon-eye-open"></span>') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro edit_row(action, row_id, row) %}
|
||||||
|
{{ link(action, get_url('.edit_view', id=row_id, url=return_url), 'fa fa-pen') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro edit_row_popup(action, row_id, row) %}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.edit_view', id=row_id, url=return_url, modal=True), title=action.title, content='<span class="fa fa-pen"></span>') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro delete_row(action, row_id, row) %}
|
||||||
|
<form class="icon" method="POST" action="{{ get_url('.delete_view') }}">
|
||||||
|
{{ delete_form.id(value=get_pk_value(row)) }}
|
||||||
|
{{ delete_form.url(value=return_url) }}
|
||||||
|
{% if delete_form.csrf_token %}
|
||||||
|
{{ delete_form.csrf_token }}
|
||||||
|
{% elif csrf_token %}
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
{% endif %}
|
||||||
|
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete this record?') }}');"
|
||||||
|
title="Delete record">
|
||||||
|
<span class="fa fa-trash glyphicon icon-trash"></span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endmacro %}
|
30
LBI_PiPy/templates/admin_/rediscli/console.html
Normal file
30
LBI_PiPy/templates/admin_/rediscli/console.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% import 'admin/static.html' as admin_static with context%}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
<link href="{{ admin_static.url(filename='admin/css/bootstrap3/rediscli.css', v='1.0.0') }}" rel="stylesheet">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="console">
|
||||||
|
<div class="console-container">
|
||||||
|
</div>
|
||||||
|
<div class="console-line">
|
||||||
|
<form action="#">
|
||||||
|
<input type="text"></input>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/rediscli.js', v='1.0.0') }}"></script>
|
||||||
|
<script language="javascript">
|
||||||
|
$(function() {
|
||||||
|
var redisCli = new RedisCli({{ admin_view.get_url('.execute_view')|tojson }});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
32
LBI_PiPy/templates/admin_/rediscli/response.html
Normal file
32
LBI_PiPy/templates/admin_/rediscli/response.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{% macro render(item, depth=0) %}
|
||||||
|
{% set type = type_name(item) %}
|
||||||
|
|
||||||
|
{% if type == 'tuple' or type == 'list' %}
|
||||||
|
{% if not item %}
|
||||||
|
Empty {{ type }}.
|
||||||
|
{% else %}
|
||||||
|
{% for n in item %}
|
||||||
|
{{ loop.index }}) {{ render(n, depth + 1) }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% elif type == 'bool' %}
|
||||||
|
{% if depth == 0 and item %}
|
||||||
|
OK
|
||||||
|
{% else %}
|
||||||
|
<span class="type-bool">{{ item }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% elif type == 'str' or type == 'unicode' %}
|
||||||
|
"{{ item }}"
|
||||||
|
{% elif type == 'bytes' %}
|
||||||
|
"{{ item.decode('utf-8') }}"
|
||||||
|
{% elif type == 'TextWrapper' %}
|
||||||
|
<pre>{{ item }}</pre>
|
||||||
|
{% elif type == 'dict' %}
|
||||||
|
{% for k, v in item.items() %}
|
||||||
|
{{ loop.index }}) {{ k }} - {{ render(v, depth + 1) }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
{{ item }}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
{{ render(result) }}
|
3
LBI_PiPy/templates/admin_/static.html
Normal file
3
LBI_PiPy/templates/admin_/static.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{% macro url() -%}
|
||||||
|
{{ get_url('admin.static', *varargs, **kwargs) }}
|
||||||
|
{%- endmacro %}
|
37
LBI_PiPy/templates/admin__/actions.html
Normal file
37
LBI_PiPy/templates/admin__/actions.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
|
||||||
|
{% macro dropdown(actions, btn_class='btn dropdown-toggle') -%}
|
||||||
|
<a class="{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">{{ _gettext('With selected') }}<b
|
||||||
|
class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
{% for p in actions %}
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
onclick="return modelActions.execute('{{ p[0] }}');">{{ _gettext(p[1]) }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form(actions, url) %}
|
||||||
|
{% if actions %}
|
||||||
|
<form id="action_form" action="{{ url }}" method="POST" style="display: none">
|
||||||
|
{% if action_form.csrf_token %}
|
||||||
|
{{ action_form.csrf_token }}
|
||||||
|
{% elif csrf_token %}
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{{ action_form.url(value=return_url) }}
|
||||||
|
{{ action_form.action() }}
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro script(message, actions, actions_confirmation) %}
|
||||||
|
{% if actions %}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/actions.js', v='1.0.0') }}"></script>
|
||||||
|
<script language="javascript">
|
||||||
|
var modelActions = new AdminModelActions({{ message|tojson|safe }}, {{ actions_confirmation|tojson|safe }});
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
113
LBI_PiPy/templates/admin__/base.html
Normal file
113
LBI_PiPy/templates/admin__/base.html
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
{% import 'admin/layout.html' as layout with context -%}
|
||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{% block title %}{% if admin_view.category %}{{ admin_view.category }} - {% endif %}{{ admin_view.name }} -
|
||||||
|
{{ admin_view.admin.name }}{% endblock %}</title>
|
||||||
|
{% block head_meta %}
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
{% endblock %}
|
||||||
|
{% block head_css %}
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="stylesheet" href="{{ url_for("static", filename="external/bootstrap/4.3.1/css/bootstrap.min.css") }}">
|
||||||
|
<!-- Select2.js CSS -->
|
||||||
|
<link rel="stylesheet" href="{{ url_for("static", filename="external/select2/4.0.6/css/select2.min.css") }}">
|
||||||
|
<!-- Fontawesome -->
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
|
||||||
|
integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
|
||||||
|
crossorigin="anonymous">
|
||||||
|
{# Extra css for admin pages #}
|
||||||
|
{% if admin_view.extra_css %}
|
||||||
|
{% for css_url in admin_view.extra_css %}
|
||||||
|
<link href="{{ css_url }}" rel="stylesheet">
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
<!-- Main css for admin pages -->
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename="admin/css/admin.css") }}">
|
||||||
|
{% endblock %}
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename="admin/favicon.ico") }}"/>
|
||||||
|
{% block head %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block head_tail %}
|
||||||
|
{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block page_body %}
|
||||||
|
<nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
|
||||||
|
{% block brand %}
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="{{ admin_view.admin.url }}">
|
||||||
|
<img src="{{ url_for('static', filename="admin/favicon.ico") }}" width="30" height="30"
|
||||||
|
class="d-inline-block align-top" alt="">
|
||||||
|
{{ admin_view.admin.name }}
|
||||||
|
</a>
|
||||||
|
{% endblock %}
|
||||||
|
<input class="form-control form-control-dark w-100" type="text" placeholder="Rechercher" aria-label="Search">
|
||||||
|
<ul class="navbar-nav px-3">
|
||||||
|
<li class="nav-item text-nowrap">
|
||||||
|
<a class="nav-link" href="{# todo: Disconnect link #}">Déconection</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
{% block main_menu %}
|
||||||
|
<ul class="nav flex-column">
|
||||||
|
{{ layout.menu() }}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
{% block menu_links %}
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
{{ layout.menu_links() }}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
{% block access_control %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{% block messages %}
|
||||||
|
{{ layout.messages() }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{# store the jinja2 context for form_rules rendering logic #}
|
||||||
|
{% set render_ctx = h.resolve_ctx() %}
|
||||||
|
<main class="col-md-9 ml-sm-auto col-lg-10 px-4" role="main">
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail_js %}
|
||||||
|
<!-- jQuery - Slim version (=without AJAX) -->
|
||||||
|
<script src="{{ url_for("static", filename="external/jquery/3.4.0/js/jquery.slim.min.js") }}"></script>
|
||||||
|
<!-- Popper.JS -->
|
||||||
|
<script src="{{ url_for("static", filename="external/popper/1.15.0/js/popper.min.js") }}"></script>
|
||||||
|
<!-- Bootstrap JS -->
|
||||||
|
<script src="{{ url_for("static", filename="external/bootstrap/4.3.1/js/bootstrap.min.js") }}"></script>
|
||||||
|
<!-- Moment.js -->
|
||||||
|
<script src="{{ url_for("static", filename="external/moment/2.24.0/js/moment.min.js") }}"></script>
|
||||||
|
<!-- Select2.js -->
|
||||||
|
<script src="{{ url_for("static", filename="external/select2/4.0.6/js/select2.min.js") }}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
{% if admin_view.extra_js %}
|
||||||
|
{% for js_url in admin_view.extra_js %}
|
||||||
|
<script src="{{ js_url }}" type="text/javascript"></script>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
49
LBI_PiPy/templates/admin__/index.html
Normal file
49
LBI_PiPy/templates/admin__/index.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% block body %}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Tableau de bord
|
||||||
|
<small>Panneau de contrôle</small>
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#"><i class="fa fa-dashboard"></i> Tableau de bord</a></li>
|
||||||
|
<li class="active">Panneau de contrôle</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
{# todo: Fill index page #}
|
||||||
|
</section>
|
||||||
|
<!-- /.content -->
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<section class="content" style="color: white;text-align: center;height:100%;width: 50%;
|
||||||
|
margin: 0 auto;">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>LBI - PiPy</h1>
|
||||||
|
<p class="lead">
|
||||||
|
Connection
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Pour accéder à l'interface d'administration veuillez utiliser vos identifiants.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('security.login') }}">Connection</a>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary" href="/"><i class="glyphicon glyphicon-chevron-left"></i> Retour</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock body %}
|
117
LBI_PiPy/templates/admin__/layout.html
Normal file
117
LBI_PiPy/templates/admin__/layout.html
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
{% macro menu_icon(item) %}
|
||||||
|
{% set icon_type = item.get_icon_type() %}
|
||||||
|
{% if icon_type %}
|
||||||
|
{% set icon_value = item.get_icon_value() %}
|
||||||
|
{% if icon_type == 'fa' %}
|
||||||
|
<i class="fa {{ icon_value }}"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="{{ icon_value }}"></i>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro menu(menu_root=None) %}
|
||||||
|
{% if menu_root is none %}
|
||||||
|
{% set menu_root = admin_view.admin.menu() %}
|
||||||
|
{% endif %}
|
||||||
|
{% for item in menu_root %}
|
||||||
|
{% if item.is_category() %}
|
||||||
|
{% set children = item.get_children() %}
|
||||||
|
{% if children %}
|
||||||
|
{% set class_name = item.get_class_name() or '' %}
|
||||||
|
{% if item.is_active(admin_view) %}
|
||||||
|
<li class="nav-item active{% if class_name %} {{ class_name }}{% endif %}">
|
||||||
|
{% else %}
|
||||||
|
<li class="nav-item{% if class_name %} {{ class_name }}{% endif %}">
|
||||||
|
{% endif %}
|
||||||
|
{% if item.is_active(admin_view) %}
|
||||||
|
<a href="#{{ item.name|e }}Submenu" data-toggle="collapse" aria-expanded="true"
|
||||||
|
class="dropdown-toggle nav-link">
|
||||||
|
{% else %}
|
||||||
|
<a href="#{{ item.name|e }}Submenu" data-toggle="collapse" aria-expanded="false"
|
||||||
|
class="dropdown-toggle nav-link">
|
||||||
|
{% endif %}
|
||||||
|
{% if item.class_name %}<span class="{{ item.class_name }}"></span> {% endif %}
|
||||||
|
{{ menu_icon(item) }}{{ item.name }}
|
||||||
|
{% if 'dropdown-submenu' in class_name %}
|
||||||
|
<i class="glyphicon glyphicon-chevron-right small"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="glyphicon glyphicon-chevron-down small"></i>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
{% if item.is_active(admin_view) %}
|
||||||
|
<ul class="collapse list-unstyled show" id="{{ item.name|e }}Submenu">
|
||||||
|
{% else %}
|
||||||
|
<ul class="collapse list-unstyled" id="{{ item.name|e }}Submenu">
|
||||||
|
{% endif %}
|
||||||
|
{% for child in children %}
|
||||||
|
{% if child.is_category() %}
|
||||||
|
{{ menu(menu_root=[child]) }}
|
||||||
|
{% else %}
|
||||||
|
{% set class_name = child.get_class_name() %}
|
||||||
|
{% if child.is_active(admin_view) %}
|
||||||
|
<li class="nav-item active{% if class_name %} {{ class_name }}{% endif %}">
|
||||||
|
{% else %}
|
||||||
|
<li{% if class_name %} class="{{ class_name }}"{% endif %}>
|
||||||
|
{% endif %}
|
||||||
|
{% if child.is_active(admin_view) %}
|
||||||
|
<a class="nav-link active" href="{{ child.get_url() }}"{% if child.target %}
|
||||||
|
target="{{ child.target }}"{% endif %}>
|
||||||
|
{{ menu_icon(child) }}{{ child.name }}</a>
|
||||||
|
{% else %}
|
||||||
|
<a class="nav-link" href="{{ child.get_url() }}"{% if child.target %}
|
||||||
|
target="{{ child.target }}"{% endif %}>
|
||||||
|
{{ menu_icon(child) }}{{ child.name }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% if item.is_accessible() and item.is_visible() %}
|
||||||
|
{% set class_name = item.get_class_name() %}
|
||||||
|
<li class="nav-item {% if class_name %} {{ class_name }}{% endif %}">
|
||||||
|
<a class="nav-link{% if item.is_active(admin_view) %} active{% endif %}" href="{{ item.get_url() }}"
|
||||||
|
{% if item.target %}
|
||||||
|
target="{{ item.target }}"{% endif %}>
|
||||||
|
{{ menu_icon(item) }}{{ item.name }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro menu_links(links=None) %}
|
||||||
|
{% if links is none %}
|
||||||
|
{% set links = admin_view.admin.menu_links() %}
|
||||||
|
{% endif %}
|
||||||
|
{% for item in links %}
|
||||||
|
{% if item.is_accessible() and item.is_visible() %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ item.get_url() }}">{{ menu_icon(item) }}{{ item.name }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro messages() %}
|
||||||
|
{% with messages = get_flashed_messages(with_categories=True) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, m in messages %}
|
||||||
|
{% if category %}
|
||||||
|
{# alert-error changed to alert-danger in bootstrap 3, mapping is for backwards compatibility #}
|
||||||
|
{% set mapping = {'message': 'info', 'error': 'danger'} %}
|
||||||
|
<div class="alert alert-{{ mapping.get(category, category) }} alert-dismissable">
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-dismissable">
|
||||||
|
{% endif %}
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||||
|
{{ m }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endmacro %}
|
257
LBI_PiPy/templates/admin__/lib.html
Normal file
257
LBI_PiPy/templates/admin__/lib.html
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
{% import 'admin/static.html' as admin_static with context %}
|
||||||
|
|
||||||
|
{# ---------------------- Pager -------------------------- #}
|
||||||
|
{% macro pager(page, pages, generator) -%}
|
||||||
|
{% if pages > 1 %}
|
||||||
|
<ul class="pagination">
|
||||||
|
{% set min = page - 3 %}
|
||||||
|
{% set max = page + 3 + 1 %}
|
||||||
|
|
||||||
|
{% if min < 0 %}
|
||||||
|
{% set max = max - min %}
|
||||||
|
{% endif %}
|
||||||
|
{% if max >= pages %}
|
||||||
|
{% set min = min - max + pages %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if min < 0 %}
|
||||||
|
{% set min = 0 %}
|
||||||
|
{% endif %}
|
||||||
|
{% if max >= pages %}
|
||||||
|
{% set max = pages %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if min > 0 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(0) }}">«</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">«</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if page > 0 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page-1) }}"><</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)"><</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for p in range(min, max) %}
|
||||||
|
{% if page == p %}
|
||||||
|
<li class="active page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">{{ p + 1 }}</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(p) }}">{{ p + 1 }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if page + 1 < pages %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page + 1) }}">></a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if max < pages %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(pages - 1) }}">»</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="javascript:void(0)">»</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% macro simple_pager(page, have_next, generator) -%}
|
||||||
|
<ul class="pagination">
|
||||||
|
{% if page > 0 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page - 1) }}"><</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="{{ generator(0) }}"><</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if have_next %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page + 1) }}">></a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled page-item">
|
||||||
|
<a class="page-link" href="{{ generator(page) }}">></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{# ---------------------- Modal Window ------------------- #}
|
||||||
|
{% macro add_modal_window(modal_window_id='fa_modal_window', modal_label_id='fa_modal_label') %}
|
||||||
|
<div class="modal fade" id="{{ modal_window_id }}" tabindex="-1" role="dialog"
|
||||||
|
aria-labelledby="{{ modal_label_id }}">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
{# bootstrap version > 3.1.0 required for this to work #}
|
||||||
|
<div class="modal-content">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro add_modal_button(url='', title='', content='', modal_window_id='fa_modal_window', btn_class='icon') %}
|
||||||
|
<a class="{{ btn_class }}" data-target="#{{ modal_window_id }}" title="{{ title }}" href="{{ url }}"
|
||||||
|
data-toggle="modal">
|
||||||
|
{{ content|safe }}
|
||||||
|
</a>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{# ---------------------- Forms -------------------------- #}
|
||||||
|
{% macro render_field(form, field, kwargs={}, caller=None) %}
|
||||||
|
{% set direct_error = h.is_field_error(field.errors) %}
|
||||||
|
<div class="form-group{{ ' has-error' if direct_error else '' }}">
|
||||||
|
<label for="{{ field.id }}" class="col-md-3 control-label">{{ field.label.text }}
|
||||||
|
{% if h.is_required_form_field(field) %}
|
||||||
|
<strong style="color: red">*</strong>
|
||||||
|
{%- else -%}
|
||||||
|
|
||||||
|
{%- endif %}
|
||||||
|
</label>
|
||||||
|
<div class="{{ kwargs.get('column_class', 'col-md-10') }}">
|
||||||
|
{% set _dummy = kwargs.setdefault('class', 'form-control') %}
|
||||||
|
{{ field(**kwargs)|safe }}
|
||||||
|
{% if field.description %}
|
||||||
|
<p class="help-block">{{ field.description|safe }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if direct_error %}
|
||||||
|
<ul class="help-block input-errors">
|
||||||
|
{% for e in field.errors if e is string %}
|
||||||
|
<li>{{ e }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% if caller %}
|
||||||
|
{{ caller(form, field, direct_error, kwargs) }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_header(form, text) %}
|
||||||
|
<h3>{{ text }}</h3>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_form_fields(form, form_opts=None) %}
|
||||||
|
{% if form.hidden_tag is defined %}
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
{% else %}
|
||||||
|
{% if csrf_token %}
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{% for f in form if f.widget.input_type == 'hidden' %}
|
||||||
|
{{ f }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if form_opts and form_opts.form_rules %}
|
||||||
|
{% for r in form_opts.form_rules %}
|
||||||
|
{{ r(form, form_opts=form_opts) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
{% for f in form if f.widget.input_type != 'hidden' %}
|
||||||
|
{% if form_opts %}
|
||||||
|
{% set kwargs = form_opts.widget_args.get(f.short_name, {}) %}
|
||||||
|
{% else %}
|
||||||
|
{% set kwargs = {} %}
|
||||||
|
{% endif %}
|
||||||
|
{{ render_field(form, f, kwargs) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form_tag(form=None, action=None) %}
|
||||||
|
<form action="{{ action or '' }}" method="POST" role="form" class="admin-form form-horizontal"
|
||||||
|
enctype="multipart/form-data">
|
||||||
|
{{ caller() }}
|
||||||
|
</form>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_form_buttons(cancel_url, extra=None, is_modal=False) %}
|
||||||
|
<hr>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-offset-2 col-md-10 submit-row">
|
||||||
|
<input type="submit" class="btn btn-primary" value="{{ _gettext('Save') }}"/>
|
||||||
|
{% if extra %}
|
||||||
|
{{ extra }}
|
||||||
|
{% endif %}
|
||||||
|
{% if cancel_url %}
|
||||||
|
<a href="{{ cancel_url }}" class="btn btn-danger" role="button"
|
||||||
|
{% if is_modal %}data-dismiss="modal"{% endif %}>{{ _gettext('Cancel') }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_form(form, cancel_url, extra=None, form_opts=None, action=None, is_modal=False) -%}
|
||||||
|
{% call form_tag(action=action) %}
|
||||||
|
{{ render_form_fields(form, form_opts=form_opts) }}
|
||||||
|
{{ render_form_buttons(cancel_url, extra, is_modal) }}
|
||||||
|
{% endcall %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form_css() %}
|
||||||
|
<link href="{{ url_for("static", filename="external/select2/4.0.6/css/select2.min.css") }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for("static", filename="external/daterangepicker/3.0.4/css/daterangepicker.css") }}"
|
||||||
|
rel="stylesheet">
|
||||||
|
{% if config.MAPBOX_MAP_ID %}
|
||||||
|
<link href="{{ url_for("static", filename="external/leaflet/1.4.0/css/leaflet.css") }}" rel="stylesheet">
|
||||||
|
{% endif %}
|
||||||
|
{% if editable_columns %}
|
||||||
|
<link href="{{ url_for("static", filename="external/bootstrap-editable/1.5.3-bs4/css/bootstrap-editable.css") }}"
|
||||||
|
rel="stylesheet">
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro form_js() %}
|
||||||
|
{% if config.MAPBOX_MAP_ID %}
|
||||||
|
<script>
|
||||||
|
window.MAPBOX_MAP_ID = "{{ config.MAPBOX_MAP_ID }}";
|
||||||
|
{% if config.MAPBOX_ACCESS_TOKEN %}
|
||||||
|
window.MAPBOX_ACCESS_TOKEN = "{{ config.MAPBOX_ACCESS_TOKEN }}";
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
<script src="{{ url_for("static", filename='external/leaflet/1.4.0/js/leaflet.js', v='1.0.0') }}"></script>
|
||||||
|
{% if config.MAPBOX_SEARCH %}
|
||||||
|
<script>
|
||||||
|
window.MAPBOX_SEARCH = "{{ config.MAPBOX_SEARCH }}";
|
||||||
|
</script>
|
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=places&key={{ config.get('GOOGLE_MAPS_API_KEY') }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
<script src="{{ url_for("static", filename="external/daterangepicker/3.0.4/js/daterangepicker.js") }}"></script>
|
||||||
|
{% if editable_columns %}
|
||||||
|
<script src="{{ url_for("static", filename="external/bootstrap-editable/1.5.3-bs4/js/bootstrap-editable.js") }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
<script src="{{ url_for("static", filename="admin/js/form.js") }}"></script>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro extra() %}
|
||||||
|
{% if admin_view.can_create %}
|
||||||
|
<input name="_add_another" type="submit" class="btn btn-secondary"
|
||||||
|
value="{{ _gettext('Save and Add Another') }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{% if admin_view.can_edit %}
|
||||||
|
<input name="_continue_editing" type="submit" class="btn btn-secondary"
|
||||||
|
value="{{ _gettext('Save and Continue Editing') }}"/>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
30
LBI_PiPy/templates/admin__/model/create.html
Normal file
30
LBI_PiPy/templates/admin__/model/create.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% from 'admin/lib.html' import extra with context %} {# backward compatible #}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_css() }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block navlinks %}
|
||||||
|
<ul class="nav nav-tabs actions-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ return_url }}">{{ _gettext('List') }}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active " href="javascript:void(0)">{{ _gettext('Create') }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block create_form %}
|
||||||
|
{{ lib.render_form(form, return_url, extra(), form_opts) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_js() }}
|
||||||
|
{% endblock %}
|
40
LBI_PiPy/templates/admin__/model/edit.html
Normal file
40
LBI_PiPy/templates/admin__/model/edit.html
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
{% from 'admin/lib.html' import extra with context %} {# backward compatible #}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_css() }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% block navlinks %}
|
||||||
|
<ul class="nav nav-tabs actions-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ return_url }}">{{ _gettext('List') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- if admin_view.can_create -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ get_url('.create_view', url=return_url) }}">{{ _gettext('Create') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active " href="javascript:void(0)">{{ _gettext('Edit') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- if admin_view.can_view_details -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ get_url('.details_view', id=request.args.get('id'), url=return_url) }}">{{ _gettext('Details') }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block edit_form %}
|
||||||
|
{{ lib.render_form(form, return_url, extra(), form_opts) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block tail %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_js() }}
|
||||||
|
{% endblock %}
|
57
LBI_PiPy/templates/admin__/model/inline_list_base.html
Normal file
57
LBI_PiPy/templates/admin__/model/inline_list_base.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{% macro render_inline_fields(field, template, render, check=None) %}
|
||||||
|
<div class="inline-field" id="{{ field.id }}">
|
||||||
|
{# existing inline form fields #}
|
||||||
|
{% for subfields in field|batch(2, ' ') %}
|
||||||
|
<div class="row inline-field-list">
|
||||||
|
{% for subfield in subfields %}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div id="{{ subfield.id }}" class="card well well-sm">
|
||||||
|
{%- if not check or check(subfield) %}
|
||||||
|
<div class="card-header">
|
||||||
|
{{ field.label.text }} #{{ loop.index }}
|
||||||
|
</div>
|
||||||
|
{%- endif -%}
|
||||||
|
<div class="card-body">
|
||||||
|
{{ render(subfield) }}
|
||||||
|
{% if subfield.get_pk and subfield.get_pk() %}
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="del-{{ subfield.id }}"
|
||||||
|
id="del-{{ subfield.id }}"/>
|
||||||
|
<label class="form-check-label" for="del-{{ subfield.id }}"
|
||||||
|
style="display: inline">{{ _gettext('Delete?') }}</label>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
value="{{ _gettext('Are you sure you want to delete this record?') }}"
|
||||||
|
class="inline-remove-field"><i
|
||||||
|
class="fa fa-times glyphicon glyphicon-remove"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{# template for new inline form fields #}
|
||||||
|
<div class="inline-field-template hide">
|
||||||
|
{% filter forceescape %}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="card well well-sm">
|
||||||
|
<div class="card-header">
|
||||||
|
{{ _gettext('New') }} {{ field.label.text }}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
{{ render(template) }}
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
value="{{ _gettext('Are you sure you want to delete this record?') }}"
|
||||||
|
class="inline-remove-field"><span class="fa fa-times glyphicon glyphicon-remove"></span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfilter %}
|
||||||
|
</div>
|
||||||
|
<a id="{{ field.id }}-button" href="javascript:void(0)" class="btn btn-default"
|
||||||
|
onclick="faForm.addInlineField(this, '{{ field.id }}');">{{ _gettext('Add') }} {{ field.label.text }}</a>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
119
LBI_PiPy/templates/admin__/model/layout.html
Normal file
119
LBI_PiPy/templates/admin__/model/layout.html
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
{%- macro filter_options(btn_class='dropdown-toggle') -%}
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true"
|
||||||
|
aria-expanded="false">
|
||||||
|
{{ _gettext('Add Filter') }}
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu field-filters">
|
||||||
|
{%- for k in filter_groups -%}
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a href="javascript:void(0)" class="filter" onclick="return false;">{{ k }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endfor -%}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro export_options(btn_class='dropdown-toggle') -%}
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link {{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
|
||||||
|
{{ _gettext('Export') }}<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu field-filters">
|
||||||
|
{%- for export_type in admin_view.export_types -%}
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a href="{{ get_url('.export', export_type=export_type, **request.args) }}"
|
||||||
|
title="{{ _gettext('Export') }}">{{ _gettext('Export') + ' ' + export_type|upper }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endfor -%}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro filter_form() -%}
|
||||||
|
<form id="filter_form" method="GET" action="{{ return_url }}">
|
||||||
|
{%- if sort_column is not none -%}
|
||||||
|
<input type="hidden" class="form-control" name="sort" value="{{ sort_column }}">
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if sort_desc -%}
|
||||||
|
<input type="hidden" class="form-control" name="desc" value="{{ sort_desc }}">
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if search -%}
|
||||||
|
<input type="hidden" class="form-control" name="search" value="{{ search }}">
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if page_size != default_page_size -%}
|
||||||
|
<input type="hidden" class="form-control" name="page_size" value="{{ page_size }}">
|
||||||
|
{%- endif -%}
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="btn btn-primary" style="display: none">{{ _gettext('Apply') }}</button>
|
||||||
|
{%- if active_filters -%}
|
||||||
|
<a href="{{ clear_search_url }}" class="btn btn-default">{{ _gettext('Reset Filters') }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="filters"></table>
|
||||||
|
</form>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro search_form(input_class="") -%}
|
||||||
|
<form method="GET" action="{{ return_url }}" class="form-inline" role="search">
|
||||||
|
{%- for flt_name, flt_value in filter_args.items() -%}
|
||||||
|
<input type="hidden" name="{{ flt_name }}" value="{{ flt_value }}">
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if page_size != default_page_size -%}
|
||||||
|
<input type="hidden" name="page_size" value="{{ page_size }}">
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if sort_column is not none -%}
|
||||||
|
<input type="hidden" name="sort" value="{{ sort_column }}">
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if sort_desc -%}
|
||||||
|
<input type="hidden" name="desc" value="{{ sort_desc }}">
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if search -%}
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" name="search" value="{{ search }}" class="{{ input_class }} form-control"
|
||||||
|
placeholder="{{ _gettext('Search') }}">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<a href="{{ clear_search_url }}" class="input-group-text">
|
||||||
|
<span class="fas fa-times"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- else -%}
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="search" value="" class="{{ input_class }} form-control"
|
||||||
|
placeholder="{{ _gettext('Search') }}">
|
||||||
|
</div>
|
||||||
|
{%- endif -%}
|
||||||
|
</form>
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro page_size_form(generator, btn_class='dropdown-toggle') -%}
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link {{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
|
||||||
|
{{ page_size }} {{ _gettext('items') }}<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="dropdown-item"><a href="{{ generator(20) }}">20 {{ _gettext('items') }}</a></li>
|
||||||
|
<li class="dropdown-item"><a href="{{ generator(50) }}">50 {{ _gettext('items') }}</a></li>
|
||||||
|
<li class="dropdown-item"><a href="{{ generator(100) }}">100 {{ _gettext('items') }}</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro actions(actions) -%}
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
|
||||||
|
{{ _gettext('With selected') }}<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
{%- for p in actions -%}
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
onclick="return modelActions.execute('{{ p[0] }}');">{{ _gettext(p[1]) }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endfor -%}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{%- endmacro -%}
|
222
LBI_PiPy/templates/admin__/model/list.html
Normal file
222
LBI_PiPy/templates/admin__/model/list.html
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
{%- extends 'admin/master.html' -%}
|
||||||
|
{%- import 'admin/lib.html' as lib with context -%}
|
||||||
|
{%- import 'admin/static.html' as admin_static with context -%}
|
||||||
|
{%- import 'admin/model/layout.html' as model_layout with context -%}
|
||||||
|
{%- import 'admin/actions.html' as actionlib with context -%}
|
||||||
|
{%- import 'admin/model/row_actions.html' as row_actions with context -%}
|
||||||
|
|
||||||
|
{%- block head -%}
|
||||||
|
{{ super() }}
|
||||||
|
{{ lib.form_css() }}
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- block body -%}
|
||||||
|
{%- block model_menu_bar -%}
|
||||||
|
<ul class="nav nav-tabs actions-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="javascript:void(0)">
|
||||||
|
{{ _gettext('List') }}{%- if count -%} ({{ count }}){%- endif -%}</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{%- if admin_view.can_create -%}
|
||||||
|
<li class="nav-item">
|
||||||
|
{%- if admin_view.create_modal -%}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.create_view', url=return_url, modal=True), title=_gettext('Create New Record'), content=_gettext('Create')) }}
|
||||||
|
{%- else -%}
|
||||||
|
<a class="nav-link" href="{{ get_url('.create_view', url=return_url) }}"
|
||||||
|
title="{{ _gettext('Create New Record') }}">{{ _gettext('Create') }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- if admin_view.can_export -%}
|
||||||
|
{{ model_layout.export_options() }}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- block model_menu_bar_before_filters -%}{%- endblock -%}
|
||||||
|
|
||||||
|
{%- if filters -%}
|
||||||
|
{{ model_layout.filter_options() }}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- if can_set_page_size -%}
|
||||||
|
{{ model_layout.page_size_form(page_size_url) }}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- if actions -%}
|
||||||
|
{{ model_layout.actions(actions) }}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- if search_supported -%}
|
||||||
|
<li>
|
||||||
|
{{ model_layout.search_form() }}
|
||||||
|
</li>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- block model_menu_bar_after_filters -%}{%- endblock -%}
|
||||||
|
</ul>
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- if filters -%}
|
||||||
|
{{ model_layout.filter_form() }}
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- block model_list_table -%}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-bordered table-hover model-list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{%- block list_header scoped -%}
|
||||||
|
{%- if actions -%}
|
||||||
|
<th class="list-checkbox-column">
|
||||||
|
<input type="checkbox" name="rowtoggle" class="action-rowtoggle"
|
||||||
|
title="{{ _gettext('Select all records') }}"/>
|
||||||
|
</th>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- block list_row_actions_header -%}
|
||||||
|
{%- if admin_view.column_display_actions -%}
|
||||||
|
<th> </th>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
{%- for c, name in list_columns -%}
|
||||||
|
{%- set column = loop.index0 -%}
|
||||||
|
<th class="column-header col-{{ c }}">
|
||||||
|
{%- if admin_view.is_sortable(c) -%}
|
||||||
|
{%- if sort_column == column -%}
|
||||||
|
<a href="{{ sort_url(column, True) }}"
|
||||||
|
title="{{ _gettext('Sort by %(name)s', name=name) }}">
|
||||||
|
{{ name }}
|
||||||
|
{%- if sort_desc -%}
|
||||||
|
<span class="fa fa-chevron-up glyphicon glyphicon-chevron-up"></span>
|
||||||
|
{%- else -%}
|
||||||
|
<span class="fa fa-chevron-down glyphicon glyphicon-chevron-down"></span>
|
||||||
|
{%- endif -%}
|
||||||
|
</a>
|
||||||
|
{%- else -%}
|
||||||
|
<a href="{{ sort_url(column) }}"
|
||||||
|
title="{{ _gettext('Sort by %(name)s', name=name) }}">{{ name }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{ name }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if admin_view.column_descriptions.get(c) -%}
|
||||||
|
<a class="fa fa-question-circle glyphicon glyphicon-question-sign"
|
||||||
|
title="{{ admin_view.column_descriptions[c] }}"
|
||||||
|
href="javascript:void(0)" data-role="tooltip"
|
||||||
|
></a>
|
||||||
|
{%- endif -%}
|
||||||
|
</th>
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{%- for row in data -%}
|
||||||
|
<tr>
|
||||||
|
{%- block list_row scoped -%}
|
||||||
|
{%- if actions -%}
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="rowid" class="action-checkbox"
|
||||||
|
value="{{ get_pk_value(row) }}" title="{{ _gettext('Select record') }}"/>
|
||||||
|
</td>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- block list_row_actions_column scoped -%}
|
||||||
|
{%- if admin_view.column_display_actions -%}
|
||||||
|
<td class="actions">
|
||||||
|
{%- block list_row_actions scoped -%}
|
||||||
|
{%- for action in list_row_actions -%}
|
||||||
|
{{ action.render_ctx(get_pk_value(row), row) }}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
</td>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- for c, name in list_columns -%}
|
||||||
|
<td class="col-{{ c }}">
|
||||||
|
{%- if admin_view.is_editable(c) -%}
|
||||||
|
{%- set form = list_forms[get_pk_value(row)] -%}
|
||||||
|
{%- if form.csrf_token -%}
|
||||||
|
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=form.csrf_token._value()) }}
|
||||||
|
{%- else -%}
|
||||||
|
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c)) }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{ get_value(row, c) }}
|
||||||
|
{%- endif -%}
|
||||||
|
</td>
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
</tr>
|
||||||
|
{%- else -%}
|
||||||
|
<tr>
|
||||||
|
<td colspan="999">
|
||||||
|
{%- block empty_list_message -%}
|
||||||
|
<div class="text-center">
|
||||||
|
{{ admin_view.get_empty_list_message() }}
|
||||||
|
</div>
|
||||||
|
{%- endblock -%}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{%- endfor -%}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{%- block list_pager -%}
|
||||||
|
{%- if num_pages is not none -%}
|
||||||
|
{{ lib.pager(page, num_pages, pager_url) }}
|
||||||
|
{%- else -%}
|
||||||
|
{{ lib.simple_pager(page, data|length == page_size, pager_url) }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- block actions -%}
|
||||||
|
{{ actionlib.form(actions, get_url('.action_view')) }}
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- if admin_view.edit_modal or admin_view.create_modal or admin_view.details_modal -%}
|
||||||
|
{{ lib.add_modal_window() }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- block tail -%}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ admin_static.url(filename='admin/js/filters.js', v='1.0.0') }}"></script>
|
||||||
|
{{ lib.form_js() }}
|
||||||
|
|
||||||
|
{{ actionlib.script(_gettext('Please select at least one record.'),
|
||||||
|
actions,
|
||||||
|
actions_confirmation) }}
|
||||||
|
|
||||||
|
<script language="javascript">
|
||||||
|
(function ($) {
|
||||||
|
$('[data-role=tooltip]').tooltip({
|
||||||
|
html: true,
|
||||||
|
placement: 'bottom'
|
||||||
|
});
|
||||||
|
{%- if filter_groups -%}
|
||||||
|
var filter = new AdminFilters(
|
||||||
|
'#filter_form', '.field-filters',
|
||||||
|
{{ filter_groups|tojson|safe }},
|
||||||
|
{{ active_filters|tojson|safe }}
|
||||||
|
);
|
||||||
|
{%- endif -%}
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
// Catch exception when closing dialog with <esc> key
|
||||||
|
// and prevent accidental deletions.
|
||||||
|
function safeConfirm(msg) {
|
||||||
|
try {
|
||||||
|
var isconfirmed = confirm(msg);
|
||||||
|
if (isconfirmed == true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{%- endblock -%}
|
39
LBI_PiPy/templates/admin__/model/row_actions.html
Normal file
39
LBI_PiPy/templates/admin__/model/row_actions.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% import 'admin/lib.html' as lib with context %}
|
||||||
|
|
||||||
|
{% macro link(action, url, icon_class=None) %}
|
||||||
|
<a class="btn btn-info" href="{{ url }}" title="{{ action.title or '' }}">
|
||||||
|
<span class="{{ icon_class or action.icon_class }}"></span>
|
||||||
|
</a>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro view_row(action, row_id, row) %}
|
||||||
|
{{ link(action, get_url('.details_view', id=row_id, url=return_url), 'fa fa-eye glyphicon icon-eye-open') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro view_row_popup(action, row_id, row) %}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.details_view', id=row_id, url=return_url, modal=True), title=action.title, content='<span class="fa fa-eye glyphicon icon-eye-open"></span>') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro edit_row(action, row_id, row) %}
|
||||||
|
{{ link(action, get_url('.edit_view', id=row_id, url=return_url), 'fa fa-pen') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro edit_row_popup(action, row_id, row) %}
|
||||||
|
{{ lib.add_modal_button(url=get_url('.edit_view', id=row_id, url=return_url, modal=True), title=action.title, content='<span class="fa fa-pen"></span>') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro delete_row(action, row_id, row) %}
|
||||||
|
<form method="POST" action="{{ get_url('.delete_view') }}">
|
||||||
|
{{ delete_form.id(value=get_pk_value(row)) }}
|
||||||
|
{{ delete_form.url(value=return_url) }}
|
||||||
|
{% if delete_form.csrf_token %}
|
||||||
|
{{ delete_form.csrf_token }}
|
||||||
|
{% elif csrf_token %}
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
{% endif %}
|
||||||
|
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete this record?') }}');"
|
||||||
|
title="Delete record" class="btn btn-danger">
|
||||||
|
<span class="fa fa-trash glyphicon icon-trash"></span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endmacro %}
|
19
LBI_PiPy/templates/index.html
Normal file
19
LBI_PiPy/templates/index.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<title>LBI_PiPy</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="LBI_PiPy">
|
||||||
|
<meta name="author" content="Louis Chauvet">
|
||||||
|
<!-- Favicon.ico -->
|
||||||
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
|
<!-- Bootstrap 4 si besoin
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="{{ url_for("admin.index") }}">Connection à la gestion des modules</a><br/>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
LBI_PiPy/templates/security/_macros.html
Normal file
27
LBI_PiPy/templates/security/_macros.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{% macro render_field_with_errors(field) %}
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
{{ field.label }} {{ field(class_='form-control', **kwargs)|safe }}
|
||||||
|
{% if field.errors %}
|
||||||
|
<ul>
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_field(field) %}
|
||||||
|
<p>{{ field(class_='form-control', **kwargs)|safe }}</p>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_checkbox_field(field) -%}
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
{{ field(type='checkbox', **kwargs) }} {{ field.label }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endmacro %}
|
19
LBI_PiPy/templates/security/_menu.html
Normal file
19
LBI_PiPy/templates/security/_menu.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% if security.registerable or security.recoverable or security.confirmable %}
|
||||||
|
<h2>Menu</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="
|
||||||
|
{{ url_for_security('login') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">Login</a>
|
||||||
|
</li>
|
||||||
|
{% if security.registerable %}
|
||||||
|
<li><a href="
|
||||||
|
{{ url_for_security('register') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">Register</a><br/>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if security.recoverable %}
|
||||||
|
<li><a href="{{ url_for_security('forgot_password') }}">Forgot password</a><br/></li>
|
||||||
|
{% endif %}
|
||||||
|
{% if security.confirmable %}
|
||||||
|
<li><a href="{{ url_for_security('send_confirmation') }}">Confirm account</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
9
LBI_PiPy/templates/security/_messages.html
Normal file
9
LBI_PiPy/templates/security/_messages.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{%- with messages = get_flashed_messages(with_categories=true) -%}
|
||||||
|
{% if messages %}
|
||||||
|
<ul class="flashes">
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<li class="{{ category }}">{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{%- endwith %}
|
24
LBI_PiPy/templates/security/login_user.html
Normal file
24
LBI_PiPy/templates/security/login_user.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% from "security/_macros.html" import render_field, render_field_with_errors, render_checkbox_field %}
|
||||||
|
{% include "security/_messages.html" %}
|
||||||
|
{% block body %}
|
||||||
|
{{ super() }}
|
||||||
|
<br><br><br><br><br>
|
||||||
|
<section class="content">
|
||||||
|
<div class="col-sm-8 col-sm-offset-2">
|
||||||
|
<div class="well">
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
|
||||||
|
{{ login_user_form.hidden_tag() }}
|
||||||
|
{{ render_field_with_errors(login_user_form.email) }}
|
||||||
|
{{ render_field_with_errors(login_user_form.password) }}
|
||||||
|
{{ render_checkbox_field(login_user_form.remember) }}
|
||||||
|
{{ render_field(login_user_form.next) }}
|
||||||
|
{{ render_field(login_user_form.submit, class="btn btn-primary") }}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br>
|
||||||
|
{% endblock body %}
|
28
LBI_PiPy/templates/security/register_user.html
Normal file
28
LBI_PiPy/templates/security/register_user.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{% extends 'admin/master.html' %}
|
||||||
|
{% from "security/_macros.html" import render_field_with_errors, render_field %}
|
||||||
|
{% include "security/_messages.html" %}
|
||||||
|
{% block body %}
|
||||||
|
{{ super() }}
|
||||||
|
<br><br><br><br>
|
||||||
|
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="col-sm-8 col-sm-offset-2">
|
||||||
|
<br>
|
||||||
|
<div class="well">
|
||||||
|
<h1>Register</h1>
|
||||||
|
<form action="{{ url_for_security('register') }}" method="POST" name="register_user_form">
|
||||||
|
{{ register_user_form.hidden_tag() }}
|
||||||
|
{{ render_field_with_errors(register_user_form.email) }}
|
||||||
|
{{ render_field_with_errors(register_user_form.password) }}
|
||||||
|
{% if register_user_form.password_confirm %}
|
||||||
|
{{ render_field_with_errors(register_user_form.password_confirm) }}
|
||||||
|
{% endif %}
|
||||||
|
{{ render_field(register_user_form.submit, class="btn btn-primary") }}
|
||||||
|
</form>
|
||||||
|
<p>Already signed up? Please <a href="{{ url_for('security.login') }}">log in</a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
|
||||||
|
{% endblock body %}
|
16
LBI_PiPy/views.py
Normal file
16
LBI_PiPy/views.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from flask import render_template, Blueprint, send_from_directory
|
||||||
|
|
||||||
|
|
||||||
|
main_bp = Blueprint('', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@main_bp.route('/')
|
||||||
|
def index():
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
|
||||||
|
@main_bp.route('/favicon.ico')
|
||||||
|
def favicon():
|
||||||
|
return send_from_directory('static','favicon.ico', mimetype='image/vnd.microsoft.icon')
|
22
Pipfile
Normal file
22
Pipfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[[source]]
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
flask = "*"
|
||||||
|
flask-admin = {git = "https://github.com/Fomys/flask-admin"}
|
||||||
|
flask-babelex = "*"
|
||||||
|
flask-security = "*"
|
||||||
|
flask-migrate = "*"
|
||||||
|
flask-script = "*"
|
||||||
|
flask-uploads = "*"
|
||||||
|
sqlalchemy = "*"
|
||||||
|
flask-sqlalchemy = "*"
|
||||||
|
flask-restful = "*"
|
||||||
|
pymysql = "*"
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.7"
|
268
Pipfile.lock
generated
Normal file
268
Pipfile.lock
generated
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"hash": {
|
||||||
|
"sha256": "571c6a0f1756f8d3293e6024f4625d4c118cf6847b8133d2a60b7b7faade4190"
|
||||||
|
},
|
||||||
|
"pipfile-spec": 6,
|
||||||
|
"requires": {
|
||||||
|
"python_version": "3.7"
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "pypi",
|
||||||
|
"url": "https://pypi.org/simple",
|
||||||
|
"verify_ssl": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"alembic": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:40b9a619aa5f25ea1e1508adcda88b33704ef28e02c9cfa6471e5c772ecf0829"
|
||||||
|
],
|
||||||
|
"version": "==1.0.9"
|
||||||
|
},
|
||||||
|
"aniso8601": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:b8a6a9b24611fc50cf2d9b45d371bfdc4fd0581d1cc52254f5502130a776d4af",
|
||||||
|
"sha256:bb167645c79f7a438f9dfab6161af9bed75508c645b1f07d1158240841d22673"
|
||||||
|
],
|
||||||
|
"version": "==6.0.0"
|
||||||
|
},
|
||||||
|
"babel": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
|
||||||
|
"sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23"
|
||||||
|
],
|
||||||
|
"version": "==2.6.0"
|
||||||
|
},
|
||||||
|
"blinker": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
|
||||||
|
],
|
||||||
|
"version": "==1.4"
|
||||||
|
},
|
||||||
|
"click": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
|
||||||
|
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
|
||||||
|
],
|
||||||
|
"version": "==7.0"
|
||||||
|
},
|
||||||
|
"flask": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
|
||||||
|
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.0.2"
|
||||||
|
},
|
||||||
|
"flask-admin": {
|
||||||
|
"git": "https://github.com/Fomys/flask-admin",
|
||||||
|
"ref": "16328db4f504f97b7d5accd8fc1fe292e31d2292"
|
||||||
|
},
|
||||||
|
"flask-babelex": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:cf79cdedb5ce860166120136b0e059e9d97b8df07a3bc2411f6243de04b754b4"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.9.3"
|
||||||
|
},
|
||||||
|
"flask-login": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:c815c1ac7b3e35e2081685e389a665f2c74d7e077cb93cecabaea352da4752ec"
|
||||||
|
],
|
||||||
|
"version": "==0.4.1"
|
||||||
|
},
|
||||||
|
"flask-mail": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
|
||||||
|
],
|
||||||
|
"version": "==0.9.1"
|
||||||
|
},
|
||||||
|
"flask-migrate": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a361578cb829681f860e4de5ed2c48886264512f0c16144e404c36ddc95ab49c",
|
||||||
|
"sha256:c24d105c5d6cc670de20f8cbfb909e04f4e04b8784d0df070005944de1f21549"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.4.0"
|
||||||
|
},
|
||||||
|
"flask-principal": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:f5d6134b5caebfdbb86f32d56d18ee44b080876a27269560a96ea35f75c99453"
|
||||||
|
],
|
||||||
|
"version": "==0.4.0"
|
||||||
|
},
|
||||||
|
"flask-restful": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:ecd620c5cc29f663627f99e04f17d1f16d095c83dc1d618426e2ad68b03092f8",
|
||||||
|
"sha256:f8240ec12349afe8df1db168ea7c336c4e5b0271a36982bff7394f93275f2ca9"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.3.7"
|
||||||
|
},
|
||||||
|
"flask-script": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:6425963d91054cfcc185807141c7314a9c5ad46325911bd24dcb489bd0161c65"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.0.6"
|
||||||
|
},
|
||||||
|
"flask-security": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:d61daa5f5a48f89f30f50555872bdf581b2c65804668b0313345cd7beff26432",
|
||||||
|
"sha256:ef837c03558db41335c8dabd16ae4977af0a5ef0c2cdecf738e33ef5202ce489"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==3.0.0"
|
||||||
|
},
|
||||||
|
"flask-sqlalchemy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3bc0fac969dd8c0ace01b32060f0c729565293302f0c4269beed154b46bec50b",
|
||||||
|
"sha256:5971b9852b5888655f11db634e87725a9031e170f37c0ce7851cf83497f56e53"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.3.2"
|
||||||
|
},
|
||||||
|
"flask-uploads": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:53ecbd6033667d50ae02b63adebbaa33c7fc56c09e5293025810cf9d841ecb02"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.2.1"
|
||||||
|
},
|
||||||
|
"flask-wtf": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:5d14d55cfd35f613d99ee7cba0fc3fbbe63ba02f544d349158c14ca15561cc36",
|
||||||
|
"sha256:d9a9e366b32dcbb98ef17228e76be15702cd2600675668bca23f63a7947fd5ac"
|
||||||
|
],
|
||||||
|
"version": "==0.14.2"
|
||||||
|
},
|
||||||
|
"itsdangerous": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
|
||||||
|
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
|
||||||
|
],
|
||||||
|
"version": "==1.1.0"
|
||||||
|
},
|
||||||
|
"jinja2": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
|
||||||
|
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
|
||||||
|
],
|
||||||
|
"version": "==2.10.1"
|
||||||
|
},
|
||||||
|
"mako": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0728c404877cd4ca72c409c0ea372dc5f3b53fa1ad2bb434e1d216c0444ff1fd"
|
||||||
|
],
|
||||||
|
"version": "==1.0.9"
|
||||||
|
},
|
||||||
|
"markupsafe": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||||
|
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
|
||||||
|
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
|
||||||
|
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
|
||||||
|
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
|
||||||
|
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
|
||||||
|
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
|
||||||
|
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
|
||||||
|
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
|
||||||
|
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
|
||||||
|
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
|
||||||
|
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
|
||||||
|
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
|
||||||
|
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
|
||||||
|
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
|
||||||
|
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
|
||||||
|
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
|
||||||
|
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
|
||||||
|
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
|
||||||
|
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
|
||||||
|
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
|
||||||
|
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
|
||||||
|
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
|
||||||
|
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
|
||||||
|
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
|
||||||
|
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
|
||||||
|
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
|
||||||
|
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
|
||||||
|
],
|
||||||
|
"version": "==1.1.1"
|
||||||
|
},
|
||||||
|
"passlib": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3d948f64138c25633613f303bcc471126eae67c04d5e3f6b7b8ce6242f8653e0",
|
||||||
|
"sha256:43526aea08fa32c6b6dbbbe9963c4c767285b78147b7437597f992812f69d280"
|
||||||
|
],
|
||||||
|
"version": "==1.7.1"
|
||||||
|
},
|
||||||
|
"pymysql": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3943fbbbc1e902f41daf7f9165519f140c4451c179380677e6a848587042561a",
|
||||||
|
"sha256:d8c059dcd81dedb85a9f034d5e22dcb4442c0b201908bede99e306d65ea7c8e7"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.9.3"
|
||||||
|
},
|
||||||
|
"python-dateutil": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
|
||||||
|
"sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
|
||||||
|
],
|
||||||
|
"version": "==2.8.0"
|
||||||
|
},
|
||||||
|
"python-editor": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:1bf6e860a8ad52a14c3ee1252d5dc25b2030618ed80c022598f00176adc8367d",
|
||||||
|
"sha256:51fda6bcc5ddbbb7063b2af7509e43bd84bfc32a4ff71349ec7847713882327b",
|
||||||
|
"sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8"
|
||||||
|
],
|
||||||
|
"version": "==1.0.4"
|
||||||
|
},
|
||||||
|
"pytz": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
|
||||||
|
"sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
|
||||||
|
],
|
||||||
|
"version": "==2019.1"
|
||||||
|
},
|
||||||
|
"six": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||||
|
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||||
|
],
|
||||||
|
"version": "==1.12.0"
|
||||||
|
},
|
||||||
|
"speaklater": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:59fea336d0eed38c1f0bf3181ee1222d0ef45f3a9dd34ebe65e6bfffdd6a65a9"
|
||||||
|
],
|
||||||
|
"version": "==1.3"
|
||||||
|
},
|
||||||
|
"sqlalchemy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:91c54ca8345008fceaec987e10924bf07dcab36c442925357e5a467b36a38319"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.3.3"
|
||||||
|
},
|
||||||
|
"werkzeug": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0a73e8bb2ff2feecfc5d56e6f458f5b99290ef34f565ffb2665801ff7de6af7a",
|
||||||
|
"sha256:7fad9770a8778f9576693f0cc29c7dcc36964df916b83734f4431c0e612a7fbc"
|
||||||
|
],
|
||||||
|
"version": "==0.15.2"
|
||||||
|
},
|
||||||
|
"wtforms": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0cdbac3e7f6878086c334aa25dc5a33869a3954e9d1e015130d65a69309b3b61",
|
||||||
|
"sha256:e3ee092c827582c50877cdbd49e9ce6d2c5c1f6561f849b3b068c1b8029626f1"
|
||||||
|
],
|
||||||
|
"version": "==2.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"develop": {}
|
||||||
|
}
|
35
manage.py
Normal file
35
manage.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from flask import url_for
|
||||||
|
from flask_migrate import Migrate, MigrateCommand
|
||||||
|
from flask_script import Manager
|
||||||
|
|
||||||
|
from LBI_PiPy import server, db
|
||||||
|
|
||||||
|
server.config.from_object('LBI_PiPy.config')
|
||||||
|
|
||||||
|
migrate = Migrate(server, db)
|
||||||
|
manager = Manager(server)
|
||||||
|
|
||||||
|
manager.add_command('db', MigrateCommand)
|
||||||
|
|
||||||
|
|
||||||
|
@manager.command
|
||||||
|
def list_routes():
|
||||||
|
import urllib.parse
|
||||||
|
output = []
|
||||||
|
for rule in server.url_map.iter_rules():
|
||||||
|
options = {}
|
||||||
|
for arg in rule.arguments:
|
||||||
|
if arg == "id":
|
||||||
|
options[arg] = "0"
|
||||||
|
else:
|
||||||
|
options[arg] = f"[{arg}]"
|
||||||
|
methods = ",".join(rule.methods)
|
||||||
|
url = url_for(rule.endpoint, **options)
|
||||||
|
line = urllib.parse.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, url))
|
||||||
|
output.append(line)
|
||||||
|
for line in sorted(output):
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
manager.run()
|
Loading…
Reference in New Issue
Block a user