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)
|
||||
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.
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
@ -285,7 +285,6 @@ classes:
|
||||
|
||||
- :class:`~horizon.tables.BatchAction`
|
||||
- :class:`~horizon.tables.DeleteAction`
|
||||
- :class:`~horizon.tables.UpdateAction` **DEPRECATED**
|
||||
- :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 LinkAction
|
||||
from horizon.tables.actions import NameFilterAction
|
||||
from horizon.tables.actions import UpdateAction
|
||||
from horizon.tables.base import Column
|
||||
from horizon.tables.base import DataTable
|
||||
from horizon.tables.base import Row
|
||||
@ -42,7 +41,6 @@ __all__ = [
|
||||
'FixedFilterAction',
|
||||
'LinkAction',
|
||||
'NameFilterAction',
|
||||
'UpdateAction',
|
||||
'Column',
|
||||
'DataTable',
|
||||
'Row',
|
||||
|
@ -26,7 +26,6 @@ from django import urls
|
||||
from django.utils.functional import Promise
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext_lazy
|
||||
import six
|
||||
|
||||
from horizon import exceptions
|
||||
@ -964,61 +963,3 @@ class handle_exception_with_detail_message(object):
|
||||
# just to re-raise the exception.
|
||||
raise
|
||||
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.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>
|
||||
|
@ -253,19 +253,6 @@ class MyServerFilterAction(tables.FilterAction):
|
||||
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):
|
||||
return "custom %s" % obj.name
|
||||
|
||||
@ -284,8 +271,7 @@ class MyTable(tables.DataTable):
|
||||
verbose_name="Verbose Name",
|
||||
sortable=True,
|
||||
form_field=forms.CharField(required=True),
|
||||
form_field_attributes={'class': 'test'},
|
||||
update_action=MyUpdateAction)
|
||||
form_field_attributes={'class': 'test'})
|
||||
value = tables.Column('value',
|
||||
sortable=True,
|
||||
link='http://example.com/',
|
||||
@ -345,8 +331,7 @@ class MyTableNotAllowedInlineEdit(MyTable):
|
||||
verbose_name="Verbose Name",
|
||||
sortable=True,
|
||||
form_field=forms.CharField(required=True),
|
||||
form_field_attributes={'class': 'test'},
|
||||
update_action=MyUpdateActionNotAllowed)
|
||||
form_field_attributes={'class': 'test'})
|
||||
|
||||
class Meta(object):
|
||||
name = "my_table"
|
||||
@ -358,7 +343,6 @@ class MyTableWrapList(MyTable):
|
||||
name = tables.Column('name',
|
||||
form_field=forms.CharField(required=True),
|
||||
form_field_attributes={'class': 'test'},
|
||||
update_action=MyUpdateActionNotAllowed,
|
||||
wrap_list=True)
|
||||
value = tables.Column('value',
|
||||
|
||||
@ -443,7 +427,6 @@ class DataTableTests(test.TestCase):
|
||||
actions.get_final_attrs().get('class', ""))
|
||||
# In-line edit action on column.
|
||||
name_column = self.table.columns['name']
|
||||
self.assertEqual(MyUpdateAction, name_column.update_action)
|
||||
self.assertEqual(forms.CharField, name_column.form_field.__class__)
|
||||
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>')
|
||||
|
||||
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):
|
||||
class TempTable(MyTable):
|
||||
name = tables.Column(get_name,
|
||||
@ -826,8 +719,7 @@ class DataTableTests(test.TestCase):
|
||||
form_field=forms.BooleanField(
|
||||
required=True,
|
||||
label="Verbose Name"),
|
||||
form_field_attributes={'class': 'test'},
|
||||
update_action=MyUpdateAction)
|
||||
form_field_attributes={'class': 'test'})
|
||||
|
||||
class Meta(object):
|
||||
name = "my_table"
|
||||
@ -850,10 +742,6 @@ class DataTableTests(test.TestCase):
|
||||
'id="name__1" name="name__1" type="checkbox" '
|
||||
'value="custom object_1" />',
|
||||
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):
|
||||
class TempTable(MyTable):
|
||||
@ -900,8 +788,7 @@ class DataTableTests(test.TestCase):
|
||||
form_field=forms.CharField(
|
||||
widget=forms.Textarea(),
|
||||
required=False),
|
||||
form_field_attributes={'class': 'test'},
|
||||
update_action=MyUpdateAction)
|
||||
form_field_attributes={'class': 'test'})
|
||||
|
||||
class Meta(object):
|
||||
name = "my_table"
|
||||
@ -1137,121 +1024,6 @@ class DataTableTests(test.TestCase):
|
||||
u'FakeObject: öbject_4'],
|
||||
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):
|
||||
table1 = MyTable(self.request)
|
||||
table2 = MyTable(self.request)
|
||||
|
@ -35,7 +35,6 @@
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.selenium.js'></script>
|
||||
{% endif %}
|
||||
<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.templates.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