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