Remove deprecated table.UpdateAction class
UpdateAction is deprecated in Newton and is used in unit-tests only Change-Id: I7952cb77b168cc39f8fc37c3b7ffe0c830d4e0d4
This commit is contained in:
parent
07237c1fc6
commit
f6f39d86da
@ -289,53 +289,6 @@ Example::
|
|||||||
admin=True)
|
admin=True)
|
||||||
return project_info
|
return project_info
|
||||||
|
|
||||||
Updating changed cell data (DEPRECATED)
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
Define an ``update_cell`` method in the class inherited from
|
|
||||||
``tables.UpdateAction``. This method takes care of saving the data of the
|
|
||||||
table cell. There can be one class for every cell thanks to the
|
|
||||||
``cell_name`` parameter. This class is then defined in tables column as
|
|
||||||
``update_action=UpdateCell``, so each column can have its own updating
|
|
||||||
method.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
class UpdateCell(tables.UpdateAction):
|
|
||||||
def allowed(self, request, project, cell):
|
|
||||||
# Determines whether given cell or row will be inline editable
|
|
||||||
# for signed in user.
|
|
||||||
return api.keystone.keystone_can_edit_project()
|
|
||||||
|
|
||||||
def update_cell(self, request, project_id, cell_name, new_cell_value):
|
|
||||||
# in-line update project info
|
|
||||||
try:
|
|
||||||
project_obj = datum
|
|
||||||
# updating changed value by new value
|
|
||||||
setattr(project_obj, cell_name, new_cell_value)
|
|
||||||
|
|
||||||
# sending new attributes back to API
|
|
||||||
api.keystone.tenant_update(
|
|
||||||
request,
|
|
||||||
project_id,
|
|
||||||
name=project_obj.name,
|
|
||||||
description=project_obj.description,
|
|
||||||
enabled=project_obj.enabled)
|
|
||||||
|
|
||||||
except Conflict:
|
|
||||||
# Validation error for naming conflict, raised when user
|
|
||||||
# choose the existing name. We will raise a
|
|
||||||
# ValidationError, that will be sent back to the client
|
|
||||||
# browser and shown inside of the table cell.
|
|
||||||
message = _("This name is already taken.")
|
|
||||||
raise ValidationError(message)
|
|
||||||
except:
|
|
||||||
# Other exception of the API just goes through standard
|
|
||||||
# channel
|
|
||||||
exceptions.handle(request, ignore=True)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
Defining a form_field for each Column that we want to be in-line edited.
|
Defining a form_field for each Column that we want to be in-line edited.
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -285,7 +285,6 @@ classes:
|
|||||||
|
|
||||||
- :class:`~horizon.tables.BatchAction`
|
- :class:`~horizon.tables.BatchAction`
|
||||||
- :class:`~horizon.tables.DeleteAction`
|
- :class:`~horizon.tables.DeleteAction`
|
||||||
- :class:`~horizon.tables.UpdateAction` **DEPRECATED**
|
|
||||||
- :class:`~horizon.tables.FixedFilterAction`
|
- :class:`~horizon.tables.FixedFilterAction`
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,277 +0,0 @@
|
|||||||
/**
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
* not use this file except in compliance with the License. You may obtain
|
|
||||||
* a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//TODO(lcastell):Inline edit is deprecated and will be removed in Horizon 12.0
|
|
||||||
horizon.inline_edit = {
|
|
||||||
get_cell_id: function (td_element) {
|
|
||||||
return [
|
|
||||||
td_element.parents("tr").first().data("object-id"),
|
|
||||||
"__",
|
|
||||||
td_element.data("cell-name")
|
|
||||||
].join('');
|
|
||||||
},
|
|
||||||
get_object_container: function () {
|
|
||||||
// global cell object container
|
|
||||||
if (!window.cell_object_container) {
|
|
||||||
window.cell_object_container = [];
|
|
||||||
}
|
|
||||||
return window.cell_object_container;
|
|
||||||
},
|
|
||||||
get_cell_object: function (td_element) {
|
|
||||||
var cell_id = horizon.inline_edit.get_cell_id(td_element);
|
|
||||||
var id = "cell__" + cell_id;
|
|
||||||
var container = horizon.inline_edit.get_object_container(td_element);
|
|
||||||
var cell_object;
|
|
||||||
if (container && container[id]){
|
|
||||||
// if cell object exists, I will reuse it
|
|
||||||
cell_object = container[id];
|
|
||||||
cell_object.reset_with(td_element);
|
|
||||||
return cell_object;
|
|
||||||
} else {
|
|
||||||
// or I will create new cell object
|
|
||||||
cell_object = new horizon.inline_edit.Cell(td_element);
|
|
||||||
// saving cell object to global container
|
|
||||||
container[id] = cell_object;
|
|
||||||
return cell_object;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Cell: function (td_element){
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// setting initial attributes
|
|
||||||
self.reset_with = function(td_element){
|
|
||||||
self.td_element = td_element;
|
|
||||||
self.form_element = td_element.find("input, textarea");
|
|
||||||
self.url = td_element.data('update-url');
|
|
||||||
self.inline_edit_mod = false;
|
|
||||||
self.successful_update = false;
|
|
||||||
};
|
|
||||||
self.reset_with(td_element);
|
|
||||||
|
|
||||||
self.refresh = function () {
|
|
||||||
horizon.ajax.queue({
|
|
||||||
url: self.url,
|
|
||||||
data: {'inline_edit_mod': self.inline_edit_mod},
|
|
||||||
beforeSend: function () {
|
|
||||||
self.start_loading();
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
// Bug in jQuery tool-tip, if I hover tool-tip, then confirm the field with
|
|
||||||
// enter and the cell is reloaded, tool-tip stays. So just to be sure, I am
|
|
||||||
// removing tool-tips manually
|
|
||||||
$(".tooltip.fade.top.in").remove();
|
|
||||||
self.stop_loading();
|
|
||||||
|
|
||||||
if (self.successful_update) {
|
|
||||||
// if cell was updated successfully, I will show fading check sign
|
|
||||||
var success = $('<div class="success"></div>');
|
|
||||||
self.td_element.find('.inline-edit-status').append(success);
|
|
||||||
|
|
||||||
// edit pencil will disappear and appear again once the check sign has faded
|
|
||||||
// also green background will disappear
|
|
||||||
self.td_element.addClass("no-transition");
|
|
||||||
self.td_element.addClass("success");
|
|
||||||
self.td_element.removeClass("no-transition");
|
|
||||||
|
|
||||||
self.td_element.removeClass("inline_edit_available");
|
|
||||||
|
|
||||||
success.fadeOut(1300, function () {
|
|
||||||
self.td_element.addClass("inline_edit_available");
|
|
||||||
self.td_element.removeClass("success");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(jqXHR) {
|
|
||||||
if (jqXHR.status === 401){
|
|
||||||
var redir_url = jqXHR.getResponseHeader("X-Horizon-Location");
|
|
||||||
if (redir_url){
|
|
||||||
location.href = redir_url;
|
|
||||||
} else {
|
|
||||||
horizon.toast.add("error", gettext("Not authorized to do this operation."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!horizon.ajax.get_messages(jqXHR)) {
|
|
||||||
// Generic error handler. Really generic.
|
|
||||||
horizon.toast.add("error", gettext("An error occurred. Please try again later."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
success: function (data) {
|
|
||||||
var $td_element = $(data);
|
|
||||||
var $tr, $cell_wrapper, td_element_text;
|
|
||||||
self.form_element = self.get_form_element($td_element);
|
|
||||||
|
|
||||||
if (self.inline_edit_mod) {
|
|
||||||
var cellWidth = self.td_element.outerWidth(true);
|
|
||||||
$td_element.width(cellWidth);
|
|
||||||
$td_element.addClass("has-form");
|
|
||||||
}
|
|
||||||
// saving old td_element for cancel and loading purposes
|
|
||||||
self.cached_presentation_view = self.td_element;
|
|
||||||
// replacing old td with the new td element returned from the server
|
|
||||||
self.rewrite_cell($td_element);
|
|
||||||
// keeping parent tr's data-display attr up to date
|
|
||||||
$tr = $td_element.closest('tr');
|
|
||||||
if ($td_element.attr('data-cell-name') === $tr.attr('data-display-key')) {
|
|
||||||
$cell_wrapper= $td_element.find('.table_cell_data_wrapper');
|
|
||||||
if ($cell_wrapper.length) {
|
|
||||||
td_element_text = $cell_wrapper.find('a').text();
|
|
||||||
if ($tr.attr('data-display') !== td_element_text) {
|
|
||||||
$tr.attr('data-display', td_element_text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// focusing the form element inside the cell
|
|
||||||
if (self.inline_edit_mod) {
|
|
||||||
self.form_element.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
self.update = function(post_data){
|
|
||||||
// make the update request
|
|
||||||
horizon.ajax.queue({
|
|
||||||
type: 'POST',
|
|
||||||
url: self.url,
|
|
||||||
data: post_data,
|
|
||||||
beforeSend: function () {
|
|
||||||
self.start_loading();
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
if (!self.successful_update){
|
|
||||||
self.stop_loading();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(jqXHR) {
|
|
||||||
if (jqXHR.status === 400){
|
|
||||||
// make place for error icon, only if the error icon is not already present
|
|
||||||
if (self.td_element.find(".inline-edit-error .error").length <= 0) {
|
|
||||||
self.form_element.css('padding-left', '20px');
|
|
||||||
self.form_element.width(self.form_element.width() - 20);
|
|
||||||
}
|
|
||||||
// obtain the error message from response body
|
|
||||||
var error_message = $.parseJSON(jqXHR.responseText).message;
|
|
||||||
// insert the error icon
|
|
||||||
var error = $('<div title="' + error_message + '" class="error"></div>');
|
|
||||||
self.td_element.find(".inline-edit-error").html(error);
|
|
||||||
error.tooltip({'placement':'top'});
|
|
||||||
}
|
|
||||||
else if (jqXHR.status === 401){
|
|
||||||
var redir_url = jqXHR.getResponseHeader("X-Horizon-Location");
|
|
||||||
if (redir_url){
|
|
||||||
location.href = redir_url;
|
|
||||||
} else {
|
|
||||||
horizon.toast.add("error", gettext("Not authorized to do this operation."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!horizon.ajax.get_messages(jqXHR)) {
|
|
||||||
// Generic error handler. Really generic.
|
|
||||||
horizon.toast.add("error", gettext("An error occurred. Please try again later."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
success: function () {
|
|
||||||
// if update was successful
|
|
||||||
self.successful_update = true;
|
|
||||||
self.refresh();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
self.cancel = function() {
|
|
||||||
self.rewrite_cell(self.cached_presentation_view);
|
|
||||||
self.stop_loading();
|
|
||||||
};
|
|
||||||
self.get_form_element = function(td_element){
|
|
||||||
return td_element.find("input, textarea");
|
|
||||||
};
|
|
||||||
self.rewrite_cell = function(td_element){
|
|
||||||
self.td_element.replaceWith(td_element);
|
|
||||||
self.td_element = td_element;
|
|
||||||
};
|
|
||||||
self.start_loading = function() {
|
|
||||||
self.td_element.addClass("no-transition");
|
|
||||||
|
|
||||||
var spinner = $('<div class="loading"></div>');
|
|
||||||
self.td_element.find('.inline-edit-status').append(spinner);
|
|
||||||
self.td_element.addClass("loading");
|
|
||||||
self.td_element.removeClass("inline_edit_available");
|
|
||||||
self.get_form_element(self.td_element).attr("disabled", "disabled");
|
|
||||||
};
|
|
||||||
self.stop_loading = function() {
|
|
||||||
self.td_element.find('div.inline-edit-status div.loading').remove();
|
|
||||||
self.td_element.removeClass("loading");
|
|
||||||
self.td_element.addClass("inline_edit_available");
|
|
||||||
self.get_form_element(self.td_element).removeAttr("disabled");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
horizon.addInitFunction(horizon.inline_edit.init = function(parent) {
|
|
||||||
parent = parent || document;
|
|
||||||
var $table = $(parent).find('table');
|
|
||||||
|
|
||||||
$table.on('click', '.ajax-inline-edit', function (evt) {
|
|
||||||
var $this = $(this);
|
|
||||||
var td_element = $this.parents('td').first();
|
|
||||||
|
|
||||||
var cell = horizon.inline_edit.get_cell_object(td_element);
|
|
||||||
cell.inline_edit_mod = true;
|
|
||||||
cell.refresh();
|
|
||||||
|
|
||||||
evt.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
var submit_form = function(evt, el){
|
|
||||||
var $submit = $(el);
|
|
||||||
var td_element = $submit.parents('td').first();
|
|
||||||
var post_data = $submit.parents('form').first().serialize();
|
|
||||||
|
|
||||||
var cell = horizon.inline_edit.get_cell_object(td_element);
|
|
||||||
cell.update(post_data);
|
|
||||||
|
|
||||||
evt.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
$table.on('click', '.inline-edit-submit', function (evt) {
|
|
||||||
submit_form(evt, this);
|
|
||||||
});
|
|
||||||
|
|
||||||
$table.on('keypress', '.inline-edit-form', function (evt) {
|
|
||||||
if (evt.which === 13 && !evt.shiftKey) {
|
|
||||||
submit_form(evt, this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$table.on('click', '.inline-edit-cancel', function (evt) {
|
|
||||||
var $cancel = $(this);
|
|
||||||
var td_element = $cancel.parents('td').first();
|
|
||||||
|
|
||||||
var cell = horizon.inline_edit.get_cell_object(td_element);
|
|
||||||
cell.cancel();
|
|
||||||
|
|
||||||
evt.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
$table.on('mouseenter', '.inline_edit_available', function () {
|
|
||||||
$(this).find(".table_cell_action").fadeIn(100);
|
|
||||||
});
|
|
||||||
|
|
||||||
$table.on('mouseleave', '.inline_edit_available', function () {
|
|
||||||
$(this).find(".table_cell_action").fadeOut(200);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -124,5 +124,3 @@ horizon.addInitFunction(horizon.tabs.init = function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO(lcastell):Inline edit is deprecated and will be removed in Horizon 12.0
|
|
||||||
horizon.tabs.addTabLoadFunction(horizon.inline_edit.init);
|
|
||||||
|
@ -22,7 +22,6 @@ from horizon.tables.actions import FilterAction
|
|||||||
from horizon.tables.actions import FixedFilterAction
|
from horizon.tables.actions import FixedFilterAction
|
||||||
from horizon.tables.actions import LinkAction
|
from horizon.tables.actions import LinkAction
|
||||||
from horizon.tables.actions import NameFilterAction
|
from horizon.tables.actions import NameFilterAction
|
||||||
from horizon.tables.actions import UpdateAction
|
|
||||||
from horizon.tables.base import Column
|
from horizon.tables.base import Column
|
||||||
from horizon.tables.base import DataTable
|
from horizon.tables.base import DataTable
|
||||||
from horizon.tables.base import Row
|
from horizon.tables.base import Row
|
||||||
@ -42,7 +41,6 @@ __all__ = [
|
|||||||
'FixedFilterAction',
|
'FixedFilterAction',
|
||||||
'LinkAction',
|
'LinkAction',
|
||||||
'NameFilterAction',
|
'NameFilterAction',
|
||||||
'UpdateAction',
|
|
||||||
'Column',
|
'Column',
|
||||||
'DataTable',
|
'DataTable',
|
||||||
'Row',
|
'Row',
|
||||||
|
@ -26,7 +26,6 @@ from django import urls
|
|||||||
from django.utils.functional import Promise
|
from django.utils.functional import Promise
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.translation import ungettext_lazy
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
@ -964,61 +963,3 @@ class handle_exception_with_detail_message(object):
|
|||||||
# just to re-raise the exception.
|
# just to re-raise the exception.
|
||||||
raise
|
raise
|
||||||
return decorated
|
return decorated
|
||||||
|
|
||||||
|
|
||||||
class Deprecated(type):
|
|
||||||
# TODO(lcastell) Replace class with similar functionality from
|
|
||||||
# oslo_log.versionutils when it's finally added in 11.0
|
|
||||||
def __new__(meta, name, bases, kwargs):
|
|
||||||
cls = super(Deprecated, meta).__new__(meta, name, bases, kwargs)
|
|
||||||
if name != 'UpdateAction':
|
|
||||||
LOG.warning(
|
|
||||||
"WARNING:The UpdateAction class defined in module '%(mod)s' "
|
|
||||||
"is deprecated as of Newton and may be removed in "
|
|
||||||
"Horizon P (12.0). Class '%(name)s' defined at "
|
|
||||||
"module '%(module)s' shall no longer subclass it.",
|
|
||||||
{'mod': UpdateAction.__module__,
|
|
||||||
'name': name,
|
|
||||||
'module': kwargs['__module__']})
|
|
||||||
return cls
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(Deprecated)
|
|
||||||
class UpdateAction(object):
|
|
||||||
"""**DEPRECATED**: A table action for cell updates by inline editing."""
|
|
||||||
|
|
||||||
name = "update"
|
|
||||||
|
|
||||||
def action(self, request, datum, obj_id, cell_name, new_cell_value):
|
|
||||||
self.update_cell(request, datum, obj_id, cell_name, new_cell_value)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def action_present(count):
|
|
||||||
return ungettext_lazy(
|
|
||||||
u"Update Item",
|
|
||||||
u"Update Items",
|
|
||||||
count
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def action_past(count):
|
|
||||||
return ungettext_lazy(
|
|
||||||
u"Updated Item",
|
|
||||||
u"Updated Items",
|
|
||||||
count
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_cell(self, request, datum, obj_id, cell_name, new_cell_value):
|
|
||||||
"""Method for saving data of the cell.
|
|
||||||
|
|
||||||
This method must implements saving logic of the inline edited table
|
|
||||||
cell.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def allowed(self, request, datum, cell):
|
|
||||||
"""Determine whether updating is allowed for the current request.
|
|
||||||
|
|
||||||
This method is meant to be overridden with more specific checks.
|
|
||||||
Data of the row and of the cell are passed to the method.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
|
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.modals.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.modals.js'></script>
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tables.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.tables.js'></script>
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tables_inline_edit.js'></script>
|
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tabs.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.tabs.js'></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -253,19 +253,6 @@ class MyServerFilterAction(tables.FilterAction):
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
class MyUpdateAction(tables.UpdateAction):
|
|
||||||
def allowed(self, *args):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def update_cell(self, *args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MyUpdateActionNotAllowed(MyUpdateAction):
|
|
||||||
def allowed(self, *args):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_name(obj):
|
def get_name(obj):
|
||||||
return "custom %s" % obj.name
|
return "custom %s" % obj.name
|
||||||
|
|
||||||
@ -284,8 +271,7 @@ class MyTable(tables.DataTable):
|
|||||||
verbose_name="Verbose Name",
|
verbose_name="Verbose Name",
|
||||||
sortable=True,
|
sortable=True,
|
||||||
form_field=forms.CharField(required=True),
|
form_field=forms.CharField(required=True),
|
||||||
form_field_attributes={'class': 'test'},
|
form_field_attributes={'class': 'test'})
|
||||||
update_action=MyUpdateAction)
|
|
||||||
value = tables.Column('value',
|
value = tables.Column('value',
|
||||||
sortable=True,
|
sortable=True,
|
||||||
link='http://example.com/',
|
link='http://example.com/',
|
||||||
@ -345,8 +331,7 @@ class MyTableNotAllowedInlineEdit(MyTable):
|
|||||||
verbose_name="Verbose Name",
|
verbose_name="Verbose Name",
|
||||||
sortable=True,
|
sortable=True,
|
||||||
form_field=forms.CharField(required=True),
|
form_field=forms.CharField(required=True),
|
||||||
form_field_attributes={'class': 'test'},
|
form_field_attributes={'class': 'test'})
|
||||||
update_action=MyUpdateActionNotAllowed)
|
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
name = "my_table"
|
name = "my_table"
|
||||||
@ -358,7 +343,6 @@ class MyTableWrapList(MyTable):
|
|||||||
name = tables.Column('name',
|
name = tables.Column('name',
|
||||||
form_field=forms.CharField(required=True),
|
form_field=forms.CharField(required=True),
|
||||||
form_field_attributes={'class': 'test'},
|
form_field_attributes={'class': 'test'},
|
||||||
update_action=MyUpdateActionNotAllowed,
|
|
||||||
wrap_list=True)
|
wrap_list=True)
|
||||||
value = tables.Column('value',
|
value = tables.Column('value',
|
||||||
|
|
||||||
@ -443,7 +427,6 @@ class DataTableTests(test.TestCase):
|
|||||||
actions.get_final_attrs().get('class', ""))
|
actions.get_final_attrs().get('class', ""))
|
||||||
# In-line edit action on column.
|
# In-line edit action on column.
|
||||||
name_column = self.table.columns['name']
|
name_column = self.table.columns['name']
|
||||||
self.assertEqual(MyUpdateAction, name_column.update_action)
|
|
||||||
self.assertEqual(forms.CharField, name_column.form_field.__class__)
|
self.assertEqual(forms.CharField, name_column.form_field.__class__)
|
||||||
self.assertEqual({'class': 'test'}, name_column.form_field_attributes)
|
self.assertEqual({'class': 'test'}, name_column.form_field_attributes)
|
||||||
|
|
||||||
@ -728,96 +711,6 @@ class DataTableTests(test.TestCase):
|
|||||||
self.assertNotContains(resp_optional, '<ul>')
|
self.assertNotContains(resp_optional, '<ul>')
|
||||||
self.assertNotContains(resp_optional, '</ul>')
|
self.assertNotContains(resp_optional, '</ul>')
|
||||||
|
|
||||||
def test_inline_edit_available_cell_rendering(self):
|
|
||||||
self.table = MyTable(self.request, TEST_DATA_2)
|
|
||||||
row = self.table.get_rows()[0]
|
|
||||||
name_cell = row.cells['name']
|
|
||||||
|
|
||||||
# Check if in-line edit is available in the cell,
|
|
||||||
# but is not in inline_edit_mod.
|
|
||||||
self.assertTrue(name_cell.inline_edit_available)
|
|
||||||
self.assertFalse(name_cell.inline_edit_mod)
|
|
||||||
|
|
||||||
# Check if is cell is rendered correctly.
|
|
||||||
name_cell_rendered = name_cell.render()
|
|
||||||
resp = http.HttpResponse(name_cell_rendered)
|
|
||||||
|
|
||||||
self.assertContains(resp, '<td', 1)
|
|
||||||
self.assertContains(resp, 'inline_edit_available', 1)
|
|
||||||
self.assertContains(resp,
|
|
||||||
'data-update-url="?action=cell_update&'
|
|
||||||
'table=my_table&cell_name=name&obj_id=1"',
|
|
||||||
1)
|
|
||||||
self.assertContains(resp, 'table_cell_wrapper', 1)
|
|
||||||
self.assertContains(resp, 'table_cell_data_wrapper', 1)
|
|
||||||
self.assertContains(resp, 'table_cell_action', 1)
|
|
||||||
self.assertContains(resp, 'ajax-inline-edit', 1)
|
|
||||||
|
|
||||||
def test_inline_edit_available_not_allowed_cell_rendering(self):
|
|
||||||
self.table = MyTableNotAllowedInlineEdit(self.request, TEST_DATA_2)
|
|
||||||
|
|
||||||
row = self.table.get_rows()[0]
|
|
||||||
name_cell = row.cells['name']
|
|
||||||
|
|
||||||
# Check if in-line edit is available in the cell,
|
|
||||||
# but is not in inline_edit_mod.
|
|
||||||
self.assertTrue(name_cell.inline_edit_available)
|
|
||||||
self.assertFalse(name_cell.inline_edit_mod)
|
|
||||||
|
|
||||||
# Check if is cell is rendered correctly.
|
|
||||||
name_cell_rendered = name_cell.render()
|
|
||||||
resp = http.HttpResponse(name_cell_rendered)
|
|
||||||
|
|
||||||
self.assertContains(resp, '<td', 1)
|
|
||||||
self.assertContains(resp, 'inline_edit_available', 1)
|
|
||||||
self.assertContains(resp,
|
|
||||||
'data-update-url="?action=cell_update&'
|
|
||||||
'table=my_table&cell_name=name&obj_id=1"',
|
|
||||||
1)
|
|
||||||
self.assertContains(resp, 'table_cell_wrapper', 0)
|
|
||||||
self.assertContains(resp, 'table_cell_data_wrapper', 0)
|
|
||||||
self.assertContains(resp, 'table_cell_action', 0)
|
|
||||||
self.assertContains(resp, 'ajax-inline-edit', 0)
|
|
||||||
|
|
||||||
def test_inline_edit_mod_cell_rendering(self):
|
|
||||||
self.table = MyTable(self.request, TEST_DATA_2)
|
|
||||||
name_col = self.table.columns['name']
|
|
||||||
name_col.auto = "form_field"
|
|
||||||
|
|
||||||
row = self.table.get_rows()[0]
|
|
||||||
name_cell = row.cells['name']
|
|
||||||
name_cell.inline_edit_mod = True
|
|
||||||
|
|
||||||
# Check if in-line edit is available in the cell,
|
|
||||||
# and is in inline_edit_mod, also column auto must be
|
|
||||||
# set as form_field.
|
|
||||||
self.assertTrue(name_cell.inline_edit_available)
|
|
||||||
self.assertTrue(name_cell.inline_edit_mod)
|
|
||||||
self.assertEqual('form_field',
|
|
||||||
name_col.auto)
|
|
||||||
|
|
||||||
# Check if is cell is rendered correctly.
|
|
||||||
name_cell_rendered = name_cell.render()
|
|
||||||
resp = http.HttpResponse(name_cell_rendered)
|
|
||||||
|
|
||||||
self.assertContains(resp,
|
|
||||||
'<input class="test" id="name__1" name="name__1"'
|
|
||||||
' type="text" value="custom object_1" />',
|
|
||||||
count=1, html=True)
|
|
||||||
|
|
||||||
self.assertContains(resp, '<td', 1)
|
|
||||||
self.assertContains(resp, 'inline_edit_available', 1)
|
|
||||||
self.assertContains(resp,
|
|
||||||
'data-update-url="?action=cell_update&'
|
|
||||||
'table=my_table&cell_name=name&obj_id=1"',
|
|
||||||
1)
|
|
||||||
self.assertContains(resp, 'table_cell_wrapper', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-error', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-form', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-actions', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-submit', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-cancel', 1)
|
|
||||||
|
|
||||||
def test_inline_edit_mod_checkbox_with_label(self):
|
def test_inline_edit_mod_checkbox_with_label(self):
|
||||||
class TempTable(MyTable):
|
class TempTable(MyTable):
|
||||||
name = tables.Column(get_name,
|
name = tables.Column(get_name,
|
||||||
@ -826,8 +719,7 @@ class DataTableTests(test.TestCase):
|
|||||||
form_field=forms.BooleanField(
|
form_field=forms.BooleanField(
|
||||||
required=True,
|
required=True,
|
||||||
label="Verbose Name"),
|
label="Verbose Name"),
|
||||||
form_field_attributes={'class': 'test'},
|
form_field_attributes={'class': 'test'})
|
||||||
update_action=MyUpdateAction)
|
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
name = "my_table"
|
name = "my_table"
|
||||||
@ -850,10 +742,6 @@ class DataTableTests(test.TestCase):
|
|||||||
'id="name__1" name="name__1" type="checkbox" '
|
'id="name__1" name="name__1" type="checkbox" '
|
||||||
'value="custom object_1" />',
|
'value="custom object_1" />',
|
||||||
count=1, html=True)
|
count=1, html=True)
|
||||||
self.assertContains(resp,
|
|
||||||
'<label class="inline-edit-label" for="name__1">'
|
|
||||||
'Verbose Name</label>',
|
|
||||||
count=1, html=True)
|
|
||||||
|
|
||||||
def test_table_search_action(self):
|
def test_table_search_action(self):
|
||||||
class TempTable(MyTable):
|
class TempTable(MyTable):
|
||||||
@ -900,8 +788,7 @@ class DataTableTests(test.TestCase):
|
|||||||
form_field=forms.CharField(
|
form_field=forms.CharField(
|
||||||
widget=forms.Textarea(),
|
widget=forms.Textarea(),
|
||||||
required=False),
|
required=False),
|
||||||
form_field_attributes={'class': 'test'},
|
form_field_attributes={'class': 'test'})
|
||||||
update_action=MyUpdateAction)
|
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
name = "my_table"
|
name = "my_table"
|
||||||
@ -1137,121 +1024,6 @@ class DataTableTests(test.TestCase):
|
|||||||
u'FakeObject: öbject_4'],
|
u'FakeObject: öbject_4'],
|
||||||
transform=six.text_type)
|
transform=six.text_type)
|
||||||
|
|
||||||
def test_inline_edit_update_action_get_non_ajax(self):
|
|
||||||
# Non ajax inline edit request should return None.
|
|
||||||
url = ('/my_url/?action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.get(url, {})
|
|
||||||
self.table = MyTable(req, TEST_DATA_2)
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
# Checking the response header.
|
|
||||||
self.assertIsNone(handled)
|
|
||||||
|
|
||||||
def test_inline_edit_update_action_get(self):
|
|
||||||
# Get request should return td field with data.
|
|
||||||
url = ('/my_url/?action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.get(url, {},
|
|
||||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
self.table = MyTable(req, TEST_DATA_2)
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
# Checking the response header.
|
|
||||||
self.assertEqual(200, handled.status_code)
|
|
||||||
# Checking the response content.
|
|
||||||
resp = handled
|
|
||||||
self.assertContains(resp, '<td', 1)
|
|
||||||
self.assertContains(resp, 'inline_edit_available', 1)
|
|
||||||
self.assertContains(
|
|
||||||
resp,
|
|
||||||
'data-update-url="/my_url/?action=cell_update&'
|
|
||||||
'table=my_table&cell_name=name&obj_id=1"',
|
|
||||||
1)
|
|
||||||
self.assertContains(resp, 'table_cell_wrapper', 1)
|
|
||||||
self.assertContains(resp, 'table_cell_data_wrapper', 1)
|
|
||||||
self.assertContains(resp, 'table_cell_action', 1)
|
|
||||||
self.assertContains(resp, 'ajax-inline-edit', 1)
|
|
||||||
|
|
||||||
def test_inline_edit_update_action_get_not_allowed(self):
|
|
||||||
# Name column has required validation, sending blank
|
|
||||||
# will return error.
|
|
||||||
url = ('/my_url/?action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.post(url, {})
|
|
||||||
self.table = MyTableNotAllowedInlineEdit(req, TEST_DATA_2)
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
# Checking the response header.
|
|
||||||
self.assertEqual(401, handled.status_code)
|
|
||||||
|
|
||||||
def test_inline_edit_update_action_get_inline_edit_mod(self):
|
|
||||||
# Get request in inline_edit_mode should return td with form field.
|
|
||||||
url = ('/my_url/?inline_edit_mod=true&action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.get(url, {},
|
|
||||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
self.table = MyTable(req, TEST_DATA_2)
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
# Checking the response header.
|
|
||||||
self.assertEqual(200, handled.status_code)
|
|
||||||
# Checking the response content.
|
|
||||||
resp = handled
|
|
||||||
self.assertContains(resp,
|
|
||||||
'<input class="test" id="name__1" name="name__1"'
|
|
||||||
' type="text" value="custom object_1" />',
|
|
||||||
count=1, html=True)
|
|
||||||
|
|
||||||
self.assertContains(resp, '<td', 1)
|
|
||||||
self.assertContains(resp, 'inline_edit_available', 1)
|
|
||||||
self.assertContains(
|
|
||||||
resp,
|
|
||||||
'data-update-url="/my_url/?action=cell_update&'
|
|
||||||
'table=my_table&cell_name=name&obj_id=1"',
|
|
||||||
1)
|
|
||||||
self.assertContains(resp, 'table_cell_wrapper', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-error', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-form', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-actions', 1)
|
|
||||||
self.assertContains(resp, '<button', 2)
|
|
||||||
self.assertContains(resp, 'inline-edit-submit', 1)
|
|
||||||
self.assertContains(resp, 'inline-edit-cancel', 1)
|
|
||||||
|
|
||||||
def test_inline_edit_update_action_post(self):
|
|
||||||
# Post request should invoke the cell update table action.
|
|
||||||
url = ('/my_url/?action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.post(url, {'name__1': 'test_name'})
|
|
||||||
self.table = MyTable(req, TEST_DATA_2)
|
|
||||||
# checking the response header
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
self.assertEqual(200, handled.status_code)
|
|
||||||
|
|
||||||
def test_inline_edit_update_action_post_not_allowed(self):
|
|
||||||
# Post request should invoke the cell update table action.
|
|
||||||
url = ('/my_url/?action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.post(url, {'name__1': 'test_name'})
|
|
||||||
self.table = MyTableNotAllowedInlineEdit(req, TEST_DATA_2)
|
|
||||||
# checking the response header
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
self.assertEqual(401, handled.status_code)
|
|
||||||
|
|
||||||
def test_inline_edit_update_action_post_validation_error(self):
|
|
||||||
# Name column has required validation, sending blank
|
|
||||||
# will return error.
|
|
||||||
url = ('/my_url/?action=cell_update'
|
|
||||||
'&table=my_table&cell_name=name&obj_id=1')
|
|
||||||
req = self.factory.post(url, {})
|
|
||||||
self.table = MyTable(req, TEST_DATA_2)
|
|
||||||
handled = self.table.maybe_preempt()
|
|
||||||
# Checking the response header.
|
|
||||||
self.assertEqual(400, handled.status_code)
|
|
||||||
self.assertEqual(('Content-Type', 'application/json'),
|
|
||||||
handled._headers['content-type'])
|
|
||||||
# Checking the response content.
|
|
||||||
resp = handled
|
|
||||||
self.assertContains(resp,
|
|
||||||
'"message": "This field is required."',
|
|
||||||
count=1, status_code=400)
|
|
||||||
|
|
||||||
def test_column_uniqueness(self):
|
def test_column_uniqueness(self):
|
||||||
table1 = MyTable(self.request)
|
table1 = MyTable(self.request)
|
||||||
table2 = MyTable(self.request)
|
table2 = MyTable(self.request)
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.selenium.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.selenium.js'></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tables.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.tables.js'></script>
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tables_inline_edit.js'></script>
|
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tabs.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.tabs.js'></script>
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.templates.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.templates.js'></script>
|
||||||
<script src='{{ STATIC_URL }}horizon/js/horizon.users.js'></script>
|
<script src='{{ STATIC_URL }}horizon/js/horizon.users.js'></script>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
other:
|
||||||
|
- |
|
||||||
|
UpdateAction is deprecated in Newton and removed now. You should not use
|
||||||
|
inline edit functionality in your plugins anymore.
|
Loading…
Reference in New Issue
Block a user