Commit d8f23e3d authored by Serge S. Koval's avatar Serge S. Koval

Bootstrap 3 support. Work in progress. Fixes #386

parents 77989507 d2dc7074
This example shows how to customize Flask-Admin layout and overall look and feel.
\ No newline at end of file
import os
import os.path as op
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext import admin
from flask.ext.admin.contrib.sqla import ModelView
# Create application
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Models
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
email = db.Column(db.Unicode(64))
def __unicode__(self):
return self.name
class Page(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Unicode(64))
content = db.Column(db.UnicodeText)
def __unicode__(self):
return self.name
# Customized admin interface
class CustomView(ModelView):
list_template = 'list.html'
create_template = 'create.html'
edit_template = 'edit.html'
class UserAdmin(CustomView):
column_searchable_list = ('name',)
column_filters = ('name', 'email')
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
# Create admin with custom base template
admin = admin.Admin(app, base_template='layout.html', template_mode='bootstrap3')
# Add views
admin.add_view(UserAdmin(User, db.session))
admin.add_view(CustomView(Page, db.session))
def build_sample_db():
"""
Populate a small db with some example entries.
"""
db.drop_all()
db.create_all()
first_names = [
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
]
last_names = [
'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
]
for i in range(len(first_names)):
user = User()
user.name = first_names[i] + " " + last_names[i]
user.email = first_names[i].lower() + "@example.com"
db.session.add(user)
sample_text = [
{
'title': "de Finibus Bonorum et Malorum - Part I",
'content': "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure \
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt \
mollit anim id est laborum."
},
{
'title': "de Finibus Bonorum et Malorum - Part II",
'content': "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque \
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto \
beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur \
aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi \
nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, \
adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam \
aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam \
corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum \
iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum \
qui dolorem eum fugiat quo voluptas nulla pariatur?"
},
{
'title': "de Finibus Bonorum et Malorum - Part III",
'content': "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium \
voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati \
cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id \
est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam \
libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod \
maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. \
Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet \
ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur \
a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis \
doloribus asperiores repellat."
}
]
for entry in sample_text:
page = Page()
page.title = entry['title']
page.content = entry['content']
db.session.add(page)
db.session.commit()
return
if __name__ == '__main__':
# Build a sample db on the fly, if one does not exist yet.
app_dir = op.realpath(os.path.dirname(__file__))
database_path = op.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
# Start app
app.run(debug=True)
body {
background: #EEE;
}
#content {
background: white;
border: 1px solid #CCC;
padding: 15px 20px 30px 35px;
}
#content .row {
margin-left: 0px;
}
#brand {
display: inline;
}
.search-form {
margin: 0 5px;
}
.search-form form {
margin: 0;
}
.btn-menu {
margin: 4px 5px 0 0;
float: right;
}
.btn-menu a, .btn-menu input {
padding: 7px 16px !important;
border-radius: 1px !important;
border-color: #ccc;
}
.btn, textarea, input[type], button, .model-list {
border-radius: 0;
}
.model-list {
border-radius: 0;
}
.nav-pills li > a {
border-radius: 0;
}
.select2-container .select2-choice {
border-radius: 0;
}
a.dropdown-toggle b.caret {
margin-left: 5px;
}
\ No newline at end of file
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row">
<h1>Flask-Admin example</h1>
<p class="lead">
Customize the layout
</p>
<p>
This example shows how you can customize the look & feel of the admin interface.
</p>
<p>
This is done by overriding some of the built-in templates.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
{% endblock body %}
{% extends 'admin/model/create.html' %}
{% block brand %}
<h2 id="brand">Create {{ admin_view.name|capitalize }}</h2>
<div class="clearfix"></div>
<hr>
{% endblock %}
{% block body %}
{% call lib.form_tag(form) %}
{{ lib.render_form_fields(form, form_opts=form_opts) }}
<div class="form-buttons">
{{ lib.render_form_buttons(return_url, extra()) }}
</div>
{% endcall %}
{% endblock %}
{% extends 'admin/model/edit.html' %}
{% block brand %}
<h2 id="brand">Edit {{ admin_view.name|capitalize }}</h2>
<div class="clearfix"></div>
<hr>
{% endblock %}
{% block body %}
{% call lib.form_tag(form) %}
{{ lib.render_form_fields(form, form_opts=form_opts) }}
<div class="form-buttons">
{{ lib.render_form_buttons(return_url) }}
</div>
{% endcall %}
{% endblock %}
{% import 'admin/layout.html' as layout with context -%}
{% extends 'admin/base.html' %}
{% block head_tail %}
{{ super() }}
<link href="{{ url_for('static', filename='layout.css') }}" rel="stylesheet">
{% endblock %}
{% block page_body %}
<div class="container">
<div class="row">
<div class="col-md-2" role="navigation">
<ul class="nav nav-pills nav-stacked">
{{ layout.menu() }}
{{ layout.menu_links() }}
</ul>
</div>
<div class="col-md-10">
<div id="content" class="row">
{% block brand %}
<h2 id="brand">{{ admin_view.name|capitalize }}</h2>
{% endblock %}
{{ layout.messages() }}
{% block body %}{% endblock %}
</div>
</div>
</div>
</div>
{% endblock %}
{% extends 'admin/model/list.html' %}
{% import 'admin/model/layout.html' as model_layout with context %}
{% block brand %}
<h2 id="brand">{{ admin_view.name|capitalize }} list</h2>
{% if admin_view.can_create %}
<div class="btn-menu">
<a href="{{ url_for('.create_view', url=return_url) }}" class="btn btn-primary pull-right">{{ _gettext('Create') }}</a>
</div>
{% endif %}
{% if filter_groups %}
<div class="btn-group btn-menu">
{{ model_layout.filter_options(btn_class='btn dropdown-toggle btn-title') }}
</div>
{% endif %}
{% if actions %}
<div class="btn-group btn-menu">
{{ actionlib.dropdown(actions, btn_class='btn dropdown-toggle btn-title') }}
</div>
{% endif %}
{% if search_supported %}
<div class="search-form btn-menu">
{{ model_layout.search_form(input_class='span2 btn-title') }}
</div>
{% endif %}
<div class="clearfix"></div>
<hr>
{% endblock %}
{% block model_menu_bar %}
{% endblock %}
......@@ -8,7 +8,7 @@
{% block body %}
{% call lib.form_tag(form) %}
{{ lib.render_form_fields(form, form_opts=form_opts, form_rules=form_rules) }}
{{ lib.render_form_fields(form, form_opts=form_opts) }}
<div class="form-buttons">
{{ lib.render_form_buttons(return_url, extra()) }}
</div>
......
......@@ -8,7 +8,7 @@
{% block body %}
{% call lib.form_tag(form) %}
{{ lib.render_form_fields(form, form_opts=form_opts, form_rules=form_rules) }}
{{ lib.render_form_fields(form, form_opts=form_opts) }}
<div class="form-buttons">
{{ lib.render_form_buttons(return_url) }}
</div>
......
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<h1>Flask-Admin example</h1>
<p class="lead">
Simple admin views, not related to models.
</p>
<p>
This example shows how to add your own views to the admin interface. The views do not have to be associated
to any of your models, and you can fill them with whatever content you want.
</p>
<p>
By adding custom views to the admin interface, they become accessible through the <em>navbar</em> at the top.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
<div class="row col-md-10 col-md-offset-1">
<h1>Flask-Admin example</h1>
<p class="lead">
Simple admin views, not related to models.
</p>
<p>
This example shows how to add your own views to the admin interface. The views do not have to be associated
to any of your models, and you can fill them with whatever content you want.
</p>
<p>
By adding custom views to the admin interface, they become accessible through the <em>navbar</em> at the top.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
{% endblock body %}
\ No newline at end of file
{% endblock body %}
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<div class="row col-md-10 col-md-offset-1">
<h1>Flask-Admin example</h1>
<p class="lead">
Basic SQLAlchemy model views.
......@@ -14,4 +14,4 @@
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
{% endblock body %}
\ No newline at end of file
{% endblock body %}
import os.path as op
from functools import wraps
from flask import Blueprint, render_template, abort, g
......@@ -219,7 +221,7 @@ class BaseView(with_metaclass(AdminViewMeta, BaseViewClass)):
self.blueprint = Blueprint(self.endpoint, __name__,
url_prefix=self.url,
subdomain=self.admin.subdomain,
template_folder='templates',
template_folder=op.join('templates', self.admin.template_mode),
static_folder=self.static_folder,
static_url_path=self.static_url_path)
......@@ -356,7 +358,8 @@ class Admin(object):
translations_path=None,
endpoint=None,
static_url_path=None,
base_template=None):
base_template=None,
template_mode=None):
"""
Constructor.
......@@ -381,6 +384,9 @@ class Admin(object):
all its views. Can be overridden in view configuration.
:param base_template:
Override base HTML template for all static views. Defaults to `admin/base.html`.
:param template_mode:
Base template path. Defaults to `bootstrap2`. If you want to use
Bootstrap 3 integration, change it to `bootstrap3`.
"""
self.app = app
......@@ -401,6 +407,7 @@ class Admin(object):
self.static_url_path = static_url_path
self.subdomain = subdomain
self.base_template = base_template or 'admin/base.html'
self.template_mode = template_mode or 'bootstrap2'
# Add predefined index view
self.add_view(self.index_view)
......
......@@ -29,7 +29,8 @@ def bool_formatter(view, value):
:param value:
Value to check
"""
return Markup('<i class="icon-ok"></i>' if value else '')
glyph = 'ok-circle' if value else 'minus-sign'
return Markup('<span class="glyphicon glyphicon-%s"></span>' % glyph)
def list_formatter(view, values):
......
/* Global styles */
body
{
padding-top: 4px;
}
/* Form customizations */
form.icon {
display: inline;
}
form.icon button {
border: none;
background: transparent;
text-decoration: none;
padding: 0;
line-height: normal;
}
a.icon, button span.glyphicon {
text-decoration: none;
margin-left: 10px;
color: black;
}
/* Model search form */
form.navbar-form {
margin: 1px 0 0 0;
}
form.navbar-form a.clear span {
margin-top: 8px;
margin-left: -20px;
}
form.navbar-form div.input-append {
display: inline-flex;
}
form.search-form div input {
margin: 0;
}
/* Filters */
table.filters {
border-collapse: collapse;
border-spacing: 4px;
margin: 12px 0px 20px 0px;
}
table.filters tr td {
padding-right: 5px;
padding-bottom: 3px;
}
table.flters tr td:nth-child(2){
width: 60%;
}
.filters input, .filters div.select2-container {
margin-bottom: 0px;
}
.filters div.select2-container {
width: 100% !important;
}
.filters a.remove-filter {
margin-bottom: 0;
display: block;
text-align: left;
}
.filters .remove-filter
{
vertical-align: middle;
}
.filters .remove-filter .close-icon
{
font-size: 16px;
}
.filters .remove-filter .close-icon:hover
{
color: black;
opacity: 0.4;
}
.filters .filter-op > a {
height: 28px;
line-height: 28px;
}
/* Inline forms */
.inline-field {
margin-bottom: 5px;
}
.inline-field-control {
float: right;
}
.inline-field .inline-form {
border-left: 1px solid #eeeeee;
padding-left: 8px;
margin-bottom: 4px;
}
.inline-field-control .glyphicon-remove {
margin-left: -30px;
}
.panel {
padding-top: 25px;
padding-left: 30px;
}
/* Image thumbnails */
.image-thumbnail img {
max-width: 100px;
max-height: 100px;
}
/* Forms */
.form-horizontal {
margin-top: 35px;
}
.submit-row {
margin-top: 35px;
}
td>span.glyphicon {
padding-left: 35%;
}
/* Patch Select2 */
.select2-results li {
min-height: 24px !important;
}
.select2-container.form-control {
height: auto !important;
padding: 0px;
border-width: 0px;
}
form .select2-choice {
height: 30px !important;
}
.select2-search-choice {
height: 24px !important;
margin-top: 4px !important;
}
/* link style */
a.btn-cancel {
border-radius: 4px;
border-color: #a08c8c;
color: #333;
background-color: #f0b8b8;
}
a.btn-link {
border-radius: 4px;
border-color: #95bee2;
}
a.btn-filter, a.btn-filter:hover {
border-radius: 4px;
border-color: #adadad;
color: #333;
background-color: #ebebeb;
max-height: 32px;
line-height: 16px;
}
.help-block {
margin-bottom: 0px;
}
ul.has-error {
margin-bottom: -8px;
}
.tooltip.top {
font-size: 1.1em;
top: -35px;
}
.checkbox input[type="checkbox"] {
margin-left: 0px;
margin-right: 15px;
}
.list-checkbox-column {
width: 14px;
}
.console {
position: relative;
width: 100%;
min-height: 400px;
}
.console-container {
border-radius: 4px;
position: absolute;
border: 1px solid #d4d4d4;
padding: 2px;
overflow: scroll;
top: 2px;
left: 2px;
right: 2px;
bottom: 5em;
}
.console-line {
position: absolute;
left: 2px;
right: 2px;
bottom: 2px;
}
.console-line input {
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
height: 2em;
}
.console .cmd {
background-color: #f5f5f5;
padding: 2px;
margin: 1px;
}
.console .response {
background-color: #f0f0f0;
padding: 2px;
margin: 1px;
}
.console .error {
color: red;
}
\ No newline at end of file
......@@ -40,7 +40,7 @@ var AdminFilters = function(element, filtersElement, filterGroups) {
// Filter list
$el.append(
$('<td/>').append(
$('<a href="#" class="btn remove-filter" />')
$('<a href="#" class="btn btn-filter remove-filter" />')
.append($('<span class="close-icon">&times;</span>'))
.append('&nbsp;')
.append(name)
......@@ -80,7 +80,7 @@ var AdminFilters = function(element, filtersElement, filterGroups) {
$field.select2({width: 'resolve'});
} else
{
$field = $('<input type="text" class="filter-val" />')
$field = $('<input type="text" class="filter-val form-control" />')
.attr('name', makeName(filter.arg));
$el.append($('<td/>').append($field));
}
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -10,9 +10,9 @@
<meta name="author" content="">
{% endblock %}
{% block head_css %}
<link href="{{ admin_static.url(filename='bootstrap/css/bootstrap.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/css/bootstrap-responsive.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/admin.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap-responsive.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/bootstrap2/admin.css') }}" rel="stylesheet">
{% endblock %}
{% block head %}
{% endblock %}
......@@ -53,8 +53,8 @@
{% endblock %}
{% block tail_js %}
<script src="{{ admin_static.url(filename='vendor/jquery-1.8.3.min.js') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='vendor/jquery-2.0.3.min.js') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='bootstrap/bootstrap2/js/bootstrap.min.js') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='select2/select2.min.js') }}" type="text/javascript"></script>
{% endblock %}
......
......@@ -4,7 +4,7 @@
{% block head %}
{{ super() }}
<link href="{{ admin_static.url(filename='admin/css/rediscli.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/bootstrap2/rediscli.css') }}" rel="stylesheet">
{% endblock %}
{% block body %}
......
{% import 'admin/static.html' as admin_static with context %}
{% macro dropdown(actions, btn_class='btn btn-default 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>
<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 csrf_token %}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
{% endif %}
<input type="hidden" id="action" name="action" />
</form>
{% endif %}
{% endmacro %}
{% macro script(message, actions, actions_confirmation) %}
{% if actions %}
<script src="{{ admin_static.url(filename='admin/js/actions.js') }}"></script>
<script language="javascript">
var modelActions = new AdminModelActions({{ message|tojson|safe }}, {{ actions_confirmation|tojson|safe }});
</script>
{% endif %}
{% endmacro %}
{% 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 name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
{% endblock %}
{% block head_css %}
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap-theme.min.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css') }}" rel="stylesheet">
{% endblock %}
{% block head %}
{% endblock %}
{% block head_tail %}
{% endblock %}
</head>
<body>
{% block page_body %}
<div class="container">
<nav class="navbar navbar-default" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#admin-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
{% block brand %}
<a class="navbar-brand" href="#">{{ admin_view.admin.name }}</a>
{% endblock %}
</div>
<!-- navbar content -->
<div class="collapse navbar-collapse" id="#admin-navbar-collapse">
{% block main_menu %}
<ul class="nav navbar-nav">
{{ layout.menu() }}
</ul>
{% endblock %}
{% block menu_links %}
<ul class="nav navbar-right">
{{ layout.menu_links() }}
</ul>
{% endblock %}
{% block access_control %}
{% endblock %}
</div>
</nav>
{% block messages %}
{{ layout.messages() }}
{% endblock %}
{% set render_ctx = h.resolve_ctx() %}
{% block body %}{% endblock %}
</div>
{% endblock %}
{% block tail_js %}
<script src="{{ admin_static.url(filename='vendor/jquery-2.0.3.min.js') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='bootstrap/bootstrap3/js/bootstrap.min.js') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='select2/select2.min.js') }}" type="text/javascript"></script>
{% endblock %}
{% block tail %}
{% endblock %}
</body>
</html>
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
<h3>{{ _gettext('You are editing %(path)s', path=path) }}</h3>
{% if error %}
<span>This file cannot be edited for now.</span>
{% else %}
{{ lib.render_form(form, dir_url) }}
{% endif %}
{% endblock %}
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
{{ lib.render_form(form, dir_url) }}
{% endblock %}
\ No newline at end of file
{% 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>
<a href="{{ get_dir_url('.index', path=None) }}">{{ _gettext('Root') }}</a>
</li>
{% for name, path in breadcrumbs[:-1] %}
<li>
<a href="{{ get_dir_url('.index', path=path) }}">{{ name }}</a>
</li>
{% endfor %}
{% if breadcrumbs %}
<li>
<a href="{{ get_dir_url('.index', path=breadcrumbs[-1][1]) }}">{{ breadcrumbs[-1][0] }}</a>
</li>
{% endif %}
</ul>
{% endblock %}
{% block file_list_table %}
<table class="table table-striped table-bordered model-list">
<thead>
<tr>
{% block list_header scoped %}
{% if actions %}
<th class="list-checkbox-column">
<input type="checkbox" name="rowtoggle" class="action-rowtoggle" />
</th>
{% endif %}
<th class="col-md-1">&nbsp;</th>
<th>Name</th>
<th>Size</th>
{% endblock %}
</tr>
</thead>
{% for name, path, is_dir, size 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 != '..' %}
<a class="icon" href="{{ url_for('.rename', path=path) }}">
<i class="glyphicon glyphicon-pencil"></i>
</a>
{% 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="{{ url_for('.delete') }}">
<input type="hidden" name="path" value="{{ path }}"></input>
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\' recursively?', name=name) }}')">
<i class="icon-remove"></i>
</button>
</form>
{% endif %}
{% else %}
<form class="icon" method="POST" action="{{ url_for('.delete') }}">
<input type="hidden" name="path" value="{{ path }}"></input>
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\'?', name=name) }}')">
<i class="glyphicon glyphicon-trash"></i>
</button>
</form>
{% endif %}
{%- endif -%}
{% endblock %}
</td>
{% if is_dir %}
<td colspan="2">
<a href="{{ get_dir_url('.index', path)|safe }}">
<i class="glyphicon glyphicon-folder-close"></i> <span>{{ name }}</span>
</a>
</td>
{% else %}
<td>
{% if admin_view.can_download %}
<a href="{{ get_file_url(path)|safe }}">{{ name }}</a>
{% else %}
{{ name }}
{% endif %}
</td>
<td>
{{ size|filesizeformat }}
</td>
{% endif %}
{% endblock %}
</tr>
{% endfor %}
</table>
{% endblock %}
{% block toolbar %}
<div class="btn-toolbar">
{% if admin_view.can_upload %}
<div class="btn-group">
<a class="btn btn-default btn-large" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a>
</div>
{% endif %}
{% if admin_view.can_mkdir %}
<div class="btn-group">
<a class="btn btn-default btn-large" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a>
</div>
{% endif %}
{% if actions %}
<div class="btn-group">
{{ actionslib.dropdown(actions, 'dropdown-toggle btn btn-default btn-large') }}
</div>
{% endif %}
</div>
{% endblock %}
{% block actions %}
{{ actionslib.form(actions, url_for('.action_view')) }}
{% endblock %}
{% endblock %}
{% block tail %}
{{ super() }}
{{ actionslib.script(_gettext('Please select at least one file.'),
actions,
actions_confirmation) }}
{% endblock %}
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
<h3>{{ _gettext('Please provide new name for %(name)s', name=name) }}</h3>
{{ lib.render_form(form, dir_url) }}
{% endblock %}
\ No newline at end of file
{% extends 'admin/master.html' %}
{% block body %}
{% endblock %}
{% macro menu() %}
{% for item in admin_view.admin.menu() %}
{% if item.is_category() %}
{% set children = item.get_children() %}
{% if children %}
{% if item.is_active(admin_view) %}<li class="active dropdown">{% else %}<li class="dropdown">{% endif %}
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">{{ item.name }}<b class="caret"></b></a>
<ul class="dropdown-menu">
{% for child in children %}
{% if child.is_active(admin_view) %}<li class="active">{% else %}<li>{% endif %}
<a href="{{ child.get_url() }}">{{ child.name }}</a>
</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% else %}
{% if item.is_accessible() and item.is_visible() %}
{% if item.is_active(admin_view) %}<li class="active">{% else %}<li>{% endif %}
<a href="{{ item.get_url() }}">{{ item.name }}</a>
</li>
{% endif %}
{% endif %}
{% endfor %}
{% endmacro %}
{% macro menu_links() %}
{% for item in admin_view.admin.menu_links() %}
{% if item.is_accessible() and item.is_visible() %}
<li>
<a href="{{ item.get_url() }}">{{ 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 %}
<div class="alert alert-{{ category }} alert-dismissable">
{% else %}
<div class="alert alert-dismissable">
{% endif %}
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ m }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% endmacro %}
{# ---------------------- 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>
<a href="{{ generator(0) }}">&laquo;</a>
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&laquo;</a>
</li>
{% endif %}
{% if page > 0 %}
<li>
<a href="{{ generator(page-1) }}">&lt;</a>
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&lt;</a>
</li>
{% endif %}
{% for p in range(min, max) %}
{% if page == p %}
<li class="active">
<a href="javascript:void(0)">{{ p + 1 }}</a>
</li>
{% else %}
<li>
<a href="{{ generator(p) }}">{{ p + 1 }}</a>
</li>
{% endif %}
{% endfor %}
{% if page + 1 < pages %}
<li>
<a href="{{ generator(page + 1) }}">&gt;</a>
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&gt;</a>
</li>
{% endif %}
{% if max < pages %}
<li>
<a href="{{ generator(pages - 1) }}">&raquo;</a>
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&raquo;</a>
</li>
{% endif %}
</ul>
{% endif %}
{%- endmacro %}
{# ---------------------- Forms -------------------------- #}
{% macro render_field(form, field, kwargs={}) %}
{% set direct_error = h.is_field_error(field.errors) %}
<div class="form-group{{ ' 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">&#42;</strong>
{%- else -%}
&nbsp;
{%- endif %}
</label>
<div class="col-md-4">
{% set _dummy = kwargs.setdefault('class', 'form-control') %}
{{ field(**kwargs)|safe }}
</div>
{% if field.description %}
<span class="help-block">{{ field.description }}</span>
{% endif %}
{% if direct_error %}
<ul{% if direct_error %} class="input-errors"{% endif %}>
{% for e in field.errors if e is string %}
<li>{{ e }}</li>
{% endfor %}
</ul>
{% 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.type == 'HiddenField' %}
{{ 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.type != 'HiddenField' and f.type != 'CSRFTokenField' %}
{% if form_opts %}
{% set kwargs = form_opts.widget_args.get(f.name, {}) %}
{% else %}
{% set kwargs = {} %}
{% endif %}
{{ render_field(form, f, kwargs) }}
{% endfor %}
{% endif %}
{% endmacro %}
{% macro form_tag(form=None) %}
<form action="" method="POST" role="form" class="form-horizontal" enctype="multipart/form-data">
{{ caller() }}
</form>
{% endmacro %}
{% macro render_form_buttons(cancel_url, extra=None) %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10 submit-row">
<input type="submit" class="btn btn-primary" value="{{ _gettext('Submit') }}" />
{% if extra %}
{{ extra }}
{% endif %}
{% if cancel_url %}
<a href="{{ cancel_url }}" class="btn btn-cancel" role="button">{{ _gettext('Cancel') }}</a>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro render_form(form, cancel_url, extra=None, form_opts=None) -%}
{% call form_tag() %}
{{ render_form_fields(form, form_opts=form_opts) }}
{{ render_form_buttons(cancel_url, extra) }}
{% endcall %}
{% endmacro %}
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% import 'admin/static.html' as admin_static with context %}
{% macro extra() %}
<input name="_add_another" type="submit" class="btn btn-large" value="{{ _gettext('Save and Add') }}" />
{% endmacro %}
{% block head %}
{{ super() }}
<link href="{{ admin_static.url(filename='select2/select2.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='datetimepicker/bootstrap-datetimepicker.css') }}" rel="stylesheet">
{% endblock %}
{% block body %}
<ul class="nav nav-tabs">
<li>
<a href="{{ return_url }}">{{ _gettext('List') }}</a>
</li>
<li class="active">
<a href="javascript:void(0)">{{ _gettext('Create') }}</a>
</li>
</ul>
{% call lib.form_tag(form) %}
{{ lib.render_form_fields(form, form_opts=form_opts) }}
{{ lib.render_form_buttons(return_url, extra()) }}
{% endcall %}
{% endblock %}
{% block tail %}
{{ super() }}
<script src="{{ admin_static.url(filename='datetimepicker/bootstrap-datetimepicker.js') }}"></script>
<script src="{{ admin_static.url(filename='admin/js/form.js') }}"></script>
{% endblock %}
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% import 'admin/static.html' as admin_static with context %}
{% macro extra() %}
<input name="_continue_editing" type="submit" class="btn" value="{{ _gettext('Save and Continue') }}" />
{% endmacro %}
{% block head %}
{{ super() }}
<link href="{{ admin_static.url(filename='select2/select2.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='datetimepicker/bootstrap-datetimepicker.css') }}" rel="stylesheet">
{% endblock %}
{% block body %}
{% call lib.form_tag(form) %}
{{ lib.render_form_fields(form, form_opts=form_opts) }}
{{ lib.render_form_buttons(return_url, extra()) }}
{% endcall %}
{% endblock %}
{% block tail %}
{{ super() }}
<script src="{{ admin_static.url(filename='datetimepicker/bootstrap-datetimepicker.js') }}"></script>
<script src="{{ admin_static.url(filename='admin/js/form.js') }}"></script>
{% endblock %}
{% import 'admin/model/inline_list_base.html' as base with context %}
{% macro render_field(field) %}
{{ field }}
{% endmacro %}
{{ base.render_inline_fields(field, template, render_field) }}
{% import 'admin/lib.html' as lib with context %}
<div class="inline-form-field">
{{ lib.render_form_fields(field.form, form_opts=form_opts) }}
</div>
{% macro render_inline_fields(field, template, render, check=None) %}
<div class="inline-field">
<div class="inline-field-list">
{% for subfield in field %}
<div id="{{ subfield.id }}" class="inline-field well">
{%- if not check or check(subfield) %}
{% if subfield.get_pk and subfield.get_pk() %}
<div class="inline-field-control">
<input type="checkbox" name="del-{{ subfield.id }}" id="del-{{ subfield.id }}" />
<label for="del-{{ subfield.id }}" style="display: inline">{{ _gettext('Delete?') }}</label>
</div>
{% else %}
<div class="inline-field-control">
<a href="javascript:void(0)" class="inline-remove-field"><i class="icon-remove"></i></a>
</div>
{% endif %}
{%- endif -%}
{{ render(subfield) }}
</div>
{% endfor %}
</div>
<div class="inline-field-template hide">
{% filter forceescape %}
<div class="inline-field panel panel-info">
<div class="inline-field-control">
<a href="javascript:void(0)" class="inline-remove-field"><span class="glyphicon glyphicon-remove"></span></a>
</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 %}
{% macro filter_options(btn_class='dropdown-toggle') %}
<a class="{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
{{ _gettext('Add Filter') }}<b class="caret"></b>
</a>
<ul class="dropdown-menu field-filters">
{% for k in filter_groups %}
<li>
<a href="javascript:void(0)" class="filter" onclick="return false;">{{ k }}</a>
</li>
{% endfor %}
</ul>
{% endmacro %}
{% macro filter_form() %}
<form id="filter_form" method="GET" action="{{ return_url }}">
<div class="pull-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-link">{{ _gettext('Reset Filters') }}</a>
{% endif %}
</div>
<table class="filters">
{%- for n, values in enumerate(active_filters) -%}
<tr>
{% set idx, value = values %}
{% set filter = filters[idx] %}
{% set filter_arg = admin_view.get_filter_arg(idx, filter) %}
<td>
<a href="javascript:void(0)" class="btn btn-filter remove-filter" title="{{ _gettext('Remove Filter') }}">
<span class="close-icon">&times;</span>&nbsp;{{ filter.name }}
</a>
</td>
<td>
<select class="filter-op" data-role="select2">
{% for op in filter_groups[filter.name] %}
<option value="{{ op['arg'] }}"{% if idx == op['index'] %} selected="selected"{% endif %}>{{ op['operation'] }}</option>
{% endfor %}
</select>
</td>
<td>
{%- if filter.options -%}
<select name="flt{{n}}_{{ filter_arg }}" class="filter-val" data-role="select2">
{%- for d in filter.options %}
<option value="{{ d[0] }}"{% if value == d[0] %} selected{% endif %}>{{ d[1] }}</option>
{%- endfor %}
</select>
{%- else -%}
<input name="flt{{n}}_{{ filter_arg }}" type="text" value="{{ value or '' }}" class="filter-val form-control"{% if filter.data_type %} data-role="{{ filter.data_type }}"{% endif %}></input>
{%- endif -%}
</td>
</tr>
{% endfor %}
</table>
</form>
<div class="clearfix"></div>
{% endmacro %}
{% macro search_form(input_class="span2") %}
<form method="GET" action="{{ return_url }}" class="navbar-form navbar-left" role="search">
{% if sort_column is not none %}
<input type="hidden" name="sort" value="{{ sort_column }}"></input>
{% endif %}
{% if sort_desc %}
<input type="hidden" name="desc" value="{{ sort_desc }}"></input>
{% endif %}
{% if search %}
<div class="input-append form-group">
<input type="text" name="search" value="{{ search }}" class="{{ input_class }} form-control" placeholder="{{ _gettext('Search') }}"></input>
<a href="{{ clear_search_url }}" class="clear add-on">
<span class="glyphicon glyphicon-remove"></span>
</a>
</div>
{% else %}
<div class="form-group">
<input type="text" name="search" value="" class="{{ input_class }} form-control" placeholder="{{ _gettext('Search') }}"></input>
</div>
{% endif %}
</form>
{% endmacro %}
{% 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 %}
{% block head %}
{{ super() }}
<link href="{{ admin_static.url(filename='select2/select2.css') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='datetimepicker/bootstrap-datetimepicker.css') }}" rel="stylesheet">
{% endblock %}
{% block body %}
{% block model_menu_bar %}
<ul class="nav nav-tabs">
<li class="active">
<a href="javascript:void(0)">{{ _gettext('List') }} ({{ count }})</a>
</li>
{% if admin_view.can_create %}
<li>
<a href="{{ url_for('.create_view', url=return_url) }}" title="{{ _gettext('Create new record') }}">{{ _gettext('Create') }}</a>
</li>
{% endif %}
{% if filters %}
<li class="dropdown">
{{ model_layout.filter_options() }}
</li>
{% endif %}
{% if actions %}
<li class="dropdown">
{{ actionlib.dropdown(actions) }}
</li>
{% endif %}
{% if search_supported %}
<li>
{{ model_layout.search_form() }}
</li>
{% endif %}
</ul>
{% endblock %}
{% if filters %}
{{ model_layout.filter_form() }}
<div class="clearfix"></div>
{% endif %}
{% block model_list_table %}
<table class="table table-striped table-bordered 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 %}
<th class="col-md-1">&nbsp;</th>
{% endblock %}
{% set column = 0 %}
{% for c, name in list_columns %}
<th class="column-header">
{% 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="glyphicon glyphicon-chevron-up"></span>
{% else %}
<span class="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="glyphicon glyphicon-question-sign"
title="{{ admin_view.column_descriptions[c] }}"
href="javascript:void(0)" data-role="tooltip"
></a>
{% endif %}
</th>
{% set column = column + 1 %}
{% 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 %}
<td>
{% block list_row_actions scoped %}
{%- if admin_view.can_edit -%}
<a class="icon" href="{{ url_for('.edit_view', id=get_pk_value(row), url=return_url) }}" title="Edit record">
<span class="glyphicon glyphicon-pencil"></span>
</a>
{%- endif -%}
{%- if admin_view.can_delete -%}
<form class="icon" method="POST" action="{{ url_for('.delete_view', id=get_pk_value(row), url=return_url) }}">
{% if csrf_token %}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
{% endif %}
<button onclick="return confirm('{{ _gettext('You sure you want to delete this item?') }}');" title="Delete record">
<span class="glyphicon glyphicon-trash"></span>
</button>
</form>
{%- endif -%}
{% endblock %}
</td>
{% endblock %}
{% for c, name in list_columns %}
<td>{{ get_value(row, c) }}</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>
{{ lib.pager(page, num_pages, pager_url) }}
{% endblock %}
{{ actionlib.form(actions, url_for('.action_view')) }}
{% endblock %}
{% block tail %}
{{ super() }}
<script src="{{ admin_static.url(filename='datetimepicker/bootstrap-datetimepicker.js') }}"></script>
<script src="{{ admin_static.url(filename='admin/js/form.js') }}"></script>
<script src="{{ admin_static.url(filename='admin/js/filters.js') }}"></script>
{{ actionlib.script(_gettext('Please select at least one model.'),
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 }}
);
{% endif %}
})(jQuery);
</script>
{% endblock %}
{% 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') }}" 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') }}"></script>
<script language="javascript">
$(function() {
var redisCli = new RedisCli({{ url_for('.execute_view')|tojson }});
});
</script>
{% endblock %}
{% 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) }}
\ No newline at end of file
{% macro url() -%}
{{ url_for('admin.static', *varargs, **kwargs) }}
{%- endmacro %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment