diff options
Diffstat (limited to 'modules-available/locationinfo')
13 files changed, 304 insertions, 189 deletions
diff --git a/modules-available/locationinfo/api.inc.php b/modules-available/locationinfo/api.inc.php index a89f16ed..ceaf04c0 100644 --- a/modules-available/locationinfo/api.inc.php +++ b/modules-available/locationinfo/api.inc.php @@ -175,10 +175,10 @@ function getCalendar($idList) foreach ($serverList as $serverid => $server) { $serverInstance = CourseBackend::getInstance($server['type']); if ($serverInstance === false) { - EventLog::warning('Cannot fetch schedule for locationid ' . $server['locationid'] + EventLog::warning('Cannot fetch schedule for location (' . implode(', ', $server['idlist']) . ')' . ': Backend type ' . $server['type'] . ' unknown. Disabling location.'); - Database::exec("UPDATE locationinfo_locationconfig SET serverid = 0 WHERE locationid = :lid", - array('lid' => $server['locationid'])); + Database::exec("UPDATE locationinfo_locationconfig SET serverid = NULL WHERE locationid IN (:lid)", + array('lid' => $server['idlist'])); continue; } $credentialsOk = $serverInstance->setCredentials($serverid, $server['credentials']); diff --git a/modules-available/locationinfo/frontend/frontendscript.js b/modules-available/locationinfo/frontend/frontendscript.js new file mode 100644 index 00000000..cc5c6827 --- /dev/null +++ b/modules-available/locationinfo/frontend/frontendscript.js @@ -0,0 +1,83 @@ +/** + * checks if a room is on a given date/time open + * @param date Date Object + * @param room Room object + * @returns {Boolean} for open or not + */ +function IsOpen(date, room) { + if (!room.openingTimes || room.openingTimes.length === 0) return true; + var tmp = room.openingTimes[date.getDay()]; + if (!tmp) return false; + var openDate = new Date(date.getTime()); + var closeDate = new Date(date.getTime()); + for (var i = 0; i < tmp.length; i++) { + openDate.setHours(tmp[i].HourOpen); + openDate.setMinutes(tmp[i].MinutesOpen); + closeDate.setHours(tmp[i].HourClose); + closeDate.setMinutes(tmp[i].MinutesClose); + if (openDate < date && closeDate > date) { + return true; + } + } + return false; +} + +/** + * Convert passed argument to integer if possible, return NaN otherwise. + * The difference to parseInt() is that leading zeros are ignored and not + * interpreted as octal representation. + * + * @param str string or already a number + * @return {number} str converted to number, or NaN + */ +function toInt(str) { + var t = typeof str; + if (t === 'number') return str | 0; + if (t === 'string') return parseInt(str.replace(/^0+([^0])/, '$1')); + return NaN; +} + +/** + * used for countdown + * computes the time difference between 2 Date objects + * @param {Date} a + * @param {Date} b + * @param {Array} globalConfig + * @returns {string} printable time + */ +function GetTimeDiferenceAsString(a, b, globalConfig = null) { + if (!a || !b) { + return ""; + } + var milliseconds = a.getTime() - b.getTime(); + var days = Math.floor((milliseconds / (1000 * 60 * 60 * 24)) % 31); + if (days !== 0) { + // don't show? + return ""; + } + var seconds = Math.floor((milliseconds / 1000) % 60); + milliseconds -= seconds * 1000; + var minutes = Math.floor((milliseconds / (1000 * 60)) % 60); + milliseconds -= minutes * 1000 * 60; + var hours = Math.floor((milliseconds / (1000 * 60 * 60)) % 24); + + if (globalConfig && globalConfig.prettytime) { + var str = ''; + if (hours > 0) { + str += hours + 'h '; + } + str += minutes + 'min '; + return str; + } + + if (minutes < 10) { + minutes = "0" + minutes; + } + if (globalConfig && globalConfig.eco) { + return hours + ":" + minutes; + } + if (seconds < 10) { + seconds = "0" + seconds; + } + return hours + ":" + minutes + ":" + seconds; +}
\ No newline at end of file diff --git a/modules-available/locationinfo/inc/coursebackend.inc.php b/modules-available/locationinfo/inc/coursebackend.inc.php index 1fe87202..7162c885 100644 --- a/modules-available/locationinfo/inc/coursebackend.inc.php +++ b/modules-available/locationinfo/inc/coursebackend.inc.php @@ -47,17 +47,20 @@ abstract class CourseBackend foreach (glob(dirname(__FILE__) . '/coursebackend/coursebackend_*.inc.php', GLOB_NOSORT) as $file) { require_once $file; preg_match('#coursebackend_([^/\.]+)\.inc\.php$#i', $file, $out); - if (!class_exists('coursebackend_' . $out[1])) { - trigger_error("Backend type source unit $file doesn't seem to define class CourseBackend_{$out[1]}", E_USER_ERROR); + $className = 'CourseBackend_' . $out[1]; + if (!class_exists($className)) { + trigger_error("Backend type source unit $file doesn't seem to define class $className", E_USER_ERROR); } + if (!CONFIG_DEBUG && defined("$className::DEBUG") && constant("$className::DEBUG")) + continue; self::$backendTypes[$out[1]] = true; } } /** - * Get all known config module types. + * Get all known backend types. * - * @return array list of modules + * @return array list of backends */ public static function getList() { @@ -65,24 +68,30 @@ abstract class CourseBackend return array_keys(self::$backendTypes); } + public static function exists($backendType) + { + self::loadDb(); + return isset(self::$backendTypes[$backendType]); + } + /** - * Get fresh instance of ConfigModule subclass for given module type. + * Get fresh instance of CourseBackend subclass for given backend type. * - * @param string $moduleType name of module type - * @return \CourseBackend module instance + * @param string $backendType name of module type + * @return \CourseBackend|false module instance */ - public static function getInstance($moduleType) + public static function getInstance($backendType) { self::loadDb(); - if (!isset(self::$backendTypes[$moduleType])) { - error_log('Unknown module type: ' . $moduleType); + if (!isset(self::$backendTypes[$backendType])) { + error_log('Unknown module type: ' . $backendType); return false; } - if (!is_object(self::$backendTypes[$moduleType])) { - $class = "coursebackend_$moduleType"; - self::$backendTypes[$moduleType] = new $class; + if (!is_object(self::$backendTypes[$backendType])) { + $class = "coursebackend_$backendType"; + self::$backendTypes[$backendType] = new $class; } - return self::$backendTypes[$moduleType]; + return self::$backendTypes[$backendType]; } /** @@ -131,6 +140,19 @@ abstract class CourseBackend */ protected abstract function fetchSchedulesInternal($roomId); + private static function fixTime(&$start, &$end) + { + if (!preg_match('/^\d+-\d+-\d+T\d+:\d+:\d+$/', $start) || !preg_match('/^\d+-\d+-\d+T\d+:\d+:\d+$/', $start)) + return false; + $start = strtotime($start); + $end = strtotime($end); + if ($start >= $end) + return false; + $start = date('Y-m-d\TH:i:s', $start); + $end = date('Y-m-d\TH:i:s', $end); + return true; + } + /** * Method for fetching the schedule of the given rooms on a server. * @@ -184,18 +206,31 @@ abstract class CourseBackend return false; } - if ($this->getCacheTime() > 0) { - // Caching requested by backend, write to DB - foreach ($backendResponse as $serverRoomId => $calendar) { + foreach ($backendResponse as $serverRoomId => &$calendar) { + $calendar = array_values($calendar); + for ($i = 0; $i < count($calendar); ++$i) { + if (empty($calendar[$i]['title'])) { + $calendar[$i]['title'] = '-'; + } + if (!self::fixTime($calendar[$i]['start'], $calendar[$i]['end'])) { + error_log("Ignoring calendar entry '{$calendar[$i]['title']}' with bad time format"); + unset($calendar[$i]); + } + } + $calendar = array_values($calendar); + if ($this->getCacheTime() > 0) { + // Caching requested by backend, write to DB $value = json_encode($calendar); Database::simpleQuery("UPDATE locationinfo_locationconfig SET calendar = :ttable, lastcalendarupdate = :now - WHERE serverid = :serverid AND serverlocationid = :serverlocationid", array( + WHERE serverid = :serverid AND serverlocationid = :serverlocationid", array( 'serverid' => $this->serverId, 'serverlocationid' => $serverRoomId, 'ttable' => $value, 'now' => $NOW )); } + + unset($calendar); } // Add rooms that were requested to the final return value foreach ($remoteIds as $location => $serverRoomId) { @@ -302,6 +337,9 @@ abstract class CourseBackend $xml = new SimpleXMLElement($cleanresponse); } catch (Exception $e) { $this->error = 'Could not parse reply as XML, got ' . get_class($e) . ': ' . $e->getMessage(); + if (CONFIG_DEBUG) { + error_log($cleanresponse); + } return false; } $array = json_decode(json_encode((array)$xml), true); diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php index fac3f296..8843e372 100644 --- a/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php +++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php @@ -106,6 +106,9 @@ class CourseBackend_Davinci extends CourseBackend } $return = $this->xmlStringToArray($return); if ($return === false) { + if (CONFIG_DEBUG) { + error_log('Room was ' . $roomId); + } continue; } $lessons = $this->getArrayPath($return, '/Lessons/Lesson'); diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php index e2577284..adff8b1b 100644 --- a/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php +++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php @@ -4,6 +4,8 @@ class CourseBackend_Dummy extends CourseBackend { private $pw; + const DEBUG = true; + /** * uses json to setCredentials, the json must follow the form given in * getCredentials @@ -87,13 +89,24 @@ class CourseBackend_Dummy extends CourseBackend * * @param $roomIds array with local ID as key and serverId as value * @return array a recursive array that uses the roomID as key - * and has the schedule array as value. A shedule array contains an array in this format: - * ["start"=>'JJJJ-MM-DD HH:MM:SS',"end"=>'JJJJ-MM-DD HH:MM:SS',"title"=>string] + * and has the schedule array as value. A schedule array contains an array in this format: + * ["start"=>'YYYY-MM-DD<T>HH:MM:SS',"end"=>'YYYY-MM-DD<T>HH:MM:SS',"title"=>string] */ public function fetchSchedulesInternal($roomId) { $a = array(); foreach ($roomId as $id) { + if ($id == 1) { + $now = time(); + return array($id => array( + array( + 'title' => 'Lange', + 'start' => date('Y-m-d', $now) . 'T0:00:00', + 'end' => date('Y-m-d', $now + 86400 * 3) . 'T0:00:00', + ) + )); + } + // Normal $x = array(); $time = strtotime('today'); $end = strtotime('+7 days', $time); diff --git a/modules-available/locationinfo/inc/infopanel.inc.php b/modules-available/locationinfo/inc/infopanel.inc.php index 94f264bb..12b6aec7 100644 --- a/modules-available/locationinfo/inc/infopanel.inc.php +++ b/modules-available/locationinfo/inc/infopanel.inc.php @@ -45,17 +45,27 @@ class InfoPanel } $config['locations'] = array(); $lids = array_map('intval', explode(',', $panel['locationids'])); - foreach ($lids as $lid) { - $config['locations'][$lid] = array( - 'id' => $lid, - 'name' => isset($locations[$lid]) ? $locations[$lid]['locationname'] : 'noname00.pas', - ); - // Now apply any overrides from above - if (isset($overrides[$lid]) && is_array($overrides[$lid])) { - $config['locations'][$lid]['config'] = $overrides[$lid]; + // Locations - + if ($panel['paneltype'] === 'SUMMARY') { + $lids = Location::getRecursiveFlat($lids); + $lids = array_keys($lids); + foreach ($lids as $lid) { + $config['locations'][$lid] = array('id' => $lid); + } + } + if ($panel['paneltype'] === 'DEFAULT') { + foreach ($lids as $lid) { + $config['locations'][$lid] = array( + 'id' => $lid, + 'name' => isset($locations[$lid]) ? $locations[$lid]['locationname'] : 'noname00.pas', + ); + // Now apply any overrides from above + if (isset($overrides[$lid]) && is_array($overrides[$lid])) { + $config['locations'][$lid]['config'] = $overrides[$lid]; + } } + self::appendMachineData($config['locations'], $lids, true); } - self::appendMachineData($config['locations'], $lids, true); self::appendOpeningTimes($config['locations'], $lids); $config['ts'] = (int)$panel['lastchange']; diff --git a/modules-available/locationinfo/inc/locationinfo.inc.php b/modules-available/locationinfo/inc/locationinfo.inc.php index 64070cd4..2ed3622d 100644 --- a/modules-available/locationinfo/inc/locationinfo.inc.php +++ b/modules-available/locationinfo/inc/locationinfo.inc.php @@ -36,11 +36,7 @@ class LocationInfo $idArray = array_map('intval', explode(',', $panel['locationids'])); if ($panel['paneltype'] == "SUMMARY" && $recursive) { $idList = Location::getRecursiveFlat($idArray); - $idArray = array(); - - foreach ($idList as $key => $value) { - $idArray[] = $key; - } + $idArray = array_keys($idList); } return $idArray; } @@ -143,6 +139,7 @@ class LocationInfo ConfigHolder::add('SLX_SCREEN_STANDBY_TIMEOUT', '', 1000); ConfigHolder::add('SLX_SYSTEM_STANDBY_TIMEOUT', '', 1000); ConfigHolder::add('SLX_AUTOLOGIN', '1', 1000); + ConfigHolder::add('SLX_BROWSER_INSECURE', '1'); // TODO: Sat server might redirect to HTTPS, which in turn could have a self-signed cert - push to client } } diff --git a/modules-available/locationinfo/install.inc.php b/modules-available/locationinfo/install.inc.php index 7c47ac90..bbba3741 100644 --- a/modules-available/locationinfo/install.inc.php +++ b/modules-available/locationinfo/install.inc.php @@ -26,7 +26,7 @@ $t2 = $res[] = tableCreate('locationinfo_coursebackend', ' $t3 = $res[] = tableCreate('locationinfo_panel', " `paneluuid` char(36) CHARACTER SET ascii NOT NULL, `panelname` varchar(30) NOT NULL, - `locationids` varchar(20) CHARACTER SET ascii NOT NULL, + `locationids` varchar(100) CHARACTER SET ascii NOT NULL, `paneltype` enum('DEFAULT','SUMMARY', 'URL') NOT NULL, `panelconfig` blob NOT NULL, `lastchange` int(10) UNSIGNED NOT NULL DEFAULT 0, @@ -52,7 +52,7 @@ if ($t1 === UPDATE_NOOP) { if ($ret === false) { finalResponse(UPDATE_FAILED, 'Could not add lastchange field'); } elseif ($ret > 0) { - $ret[] = UPDATE_DONE; + $res[] = UPDATE_DONE; } } } @@ -71,6 +71,9 @@ if ($t1 === UPDATE_DONE) { if ($t3 === UPDATE_NOOP) { Database::exec("ALTER TABLE `locationinfo_panel` CHANGE `paneltype` `paneltype` ENUM('DEFAULT', 'SUMMARY', 'URL') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL"); + // 2017-12-02 expand locationids column + Database::exec("ALTER TABLE `locationinfo_panel` CHANGE `locationids` + `locationids` varchar(100) CHARACTER SET ascii NOT NULL"); } // 2017-07-26 Add servername key diff --git a/modules-available/locationinfo/lang/en/template-tags.json b/modules-available/locationinfo/lang/en/template-tags.json index 0d2b42a3..be927ee4 100644 --- a/modules-available/locationinfo/lang/en/template-tags.json +++ b/modules-available/locationinfo/lang/en/template-tags.json @@ -39,7 +39,7 @@ "lang_language": "Language", "lang_languageTooltip": "The language the frontend uses", "lang_locationName": "Name", - "lang_locationSettings": "Settings", + "lang_locationSettings": "Location specific settings", "lang_locations": "Locations", "lang_locationsTable": "Rooms \/ Locations", "lang_locationsTableHints": "Here you can define opening times for your locations and link the location ID to a configured backend (e.g. HISinOne) to show calendar events.", diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php index d6035869..c6aa0860 100644 --- a/modules-available/locationinfo/page.inc.php +++ b/modules-available/locationinfo/page.inc.php @@ -449,7 +449,7 @@ class Page_LocationInfo extends Page $locations = Location::getLocations(0, 0, false, true); // Get hidden state of all locations - $dbquery = Database::simpleQuery("SELECT li.locationid, li.serverid, li.serverlocationid, li.openingtime, li.lastcalendarupdate, cb.servername + $dbquery = Database::simpleQuery("SELECT li.locationid, li.serverid, li.serverlocationid, li.openingtime, li.lastcalendarupdate, cb.servertype, cb.servername FROM `locationinfo_locationconfig` AS li LEFT JOIN `locationinfo_coursebackend` AS cb USING (serverid)"); @@ -466,6 +466,7 @@ class Page_LocationInfo extends Page 'openingGlyph' => $glyph, 'backend' => $backend, 'lastCalendarUpdate' => $row['lastcalendarupdate'], // TODO + 'backendMissing' => !CourseBackend::exists($row['servertype']), ); } diff --git a/modules-available/locationinfo/templates/frontend-default.html b/modules-available/locationinfo/templates/frontend-default.html index 4147e4e2..92cad055 100755 --- a/modules-available/locationinfo/templates/frontend-default.html +++ b/modules-available/locationinfo/templates/frontend-default.html @@ -343,6 +343,7 @@ optional: <script type='text/javascript' src='{{dirprefix}}script/jquery.js'></script> <script type='text/javascript' src='{{dirprefix}}modules/js_jqueryui/clientscript.js'></script> <script type='text/javascript' src="{{dirprefix}}modules/js_weekcalendar/clientscript.js"></script> + <script type='text/javascript' src='{{dirprefix}}modules/locationinfo/frontend/frontendscript.js'></script> </head> <body> @@ -980,10 +981,11 @@ optional: var columnWidth = $cal.find(".wc-day-1").width(); if (room.config.scaledaysauto) { - var result = ($cal.weekCalendar("option", "daysToShow") * columnWidth) / 100; + var result = ($cal.weekCalendar("option", "daysToShow") * columnWidth) / 130; result = parseInt(Math.min(Math.max(Math.abs(result), 1), 7)); if (result !== $cal.weekCalendar("option", "daysToShow")) { $cal.weekCalendar("option", "daysToShow", result); + columnWidth = $cal.find(".wc-day-1").width(); } } if (((!room.config.scaledaysauto) || $cal.weekCalendar("option", "daysToShow") === 1) && columnWidth < 85) { @@ -1007,21 +1009,21 @@ optional: clientHeight -= 6; var height = clientHeight / (room.openTimes * $cal.weekCalendar("option", "timeslotsPerHour")); - if (height < 30) { height = 30; } + var fontHeight = Math.min(height, columnWidth / 2.1); // Scale calendar font - if (height > 120) { + if (fontHeight > 120) { $cal.weekCalendar("option", "textSize", 28); } - else if (height > 100) { + else if (fontHeight > 100) { $cal.weekCalendar("option", "textSize", 24); - } else if (height > 80) { + } else if (fontHeight > 80) { $cal.weekCalendar("option", "textSize", 22); - } else if (height > 70) { + } else if (fontHeight > 70) { $cal.weekCalendar("option", "textSize", 20); - } else if (height > 60) { + } else if (fontHeight > 60) { $cal.weekCalendar("option", "textSize", 14); } else { $cal.weekCalendar("option", "textSize", 13); @@ -1040,50 +1042,6 @@ optional: } /** - * used for countdown - * computes the time difference between 2 Date objects - * @param {Date} a - * @param {Date} b - * @returns {string} printable time - */ - function GetTimeDiferenceAsString(a, b) { - if (!a || !b) { - return ""; - } - var milliseconds = a.getTime() - b.getTime(); - var days = Math.floor((milliseconds / (1000 * 60 * 60 * 24)) % 31); - if (days !== 0) { - // don't show? - return ""; - } - var seconds = Math.floor((milliseconds / 1000) % 60); - milliseconds -= seconds * 1000; - var minutes = Math.floor((milliseconds / (1000 * 60)) % 60); - milliseconds -= minutes * 1000 * 60; - var hours = Math.floor((milliseconds / (1000 * 60 * 60)) % 24); - - if (globalConfig.prettytime) { - var str = ''; - if (hours > 0) { - str += hours + 'h '; - } - str += minutes + 'min '; - return str; - } - - if (minutes < 10) { - minutes = "0" + minutes; - } - if (globalConfig.eco) { - return hours + ":" + minutes; - } - if (seconds < 10) { - seconds = "0" + seconds; - } - return hours + ":" + minutes + ":" + seconds; - } - - /** * returns next closing time of a given room * @param room * @returns {Date} Object of next closing @@ -1114,32 +1072,6 @@ optional: return null; } - - /** - * checks if a room is on a given date/time open - * @param date Date Object - * @param room Room object - * @returns {Boolean} for open or not - */ - function IsOpen(date, room) { - if (!room.openingTimes || room.openingTimes.length === 0) return true; - var tmp = room.openingTimes[date.getDay()]; - if (!tmp) return false; - var openDate = new Date(date.getTime()); - var closeDate = new Date(date.getTime()); - for (var i = 0; i < tmp.length; i++) { - openDate.setHours(tmp[i].HourOpen); - openDate.setMinutes(tmp[i].MinutesOpen); - closeDate.setHours(tmp[i].HourClose); - closeDate.setMinutes(tmp[i].MinutesClose); - if (openDate < date && closeDate > date) { - return true; - } - } - return false; - } - - /** * Returns next Opening * @param room Room Object @@ -1200,7 +1132,7 @@ optional: var newText = false, newTime = false; var seats = room.freePcs; if (tmp.state === 'closed' || tmp.state === 'CalendarEvent' || tmp.state === 'Free') { - newTime = GetTimeDiferenceAsString(tmp.end, MyDate()); + newTime = GetTimeDiferenceAsString(tmp.end, MyDate(), globalConfig); } else if (!same) { newTime = ''; } @@ -1726,20 +1658,5 @@ optional: }, interval); } - /** - * Convert passed argument to integer if possible, return NaN otherwise. - * The difference to parseInt() is that leading zeros are ignored and not - * interpreted as octal representation. - * - * @param str string or already a number - * @return {number} str converted to number, or NaN - */ - function toInt(str) { - var t = typeof str; - if (t === 'number') return str | 0; - if (t === 'string') return parseInt(str.replace(/^0+([^0])/, '$1')); - return NaN; - } - </script> </html> diff --git a/modules-available/locationinfo/templates/frontend-summary.html b/modules-available/locationinfo/templates/frontend-summary.html index 7faa01e5..ec5d8aab 100644 --- a/modules-available/locationinfo/templates/frontend-summary.html +++ b/modules-available/locationinfo/templates/frontend-summary.html @@ -3,6 +3,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8"> <head> <script type='text/javascript' src='{{dirprefix}}script/jquery.js'></script> + <script type='text/javascript' src='{{dirprefix}}modules/locationinfo/frontend/frontendscript.js'></script> <style type='text/css'> @@ -33,6 +34,7 @@ .parent .parent, .parent .child { min-height: 5em; + min-width: 90px; } .border { @@ -101,7 +103,8 @@ .paperEffect { margin: 0 auto; background-color: #fff; - box-shadow: 0 0 0.2vmin rgba(0, 0, 0, 0.4), inset 0 0 1vmin rgba(0, 0, 0, 0.1); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.4), 0 0 10px rgba(0, 0, 0, 0.1) inset; + box-shadow: 0 0 0.2vmin rgba(0, 0, 0, 0.4), 0 0 1vmin rgba(0, 0, 0, 0.1) inset; border-radius: 1px; } @@ -115,21 +118,25 @@ var config = {{{config}}}; $(document).ready(function () { - //temp - SetUpDate(new Date()); init(); }); function init() { - // var ids = getUrlParameter("id"); - - /* - $.getJSON("../../../api.php?do=locationinfo&action=locationtree&id=" + ids, function (result) { - generateLayout(result); - - setTimeout(update, 1000); - }); - */ + var time = false; + if (config.time) { + var p = config.time.split('-'); + if (p.length === 6) { + time = new Date(p[0], (p[1] - 1), p[2], p[3], p[4], p[5]); + console.log(time); + } + if (time === false || isNaN(time.getTime()) || time.getFullYear() < 2010) { + time = new Date(config.time); + } + if (!time || isNaN(time.getTime()) || time.getFullYear() < 2010) { + time = new Date(); + } + } + SetUpDate(time); generateLayout(config.tree); update(); } @@ -187,14 +194,16 @@ const ROOMUPDATE_MS = 2*60*1000; const CALUPDATE_MS = 20*60*1000; + var timeout = null; function update() { var calendarUpdateIds = ""; var rommUpdateIds = ""; var count = 0; var nextUpdate = 15000; + var property; // TODO: Only query a few rooms is not possible with the new api stuff ... - for (var property in rooms) { + for (property in rooms) { if (rooms[property].lastCalendarUpdate === null || rooms[property].lastCalendarUpdate + CALUPDATE_MS < MyDate().getTime()) { // TODO: NOT NECESSARY ANYMORE?! calendarUpdateIds = addIdToUpdateList(calendarUpdateIds, rooms[property].id); @@ -207,7 +216,7 @@ count++; rooms[property].lastRoomUpdate = MyDate().getTime(); } - if (count > 7) break; + // TODO if (count > 7) break; } if (calendarUpdateIds !== "") { queryCalendars(); @@ -217,12 +226,33 @@ queryRooms(); nextUpdate = 1000; } - for (var property in rooms) { + for (property in rooms) { upDateRoomState(rooms[property]); } + clearTimeout(timeout); setTimeout(update, nextUpdate); } + function cleanDate(d) { + if (typeof d === 'string') { + // if is numeric + if (!isNaN(Number(d))) { + return cleanDate(parseInt(d, 10)); + } + + // this is a human readable date + if (d[d.length - 1] !== 'Z') d += 'Z'; + var o = new Date(d); + o.setTime(o.getTime() + (o.getTimezoneOffset() * 60 * 1000)); + return o; + } + + if (typeof d === 'number') { + return new Date(d); + } + + return d; + } function UpdateTimeTables(json) { var l = json.length; @@ -232,11 +262,12 @@ } rooms[json[i].id].timetable = json[i].calendar; for (var property in rooms[json[i].id].timetable) { - rooms[json[i].id].timetable[property].start = new Date(rooms[json[i].id].timetable[property].start); - rooms[json[i].id].timetable[property].end = new Date(rooms[json[i].id].timetable[property].end); + rooms[json[i].id].timetable[property].start = cleanDate(rooms[json[i].id].timetable[property].start); + rooms[json[i].id].timetable[property].end = cleanDate(rooms[json[i].id].timetable[property].end); } ComputeCurrentState(rooms[json[i].id]); } + update(); } /** @@ -289,7 +320,6 @@ updateCourseText(room.id, "Geschlossen"); updateCoursTimer(room.id, ""); } - } /** @@ -303,6 +333,10 @@ } } + + const OT_DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + const OT_KEYS = ['HourOpen', 'HourClose', 'MinutesOpen', 'MinutesClose']; + /** * Generates a room Object and adds it to the rooms array * @param id ID of the room @@ -310,6 +344,22 @@ * @param config Config Json of the room */ function addRoom(id, name) { + var ot = []; + if (config && config.locations) { + for (var i = 0; i < config.locations.length; ++i) { + if (config.locations[i].id == id) { + // TODO: Messed up transformation from default panel + if (config.locations[i].openingtime) { + var raw_ot = config.locations[i].openingtime; + + for (var j = 0; j < OT_DAYS.length; ++j) { + ot.push(filterOpeningTimesDay(raw_ot[OT_DAYS[j]])); + } + } + } + } + } + var room = { id: id, name: name, @@ -318,7 +368,7 @@ nextEventEnd: null, timeTilFree: null, state: null, - openingTimes: null, + openingTimes: ot, lastCalendarUpdate: null, lastRoomUpdate: null, getState: function () { @@ -346,6 +396,33 @@ } } + /** + * Filter out invalid opening time entries from given array, + * also make sure all the values are of type number (int) + * + * @param {Array} arr + * @return {Array} list of valid opening times + */ + function filterOpeningTimesDay(arr) { + if (!arr || arr.constructor !== Array) return []; + return arr.map(function (el) { + if (!el || typeof el !== 'object') return null; + for (var i = 0; i < OT_KEYS.length; ++i) { + el[OT_KEYS[i]] = toInt(el[OT_KEYS[i]]); + if (isNaN(el[OT_KEYS[i]])) return null; + } + return el; + }).filter(function (el) { + if (!el) return false; + if (el.HourOpen < 0 || el.HourOpen > 23) return false; + if (el.HourClose < 0 || el.HourClose > 23) return false; + if (el.HourClose < el.HourOpen) return false; + if (el.MinutesOpen < 0 || el.MinutesOpen > 59) return false; + if (el.MinutesClose < 0 || el.MinutesClose > 59) return false; + if (el.HourOpen === el.HourClose && el.MinutesClose < el.MinutesOpen) return false; + return true; + }); + } /** * computes state of a room, states are: @@ -396,6 +473,7 @@ room.state = {state: "Free", end: closing, titel: "", next: "closing"}; } } + /** * checks if a room is open * @param room Room object @@ -408,6 +486,7 @@ // changes from falls needs testing return true; } + var tmp = room.openingTimes[now.getDay()]; if (tmp == null) { return false; @@ -477,7 +556,7 @@ openDate.setHours(tmp[i].HourOpen); openDate.setMinutes(tmp[i].MinutesOpen); if (openDate > now) { - if (!IsOpen(new Date(openDate.getTime() - 60000))) { + if (!IsOpen(new Date(openDate.getTime() - 60000), room)) { if (bestdate == null || bestdate > openDate) { bestdate = openDate; } @@ -517,7 +596,7 @@ closeDate.setHours(tmp[i].HourClose); closeDate.setMinutes(tmp[i].MinutesClose); if (closeDate > now) { - if (!IsOpen(new Date(closeDate.getTime() + 60000))) { + if (!IsOpen(new Date(closeDate.getTime() + 60000), room)) { if (bestdate == null || bestdate > closeDate) { bestdate = closeDate; } @@ -541,13 +620,16 @@ * @param occupied PC's used * @param offline PC's that are off * @param broken PC's that are broken + * @param standby PCs in standby mode */ function updateRoomUsage(id, idle, occupied, offline, broken, standby) { - if (idle == 0 && occupied == 0 && offline == 0 && broken == 0 && standby == 0) { + /* TODO Broken + if (idle === 0 && occupied === 0 && offline === 0 && broken === 0 && standby === 0) { $('#parent_' + id).parent().hide(); return; } $('#parent_' + id).parent().show(); + */ var total = parseInt(idle) + parseInt(occupied) + parseInt(offline) + parseInt(broken) + parseInt(standby); $("#pc_Idle_" + id).text(idle).width((idle / total) * 100 + '%'); $("#pc_Occupied_" + id).text(occupied).width((occupied / total) * 100 + '%'); @@ -683,38 +765,6 @@ }); } - - /** - * used for countdown - * computes the time difference between 2 Date objects - * @param a Date Object - * @param b Date Object - * @returns time string - */ - function GetTimeDiferenceAsString(a, b) { - if (a == null || b == null) { - return ""; - } - var milliseconds = a.getTime() - b.getTime(); - var seconds = Math.floor((milliseconds / 1000) % 60); - milliseconds -= seconds * 1000; - var minutes = Math.floor((milliseconds / (1000 * 60)) % 60); - milliseconds -= minutes * 1000 * 60; - var hours = Math.floor((milliseconds / (1000 * 60 * 60)) % 24); - - var days = Math.floor((milliseconds / (1000 * 60 * 60 * 24)) % 31); - if (seconds < 10) { - seconds = "0" + seconds; - } - if (minutes < 10) { - minutes = "0" + minutes; - } - if (days != 0) { - // dont show? - return ""; - } - return hours + ":" + minutes + ":" + seconds; - } </script> </head> <body> diff --git a/modules-available/locationinfo/templates/page-locations.html b/modules-available/locationinfo/templates/page-locations.html index 3eafa7bf..de8dab7e 100644 --- a/modules-available/locationinfo/templates/page-locations.html +++ b/modules-available/locationinfo/templates/page-locations.html @@ -21,7 +21,7 @@ <span class="glyphicon glyphicon-edit"></span> </a> </td> - <td> + <td {{#backendMissing}}class="text-danger"{{/backendMissing}}> {{backend}} </td> <td> |