From e44ff71a58f555be4f2be9029dddb0c138611ead Mon Sep 17 00:00:00 2001 From: ABelliqueux Date: Sun, 15 Jan 2023 16:32:13 +0100 Subject: [PATCH] Sync queue management UI, sync/reboot/poweroff all btns --- app.py | 10 ++-- changelog_todo.md | 68 ++++++++++++++++++---------- static/script.js | 108 ++++++++++++++++++++++++++++++++------------ static/style.css | 16 ++++++- templates/main.html | 2 + 5 files changed, 143 insertions(+), 61 deletions(-) diff --git a/app.py b/app.py index d3b8189..1270ff8 100755 --- a/app.py +++ b/app.py @@ -38,6 +38,9 @@ gui_l10n = {"locale": LOCALE[:2], "str_sync": _("Sync"), "str_poweroff": _("Poweroff"), "str_reboot": _("Reboot"), + # TODO : add to l10n + "str_poweroff_all": _("Poweroff all"), + "str_reboot_all": _("Reboot all"), "str_blink": _("Blink"), "str_link": _("Link"), "str_refresh": _("Refresh"), @@ -631,11 +634,8 @@ def sync(host, arg0): if arg0 == "stop": return stop_upload() elif host == "all": - reset_current_upload() - return sync_media_folder(media_folder_local, media_folder_remote_expanded, host, cmd_port) - # TODO : figure it out for multiple hosts - # ~ for hostl in hosts_available: - # ~ sync_media_folder(media_folder_local, media_folder_remote_expanded, hostl, cmd_port) + # This is done in js for now. + pass else: reset_current_upload() return sync_media_folder(media_folder_local, media_folder_remote_expanded, host, cmd_port) diff --git a/changelog_todo.md b/changelog_todo.md index d1b41d0..529f25a 100644 --- a/changelog_todo.md +++ b/changelog_todo.md @@ -28,7 +28,7 @@ sha256 : 0fe3fe76d0e56e445124fa20646fa8b3d8c59568786b3ebc8a96d83d92f203e3 * Use nginx reverse proxy + SSL between server and clients ( https://medium.com/@antelle/how-to-generate-a-self-signed-ssl-certificate-for-an-ip-address-f0dd8dddf754 ) * Webgui beautifying -## 0.4 : 2022-10-21-videopi.img.xz +## 0.4 : 2022-10-21-pilpil.img.xz md5 : dee7af70135994169cab4f073ee51905 sha256 : ec3e17fc9b41f8c5181484e9866be2d1d92cab8403210e3d22f4f689edd4cfde @@ -38,7 +38,7 @@ sha256 : ec3e17fc9b41f8c5181484e9866be2d1d92cab8403210e3d22f4f689edd4cfde * Add media folder sync (scp, rsync, http upload) * Install script ; Wifi setup, generate/install SSH keys/ nginx SSL cert/key fore each host, change hostname, static IPs -## 0.5 : 2022-11-17-videopi.img.xz +## 0.5 : 2022-11-17-pilpil.img.xz md5 : d1dd7404ec05d16c8a4179370a214821 sha256 : 401359a84c6d60902c05602bd52fae70f0b2ecac36d550b52d14e1e3230854a6 @@ -55,6 +55,31 @@ sha256 : 401359a84c6d60902c05602bd52fae70f0b2ecac36d550b52d14e1e3230854a6 * FR localisation for server, client and install script * pep8ification +## 0.6 : 2023-01-06-pilpil.img.xz +md5 : +sha256 : + + * os update, cleanup + * server: upload in chunks + * server: file upload : only send new files, get upload status (/sync/status) + * server: pep8fied (except for line length) + * server: better overclock values for RPIs + * server: VLC file caching set to 5000ms for seamless playback + * server: BCM4345 workaround to solve wifi connectivity (https://wiki.arthus.net/?Rpi_wifi_-_BCM4345_and_CTRL-EVENT-ASSOC-REJECT) + * webgui: remove file from timeline (drag&drop to bin) + * webgui: upload progress dialog + * webgui: l10n html + js + * webgui: Add remote file enqueuing + * webgui: Fix timeline UI + * webgui: Add video thumbnails to timeline UI + * webgui: fix timeline/file sync with multiple clients + * webgui: file sync queuing UI + * webgui: sync all live hosts button + * webgui: Add remove from sync queue button + * webgui: Poweroff/Reboot all btn + * client: Only blink when running on rpi + * client: Generate video thumbnails on startup/upload with ffmpeg, serve SVG when file not found, create folder if needed + # FS checklist @@ -70,32 +95,27 @@ sha256 : 401359a84c6d60902c05602bd52fae70f0b2ecac36d550b52d14e1e3230854a6 # DOING NEXT : - * server : remove incomplete files before upload - * webgui/server : interrupt current download ? - * webgui : upload status CSS transition ? - + * FIXME : playhead stuck after removing item from playlist + # DONE : - - * server : upload in chunks - * webgui: remove file from timeline (drag&drop to bin?) (check bugs) - * webgui: upload progress dialog - * server : file upload : only send new files, get upload status (/sync/status) - * webgui: l10n html + js - * webgui: Add remote file enqueuing - * webgui: Fix timeline UI - * webgui: Add video thumbnails to timeline UI - * client: Only blink when running on rpi - * client: Generate video thumbnail on start with ffmpegthumbnailer, serve SVG when file not found - * server: pep8fied (except for line length) - - + # TODO : - * ~ Test with several rpis - * ? Scripts hotspot linux : nmcli - win : https://github.com/JamesCullum/Windows-Hotspot - mac : https://apple.stackexchange.com/questions/2488/start-stop-internet-sharing-from-a-script + * check control from wifi client ( smartphone ) + * playlist save/load ? + * webgui/server : interrupt current download ? + * server : remove incomplete uploaded files before new upload ? + * webgui : upload status CSS transition ? * ! Remove git personal details/resolv.conf, remove authorized_keys, ssh config, clean home, re-enable ssh pw login * ~ Doc # OTHER: + * ? Scripts hotspot + linux : nmcli + win : https://github.com/JamesCullum/Windows-Hotspot + mac : https://apple.stackexchange.com/questions/2488/start-stop-internet-sharing-from-a-script * get_client_rssi.sh on server + +# À FINANCER + * Shutters/motor control + * XLR support + * UDEV rules : keyboard/mouse = standalone GUI \ No newline at end of file diff --git a/static/script.js b/static/script.js index 20a60f2..7bf9a1a 100644 --- a/static/script.js +++ b/static/script.js @@ -435,6 +435,8 @@ function update_host_list(infos_array){ host_down.forEach(function(element){ document.getElementById(element).style.display = 'none'; }); + currentUser.hosts_up = host_up; + currentUser.hosts_down = host_down; currentUser.status_all = host_up.length + " client(s)."; return host_up.length; } @@ -449,10 +451,10 @@ function freeze_ui_host(host, html_attributes, inner_html=0, inner_text=0){ let upload_dialog_cont_element = add_HTML_element("div", html_attributes, 0, host); container_element.insertBefore(upload_dialog_cont_element, siblings[0]); if (inner_html){ - let child_node = add_HTML_element("div", inner_html, 0, host) + let child_node = add_HTML_element("div", inner_html, 0, host); let new_node = container_element.children.item(html_attributes.id + host).appendChild(child_node); if (inner_text){ - new_node.innerText = inner_text; + new_node.innerHTML = inner_text; } } } @@ -461,17 +463,43 @@ function freeze_queued_container(command){ freeze_attributes = {"id":"ul_queued_freeze_", "class": "ul_queued_freeze"}; inner_html = {"id":"ul_queued_msg_", "class": "ul_queued_msg"}; inner_text = t9n[LOCALE].item_queued; - freeze_ui_host(command.split("/")[2], freeze_attributes, inner_html, inner_text); + let host = command.split("/")[2]; + inner_text += 'X 0){ + console.log(host + " unqueuing"); + currentUser.ul_queue.splice(item_index, 1); + unfreeze_queued_container(host); + } + } +} + // UI addEventListener("DOMContentLoaded", function() { //~ adjust_timeline(); @@ -716,11 +755,11 @@ addEventListener("DOMContentLoaded", function() { let command = clickedButton.value; if ( command.indexOf("/reboot" ) > -1 || command.indexOf("/poweroff") > -1 ) { - // TODO : l10n - if ( !confirm(t9n[LOCALE].confirmMessage) ) { - return 0; + if (command.indexOf("/all" ) == -1){ + if ( !confirm(t9n[LOCALE].confirmMessage) ) { + return 0; + } } - } else if ( command == "/scan" ) { document.getElementById("status_all").innerHTML = currentUser.status_all; @@ -741,27 +780,36 @@ addEventListener("DOMContentLoaded", function() { request.onload = send_ajax_cmd(command); } else if ( command.indexOf("/sync/") > -1 ) { - console.log("Sync command detected"); + if ( command.indexOf("/all") > -1 ) { + console.log("Sync all request"); + // If command is /sync/all, add live hosts to sync queue + if (currentUser.hosts_up){ + currentUser.hosts_up.forEach(function(host){ + let command = "/sync/" + host; + if (currentUser.ul_queue.indexOf(command) == -1){ + console.log("Adding " + host + " to sync queue..."); + currentUser.ul_queue.push(command); + freeze_queued_container(command); + } + }); + } + if (currentUser.ul_queue.length > 1){ + sync_host(); + } + // Prevent request + return 0; + } // If command not already in queue, add it if (!currentUser.ul_queue.includes(command)){ - console.log("Queuing command..."); currentUser.ul_queue.push(command); freeze_queued_container(command); } else { console.log("Command already in queue..."); + return 0; } - sync_host(); - //~ if (currentUser.ul_queue.length > 1){ - //~ if (currentUser.freeze_ul){ - //~ console.log("UL freezed, wait for queue to complete.") - // Offload command sending to sync_host() - return 1; - //~ } - //~ currentUser.status_all = t9n[LOCALE].sync; - //~ // Display dialog - //~ display_upload_status(command); - //~ // Request values to fill dialog - //~ setTimeout(send_ajax_cmd, 1000, command + "/status"); + sync_host(); + // Prevent request + return 1; } else if ( command.indexOf("/browse") > -1 ) { request.onload = send_ajax_cmd("/all/browse"); diff --git a/static/style.css b/static/style.css index 69aa99d..a21ae1a 100644 --- a/static/style.css +++ b/static/style.css @@ -63,7 +63,12 @@ tr:nth-child(2n+1) {background-color: #888;} /* .client_container .left_col{border-right: #a8a8a8 2px solid;} */ -.client_container .button{} +.client_container .btn { + min-width:1em; +} +.client_container .right_col .btn { + min-width: 3em; +} .client_container .upload_dialog_cont { position: absolute; @@ -122,6 +127,7 @@ tr:nth-child(2n+1) {background-color: #888;} margin-top:1em; background-color: #33333361; } + [id^="tl_cont"] { float: left; width: 10%; @@ -152,7 +158,7 @@ tr:nth-child(2n+1) {background-color: #888;} .buttons {width:75%;margin:auto;text-align: center;padding: 2em;} .btn { margin:auto; - width:3em; + min-width:2em; height: 4em; display:inline-block; padding: 0; @@ -182,6 +188,11 @@ tr:nth-child(2n+1) {background-color: #888;} } .btn_txt {display: block;font-size: small;} +.btn-unqueue {background: #bbb; + width: 1em; + height: 1em; +} + #delete_btn { width: 5em; height: 3em; @@ -199,6 +210,7 @@ tr:nth-child(2n+1) {background-color: #888;} /*Right column*/ .right_col {width: 71%;display: inline-block;} + /*Left column*/ .left_col {width: 28%;display: inline-block;float: left;clear: left;} .left_col button { diff --git a/templates/main.html b/templates/main.html index de2b799..40d1080 100644 --- a/templates/main.html +++ b/templates/main.html @@ -26,6 +26,8 @@ + +