diff --git a/supervisor/shared/web_workflow/static/directory.html b/supervisor/shared/web_workflow/static/directory.html
index 0586cd0a54..0466cb717d 100644
--- a/supervisor/shared/web_workflow/static/directory.html
+++ b/supervisor/shared/web_workflow/static/directory.html
@@ -9,7 +9,7 @@
- | | | | |
+ | | | | | Edit |
Type | Size | Path | Modified | |
diff --git a/supervisor/shared/web_workflow/static/directory.js b/supervisor/shared/web_workflow/static/directory.js
index b2b76648c2..9dbe8384d6 100644
--- a/supervisor/shared/web_workflow/static/directory.js
+++ b/supervisor/shared/web_workflow/static/directory.js
@@ -91,6 +91,9 @@ async function refresh_list() {
delete_button.disabled = !editable;
delete_button.onclick = del;
+ let edit_url = new URL("/edit/#" + f.name, url_base);
+ let edit_link = clone.querySelector(".edit_link");
+ edit_link.href = edit_url
new_children.push(clone);
}
diff --git a/supervisor/shared/web_workflow/static/edit.html b/supervisor/shared/web_workflow/static/edit.html
new file mode 100644
index 0000000000..c223a11047
--- /dev/null
+++ b/supervisor/shared/web_workflow/static/edit.html
@@ -0,0 +1,26 @@
+
+
+
+
+ Code Edit
+
+
+
+
+
+Loading
+
+
+
+
+
diff --git a/supervisor/shared/web_workflow/static/edit.js b/supervisor/shared/web_workflow/static/edit.js
new file mode 100644
index 0000000000..60dd8b1073
--- /dev/null
+++ b/supervisor/shared/web_workflow/static/edit.js
@@ -0,0 +1,47 @@
+let $editor = document.querySelector("#code_textarea");
+let filename = location.hash.substring(1);
+let $output_text = document.querySelector("#output_text");
+
+fetch(`/fs/${filename}`)
+ .then(function (response) {
+ $output_text.innerText = `Loading Status: ${response.status}`;
+ return response.status === 200 ? response.text() : "";
+ })
+ .then(function (data) {
+ $editor.value = data;
+ });
+
+function save() {
+ $output_text.innerText = "Saving..."
+ const requestOptions = {
+ method: 'PUT',
+ body: $editor.value
+ };
+ fetch(`/fs/${filename}`, requestOptions)
+ .then(function (response) {
+ $output_text.innerText = `Saving Status: ${response.status}`;
+ return response.text();
+ })
+ .then(function (data) {
+ console.log("after fetch: " + data);
+ });
+}
+
+document.querySelector("#save_btn").onclick = function () {
+ console.log("Click Save!");
+ save();
+}
+
+let isCtrl = false;
+document.onkeyup=function(e){
+ if(e.keyCode === 17) isCtrl=false;
+}
+
+document.onkeydown=function(e){
+ if(e.keyCode === 17) isCtrl=true;
+ if(e.keyCode === 83 && isCtrl === true) {
+ //ctrl-s pressed
+ save();
+ return false;
+ }
+}
diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c
index 4c768e320b..0f92f635a4 100644
--- a/supervisor/shared/web_workflow/web_workflow.c
+++ b/supervisor/shared/web_workflow/web_workflow.c
@@ -916,6 +916,8 @@ STATIC_FILE(directory_html);
STATIC_FILE(directory_js);
STATIC_FILE(welcome_html);
STATIC_FILE(welcome_js);
+STATIC_FILE(edit_html);
+STATIC_FILE(edit_js);
STATIC_FILE(style_css);
STATIC_FILE(serial_html);
STATIC_FILE(serial_js);
@@ -1087,6 +1089,16 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
}
}
}
+ } else if (strcmp(request->path, "/edit/") == 0) {
+ if (!request->authenticated) {
+ if (_api_password[0] != '\0') {
+ _reply_unauthorized(socket, request);
+ } else {
+ _reply_forbidden(socket, request);
+ }
+ } else {
+ _REPLY_STATIC(socket, request, edit_html);
+ }
} else if (strncmp(request->path, "/cp/", 4) == 0) {
const char *path = request->path + 3;
if (strcasecmp(request->method, "OPTIONS") == 0) {
@@ -1126,6 +1138,8 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
_REPLY_STATIC(socket, request, welcome_js);
} else if (strcmp(request->path, "/serial.js") == 0) {
_REPLY_STATIC(socket, request, serial_js);
+ } else if (strcmp(request->path, "/edit.js") == 0) {
+ _REPLY_STATIC(socket, request, edit_js);
} else if (strcmp(request->path, "/style.css") == 0) {
_REPLY_STATIC(socket, request, style_css);
} else if (strcmp(request->path, "/favicon.ico") == 0) {
diff --git a/tools/gen_web_workflow_static.py b/tools/gen_web_workflow_static.py
index b8c5baf619..172a80dac0 100644
--- a/tools/gen_web_workflow_static.py
+++ b/tools/gen_web_workflow_static.py
@@ -29,7 +29,9 @@ for f in args.files:
if f.name.endswith(".html"):
uncompressed = minify_html.minify(uncompressed.decode("utf-8")).encode("utf-8")
elif f.name.endswith(".js"):
- uncompressed = jsmin.jsmin(uncompressed.decode("utf-8")).encode("utf-8")
+ uncompressed = jsmin.jsmin(uncompressed.decode("utf-8"), quote_chars="'\"`").encode(
+ "utf-8"
+ )
compressed = gzip.compress(uncompressed)
clen = len(compressed)
compressed = ", ".join([hex(x) for x in compressed])