Commit 3499208d authored by Petrus Janse van Rensburg's avatar Petrus Janse van Rensburg

Merge pull request #933 from pawl/add_fileadmin_modals

Add modals to FileAdmin, minor changes to forms
parents 1a883db4 e6baed0c
...@@ -136,6 +136,19 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -136,6 +136,19 @@ class FileAdmin(BaseView, ActionsMixin):
""" """
# Modals
rename_modal = False
"""Setting this to true will display the rename view as a modal dialog."""
upload_modal = False
"""Setting this to true will display the upload view as a modal dialog."""
mkdir_modal = False
"""Setting this to true will display the mkdir view as a modal dialog."""
edit_modal = False
"""Setting this to true will display the edit view as a modal dialog."""
def __init__(self, base_path, base_url=None, def __init__(self, base_path, base_url=None,
name=None, category=None, endpoint=None, url=None, name=None, category=None, endpoint=None, url=None,
verify_path=True, menu_class_name=None, menu_icon_type=None, menu_icon_value=None): verify_path=True, menu_class_name=None, menu_icon_type=None, menu_icon_value=None):
...@@ -422,7 +435,7 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -422,7 +435,7 @@ class FileAdmin(BaseView, ActionsMixin):
Additional arguments Additional arguments
""" """
if not path: if not path:
return self.get_url(endpoint) return self.get_url(endpoint, **kwargs)
else: else:
if self._on_windows: if self._on_windows:
path = path.replace('\\', '/') path = path.replace('\\', '/')
...@@ -431,7 +444,7 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -431,7 +444,7 @@ class FileAdmin(BaseView, ActionsMixin):
return self.get_url(endpoint, **kwargs) return self.get_url(endpoint, **kwargs)
def _get_file_url(self, path): def _get_file_url(self, path, **kwargs):
""" """
Return static file url Return static file url
...@@ -443,7 +456,7 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -443,7 +456,7 @@ class FileAdmin(BaseView, ActionsMixin):
else: else:
route = '.download' route = '.download'
return self.get_url(route, path=path) return self.get_url(route, path=path, **kwargs)
def _normalize_path(self, path): def _normalize_path(self, path):
""" """
...@@ -641,11 +654,15 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -641,11 +654,15 @@ class FileAdmin(BaseView, ActionsMixin):
if self.validate_form(form): if self.validate_form(form):
try: try:
self._save_form_files(directory, path, form) self._save_form_files(directory, path, form)
flash(gettext('Successfully saved file: %(name)s',
name=form.upload.data.filename))
return redirect(self._get_dir_url('.index', path)) return redirect(self._get_dir_url('.index', path))
except Exception as ex: except Exception as ex:
flash(gettext('Failed to save file: %(error)s', error=ex), 'error') flash(gettext('Failed to save file: %(error)s', error=ex), 'error')
return self.render(self.upload_template, form=form) return self.render(self.upload_template, form=form,
header_text=gettext('Upload File'),
modal=request.args.get('modal'))
@expose('/download/<path:path>') @expose('/download/<path:path>')
def download(self, path=None): def download(self, path=None):
...@@ -696,15 +713,17 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -696,15 +713,17 @@ class FileAdmin(BaseView, ActionsMixin):
try: try:
os.mkdir(op.join(directory, form.name.data)) os.mkdir(op.join(directory, form.name.data))
self.on_mkdir(directory, form.name.data) self.on_mkdir(directory, form.name.data)
flash(gettext('Successfully created directory: %(directory)s',
directory=form.name.data))
return redirect(dir_url) return redirect(dir_url)
except Exception as ex: except Exception as ex:
flash(gettext('Failed to create directory: %(error)s', error=ex), 'error') flash(gettext('Failed to create directory: %(error)s', error=ex), 'error')
else: else:
helpers.flash_errors(form, message='Failed to create directory: %(error)s') helpers.flash_errors(form, message='Failed to create directory: %(error)s')
return self.render(self.mkdir_template, return self.render(self.mkdir_template, form=form, dir_url=dir_url,
form=form, header_text=gettext('Create Directory'),
dir_url=dir_url) modal=request.args.get('modal'))
@expose('/delete/', methods=('POST',)) @expose('/delete/', methods=('POST',))
def delete(self): def delete(self):
...@@ -789,8 +808,8 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -789,8 +808,8 @@ class FileAdmin(BaseView, ActionsMixin):
os.rename(full_path, op.join(dir_base, filename)) os.rename(full_path, op.join(dir_base, filename))
self.on_rename(full_path, dir_base, filename) self.on_rename(full_path, dir_base, filename)
flash(gettext('Successfully renamed "%(src)s" to "%(dst)s"', flash(gettext('Successfully renamed "%(src)s" to "%(dst)s"',
src=op.basename(path), src=op.basename(path),
dst=filename)) dst=filename))
except Exception as ex: except Exception as ex:
flash(gettext('Failed to rename: %(error)s', error=ex), 'error') flash(gettext('Failed to rename: %(error)s', error=ex), 'error')
...@@ -802,7 +821,8 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -802,7 +821,8 @@ class FileAdmin(BaseView, ActionsMixin):
form=form, form=form,
path=op.dirname(path), path=op.dirname(path),
name=op.basename(path), name=op.basename(path),
dir_url=return_url) dir_url=return_url,
modal=request.args.get('modal'))
@expose('/edit/', methods=('GET', 'POST')) @expose('/edit/', methods=('GET', 'POST'))
def edit(self): def edit(self):
...@@ -870,7 +890,8 @@ class FileAdmin(BaseView, ActionsMixin): ...@@ -870,7 +890,8 @@ class FileAdmin(BaseView, ActionsMixin):
form.content.data = content form.content.data = content
return self.render(self.edit_template, dir_url=dir_url, path=path, return self.render(self.edit_template, dir_url=dir_url, path=path,
form=form, error=error) form=form, error=error,
modal=request.args.get('modal'))
@expose('/action/', methods=('POST',)) @expose('/action/', methods=('POST',))
def action_view(self): def action_view(self):
......
...@@ -1611,7 +1611,8 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1611,7 +1611,8 @@ class BaseModelView(BaseView, ActionsMixin):
return self.render(self.create_template, return self.render(self.create_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):
...@@ -1654,7 +1655,8 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1654,7 +1655,8 @@ class BaseModelView(BaseView, ActionsMixin):
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('/delete/', methods=('POST',)) @expose('/delete/', methods=('POST',))
def delete_view(self): def delete_view(self):
......
{% extends 'admin/master.html' %} {%- if not modal -%}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% block body %} {% macro check_error(error) %}
<h3>{{ _gettext('You are editing %(path)s', path=path) }}</h3>
{% if error %} {% if error %}
<span>This file cannot be edited for now.</span> <span>{{ _gettext('This file cannot be edited for now.') }}</span>
{% else %} {% else %}
{{ lib.render_form(form, dir_url) }} {{ caller() }}
{% endif %} {% endif %}
{% endmacro %}
{% block body %}
{% call check_error(error) %}
{%- if modal -%}
{# content added to modal-content #}
{{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
{%- else -%}
{% block header_text -%}
<h3>{{ _gettext('Editing %(path)s', path=path) }}<h3>
{%- endblock %}
{{ lib.render_form(form, dir_url) }}
{%- endif -%}
{% endcall %}
{% endblock %}
{% block tail %}
{%- if modal -%}
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{{ self.header_text() }}');
// fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() {
$(this).removeData('modal');
});
</script>
{%- endif -%}
{% endblock %} {% endblock %}
{% extends 'admin/master.html' %} {%- if not modal -%}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% block body %} {% block body %}
{{ lib.render_form(form, dir_url) }} {%- if modal -%}
{% endblock %} {{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
\ No newline at end of file {%- else -%}
<h3>{{ header_text }}</h3>
{{ lib.render_form(form, dir_url) }}
{%- endif -%}
{% endblock %}
{% block tail %}
{%- if modal -%}
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{{ header_text }}');
// fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() {
$(this).removeData('modal');
});
</script>
{%- endif -%}
{% endblock %}
...@@ -50,9 +50,15 @@ ...@@ -50,9 +50,15 @@
<td> <td>
{% block list_row_actions scoped %} {% block list_row_actions scoped %}
{% if admin_view.can_rename and path and name != '..' %} {% if admin_view.can_rename and path and name != '..' %}
<a class="icon" href="{{ get_url('.rename', path=path) }}"> {%- if admin_view.rename_modal -%}
<i class="fa fa-pencil icon-pencil"></i> {{ lib.add_modal_button(url=get_url('.rename', path=path, modal=True),
</a> title=_gettext('Rename File'),
content='<i class="fa fa-pencil icon-pencil"></i>') }}
{% else %}
<a class="icon" href="{{ get_url('.rename', path=path) }}" title="{{ _gettext('Rename File') }}">
<i class="fa fa-pencil icon-pencil"></i>
</a>
{%- endif -%}
{% endif %} {% endif %}
{%- if admin_view.can_delete and path -%} {%- if admin_view.can_delete and path -%}
{% if is_dir %} {% if is_dir %}
...@@ -86,9 +92,14 @@ ...@@ -86,9 +92,14 @@
{% else %} {% else %}
<td> <td>
{% if admin_view.can_download %} {% if admin_view.can_download %}
<a href="{{ get_file_url(path)|safe }}">{{ name }}</a> {%- if admin_view.edit_modal and admin_view.is_file_editable(path) -%}
{{ lib.add_modal_button(url=get_file_url(path, modal=True)|safe,
btn_class='', content=name) }}
{% else %}
<a href="{{ get_file_url(path)|safe }}">{{ name }}</a>
{%- endif -%}
{% else %} {% else %}
{{ name }} {{ name }}
{% endif %} {% endif %}
</td> </td>
<td> <td>
...@@ -104,12 +115,24 @@ ...@@ -104,12 +115,24 @@
<div class="btn-toolbar"> <div class="btn-toolbar">
{% if admin_view.can_upload %} {% if admin_view.can_upload %}
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-large" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a> {%- if admin_view.upload_modal -%}
{{ lib.add_modal_button(url=get_dir_url('.upload', path=dir_path, modal=True),
btn_class="btn btn-large",
content=_gettext('Upload File')) }}
{% else %}
<a class="btn btn-large" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a>
{%- endif -%}
</div> </div>
{% endif %} {% endif %}
{% if admin_view.can_mkdir %} {% if admin_view.can_mkdir %}
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-large" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a> {%- if admin_view.mkdir_modal -%}
{{ lib.add_modal_button(url=get_dir_url('.mkdir', path=dir_path, modal=True),
btn_class="btn btn-large",
content=_gettext('Create Directory')) }}
{% else %}
<a class="btn btn-large" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a>
{%- endif -%}
</div> </div>
{% endif %} {% endif %}
{% if actions %} {% if actions %}
...@@ -119,14 +142,20 @@ ...@@ -119,14 +142,20 @@
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}
{% block actions %} {% block actions %}
{{ actionslib.form(actions, get_url('.action_view')) }} {{ actionslib.form(actions, get_url('.action_view')) }}
{% endblock %} {% endblock %}
{%- if admin_view.rename_modal or admin_view.mkdir_modal
or admin_view.upload_modal or admin_view.edit_modal -%}
{{ lib.add_modal_window() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{{ super() }} {{ super() }}
{{ actionslib.script(_gettext('Please select at least one file.'), {{ actionslib.script(_gettext('Please select at least one file.'),
actions, actions,
actions_confirmation) }} actions_confirmation) }}
{% endblock %} {% endblock %}
{% extends 'admin/master.html' %} {%- if not modal -%}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% block body %} {% block body %}
<h3>{{ _gettext('Please provide new name for %(name)s', name=name) }}</h3> {%- if modal -%}
{# content added to modal-content #}
{{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
{%- else -%}
<h3>{% block header_text -%}
{{ _gettext('Rename %(name)s', name=name) }}
{%- endblock %}</h3>
{{ lib.render_form(form, dir_url) }} {{ lib.render_form(form, dir_url) }}
{% endblock %} {%- endif -%}
\ No newline at end of file {% endblock %}
{% block tail %}
{%- if modal -%}
<script>
// fill the header of modal dynamically
$('.modal-header h3').html('{{ self.header_text() }}');
// fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() {
$(this).removeData('modal');
});
</script>
{%- endif -%}
{% endblock %}
...@@ -113,8 +113,8 @@ ...@@ -113,8 +113,8 @@
</div> </div>
{% endmacro %} {% endmacro %}
{% macro add_modal_button(url='', title='', content='', modal_window_id='fa_modal_window') %} {% macro add_modal_button(url='', title='', content='', modal_window_id='fa_modal_window', btn_class='icon') %}
<a class="icon" href="#" data-toggle="modal" title="{{ title }}" data-target="#{{ modal_window_id }}" data-remote="{{ url }}"> <a class="{{ btn_class }}" href="#" data-toggle="modal" title="{{ title }}" data-target="#{{ modal_window_id }}" data-remote="{{ url }}">
{{ content|safe }} {{ content|safe }}
</a> </a>
{% endmacro %} {% endmacro %}
......
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{% extends 'admin/master.html' %} {% extends 'admin/master.html' %}
{%- endif -%} {%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
...@@ -8,17 +8,16 @@ ...@@ -8,17 +8,16 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if request.args.get('modal') -%} {%- if modal -%}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts, {{ lib.render_form(form, return_url, extra=None, form_opts=form_opts,
action=url_for('.create_view', url=return_url), action=request.url, is_modal=True) }}
is_modal=request.args.get('modal')) }}
{%- else -%} {%- else -%}
{% block navlinks %} {% block navlinks %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
...@@ -31,17 +30,15 @@ ...@@ -31,17 +30,15 @@
</ul> </ul>
{% endblock %} {% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts=form_opts, {{ lib.render_form(form, return_url, extra(), form_opts=form_opts) }}
action=url_for('.create_view', url=return_url),
is_modal=request.args.get('modal')) }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if request.args.get('modal') -%} {%- if modal -%}
<script> <script>
// fill the header of modal dynamically // fill the header of modal dynamically
$('.modal-header h3').html('{% block modal_header %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}'); $('.modal-header h3').html('{% block header_text %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}');
// fixes "remote modal shows same content every time" // fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() { $('.modal').on('hidden', function() {
......
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{% extends 'admin/master.html' %} {% extends 'admin/master.html' %}
{%- endif -%} {%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
...@@ -8,30 +8,43 @@ ...@@ -8,30 +8,43 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if request.args.get('modal') -%} {%- if modal -%}
{# remove save and continue button for modal (it won't function properly) #} {# remove save and continue button for modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts, {{ 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), action=request.url, is_modal=True) }}
is_modal=request.args.get('modal')) }}
{%- else -%} {%- else -%}
{{ lib.render_form(form, return_url, extra(), form_opts, {% block navlinks %}
action=url_for('.edit_view', id=request.args.get('id'), url=return_url), <ul class="nav nav-tabs">
is_modal=request.args.get('modal')) }} <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('Edit') }}</a>
</li>
</ul>
{% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts) }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if request.args.get('modal') -%} {%- if modal -%}
<script> <script>
// fill the header of modal dynamically // fill the header of modal dynamically
$('.modal-header h3').html('{% block modal_header %}<h3>{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}</h3>{% endblock %}'); $('.modal-header h3').html('{% block header_text -%}
{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}
{%- endblock %}');
// fixes "remote modal shows same content every time" // fixes "remote modal shows same content every time"
$('.modal').on('hidden', function() { $('.modal').on('hidden', function() {
...@@ -47,4 +60,4 @@ ...@@ -47,4 +60,4 @@
{{ super() }} {{ super() }}
{{ lib.form_js() }} {{ lib.form_js() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
\ No newline at end of file
{% extends 'admin/master.html' %} {%- if not modal -%}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% block body %} {% macro check_error(error) %}
<h3>{{ _gettext('You are editing %(path)s', path=path) }}</h3>
{% if error %} {% if error %}
<span>This file cannot be edited for now.</span> <span>{{ _gettext('This file cannot be edited for now.') }}</span>
{% else %} {% else %}
{{ lib.render_form(form, dir_url) }} {{ caller() }}
{% endif %} {% endif %}
{% endmacro %}
{% 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('Editing %(path)s', path=path) }}</h3>
{% endblock %}
</div>
<div class="modal-body">
{% call check_error(error) %}
{{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
{% endcall %}
</div>
{%- else -%}
{{ self.header_text() }}
{% call check_error(error) %}
{{ lib.render_form(form, dir_url) }}
{% endcall %}
{%- endif -%}
{% endblock %}
{% 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();
});
</script>
{%- endif -%}
{% endblock %} {% endblock %}
{% extends 'admin/master.html' %} {%- if not modal -%}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% block body %} {% block body %}
{{ lib.render_form(form, dir_url) }} {%- if modal -%}
{% endblock %} {# content added to modal-content #}
\ No newline at end of file <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h3>{{ header_text }}</h3>
</div>
<div class="modal-body">
{{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
</div>
{%- else -%}
<h3>{{ header_text }}</h3>
{{ lib.render_form(form, dir_url) }}
{%- endif -%}
{% endblock %}
{% 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();
});
</script>
{%- endif -%}
{% endblock %}
...@@ -50,9 +50,15 @@ ...@@ -50,9 +50,15 @@
<td> <td>
{% block list_row_actions scoped %} {% block list_row_actions scoped %}
{% if admin_view.can_rename and path and name != '..' %} {% if admin_view.can_rename and path and name != '..' %}
<a class="icon" href="{{ get_url('.rename', path=path) }}"> {%- if admin_view.rename_modal -%}
<i class="fa fa-pencil glyphicon glyphicon-pencil"></i> {{ lib.add_modal_button(url=get_url('.rename', path=path, modal=True),
</a> title=_gettext('Rename File'),
content='<i class="fa fa-pencil glyphicon glyphicon-pencil"></i>') }}
{% else %}
<a class="icon" href="{{ get_url('.rename', path=path) }}" title="{{ _gettext('Rename File') }}">
<i class="fa fa-pencil glyphicon glyphicon-pencil"></i>
</a>
{%- endif -%}
{% endif %} {% endif %}
{%- if admin_view.can_delete and path -%} {%- if admin_view.can_delete and path -%}
{% if is_dir %} {% if is_dir %}
...@@ -86,9 +92,14 @@ ...@@ -86,9 +92,14 @@
{% else %} {% else %}
<td> <td>
{% if admin_view.can_download %} {% if admin_view.can_download %}
<a href="{{ get_file_url(path)|safe }}">{{ name }}</a> {%- if admin_view.edit_modal and admin_view.is_file_editable(path) -%}
{{ lib.add_modal_button(url=get_file_url(path, modal=True)|safe,
btn_class='', content=name) }}
{% else %}
<a href="{{ get_file_url(path)|safe }}">{{ name }}</a>
{%- endif -%}
{% else %} {% else %}
{{ name }} {{ name }}
{% endif %} {% endif %}
</td> </td>
<td> <td>
...@@ -104,12 +115,24 @@ ...@@ -104,12 +115,24 @@
<div class="btn-toolbar"> <div class="btn-toolbar">
{% if admin_view.can_upload %} {% if admin_view.can_upload %}
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-default btn-large" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a> {%- if admin_view.upload_modal -%}
{{ lib.add_modal_button(url=get_dir_url('.upload', path=dir_path, modal=True),
btn_class="btn btn-default btn-large",
content=_gettext('Upload File')) }}
{% else %}
<a class="btn btn-default btn-large" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a>
{%- endif -%}
</div> </div>
{% endif %} {% endif %}
{% if admin_view.can_mkdir %} {% if admin_view.can_mkdir %}
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-default btn-large" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a> {%- if admin_view.mkdir_modal -%}
{{ lib.add_modal_button(url=get_dir_url('.mkdir', path=dir_path, modal=True),
btn_class="btn btn-default btn-large",
content=_gettext('Create Directory')) }}
{% else %}
<a class="btn btn-default btn-large" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a>
{%- endif -%}
</div> </div>
{% endif %} {% endif %}
{% if actions %} {% if actions %}
...@@ -119,14 +142,20 @@ ...@@ -119,14 +142,20 @@
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}
{% block actions %} {% block actions %}
{{ actionslib.form(actions, get_url('.action_view')) }} {{ actionslib.form(actions, get_url('.action_view')) }}
{% endblock %} {% endblock %}
{%- if admin_view.rename_modal or admin_view.mkdir_modal
or admin_view.upload_modal or admin_view.edit_modal -%}
{{ lib.add_modal_window() }}
{%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{{ super() }} {{ super() }}
{{ actionslib.script(_gettext('Please select at least one file.'), {{ actionslib.script(_gettext('Please select at least one file.'),
actions, actions,
actions_confirmation) }} actions_confirmation) }}
{% endblock %} {% endblock %}
{% extends 'admin/master.html' %} {%- if not modal -%}
{% extends 'admin/master.html' %}
{%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
{% block body %} {% block body %}
<h3>{{ _gettext('Please provide new name for %(name)s', name=name) }}</h3> {%- if modal -%}
{{ lib.render_form(form, dir_url) }} {# content added to modal-content #}
{% endblock %} <div class="modal-header">
\ No newline at end of file <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% block header_text %}
<h3>{{ _gettext('Rename %(name)s', name=name) }}</h3>
{% endblock %}
</div>
<div class="modal-body">
{{ lib.render_form(form, dir_url, action=request.url, is_modal=True) }}
</div>
{%- else -%}
<h3>{{ self.header_text() }}</h3>
{{ lib.render_form(form, dir_url) }}
{%- endif -%}
{% endblock %}
{% 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();
});
</script>
{%- endif -%}
{% endblock %}
...@@ -108,8 +108,8 @@ ...@@ -108,8 +108,8 @@
</div> </div>
{% endmacro %} {% endmacro %}
{% macro add_modal_button(url='', title='', content='', modal_window_id='fa_modal_window') %} {% macro add_modal_button(url='', title='', content='', modal_window_id='fa_modal_window', btn_class='icon') %}
<a class="icon" data-target="#{{ modal_window_id }}" title="{{ title }}" href="{{ url }}" data-toggle="modal"> <a class="{{ btn_class }}" data-target="#{{ modal_window_id }}" title="{{ title }}" href="{{ url }}" data-toggle="modal">
{{ content|safe }} {{ content|safe }}
</a> </a>
{% endmacro %} {% endmacro %}
......
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{% extends 'admin/master.html' %} {% extends 'admin/master.html' %}
{%- endif -%} {%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
...@@ -8,23 +8,22 @@ ...@@ -8,23 +8,22 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if request.args.get('modal') -%} {%- if modal -%}
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% block modal_header %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %} {% block header_text %}<h3>{{ _gettext('Create New Record') }}</h3>{% endblock %}
</div> </div>
<div class="modal-body"> <div class="modal-body">
{# remove save and continue button for modal (it won't function properly) #} {# remove save and continue button for modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts, {{ lib.render_form(form, return_url, extra(), form_opts=form_opts,
action=url_for('.create_view', url=return_url), action=request.url, is_modal=True) }}
is_modal=request.args.get('modal')) }}
</div> </div>
{%- else -%} {%- else -%}
{% block navlinks %} {% block navlinks %}
...@@ -38,14 +37,12 @@ ...@@ -38,14 +37,12 @@
</ul> </ul>
{% endblock %} {% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts=form_opts, {{ lib.render_form(form, return_url, extra(), form_opts=form_opts) }}
action=url_for('.create_view', url=return_url),
is_modal=request.args.get('modal')) }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if request.args.get('modal') -%} {%- if modal -%}
<script> <script>
// fixes "remote modal shows same content every time", avoiding the flicker // fixes "remote modal shows same content every time", avoiding the flicker
$('body').on('hidden.bs.modal', '.modal', function () { $('body').on('hidden.bs.modal', '.modal', function () {
......
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{% extends 'admin/master.html' %} {% extends 'admin/master.html' %}
{%- endif -%} {%- endif -%}
{% import 'admin/lib.html' as lib with context %} {% import 'admin/lib.html' as lib with context %}
...@@ -8,34 +8,47 @@ ...@@ -8,34 +8,47 @@
{% endmacro %} {% endmacro %}
{% block head %} {% block head %}
{%- if not request.args.get('modal') -%} {%- if not modal -%}
{{ super() }} {{ super() }}
{{ lib.form_css() }} {{ lib.form_css() }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- if request.args.get('modal') -%} {%- if modal -%}
{# content added to modal-content #} {# content added to modal-content #}
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% block modal_header %}<h3>{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}</h3>{% endblock %} {% block header_text %}
<h3>{{ _gettext('Edit Record') + ' #' + request.args.get('id') }}</h3>
{% endblock %}
</div> </div>
<div class="modal-body"> <div class="modal-body">
{# remove save and continue button for modal (it won't function properly) #} {# remove save and continue button for modal (it won't function properly) #}
{{ lib.render_form(form, return_url, extra=None, form_opts=form_opts, {{ 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), action=request.url, is_modal=True) }}
is_modal=request.args.get('modal')) }}
</div> </div>
{%- else -%} {%- else -%}
{{ lib.render_form(form, return_url, extra(), form_opts, {% block navlinks %}
action=url_for('.edit_view', id=request.args.get('id'), url=return_url), <ul class="nav nav-tabs">
is_modal=request.args.get('modal')) }} <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('Edit') }}</a>
</li>
</ul>
{% endblock %}
{{ lib.render_form(form, return_url, extra(), form_opts) }}
{%- endif -%} {%- endif -%}
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}
{%- if request.args.get('modal') -%} {%- if modal -%}
<script> <script>
// fixes "remote modal shows same content every time", avoiding the flicker // fixes "remote modal shows same content every time", avoiding the flicker
$('body').on('hidden.bs.modal', '.modal', function () { $('body').on('hidden.bs.modal', '.modal', function () {
......
...@@ -168,7 +168,9 @@ ...@@ -168,7 +168,9 @@
{% endblock %} {% endblock %}
{% endblock %} {% endblock %}
{% block actions %}
{{ actionlib.form(actions, get_url('.action_view')) }} {{ actionlib.form(actions, get_url('.action_view')) }}
{% endblock %}
{%- if admin_view.edit_modal or admin_view.create_modal -%} {%- if admin_view.edit_modal or admin_view.create_modal -%}
{{ lib.add_modal_window() }} {{ lib.add_modal_window() }}
......
...@@ -3,6 +3,8 @@ import os.path as op ...@@ -3,6 +3,8 @@ import os.path as op
from nose.tools import eq_, ok_ from nose.tools import eq_, ok_
from flask_admin.contrib import fileadmin from flask_admin.contrib import fileadmin
from flask_admin import Admin
from flask import Flask
from . import setup from . import setup
...@@ -131,3 +133,58 @@ def test_file_admin(): ...@@ -131,3 +133,58 @@ def test_file_admin():
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
ok_('path=dummy_renamed_dir' not in rv.data.decode('utf-8')) ok_('path=dummy_renamed_dir' not in rv.data.decode('utf-8'))
ok_('path=dummy.txt' in rv.data.decode('utf-8')) ok_('path=dummy.txt' in rv.data.decode('utf-8'))
def test_modal_edit():
# bootstrap 2 - test edit_modal
app_bs2 = Flask(__name__)
admin_bs2 = Admin(app_bs2, template_mode="bootstrap2")
class EditModalOn(fileadmin.FileAdmin):
edit_modal = True
editable_extensions = ('txt',)
class EditModalOff(fileadmin.FileAdmin):
edit_modal = False
editable_extensions = ('txt',)
path = op.join(op.dirname(__file__), 'files')
edit_modal_on = EditModalOn(path, '/files/', endpoint='edit_modal_on')
edit_modal_off = EditModalOff(path, '/files/', endpoint='edit_modal_off')
admin_bs2.add_view(edit_modal_on)
admin_bs2.add_view(edit_modal_off)
client_bs2 = app_bs2.test_client()
# bootstrap 2 - ensure modal window is added when edit_modal is enabled
rv = client_bs2.get('/admin/edit_modal_on/')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('fa_modal_window' in data)
# bootstrap 2 - test edit modal disabled
rv = client_bs2.get('/admin/edit_modal_off/')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('fa_modal_window' not in data)
# bootstrap 3
app_bs3 = Flask(__name__)
admin_bs3 = Admin(app_bs3, template_mode="bootstrap3")
admin_bs3.add_view(edit_modal_on)
admin_bs3.add_view(edit_modal_off)
client_bs3 = app_bs3.test_client()
# bootstrap 3 - ensure modal window is added when edit_modal is enabled
rv = client_bs3.get('/admin/edit_modal_on/')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('fa_modal_window' in data)
# bootstrap 3 - test modal disabled
rv = client_bs3.get('/admin/edit_modal_off/')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('fa_modal_window' not in data)
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