[1.1.7] #8 Editor for Names

This commit is contained in:
BlubbFish 2019-04-14 17:25:37 +02:00
parent aff3528ac8
commit 3744613277
11 changed files with 159 additions and 42 deletions

View File

@ -68,9 +68,7 @@
<None Include="dpkg\preinst" />
<None Include="dpkg\prerm" />
<None Include="layer.json" />
<None Include="names.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="names.json" />
<None Include="resources\icons\marker\din1451m.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@ -136,12 +134,6 @@
<Content Include="resources\icons\marker\Person.svg">
<SubType>Designer</SubType>
</Content>
<Content Include="resources\icons\marker\thw\einheiten\26-91.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\icons\marker\thw\einheiten\27-92.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\js\functions.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@ -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<Int64, AdminSession> session = new Dictionary<Int64, AdminSession>();
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);

View File

@ -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"];

View File

@ -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
*/

View File

@ -16,11 +16,32 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
{
private readonly SortedDictionary<String, PositionItem> positions = new SortedDictionary<String, PositionItem>();
private readonly SortedDictionary<String, AlarmItem> alarms = new SortedDictionary<String, AlarmItem>();
private readonly JsonData marker;
private JsonData marker;
private readonly Dictionary<String, Marker> markertable = new Dictionary<String, Marker>();
private readonly AdminModel admin = new AdminModel();
public Server(ADataBackend backend, Dictionary<String, String> settings, InIReader requests) : base(backend, settings, requests) => this.marker = JsonMapper.ToObject(File.ReadAllText("names.json"));
public Server(ADataBackend backend, Dictionary<String, String> 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<String, PositionItem> 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 {

View File

@ -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 {

View File

@ -13,8 +13,7 @@
<ul>
<li><a onclick="menu_names(); return false;" href="#">Namen und Icons</a></li>
<li><a onclick="menu_overlay(); return false;" href="#">Karteneditor</a></li>
<li><a onclick="menu_export(); return false;" href="#">Einstellungen Exportieren</a></li>
<li><a onclick="menu_import(); return false;" href="#">Einstellungen Importieren</a></li>
<li><a onclick="menu_eximport(); return false;" href="#">Ex- und Import</a></li>
</ul>
</div>
<div id="content">Wilkommen im Adminbereich</div>

View File

@ -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 = "<div id='nameeditor'><div class='title'>Namenseinträge in den Einstellungen</div>";
html += "<table id='nametable'>";
html += "<thead><tr><th class='rowid'>ID</th><th class='rowname'>Name</th><th class='rowicon'>Icon</th><th class='rowedit'></th></tr></thead>";
html += "<tbody>";
for (var id in namesconfig) {
if (namesconfig.hasOwnProperty(id)) {
var nameentry = namesconfig[id];
@ -46,6 +43,7 @@ var NamesEditor = {
"</tr>";
}
}
html += "</tbody>";
html += "<tfoot><tr><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='NamesEditor.Add()' class='pointer'> <img src='../icons/general/save.png' onclick='NamesEditor.Save()' class='pointer'></td></tr></tfoot>";
html += "</table>";
document.getElementById("content").innerHTML = html + "</div>";
@ -69,6 +67,26 @@ var NamesEditor = {
}
return "<object data='"+url+"' type='image/svg+xml' style='height:50px; width:50px;'></object>";
},
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 = "<td><input class='name'/></td>";
@ -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 = "<td>" + id + "</td>" +
@ -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 = {
"<div class='preview'><object id='markerprev' data='" + url + "' type='image/svg+xml' style='height:200px; width:200px;'></object></div>" +
"<div class='controls'>" +
this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, "iconeditor-type-") + "<br>" +
"<div id='iconeditor-type-person' style='display: " + ((query.hasOwnProperty("icon") && query["icon"] == "person") ? "block" : "none") + ";'>" +
"<div id='iconeditor-type-person' style='display: " + (query.hasOwnProperty("icon") && query["icon"] === "person" ? "block" : "none") + ";'>" +
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" }) + "<br>" +
this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "<br>" +
this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug":"Zug" }) + "<br>" +
"Text: <input onchange='NamesEditor.ChangeLinkPreview(\"person-text\",this.value);' value='" + ((query.hasOwnProperty("person-text")) ? query["person-text"] : "") + "'><br>" +
"Text: <input onchange='NamesEditor.ChangeLinkPreview(\"person-text\",this.value);' value='" + (query.hasOwnProperty("person-text") ? query["person-text"] : "") + "'><br>" +
"</div>" +
"</div>" +
"<div class='save'><button onclick='NamesEditor.SaveIconEditor(\"" + el.id + "\"); '>Schließen</botton></div>" +
@ -155,7 +194,7 @@ var NamesEditor = {
html += "<select onchange='" + eventtext + "'>";
html += "<option>---</option>";
for (var value in options) {
if (query.hasOwnProperty(key) && query[key] == value) {
if (query.hasOwnProperty(key) && query[key] === value) {
html += "<option value='" + value + "' selected>" + options[value] + "</option>";
} else {
html += "<option value='" + value + "'>" + options[value] + "</option>";
@ -203,4 +242,6 @@ var NamesEditor = {
}
document.getElementById("markerprev").data = cur.file + "?" + this.JoinObjectIntoQuery(query);
}
};
};
var ExImport = {};

View File

@ -4,7 +4,7 @@ timecorrectionrunner();
function timecorrectionrunner() {
var timecorrection = new XMLHttpRequest();
timecorrection.onreadystatechange = parseAjaxTimecorrection;
timecorrection.open("GET", "http://{%REQUEST_URL_HOST%}:8080/currenttime", true);
timecorrection.open("GET", "http://{%REQUEST_URL_HOST%}/currenttime", true);
timecorrection.send();
}

View File

@ -2,12 +2,12 @@
function datarunner() {
var loc = new XMLHttpRequest();
loc.onreadystatechange = parseAjaxLoc;
loc.open("GET", "http://{%REQUEST_URL_HOST%}:8080/loc", true);
loc.open("GET", "http://{%REQUEST_URL_HOST%}/loc", true);
loc.send();
var panic = new XMLHttpRequest();
panic.onreadystatechange = parseAjaxPanic;
panic.open("GET", "http://{%REQUEST_URL_HOST%}:8080/panic", true);
panic.open("GET", "http://{%REQUEST_URL_HOST%}/panic", true);
panic.send();
}
@ -37,6 +37,26 @@ function parseAjaxLoc() {
markers[key] = marker.addTo(mymap).on("click", showMarkerInfo, key);
} else {
markers[key].setLatLng([positionItem['Latitude'], positionItem['Longitude']]);
if (positionItem['Icon'] !== null) {
if (markers[key]._icon.children.length === 0) {
markers[key].setIcon(L.divIcon({
className: 'pos-marker',
iconSize: [56, 80],
iconAnchor: [0, 80],
html: '<object data="' + positionItem['Icon'] + '" type="image/svg+xml" style="height:80px; width:56px;"></object>'
}));
} else if (markers[key]._icon.children[0].hasAttribute("data")) {
var old = markers[key]._icon.children[0]["data"].substring(markers[key]._icon.children[0]["data"].indexOf("/", 7) + 1);
if (old !== positionItem['Icon']) {
markers[key]._icon.children[0]["data"] = positionItem['Icon'];
}
}
} else {
if (markers[key]._icon.children.length === 1 && markers[key]._icon.children[0].hasAttribute("data")) {
markers[key].removeFrom(mymap);
markers[key] = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'] }).addTo(mymap).on("click", showMarkerInfo, key);
}
}
}
}
}

View File

@ -93,6 +93,20 @@ function updateOverviewElement(positionItem, id) {
document.getElementById("overview-gps-id-" + id).style.color = "red";
}
document.getElementById("overview-update-id-" + id).innerText = "Letzter Datenempfang: vor " + timeCalculation(positionItem["Recievedtime"], "difftext");
if (positionItem['Icon'] === null) {
var icon = document.getElementById("overview-icon-id-" + id);
if (icon.children[0].hasAttribute("data")) {
document.getElementById("overview-icon-id-" + id).innerHTML = "<img src =\"icons/marker/map-marker.png\">";
}
} else {
if (document.getElementById("overview-icon-id-" + id).children[0].hasAttribute("data")) {
if (document.getElementById("overview-icon-id-" + id).children[0]["data"].substring(document.getElementById("overview-icon-id-" + id).children[0]["data"].indexOf("/", 7) + 1) !== positionItem['Icon'] + "&marker-bg=hidden") {
document.getElementById("overview-icon-id-" + id).children[0]["data"] = positionItem['Icon'] + "&marker-bg=hidden";
}
} else {
document.getElementById("overview-icon-id-" + id).innerHTML = "<object data=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" type=\"image/svg+xml\"></object>";
}
}
}
function createOverviewElement(positionItem, id) {
@ -102,9 +116,9 @@ function createOverviewElement(positionItem, id) {
divItem.setAttribute("rel", id);
divItem.innerHTML = "<span class=\"color\" id=\"overview-color-id-" + id + "\"></span>";
if (positionItem['Icon'] !== null) {
divItem.innerHTML += "<span class=\"icon\"><object data=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" type=\"image/svg+xml\"></object></span>";
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><object data=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" type=\"image/svg+xml\"></object></span>";
} else {
divItem.innerHTML += "<span class=\"icon\"><img src=\"icons/marker/map-marker.png\"></span>";
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><img src=\"icons/marker/map-marker.png\"></span>";
}
divItem.innerHTML += "<div class=\"line1\">" +
"<span class=\"name\" id=\"overview-name-id-" + id + "\"></span>" +
@ -119,7 +133,7 @@ function createOverviewElement(positionItem, id) {
function update_pannels_admin() {
var testadmin = new XMLHttpRequest();
testadmin.onreadystatechange = parseAjaxPannelAdmin;
testadmin.open("GET", "http://{%REQUEST_URL_HOST%}:8080/admin", true);
testadmin.open("GET", "http://{%REQUEST_URL_HOST%}/admin", true);
testadmin.send();
}
@ -131,14 +145,14 @@ function parseAjaxPannelAdmin() {
html += "<div><span class='login'><input type='submit'></span></div></form>";
document.getElementById("pannels_admin").innerHTML = html;
} else if (this.readyState === 4 && this.status === 200) {
document.getElementById("pannels_admin").innerHTML = "<a href='/admin' target='_blank'>Adminpannel</a>";
document.getElementById("pannels_admin").innerHTML = "<a href='/admin/' target='_blank'>Adminpannel</a>";
}
}
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));
}