From 5438d7bbd931abdbc36ab506700e374f20e54b5c Mon Sep 17 00:00:00 2001 From: Proddy Date: Mon, 2 May 2022 13:08:31 +0200 Subject: [PATCH 1/3] API extract individual attributes - #462 --- CHANGELOG_LATEST.md | 1 + src/command.cpp | 19 ++++++++----------- src/emsdevice.cpp | 38 +++++++++++++++++++++++++++++++++++--- src/test/test.cpp | 13 ++++++++++++- src/test/test.h | 4 ++-- src/version.h | 2 +- src/web/WebAPIService.cpp | 9 +++++++++ 7 files changed, 68 insertions(+), 18 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 2a610339d..b665af1e2 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -37,6 +37,7 @@ - Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437) - Added Shower Alert trigger time and cold shot time [#436](https://github.com/emsesp/EMS-ESP32/issues/436) - Improved Table layout in Web UI (searching, filtering, sorting, exporting to CSV) +- API fetch individual attributes from an entity [#462](https://github.com/emsesp/EMS-ESP32/issues/462) ### Fixed diff --git a/src/command.cpp b/src/command.cpp index 98d5b63b2..d8c7b8406 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -86,7 +86,7 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec return message(CommandRet::ERROR, "unknown device", output); } - // the next value on the path should be the command + // the next value on the path should be the command or entity name const char * command_p = nullptr; if (num_paths == 2) { command_p = p.paths()[1].c_str(); @@ -104,7 +104,7 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec } } - // some commands may be prefixed with hc. or wwc. so extract these if they exist + // some commands may be prefixed with hc. wwc. or hc/ or wwc/ so extract these if they exist // parse_command_string returns the extracted command command_p = parse_command_string(command_p, id_n); if (command_p == nullptr) { @@ -189,7 +189,7 @@ const char * Command::parse_command_string(const char * command, int8_t & id) { } // make a copy of the string command for parsing - char command_s[100]; + char command_s[30]; strlcpy(command_s, command, sizeof(command_s)); // look for a delimeter and split the string @@ -202,7 +202,7 @@ const char * Command::parse_command_string(const char * command, int8_t & id) { p = command_s; // reset and look for _ breakp = strchr(p, '_'); if (!breakp) { - return command; + return command; // no delimeter found, return the whole string } } } @@ -214,10 +214,8 @@ const char * Command::parse_command_string(const char * command, int8_t & id) { } else if (!strncmp(command, "wwc", 3) && start_pos == 5) { id = command[start_pos - 2] - '0' + 8; // wwc1 has id 9 } else { -#if defined(EMSESP_DEBUG) - LOG_DEBUG(F("[DEBUG] Command parse error, unknown hc/wwc in %s"), command_s); -#endif - return nullptr; + id = 0; // special case for extracting the attributes + return command; } return (command + start_pos); @@ -244,13 +242,12 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * // see if there is a command registered auto cf = find_command(device_type, cmd); - // check if its a call to and end-point to a device, i.e. has no value + // check if its a call to and end-point to a device // except for system commands as this is a special device without any queryable entities (device values) - // exclude SYSTEM if ((device_type > EMSdevice::DeviceType::SYSTEM) && (!value || !strlen(value))) { if (!cf || !cf->cmdfunction_json_) { #if defined(EMSESP_DEBUG) - LOG_DEBUG(F("[DEBUG] Calling %s command '%s' to retrieve values"), dname.c_str(), cmd); + LOG_DEBUG(F("[DEBUG] Calling %s command '%s' to retrieve attributes"), dname.c_str(), cmd); #endif return EMSESP::get_device_value_info(output, cmd, id, device_type) ? CommandRet::OK : CommandRet::ERROR; // entity = cmd } diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 3e9c728ab..b3e5897f6 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -915,13 +915,26 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8 tag = DeviceValueTAG::TAG_HC1 + id - 1; } else if (id >= 9 && id <= 19) { tag = DeviceValueTAG::TAG_WWC1 + id - 9; - } else if (id != -1) { - return false; // error + } + + // make a copy of the string command for parsing + char command_s[30]; + strlcpy(command_s, cmd, sizeof(command_s)); + char * attribute_s = command_s; + + // if id=0 then we have a specific attribute to fetch instead of the complete record + if (id == 0) { + char * p = command_s; + char * breakp = strchr(p, '/'); + if (breakp) { + *breakp = '\0'; + attribute_s = breakp + 1; + } } // search device value with this tag for (auto & dv : devicevalues_) { - if (strcmp(cmd, Helpers::toLower(read_flash_string(dv.short_name)).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) { + if (strcmp(command_s, Helpers::toLower(read_flash_string(dv.short_name)).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) { int8_t divider = (dv.options_size == 1) ? Helpers::atoint(read_flash_string(dv.options[0]).c_str()) : 0; uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0; @@ -1060,6 +1073,25 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8 json[value] = "not set"; } + // if id is 0 then we're filtering on an attribute, go find it + if (id == 0) { +#if defined(EMSESP_DEBUG) + EMSESP::logger().debug(F("[DEBUG] Attribute '%s'"), attribute_s); +#endif + if (json.containsKey(attribute_s)) { + JsonVariant data = json[attribute_s]; + output.clear(); + output["api_data"] = data; + return true; + } else { + char error[100]; + snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, command_s); + output.clear(); + output["message"] = error; + return false; + } + } + return true; } } diff --git a/src/test/test.cpp b/src/test/test.cpp index 029636c9f..66f70989f 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -660,9 +660,20 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const DynamicJsonDocument doc(2000); JsonVariant json; request.method(HTTP_GET); + + request.url("/api/boiler/values"); + EMSESP::webAPIService.webAPIService_get(&request); request.url("/api/boiler/wwcirc"); EMSESP::webAPIService.webAPIService_get(&request); - request.url("/api/boiler/values"); + request.url("/api/boiler/wwcirc/fullname"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/boiler/selburnpow/value"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/boiler/wwchargetype/writeable"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/boiler/flamecurr/value"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/boiler/flamecurr/bad"); EMSESP::webAPIService.webAPIService_get(&request); #endif } diff --git a/src/test/test.h b/src/test/test.h index 65021652e..be3bf9cb1 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -31,7 +31,7 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "mixer" // #define EMSESP_DEBUG_DEFAULT "web" // #define EMSESP_DEBUG_DEFAULT "mqtt" -#define EMSESP_DEBUG_DEFAULT "general" +// #define EMSESP_DEBUG_DEFAULT "general" // #define EMSESP_DEBUG_DEFAULT "boiler" // #define EMSESP_DEBUG_DEFAULT "mqtt2" // #define EMSESP_DEBUG_DEFAULT "mqtt_nested" @@ -48,7 +48,7 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "2thermostats" // #define EMSESP_DEBUG_DEFAULT "dallas" // #define EMSESP_DEBUG_DEFAULT "analog" -// #define EMSESP_DEBUG_DEFAULT "api_values" +#define EMSESP_DEBUG_DEFAULT "api_values" // #define EMSESP_DEBUG_DEFAULT "mqtt_post" class Test { diff --git a/src/version.h b/src/version.h index 60abd800d..b411d73c8 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.4.0b15" +#define EMSESP_APP_VERSION "3.4.0b16" diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index 3ade88792..be8966a1e 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -120,6 +120,15 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) { } } + // if we're returning single values, just sent as plain text + // https://github.com/emsesp/EMS-ESP32/issues/462#issuecomment-1093877210 + if (output.containsKey("api_data")) { + JsonVariant data = output["api_data"]; + request->send(200, "text/plain", data.as()); + api_count_++; + return; + } + // send the json that came back from the command call // FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED = 400 (bad request), 200 (OK), 400 (not found), 400 (bad request), 401 (unauthorized) int ret_codes[5] = {400, 200, 400, 400, 401}; From 883c81320b4442c35a989615af074a3dc2a057f8 Mon Sep 17 00:00:00 2001 From: Proddy Date: Mon, 2 May 2022 15:11:42 +0200 Subject: [PATCH 2/3] package updates --- interface/package-lock.json | 74 ++++++++++++++++++------------------- interface/package.json | 6 +-- mock-api/package-lock.json | 14 +++---- mock-api/package.json | 2 +- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/interface/package-lock.json b/interface/package-lock.json index 6b6cb4442..080159463 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -12,10 +12,10 @@ "@emotion/styled": "^11.8.1", "@msgpack/msgpack": "^2.7.2", "@mui/icons-material": "^5.6.2", - "@mui/material": "^5.6.3", + "@mui/material": "^5.6.4", "@table-library/react-table-library": "^3.1.0", "@types/lodash": "^4.14.182", - "@types/node": "^17.0.30", + "@types/node": "^17.0.31", "@types/react": "^17.0.43", "@types/react-dom": "^17.0.14", "@types/react-router-dom": "^5.3.3", @@ -29,7 +29,7 @@ "react": "^17.0.2", "react-app-rewired": "^2.2.1", "react-dom": "^17.0.2", - "react-dropzone": "^14.0.1", + "react-dropzone": "^14.1.1", "react-icons": "^4.3.1", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", @@ -2856,9 +2856,9 @@ } }, "node_modules/@mui/base": { - "version": "5.0.0-alpha.78", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.78.tgz", - "integrity": "sha512-5L+GNe2M9/tFjQpjK2r837+kzRg/l6D5R9SQbG1wmSWejw5Ei8P+KXIgS/NLNi9g7dUT8bnCyzz9AZKQX1Jsfg==", + "version": "5.0.0-alpha.79", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.79.tgz", + "integrity": "sha512-/lZLF027BkiEjM8MIYoeS/FEhTKf+41ePU9SOijMGrCin1Y0Igucw+IHa1fF8HXD7wDbFKqHuso3J1jMG8wyNw==", "dependencies": { "@babel/runtime": "^7.17.2", "@emotion/is-prop-valid": "^1.1.2", @@ -2913,13 +2913,13 @@ } }, "node_modules/@mui/material": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.6.3.tgz", - "integrity": "sha512-2VovFsbCEhic29NYoBF7zFrpH2sEOlKXXDhGjzxmWiI9OnC3SX63hapWunjaVsiRINVnjuMHuW1MOs4UtV8Gfg==", + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.6.4.tgz", + "integrity": "sha512-7TD+u/SExZK2a55w6reX56oPk37gKr/M/XGt156X+m0d9LhzOsW864nkErIX/H8oSkX/6kCimxu1FDsO+gjiVw==", "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/base": "5.0.0-alpha.78", - "@mui/system": "^5.6.3", + "@mui/base": "5.0.0-alpha.79", + "@mui/system": "^5.6.4", "@mui/types": "^7.1.3", "@mui/utils": "^5.6.1", "@types/react-transition-group": "^4.4.4", @@ -3013,9 +3013,9 @@ } }, "node_modules/@mui/system": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.6.3.tgz", - "integrity": "sha512-4SRi52a4ttZ2S4EHEDE8arVNuKqyQLTYUTF80WAZ0tQwnG20qwlBtzcrywCGItmVAMl7RUaYopyWOx3yVPvrmQ==", + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.6.4.tgz", + "integrity": "sha512-7rsWED1wMFMePySJobsBerFZNu7ga580QSi3Zd6sJR8nVj12qD3yIdfvxA70/PxJ/805KbIT0GX7edKI+hpyhA==", "dependencies": { "@babel/runtime": "^7.17.2", "@mui/private-theming": "^5.6.2", @@ -3763,9 +3763,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "17.0.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.30.tgz", - "integrity": "sha512-oNBIZjIqyHYP8VCNAV9uEytXVeXG2oR0w9lgAXro20eugRQfY002qr3CUl6BAe+Yf/z3CRjPdz27Pu6WWtuSRw==" + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", + "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -14437,9 +14437,9 @@ } }, "node_modules/react-dropzone": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.0.1.tgz", - "integrity": "sha512-FyRWrlMmM2+8TkM0aPdRwdZJ5HX3+4O1vWtHecJMFB36N89Bub1sIrk8HyOrjb9hwm1HXGRZ4Q+PW4G/MDFg1Q==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.1.1.tgz", + "integrity": "sha512-JYavQrxU66hBHwDAXCMoHNvhMonKDA0VQ8ouJi8Ouxgz9lmtA4OGVBXgOTCq4vCbwTTDT9synvNUCIpT6zWWow==", "dependencies": { "attr-accept": "^2.2.2", "file-selector": "^0.5.0", @@ -19569,9 +19569,9 @@ "integrity": "sha512-rYEi46+gIzufyYUAoHDnRzkWGxajpD9vVXFQ3g1vbjrBm6P7MBmm+s/fqPa46sxa+8FOUdEuRQKaugo5a4JWpw==" }, "@mui/base": { - "version": "5.0.0-alpha.78", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.78.tgz", - "integrity": "sha512-5L+GNe2M9/tFjQpjK2r837+kzRg/l6D5R9SQbG1wmSWejw5Ei8P+KXIgS/NLNi9g7dUT8bnCyzz9AZKQX1Jsfg==", + "version": "5.0.0-alpha.79", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.79.tgz", + "integrity": "sha512-/lZLF027BkiEjM8MIYoeS/FEhTKf+41ePU9SOijMGrCin1Y0Igucw+IHa1fF8HXD7wDbFKqHuso3J1jMG8wyNw==", "requires": { "@babel/runtime": "^7.17.2", "@emotion/is-prop-valid": "^1.1.2", @@ -19592,13 +19592,13 @@ } }, "@mui/material": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.6.3.tgz", - "integrity": "sha512-2VovFsbCEhic29NYoBF7zFrpH2sEOlKXXDhGjzxmWiI9OnC3SX63hapWunjaVsiRINVnjuMHuW1MOs4UtV8Gfg==", + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.6.4.tgz", + "integrity": "sha512-7TD+u/SExZK2a55w6reX56oPk37gKr/M/XGt156X+m0d9LhzOsW864nkErIX/H8oSkX/6kCimxu1FDsO+gjiVw==", "requires": { "@babel/runtime": "^7.17.2", - "@mui/base": "5.0.0-alpha.78", - "@mui/system": "^5.6.3", + "@mui/base": "5.0.0-alpha.79", + "@mui/system": "^5.6.4", "@mui/types": "^7.1.3", "@mui/utils": "^5.6.1", "@types/react-transition-group": "^4.4.4", @@ -19631,9 +19631,9 @@ } }, "@mui/system": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.6.3.tgz", - "integrity": "sha512-4SRi52a4ttZ2S4EHEDE8arVNuKqyQLTYUTF80WAZ0tQwnG20qwlBtzcrywCGItmVAMl7RUaYopyWOx3yVPvrmQ==", + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.6.4.tgz", + "integrity": "sha512-7rsWED1wMFMePySJobsBerFZNu7ga580QSi3Zd6sJR8nVj12qD3yIdfvxA70/PxJ/805KbIT0GX7edKI+hpyhA==", "requires": { "@babel/runtime": "^7.17.2", "@mui/private-theming": "^5.6.2", @@ -20150,9 +20150,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "@types/node": { - "version": "17.0.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.30.tgz", - "integrity": "sha512-oNBIZjIqyHYP8VCNAV9uEytXVeXG2oR0w9lgAXro20eugRQfY002qr3CUl6BAe+Yf/z3CRjPdz27Pu6WWtuSRw==" + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", + "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" }, "@types/parse-json": { "version": "4.0.0", @@ -27793,9 +27793,9 @@ } }, "react-dropzone": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.0.1.tgz", - "integrity": "sha512-FyRWrlMmM2+8TkM0aPdRwdZJ5HX3+4O1vWtHecJMFB36N89Bub1sIrk8HyOrjb9hwm1HXGRZ4Q+PW4G/MDFg1Q==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.1.1.tgz", + "integrity": "sha512-JYavQrxU66hBHwDAXCMoHNvhMonKDA0VQ8ouJi8Ouxgz9lmtA4OGVBXgOTCq4vCbwTTDT9synvNUCIpT6zWWow==", "requires": { "attr-accept": "^2.2.2", "file-selector": "^0.5.0", diff --git a/interface/package.json b/interface/package.json index 775829526..bc5abb306 100644 --- a/interface/package.json +++ b/interface/package.json @@ -8,10 +8,10 @@ "@emotion/styled": "^11.8.1", "@msgpack/msgpack": "^2.7.2", "@mui/icons-material": "^5.6.2", - "@mui/material": "^5.6.3", + "@mui/material": "^5.6.4", "@table-library/react-table-library": "^3.1.0", "@types/lodash": "^4.14.182", - "@types/node": "^17.0.30", + "@types/node": "^17.0.31", "@types/react": "^17.0.43", "@types/react-dom": "^17.0.14", "@types/react-router-dom": "^5.3.3", @@ -25,7 +25,7 @@ "react": "^17.0.2", "react-app-rewired": "^2.2.1", "react-dom": "^17.0.2", - "react-dropzone": "^14.0.1", + "react-dropzone": "^14.1.1", "react-icons": "^4.3.1", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", diff --git a/mock-api/package-lock.json b/mock-api/package-lock.json index b0a9c3d66..e7dd05f0a 100644 --- a/mock-api/package-lock.json +++ b/mock-api/package-lock.json @@ -14,7 +14,7 @@ "express": "^4.18.1", "express-sse": "^0.5.3", "nodemon": "^2.0.16", - "ws": "^8.5.0" + "ws": "^8.6.0" } }, "node_modules/@msgpack/msgpack": { @@ -1811,9 +1811,9 @@ } }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", + "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "engines": { "node": ">=10.0.0" }, @@ -3169,9 +3169,9 @@ } }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", + "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "requires": {} }, "xdg-basedir": { diff --git a/mock-api/package.json b/mock-api/package.json index b963eb4a8..bdc44b1c3 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -16,6 +16,6 @@ "express": "^4.18.1", "express-sse": "^0.5.3", "nodemon": "^2.0.16", - "ws": "^8.5.0" + "ws": "^8.6.0" } } From 7172ed303e4aa99435092bfa1722a540e6477293 Mon Sep 17 00:00:00 2001 From: Proddy Date: Mon, 2 May 2022 15:11:57 +0200 Subject: [PATCH 3/3] make table headers consistent --- interface/src/framework/security/ManageUsersForm.tsx | 2 ++ interface/src/project/DashboardStatus.tsx | 1 + 2 files changed, 3 insertions(+) diff --git a/interface/src/framework/security/ManageUsersForm.tsx b/interface/src/framework/security/ManageUsersForm.tsx index 0dd1868d2..de533423f 100644 --- a/interface/src/framework/security/ManageUsersForm.tsx +++ b/interface/src/framework/security/ManageUsersForm.tsx @@ -38,11 +38,13 @@ const ManageUsersForm: FC = () => { BaseRow: ` font-size: 14px; color: white; + padding-left: 8px; `, HeaderRow: ` text-transform: uppercase; background-color: black; color: #90CAF9; + font-weight: 500; border-bottom: 1px solid #e0e0e0; `, Row: ` diff --git a/interface/src/project/DashboardStatus.tsx b/interface/src/project/DashboardStatus.tsx index 347e89163..d97f9e0e8 100644 --- a/interface/src/project/DashboardStatus.tsx +++ b/interface/src/project/DashboardStatus.tsx @@ -97,6 +97,7 @@ const DashboardStatus: FC = () => { text-transform: uppercase; background-color: black; color: #90CAF9; + font-weight: 500; border-bottom: 1px solid #e0e0e0; `, Row: `