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

Draw filters in a table

parent 1c38485a
......@@ -8,10 +8,11 @@ Flask-Admin
Introduction
------------
This is a library for building an administrative interface on top of the Flask framework.
Flask-Admin is advanced, extensible and simple to use administrative interface building library for Flask framework.
Flask-Admin comes with a few batteries included: model scaffolding for `SQLAlchemy <http://www.sqlalchemy.org/>`_,
`MongoEngine <http://mongoengine.org/>`_ and `Peewee <https://github.com/coleifer/peewee>`_ ORMs as well as a simple file management interface.
Library comes with batteries included: model scaffolding for `SQLAlchemy <http://www.sqlalchemy.org/>`_,
`MongoEngine <http://mongoengine.org/>`_, MongoDB and `Peewee <https://github.com/coleifer/peewee>`_ ORMs, simple
file management interface and a lot of usage samples.
You're not limited by the default functionality - instead of providing simple scaffolding for the ORM
models, Flask-Admin provides tools that can be used to construct administrative interfaces of any complexity,
......
......@@ -66,4 +66,4 @@ if __name__ == '__main__':
# Start app
app.debug = True
app.run('0.0.0.0', 8001)
app.run('0.0.0.0', 8000)
......@@ -32,14 +32,18 @@ body {
border-radius: 0 !important;
}
.model-list {
.btn, textarea, input[type], button, .model-list {
border-radius: 0;
}
.form-buttons a, .form-buttons input, .form-buttons button {
.model-list {
border-radius: 0;
}
.nav-pills li > a {
border-radius: 0;
}
.select2-container .select2-choice {
border-radius: 0;
}
\ No newline at end of file
{% import 'admin/layout.html' as layout with context -%}
{% extends 'admin/base.html' %}
{% block head_css %}
{% block head_tail %}
{{ super() }}
<link href="{{ url_for('static', filename='layout.css') }}" rel="stylesheet">
{% endblock %}
......
......@@ -629,7 +629,7 @@ class ModelView(BaseModelView):
for table in join_tables:
if table.name not in joins:
query = query.join(table)
joins.add(table)
joins.add(table.name)
# Apply filter
query = flt.apply(query, value)
......
......@@ -31,36 +31,43 @@ form.search-form a.clear i {
}
/* Filters */
.filter-row {
margin: 4px;
table.filters {
border-collapse: none;
border-spacing: 4px;
}
.filter-row a, .filter-row select {
margin-right: 4px;
.filters input
{
margin-bottom: 0;
}
.filter-row input
{
margin-bottom: 0px;
width: 208px;
.filters a.remove-filter {
margin-bottom: 0;
display: block;
text-align: left;
}
.filter-row .remove-filter
.filters .remove-filter
{
vertical-align: middle;
}
.filter-row .remove-filter .close-icon
.filters .remove-filter .close-icon
{
font-size: 16px;
}
.filter-row .remove-filter .close-icon:hover
.filters .remove-filter .close-icon:hover
{
color: black;
opacity: 0.4;
}
.filters .filter-op > a {
height: 28px;
line-height: 28px;
}
/* Inline forms */
.fa-inline-field {
padding-bottom: 0.5em;
......
......@@ -9,48 +9,56 @@ var AdminFilters = function(element, filters_element, operations, options, types
}
function changeOperation() {
var $parent = $(this).parent();
var $el = $('.filter-val', $parent);
var $row = $(this).closest('tr');
var $el = $('.filter-val', $row);
var count = getCount($el.attr('name'));
$el.attr('name', 'flt' + count + '_' + $(this).val());
$('button', $root).show();
}
function removeFilter() {
$(this).parent().remove();
$(this).closest('tr').remove();
$('button', $root).show();
return false;
}
function addFilter(name, op) {
var $el = $('<div class="filter-row" />').appendTo($container);
$('<a href="#" class="btn remove-filter" />')
.append($('<span class="close-icon">&times;</span>'))
.append('&nbsp;')
.append(name)
.appendTo($el)
.click(removeFilter);
var $el = $('<tr />').appendTo($container);
// Filter list
$el.append(
$('<td/>').append(
$('<a href="#" class="btn remove-filter" />')
.append($('<span class="close-icon">&times;</span>'))
.append('&nbsp;')
.append(name)
.click(removeFilter)
)
);
// Filter type
var $select = $('<select class="filter-op" />')
.appendTo($el)
.change(changeOperation);
$(op).each(function() {
$select.append($('<option/>').attr('value', this[0]).text(this[1]));
});
$el.append(
$('<td/>').append($select)
);
$select.select2({width: 'resolve'});
// Input
var optId = op[0][0];
var $field;
if (optId in options) {
$field = $('<select class="filter-val" />')
.attr('name', 'flt' + lastCount + '_' + optId)
.appendTo($el);
.attr('name', 'flt' + lastCount + '_' + optId);
$(options[optId]).each(function() {
$field.append($('<option/>')
......@@ -62,10 +70,13 @@ var AdminFilters = function(element, filters_element, operations, options, types
} else
{
$field = $('<input type="text" class="filter-val" />')
.attr('name', 'flt' + lastCount + '_' + optId)
.appendTo($el);
.attr('name', 'flt' + lastCount + '_' + optId);
}
$el.append(
$('<td/>').append($field)
);
if (optId in types) {
$field.attr('data-role', types[optId]);
faForm.applyStyle($field, types[optId]);
......
......@@ -15,6 +15,8 @@
{% endblock %}
{% block head %}
{% endblock %}
{% block head_tail %}
{% endblock %}
</head>
<body>
{% block page_body %}
......
......@@ -6,6 +6,7 @@
{% endmacro %}
{% block head %}
{{ super() }}
<link href="{{ url_for('admin.static', filename='select2/select2.css') }}" rel="stylesheet">
<link href="{{ url_for('admin.static', filename='css/datepicker.css') }}" rel="stylesheet">
{% endblock %}
......
......@@ -2,6 +2,7 @@
{% import 'admin/lib.html' as lib with context %}
{% block head %}
{{ super() }}
<link href="{{ url_for('admin.static', filename='select2/select2.css') }}" rel="stylesheet">
<link href="{{ url_for('admin.static', filename='css/datepicker.css') }}" rel="stylesheet">
{% endblock %}
......
......@@ -20,31 +20,39 @@
{% endif %}
</div>
<div class="filters">
<table class="filters">
{%- for i, flt in enumerate(active_filters) -%}
<div class="filter-row">
<tr>
{% set filter = admin_view._filters[flt[0]] %}
<a href="#" class="btn remove-filter" title="{{ _gettext('Remove Filter') }}">
<span class="close-icon">&times;</span>&nbsp;{{ filters[flt[0]] }}
</a><select class="filter-op" data-role="select2">
{% for op in admin_view._filter_dict[filter.name] %}
<option value="{{ op[0] }}"{% if flt[0] == op[0] %} selected="selected"{% endif %}>{{ op[1] }}</option>
{% endfor %}
</select>
{%- set data = filter_data.get(flt[0]) -%}
{%- if data -%}
<select name="flt{{ i }}_{{ flt[0] }}" class="filter-val" data-role="select2">
{%- for d in data %}
<option value="{{ d[0] }}"{% if flt[1] == d[0] %} selected{% endif %}>{{ d[1] }}</option>
{%- endfor %}
</select>
{%- else -%}
<input name="flt{{ i }}_{{ flt[0] }}" type="text" value="{{ flt[1] or '' }}" class="filter-val"{% if flt[0] in filter_types %} data-role="{{ filter_types[flt[0]] }}"{% endif %}></input>
{%- endif -%}
</div>
<td>
<a href="#" class="btn remove-filter" title="{{ _gettext('Remove Filter') }}">
<span class="close-icon">&times;</span>&nbsp;{{ filters[flt[0]] }}
</a>
</td>
<td>
<select class="filter-op" data-role="select2">
{% for op in admin_view._filter_dict[filter.name] %}
<option value="{{ op[0] }}"{% if flt[0] == op[0] %} selected="selected"{% endif %}>{{ op[1] }}</option>
{% endfor %}
</select>
</td>
<td>
{%- set data = filter_data.get(flt[0]) -%}
{%- if data -%}
<select name="flt{{ i }}_{{ flt[0] }}" class="filter-val" data-role="select2">
{%- for d in data %}
<option value="{{ d[0] }}"{% if flt[1] == d[0] %} selected{% endif %}>{{ d[1] }}</option>
{%- endfor %}
</select>
{%- else -%}
<input name="flt{{ i }}_{{ flt[0] }}" type="text" value="{{ flt[1] or '' }}" class="filter-val"{% if flt[0] in filter_types %} data-role="{{ filter_types[flt[0]] }}"{% endif %}></input>
{%- endif -%}
</td>
</tr>
{% endfor %}
</div>
</table>
</form>
<div class="clearfix"></div>
{% endmacro %}
{% macro search_form(input_class="search-query span2") %}
......
......@@ -43,6 +43,7 @@
{% if filter_groups %}
{{ model_layout.filter_form() }}
<div class="clearfix"></div>
{% endif %}
{% block model_list_table %}
......
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