diff --git a/app/controllers/start.php b/app/controllers/start.php index f47520297c16a46ba98d15962fce31dae5cad089..e48bc899a25b10af9381069004c544542743c55a 100644 --- a/app/controllers/start.php +++ b/app/controllers/start.php @@ -255,16 +255,17 @@ class StartController extends AuthenticatedController /** * Action to store the widget placements - * - * @return void */ - public function storeNewOrder_action() + public function storeNewOrder_action(): void { - WidgetHelper::storeNewPositions( - Request::get('widget'), - Request::get('position'), - Request::get('column') - ); + if (!Request::isPost()) { + throw new MethodNotAllowedException(); + } + + $lanes = Request::getArray('lanes'); + + WidgetHelper::storeNewPositions($lanes); + $this->render_nothing(); } diff --git a/lib/classes/WidgetHelper.php b/lib/classes/WidgetHelper.php index 2122a60c763c1a33489e7303c02de8b51a23eb98..548184ebb6b83968827f5ba0b4ec2e71a81d13ec 100644 --- a/lib/classes/WidgetHelper.php +++ b/lib/classes/WidgetHelper.php @@ -63,37 +63,48 @@ class WidgetHelper /** * storeNewPositions - stores new Widget positions for a given user * - * @param array ids of widgets to be stored + * @param array $lanes array with column as index and ids array as value * * @return void */ - public static function storeNewPositions($widget, $position, $column) + public static function storeNewPositions(array $lanes): void { - $db = DBManager::get(); - $oldWidget = $db->fetchOne("SELECT position,col FROM widget_user WHERE id = ? AND range_id = ?", [$widget, $GLOBALS['user']->id]); - if ($oldWidget) { - - if ($oldWidget['col'] == $column) { - // Insert element - $db->execute("UPDATE widget_user SET position = ? WHERE id = ? ", [$position, $widget]); - if ($oldWidget['position'] < $position) { - //Move back items BETWEEN old and new position - $db->execute("UPDATE widget_user SET position = position - 1 WHERE col = ? AND range_id = ? AND position > ? AND position <= ? AND id <> ?", [$oldWidget['col'], $GLOBALS['user']->id, $oldWidget['position'], $position, $widget]); - } else { - //Move forward items BETWEEN old and new position - $db->execute("UPDATE widget_user SET position = position + 1 WHERE col = ? AND range_id = ? AND position < ? AND position >= ? AND id <> ?", [$oldWidget['col'], $GLOBALS['user']->id, $oldWidget['position'], $position, $widget]); - } - } else { - // Push all entries in the new column one position away - $db->execute("UPDATE widget_user SET position = position + 1 WHERE range_id = ? AND col = ? AND position >= ?", [$GLOBALS['user']->id, $column, $position]); + // Query not displayed widgets to sort them to the bottom of a lane + $query = "SELECT `col`, `id` + FROM `widget_user` + WHERE `range_id` = ? + AND `id` NOT IN (?) + ORDER BY `col`, `position`"; + $undisplayed = DBManager::get()->fetchGrouped($query, [ + User::findCurrent()->id, + array_merge(...$lanes) + ], function ($row) { + return array_column($row, 'id'); + }); + + // Set new positions + $query = "UPDATE `widget_user` + SET `col` = :column, + `position` = :position + WHERE `id` = :id + AND `range_id` = :user_id"; + $statement = DBManager::get()->prepare($query); + $statement->bindValue(':user_id', User::findCurrent()->id); - // Insert element - $db->execute("UPDATE widget_user SET position = ?, col = ? WHERE id = ? ", [$position, $column, $widget]); + foreach ([0, 1] as $column) { + $statement->bindValue(':column', $column); - // Move positions in old column - $db->execute("UPDATE widget_user SET position = position - 1 WHERE col = ? AND range_id = ? AND position > ?", [$oldWidget['col'], $GLOBALS['user']->id, $oldWidget['position']]); - } + $ids = array_merge( + $lanes[$column] ?? [], + $undisplayed[$column] ?? [] + ); + $position = 0; + foreach ($ids as $id) { + $statement->bindValue(':position', $position++); + $statement->bindValue(':id', $id); + $statement->execute(); + } } } diff --git a/resources/assets/javascripts/lib/startpage.js b/resources/assets/javascripts/lib/startpage.js index 15b2c591acea40aa13417ccc901dcc6cf7513cbb..1d7de31fa82871afc6757f7a63cd7048df783e1b 100644 --- a/resources/assets/javascripts/lib/startpage.js +++ b/resources/assets/javascripts/lib/startpage.js @@ -1,22 +1,31 @@ const startpage = { - init: function() { + init() { $('.start-widgetcontainer .portal-widget-list').sortable({ handle: '.widget-header', connectWith: 'ul.portal-widget-list', - start: function() { + start() { $(this) .closest('.start-widgetcontainer') .find('.portal-widget-list') - .addClass('ui-sortable move'); + .addClass('move'); }, - stop: function(event, ui) { - $.get(STUDIP.ABSOLUTE_URI_STUDIP + 'dispatch.php/start/storeNewOrder', { - widget: $(ui.item).attr('id'), - position: $(ui.item).index(), - column: $(ui.item) - .parent() - .index() - }); + update(event, ui) { + let lanes = []; + $(this) + .closest('.start-widgetcontainer') + .children('.portal-widget-list') + .each((index, element) => { + lanes[index] = $('.studip-widget-wrapper', element) + .map((i, el) => el.getAttribute('id')) + .get(); // Ensure we have an array + }); + + $.post( + STUDIP.URLHelper.getURL('dispatch.php/start/storeNewOrder'), + {lanes} + ); + }, + stop() { $(this) .closest('.start-widgetcontainer') .find('.portal-widget-list') @@ -25,7 +34,7 @@ const startpage = { }); }, - init_edit: function(perm) { + init_edit(perm) { $('.edit-widgetcontainer .portal-widget-list').sortable({ handle: '.widget-header', connectWith: '.edit-widgetcontainer .portal-widget-list',