diff --git a/doc/source/contributor/topics/tables.rst b/doc/source/contributor/topics/tables.rst index e8c3225363..6cea53a61e 100644 --- a/doc/source/contributor/topics/tables.rst +++ b/doc/source/contributor/topics/tables.rst @@ -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. ------------------------------------------------------------------------ diff --git a/doc/source/contributor/tutorials/dashboard.rst b/doc/source/contributor/tutorials/dashboard.rst index 0771719c40..8eb3e1f5b4 100644 --- a/doc/source/contributor/tutorials/dashboard.rst +++ b/doc/source/contributor/tutorials/dashboard.rst @@ -285,7 +285,6 @@ classes: - :class:`~horizon.tables.BatchAction` - :class:`~horizon.tables.DeleteAction` -- :class:`~horizon.tables.UpdateAction` **DEPRECATED** - :class:`~horizon.tables.FixedFilterAction` diff --git a/horizon/static/horizon/js/horizon.tables_inline_edit.js b/horizon/static/horizon/js/horizon.tables_inline_edit.js deleted file mode 100644 index ce868e9c80..0000000000 --- a/horizon/static/horizon/js/horizon.tables_inline_edit.js +++ /dev/null @@ -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 = $('
'); - 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 = $('
'); - 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 = $('
'); - 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); - }); -}); - diff --git a/horizon/static/horizon/js/horizon.tabs.js b/horizon/static/horizon/js/horizon.tabs.js index 8b86551ad0..81df14b0fc 100644 --- a/horizon/static/horizon/js/horizon.tabs.js +++ b/horizon/static/horizon/js/horizon.tabs.js @@ -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); diff --git a/horizon/tables/__init__.py b/horizon/tables/__init__.py index ed20462eb9..2a8840423d 100644 --- a/horizon/tables/__init__.py +++ b/horizon/tables/__init__.py @@ -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', diff --git a/horizon/tables/actions.py b/horizon/tables/actions.py index b3f07b90a2..1011bdaa3b 100644 --- a/horizon/tables/actions.py +++ b/horizon/tables/actions.py @@ -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 diff --git a/horizon/test/templates/base.html b/horizon/test/templates/base.html index 819643c230..d3379035eb 100644 --- a/horizon/test/templates/base.html +++ b/horizon/test/templates/base.html @@ -65,7 +65,6 @@ - {% endif %} - diff --git a/releasenotes/notes/remove-table-update-action-d3fc1c5e5e3598b0.yaml b/releasenotes/notes/remove-table-update-action-d3fc1c5e5e3598b0.yaml new file mode 100644 index 0000000000..bd365cd131 --- /dev/null +++ b/releasenotes/notes/remove-table-update-action-d3fc1c5e5e3598b0.yaml @@ -0,0 +1,5 @@ +--- +other: + - | + UpdateAction is deprecated in Newton and removed now. You should not use + inline edit functionality in your plugins anymore.