diff options
Diffstat (limited to 'modules-available/locationinfo/templates/frontend-summary.html')
-rw-r--r-- | modules-available/locationinfo/templates/frontend-summary.html | 700 |
1 files changed, 700 insertions, 0 deletions
diff --git a/modules-available/locationinfo/templates/frontend-summary.html b/modules-available/locationinfo/templates/frontend-summary.html new file mode 100644 index 00000000..dd5fc25d --- /dev/null +++ b/modules-available/locationinfo/templates/frontend-summary.html @@ -0,0 +1,700 @@ +<!DOCTYPE html> +<html lang="de"> +<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8"> +<head> + <script type='text/javascript' src='../../../script/jquery.js'></script> + + <style type='text/css'> + body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + background-color: lightgrey; + color: black; + } + + #main { + display: flex; + flex-wrap: wrap; + } + + .outermost { + font-size: 16pt; + } + + .parent, .child { + padding: 5px; + float: left; + background-color: white; + font-size: 90%; + min-height: 7em; + flex-grow: 1; + align-items: stretch; + } + + .parent .parent, .parent .child { + min-height: 5em; + } + + .border { + flex-grow: 1; + display: inline-flex; + align-items: stretch; + padding: 5px; + } + + .courseFont { + padding: 2px; + font-size: 90%; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bold; + overflow: hidden; + } + + .headerFont { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bold; + border: 0px; + border-bottom: 1px; + margin-bottom: 1px; + border-color: grey; + border-style: solid; + } + + .pc-idle, .pc-occupied, .pc-off, .pc-broken { + padding: 2px 1px; + text-align: center; + font-size: 90%; + font-weight: 800; + overflow: hidden; + transition: width 2s; + width: 25%; + } + + .pc-idle { + background-color: green; + } + + .pc-occupied { + background-color: red; + border-radius: 3px 0px 0px 3px; + } + + .pc-off { + background-color: darkgrey; + } + + .pc-broken { + background-color: black; + color: white; + border-radius: 0px 3px 3px 0px; + } + + .pc-state-wrapper { + display: flex; + } + + .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); + border-radius: 1px; + } + + + </style> + <script type='text/javascript'> + + var rooms = {}; + var startdate; + var roomidsString = ""; + + + $(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); + }); + + } + + function SetUpDate(d) { + startdate = d.getTime() - new Date().getTime(); + } + + function MyDate() { + return new Date(startdate + new Date().getTime()); + } + + function generateLayout(json) { + for (var i = 0; i < json.length; i++) { + console.log('Outermost for ' + json[i].locationid); + var el = generateObject(json[i], ($("#main")), true); + } + } + + /** + * generates the divs, decidecs if parent or child + * @param json Room tree json + * @param myParent parent div + * @param outermost if the object is a root node + * @returns generated div + */ + function generateObject(json, myParent, outermost) { + var obj; + if (!json.children || json.children.length == 0) { + obj = generateChild(myParent, json.locationid, json.locationname, outermost); + } else { + obj = generateParent(myParent, json.locationid, json.locationname, outermost); + for (var i = 0; i < json.children.length; i++) { + generateObject(json.children[i], $("#parent_" + json.locationid), false); + } + } + return obj; + + } + + /** + * Helper function to generate id string used in query functions + * @param list A string, wicht contains ids or not(for now) + * @param id An ID which should be added to the list + */ + function addIdToUpdateList(list, id) { + if (list == "") { + list += id; + } else { + list += ("," + id); + } + return list; + } + + + const ROOMUPDATE_MS = 2*60*1000; + const CALUPDATE_MS = 20*60*1000; + + function update() { + var calendarUpdateIds = ""; + var rommUpdateIds = ""; + var count = 0; + var nextUpdate = 15000; + for (var property in rooms) { + if (rooms[property].lastCalendarUpdate === null || rooms[property].lastCalendarUpdate + CALUPDATE_MS < MyDate().getTime()) { + calendarUpdateIds = addIdToUpdateList(calendarUpdateIds, rooms[property].id); + count++; + rooms[property].lastCalendarUpdate = MyDate().getTime(); + } + if (rooms[property].lastRoomUpdate === null || rooms[property].lastRoomUpdate + ROOMUPDATE_MS < MyDate().getTime()) { + rommUpdateIds = addIdToUpdateList(rommUpdateIds, rooms[property].id); + count++; + rooms[property].lastRoomUpdate = MyDate().getTime(); + } + if (count > 7) break; + } + if (calendarUpdateIds !== "") { + queryCalendars(calendarUpdateIds); + nextUpdate = 1000; + } + if (rommUpdateIds !== "") { + queryRooms(rommUpdateIds); + nextUpdate = 1000; + } + for (var property in rooms) { + upDateRoomState(rooms[property]); + } + setTimeout(update, nextUpdate); + } + + + function UpdateTimeTables(json) { + var l = json.length; + for (var i = 0; i < l; i++) { + 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); + } + ComputeCurrentState(rooms[json[i].id]); + } + } + + /** + * Querys Pc states + * @param ids Room ID's which should be queried. Format for e.g.: "20,5,6" + */ + function queryRooms(ids) { + $.ajax({ + url: "../../../api.php?do=locationinfo&action=pcstates&id=" + ids, + dataType: 'json', + cache: false, + timeout: 30000, + success: function (result) { + var l = result.length; + if (result[0] == null) { + console.log("Error: Backend reported null back for RoomUpdate, this might happend if the room isn't" + + "configurated."); + return; + } + updatePcStates(result); + }, error: function () { + + } + }) + } + + /** + * Updates a room visualy + * @param room A room to update + */ + function upDateRoomState(room) { + if (room === undefined || room.lastRoomUpdate === null) { + return; + } + + var state = room.getState(); + + if (state.state == "CalendarEvent") { + updateCourseText(room.id, state.titel); + updateCoursTimer(room.id, GetTimeDiferenceAsString(state.end, MyDate())); + } else if (state.state == "Free") { + updateCourseText(room.id, "Frei"); + updateCoursTimer(room.id, GetTimeDiferenceAsString(state.end, MyDate())); + } else if (state.state == "FreeNoEnd") { + updateCourseText(room.id, "Frei"); + updateCoursTimer(room.id, ""); + } + else if (state.state == "closed") { + updateCourseText(room.id, "Geschlossen"); + updateCoursTimer(room.id, ""); + } + + } + + /** + * Updates for all rooms the PC's states + * @param json Json with information about the PC's states + */ + function updatePcStates(json) { + var l = json.length; + for (var i = 0; i < l; i++) { + updateRoomUsage(json[i].id, json[i].idle, json[i].occupied, json[i].off, json[i].broken) + } + + } + /** + * Generates a room Object and adds it to the rooms array + * @param id ID of the room + * @param name Name of the room + * @param config Config Json of the room + */ + function addRoom(id, name) { + var room = { + id: id, + name: name, + timetable: null, + currentEvent: null, + nextEventEnd: null, + timeTilFree: null, + state: null, + openingTimes: null, + lastCalendarUpdate: null, + lastRoomUpdate: null, + getState: function () { + if (!this.state) { + ComputeCurrentState(this); + return this.state; + } + if (this.state.end != "") { + if (this.state.end < new MyDate()) { + ComputeCurrentState(this); + } + } + return this.state; + } + + + }; + + rooms[id] = room; + + if (roomidsString == "") { + roomidsString = id; + } else { + roomidsString = roomidsString + "," + id; + } + } + + + /** + * computes state of a room, states are: + * closed, FreeNoEnd, Free, ClaendarEvent. + * @param Room Object + */ + function ComputeCurrentState(room) { + if (room.lastRoomUpdate === null) { + room.state = {state: 'unknown'}; + return; + } + if (!IsOpenNow(room)) { + room.state = {state: "closed", end: GetNextOpening(room), titel: "", next: ""}; + + return; + } + var closing = GetNextClosing(room); + + var event = getNextEvent(room.timetable); + // no event and no closing + if (closing == null && event == null) { + room.state = {state: "FreeNoEnd", end: "", titel: "", next: ""}; + return; + } + + // no event so closing is next + if (event == null) { + room.state = {state: "Free", end: closing, titel: "", next: "closing"}; + return; + } + + // event is at the moment + if ((closing == null || event.start.getTime() < closing.getTime()) && event.start.getTime() < new MyDate()) { + room.state = {state: "CalendarEvent", end: event.end, titel: event.title, next: ""}; + return; + } + + // no closing so event is next + if (closing == null) { + room.state = {state: "Free", end: event.start, titel: "", next: "event"}; + return; + } + + // event sooner then closing + if (event.start.getTime() < closing) { + room.state = {state: "Free", end: event.start, titel: "", next: "event"}; + } else if (event.start.getTime() > closing) { + room.state = {state: "Free", end: closing, titel: "", next: "closing"}; + } + } + /** + * checks if a room is open + * @param room Room object + * @returns bool for open or not + */ + function IsOpenNow(room) { + var now = new MyDate(); + if (room.openingTimes == null) { + + // changes from falls needs testing + return true; + } + var tmp = room.openingTimes[now.getDay()]; + if (tmp == null) { + return false; + } + for (var i = 0; i < tmp.length; i++) { + var openDate = new MyDate(); + openDate.setHours(tmp[i].HourOpen); + openDate.setMinutes(tmp[i].MinutesOpen); + var closeDate = new MyDate(); + closeDate.setHours(tmp[i].HourClose); + closeDate.setMinutes(tmp[i].MinutesClose); + if (openDate < now && closeDate > now) { + return true; + } + } + return false; + } + + /** + * returns next event from a given json of events + * @param json Json which contains the calendar data. + * @returns event next Carlendar Event + */ + function getNextEvent(json) { + if (json == null) { + return; + } + var event; + var now = new MyDate(); + for (var i = 0; i < json.length; i++) { + //event is now active + if (json[i].start.getTime() < now.getTime() && json[i].end.getTime() > now.getTime()) { + return json[i]; + } + //first element to consider + if (event == null) { + if (json[i].start.getTime() > now.getTime()) { + event = json[i]; + } + } + if (json[i].start.getTime() > now.getTime() && event.start.getTime() > json[i].start.getTime()) { + event = json[i]; + } + } + return event; + } + + /** + * Retruns next Opening + * @param room Room Object + * @returns bestdate Date Object of next opening + */ + function GetNextOpening(room) { + var now = new MyDate(); + var day = now.getDay(); + var offset = 0; + var bestdate; + for (var a = 0; a < 7; a++) { + if (room.openingTimes == null) { + return null; + } + var tmp = room.openingTimes[day]; + if (tmp != null) { + for (var i = 0; i < tmp.length; i++) { + var openDate = new MyDate(); + openDate.setDate(now.getDate() + offset); + openDate.setHours(tmp[i].HourOpen); + openDate.setMinutes(tmp[i].MinutesOpen); + if (openDate > now) { + if (!IsOpen(new Date(openDate.getTime() - 60000))) { + if (bestdate == null || bestdate > openDate) { + bestdate = openDate; + } + } + } + } + } + offset++; + day++; + if (day > 6) { + day = 0; + } + } + return bestdate; + } + + /** + * returns next closing time of a given room + * @param room + * @returns Date Object of next closing + */ + function GetNextClosing(room) { + var now = new MyDate(); + var day = now.getDay(); + var offset = 0; + var bestdate; + for (var a = 0; a < 7; a++) { + //Test + if (room.openingTimes === null) { + return null; + } + var tmp = room.openingTimes[day]; + if (tmp != null) { + for (var i = 0; i < tmp.length; i++) { + var closeDate = new MyDate(); + closeDate.setDate(now.getDate() + offset); + closeDate.setHours(tmp[i].HourClose); + closeDate.setMinutes(tmp[i].MinutesClose); + if (closeDate > now) { + if (!IsOpen(new Date(closeDate.getTime() + 60000))) { + if (bestdate == null || bestdate > closeDate) { + bestdate = closeDate; + } + } + } + } + } + offset++; + day++; + if (day > 6) { + day = 0; + } + } + return bestdate; + } + + /** + * Updates the Course Text of a child + * @param id of the child + * @param idle PC's on + * @param occupied PC's used + * @param off PC's that are off + * @param broken PC's that are broken + */ + function updateRoomUsage(id, idle, occupied, off, broken) { + if (idle == 0 && occupied == 0 && off == 0) { + $('#parent_' + id).parent().hide(); + return; + } + $('#parent_' + id).parent().show(); + var total = parseInt(idle) + parseInt(occupied) + parseInt(off) + parseInt(broken); + $("#pc_Idle_" + id).text(idle).width((idle / total) * 100 + '%'); + $("#pc_Occupied_" + id).text(occupied).width((occupied / total) * 100 + '%'); + $("#pc_Off_" + id).text(off).width((off / total) * 100 + '%'); + $("#pc_Broken_" + id).text(broken).width((broken / total) * 100 + '%'); + } + + /** + * Updates the Course Text of a child + * @param id of the child + * @param text Text + */ + function updateCourseText(id, text) { + $("#div_course" + id).text(text); + } + + /** + * Updates the Course time of a child + * @param id of the child + * @param time Time value + */ + function updateCoursTimer(id, time) { + $("#div_Time_" + id).text(time); + } + + /** + * generates a Div, used for a child node + * @param target Div it should be inserted + * @param id ID of the Object it represents + * @param name Name of the Object it represents + * @param outermost if the object is a root node + * @returns generated div + */ + function generateChild(target, id, name, outermost) { + + var c = ""; + if (outermost) { + c = "outermost"; + } + + var text = "<div class='border " + c + "'>" + + "<div class='child paperEffect' id='parent_" + id + "'>" + + "<div class='headerFont'>" + name + "</div>" + + "<div class='pc-state-wrapper'>" + + "<div id = 'pc_Occupied_" + id + "' class='pc-occupied'>?</div>" + + "<div id = 'pc_Idle_" + id + "' class='pc-idle'>?</div>" + + "<div id = 'pc_Off_" + id + "' class='pc-off'>?</div>" + + "<div id = 'pc_Broken_" + id + "' class='pc-broken'>?</div>" + + "</div>" + + "<div class='aroundCourse'>" + + "<div id = 'div_course" + id + "'class='courseFont'>?</div>" + + "<div id = 'div_Time_" + id + "'class='courseFont'></div></div></div></div>"; + var obj = $(target).append(text); + addRoom(id, name); + return obj + + } + + /** + * generates a Div, used for a parent node + * @param target Div it should be inserted + * @param id ID of the Object it represents + * @param name Name of the Object it represents + * @param outermost if the object is a root node + * @returns generated div + */ + function generateParent(target, id, name, outermost) { + var c = ""; + if (outermost) { + c = "outermost"; + } + + var text = "<div class='border " + c + "'>" + + "<div class='parent paperEffect'>" + + "<div class='headerFont'>" + name + "</div>" + + "<div id='parent_" + id + "'></div>" + + "</div></div>"; + return $(target).append(text); + } + + /** + * returns parameter value from the url + * @param sParam + * @returns value for given parameter + */ + var getUrlParameter = function getUrlParameter(sParam) { + var sPageURL = decodeURIComponent(window.location.search.substring(1)), + sURLVariables = sPageURL.split('&'), + sParameterName, + i; + + for (i = 0; i < sURLVariables.length; i++) { + sParameterName = sURLVariables[i].split('='); + + if (sParameterName[0] === sParam) { + return sParameterName[1] === undefined ? true : sParameterName[1]; + } + } + }; + + + /** + * querys the Calendar data + * @param ids ID'S of rooms to query as string, for e.g.: "5,17,8" or "5" + */ + function queryCalendars(ids) { + var url = "../../../api.php?do=locationinfo&action=calendar&id=" + ids; + + // Todo reimplement Frontend methode if needed + /* + if(!(room.config.calendarqueryurl === undefined)) { + url = room.config.calendarqueryurl; + } + */ + $.ajax({ + url: url, + dataType: 'json', + cache: false, + timeout: 30000, + success: function (result) { + UpdateTimeTables(result); + + + }, error: function () { + + } + }); + } + + + /** + * 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> +<div id="main"></div> +</body> +</html> |