From 3dee474356eb273df59da64ab62a028a0e087bf8 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Sun, 4 Aug 2019 20:19:33 +0200 Subject: [PATCH] Instance names can now be renamed on the WebUI (incl. inst 0) Signed-off-by: Paulchen-Panther --- assets/webconfig/css/hyperion.css | 4 ++ assets/webconfig/i18n/de.json | 10 ++++ assets/webconfig/i18n/en.json | 2 + assets/webconfig/js/content_general.js | 36 +++++++++---- assets/webconfig/js/hyperion.js | 5 ++ assets/webconfig/js/ui_utils.js | 51 +++++++++++++------ .../build/tinkerforge/ip_connection.c | 4 +- include/db/InstanceTable.h | 40 ++++++++++----- libsrc/api/JsonAPI.cpp | 13 +++-- 9 files changed, 121 insertions(+), 44 deletions(-) diff --git a/assets/webconfig/css/hyperion.css b/assets/webconfig/css/hyperion.css index e2dbaa51..9c409f19 100644 --- a/assets/webconfig/css/hyperion.css +++ b/assets/webconfig/css/hyperion.css @@ -196,6 +196,10 @@ table label{margin:0} background-color:#d1322e; } +.modal-icon-edit{ + background-color:#3579b6; +} + .overlay { background-image: url('/img/hyperion/hyperionwhitelogo.png'); background-repeat: no-repeat; diff --git a/assets/webconfig/i18n/de.json b/assets/webconfig/i18n/de.json index 70ef288e..cb955d54 100644 --- a/assets/webconfig/i18n/de.json +++ b/assets/webconfig/i18n/de.json @@ -35,6 +35,7 @@ "general_btn_stop" : "Stop", "general_btn_continue": "Fortfahren", "general_btn_delete" : "Löschen", + "general_btn_rename" : "Umbenennen", "general_btn_save": "Speichern", "general_btn_saverestart": "Speichern und neustarten", "general_btn_saveandreload": "Speichern und neu laden", @@ -103,6 +104,15 @@ "conf_general_impexp_l2": "Exportiere eine Konfiguration, indem du auf \"Exportieren\" klickst. Dein Browser startet einen Download.", "conf_general_impexp_impbtn": "Importieren", "conf_general_impexp_expbtn": "Exportieren", + "conf_general_inst_title" : "LED Hardware Instanzverwaltung", + "conf_general_inst_desc" : "Verwende mehrere LED Hardware gleichzeitig. Jede Instanz läuft unabhängig voneinander, wodurch unterschiedliche LED-Layouts und Kalibrierungseinstellungen möglich sind. Laufende Instanzen sind in der oberen Symbolleiste verfügbar.", + "conf_general_inst_namehead" : "Instanzname", + "conf_general_inst_actionhead" : "Aktionen", + "conf_general_inst_name_title" : "Neuer Instanzname", + "conf_general_createInst_btn" : "Instanz erstellen", + "conf_general_inst_renreq_t" : "Gib in das untere Feld deinen neuen Instanznamen ein.", + "conf_general_inst_delreq_h" : "LED Hardware Instanz löschen", + "conf_general_inst_delreq_t" : "Bist du Dir sicher, das du die Instanz \"$1\" löschen möchtest? Alle Einstellungen zu dieser Instanz gehen verloren.", "conf_helptable_option": "Option", "conf_helptable_expl": "Erklärung", "conf_effect_path_intro": "Hier kannst du Ordner angeben, die beim Laden von Effekten berücksichtig werden sollen. Zusätzlich können Effekte anhand ihres Namens deaktiviert werden um sie aus Listen zu löschen.", diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index aeff1618..a73a64dc 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -34,6 +34,7 @@ "general_btn_stop" : "Stop", "general_btn_cancel" : "Cancel", "general_btn_delete" : "Delete", + "general_btn_rename" : "Rename", "general_btn_continue" : "Continue", "general_btn_save" : "Save", "general_btn_saveandreload" : "Save and reload", @@ -108,6 +109,7 @@ "conf_general_inst_actionhead" : "Action", "conf_general_inst_name_title" : "New Instance name", "conf_general_createInst_btn" : "Create Instance", + "conf_general_inst_renreq_t" : "Enter a new name for your instance in the field below.", "conf_general_inst_delreq_h" : "Delete LED Hardware instance", "conf_general_inst_delreq_t" : "Are you sure that you want to delete instance \"$1\"? All settings will be deleted too.", "conf_helptable_option" : "Option", diff --git a/assets/webconfig/js/content_general.js b/assets/webconfig/js/content_general.js index f35bc0dd..33260cde 100644 --- a/assets/webconfig/js/content_general.js +++ b/assets/webconfig/js/content_general.js @@ -25,9 +25,21 @@ $(document).ready( function() { requestWriteConfig(conf_editor.getValue()); }); - - // Instance handling + function handleInstanceRename(e) + { + var inst = e.currentTarget.id.split("_")[1]; + showInfoDialog('renInst', $.i18n('conf_general_inst_renreq_t'), getInstanceNameByIndex(inst)); + + $("#id_btn_ok").off().on('click', function(){ + requestInstanceRename(inst, $('#renInst_name').val()) + }); + + $('#renInst_name').off().on('input',function(e) { + (e.currentTarget.value.length >= 5 && e.currentTarget.value != getInstanceNameByIndex(inst)) ? $('#id_btn_ok').attr('disabled', false) : $('#id_btn_ok').attr('disabled', true); + }); + } + function handleInstanceStartStop(e) { var inst = e.currentTarget.id.split("_")[1]; @@ -38,7 +50,7 @@ $(document).ready( function() { function handleInstanceDelete(e) { var inst = e.currentTarget.id.split("_")[1]; - showInfoDialog('delplug',$.i18n('conf_general_inst_delreq_h'),$.i18n('conf_general_inst_delreq_t',getInstanceNameByIndex(inst))); + showInfoDialog('delInst',$.i18n('conf_general_inst_delreq_h'),$.i18n('conf_general_inst_delreq_t',getInstanceNameByIndex(inst))); $("#id_btn_yes").off().on('click', function(){ requestInstanceDelete(inst) }); @@ -51,29 +63,35 @@ $(document).ready( function() { for(var key in inst) { var startBtnColor = inst[key].running ? "success" : "danger"; + var startBtnIcon = inst[key].running ? "stop" : "play"; var startBtnText = inst[key].running ? $.i18n('general_btn_stop') : $.i18n('general_btn_start'); - var startBtn = "-" - var delBtn = "-"; + var renameBtn = ''; + var startBtn = "" + var delBtn = ""; if(inst[key].instance > 0) { - delBtn = ''; - startBtn = ''; + delBtn = ''; + startBtn = ''; } - $('.itbody').append(createTableRow([inst[key].friendly_name, startBtn, delBtn], false, true)); + $('.itbody').append(createTableRow([inst[key].friendly_name, renameBtn, startBtn, delBtn], false, true)); + $('#instren_'+inst[key].instance).off().on('click', handleInstanceRename); $('#inst_'+inst[key].instance).off().on('click', handleInstanceStartStop); $('#instdel_'+inst[key].instance).off().on('click', handleInstanceDelete); } } createTable('ithead', 'itbody', 'itable'); - $('.ithead').html(createTableRow([$.i18n('conf_general_inst_namehead'), $.i18n('conf_general_inst_actionhead'), $.i18n('general_btn_delete')], true, true)); + $('.ithead').html(createTableRow([$.i18n('conf_general_inst_namehead'), "", $.i18n('conf_general_inst_actionhead'), ""], true, true)); buildInstanceList(); $('#inst_name').off().on('input',function(e) { (e.currentTarget.value.length >= 5) ? $('#btn_create_inst').attr('disabled', false) : $('#btn_create_inst').attr('disabled', true); }); + $('#btn_create_inst').off().on('click',function(e) { requestInstanceCreate($('#inst_name').val()); + $('#inst_name').val(""); + $('#btn_create_inst').attr('disabled', true) }); $(hyperion).off("instance-updated").on("instance-updated", function(event) { diff --git a/assets/webconfig/js/hyperion.js b/assets/webconfig/js/hyperion.js index a57a0885..14373d11 100644 --- a/assets/webconfig/js/hyperion.js +++ b/assets/webconfig/js/hyperion.js @@ -190,6 +190,11 @@ function requestTokenDelete(id) sendToHyperion("authorize","deleteToken",'"id":"'+id+'"'); } +function requestInstanceRename(inst, name) +{ + sendToHyperion("instance", "saveName",'"instance": '+inst+', "name": "'+name+'"'); +} + function requestInstanceStartStop(inst, start) { if(start) diff --git a/assets/webconfig/js/ui_utils.js b/assets/webconfig/js/ui_utils.js index 705840c7..ada22303 100644 --- a/assets/webconfig/js/ui_utils.js +++ b/assets/webconfig/js/ui_utils.js @@ -214,53 +214,69 @@ function setClassByBool(obj,enable,class1,class2) function showInfoDialog(type,header,message) { - if (type=="success"){ + if (type=="success") + { $('#id_body').html(''); if(header == "") $('#id_body').append('

