diff --git a/src/Sys/SysModFiles.cpp b/src/Sys/SysModFiles.cpp index 02a9c7a..033eeb6 100644 --- a/src/Sys/SysModFiles.cpp +++ b/src/Sys/SysModFiles.cpp @@ -34,12 +34,6 @@ void SysModFiles::setup() { case onUI: ui->setComment(var, "List of files"); return true; - case onAdd: - rowNr = fileNames.size(); - web->getResponseObject()["onAdd"]["rowNr"] = rowNr; //also done in callVarFun?? - //add a row with all defaults - //tbd: File upload does not call onAdd (bug?) - return true; case onDelete: if (rowNr != UINT8_MAX && rowNr < fileNames.size()) { const char * fileName = fileNames[rowNr].s; @@ -54,11 +48,9 @@ void SysModFiles::setup() { strlcpy(web->lastFileUpdated, name, sizeof(web->lastFileUpdated)); } #endif - - // print->printVar(var); - // ppf("\n"); } return true; + //tbd: File upload does not call onAdd (bug?) default: return false; }}); diff --git a/src/Sys/SysModSystem.cpp b/src/Sys/SysModSystem.cpp index 8ef8e38..e00279b 100644 --- a/src/Sys/SysModSystem.cpp +++ b/src/Sys/SysModSystem.cpp @@ -211,7 +211,7 @@ void SysModSystem::setup() { ui->initFileUpload(parentVar, "update", nullptr, UINT16_MAX, false, [](JsonObject var, uint8_t rowNr, uint8_t funType) { switch (funType) { //varFun case onUI: - ui->setComment(var, "OTA Update"); + ui->setComment(var, "OTA Firmware Update"); return true; default: return false; }}); diff --git a/src/Sys/SysModUI.cpp b/src/Sys/SysModUI.cpp index cf05016..29a2bb2 100644 --- a/src/Sys/SysModUI.cpp +++ b/src/Sys/SysModUI.cpp @@ -179,24 +179,16 @@ void SysModUI::processJson(JsonVariant json) { uint8_t rowNr = command["rowNr"].isNull()?UINT8_MAX:command["rowNr"]; ppf("processJson %s - %s[%d]\n", key, Variable(var).id(), rowNr); - bool doWS = false; - - if (callVarFun(var, rowNr, pair.key() == "onAdd"?onAdd:onDelete)) { - doWS = true; - } + callVarFun(var, rowNr, pair.key() == "onAdd"?onAdd:onDelete); //first remove the deleted row both on server and on client(s) if (pair.key() == "onDelete") { - ppf("onDelete remove values\n"); + ppf("onDelete remove removeValuesForRow\n"); Variable(var).removeValuesForRow(rowNr); - doWS = true; } - - if (doWS) - web->sendResponseObject(); //async response //trigger receiveData->onDelete - } - json.remove(key); //key processed we don't need the key in the response + // we need to send back the key so UI can add or delete the value + // json.remove(key); //key processed we don't need the key in the response } else if (pair.key() == "onUI") { //JsonString can do == //find the select var and collect it's options... diff --git a/src/Sys/SysModUI.h b/src/Sys/SysModUI.h index 1dc5d17..8123aee 100644 --- a/src/Sys/SysModUI.h +++ b/src/Sys/SysModUI.h @@ -319,8 +319,36 @@ class SysModUI: public SysModule { Variable variable = Variable(var); bool result = false; + //call varFun if exists + if (!var["fun"].isNull()) {//isNull needed here! + size_t funNr = var["fun"]; + if (funNr < varFunctions.size()) { + result = varFunctions[funNr](var, rowNr, funType); + if (result && !variable.readOnly()) { //send rowNr = 0 if no rowNr + //only print vars with a value and not onSetValue as that changes a lot due to insTbl clTbl etc (tbd) + //don't print if onSetValue or oldValue is null + if (funType != onSetValue && (!var["oldValue"].isNull() || ((rowNr != UINT8_MAX) && !var["oldValue"][rowNr].isNull()))) { + ppf("%sFun %s", funType==onSetValue?"val":funType==onUI?"ui":funType==onChange?"ch":funType==onAdd?"add":funType==onDelete?"del":"other", Variable(var).id()); + if (rowNr != UINT8_MAX) { + ppf("[%d] (", rowNr); + if (funType == onChange) ppf("%s ->", var["oldValue"][rowNr].as().c_str()); + ppf("%s)\n", var["value"][rowNr].as().c_str()); + } + else { + ppf(" ("); + if (funType == onChange) ppf("%s ->", var["oldValue"].as().c_str()); + ppf("%s)\n", variable.valueString().c_str()); + } + } + } //varFun exists + } + else + ppf("dev callVarFun function nr %s.%s outside bounds %d >= %d\n", variable.pid(), variable.id(), funNr, varFunctions.size()); + } //varFun exists + + //delete pointers after calling var.onDelete as var.onDelete might need the values if (funType == onAdd || funType == onDelete) { - //do this before calling onDelete + print->printJson("callVarFun add/del", var); //if delete, delete also from vector ... //find the columns of the table @@ -338,54 +366,33 @@ class SysModUI: public SysModule { //pointer checks if (childVar["type"] == "select" || childVar["type"] == "range" || childVar["type"] == "pin") { std::vector *valuePointer = (std::vector *)pointer; - (*valuePointer).erase((*valuePointer).begin() + rowNr); + if (rowNr < (*valuePointer).size()) + (*valuePointer).erase((*valuePointer).begin() + rowNr); } else if (childVar["type"] == "number") { std::vector *valuePointer = (std::vector *)pointer; - (*valuePointer).erase((*valuePointer).begin() + rowNr); + if (rowNr < (*valuePointer).size()) + (*valuePointer).erase((*valuePointer).begin() + rowNr); } else if (childVar["type"] == "checkbox") { std::vector *valuePointer = (std::vector *)pointer; - (*valuePointer).erase((*valuePointer).begin() + rowNr); + if (rowNr < (*valuePointer).size()) + (*valuePointer).erase((*valuePointer).begin() + rowNr); } else if (childVar["type"] == "text" || childVar["type"] == "fileEdit") { std::vector *valuePointer = (std::vector *)pointer; - (*valuePointer).erase((*valuePointer).begin() + rowNr); + if (rowNr < (*valuePointer).size()) + (*valuePointer).erase((*valuePointer).begin() + rowNr); } else if (childVar["type"] == "coord3D") { std::vector *valuePointer = (std::vector *)pointer; - (*valuePointer).erase((*valuePointer).begin() + rowNr); + if (rowNr < (*valuePointer).size()) + (*valuePointer).erase((*valuePointer).begin() + rowNr); } else print->printJson("dev callVarFun onDelete type not supported yet", childVar); } } - } + } //onDelete web->getResponseObject()[funType==onAdd?"onAdd":"onDelete"]["rowNr"] = rowNr; - } - - //call varFun if exists - if (!var["fun"].isNull()) {//isNull needed here! - size_t funNr = var["fun"]; - if (funNr < varFunctions.size()) { - result = varFunctions[funNr](var, rowNr, funType); - if (result && !variable.readOnly()) { //send rowNr = 0 if no rowNr - //only print vars with a value and not onSetValue as that changes a lot due to insTbl clTbl etc (tbd) - //don't print if onSetValue or oldValue is null - if (funType != onSetValue && (!var["oldValue"].isNull() || ((rowNr != UINT8_MAX) && !var["oldValue"][rowNr].isNull()))) { - ppf("%sFun %s", funType==onSetValue?"val":funType==onUI?"ui":funType==onChange?"ch":funType==onAdd?"add":funType==onDelete?"del":"other", Variable(var).id()); - if (rowNr != UINT8_MAX) { - ppf("[%d] (", rowNr); - if (funType == onChange) ppf("%s ->", var["oldValue"][rowNr].as().c_str()); - ppf("%s)\n", var["value"][rowNr].as().c_str()); - } - else { - ppf(" ("); - if (funType == onChange) ppf("%s ->", var["oldValue"].as().c_str()); - ppf("%s)\n", variable.valueString().c_str()); - } - } - } - } - else - ppf("dev callVarFun function nr %s.%s outside bounds %d >= %d\n", variable.pid(), variable.id(), funNr, varFunctions.size()); - } + print->printJson("callVarFun add/del response", web->getResponseObject()); + } //onAdd onDelete //for ro variables, call onSetValue to add also the value in responseDoc (as it is not stored in the model) if (funType == onUI && variable.readOnly()) { diff --git a/src/Sys/SysModWeb.cpp b/src/Sys/SysModWeb.cpp index e582f52..f9b55f3 100644 --- a/src/Sys/SysModWeb.cpp +++ b/src/Sys/SysModWeb.cpp @@ -324,7 +324,7 @@ void SysModWeb::wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, v sendResponseObject(isOnUI?client:nullptr); //onUI only send to requesting client async response } else { - ppf("WS_EVT_DATA no responseDoc\n"); + ppf("wsEvent no responseDoc\n"); client->text("{\"success\":true}"); // we have to send something back otherwise WS connection closes } } diff --git a/src/User/UserModLive.h b/src/User/UserModLive.h index cf5a7a0..0a6246e 100644 --- a/src/User/UserModLive.h +++ b/src/User/UserModLive.h @@ -118,7 +118,7 @@ class UserModLive:public SysModule { parentVar = ui->initUserMod(parentVar, name, 6310); - ui->initSelect(parentVar, "script", UINT16_MAX, false, [this](JsonObject var, uint8_t rowNr, uint8_t funType) { switch (funType) { //varFun + ui->initSelect(parentVar, "script", UINT8_MAX, false, [this](JsonObject var, uint8_t rowNr, uint8_t funType) { switch (funType) { //varFun case onUI: { // ui->setComment(var, "Fixture to display effect on"); JsonArray options = ui->setOptions(var); @@ -148,13 +148,13 @@ class UserModLive:public SysModule { ui->initText(parentVar, "fps1", nullptr, 10, true, [this](JsonObject var, uint8_t rowNr, uint8_t funType) { switch (funType) { //varFun case onLoop1s: - mdl->setValue(var, "%.0f /s", fps); + mdl->setValue(var, "%.0f /s", fps, 0); //0 is to force format overload used return true; default: return false; }}); ui->initText(parentVar, "fps2", nullptr, 10, true, [this](JsonObject var, uint8_t rowNr, uint8_t funType) { switch (funType) { //varFun case onLoop1s: - mdl->setValue(var, "%d /s", frameCounter); + mdl->setValue(var, "%d /s", frameCounter, 0); //0 is to force format overload used frameCounter = 0; return true; default: return false;