Commit 3f735f52 authored by Paul Brown's avatar Paul Brown

add read-only details view, move modals to their own templates

parent 45d6d626
...@@ -89,6 +89,12 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -89,6 +89,12 @@ class BaseModelView(BaseView, ActionsMixin):
can_delete = True can_delete = True
"""Is model deletion allowed""" """Is model deletion allowed"""
can_view_details = False
"""
Setting this to true will enable the details view. This is recommended
when there are too many columns to display in the list_view.
"""
# Templates # Templates
list_template = 'admin/model/list.html' list_template = 'admin/model/list.html'
"""Default list view template""" """Default list view template"""
...@@ -99,6 +105,19 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -99,6 +105,19 @@ class BaseModelView(BaseView, ActionsMixin):
create_template = 'admin/model/create.html' create_template = 'admin/model/create.html'
"""Default create template""" """Default create template"""
details_template = 'admin/model/details.html'
"""Default details view template"""
# Modal Templates
edit_modal_template = 'admin/model/modals/edit.html'
"""Default edit modal template"""
create_modal_template = 'admin/model/modals/create.html'
"""Default create modal template"""
details_modal_template = 'admin/model/modals/details.html'
"""Default details modal view template"""
# Modals # Modals
edit_modal = False edit_modal = False
"""Setting this to true will display the edit_view as a modal dialog.""" """Setting this to true will display the edit_view as a modal dialog."""
...@@ -106,6 +125,9 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -106,6 +125,9 @@ class BaseModelView(BaseView, ActionsMixin):
create_modal = False create_modal = False
"""Setting this to true will display the create_view as a modal dialog.""" """Setting this to true will display the create_view as a modal dialog."""
details_modal = False
"""Setting this to true will display the details_view as a modal dialog."""
# Customizations # Customizations
column_list = ObsoleteAttr('column_list', 'list_columns', None) column_list = ObsoleteAttr('column_list', 'list_columns', None)
""" """
...@@ -129,6 +151,17 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -129,6 +151,17 @@ class BaseModelView(BaseView, ActionsMixin):
column_exclude_list = ('last_name', 'email') column_exclude_list = ('last_name', 'email')
""" """
column_details_list = None
"""
Collection of the field names included in the details view.
If set to `None`, will get them from the model.
"""
details_exclude_list = None
"""
Collection of fields excluded from the details view.
"""
column_formatters = ObsoleteAttr('column_formatters', 'list_formatters', dict()) column_formatters = ObsoleteAttr('column_formatters', 'list_formatters', dict())
""" """
Dictionary of list view column formatters. Dictionary of list view column formatters.
...@@ -670,6 +703,10 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -670,6 +703,10 @@ class BaseModelView(BaseView, ActionsMixin):
self._list_columns = self.get_list_columns() self._list_columns = self.get_list_columns()
self._sortable_columns = self.get_sortable_columns() self._sortable_columns = self.get_sortable_columns()
# Details view
if self.can_view_details:
self._details_columns = self.get_details_columns()
# Labels # Labels
if self.column_labels is None: if self.column_labels is None:
self.column_labels = {} self.column_labels = {}
...@@ -755,6 +792,23 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -755,6 +792,23 @@ class BaseModelView(BaseView, ActionsMixin):
return [(c, self.get_column_name(c)) for c in columns] return [(c, self.get_column_name(c)) for c in columns]
def get_details_columns(self):
"""
Returns a list of the model field names in the details view. If
`column_details_list` was set, returns it. Otherwise calls
`scaffold_list_columns` to generate the list from the model.
"""
columns = self.column_details_list
if columns is None:
columns = self.scaffold_list_columns()
# Filter excluded columns
if self.details_exclude_list:
columns = [c for c in columns if c not in self.details_exclude_list]
return [(c, self.get_column_name(c)) for c in columns]
def scaffold_sortable_columns(self): def scaffold_sortable_columns(self):
""" """
Returns dictionary of sortable columns. Must be implemented in Returns dictionary of sortable columns. Must be implemented in
...@@ -1608,11 +1662,15 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1608,11 +1662,15 @@ class BaseModelView(BaseView, ActionsMixin):
form_opts = FormOpts(widget_args=self.form_widget_args, form_opts = FormOpts(widget_args=self.form_widget_args,
form_rules=self._form_create_rules) form_rules=self._form_create_rules)
return self.render(self.create_template, if request.args.get('modal'):
template = self.create_modal_template
else:
template = self.create_template
return self.render(template,
form=form, form=form,
form_opts=form_opts, form_opts=form_opts,
return_url=return_url, return_url=return_url)
modal=request.args.get('modal'))
@expose('/edit/', methods=('GET', 'POST')) @expose('/edit/', methods=('GET', 'POST'))
def edit_view(self): def edit_view(self):
...@@ -1631,6 +1689,7 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1631,6 +1689,7 @@ class BaseModelView(BaseView, ActionsMixin):
model = self.get_one(id) model = self.get_one(id)
if model is None: if model is None:
flash(gettext('Record does not exist.'))
return redirect(return_url) return redirect(return_url)
form = self.edit_form(obj=model) form = self.edit_form(obj=model)
...@@ -1651,12 +1710,48 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1651,12 +1710,48 @@ class BaseModelView(BaseView, ActionsMixin):
form_opts = FormOpts(widget_args=self.form_widget_args, form_opts = FormOpts(widget_args=self.form_widget_args,
form_rules=self._form_edit_rules) form_rules=self._form_edit_rules)
return self.render(self.edit_template, if request.args.get('modal'):
template = self.edit_modal_template
else:
template = self.edit_template
return self.render(template,
model=model, model=model,
form=form, form=form,
form_opts=form_opts, form_opts=form_opts,
return_url=return_url, return_url=return_url)
modal=request.args.get('modal'))
@expose('/details/')
def details_view(self):
"""
Details model view
"""
return_url = get_redirect_target() or self.get_url('.index_view')
if not self.can_view_details:
return redirect(return_url)
id = get_mdict_item_or_list(request.args, 'id')
if id is None:
return redirect(return_url)
model = self.get_one(id)
if model is None:
flash(gettext('Record does not exist.'))
return redirect(return_url)
if request.args.get('modal'):
template = self.details_modal_template
else:
template = self.details_template
return self.render(template,
model=model,
details_columns=self._details_columns,
get_value=self.get_list_value,
get_pk_value=self.get_pk_value,
return_url=return_url)
@expose('/delete/', methods=('POST',)) @expose('/delete/', methods=('POST',))
def delete_view(self): def delete_view(self):
...@@ -1677,6 +1772,7 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1677,6 +1772,7 @@ class BaseModelView(BaseView, ActionsMixin):
model = self.get_one(id) model = self.get_one(id)
if model is None: if model is None:
flash(gettext('Record does not exist.'))
return redirect(return_url) return redirect(return_url)
# message is flashed from within delete_model if it fails # message is flashed from within delete_model if it fails
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
width: 14px; width: 14px;
} }
/* List View - prevent word wrap on buttons column, to keep it on one line */
.list-buttons-column {
white-space: nowrap;
}
/* List View - fix gap between actions and table */ /* List View - fix gap between actions and table */
.model-list { .model-list {
position: relative; position: relative;
......
...@@ -11,10 +11,13 @@ ...@@ -11,10 +11,13 @@
line-height: normal; line-height: normal;
} }
.model-list a.icon:first-child {
margin-left: 10px;
}
/* List View - prevent link icons from differing from trash icon */ /* List View - prevent link icons from differing from trash icon */
.model-list a.icon { .model-list a.icon {
text-decoration: none; text-decoration: none;
margin-left: 10px;
color: inherit; color: inherit;
} }
...@@ -89,3 +92,9 @@ body.modal-open { ...@@ -89,3 +92,9 @@ body.modal-open {
overflow-y: scroll; overflow-y: scroll;
padding-right: 0 !important; padding-right: 0 !important;
} }
/* Details View - add space between navbar and results */
.fa_filter_container {
margin-top: 20px;
margin-bottom: 10px;
}
// fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() {
$(this).removeData('modal');
});
// fixes "remote modal shows same content every time", avoiding the flicker
$('body').on('hidden.bs.modal', '.modal', function () {
$(this).removeData('bs.modal').find(".modal-content").empty();
});
// filters the details table based on input
$(document).ready(function () {
$('#fa_filter').keyup(function () {
var rex = new RegExp($(this).val(), 'i');
$('.searchable tr').hide();
$('.searchable tr').filter(function () {
return rex.test($(this).text());
}).show();
});
});
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
{% block head_css %} {% block head_css %}
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap.css', v='2.3.2') }}" rel="stylesheet"> <link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap.css', v='2.3.2') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap-responsive.css', v='2.3.2') }}" rel="stylesheet"> <link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap-responsive.css', v='2.3.2') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/bootstrap2/admin.css', v='1.1.0') }}" rel="stylesheet"> <link href="{{ admin_static.url(filename='admin/css/bootstrap2/admin.css', v='1.1.1') }}" rel="stylesheet">
<style> <style>
body { body {
padding-top: 4px; padding-top: 4px;
......
{%- if not modal -%} {% extends 'admin/master.html' %}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% macro extra() %} {% macro extra() %}
...@@ -8,17 +6,11 @@ ...@@ -8,17 +6,11 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if modal -%}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
action=request.url, is_modal=True) }}
{%- else -%}
{% block navlinks %} {% block navlinks %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li> <li>
...@@ -31,27 +23,9 @@ ...@@ -31,27 +23,9 @@
{% endblock %} {% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts=form_opts) }} {{ lib.render_form(form, return_url, extra(), form_opts=form_opts) }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if modal -%}
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{% block header_text %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}');
// fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() {
$(this).removeData('modal');
});
$(function() {
// Apply flask-admin global styles after the modal is loaded
window.faForm.applyGlobalStyles(document);
});
</script>
{%- else -%}
{{ super() }} {{ super() }}
{{ lib.form_js() }} {{ lib.form_js() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
{% block navlinks %}
<ul class="nav nav-tabs">
<li>
<a href="{{ return_url }}">{{ _gettext('List') }}</a>
</li>
<li>
<a href="{{ get_url('.create_view', url=return_url) }}">{{ _gettext('Create') }}</a>
</li>
<li class="active">
<a href="javascript:void(0)">{{ _gettext('View Record') }}</a>
</li>
</ul>
{% endblock %}
{% block details_search %}
<div class="row-fluid">
<div class="input-prepend fa_filter_container">
<span class="add-on">{{ _gettext('Filter') }}</span>
<input id="fa_filter" id="prependedInput" type="text">
</div>
</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 %}
<script src="{{ admin_static.url(filename='admin/js/details_filter.js', v='1.0.0') }}"></script>
{% endblock %}
{%- if not modal -%} {% extends 'admin/master.html' %}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% macro extra() %} {% macro extra() %}
...@@ -8,18 +6,11 @@ ...@@ -8,18 +6,11 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if modal -%}
{# remove save and continue button for modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
action=request.url, is_modal=True) }}
{%- else -%}
{% block navlinks %} {% block navlinks %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li> <li>
...@@ -35,29 +26,9 @@ ...@@ -35,29 +26,9 @@
{% endblock %} {% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts) }} {{ lib.render_form(form, return_url, extra(), form_opts) }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if modal -%}
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{% block header_text -%}
{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}
{%- endblock %}');
// fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() {
$(this).removeData('modal');
});
$(function() {
// Apply flask-admin global styles after the modal is loaded
window.faForm.applyGlobalStyles(document);
});
</script>
{%- else -%}
{{ super() }} {{ super() }}
{{ lib.form_js() }} {{ lib.form_js() }}
{%- endif -%}
{% endblock %} {% endblock %}
...@@ -104,8 +104,17 @@ ...@@ -104,8 +104,17 @@
</td> </td>
{% endif %} {% endif %}
{% block list_row_actions_column scoped %} {% block list_row_actions_column scoped %}
<td> <td class="list-buttons-column">
{% block list_row_actions scoped %} {% block list_row_actions scoped %}
{%- if admin_view.can_view_details -%}
{%- if admin_view.details_modal -%}
{{ lib.add_modal_button(url=get_url('.details_view', id=get_pk_value(row), url=return_url, modal=True), title=_gettext('View Record'), content='<span class="fa fa-eye glyphicon icon-eye-open"></span>') }}
{% else %}
<a class="icon" href="{{ get_url('.details_view', id=get_pk_value(row), url=return_url) }}" title="{{ _gettext('View Record') }}">
<span class="fa fa-eye icon-eye-open"></span>
</a>
{%- endif -%}
{%- endif -%}
{%- if admin_view.can_edit -%} {%- if admin_view.can_edit -%}
{%- if admin_view.edit_modal -%} {%- if admin_view.edit_modal -%}
{{ lib.add_modal_button(url=get_url('.edit_view', id=get_pk_value(row), url=return_url, modal=True), title=_gettext('Edit record'), content='<i class="fa fa-pencil icon-pencil"></i>') }} {{ lib.add_modal_button(url=get_url('.edit_view', id=get_pk_value(row), url=return_url, modal=True), title=_gettext('Edit record'), content='<i class="fa fa-pencil icon-pencil"></i>') }}
...@@ -171,7 +180,7 @@ ...@@ -171,7 +180,7 @@
{{ actionlib.form(actions, get_url('.action_view')) }} {{ actionlib.form(actions, get_url('.action_view')) }}
{%- if admin_view.edit_modal or admin_view.create_modal -%} {%- if admin_view.edit_modal or admin_view.create_modal or admin_view.details_modal -%}
{{ lib.add_modal_window() }} {{ lib.add_modal_window() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
......
{% import 'admin/static.html' as admin_static with context%}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
{# "save and continue" button is removed from modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
action=url_for('.create_view', url=return_url),
is_modal=True) }}
{% endblock %}
{% block tail %}
<script src="{{ admin_static.url(filename='admin/js/bs2_modal.js', v='1.0.0') }}"></script>
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{% block header_text -%}
<h3>{{ _gettext('Create New Record') }}</h3>
{%- endblock %}');
$(function() {
// Apply flask-admin form styles after the modal is loaded
window.faForm.applyGlobalStyles(document);
});
</script>
{% endblock %}
{% import 'admin/static.html' as admin_static with context%}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
{% block details_search %}
<div class="row-fluid">
<div class="input-prepend fa_filter_container">
<span class="add-on">{{ _gettext('Filter') }}</span>
<input id="fa_filter" id="prependedInput" type="text">
</div>
</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 %}
<script src="{{ admin_static.url(filename='admin/js/details_filter.js', v='1.0.0') }}"></script>
<script src="{{ admin_static.url(filename='admin/js/bs2_modal.js', v='1.0.0') }}"></script>
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{% block header_text -%}
{{ _gettext('View Record') + ' #' + request.args.get('id') }}
{%- endblock %}');
</script>
{% endblock %}
{% import 'admin/static.html' as admin_static with context%}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
{# "save and continue" button is removed from modal (it won't function properly) #}
{{ 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 %}
{% block tail %}
<script src="{{ admin_static.url(filename='admin/js/bs2_modal.js', v='1.0.0') }}"></script>
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{% block header_text -%}
{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}
{%- endblock %}');
$(function() {
// Apply flask-admin form styles after the modal is loaded
window.faForm.applyGlobalStyles(document);
});
</script>
{% endblock %}
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
{% block head_css %} {% block head_css %}
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap.min.css', v='3.3.5') }}" rel="stylesheet"> <link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap.min.css', v='3.3.5') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap-theme.min.css', v='3.3.5') }}" rel="stylesheet"> <link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap-theme.min.css', v='3.3.5') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css', v='1.1.0') }}" rel="stylesheet"> <link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css', v='1.1.1') }}" rel="stylesheet">
<style> <style>
body { body {
padding-top: 4px; padding-top: 4px;
......
{%- if not modal -%} {% extends 'admin/master.html' %}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% macro extra() %} {% macro extra() %}
<input name="_add_another" type="submit" class="btn btn-large" value="{{ _gettext('Save and Add') }}" /> <input name="_add_another" type="submit" class="btn btn-default" value="{{ _gettext('Save and Add') }}" />
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if modal -%}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% block header_text %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}
</div>
<div class="modal-body">
{# remove save and continue button for modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra(), form_opts=form_opts,
action=request.url, is_modal=True) }}
</div>
{%- else -%}
{% block navlinks %} {% block navlinks %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li> <li>
...@@ -38,24 +23,9 @@ ...@@ -38,24 +23,9 @@
{% endblock %} {% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts=form_opts) }} {{ lib.render_form(form, return_url, extra(), form_opts=form_opts) }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if modal -%}
<script>
// fixes "remote modal shows same content every time", avoiding the flicker
$('body').on('hidden.bs.modal', '.modal', function () {
$(this).removeData('bs.modal').find(".modal-content").empty();
});
$(function() {
// Apply flask-admin global styles after the modal is loaded
window.faForm.applyGlobalStyles(document);
});
</script>
{%- else -%}
{{ super() }} {{ super() }}
{{ lib.form_js() }} {{ lib.form_js() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% extends 'admin/master.html' %}
{% import 'admin/lib.html' as lib with context %}
{% block body %}
{% block navlinks %}
<ul class="nav nav-tabs">
<li>
<a href="{{ return_url }}">{{ _gettext('List') }}</a>
</li>
<li>
<a href="{{ get_url('.create_view', url=return_url) }}">{{ _gettext('Create') }}</a>
</li>
<li class="active">
<a href="javascript:void(0)">{{ _gettext('View Record') }}</a>
</li>
</ul>
{% endblock %}
{% block details_search %}
<div class="input-group fa_filter_container col-lg-6">
<span class="input-group-addon">{{ _gettext('Filter') }}</span>
<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 %}
<script src="{{ admin_static.url(filename='admin/js/details_filter.js', v='1.0.0') }}"></script>
{% endblock %}
{%- if not modal -%} {% extends 'admin/master.html' %}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% macro extra() %} {% macro extra() %}
...@@ -8,27 +6,11 @@ ...@@ -8,27 +6,11 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if modal -%}
{# content added to modal-content #}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% block header_text %}
<h3>{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}</h3>
{% endblock %}
</div>
<div class="modal-body">
{# remove save and continue button for modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
action=request.url, is_modal=True) }}
</div>
{%- else -%}
{% block navlinks %} {% block navlinks %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li> <li>
...@@ -44,24 +26,9 @@ ...@@ -44,24 +26,9 @@
{% endblock %} {% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts) }} {{ lib.render_form(form, return_url, extra(), form_opts) }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if modal -%}
<script>
// fixes "remote modal shows same content every time", avoiding the flicker
$('body').on('hidden.bs.modal', '.modal', function () {
$(this).removeData('bs.modal').find(".modal-content").empty();
});
$(function() {
// Apply flask-admin global styles after the modal is loaded
window.faForm.applyGlobalStyles(document);
});
</script>
{%- else -%}
{{ super() }} {{ super() }}
{{ lib.form_js() }} {{ lib.form_js() }}
{%- endif -%}
{% endblock %} {% endblock %}
...@@ -104,8 +104,17 @@ ...@@ -104,8 +104,17 @@
</td> </td>
{% endif %} {% endif %}
{% block list_row_actions_column scoped %} {% block list_row_actions_column scoped %}
<td> <td class="list-buttons-column">
{% block list_row_actions scoped %} {% block list_row_actions scoped %}
{%- if admin_view.can_view_details -%}
{%- if admin_view.details_modal -%}
{{ lib.add_modal_button(url=get_url('.details_view', id=get_pk_value(row), url=return_url, modal=True), title=_gettext('View Record'), content='<span class="fa fa-eye glyphicon glyphicon-eye-open"></span>') }}
{% else %}
<a class="icon" href="{{ get_url('.details_view', id=get_pk_value(row), url=return_url) }}" title="{{ _gettext('View Record') }}">
<span class="fa fa-eye glyphicon glyphicon-eye-open"></span>
</a>
{%- endif -%}
{%- endif -%}
{%- if admin_view.can_edit -%} {%- if admin_view.can_edit -%}
{%- if admin_view.edit_modal -%} {%- if admin_view.edit_modal -%}
{{ lib.add_modal_button(url=get_url('.edit_view', id=get_pk_value(row), url=return_url, modal=True), title=_gettext('Edit record'), content='<span class="fa fa-pencil glyphicon glyphicon-pencil"></span>') }} {{ lib.add_modal_button(url=get_url('.edit_view', id=get_pk_value(row), url=return_url, modal=True), title=_gettext('Edit record'), content='<span class="fa fa-pencil glyphicon glyphicon-pencil"></span>') }}
...@@ -172,7 +181,7 @@ ...@@ -172,7 +181,7 @@
{{ actionlib.form(actions, get_url('.action_view')) }} {{ actionlib.form(actions, get_url('.action_view')) }}
{% endblock %} {% endblock %}
{%- if admin_view.edit_modal or admin_view.create_modal -%} {%- if admin_view.edit_modal or admin_view.create_modal or admin_view.details_modal -%}
{{ lib.add_modal_window() }} {{ lib.add_modal_window() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
......
{% 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">&times;</span></button>
{% block header_text %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}
</div>
<div class="modal-body">
{# "save and continue" button is removed from modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
action=url_for('.create_view', url=return_url),
is_modal=True) }}
</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 %}
{% 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">&times;</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">
<span class="input-group-addon">{{ _gettext('Filter') }}</span>
<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 %}
{% 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">&times;</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) #}
{{ 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) }}
</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 %}
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