Browse Source

feat(offline): enable GridStack offline-first fallback and harden local launch scripts

- Downloaded GridStack.js and CSS assets (v10.1.2) to the vendor folder for offline support.
- Configured index.html with local-first script loading and CDN fallback logic.
- Hardened server.py to explicitly bind to 127.0.0.1 and anchor to the script directory.
- Optimized Visualization_Start.bat with working directory anchoring and a delayed browser launch to ensure the server is fully ready.
refactor/sync-centralize
RUSHIL AMBARISH KADU 2 months ago
parent
commit
4506cbc569
  1. 20
      steps/Visualization_Start.bat
  2. 17
      steps/index.html
  3. 14
      steps/server.py
  4. 3
      steps/vendor/gridstack-all.js
  5. 1
      steps/vendor/gridstack.min.css

20
steps/Visualization_Start.bat

@ -1,8 +1,11 @@
@echo off
:: Force the working directory to be the folder containing this script
cd /d "%~dp0"
title Radar and Video Visualizer - Server
color 0B
cls
echo.
echo ======================================================
echo Radar and Video Visualizer - Local Server
@ -16,10 +19,17 @@ echo ======================================================
echo.
echo Launching the application in your default browser...
start http://127.0.0.1:8000/index.html
:: Delay the browser launch by 2 seconds to allow the Python server to start up
start /b "" cmd /c "timeout /t 2 /nobreak > nul && start http://127.0.0.1:8000/index.html"
echo Server is now running on http://127.0.0.1:8000
echo Server is starting on http://127.0.0.1:8000
echo Press CTRL+C at any time to stop the server.
echo.
:: Run the server command directly. We know 'python' works from our test.
python server.py
:: Detect python and run server.py
python server.py || py server.py || python3 server.py || (
echo.
echo ERROR: Could not start Python server.
echo Check if Python is installed and in your PATH.
pause
)

17
steps/index.html

@ -71,8 +71,21 @@
})();
</script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack-all.js"></script>
<link rel="stylesheet" href="./vendor/gridstack.min.css"/>
<script src="./vendor/gridstack-all.js"></script>
<script>
!window.GridStack && (function() {
// If local GridStack for some reason didn't load, try the CDN
var s = document.createElement('script');
s.src = 'https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack-all.js';
document.head.appendChild(s);
var l = document.createElement('link');
l.rel = 'stylesheet';
l.href = 'https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack.min.css';
document.head.appendChild(l);
})();
</script>
<script>
tailwind.config = {

14
steps/server.py

@ -1,27 +1,29 @@
import http.server
import socketserver
import os
import sys
# Ensure the server runs from the same directory as the script
os.chdir(os.path.dirname(os.path.abspath(__file__)))
PORT = 8000
class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
# Disable caching for all files
# Disable caching for all files to ensure latest assets are loaded
self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
self.send_header('Pragma', 'no-cache')
self.send_header('Expires', '0')
super().end_headers()
def log_message(self, format, *args):
# Optional: cleaner logging
super().log_message(format, *args)
Handler = MyHTTPRequestHandler
print(f"Starting server on http://127.0.0.1:{PORT}")
print("Working directory:", os.getcwd())
print("Cache-busting enabled: Browser will always fetch latest files.")
with socketserver.TCPServer(("", PORT), Handler) as httpd:
# Explicitly bind to 127.0.0.1 for better reliability in offline/local environments
with socketserver.TCPServer(("127.0.0.1", PORT), Handler) as httpd:
try:
httpd.serve_forever()
except KeyboardInterrupt:

3
steps/vendor/gridstack-all.js
File diff suppressed because it is too large
View File

1
steps/vendor/gridstack.min.css

@ -0,0 +1 @@
.grid-stack{position:relative}.grid-stack-rtl{direction:ltr}.grid-stack-rtl>.grid-stack-item{direction:rtl}.grid-stack-placeholder>.placeholder-content{background-color:rgba(0,0,0,.1);margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="%23666" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 20 20"><path d="m10 3 2 2H8l2-2v14l-2-2h4l-2 2"/></svg>');background-repeat:no-repeat;background-position:center}.grid-stack-item>.ui-resizable-ne{transform:translate(0,10px) rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:translate(0,10px) rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:0;left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:0;right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,top;cursor:move}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,.2);opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y="0"]{top:0}.grid-stack>.grid-stack-item[gs-x="0"]{left:0}.gs-12>.grid-stack-item{width:8.333%}.gs-12>.grid-stack-item[gs-x="1"]{left:8.333%}.gs-12>.grid-stack-item[gs-w="2"]{width:16.667%}.gs-12>.grid-stack-item[gs-x="2"]{left:16.667%}.gs-12>.grid-stack-item[gs-w="3"]{width:25%}.gs-12>.grid-stack-item[gs-x="3"]{left:25%}.gs-12>.grid-stack-item[gs-w="4"]{width:33.333%}.gs-12>.grid-stack-item[gs-x="4"]{left:33.333%}.gs-12>.grid-stack-item[gs-w="5"]{width:41.667%}.gs-12>.grid-stack-item[gs-x="5"]{left:41.667%}.gs-12>.grid-stack-item[gs-w="6"]{width:50%}.gs-12>.grid-stack-item[gs-x="6"]{left:50%}.gs-12>.grid-stack-item[gs-w="7"]{width:58.333%}.gs-12>.grid-stack-item[gs-x="7"]{left:58.333%}.gs-12>.grid-stack-item[gs-w="8"]{width:66.667%}.gs-12>.grid-stack-item[gs-x="8"]{left:66.667%}.gs-12>.grid-stack-item[gs-w="9"]{width:75%}.gs-12>.grid-stack-item[gs-x="9"]{left:75%}.gs-12>.grid-stack-item[gs-w="10"]{width:83.333%}.gs-12>.grid-stack-item[gs-x="10"]{left:83.333%}.gs-12>.grid-stack-item[gs-w="11"]{width:91.667%}.gs-12>.grid-stack-item[gs-x="11"]{left:91.667%}.gs-12>.grid-stack-item[gs-w="12"]{width:100%}.gs-1>.grid-stack-item{width:100%}
Loading…
Cancel
Save