diff --git a/cq_server/module_manager.py b/cq_server/module_manager.py index b125281..e9d510c 100644 --- a/cq_server/module_manager.py +++ b/cq_server/module_manager.py @@ -6,7 +6,7 @@ from typing import List, Dict, Tuple import glob import json - +import time IGNORE_FILE_NAME = '.cqsignore' @@ -185,9 +185,13 @@ def get_data(self) -> dict: if self.module_name: try: + start_time = time.perf_counter() + model = self.get_json_model() + end_time = time.perf_counter() data = { 'module_name': self.module_name, - 'model': self.get_json_model(), + 'model': model, + 'time_elapsed': end_time - start_time, 'source': '' } except ModuleManagerError as error: diff --git a/cq_server/server.py b/cq_server/server.py index 1e930fb..3accd98 100644 --- a/cq_server/server.py +++ b/cq_server/server.py @@ -13,7 +13,8 @@ WATCH_PERIOD = 0.3 -SSE_MESSAGE_TEMPLATE = 'event: file_update\ndata: %s\n\n' +SSE_FILE_UPDATE_MESSAGE_TEMPLATE = 'event: file_update\ndata: %s\n\n' +SSE_LOADING_MODEL_MESSAGE_TEMPLATE = 'event: loading_model\ndata: %s\n\n' app = Flask(__name__, static_url_path='/static') @@ -74,8 +75,9 @@ def watchdog() -> None: if last_updated_file: module_manager.module_name = op.basename(last_updated_file)[:-3] + events_queue.put(SSE_LOADING_MODEL_MESSAGE_TEMPLATE % module_manager.module_name) data = module_manager.get_data() - events_queue.put(SSE_MESSAGE_TEMPLATE % json.dumps(data)) + events_queue.put(SSE_FILE_UPDATE_MESSAGE_TEMPLATE % json.dumps(data)) sleep(WATCH_PERIOD) events_queue = Queue(maxsize = 3) diff --git a/cq_server/static/viewer.css b/cq_server/static/viewer.css index a64be2f..e80472c 100644 --- a/cq_server/static/viewer.css +++ b/cq_server/static/viewer.css @@ -34,6 +34,24 @@ body { background-color: grey; } +.toast { + position: absolute; + z-index: 1000; + left: 50%; + top: 56px; + transform: translate(-50%, -50%); + padding: 5px 20px; + border: 1px solid black; + border-radius: 5px; + background-color: #444; + opacity: 0.8; + font-family: sans-serif; + color: white; + font-weight: 100; + font-size: 14px; + text-align: center; +} + .cqs_module_item { margin: 0.5em; display: inline-block; diff --git a/cq_server/static/viewer.js b/cq_server/static/viewer.js index fc502d3..676d69a 100644 --- a/cq_server/static/viewer.js +++ b/cq_server/static/viewer.js @@ -9,12 +9,22 @@ let modules_name = []; let viewer = null; let timer = null; let sse = null; +let toast_timeout = null; function init_sse() { sse = new EventSource('events'); + sse.addEventListener('loading_model', event => { + const message = "Reloading model: " + event.data; + show_toast(message); + }) sse.addEventListener('file_update', event => { - render(JSON.parse(event.data)); + const data = JSON.parse(event.data); + render(data); + hide_toast(); + if (data.time_elapsed !== undefined) { + console.log(`${data.module_name}: model reloaded in ${data.time_elapsed.toFixed(2)} seconds`); + } }) sse.onerror = error => { if (sse.readyState == 2) { @@ -54,6 +64,29 @@ function init_viewer(_options, _modules_name) { } } +function show_toast(message, duration = -1) { + if (toast_timeout) { + clearTimeout(toast_timeout); + toast_timeout = null; + } + + document.getElementById('cqs_toast_message').innerText = message; + document.getElementById('cqs_toast').style.display = 'block'; + + if (duration !== -1) { + toast_timeout = setTimeout(hide_toast, duration); + } +} + +function hide_toast() { + if (toast_timeout) { + clearTimeout(toast_timeout); + toast_timeout = null; + } + + document.getElementById('cqs_toast').style.display = 'none'; +} + function show_error() { document.title = 'error | CadQuery Server'; document.getElementById('cqs_index').style.display = 'none'; diff --git a/cq_server/templates/viewer.html b/cq_server/templates/viewer.html index 185cfeb..30833f7 100644 --- a/cq_server/templates/viewer.html +++ b/cq_server/templates/viewer.html @@ -25,6 +25,10 @@
+ +