diff --git a/Lora-Map/Lora-Map.csproj b/Lora-Map/Lora-Map.csproj index a661804..f368f5e 100644 --- a/Lora-Map/Lora-Map.csproj +++ b/Lora-Map/Lora-Map.csproj @@ -68,9 +68,7 @@ - - PreserveNewest - + PreserveNewest @@ -136,12 +134,6 @@ Designer - - PreserveNewest - - - PreserveNewest - PreserveNewest diff --git a/Lora-Map/Model/Admin/Adminmodel.cs b/Lora-Map/Model/Admin/Adminmodel.cs index ad3da9f..d81963d 100644 --- a/Lora-Map/Model/Admin/Adminmodel.cs +++ b/Lora-Map/Model/Admin/Adminmodel.cs @@ -8,6 +8,9 @@ using BlubbFish.Utils.IoT.Bots; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { class AdminModel { + public delegate void AdminEvent(Object sender, EventArgs e); + public event AdminEvent NamesUpdate; + private readonly Dictionary session = new Dictionary(); public Boolean ParseReuqest(HttpListenerContext cont) { if(cont.Request.Url.PathAndQuery == "/admin/login") { @@ -19,12 +22,29 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { if(cont.Request.Url.PathAndQuery.StartsWith("/admin/get_json_")) { return this.SendJson(cont); } + if(cont.Request.Url.PathAndQuery.StartsWith("/admin/set_json_")) { + return this.GetJson(cont); + } return Webserver.SendFileResponse(cont); } + private Boolean GetJson(HttpListenerContext cont) { + if(cont.Request.Url.PathAndQuery == "/admin/set_json_names") { + StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding); + String rawData = reader.ReadToEnd(); + cont.Request.InputStream.Close(); + reader.Close(); + File.WriteAllText("json/names.json", rawData); + Console.WriteLine("200 - Get names.json " + cont.Request.Url.PathAndQuery); + this.NamesUpdate?.Invoke(this, new EventArgs()); + return true; + } + return false; + } + private Boolean SendJson(HttpListenerContext cont) { if(cont.Request.Url.PathAndQuery == "/admin/get_json_names") { - String file = File.ReadAllText("names.json"); + String file = File.ReadAllText("json/names.json"); Byte[] buf = Encoding.UTF8.GetBytes(file); cont.Response.ContentLength64 = buf.Length; cont.Response.OutputStream.Write(buf, 0, buf.Length); diff --git a/Lora-Map/Model/PositionItem.cs b/Lora-Map/Model/PositionItem.cs index 0f07098..738d5d6 100644 --- a/Lora-Map/Model/PositionItem.cs +++ b/Lora-Map/Model/PositionItem.cs @@ -21,7 +21,10 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { public PositionItem(JsonData json, JsonData marker) { this.Update(json); - String id = GetId(json); + this.UpdateMarker(marker, GetId(json)); + } + + public void UpdateMarker(JsonData marker, String id) { if(marker.ContainsKey(id)) { if(marker[id].ContainsKey("name") && marker[id]["name"].IsString) { this.Name = (String)marker[id]["name"]; @@ -40,7 +43,6 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { this.Icon = null; } } - public static Boolean CheckJson(JsonData json) => json.ContainsKey("Rssi") && json["Rssi"].IsDouble && json.ContainsKey("Snr") && json["Snr"].IsDouble && json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString @@ -57,6 +59,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { && json.ContainsKey("Name") && json["Name"].IsString; public static String GetId(JsonData json) => (String)json["Name"]; + public void Update(JsonData json) { this.Rssi = (Double)json["Rssi"]; this.Snr = (Double)json["Snr"]; diff --git a/Lora-Map/Properties/AssemblyInfo.cs b/Lora-Map/Properties/AssemblyInfo.cs index 8ab8c4c..5edc28b 100644 --- a/Lora-Map/Properties/AssemblyInfo.cs +++ b/Lora-Map/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Fraunhofer FIT")] [assembly: AssemblyProduct("Lora-Map")] -[assembly: AssemblyCopyright("Copyright © 2018 - 03.04.2019")] +[assembly: AssemblyCopyright("Copyright © 2018 - 14.04.2019")] [assembly: AssemblyTrademark("Fraunhofer FIT, BlubbFish")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("de-DE")] @@ -33,8 +33,8 @@ using System.Runtime.InteropServices; // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.6")] -[assembly: AssemblyFileVersion("1.1.6")] +[assembly: AssemblyVersion("1.1.7")] +[assembly: AssemblyFileVersion("1.1.7")] /* * 1.1.1 Add Debian package config @@ -43,4 +43,5 @@ using System.Runtime.InteropServices; * 1.1.4 #3 Create icons for devices * 1.1.5 Add support for alert button * 1.1.6 #5 Create admin area +* 1.1.7 #8 Editor for Names */ diff --git a/Lora-Map/Server.cs b/Lora-Map/Server.cs index db7b031..5d22ecb 100644 --- a/Lora-Map/Server.cs +++ b/Lora-Map/Server.cs @@ -16,11 +16,32 @@ namespace Fraunhofer.Fit.IoT.LoraMap { { private readonly SortedDictionary positions = new SortedDictionary(); private readonly SortedDictionary alarms = new SortedDictionary(); - private readonly JsonData marker; + private JsonData marker; private readonly Dictionary markertable = new Dictionary(); private readonly AdminModel admin = new AdminModel(); - public Server(ADataBackend backend, Dictionary settings, InIReader requests) : base(backend, settings, requests) => this.marker = JsonMapper.ToObject(File.ReadAllText("names.json")); + public Server(ADataBackend backend, Dictionary settings, InIReader requests) : base(backend, settings, requests) { + this.CheckJsonFiles(); + this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); + this.admin.NamesUpdate += this.AdminModelUpdateNames; + this.StartListen(); + } + + private void AdminModelUpdateNames(Object sender, EventArgs e) { + this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); + foreach(KeyValuePair item in this.positions) { + item.Value.UpdateMarker(this.marker, item.Key); + } + } + + private void CheckJsonFiles() { + if(!Directory.Exists("json")) { + Directory.CreateDirectory("json"); + } + if(!File.Exists("json/names.json")) { + File.WriteAllText("json/names.json", "{}"); + } + } protected override void Backend_MessageIncomming(Object sender, BackendEvent e) { try { diff --git a/Lora-Map/resources/admin/css/global.css b/Lora-Map/resources/admin/css/global.css index 233d713..98ca1dc 100644 --- a/Lora-Map/resources/admin/css/global.css +++ b/Lora-Map/resources/admin/css/global.css @@ -39,6 +39,7 @@ border-collapse: collapse; } #content #nameeditor #nametable thead { + background-color: #CCCCCC; background-color: rgba(0,0,0,0.2); } #content #nameeditor #nametable thead th { @@ -57,21 +58,25 @@ width: 250px; } #content #nameeditor #nametable tbody tr:nth-child(odd) { + background-color: #f39d9d; background-color: rgba(20,0,250,0.1); } #content #nameeditor #nametable tbody tr:nth-child(even) { + background-color: #9c9eee; background-color: rgba(250,59,0,0.1); } #content #nameeditor #nametable tbody tr:hover { - background-color: rgba(0,0,0,0.1) !important; + background-color: #e4e1e1; + background-color: rgba(0,0,0,0.1); } #content #nameeditor #nametable tfoot { + background-color: #e4e1e1; background-color: rgba(0,0,0,0.1); } #content #nameeditor .pointer { cursor: pointer; } -#content #nameeditor #nametable tbody input.name { +#content #nameeditor #nametable tbody .name { width: 55px; } @@ -81,6 +86,7 @@ left: 0; right: 0; bottom: 0; + background-color: #333232; background-color: rgba(0,0,0,0.8); } #iconeditor .innerbox { diff --git a/Lora-Map/resources/admin/index.html b/Lora-Map/resources/admin/index.html index cbd7b26..5b876b5 100644 --- a/Lora-Map/resources/admin/index.html +++ b/Lora-Map/resources/admin/index.html @@ -13,8 +13,7 @@
Wilkommen im Adminbereich
diff --git a/Lora-Map/resources/admin/js/menu.js b/Lora-Map/resources/admin/js/menu.js index 5881c49..828e98f 100644 --- a/Lora-Map/resources/admin/js/menu.js +++ b/Lora-Map/resources/admin/js/menu.js @@ -5,7 +5,7 @@ NamesEditor.ParseJson(parsenames.responseText); } }; - parsenames.open("GET", "http://{%REQUEST_URL_HOST%}:8080/admin/get_json_names", true); + parsenames.open("GET", "http://{%REQUEST_URL_HOST%}/admin/get_json_names", true); parsenames.send(); } @@ -13,11 +13,7 @@ function menu_overlay() { } -function menu_export() { - -} - -function menu_import() { +function menu_eximport() { } @@ -29,6 +25,7 @@ var NamesEditor = { var html = "
Namenseinträge in den Einstellungen
"; html += ""; html += ""; + html += ""; for (var id in namesconfig) { if (namesconfig.hasOwnProperty(id)) { var nameentry = namesconfig[id]; @@ -46,6 +43,7 @@ var NamesEditor = { ""; } } + html += ""; html += ""; html += "
IDNameIcon
"; document.getElementById("content").innerHTML = html + "
"; @@ -69,6 +67,26 @@ var NamesEditor = { } return ""; }, + BuildIconJson: function (url) { + var query = this.SplitQueryIntoObject(this.SplitUrlIntoParts(url).query); + var markerobj = {}; + if (query.hasOwnProperty("icon") && query["icon"] === "person") { + markerobj["person"] = {}; + if (query.hasOwnProperty("person-org")) { + markerobj["person"]["org"] = query["person-org"]; + } + if (query.hasOwnProperty("person-funct")) { + markerobj["person"]["funct"] = query["person-funct"]; + } + if (query.hasOwnProperty("person-rang")) { + markerobj["person"]["rang"] = query["person-rang"]; + } + if (query.hasOwnProperty("person-text")) { + markerobj["person"]["text"] = query["person-text"]; + } + } + return markerobj; + }, Add: function () { var newrow = document.createElement("tr"); newrow.innerHTML = ""; @@ -78,7 +96,28 @@ var NamesEditor = { document.getElementById("nametable").children[1].appendChild(newrow); }, Save: function () { - alert("Save"); + var rows = document.getElementById("nametable").children[1].children; + var namejson = {}; + for (var i = 0; i < rows.length; i++) { + if (rows[i].children[0].children.length === 1) { + alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); + return; + } + var id = rows[i].children[0].innerText; + var name = rows[i].children[1].innerText; + namejson[id] = { "name": name }; + if (rows[i].children[2].children[0].hasAttribute("data")) { + namejson[id]["marker.svg"] = this.BuildIconJson(rows[i].children[2].children[0].data); + } + } + var savenames = new XMLHttpRequest(); + savenames.onreadystatechange = function () { + if (savenames.readyState === 4 && savenames.status === 200) { + alert("Änderungen gespeichert!"); + } + }; + savenames.open("POST", "http://{%REQUEST_URL_HOST%}/admin/set_json_names", true); + savenames.send(JSON.stringify(namejson)); }, Delete: function (el) { var name = el.firstChild.innerHTML; @@ -110,7 +149,7 @@ var NamesEditor = { var id = el.children[0].children[0].value; var name = el.children[1].children[0].value; var url = null; - if (el.children[2].children.length == 2) { + if (el.children[2].children.length === 2) { url = el.children[2].children[1].data; } el.innerHTML = "" + id + "" + @@ -125,7 +164,7 @@ var NamesEditor = { IconEditor: function (el) { var url = "../icons/marker/Marker.svg?marker-bg=hidden"; el.id = "icon_edit_" + this.iconeditorcounter++; - if (el.children.length == 2) { + if (el.children.length === 2) { url = el.children[1].data; } var query = this.SplitQueryIntoObject(this.SplitUrlIntoParts(url).query); @@ -135,11 +174,11 @@ var NamesEditor = { "
" + "
" + this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, "iconeditor-type-") + "
" + - "
" + + "
" + this.CreateSelectBox("Organisation", "person-org", query, { "fw": "Feuerwehr", "thw": "Technisches Hilfswerk", "hilo": "Hilfsorganisationen, Bundeswehr", "fueh": "Einrichtungen der Führung", "pol": "Polizei, Bundespolizei, Zoll", "sonst": "Sonstige Einrichtungen der Gefahrenabwehr" }) + "
" + this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "
" + this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug":"Zug" }) + "
" + - "Text:
" + + "Text:
" + "
" + "
" + "
" + @@ -155,7 +194,7 @@ var NamesEditor = { html += "
"; document.getElementById("pannels_admin").innerHTML = html; } else if (this.readyState === 4 && this.status === 200) { - document.getElementById("pannels_admin").innerHTML = "Adminpannel"; + document.getElementById("pannels_admin").innerHTML = "Adminpannel"; } } function submitloginform() { var adminlogin = new XMLHttpRequest(); adminlogin.onreadystatechange = parseAjaxLogin; - adminlogin.open("POST", "http://{%REQUEST_URL_HOST%}:8080/admin/login", true); + adminlogin.open("POST", "http://{%REQUEST_URL_HOST%}/admin/login", true); adminlogin.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); adminlogin.send("user=" + encodeURI(document.getElementById("pannels_admin_name").value) + "&pass=" + encodeURI(document.getElementById("pannels_admin_pass").value)); }