mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
[Cleanup] Reduce build size by using CDN for CSS and JS
This commit is contained in:
@@ -45,6 +45,12 @@ To create/register a plugin, you have to :
|
||||
#ifndef WEBSERVER_FAVICON
|
||||
#define WEBSERVER_FAVICON
|
||||
#endif
|
||||
#ifndef WEBSERVER_CSS
|
||||
#define WEBSERVER_CSS
|
||||
#endif
|
||||
#ifndef WEBSERVER_INCLUDE_JS
|
||||
#define WEBSERVER_INCLUDE_JS
|
||||
#endif
|
||||
#ifndef WEBSERVER_LOG
|
||||
#define WEBSERVER_LOG
|
||||
#endif
|
||||
@@ -323,6 +329,12 @@ To create/register a plugin, you have to :
|
||||
#ifdef WEBSERVER_FAVICON
|
||||
#undef WEBSERVER_FAVICON
|
||||
#endif
|
||||
#ifdef WEBSERVER_CSS
|
||||
#undef WEBSERVER_CSS
|
||||
#endif
|
||||
#ifdef WEBSERVER_INCLUDE_JS
|
||||
#undef WEBSERVER_INCLUDE_JS
|
||||
#endif
|
||||
#ifdef WEBSERVER_LOG
|
||||
#undef WEBSERVER_LOG
|
||||
#endif
|
||||
@@ -1037,7 +1049,10 @@ To create/register a plugin, you have to :
|
||||
/******************************************************************************\
|
||||
* Libraries dependencies *****************************************************
|
||||
\******************************************************************************/
|
||||
#if defined(USES_P049) || defined(USES_P052) || defined(USES_P053) || defined(USES_P056) || defined(USES_P071) || defined(USES_P075) || defined(USES_P082) || defined(USES_P087) || defined(USES_P094)
|
||||
#if defined(USES_P049) || defined(USES_P052) || defined(USES_P053) || defined(USES_P056) || defined(USES_P071) || defined(USES_P075) || defined(USES_P078) || defined(USES_P082) || defined(USES_P085) || defined(USES_P087) || defined(USES_P094) || defined(USES_P102)
|
||||
#ifndef PLUGIN_USES_SERIAL
|
||||
#define PLUGIN_USES_SERIAL
|
||||
#endif
|
||||
// At least one plugin uses serial.
|
||||
#else
|
||||
// No plugin uses serial, so make sure software serial is not included.
|
||||
@@ -1113,6 +1128,11 @@ To create/register a plugin, you have to :
|
||||
#undef WEBSERVER_TIMINGSTATS
|
||||
#endif
|
||||
|
||||
// Do not include large blobs but fetch them from CDN
|
||||
#ifndef WEBSERVER_USE_CDN_JS_CSS
|
||||
#define WEBSERVER_USE_CDN_JS_CSS
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
#define BUILD_NO_DEBUG
|
||||
#endif
|
||||
@@ -1179,7 +1199,21 @@ To create/register a plugin, you have to :
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
#define BUILD_NO_RAM_TRACKER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Do not include large blobs but fetch them from CDN
|
||||
#ifdef WEBSERVER_USE_CDN_JS_CSS
|
||||
#ifdef WEBSERVER_FAVICON
|
||||
#ifndef WEBSERVER_FAVICON_CDN
|
||||
#define WEBSERVER_FAVICON_CDN
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WEBSERVER_CSS
|
||||
#undef WEBSERVER_CSS
|
||||
#endif
|
||||
#ifdef WEBSERVER_INCLUDE_JS
|
||||
#undef WEBSERVER_INCLUDE_JS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(USES_C002) || defined (USES_C005) || defined(USES_C006) || defined(USES_C014) || defined(USES_P037)
|
||||
|
||||
@@ -4,6 +4,5 @@ void Caches::clearAllCaches()
|
||||
{
|
||||
taskIndexName.clear();
|
||||
taskIndexValueName.clear();
|
||||
|
||||
|
||||
}
|
||||
fileExistsMap.clear();
|
||||
}
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
#include "../../ESPEasy_common.h"
|
||||
#include "../Globals/Plugins.h"
|
||||
|
||||
typedef std::map<String, taskIndex_t> TaskIndexNameMap;
|
||||
typedef std::map<String, byte> TaskIndexValueNameMap;
|
||||
typedef std::map<String, taskIndex_t>TaskIndexNameMap;
|
||||
typedef std::map<String, byte> TaskIndexValueNameMap;
|
||||
typedef std::map<String, bool> FilePresenceMap;
|
||||
|
||||
struct Caches {
|
||||
void clearAllCaches();
|
||||
|
||||
|
||||
TaskIndexNameMap taskIndexName;
|
||||
TaskIndexNameMap taskIndexName;
|
||||
TaskIndexValueNameMap taskIndexValueName;
|
||||
FilePresenceMap fileExistsMap;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -117,7 +117,14 @@ String appendToFile(const String& fname, const uint8_t *data, unsigned int size)
|
||||
}
|
||||
|
||||
bool fileExists(const String& fname) {
|
||||
return ESPEASY_FS.exists(patch_fname(fname));
|
||||
const String patched_fname = patch_fname(fname);
|
||||
auto search = Cache.fileExistsMap.find(patched_fname);
|
||||
if (search != Cache.fileExistsMap.end()) {
|
||||
return search->second;
|
||||
}
|
||||
bool res = ESPEASY_FS.exists(patched_fname);
|
||||
Cache.fileExistsMap[patched_fname] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
fs::File tryOpenFile(const String& fname, const String& mode) {
|
||||
@@ -129,8 +136,11 @@ fs::File tryOpenFile(const String& fname, const String& mode) {
|
||||
|
||||
bool exists = fileExists(fname);
|
||||
|
||||
if ((mode == F("r")) && !exists) {
|
||||
return f;
|
||||
if (!exists) {
|
||||
if (mode == F("r")) {
|
||||
return f;
|
||||
}
|
||||
Cache.fileExistsMap.clear();
|
||||
}
|
||||
f = ESPEASY_FS.open(patch_fname(fname), mode.c_str());
|
||||
STOP_TIMER(TRY_OPEN_FILE);
|
||||
@@ -138,7 +148,9 @@ fs::File tryOpenFile(const String& fname, const String& mode) {
|
||||
}
|
||||
|
||||
bool tryRenameFile(const String& fname_old, const String& fname_new) {
|
||||
Cache.fileExistsMap.clear();
|
||||
if (fileExists(fname_old) && !fileExists(fname_new)) {
|
||||
clearAllCaches();
|
||||
return ESPEASY_FS.rename(patch_fname(fname_old), patch_fname(fname_new));
|
||||
}
|
||||
return false;
|
||||
@@ -148,6 +160,7 @@ bool tryDeleteFile(const String& fname) {
|
||||
if (fname.length() > 0)
|
||||
{
|
||||
bool res = ESPEASY_FS.remove(patch_fname(fname));
|
||||
clearAllCaches();
|
||||
|
||||
// A call to GarbageCollection() will at most erase a single block. (e.g. 8k block size)
|
||||
// A deleted file may have covered more than a single block, so try to clear multiple blocks.
|
||||
@@ -277,6 +290,7 @@ void fileSystemCheck()
|
||||
|
||||
if (ESPEASY_FS.begin())
|
||||
{
|
||||
clearAllCaches();
|
||||
#if defined(ESP8266)
|
||||
fs::FSInfo fs_info;
|
||||
ESPEASY_FS.info(fs_info);
|
||||
|
||||
@@ -218,6 +218,7 @@ String doFormatUserVar(struct EventStruct *event, byte rel_index, bool mustCheck
|
||||
if (valueCount <= rel_index) {
|
||||
isvalid = false;
|
||||
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("No sensor value for TaskIndex: ");
|
||||
log += event->TaskIndex + 1;
|
||||
@@ -227,6 +228,7 @@ String doFormatUserVar(struct EventStruct *event, byte rel_index, bool mustCheck
|
||||
log += getSensorTypeLabel(sensorType);
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include "../WebServer/AccessControl.h"
|
||||
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
HandledWebCommand_result handle_command_from_web(EventValueSource::Enum source, String& webrequest)
|
||||
{
|
||||
if (!clientIPallowed()) { return HandledWebCommand_result::IP_not_allowed; }
|
||||
@@ -57,11 +55,11 @@ HandledWebCommand_result handle_command_from_web(EventValueSource::Enum source,
|
||||
if (sendOK) {
|
||||
if (printToWebJSON) {
|
||||
// Format "OK" to JSON format
|
||||
const int capacity = JSON_OBJECT_SIZE(2);
|
||||
StaticJsonDocument<capacity> root;
|
||||
root[F("return")] = F("OK");
|
||||
root[F("command")] = webrequest;
|
||||
serializeJson(root, printWebString);
|
||||
printWebString = F("{\"return\": \"");
|
||||
printWebString += F("OK");
|
||||
printWebString += F("\",\"command\": \"");
|
||||
printWebString += webrequest;
|
||||
printWebString += F("\"}");
|
||||
} else {
|
||||
printWebString = F("OK");
|
||||
}
|
||||
@@ -71,11 +69,11 @@ HandledWebCommand_result handle_command_from_web(EventValueSource::Enum source,
|
||||
|
||||
if (printToWebJSON) {
|
||||
// Format error to JSON format
|
||||
const int capacity = JSON_OBJECT_SIZE(2);
|
||||
StaticJsonDocument<capacity> root;
|
||||
root[F("return")] = F("Unknown or restricted command");
|
||||
root[F("command")] = webrequest;
|
||||
serializeJson(root, printWebString);
|
||||
printWebString = F("{\"return\": \"");
|
||||
printWebString += F("Unknown or restricted command");
|
||||
printWebString += F("\",\"command\": \"");
|
||||
printWebString += webrequest;
|
||||
printWebString += F("\"}");
|
||||
}
|
||||
return HandledWebCommand_result::Unknown_or_restricted_command;
|
||||
}
|
||||
|
||||
@@ -161,11 +161,15 @@ String formatDomoticzSensorType(struct EventStruct *event) {
|
||||
break;
|
||||
default:
|
||||
{
|
||||
String log = F("Domoticz Controller: Not yet implemented sensor type: ");
|
||||
log += static_cast<byte>(event->sensorType);
|
||||
log += F(" idx: ");
|
||||
log += event->idx;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("Domoticz Controller: Not yet implemented sensor type: ");
|
||||
log += static_cast<byte>(event->sensorType);
|
||||
log += F(" idx: ");
|
||||
log += event->idx;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,13 +182,17 @@ String formatDomoticzSensorType(struct EventStruct *event) {
|
||||
}
|
||||
values.trim();
|
||||
{
|
||||
String log = F(" Domoticz: Sensortype: ");
|
||||
log += static_cast<byte>(event->sensorType);
|
||||
log += F(" idx: ");
|
||||
log += event->idx;
|
||||
log += F(" values: ");
|
||||
log += values;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F(" Domoticz: Sensortype: ");
|
||||
log += static_cast<byte>(event->sensorType);
|
||||
log += F(" idx: ");
|
||||
log += event->idx;
|
||||
log += F(" values: ");
|
||||
log += values;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "../Static/WebStaticData.h"
|
||||
|
||||
#include "../Globals/Cache.h"
|
||||
#include "../Helpers/ESPEasy_Storage.h"
|
||||
#include "../WebServer/HTML_wrappers.h"
|
||||
|
||||
String generate_external_URL(const String& fname) {
|
||||
String url;
|
||||
url.reserve(80 + fname.length());
|
||||
url = F("https://cdn.jsdelivr.net/gh/letscontrolit/ESPEasy@mega-20201130/static/");
|
||||
url += fname;
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
void serve_CSS() {
|
||||
String url = F("esp.css");
|
||||
if (!fileExists(url))
|
||||
{
|
||||
#ifndef WEBSERVER_CSS
|
||||
url = generate_external_URL(F("espeasy_default.css"));
|
||||
#else
|
||||
addHtml(F("<style>"));
|
||||
|
||||
// Send CSS in chunks
|
||||
TXBuffer += DATA_ESPEASY_DEFAULT_MIN_CSS;
|
||||
addHtml(F("</style>"));
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
addHtml(F("<link"));
|
||||
addHtmlAttribute(F("rel"), F("stylesheet"));
|
||||
addHtmlAttribute(F("type"), F("text/css"));
|
||||
addHtmlAttribute(F("href"), url);
|
||||
addHtml('/');
|
||||
addHtml('>');
|
||||
}
|
||||
|
||||
void serve_favicon() {
|
||||
#ifdef WEBSERVER_FAVICON_CDN
|
||||
addHtml(F("<link"));
|
||||
addHtmlAttribute(F("rel"), F("icon"));
|
||||
addHtmlAttribute(F("type"), F("image/x-icon"));
|
||||
addHtmlAttribute(F("href"), generate_external_URL(F("favicon.ico")));
|
||||
addHtml('/');
|
||||
addHtml('>');
|
||||
#endif
|
||||
}
|
||||
|
||||
void serve_JS(JSfiles_e JSfile) {
|
||||
String url;
|
||||
switch (JSfile) {
|
||||
case JSfiles_e::UpdateSensorValuesDevicePage:
|
||||
url = F("update_sensor_values_device_page.js");
|
||||
break;
|
||||
case JSfiles_e::FetchAndParseLog:
|
||||
url = F("fetch_and_parse_log.js");
|
||||
break;
|
||||
case JSfiles_e::SaveRulesFile:
|
||||
url = F("rules_save.js");
|
||||
break;
|
||||
case JSfiles_e::GitHubClipboard:
|
||||
url = F("github_clipboard.js");
|
||||
break;
|
||||
case JSfiles_e::Reboot:
|
||||
url = F("reboot.js");
|
||||
break;
|
||||
case JSfiles_e::Toasting:
|
||||
url = F("toasting.js");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fileExists(url))
|
||||
{
|
||||
#ifndef WEBSERVER_INCLUDE_JS
|
||||
url = generate_external_URL(url);
|
||||
#else
|
||||
html_add_script(true);
|
||||
switch (JSfile) {
|
||||
case JSfiles_e::UpdateSensorValuesDevicePage:
|
||||
#ifdef WEBSERVER_DEVICES
|
||||
TXBuffer += DATA_UPDATE_SENSOR_VALUES_DEVICE_PAGE_JS;
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::FetchAndParseLog:
|
||||
#ifdef WEBSERVER_LOG
|
||||
TXBuffer += DATA_FETCH_AND_PARSE_LOG_JS;
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::SaveRulesFile:
|
||||
#ifdef WEBSERVER_RULES
|
||||
TXBuffer += jsSaveRules;
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::GitHubClipboard:
|
||||
#ifdef WEBSERVER_GITHUB_COPY
|
||||
TXBuffer += DATA_GITHUB_CLIPBOARD_JS;
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::Reboot:
|
||||
TXBuffer += DATA_REBOOT_JS;
|
||||
break;
|
||||
case JSfiles_e::Toasting:
|
||||
TXBuffer += jsToastMessageBegin;
|
||||
// we can push custom messages here in future releases...
|
||||
addHtml(F("Submitted"));
|
||||
TXBuffer += jsToastMessageEnd;
|
||||
break;
|
||||
|
||||
}
|
||||
html_add_script_end();
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
addHtml(F("<script"));
|
||||
addHtml(F(" defer"));
|
||||
addHtmlAttribute(F("src"), url);
|
||||
addHtml('>');
|
||||
html_add_script_end();
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -355,9 +355,13 @@ void handle_devices_CopySubmittedSettings(taskIndex_t taskIndex, pluginID_t task
|
||||
if ((Device[DeviceIndex].Type == DEVICE_TYPE_SERIAL) ||
|
||||
(Device[DeviceIndex].Type == DEVICE_TYPE_SERIAL_PLUS1))
|
||||
{
|
||||
#ifdef PLUGIN_USES_SERIAL
|
||||
serialHelper_webformSave(&TempEvent);
|
||||
}
|
||||
#else
|
||||
addLog(LOG_LEVEL_ERROR, F("PLUGIN_USES_SERIAL not defined"));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
const byte valueCount = getValueCountForTask(taskIndex);
|
||||
|
||||
@@ -394,9 +398,7 @@ void handle_devices_CopySubmittedSettings(taskIndex_t taskIndex, pluginID_t task
|
||||
// ********************************************************************************
|
||||
void handle_devicess_ShowAllTasksTable(byte page)
|
||||
{
|
||||
html_add_script(true);
|
||||
TXBuffer += DATA_UPDATE_SENSOR_VALUES_DEVICE_PAGE_JS;
|
||||
html_add_script_end();
|
||||
serve_JS(JSfiles_e::UpdateSensorValuesDevicePage);
|
||||
html_table_class_multirow();
|
||||
html_TR();
|
||||
html_table_header("", 70);
|
||||
@@ -523,7 +525,12 @@ void handle_devicess_ShowAllTasksTable(byte page)
|
||||
}
|
||||
case DEVICE_TYPE_SERIAL:
|
||||
case DEVICE_TYPE_SERIAL_PLUS1:
|
||||
#ifdef PLUGIN_USES_SERIAL
|
||||
addHtml(serialHelper_getSerialTypeLabel(&TempEvent));
|
||||
#else
|
||||
addHtml(F("PLUGIN_USES_SERIAL not defined"));
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -627,8 +634,12 @@ void handle_devicess_ShowAllTasksTable(byte page)
|
||||
// fallthrough
|
||||
case DEVICE_TYPE_SERIAL:
|
||||
{
|
||||
#ifdef PLUGIN_USES_SERIAL
|
||||
addHtml(serialHelper_getGpioDescription(static_cast<ESPEasySerialPort>(Settings.TaskDevicePort[x]), Settings.TaskDevicePin1[x],
|
||||
Settings.TaskDevicePin2[x], F("<BR>")));
|
||||
#else
|
||||
addHtml(F("PLUGIN_USES_SERIAL not defined"));
|
||||
#endif
|
||||
|
||||
if (showpin3) {
|
||||
html_BR();
|
||||
@@ -893,7 +904,12 @@ void handle_devices_TaskSettingsPage(taskIndex_t taskIndex, byte page)
|
||||
case DEVICE_TYPE_SERIAL:
|
||||
case DEVICE_TYPE_SERIAL_PLUS1:
|
||||
{
|
||||
#ifdef PLUGIN_USES_SERIAL
|
||||
devicePage_show_serial_config(taskIndex);
|
||||
#else
|
||||
addHtml(F("PLUGIN_USES_SERIAL not defined"));
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ bool loadFromFS(boolean spiffs, String path) {
|
||||
|
||||
if (spiffs)
|
||||
{
|
||||
if (!fileExists(path)) {
|
||||
return false;
|
||||
}
|
||||
fs::File dataFile = tryOpenFile(path.c_str(), "r");
|
||||
|
||||
if (!dataFile) {
|
||||
|
||||
@@ -33,9 +33,7 @@ void handle_log() {
|
||||
addCheckBox(F("autoscroll"), true);
|
||||
addHtml(F("<BR></body>"));
|
||||
|
||||
html_add_script(true);
|
||||
TXBuffer += DATA_FETCH_AND_PARSE_LOG_JS;
|
||||
html_add_script_end();
|
||||
serve_JS(JSfiles_e::FetchAndParseLog);
|
||||
|
||||
#else // ifdef WEBSERVER_LOG
|
||||
addHtml(F("Not included in build"));
|
||||
|
||||
@@ -45,12 +45,14 @@ void handle_root() {
|
||||
|
||||
// if index.htm exists on FS serve that one (first check if gziped version exists)
|
||||
if (loadFromFS(true, F("/index.htm.gz"))) { return; }
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
if (loadFromFS(false, F("/index.htm.gz"))) { return; }
|
||||
#endif
|
||||
|
||||
if (loadFromFS(true, F("/index.htm"))) { return; }
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
if (loadFromFS(false, F("/index.htm"))) { return; }
|
||||
#endif
|
||||
|
||||
TXBuffer.startStream();
|
||||
String sCommand = web_server.arg(F("cmd"));
|
||||
|
||||
@@ -95,9 +95,7 @@ void handle_rules() {
|
||||
addButton(fileName, F("Download to file"));
|
||||
html_end_table();
|
||||
|
||||
html_add_script(true);
|
||||
TXBuffer += jsSaveRules;
|
||||
html_add_script_end();
|
||||
serve_JS(JSfiles_e::SaveRulesFile);
|
||||
|
||||
sendHeadandTail_stdtemplate(true);
|
||||
TXBuffer.endStream();
|
||||
|
||||
@@ -251,9 +251,8 @@ void handle_sysinfo() {
|
||||
addCopyButton(F("copyText"), F("\\n"), F("Copy info to clipboard"));
|
||||
|
||||
TXBuffer += githublogo;
|
||||
html_add_script(false);
|
||||
TXBuffer += DATA_GITHUB_CLIPBOARD_JS;
|
||||
html_add_script_end();
|
||||
serve_JS(JSfiles_e::GitHubClipboard);
|
||||
|
||||
# else // ifdef WEBSERVER_GITHUB_COPY
|
||||
addFormHeader(F("System Info"));
|
||||
|
||||
@@ -682,7 +681,7 @@ void handle_sysinfo_Storage() {
|
||||
html += F(" kB free)");
|
||||
addHtml(html);
|
||||
}
|
||||
|
||||
#ifndef LIMIT_BUILD_SIZE
|
||||
addRowLabel(F("Page size"));
|
||||
addHtml(String(SpiffsPagesize()));
|
||||
|
||||
@@ -704,6 +703,7 @@ void handle_sysinfo_Storage() {
|
||||
|
||||
# endif // if defined(ESP8266)
|
||||
}
|
||||
#endif
|
||||
|
||||
# ifndef BUILD_MINIMAL_OTA
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../WebServer/AccessControl.h"
|
||||
#include "../WebServer/HTML_wrappers.h"
|
||||
|
||||
#include "../Globals/Cache.h"
|
||||
#include "../Helpers/ESPEasy_Storage.h"
|
||||
|
||||
#include "../../ESPEasy-Globals.h"
|
||||
@@ -14,7 +15,8 @@
|
||||
// ********************************************************************************
|
||||
// Web Interface upload page
|
||||
// ********************************************************************************
|
||||
byte uploadResult = 0;
|
||||
uploadResult_e uploadResult = uploadResult_e::UploadStarted;
|
||||
|
||||
void handle_upload() {
|
||||
if (!isLoggedIn()) { return; }
|
||||
navMenuIndex = MENU_INDEX_TOOLS;
|
||||
@@ -43,22 +45,22 @@ void handle_upload_post() {
|
||||
TXBuffer.startStream();
|
||||
sendHeadandTail_stdtemplate();
|
||||
|
||||
|
||||
if (uploadResult == 1)
|
||||
{
|
||||
addHtml(F("Upload OK!<BR>You may need to reboot to apply all settings..."));
|
||||
LoadSettings();
|
||||
switch (uploadResult) {
|
||||
case uploadResult_e::Success:
|
||||
addHtml(F("Upload OK!<BR>You may need to reboot to apply all settings..."));
|
||||
clearAllCaches();
|
||||
LoadSettings();
|
||||
break;
|
||||
case uploadResult_e::InvalidFile:
|
||||
addHtml(F("<font color=\"red\">Upload file invalid!</font>"));
|
||||
break;
|
||||
case uploadResult_e::NoFilename:
|
||||
addHtml(F("<font color=\"red\">No filename!</font>"));
|
||||
break;
|
||||
case uploadResult_e::UploadStarted:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uploadResult == 2) {
|
||||
addHtml(F("<font color=\"red\">Upload file invalid!</font>"));
|
||||
}
|
||||
|
||||
if (uploadResult == 3) {
|
||||
addHtml(F("<font color=\"red\">No filename!</font>"));
|
||||
}
|
||||
|
||||
|
||||
addHtml(F("Upload finished"));
|
||||
sendHeadandTail_stdtemplate(true);
|
||||
TXBuffer.endStream();
|
||||
@@ -71,7 +73,7 @@ void handle_upload_json() {
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
checkRAM(F("handle_upload_post"));
|
||||
#endif
|
||||
uint8_t result = uploadResult;
|
||||
uint8_t result = static_cast<int>(uploadResult);
|
||||
|
||||
if (!isLoggedIn()) { result = 255; }
|
||||
|
||||
@@ -102,7 +104,7 @@ void handleFileUpload() {
|
||||
|
||||
if (upload.filename.c_str()[0] == 0)
|
||||
{
|
||||
uploadResult = 3;
|
||||
uploadResult = uploadResult_e::NoFilename;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,7 +116,7 @@ void handleFileUpload() {
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
valid = false;
|
||||
uploadResult = 0;
|
||||
uploadResult = uploadResult_e::UploadStarted;
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_WRITE)
|
||||
{
|
||||
@@ -180,10 +182,10 @@ void handleFileUpload() {
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
uploadResult = 1;
|
||||
uploadResult = uploadResult_e::Success;
|
||||
}
|
||||
else {
|
||||
uploadResult = 2;
|
||||
uploadResult = uploadResult_e::InvalidFile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,16 @@
|
||||
// ********************************************************************************
|
||||
// Web Interface upload page
|
||||
// ********************************************************************************
|
||||
extern byte uploadResult;
|
||||
enum class uploadResult_e {
|
||||
// Int values are used in JSON, so keep them numbered like this.
|
||||
UploadStarted = 0,
|
||||
Success = 1,
|
||||
InvalidFile = 2,
|
||||
NoFilename = 3
|
||||
};
|
||||
|
||||
extern uploadResult_e uploadResult;
|
||||
|
||||
void handle_upload();
|
||||
|
||||
// ********************************************************************************
|
||||
|
||||
@@ -144,9 +144,7 @@ void sendHeadandTail(const String& tmplName, boolean Tail, boolean rebooting) {
|
||||
|
||||
if (shouldReboot) {
|
||||
// we only add this here as a seperate chunk to prevent using too much memory at once
|
||||
html_add_script(false);
|
||||
TXBuffer += DATA_REBOOT_JS;
|
||||
html_add_script_end();
|
||||
serve_JS(JSfiles_e::Reboot);
|
||||
}
|
||||
STOP_TIMER(HANDLE_SERVING_WEBPAGE);
|
||||
}
|
||||
@@ -159,6 +157,7 @@ void sendHeadandTail_stdtemplate(boolean Tail, boolean rebooting) {
|
||||
addHtmlError(F("Warning: Connected via AP"));
|
||||
}
|
||||
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
const int nrArgs = web_server.args();
|
||||
|
||||
@@ -176,6 +175,7 @@ void sendHeadandTail_stdtemplate(boolean Tail, boolean rebooting) {
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,11 +559,7 @@ void getWebPageTemplateVar(const String& varName)
|
||||
|
||||
addHtml(F("<a "));
|
||||
|
||||
if (i == navMenuIndex) {
|
||||
addHtmlAttribute(F("class"), F("menu active"));
|
||||
} else {
|
||||
addHtmlAttribute(F("class"), F("menu"));
|
||||
}
|
||||
addHtmlAttribute(F("class"), (i == navMenuIndex) ? F("menu active") : F("menu"));
|
||||
addHtmlAttribute(F("href"), getGpMenuURL(i));
|
||||
addHtml('>');
|
||||
addHtml(getGpMenuIcon(i));
|
||||
@@ -585,25 +581,17 @@ void getWebPageTemplateVar(const String& varName)
|
||||
|
||||
else if (varName == F("css"))
|
||||
{
|
||||
if (fileExists(F("esp.css"))) // now css is written in writeDefaultCSS() to FS and always present
|
||||
// if (0) //TODO
|
||||
{
|
||||
addHtml(F("<link rel=\"stylesheet\" type=\"text/css\" href=\"esp.css\">"));
|
||||
}
|
||||
else
|
||||
{
|
||||
addHtml(F("<style>"));
|
||||
|
||||
// Send CSS per chunk to avoid sending either too short or too large strings.
|
||||
TXBuffer += DATA_ESPEASY_DEFAULT_MIN_CSS;
|
||||
addHtml(F("</style>"));
|
||||
}
|
||||
serve_favicon();
|
||||
serve_CSS();
|
||||
}
|
||||
|
||||
|
||||
else if (varName == F("js"))
|
||||
{
|
||||
html_add_autosubmit_form();
|
||||
|
||||
// FIXME TD-er: Can only call this after tag has been set for the file.
|
||||
//serve_JS(JSfiles_e::Toasting);
|
||||
html_add_script(false);
|
||||
TXBuffer += jsToastMessageBegin;
|
||||
|
||||
@@ -626,11 +614,13 @@ void getWebPageTemplateVar(const String& varName)
|
||||
|
||||
else
|
||||
{
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("Templ: Unknown Var : ");
|
||||
log += varName;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
#endif
|
||||
|
||||
// no return string - eat var name
|
||||
}
|
||||
|
||||
+545
-424
@@ -1,424 +1,545 @@
|
||||
h1,h6{
|
||||
color:#07D
|
||||
}
|
||||
.checkmark:after,.dotmark:after{
|
||||
content:''
|
||||
}
|
||||
.button,.menu{
|
||||
text-decoration:none
|
||||
}
|
||||
.div_l,.menu{
|
||||
float:left
|
||||
}
|
||||
*{
|
||||
box-sizing:border-box;
|
||||
font-family:sans-serif;
|
||||
font-size:12pt;
|
||||
margin:0;
|
||||
padding:0
|
||||
}
|
||||
h1{
|
||||
font-size:16pt;
|
||||
font-weight:700;
|
||||
margin:8px 0
|
||||
}
|
||||
h2,h3{
|
||||
font-size:12pt;
|
||||
font-weight:700
|
||||
}
|
||||
h2{
|
||||
background-color:#444;
|
||||
color:#FFF;
|
||||
margin:0 -4px;
|
||||
padding:6px
|
||||
}
|
||||
h3{
|
||||
background-color:#EEE;
|
||||
color:#444;
|
||||
margin:16px -4px 0;
|
||||
padding:4px
|
||||
}
|
||||
h6{
|
||||
font-size:10pt
|
||||
}
|
||||
code,kbd,pre,samp,tt,xmp{
|
||||
font-family:monospace,monospace;
|
||||
font-size:1em
|
||||
}
|
||||
.button{
|
||||
background-color:#07D;
|
||||
border:none;
|
||||
border-radius:4px;
|
||||
color:#FFF;
|
||||
margin:4px;
|
||||
padding:4px 16px
|
||||
}
|
||||
.button.link.wide{
|
||||
display:inline-block;
|
||||
text-align:center;
|
||||
width:100%
|
||||
}
|
||||
.button.link.red{
|
||||
background-color:red
|
||||
}
|
||||
.button.help{
|
||||
border-color:gray;
|
||||
border-radius:50%;
|
||||
border-style:solid;
|
||||
border-width:1px;
|
||||
padding:2px 4px
|
||||
}
|
||||
.checkmark,input,select,textarea{
|
||||
border-color:gray;
|
||||
border-radius:4px;
|
||||
border-style:solid;
|
||||
border-width:1px
|
||||
}
|
||||
.button:hover{
|
||||
background:#369
|
||||
}
|
||||
input:hover,select:hover{
|
||||
background-color:#ccc
|
||||
}
|
||||
input,select,textarea{
|
||||
background-color:#eee;
|
||||
margin:4px;
|
||||
padding:4px 8px
|
||||
}
|
||||
input.wide, select.wide{
|
||||
max-width:500px;
|
||||
width:80%
|
||||
}
|
||||
.widenumber{
|
||||
max-width:500px;
|
||||
width:7em
|
||||
}
|
||||
.container,.container2{
|
||||
font-size:12pt;
|
||||
padding-left:35px;
|
||||
cursor:pointer
|
||||
}
|
||||
.container{
|
||||
-moz-user-select:none;
|
||||
-ms-user-select:none;
|
||||
-webkit-user-select:none;
|
||||
display:block;
|
||||
margin-left:4px;
|
||||
margin-top:0;
|
||||
position:relative;
|
||||
user-select:none
|
||||
}
|
||||
.container input{
|
||||
cursor:pointer;
|
||||
opacity:0;
|
||||
position:absolute
|
||||
}
|
||||
.checkmark.disabled{
|
||||
background-color:grey
|
||||
}
|
||||
.checkmark{
|
||||
background-color:#eee;
|
||||
height:25px;
|
||||
left:0;
|
||||
position:absolute;
|
||||
top:0;
|
||||
width:25px
|
||||
}
|
||||
.container:hover input~.checkmark{
|
||||
background-color:#ccc
|
||||
}
|
||||
.container input:checked~.checkmark{
|
||||
background-color:#07D
|
||||
}
|
||||
.checkmark:after{
|
||||
display:none;
|
||||
position:absolute
|
||||
}
|
||||
.container input:checked~.checkmark:after,.container2{
|
||||
display:block
|
||||
}
|
||||
.container .checkmark:after{
|
||||
-ms-transform:rotate(45deg);
|
||||
-webkit-transform:rotate(45deg);
|
||||
border:solid #fff;
|
||||
border-width:0 3px 3px 0;
|
||||
height:10px;
|
||||
left:7px;
|
||||
top:3px;
|
||||
transform:rotate(45deg);
|
||||
width:5px
|
||||
}
|
||||
#toastmessage,.dotmark{
|
||||
border-width:1px;
|
||||
border-color:gray;
|
||||
border-style:solid
|
||||
}
|
||||
.container2{
|
||||
-moz-user-select:none;
|
||||
-ms-user-select:none;
|
||||
-webkit-user-select:none;
|
||||
margin-bottom:20px;
|
||||
margin-left:9px;
|
||||
position:relative;
|
||||
user-select:none
|
||||
}
|
||||
.container2 input{
|
||||
cursor:pointer;
|
||||
opacity:0;
|
||||
position:absolute
|
||||
}
|
||||
.dotmark{
|
||||
background-color:#eee;
|
||||
border-radius:50%;
|
||||
height:26px;
|
||||
left:0;
|
||||
position:absolute;
|
||||
top:0;
|
||||
width:26px
|
||||
}
|
||||
.container2:hover input~.dotmark{
|
||||
background-color:#ccc
|
||||
}
|
||||
.container2 input:checked~.dotmark{
|
||||
background-color:#07D
|
||||
}
|
||||
.dotmark:after{
|
||||
display:none;
|
||||
position:absolute
|
||||
}
|
||||
.container2 input:checked~.dotmark:after{
|
||||
display:block
|
||||
}
|
||||
.container2 .dotmark:after{
|
||||
background:#fff;
|
||||
border-radius:50%;
|
||||
height:8px;
|
||||
left:8px;
|
||||
top:8px;
|
||||
width:8px
|
||||
}
|
||||
.logviewer,textarea{
|
||||
font-family:'Lucida Console',Monaco,monospace;
|
||||
max-width:1000px;
|
||||
padding:4px 8px;
|
||||
width:80%
|
||||
}
|
||||
#toastmessage{
|
||||
background-color:#07D;
|
||||
border-radius:4px;
|
||||
bottom:30%;
|
||||
color:#fff;
|
||||
font-size:17px;
|
||||
left:282px;
|
||||
margin-left:-125px;
|
||||
min-width:250px;
|
||||
padding:16px;
|
||||
position:fixed;
|
||||
text-align:center;
|
||||
visibility:hidden;
|
||||
z-index:1
|
||||
}
|
||||
#toastmessage.show{
|
||||
-webkit-animation:fadein .5s,fadeout .5s 2.5s;
|
||||
animation:fadein .5s,fadeout .5s 2.5s;
|
||||
visibility:visible
|
||||
}
|
||||
@-webkit-keyframes fadein{
|
||||
from{
|
||||
bottom:20%;
|
||||
opacity:0
|
||||
}
|
||||
to{
|
||||
bottom:30%;
|
||||
opacity:.9
|
||||
}
|
||||
}
|
||||
@keyframes fadein{
|
||||
from{
|
||||
bottom:20%;
|
||||
opacity:0
|
||||
}
|
||||
to{
|
||||
bottom:30%;
|
||||
opacity:.9
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fadeout{
|
||||
from{
|
||||
bottom:30%;
|
||||
opacity:.9
|
||||
}
|
||||
to{
|
||||
bottom:0;
|
||||
opacity:0
|
||||
}
|
||||
}
|
||||
@keyframes fadeout{
|
||||
from{
|
||||
bottom:30%;
|
||||
opacity:.9
|
||||
}
|
||||
to{
|
||||
bottom:0;
|
||||
opacity:0
|
||||
}
|
||||
}
|
||||
.level_0{
|
||||
color:#F1F1F1
|
||||
}
|
||||
.level_1{
|
||||
color:#FCFF95
|
||||
}
|
||||
.level_2{
|
||||
color:#9DCEFE
|
||||
}
|
||||
.level_3{
|
||||
color:#A4FC79
|
||||
}
|
||||
.level_4{
|
||||
color:#F2AB39
|
||||
}
|
||||
.level_9{
|
||||
color:#F50
|
||||
}
|
||||
.logviewer{
|
||||
background-color:#272727;
|
||||
border-color:gray;
|
||||
border-style:solid;
|
||||
color:#F1F1F1;
|
||||
height:530px;
|
||||
overflow:auto
|
||||
}
|
||||
textarea:hover{
|
||||
background-color:#ccc
|
||||
}
|
||||
table.multirow th,table.normal th{
|
||||
background-color:#444;
|
||||
border-color:#888;
|
||||
color:#FFF;
|
||||
font-weight:700;
|
||||
padding:6px;
|
||||
align-content: center;
|
||||
text-align:center
|
||||
}
|
||||
table.multirow,table.normal{
|
||||
border-collapse:collapse;
|
||||
color:#000;
|
||||
min-width:420px;
|
||||
width:100%
|
||||
}
|
||||
table.multirow tr,table.normal td,table.normal tr{
|
||||
padding:4px
|
||||
}
|
||||
table.normal td{
|
||||
height:30px
|
||||
}
|
||||
table.multirow td{
|
||||
height:30px;
|
||||
padding:4px;
|
||||
text-align:center
|
||||
}
|
||||
table.multirow tr:nth-child(even){
|
||||
background-color:#DEE6FF
|
||||
}
|
||||
.highlight td{
|
||||
background-color:#dbff0075
|
||||
}
|
||||
.apheader,.headermenu{
|
||||
background-color:#F8F8F8;
|
||||
padding:8px 12px
|
||||
}
|
||||
.note{
|
||||
color:#444;
|
||||
font-style:italic
|
||||
}
|
||||
.headermenu{
|
||||
border-bottom:1px solid #DDD;
|
||||
height:90px;
|
||||
left:0;
|
||||
position:fixed;
|
||||
right:0;
|
||||
top:0;
|
||||
z-index:1
|
||||
}
|
||||
.bodymenu{
|
||||
margin-top:96px
|
||||
}
|
||||
.menubar{
|
||||
position:inherit;
|
||||
top:55px
|
||||
}
|
||||
.menu{
|
||||
border:solid transparent;
|
||||
border-radius:4px 4px 0 0;
|
||||
border-width:4px 1px 1px;
|
||||
color:#444;
|
||||
padding:4px 16px 8px;
|
||||
white-space:nowrap
|
||||
}
|
||||
.menu.active{
|
||||
background-color:#FFF;
|
||||
border-color:#07D #DDD #FFF;
|
||||
color:#000
|
||||
}
|
||||
.menu:hover{
|
||||
background:#DEF;
|
||||
color:#000
|
||||
}
|
||||
.menu_button{
|
||||
display:none
|
||||
}
|
||||
.on{
|
||||
color:green
|
||||
}
|
||||
.off{
|
||||
color:red
|
||||
}
|
||||
.div_r{
|
||||
background-color:#080;
|
||||
border-radius:4px;
|
||||
color:#fff;
|
||||
float:right;
|
||||
margin:2px;
|
||||
padding:1px 10px
|
||||
}
|
||||
.alert,.warning{
|
||||
margin-bottom:15px;
|
||||
padding:20px;
|
||||
color:#fff
|
||||
}
|
||||
.div_br{
|
||||
clear:both
|
||||
}
|
||||
.alert{
|
||||
background-color:#f44336
|
||||
}
|
||||
.warning{
|
||||
background-color:#ffca17
|
||||
}
|
||||
.closebtn{
|
||||
color:#fff;
|
||||
cursor:pointer;
|
||||
float:right;
|
||||
font-size:22px;
|
||||
font-weight:700;
|
||||
line-height:20px;
|
||||
margin-left:15px;
|
||||
transition:.3s
|
||||
}
|
||||
.closebtn:hover{
|
||||
color:#000
|
||||
}
|
||||
section{
|
||||
overflow-x:auto;
|
||||
width:100%
|
||||
}
|
||||
@media screen and (max-width:960px){
|
||||
.showmenulabel{
|
||||
display:none
|
||||
}
|
||||
.menu{
|
||||
max-width:11vw;
|
||||
max-width:48px
|
||||
}
|
||||
}
|
||||
.closebtn,
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
h1,
|
||||
h6 {
|
||||
color: #07D
|
||||
}
|
||||
|
||||
.checkmark:after,
|
||||
.dotmark:after {
|
||||
content: ''
|
||||
}
|
||||
|
||||
.button,
|
||||
.menu {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
.div_l,
|
||||
.menu {
|
||||
float: left
|
||||
}
|
||||
|
||||
.closebtn,
|
||||
.div_r {
|
||||
float: right;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
font-size: 12pt;
|
||||
margin: 0;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 16pt;
|
||||
margin: 8px 0
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
font-size: 12pt
|
||||
}
|
||||
|
||||
h2 {
|
||||
background-color: #444;
|
||||
color: #FFF;
|
||||
margin: 0 -4px;
|
||||
padding: 6px
|
||||
}
|
||||
|
||||
h3 {
|
||||
background-color: #EEE;
|
||||
color: #444;
|
||||
margin: 16px -4px 0;
|
||||
padding: 4px
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 10pt
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp,
|
||||
tt,
|
||||
xmp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #07D;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: #FFF;
|
||||
margin: 4px;
|
||||
padding: 4px 16px
|
||||
}
|
||||
|
||||
.button.help,
|
||||
.checkmark,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
border-color: gray;
|
||||
border-style: solid;
|
||||
border-width: 1px
|
||||
}
|
||||
|
||||
.button.link.wide {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.button.link.red {
|
||||
background-color: red
|
||||
}
|
||||
|
||||
.button.help {
|
||||
border-radius: 50%;
|
||||
padding: 2px 4px
|
||||
}
|
||||
|
||||
.checkmark,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
border-radius: 4px
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: #369
|
||||
}
|
||||
|
||||
input:hover,
|
||||
select:hover {
|
||||
background-color: #ccc
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
background-color: #eee;
|
||||
margin: 4px;
|
||||
padding: 4px 8px
|
||||
}
|
||||
|
||||
input.wide,
|
||||
select.wide {
|
||||
max-width: 500px;
|
||||
width: 80%
|
||||
}
|
||||
|
||||
.widenumber {
|
||||
max-width: 500px;
|
||||
width: 100px
|
||||
}
|
||||
|
||||
.container,
|
||||
.container2 {
|
||||
font-size: 12pt;
|
||||
padding-left: 35px;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.container {
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
display: block;
|
||||
margin-left: 4px;
|
||||
margin-top: 0;
|
||||
position: relative;
|
||||
user-select: none
|
||||
}
|
||||
|
||||
.container input {
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
position: absolute
|
||||
}
|
||||
|
||||
.checkmark.disabled {
|
||||
background-color: grey
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
background-color: #eee;
|
||||
height: 25px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 25px
|
||||
}
|
||||
|
||||
.container:hover input~.checkmark {
|
||||
background-color: #ccc
|
||||
}
|
||||
|
||||
.container input:checked~.checkmark {
|
||||
background-color: #07D
|
||||
}
|
||||
|
||||
.checkmark:after {
|
||||
display: none;
|
||||
position: absolute
|
||||
}
|
||||
|
||||
.container input:checked~.checkmark:after,
|
||||
.container2 {
|
||||
display: block
|
||||
}
|
||||
|
||||
.container .checkmark:after {
|
||||
-ms-transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
border: solid #fff;
|
||||
border-width: 0 3px 3px 0;
|
||||
height: 10px;
|
||||
left: 7px;
|
||||
top: 3px;
|
||||
transform: rotate(45deg);
|
||||
width: 5px
|
||||
}
|
||||
|
||||
#toastmessage,
|
||||
.dotmark,
|
||||
.logviewer {
|
||||
border-color: gray;
|
||||
border-style: solid
|
||||
}
|
||||
|
||||
#toastmessage,
|
||||
.dotmark {
|
||||
border-width: 1px
|
||||
}
|
||||
|
||||
.container2 {
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
margin-bottom: 20px;
|
||||
margin-left: 9px;
|
||||
position: relative;
|
||||
user-select: none
|
||||
}
|
||||
|
||||
.container2 input {
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
position: absolute
|
||||
}
|
||||
|
||||
.dotmark {
|
||||
background-color: #eee;
|
||||
border-radius: 50%;
|
||||
height: 26px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 26px
|
||||
}
|
||||
|
||||
.container2:hover input~.dotmark {
|
||||
background-color: #ccc
|
||||
}
|
||||
|
||||
.container2 input:checked~.dotmark {
|
||||
background-color: #07D
|
||||
}
|
||||
|
||||
.dotmark:after {
|
||||
display: none;
|
||||
position: absolute
|
||||
}
|
||||
|
||||
.container2 input:checked~.dotmark:after {
|
||||
display: block
|
||||
}
|
||||
|
||||
.container2 .dotmark:after {
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
height: 8px;
|
||||
left: 8px;
|
||||
top: 8px;
|
||||
width: 8px
|
||||
}
|
||||
|
||||
.logviewer,
|
||||
textarea {
|
||||
font-family: 'Lucida Console', Monaco, monospace;
|
||||
max-width: 1000px;
|
||||
padding: 4px 8px;
|
||||
width: 80%
|
||||
}
|
||||
|
||||
#toastmessage {
|
||||
background-color: #07D;
|
||||
border-radius: 4px;
|
||||
bottom: 30%;
|
||||
color: #fff;
|
||||
font-size: 17px;
|
||||
left: 282px;
|
||||
margin-left: -125px;
|
||||
min-width: 250px;
|
||||
padding: 16px;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
visibility: hidden;
|
||||
z-index: 1
|
||||
}
|
||||
|
||||
#toastmessage.show {
|
||||
-webkit-animation: fadein .5s, fadeout .5s 2.5s;
|
||||
animation: fadein .5s, fadeout .5s 2.5s;
|
||||
visibility: visible
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadein {
|
||||
from {
|
||||
bottom: 20%;
|
||||
opacity: 0
|
||||
}
|
||||
to {
|
||||
bottom: 30%;
|
||||
opacity: .9
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from {
|
||||
bottom: 20%;
|
||||
opacity: 0
|
||||
}
|
||||
to {
|
||||
bottom: 30%;
|
||||
opacity: .9
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeout {
|
||||
from {
|
||||
bottom: 30%;
|
||||
opacity: .9
|
||||
}
|
||||
to {
|
||||
bottom: 0;
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeout {
|
||||
from {
|
||||
bottom: 30%;
|
||||
opacity: .9
|
||||
}
|
||||
to {
|
||||
bottom: 0;
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
|
||||
.level_0 {
|
||||
color: #F1F1F1
|
||||
}
|
||||
|
||||
.level_1 {
|
||||
color: #FCFF95
|
||||
}
|
||||
|
||||
.level_2 {
|
||||
color: #9DCEFE
|
||||
}
|
||||
|
||||
.level_3 {
|
||||
color: #A4FC79
|
||||
}
|
||||
|
||||
.level_4 {
|
||||
color: #F2AB39
|
||||
}
|
||||
|
||||
.level_9 {
|
||||
color: #F50
|
||||
}
|
||||
|
||||
.logviewer {
|
||||
background-color: #272727;
|
||||
color: #F1F1F1;
|
||||
height: 530px;
|
||||
overflow: auto
|
||||
}
|
||||
|
||||
textarea:hover {
|
||||
background-color: #ccc
|
||||
}
|
||||
|
||||
table.multirow th,
|
||||
table.normal th {
|
||||
background-color: #444;
|
||||
border-color: #888;
|
||||
color: #FFF;
|
||||
font-weight: 700;
|
||||
padding: 6px;
|
||||
align-content: center;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
table.multirow,
|
||||
table.normal {
|
||||
border-collapse: collapse;
|
||||
color: #000;
|
||||
min-width: 420px;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
table.multirow tr,
|
||||
table.normal td,
|
||||
table.normal tr {
|
||||
padding: 4px
|
||||
}
|
||||
|
||||
table.normal td {
|
||||
height: 30px
|
||||
}
|
||||
|
||||
table.multirow td {
|
||||
height: 30px;
|
||||
padding: 4px;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
table.multirow tr:nth-child(even) {
|
||||
background-color: #DEE6FF
|
||||
}
|
||||
|
||||
.highlight td {
|
||||
background-color: #dbff0075
|
||||
}
|
||||
|
||||
.apheader,
|
||||
.headermenu {
|
||||
background-color: #F8F8F8;
|
||||
padding: 8px 12px
|
||||
}
|
||||
|
||||
.note {
|
||||
color: #444;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.headermenu {
|
||||
border-bottom: 1px solid #DDD;
|
||||
height: 90px;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 1
|
||||
}
|
||||
|
||||
.bodymenu {
|
||||
margin-top: 96px
|
||||
}
|
||||
|
||||
.menubar {
|
||||
position: inherit;
|
||||
top: 55px
|
||||
}
|
||||
|
||||
.menu {
|
||||
border: solid transparent;
|
||||
border-radius: 4px 4px 0 0;
|
||||
border-width: 4px 1px 1px;
|
||||
color: #444;
|
||||
padding: 4px 16px 8px;
|
||||
white-space: nowrap
|
||||
}
|
||||
|
||||
.menu.active {
|
||||
background-color: #FFF;
|
||||
border-color: #07D #DDD #FFF;
|
||||
color: #000
|
||||
}
|
||||
|
||||
.menu:hover {
|
||||
background: #DEF;
|
||||
color: #000
|
||||
}
|
||||
|
||||
.menu_button {
|
||||
display: none
|
||||
}
|
||||
|
||||
.on {
|
||||
color: green
|
||||
}
|
||||
|
||||
.off {
|
||||
color: red
|
||||
}
|
||||
|
||||
.div_r {
|
||||
background-color: #080;
|
||||
border-radius: 4px;
|
||||
margin: 2px;
|
||||
padding: 1px 10px
|
||||
}
|
||||
|
||||
.alert,
|
||||
.warning {
|
||||
margin-bottom: 15px;
|
||||
padding: 20px;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.div_br {
|
||||
clear: both
|
||||
}
|
||||
|
||||
.alert {
|
||||
background-color: #f44336
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: #ffca17
|
||||
}
|
||||
|
||||
.closebtn {
|
||||
cursor: pointer;
|
||||
font-size: 22px;
|
||||
line-height: 20px;
|
||||
margin-left: 15px;
|
||||
transition: .3s
|
||||
}
|
||||
|
||||
.closebtn:hover {
|
||||
color: #000
|
||||
}
|
||||
|
||||
section {
|
||||
overflow-x: auto;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
.showmenulabel {
|
||||
display: none
|
||||
}
|
||||
.menu {
|
||||
max-width: 11vw;
|
||||
max-width: 48px
|
||||
}
|
||||
}
|
||||
@@ -117,5 +117,4 @@ function loopDeLoop(timeForNext, activeRequests) {
|
||||
};
|
||||
check = 1;
|
||||
}, timeForNext);
|
||||
}
|
||||
|
||||
}
|
||||
+16
-22
@@ -1,33 +1,27 @@
|
||||
i = document.getElementById('rbtmsg');
|
||||
i.innerHTML = "Please reboot: <input id='reboot' class='button link' value='Reboot' type='submit' onclick='r()'>";
|
||||
var x = new XMLHttpRequest();
|
||||
i = document.getElementById("rbtmsg"),
|
||||
i.innerHTML = "Please reboot: <input id='reboot' class='button link' value='Reboot' type='submit' onclick='r()'>";
|
||||
var x = new XMLHttpRequest;
|
||||
|
||||
//done
|
||||
function d() {
|
||||
i.innerHTML = '';
|
||||
clearTimeout(t);
|
||||
i.innerHTML = "",
|
||||
clearTimeout(t)
|
||||
}
|
||||
|
||||
|
||||
//keep requesting mainpage until no more errors
|
||||
function c() {
|
||||
i.innerHTML += '.';
|
||||
x.onload = d;
|
||||
x.open('GET', window.location.origin);
|
||||
x.send();
|
||||
i.innerHTML += ".",
|
||||
x.onload = d,
|
||||
x.open("GET", window.location.origin),
|
||||
x.send()
|
||||
}
|
||||
|
||||
//rebooting
|
||||
function b() {
|
||||
i.innerHTML = 'Rebooting..';
|
||||
t = setInterval(c, 2000);
|
||||
i.innerHTML = "Rebooting..",
|
||||
t = setInterval(c, 2e3)
|
||||
}
|
||||
|
||||
|
||||
//request reboot
|
||||
function r() {
|
||||
i.innerHTML += ' (requesting)';
|
||||
x.onload = b;
|
||||
x.open('GET', window.location.origin + '/?cmd=reboot');
|
||||
x.send();
|
||||
}
|
||||
i.innerHTML += " (requesting)",
|
||||
x.onload = b,
|
||||
x.open("GET", window.location.origin + "/?cmd=reboot"),
|
||||
x.send()
|
||||
}
|
||||
+33
-35
@@ -1,36 +1,34 @@
|
||||
function saveRulesFile() {
|
||||
let button = document.getElementById('save_button');
|
||||
let size = document.getElementById('size');
|
||||
let ruleTextNew = document.getElementById('rules').value;
|
||||
ruleTextNew = ruleTextNew.replace(/\\r?\\n/g, '\\r\\n');
|
||||
let ruleNumber = document.getElementById('set').value;
|
||||
let ruleTextFileData = new File([ruleTextNew], 'rules' + ruleNumber + '.txt', {
|
||||
type: 'text/plain'
|
||||
});
|
||||
let formData = new FormData();
|
||||
formData.append('file', ruleTextFileData);
|
||||
formData.append('enctype', 'multipart/form-data');
|
||||
let url = '/rules' + ruleNumber + '.txt?callback=' + Date.now();
|
||||
fetch(url).then(res => res.text()).then((ruleTextOld) => {
|
||||
if (ruleTextNew === ruleTextOld) {
|
||||
console.log('nothing to save...');
|
||||
} else {
|
||||
let url = '/upload';
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}).then(
|
||||
response => response.text()).then(html => {
|
||||
let url = '/rules' + ruleNumber + '.txt?callback=' + Date.now();
|
||||
fetch(url).then(res => res.text()).then((ruleTextNewCheck) => {
|
||||
if (ruleTextNew === ruleTextNewCheck) {
|
||||
toasting();
|
||||
size.innerHTML = ruleTextNew.length;
|
||||
} else {
|
||||
console.log('error when saving...');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
"use strict";
|
||||
let size = document.getElementById("size");
|
||||
let ruleTextNew = document.getElementById("rules").value;
|
||||
ruleTextNew = ruleTextNew.replace(/\\r?\\n/g, "\\r\\n");
|
||||
let ruleNumber = document.getElementById("set").value;
|
||||
let ruleTextFileData = new File([ruleTextNew], "rules" + ruleNumber + ".txt", {
|
||||
type: "text/plain"
|
||||
});
|
||||
let formData = new FormData();
|
||||
formData.append("file", ruleTextFileData);
|
||||
formData.append("enctype", "multipart/form-data");
|
||||
let url = "/rules" + ruleNumber + ".txt?callback=" + Date.now();
|
||||
fetch(url).then(res => res.text()).then(ruleTextOld => {
|
||||
if (ruleTextNew === ruleTextOld) {
|
||||
console.log("nothing to save...");
|
||||
} else {
|
||||
fetch("/upload", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
}).then(response => response.text()).then(l => {
|
||||
let url = "/rules" + ruleNumber + ".txt?callback=" + Date.now();
|
||||
fetch(url).then(res => res.text()).then(ruleTextNewCheck => {
|
||||
if (ruleTextNew === ruleTextNewCheck) {
|
||||
toasting();
|
||||
size.innerHTML = ruleTextNew.length;
|
||||
} else {
|
||||
console.log("error when saving...");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
function toasting() {
|
||||
var x = document.getElementById('toastmessage');
|
||||
x.innerHTML = 'Submitted';
|
||||
x.className = 'show';
|
||||
setTimeout(function() {
|
||||
x.innerHTML = '';
|
||||
x.className = x.className.replace('show', '');
|
||||
}, 2000);
|
||||
}
|
||||
Reference in New Issue
Block a user