diff --git a/javascript/GridFieldExtensions.js b/javascript/GridFieldExtensions.js index e143ef0..d196464 100644 --- a/javascript/GridFieldExtensions.js +++ b/javascript/GridFieldExtensions.js @@ -273,6 +273,82 @@ */ $(".ss-gridfield-orderable tbody").entwine({ + // reload the gridfield without triggering the change event + // this is because the change has already been saved by reorder action + reload: function (ajaxOpts, successCallback) { + var self = this.getGridField(), form = this.closest('form'), + focusedElName = this.find(':input:focus').attr('name'), // Save focused element for restoring after refresh + data = form.find(':input').serializeArray(); + + if (!ajaxOpts) { + ajaxOpts = {}; + } + if (!ajaxOpts.data) { + ajaxOpts.data = []; + } + ajaxOpts.data = ajaxOpts.data.concat(data); + + // Include any GET parameters from the current URL, as the view state might depend on it. + // For example, a list prefiltered through external search criteria might be passed to GridField. + if (window.location.search) { + ajaxOpts.data = window.location.search.replace(/^\?/, '') + '&' + $.param(ajaxOpts.data); + } + + form.addClass('loading'); + + $.ajax($.extend({}, { + headers: {"X-Pjax": 'CurrentField'}, + type: "POST", + url: this.data('url'), + dataType: 'html', + success: function (data) { + // Replace the grid field with response, not the form. + // TODO Only replaces all its children, to avoid replacing the current scope + // of the executing method. Means that it doesn't retrigger the onmatch() on the main container. + self.empty().append($(data).children()); + + // Refocus previously focused element. Useful e.g. for finding+adding + // multiple relationships via keyboard. + if (focusedElName) self.find(':input[name="' + focusedElName + '"]').focus(); + + // Update filter + if (self.find('.grid-field__filter-header').length) { + var content; + if (ajaxOpts.data[0].filter == "show") { + content = ''; + self.addClass('show-filter').find('.grid-field__filter-header').show(); + } else { + content = ''; + self.removeClass('show-filter').find('.grid-field__filter-header').hide(); + } + + self.find('.sortable-header th:last').html(content); + } + + form.removeClass('loading'); + if (successCallback) { + successCallback.apply(this, arguments); + } + self.trigger('reload', self); + + // update publish button if necessary + const publish = $('#Form_EditForm_action_publish'); + + // button needs to be updated only if it's in published state + if (publish.length > 0 && publish.hasClass('btn-outline-primary')) { + publish.removeClass('btn-outline-primary'); + publish.removeClass('font-icon-tick'); + publish.addClass('btn-primary'); + publish.addClass('font-icon-rocket'); + publish.find('.btn__title').html('Save & publish'); + } + }, + error: function (e) { + alert(i18n._t('Admin.ERRORINTRANSACTION')); + form.removeClass('loading'); + } + }, ajaxOpts)); + }, rebuildSort: function() { var grid = this.getGridField(); @@ -329,7 +405,7 @@ var grid = self.getGridField(); if (grid.data("immediate-update") && postback) { - grid.reload({ + self.reload({ url: grid.data("url-reorder") }); } diff --git a/src/GridFieldOrderableRows.php b/src/GridFieldOrderableRows.php index 8e52a33..0b2dadf 100755 --- a/src/GridFieldOrderableRows.php +++ b/src/GridFieldOrderableRows.php @@ -21,6 +21,7 @@ use SilverStripe\ORM\DB; use SilverStripe\ORM\ManyManyList; use SilverStripe\ORM\SS_List; use SilverStripe\ORM\SS_Map; +use SilverStripe\Versioned\Versioned; use SilverStripe\View\ViewableData; /** @@ -171,6 +172,35 @@ class GridFieldOrderableRows extends RequestHandler implements return $this; } + /** + * Validates sortable list + * + * @param SS_List $list + * @throws Exception + */ + public function validateSortField(SS_List $list) + { + $field = $this->getSortField(); + + if ($list instanceof ManyManyList) { + $extra = $list->getExtraFields(); + + if ($extra && array_key_exists($field, $extra)) { + return; + } + } + + $classes = ClassInfo::dataClassesFor($list->dataClass()); + + foreach ($classes as $class) { + if (singleton($class)->hasDataBaseField($field)) { + return; + } + } + + throw new \Exception("Couldn't find the sort field '" . $field . "'"); + } + /** * Gets the table which contains the sort field. * @@ -504,11 +534,9 @@ class GridFieldOrderableRows extends RequestHandler implements } // If not a ManyManyList and using versioning, detect it. - $isVersioned = false; + $this->validateSortField($list); $class = $list->dataClass(); - if ($class == $this->getSortTable($list)) { - $isVersioned = $class::has_extension('SilverStripe\\ORM\\Versioning\\Versioned'); - } + $isVersioned = $class::has_extension(Versioned::class); // Loop through each item, and update the sort values which do not // match to order the objects.