From 066e9eb236e803640a9a77d4751eb9b35fd47f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eero=20J=C3=A4=C3=A4skel=C3=A4inen?= Date: Mon, 28 Nov 2022 09:39:28 +0200 Subject: [PATCH] Sorting with known previous sibling's ID --- application/controllers/Services.php | 22 ++--- application/core/EA_Model.php | 107 ++++++++++--------------- application/models/Services_model.php | 7 +- assets/js/http/services_http_client.js | 9 +-- assets/js/pages/services.js | 16 ++-- 5 files changed, 67 insertions(+), 94 deletions(-) diff --git a/application/controllers/Services.php b/application/controllers/Services.php index 7487449c..82a6ce9c 100644 --- a/application/controllers/Services.php +++ b/application/controllers/Services.php @@ -244,29 +244,21 @@ class Services extends EA_Controller { { abort(400,'Invalid ID value'); } - $newOrder = request('new_order'); - if ( (($newOrder = filter_var($newOrder,FILTER_VALIDATE_INT)) === FALSE) || - $newOrder < 0) + + $insertAfterId = request('after'); + if (($insertAfterId = filter_var($insertAfterId,FILTER_VALIDATE_INT)) === FALSE) { - abort(400,'Invalid new order value'); + abort(400,'Invalid after value, must be ID or -1'); } - $visibleServices = request('allIds'); - if (empty($visibleServices)) + if ($insertAfterId <= 0) { - abort('allIds must be defined to successfully sort services'); + $insertAfterId = FALSE; } - if (!is_array($visibleServices)) - { - $visibleServices = Array($visibleServices); - } - - $visibleServices = array_filter(filter_var_array($visibleServices, FILTER_VALIDATE_INT)); - $service = $this->services_model->find($service_id); - $service['row_order'] = $this->services_model->set_service_order($service['id'], $newOrder,$visibleServices); + $service['row_order'] = $this->services_model->set_service_order($service['id'], $insertAfterId); return json_response($service); } diff --git a/application/core/EA_Model.php b/application/core/EA_Model.php index 818e6272..c0d929ce 100644 --- a/application/core/EA_Model.php +++ b/application/core/EA_Model.php @@ -238,83 +238,53 @@ class EA_Model extends CI_Model { /** - * Inserts entry to desired order in table relative to user visible entries + * Inserts entry order after defined entry * * @param string $table Table - * @param array $entry Entity - * @param int $desiredOrder Desired place in table (relative to visible entities) - * @param Array [$visibleIds] Visible ids to sort on - * @param string [$order_column] Ordering Column name + * @param array $entry Entity to insert + * @param mixed|bool $afterId ID of entry where to insert at. Or false to set at beginning + * @param string [$order_column] Ordering Column name (Default: row_order) * * @throws RuntimeException + * @throws InvalidArgumentException */ - public function insert_row_order_visible (string $table, array &$entry, int $desiredOrder, Array &$visibleIds = NULL, string $order_column='row_order') + public function insert_row_order_after(string $table, array &$entry, $afterId, string $order_column='row_order') { if (empty($table)) throw new InvalidArgumentException("Table parameter must be defined"); - if (empty($column)) + if (empty($order_column)) throw new InvalidArgumentException("Column parameter must be defined"); if (!array_key_exists('id', $entry)) throw new InvalidArgumentException('Entry does not contain ID column'); - if (!array_key_exists($column,$entry)) - throw new InvalidArgumentException('Entry does not contain sorting column'); + if (!array_key_exists($order_column,$entry)) + throw new InvalidArgumentException('Entry does not contain sorting column'); - $setOrder = $desiredOrder; - $id = $entry['id']; + // Get position of desired entry: + if (is_int($afterId) && $afterId > 0) + { + $position = $this->db->from($table) + ->select([$order_column]) + ->where('id',$afterId) + ->get() + ->row_array(); + if ($position === false) + { + throw new InvalidArgumentException("Could not found service with ID $afterId"); + } + $position = intval($position[$order_column]); + } + else { + $position = FALSE; + } + + if (! $this->insert_row_order($table,$entry,$position,$order_column)) + { + throw new RuntimeException('Could not update order, database error'); + } - if (!empty($visibleIds)) - { - // Set order to reflect real position in DB - - $allRows = $this->db->from($table) - ->order_by($order_column) - ->select(['id']) - ->get() - ->result_array(); - if ($desiredOrder >= count($visibleIds) -1) - { - $setOrder = count($allRows); // Desired last - } - else { - - for ($i=0; $i < count($allRows); $i++) - { - if ($i >= count($visibleIds)) - { - break; - } - elseif ($i > $desiredOrder) - { - break; - } - elseif (!in_array($allRows[$i]['id'], $visibleIds)) - { - $setOrder ++; - } - } - } - } - $currentOrder = intval( - $this->db - ->select($order_column) - ->from($table) - ->where(['id'=>$id]) - ->limit(1) - ->get() - ->row_array() - [$order_column] - ); - - if ($setOrder != $currentOrder) - { - if (! $this->insert_row_order($table,$entry,$setOrder)) - { - throw new RuntimeException('Could not update order, database error'); - } - } } @@ -323,13 +293,14 @@ class EA_Model extends CI_Model { * * @param string $table Table * @param array $entry Entry, should be associative array containing columns 'Id' and desired $column sort value. + * @param int|bool $position Position to set entry to. If set to False, it will be positioned to first. * @param string $column Column name that contains sorting data (default is 'row_order'). * * @return bool TRUE on success, FALSE on failure * @throws InvalidArgumentException */ - protected function insert_row_order(string $table, array &$entry, int $position, string $column = 'row_order') + protected function insert_row_order(string $table, array &$entry, $position, string $column = 'row_order') { if (empty($table)) throw new InvalidArgumentException("Table parameter must be defined"); @@ -341,8 +312,16 @@ class EA_Model extends CI_Model { if (!array_key_exists($column,$entry)) throw new InvalidArgumentException('Entry does not contain sorting column'); - $movingUp = $position >= intval($entry[$column]); - $newOr = $movingUp? $position +1 : $position; + + if (is_int($position)) + { + $newOr = $position +1; + } + else + { + $newOr = 0; + } + $this->db->update($table, [$column => $newOr ], [ 'id'=> $entry['id'] ]); diff --git a/application/models/Services_model.php b/application/models/Services_model.php index 02337fd9..7c377d29 100644 --- a/application/models/Services_model.php +++ b/application/models/Services_model.php @@ -542,17 +542,16 @@ class Services_model extends EA_Model { * Sort service * * @param int $service_id Service ID - * @param int $desiredOrder Desired place in table (relative to visible services) - * @param Array [$allServiceIds] Visible service ids to sort on + * @param int|bool $afterServiceId ID of service that service should be inserted after, or FALSE to set to beginning * * @return int New place in table */ - public function set_service_order(int $service_id, int $desiredOrder, Array &$allServiceIds = NULL) + public function set_service_order(int $service_id, $afterServiceId) { $service = $this->find($service_id); - $this->insert_row_order_visible('services',$service,$desiredOrder,$allServiceIds); + $this->insert_row_order_after('services',$service,$afterServiceId); return $this->value($service['id'],'row_order'); } diff --git a/assets/js/http/services_http_client.js b/assets/js/http/services_http_client.js index 38af557f..85640f6b 100644 --- a/assets/js/http/services_http_client.js +++ b/assets/js/http/services_http_client.js @@ -127,20 +127,17 @@ App.Http.Services = (function () { * * @param {Number} serviceId * - * @param {Number} newOrder - * - * @param {Array} allIds + * @param {Number} afterId * * @return {Object} */ - function sort(serviceId, newOrder, allIds) + function sort(serviceId, afterId) { const url = App.Utils.Url.siteUrl('services/sort'); const data = { csrf_token: vars('csrf_token'), service_id: serviceId, - new_order : newOrder, - allIds + after : afterId }; return $.post(url,data); } diff --git a/assets/js/pages/services.js b/assets/js/pages/services.js index 5acf8947..998df038 100644 --- a/assets/js/pages/services.js +++ b/assets/js/pages/services.js @@ -95,7 +95,13 @@ App.Pages.Services = (function () { $services.find('.results').sortable({ update: function(ev,ui){ resetForm(); - sort(ui.item.data('id'),ui.item.index()) + var afterId; + if (ui.item.index( )== 0) + afterId = -1; + else { + afterId = ui.item.prev('.service-row').data('id'); + } + sort(ui.item.data('id'), afterId) .catch(err => { $(this).sortable('cancel'); $services.find('.form-message').addClass('alert-danger').text(lang('error')).show(); @@ -228,13 +234,13 @@ App.Pages.Services = (function () { * * @param {Number} serviceId Id of service to sort * - * @param {Number} newOrder New place in order + * @param {Number} afterId Id of service to place after * * @return {Promise} */ - function sort(serviceId, newOrder){ - return App.Http.Services.sort(serviceId,newOrder, - $services.find('.results > .service-row').map((i,e)=> e.dataset['id']).get()) + function sort(serviceId, afterId){ + + return App.Http.Services.sort(serviceId, afterId) .then(response => { App.Layouts.Backend.displayNotification(lang('service_saved')); return response.row_order;