diff options
author | Simon Rettberg | 2017-04-13 18:08:31 +0200 |
---|---|---|
committer | Simon Rettberg | 2017-04-13 18:08:31 +0200 |
commit | faf18b816b6fecce5ab5023a2d87fe1f2d44f132 (patch) | |
tree | 7f48d583c9efe5b4d7e528654e69f1123e88dd70 /modules-available | |
parent | [locations] Return recursive list of children in getLocationsAssoc() (diff) | |
download | slx-admin-faf18b816b6fecce5ab5023a2d87fe1f2d44f132.tar.gz slx-admin-faf18b816b6fecce5ab5023a2d87fe1f2d44f132.tar.xz slx-admin-faf18b816b6fecce5ab5023a2d87fe1f2d44f132.zip |
[locationinfo] Refactor the main view
- Simplify javascript
- Remove client count and locationid column from view, not useful for
the average user
- Remove/simplify queries, use Location helper more to deal with locations
Diffstat (limited to 'modules-available')
5 files changed, 144 insertions, 210 deletions
diff --git a/modules-available/locationinfo/inc/locationinfo.inc.php b/modules-available/locationinfo/inc/locationinfo.inc.php index f924e469..9bd5ff5b 100644 --- a/modules-available/locationinfo/inc/locationinfo.inc.php +++ b/modules-available/locationinfo/inc/locationinfo.inc.php @@ -6,7 +6,7 @@ class LocationInfo /** * Gets the pc data and returns it's state. * - * @param $pc The pc data from the db. Array('logintime' =>, 'lastseen' =>, 'lastboot' =>) + * @param array $pc The pc data from the db. Array('logintime' =>, 'lastseen' =>, 'lastboot' =>) * @return int pc state */ public static function getPcState($pc) diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php index 88a762a8..8714bd34 100644 --- a/modules-available/locationinfo/page.inc.php +++ b/modules-available/locationinfo/page.inc.php @@ -53,13 +53,6 @@ class Page_LocationInfo extends Page Util::redirect('?do=locationinfo&action=infoscreen'); } - if ($getAction === 'hide') { - $roomId = Request::get('id', 0, 'int'); - $hiddenValue = Request::get('value', 0, 'int'); - $this->toggleHidden($roomId, $hiddenValue); - Util::redirect('?do=locationinfo&action=infoscreen#row' . $roomId); - } - } /** @@ -341,79 +334,45 @@ class Page_LocationInfo extends Page /** * Sets the new hidden value and checks childs and parents. * - * @param $id The location id which was toggled - * @param $val The hidden value true / false + * @param int $id The location id which was toggled + * @param bool $hidden The hidden value true / false */ - protected function toggleHidden($id, $val) + protected function toggleHidden($id, $hidden) { - Database::exec("INSERT INTO `location_info` (locationid, hidden) VALUES (:id, :hidden) ON DUPLICATE KEY UPDATE hidden=:hidden", array('id' => $id, - 'hidden' => $val)); - - $this->checkChildRecursive($id, $val); - $this->checkParentRecursive($id); - - } - - /** - * Recursivly sets all hidden values to all childs. - * - * @param $id The location id which childs should be checked - * @param $val The hidden value - */ - protected function checkChildRecursive($id, $val) - { - $dbquery = Database::simpleQuery("SELECT locationid FROM `location` WHERE parentlocationid = :locationid", array('locationid' => $id)); - $childs = array(); - while ($dbdata = $dbquery->fetch(PDO::FETCH_ASSOC)) { - $childs[] = $dbdata['locationid']; - } - - foreach ($childs as $key) { - Database::exec("INSERT INTO `location_info` (locationid, hidden) VALUES (:id, :hidden) ON DUPLICATE KEY UPDATE hidden=:hidden", array('id' => $key, - 'hidden' => $val)); - - $this->checkChildRecursive($key, $val); - } - } - - /** - * Recursively check all parent locations and updates the hidden values if necessary - * - * @param $id The id of the location which was toggled. - */ - protected function checkParentRecursive($id) - { - $dbquery = Database::simpleQuery("SELECT parentlocationid FROM `location` WHERE locationid = :locationid", array('locationid' => $id)); - $parent = 0; - while ($dbdata = $dbquery->fetch(PDO::FETCH_ASSOC)) { - $parent = (int)$dbdata['parentlocationid']; - } - if ($parent === 0) { - return; - } else { - $dbq = Database::simpleQuery("SELECT COUNT(CASE li.hidden WHEN '0' THEN 1 ELSE NULL END) AS '0', - COUNT(CASE li.hidden WHEN '1' THEN 1 ELSE NULL END) AS '1', - COUNT(*) - COUNT(CASE li.hidden WHEN '0' THEN 1 ELSE NULL END) - COUNT(CASE li.hidden WHEN '1' THEN 1 ELSE NULL END) AS 'NULL' - FROM `location` AS l LEFT JOIN `location_info` AS li ON l.locationid=li.locationid - WHERE parentlocationid = :parentId;", array('parentId' => $parent)); - $amountofzero = 0; - $amountofnull = 0; - - while ($dbd = $dbq->fetch(PDO::FETCH_ASSOC)) { - $amountofzero = (int)$dbd['0']; - $amountofnull = (int)$dbd['NULL']; - } - - if ($amountofzero == 0 AND $amountofnull == 0) { - Database::exec("INSERT INTO `location_info` (locationid, hidden) VALUES (:id, :hidden) ON DUPLICATE KEY UPDATE hidden=:hidden", array('id' => $parent, - 'hidden' => 1)); - } else { - Database::exec("INSERT INTO `location_info` (locationid, hidden) VALUES (:id, :hidden) ON DUPLICATE KEY UPDATE hidden=:hidden", array('id' => $parent, - 'hidden' => 0)); - } - - $this->checkParentRecursive($parent); - } + $locs = Location::getLocationsAssoc(); + if (!isset($locs[$id])) + die('Invalid location id'); + $loc = $locs[$id]; + + // The JSON to return, telling the client which locationids to update in the view + $return = array(); + $return[] = array('locationid' => $id, 'hidden' => $hidden); + + // Update the location, plus all child locations + $qs = '(?,?)' . str_repeat(',(?,?)', count($loc['children'])); + $params = array($id, $hidden); + foreach ($loc['children'] as $child) { + $params[] = $child; + $params[] = $hidden; + $return[] = array('locationid' => $child, 'hidden' => $hidden); + } + Database::exec("INSERT INTO location_info (locationid, hidden) + VALUES $qs ON DUPLICATE KEY UPDATE hidden = VALUES(hidden)", $params); + + // Handle parents - uncheck if not all children are checked + while ($loc['parentlocationid'] != 0) { + $stats = Database::queryFirst('SELECT Count(*) AS total, Sum(li.hidden > 0) AS hidecount FROM location l + LEFT JOIN location_info li USING (locationid) + WHERE l.parentlocationid = :parent', array('parent' => $loc['parentlocationid'])); + $hidden = ($stats['total'] == $stats['hidecount']) ? 1 : 0; + $params = array('locationid' => $loc['parentlocationid'], 'hidden' => $hidden); + Database::exec('INSERT INTO location_info (locationid, hidden) + VALUES (:locationid, :hidden) ON DUPLICATE KEY UPDATE hidden = VALUES(hidden)', $params); + $return[] = $params; + $loc = $locs[$loc['parentlocationid']]; + } + error_log(print_r($return, true)); + return $return; } /** @@ -421,89 +380,47 @@ class Page_LocationInfo extends Page */ protected function getInfoScreenTable() { + $locations = Location::getLocations(0, 0, false, true); - // Get a table with the needed location info. name, id, hidden, pcState (Count of pcs that are in use), total pcs - $dbquery = Database::simpleQuery("SELECT l.locationname, l.locationid, li.hidden, m.pcState, m.total FROM `location_info` AS li - RIGHT JOIN `location` AS l ON li.locationid=l.locationid LEFT JOIN - (SELECT locationid, Count(CASE m.logintime WHEN NOT 1 THEN NULL ELSE 1 END) AS pcState, Count(*) AS total FROM `machine` AS m - WHERE locationid IS NOT NULL GROUP BY locationid) AS m ON l.locationid=m.locationid"); - $pcs = array(); - - if (Module::isAvailable('locations')) { - foreach (Location::getLocations() as $loc) { - $data = array(); - $data['locationid'] = (int)$loc['locationid']; - $data['locationname'] = $loc['locationname']; - $data['depth'] = $loc['depth']; - $data['hidden'] = null; - $locid = (int)$loc['locationid']; - $pcs[$locid] = $data; - } - } - - while ($roominfo = $dbquery->fetch(PDO::FETCH_ASSOC)) { - $locid = (int)$roominfo['locationid']; + // Get hidden state of all locations + $dbquery = Database::simpleQuery("SELECT li.locationid, li.hidden FROM `location_info` AS li"); - if ($roominfo['hidden'] == null) { - $pcs[$locid]['hidden'] = 0; - } else { - $pcs[$locid]['hidden'] = $roominfo['hidden']; - } - - if ($roominfo['pcState'] != null) { - $pcs[$locid]['pcState'] = $roominfo['pcState']; - } - if ($roominfo['total'] != null) { - $pcs[$locid]['total'] = $roominfo['total']; - $pcs[$locid]['hasPcs'] = true; - } else { - $pcs[$locid]['hasPcs'] = false; - } + while ($row = $dbquery->fetch(PDO::FETCH_ASSOC)) { + $locid = (int)$row['locationid']; + $locations[$locid]['hidden_checked'] = $row['hidden'] != 0 ? 'checked' : ''; } // Get a list of all the backend types. $servertypes = array(); $s_list = CourseBackend::getList(); foreach ($s_list as $s) { - $t['type'] = $s; $typeInstance = CourseBackend::getInstance($s); - $t['display'] = $typeInstance->getDisplayName(); - $servertypes[] = $t; + $servertypes[$s] = $typeInstance->getDisplayName(); } - // Get the Serverlist from the DB and make it mustache accesable + // Get the Serverlist from the DB and make it mustache accessable $serverlist = array(); $dbquery2 = Database::simpleQuery("SELECT * FROM `setting_location_info`"); - while ($db = $dbquery2->fetch(PDO::FETCH_ASSOC)) { - $server['id'] = $db['serverid']; - $server['name'] = $db['servername']; - $server['type'] = $db['servertype']; - foreach ($servertypes as $type) { - if ($server['type'] == $type['type']) { - $server['display'] = $type['display']; - break; + while ($row = $dbquery2->fetch(PDO::FETCH_ASSOC)) { + $row['typename'] = $servertypes[$row['servertype']]; + + if (!empty($row['error'])) { + $row['autherror'] = true; + $error = json_decode($row['error'], true); + if (isset($error['timestamp'])) { + $time = date('Y/m/d H:i:s', $error['timestamp']); + } else { + $time = '???'; } + Message::addError('auth-failed', $row['servername'], $time, $error['error']); } - - if ($db['error'] == null) { - $server['auth'] = true; - } else { - $server['auth'] = false; - $error = json_decode($db['error'], true); - - $time = date('Y/m/d H:i:s', $error['timestamp']); - - Message::addError('auth-failed', $server['name'], $time, $error['error']); - } - - $server['url'] = $db['serverurl']; - $serverlist[] = $server; + $serverlist[] = $row; } // Pass the data to the html and render it. Render::addTemplate('location-info', array( - 'list' => array_values($pcs), - 'serverlist' => array_values($serverlist), + 'list' => array_values($locations), + 'serverlist' => $serverlist, )); } @@ -526,10 +443,26 @@ class Page_LocationInfo extends Page } elseif ($action === 'serverSettings') { $id = Request::any('id', 0, 'int'); $this->ajaxServerSettings($id); + } elseif ($action === 'hide') { + $this->ajaxHideLocation(); } } /** + * Request to deny displaying the door sign for the + * given location. Sends a list of all affected + * locations, so the client can update its view. + */ + private function ajaxHideLocation() + { + $locationId = Request::post('locationid', 0, 'int'); + $hidden = Request::post('hidden', 0, 'int'); + Header('Content-Type: application/json; charset=utf-8'); + $ret = $this->toggleHidden($locationId, $hidden); + echo json_encode(array('changed' => $ret)); + } + + /** * Ajax the server settings. * * @param $id Serverid diff --git a/modules-available/locationinfo/templates/config.html b/modules-available/locationinfo/templates/config.html index 0c970f2a..e97b72fc 100644 --- a/modules-available/locationinfo/templates/config.html +++ b/modules-available/locationinfo/templates/config.html @@ -18,7 +18,7 @@ <select class="form-control" name="serverid"> <option value="0">{{lang_noServer}}</option> {{#serverlist}} - <option value="{{sid}}" {{selected}}>{{servername}}</option> + <option value="{{serverid}}" {{selected}}>{{servername}}</option> {{/serverlist}} </select> </div> @@ -319,17 +319,21 @@ </form> <script type="text/javascript"><!-- - - var customURL = window.location.protocol + "//" + window.location.hostname + "/slx-admin/modules/locationinfo/frontend/doorsign.html?id={{id}}"; - $('#custom-url').val(customURL); + // Get list of form elements which affect the generated custom URL var $inputs = $('.modify-inputs input, .modify-inputs select'); + // Base for displaying the custom URL + var customURL = window.location.protocol + "//" + window.location.hostname + "/slx-admin/modules/locationinfo/frontend/doorsign.html?id={{id}}"; + // Initialize fancy tooltips $('a.helptext').tooltip(); + // Add listener to range sliders so their label can be updated $('input[type="range"]').change(function () { $(this).siblings().find('.range-display').text($(this).val()); }); + // Set state of input controls that aren't statically initialized server side loadValues(); + // Update the custom URL buildCustomUrl(); - + // Add listener to all the elements affecting custom URL $inputs.change(function () { $this = $(this); if ($this.attr('type') === 'hidden') diff --git a/modules-available/locationinfo/templates/location-info.html b/modules-available/locationinfo/templates/location-info.html index 5b5e3e24..c27b4b12 100644 --- a/modules-available/locationinfo/templates/location-info.html +++ b/modules-available/locationinfo/templates/location-info.html @@ -14,33 +14,32 @@ <th width="1"></th> </tr> {{#serverlist}} - <form method="post" action="?do=locationinfo" id="serverForm-{{id}}"> + <form method="post" action="?do=locationinfo" id="serverForm-{{serverid}}"> <input type="hidden" name="token" value="{{token}}"> - <input id="serverFormAction-{{id}}" type="hidden" name="action" value="updateServer"> - <input type="submit" id="submit-serverForm-{{id}}" style="display:none;"> + <input id="serverFormAction-{{serverid}}" type="hidden" name="action" value="updateServer"> + <input type="submit" id="submit-serverForm-{{serverid}}" style="display:none;"> <tr> - <input id="input-id-{{id}}" name="id" type="hidden" value="{{id}}"> - <td id="type-{{id}}" nowrap>{{display}}</td> - <td id="name-{{id}}" nowrap>{{name}}</td> - <td id="url-{{id}}" nowrap>{{url}}</td> - - <td align="center" id="credentials-{{id}}" onclick="event.cancelBubble = true;" - style="white-space:nowrap;"> - <button class="btn btn-sm {{#auth}}btn-success{{/auth}}{{^auth}}btn-danger{{/auth}}" - id="credentials-btn-{{id}}" type="button" onclick="loadSettingsModal({{id}},'{{name}}');"> + <input id="input-id-{{serverid}}" name="id" type="hidden" value="{{serverid}}"> + <td id="type-{{serverid}}" nowrap>{{typename}}</td> + <td id="name-{{serverid}}" nowrap>{{servername}}</td> + <td id="url-{{serverid}}" nowrap>{{serverurl}}</td> + + <td align="center" id="credentials-{{serverid}}" style="white-space:nowrap;"> + <button class="btn btn-sm {{^autherror}}btn-success{{/autherror}}{{#autherror}}btn-danger{{/autherror}}" + id="credentials-btn-{{serverid}}" type="button" onclick="loadSettingsModal({{serverid}},'{{servername}}');"> <span style="margin-right: 5px;" class="glyphicon glyphicon-cog"></span> {{lang_locationSettings}} </button> - <button class="btn btn-sm btn-primary table-refresh" id="refresh-btn-{{id}}" - title="{{lang_refresh_title}}" onclick="refreshButtonClick({{id}});"> - <span id="refresh-btn-animate-{{id}}" style="margin-right: 5px;" + <button class="btn btn-sm btn-primary table-refresh" id="refresh-btn-{{serverid}}" + title="{{lang_refresh_title}}" onclick="refreshButtonClick({{serverid}});"> + <span id="refresh-btn-animate-{{serverid}}" style="margin-right: 5px;" class="glyphicon glyphicon-refresh"></span> {{lang_refresh}} </button> </td> - <td align="center" id="btncell-{{id}}" style="white-space:nowrap;"> - <button class="btn btn-sm btn-danger table-delete" type="button" onclick="deleteButtonClick({{id}});"> + <td align="center" id="btncell-{{serverid}}" style="white-space:nowrap;"> + <button class="btn btn-sm btn-danger table-delete" type="button" onclick="deleteButtonClick({{serverid}});"> <span style="margin-right: 5px;" class="glyphicon glyphicon-remove"></span> {{lang_delete}} </button> @@ -73,8 +72,6 @@ <tr> <th>{{lang_locationName}}</th> - <th width="10">{{lang_locationID}}</th> - <th width="80">{{lang_locationInUse}}</th> <th width="50" title="{{lang_locationIsHidden_title}}">{{lang_locationIsHidden}}</th> <th width="50">{{lang_openingTime}}</th> <th width="50">{{lang_locationSettings}}</th> @@ -82,35 +79,20 @@ {{#list}} <tr id="row{{locationid}}"> - <td> <div style="display:inline-block;width:{{depth}}em"></div> - <a href="modules/locationinfo/frontend/doorsign.html?id={{locationid}}">{{locationname}}</a></td> - <td align="center">[{{locationid}}]</td> - <td align="center">{{#hasPcs}}{{pcState}} / {{total}}{{/hasPcs}}</td> - - <td id="{{locationid}}" onclick="event.cancelBubble = true;" align="center"></td> - <script> - var cbh = document.getElementById('{{locationid}}'); - var cb = document.createElement('input'); - - cb.type = 'checkbox'; - cbh.appendChild(cb); - - cb.id = 'cb' + {{locationid}}; - cb.value = {{hidden}}; - if ({{hidden}} == 1) { - cb.checked = true; - } - cb.addEventListener("click", function() { cbClick(this, {{locationid}}); }); - </script> - <td onclick="event.cancelBubble = true;"> + <a href="modules/locationinfo/frontend/doorsign.html?id={{locationid}}">{{locationname}}</a> + </td> + <td align="center"> + <input class="hidden-toggle" type="checkbox" data-locationid="{{locationid}}" {{hidden_checked}}> + </td> + <td> <a class="btn btn-sm btn-default" role="button" style="width: 100%" onclick="loadTimeModal({{locationid}}, '{{locationname}}');"> <span style="margin-right: 5px;" class="glyphicon glyphicon-time"></span> </a> </td> - <td onclick="event.cancelBubble = true;"> + <td> <a class="btn btn-sm btn-default" role="button" style="width: 100%;" onclick="loadConfigModal({{locationid}}, '{{locationname}}');"> <span style="margin-right: 5px;" class="glyphicon glyphicon-cog"></span> @@ -138,23 +120,43 @@ </div> </div> <script type="text/javascript"><!-- - var lastPcSubTable = false; + + document.addEventListener("DOMContentLoaded", function () { + + /** + * React to click on a "hidden" checkbox. + */ + $('.hidden-toggle').change(function() { + $input = $(this); + $.ajax({ + type: 'POST', + url: '?do=locationinfo&action=hide', + data: {locationid: $input.data('locationid'), hidden: $input[0].checked ? 1 : 0, token: TOKEN }, + dataType: 'json' + }).done(function(data) { + if (data && $.isArray(data.changed)) { + markBoxes(data.changed); + } else { + $input.replaceWith('ERROR'); + } + }).fail(function () { + $input.replaceWith('ERROR'); + }); + }); + + }); /** - * Sets the checkbox value and calls the php hide action. - * - * @param cb The checkbox which was clicked. - * @param locID the locationID of the checkbox. + * Gets a status array delivered by backend's ajaxHideLocation() + * and sets the checkbox states accordingly. */ - function cbClick(cb, locID) { - var value; - - if (cb.checked) { - value = 1; - } else { - value = 0; + function markBoxes(boxArray) { + for (var i = 0; i < boxArray.length; ++i) { + if (boxArray[i].locationid) { + var lid = parseInt(boxArray[i].locationid); + $('input.hidden-toggle[data-locationid="' + lid + '"]').prop('checked', !!boxArray[i].hidden); + } } - window.location.href = "?do=locationinfo&action=hide&id=" + locID + "&value=" + value; } /** @@ -199,11 +201,6 @@ } // ########### Server Table ########### - var preEditName; - var preEditUrl; - var preEditUser; - var preEditPassword; - var preEditType; /** * Deletes a server. @@ -224,7 +221,7 @@ * @param id The id of the server. */ function refreshButtonClick(id) { - $('#refresh-btn-animate-' + id).addClass('glyphicon-refresh-animate'); + $('#refresh-btn-animate-' + id).addClass('slx-rotation'); $('#serverFormAction-' + id).val("checkConnection"); $('#submit-serverForm-' + id).trigger("click"); } diff --git a/modules-available/locationinfo/templates/server-settings.html b/modules-available/locationinfo/templates/server-settings.html index a3e81272..c135543f 100644 --- a/modules-available/locationinfo/templates/server-settings.html +++ b/modules-available/locationinfo/templates/server-settings.html @@ -84,7 +84,7 @@ type = $('#input-type-{{id}}').val(); } - loadCredentials(); + loadCredentials(true); initalizeBootstrap(); /** @@ -101,7 +101,7 @@ * * @param {bool} useValue If false the form elements will be empty. Default = true. */ - function loadCredentials(useValue = true) { + function loadCredentials(useValue) { // {{name}} name of auth {{type}} type of auth (string, int etc.) {{value}} value from the db {{#backendList}} if (type == "{{typ}}") { |