'+$.i18n('infoDialog_general_success_title')+'

'); $('#id_footer').html(''); } - else if (type=="warning"){ + else if (type=="warning") + { $('#id_body').html(''); if(header == "") $('#id_body').append('

'+$.i18n('infoDialog_general_warning_title')+'

'); $('#id_footer').html(''); } - else if (type=="error"){ + else if (type=="error") + { $('#id_body').html(''); if(header == "") $('#id_body').append('

'+$.i18n('infoDialog_general_error_title')+'

'); $('#id_footer').html(''); } - else if (type == "select"){ + else if (type == "select") + { $('#id_body').html('Redefine ambient light!'); $('#id_footer').html(''); $('#id_footer').append(''); } - else if (type == "iswitch"){ + else if (type == "iswitch") + { $('#id_body').html('Redefine ambient light!'); $('#id_footer').html(''); $('#id_footer').append(''); } - else if (type == "uilock"){ + else if (type == "uilock") + { $('#id_body').html('Redefine ambient light!'); $('#id_footer').html(''+$.i18n('InfoDialog_nowrite_foottext')+''); } - else if (type == "import"){ + else if (type == "import") + { $('#id_body').html(''); $('#id_footer').html(''); $('#id_footer').append(''); } - else if (type == "delplug"){ - $('#id_body').html(''); + else if (type == "delInst") + { + $('#id_body').html(''); $('#id_footer').html(''); $('#id_footer').append(''); } + else if (type == "renInst") + { + $('#id_body').html('
'); + $('#id_body').append('

'+header+'

'); + $('#id_body').append(''); + $('#id_footer').html(''); + $('#id_footer').append(''); + } else if (type == "checklist") { $('#id_body').html('Redefine ambient light!'); $('#id_body').append('

'+$.i18n('infoDialog_checklist_title')+'

'); - $('#id_body').append(message); + $('#id_body').append(header); $('#id_footer').html(''); } else if (type == "newToken") @@ -275,8 +291,11 @@ function showInfoDialog(type,header,message) $('#id_footer').append(''); } - $('#id_body').append('

'+header+'

'); - $('#id_body').append(message); + if(type != "renInst") + { + $('#id_body').append('

'+header+'

'); + $('#id_body').append(message); + } if(type == "select" || type == "iswitch") $('#id_body').append(''); @@ -669,8 +688,8 @@ function createHelpTable(list, phead){ // break one iteration (in the loop), if the schema has the entry hidden=true if ("options" in list[key] && "hidden" in list[key].options && (list[key].options.hidden)) continue; - if ("access" in list[key] && ((list[key].access == "advanced" && storedAccess == "default") || (list[key].access == "expert" && storedAccess != "expert"))) - continue; + if ("access" in list[key] && ((list[key].access == "advanced" && storedAccess == "default") || (list[key].access == "expert" && storedAccess != "expert"))) + continue; var text = list[key].title.replace('title', 'expl'); tbody.appendChild(createTableRow([$.i18n(list[key].title), $.i18n(text)], false, false)); @@ -682,8 +701,8 @@ function createHelpTable(list, phead){ // break one iteration (in the loop), if the schema has the entry hidden=true if ("options" in ilist[ikey] && "hidden" in ilist[ikey].options && (ilist[ikey].options.hidden)) continue; - if ("access" in ilist[ikey] && ((ilist[ikey].access == "advanced" && storedAccess == "default") || (ilist[ikey].access == "expert" && storedAccess != "expert"))) - continue; + if ("access" in ilist[ikey] && ((ilist[ikey].access == "advanced" && storedAccess == "default") || (ilist[ikey].access == "expert" && storedAccess != "expert"))) + continue; var itext = ilist[ikey].title.replace('title', 'expl'); tbody.appendChild(createTableRow([$.i18n(ilist[ikey].title), $.i18n(itext)], false, false)); } diff --git a/dependencies/build/tinkerforge/ip_connection.c b/dependencies/build/tinkerforge/ip_connection.c index 5e8a30e8..0e496542 100644 --- a/dependencies/build/tinkerforge/ip_connection.c +++ b/dependencies/build/tinkerforge/ip_connection.c @@ -80,10 +80,10 @@ typedef struct { #define STATIC_ASSERT(condition, message) \ _Static_assert(condition, message) #else - #define STATIC_ASSERT(condition, message) // FIXME + #define STATIC_ASSERT(condition, message) #endif #else - #define STATIC_ASSERT(condition, message) // FIXME + #define STATIC_ASSERT(condition, message) #endif STATIC_ASSERT(sizeof(PacketHeader) == 8, "PacketHeader has invalid size"); diff --git a/include/db/InstanceTable.h b/include/db/InstanceTable.h index 5cb8b0cb..1b7d880c 100644 --- a/include/db/InstanceTable.h +++ b/include/db/InstanceTable.h @@ -25,7 +25,7 @@ public: setTable("instances"); createTable(QStringList()<<"instance INTEGER"<<"friendly_name TEXT"<<"enabled INTEGER DEFAULT 0"<<"last_use TEXT"); - // create the first Hyperion instance index 0 + // start/create the first Hyperion instance index 0 createInstance(); }; @@ -93,14 +93,21 @@ public: /// inline bool saveName(const quint8& inst, const QString& name) { - if(instanceExist(inst)) - { - VectorPair cond; - cond.append(CPair("instance",inst)); - QVariantMap data; - data["friendly_name"] = name; + VectorPair fcond; + fcond.append(CPair("friendly_name",name)); - return updateRecord(cond, data); + // check duplicate + if(!recordExists(fcond)) + { + if(instanceExist(inst)) + { + VectorPair cond; + cond.append(CPair("instance",inst)); + QVariantMap data; + data["friendly_name"] = name; + + return updateRecord(cond, data); + } } return false; } @@ -207,13 +214,18 @@ private: /// inline void createInstance() { - QVariantMap data; - data["friendly_name"] = "First LED Hardware instance"; - VectorPair cond; - cond.append(CPair("instance", 0)); - if(createRecord(cond, data)) + if(instanceExist(0)) setEnable(0, true); else - throw std::runtime_error("Failed to create Hyperion root instance in db! This should never be the case..."); + { + QVariantMap data; + data["friendly_name"] = "First LED Hardware instance"; + VectorPair cond; + cond.append(CPair("instance", 0)); + if(createRecord(cond, data)) + setEnable(0, true); + else + throw std::runtime_error("Failed to create Hyperion root instance in db! This should never be the case..."); + } } }; diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp index 16d8ccf3..8efd5120 100644 --- a/libsrc/api/JsonAPI.cpp +++ b/libsrc/api/JsonAPI.cpp @@ -1298,9 +1298,16 @@ void JsonAPI::handleInstanceCommand(const QJsonObject & message, const QString & if(subc == "saveName") { - // silent fail - _instanceManager->saveName(inst,name); - sendSuccessReply(command+"-"+subc, tan); + if(_userAuthorized) + { + // silent fail + if(_instanceManager->saveName(inst,name)) + sendSuccessReply(command+"-"+subc, tan); + else + sendErrorReply(QString("The instance name '%1' is already in use").arg(name), command+"-"+subc, tan); + } + else + sendErrorReply("No Authorization",command+"-"+subc, tan); return; } }