-
Notifications
You must be signed in to change notification settings - Fork 3
Electron standalone frontend #857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Tim020
wants to merge
31
commits into
dev
Choose a base branch
from
feature/electron-standalone-frontend
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
+12,013
−47
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Detailed architecture documentation - Implementation phases with timeline - File inventory and directory structure - Development workflows and build process - Testing strategy and success criteria Issue #839
Add platform abstraction layer to support both browser and Electron environments: - Create platform detection module (platform/index.js) with runtime detection - Add browser implementation (platform/browser.js) using window.location - Add Electron implementation (platform/electron.js) with IPC placeholders - Update utils.js, main.js, and store.js to use platform layer - Configure ESLint to support top-level await (ES2022) This foundation enables seamless operation in both web and Electron contexts with 95% code sharing and minimal modifications to the existing Vue app. Refs #839 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add Electron main process, preload script, and connection management: - Create electron/main.js with BrowserWindow and IPC handlers - Create electron/preload.js exposing window.electronAPI via contextBridge - Create ConnectionManager service using electron-store for persistence - Add package.json with Electron 32.x and dependencies - Configure dev mode (Vite dev server) and production mode (built files) The Electron app now launches successfully and loads the Vue frontend. IPC communication is established for connection management and storage. Refs #839 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add server validation and discovery capabilities: - Create VersionChecker service to validate server compatibility - Fetches /api/v1/settings endpoint - Requires exact version match between client and server - Handles connection errors with detailed error messages - Create MDNSDiscovery service for local network server discovery - Uses bonjour-service to find _digiscript._tcp services - Optional version checking for discovered servers - 5 second discovery timeout - Add IPC handlers in main.js: - version:check - Validate server compatibility - mdns:discover - Find servers on local network - mdns:discoverWithVersionCheck - Discovery with version validation - Update preload.js to expose new methods to renderer Server-side mDNS advertising will be implemented in future backend work. The client-side discovery is ready to use when servers advertise. Refs #839 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add complete connection management interface for Electron app: - Create ServerSelector.vue component with: - Saved connections list with Connect/Test/Delete actions - mDNS discovery with version compatibility checking - Manual server entry form with validation - Test connection functionality - Real-time version compatibility feedback - Update router/index.js: - Add /electron/server-selector route (Electron-only) - Add navigation guard to redirect to selector if no active connection - Prevent non-Electron access to Electron-only routes - Fix VersionChecker.js to use dynamic import for node-fetch (ES module) The Electron app now has a complete connection workflow: 1. App launches → checks for active connection 2. No connection → redirects to ServerSelector 3. User selects/adds/discovers server 4. Version compatibility verified 5. Connection saved and activated 6. Redirects to home page Refs #839 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Move Electron connection check after store initialization and skip all settings fetching and auth checks when navigating to server selector. This fixes the blank page issue where the app would try to fetch settings from a non-existent server connection, causing the navigation to fail. Refs #839
Make WebSocket initialization conditional: - Check if running in Electron and if there's an active connection - Skip WebSocket initialization if no server is configured - Use window.location.href to reload page after connecting to server This fixes the blank page issue where main.js would try to initialize WebSocket before any server connection was configured, causing the app to crash before the ServerSelector could load. Connection flow: 1. App loads → checks for connection → skips WebSocket if none 2. Router redirects to ServerSelector 3. User adds/selects server 4. Page reloads with active connection 5. WebSocket initializes with correct server URL Refs #839
Add check in App.vue created hook to skip settings fetch and WebSocket initialization when running in Electron without an active connection. This fixes the error where App.vue would try to fetch settings before the router guard could redirect to the ServerSelector, causing the app to show the navbar but get stuck with a spinner. Now App.vue checks for active connection first and skips all initialization if none exists, allowing the router to properly redirect to ServerSelector. Refs #839
Fix infinite spinner by setting loaded=true before returning early when there's no active connection in Electron. Also add null check for SETTINGS in template to prevent errors when SETTINGS hasn't been fetched. The App.vue template shows a spinner when !loaded and only renders router-view when loaded=true. Previously, when skipping initialization, we never set loaded=true, causing the spinner to show forever. Refs #839
Add dynamic version reading from package metadata to settings.as_json(): - Use importlib.metadata.version() to read from pyproject.toml - Fallback to '0.0.0' if package metadata unavailable - Required for Electron client version compatibility checking The /api/v1/settings endpoint now includes a 'version' field that the Electron client uses to validate server compatibility before connecting. Refs #839
Add v-if condition to hide navbar when on /electron/server-selector route. The navbar (with About, Help, Login buttons) is now hidden on the server selection screen, providing a cleaner first-run experience. Refs #839
Replace importlib.metadata.version() with direct reading from pyproject.toml using tomllib (Python 3.11+ built-in). This avoids dependency on package installation and ensures version is always available. - Add _get_version() helper function - Read from pyproject.toml using tomllib - Fallback to '0.0.0' if file not found or parse error - Log warning if version read fails Fixes issue where version was returning '0.0.0' because server wasn't installed as a package. Refs #839
Add CORS (Cross-Origin Resource Sharing) headers to BaseController: - set_default_headers() adds CORS headers to all responses - options() method handles CORS preflight requests - Allow all origins (*) for Electron compatibility (file:// protocol) - Allow standard HTTP methods and headers This fixes CORS errors when the Electron app (running from file:// or Vite dev server) makes requests to the backend API. Refs #839
After connecting to a server via ServerSelector and reloading the page, the router guard wasn't detecting that RBAC roles needed to be fetched. The check only looked at whether the store was undefined, not whether the store data was empty. Now also checks if RBAC_ROLES getter is empty to trigger settings fetch, ensuring all required state is loaded before navigation proceeds. Fixes Vue warnings about IS_SHOW_EDITOR and other RBAC getters being undefined during render. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
The ConfigShow component was referencing IS_SHOW_EDITOR in its template (line 6: v-if="IS_SHOW_EDITOR") but not importing it in mapGetters. This caused Vue development mode to display a warning: "Property or method IS_SHOW_EDITOR is not defined on the instance" In production builds, this was silently failing - the undefined value evaluated to falsy, so the "Edit Show" button simply didn't render instead of showing an error. Added IS_SHOW_EDITOR to the mapGetters array to properly import the getter and fix both the dev warning and ensure the button displays correctly for users with edit permissions. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Changes: - Set base: './' in Vite config for relative paths (works with both web server and Electron file:// protocol) - Updated Electron to load from ../server/static in development, process.resourcesPath/static when packaged - Added server connection dropdown in navbar (Electron only) - Added switchServer() method and clearActiveConnection IPC - Configured Electron Forge to include server/static as extraResource - Added build script: builds frontend then packages Electron app Build workflow: 1. cd client && npm run build (outputs to ../server/static) 2. cd electron && npm run build (packages app with frontend included) Both web and Electron use same built files - no duplication! Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
When loading from file:// protocol (Electron production build), Vue Router's history mode fails because it tries to navigate to file paths that don't exist (e.g., file:///show-config). Solution: Detect file:// protocol and use hash mode (#/show-config) for Electron, while keeping history mode for web server. This allows navigation to work correctly in packaged Electron apps while maintaining clean URLs in the web version. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
The issue: After connecting to a server, using window.location.href = '/' navigates to file:/// (filesystem root) instead of reloading the app. Solution: Use window.location.reload() to reload the current page, which works correctly with both file:// protocol and web servers. Changes: - ServerSelector.vue: Replace window.location.href = '/' with window.location.reload() after successful connection - App.vue: Use router.push() + reload() for switchServer action This ensures navigation works correctly in packaged Electron apps. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Issue 1: After connecting, window.location.reload() was reloading the ServerSelector page instead of navigating to home. This caused a redirect loop. Issue 2: WebSocket connection stayed active when switching servers, causing connection leaks. Solutions: 1. Navigate to home using hash-based URL (baseUrl + '#/') instead of reload, which properly navigates in hash mode 2. Close WebSocket connection with this.$socket.close() before clearing active connection and navigating to ServerSelector Now users can connect to a server and navigate properly, and switching servers cleanly closes the old connection before reconnecting. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
The issue: After connecting to a server, changing window.location.href to a hash URL (e.g., baseUrl + '#/') only triggers client-side navigation, not a full page reload. This means main.js never re-runs, so the WebSocket is never reinitialized. Solution: Set window.location.hash first (to specify target route), then call window.location.reload() to force a full page reload. This ensures main.js runs again and reinitializes the WebSocket. Changes: - ServerSelector: Set hash to '/' then reload after connecting - App.vue switchServer: Set hash to '/electron/server-selector' then reload Now the WebSocket properly reinitializes after switching/reconnecting. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Issue: Using base: './' for both web and Electron caused SPA routing issues. On refresh of nested routes like /show-config/cast, relative asset paths resolved incorrectly (e.g., ./assets/index.js became /show-config/cast/assets/index.js), causing MIME type errors. Solution: Separate build outputs with different base paths: - Web build: base: '/' → ../server/static/ (absolute paths) - Electron build: base: './' → ./dist-electron/ (relative paths) Changes: - vite.config.js: Conditional base and outDir based on BUILD_TARGET env - Electron build script: Sets BUILD_TARGET=electron - Electron main.js: Loads from ../client/dist-electron/ - Electron Forge: Packages dist-electron/ as extraResource - .gitignore: Ignore dist-electron/ Build commands: - Web: cd client && npm run build - Electron: cd electron && npm run build (builds frontend + packages) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add mDNS/DNS-SD service advertising on the server and discovery on the Electron client, allowing automatic server detection on the local network. Server changes: - Create MDNSAdvertiser class using AsyncZeroconf for async event loop compatibility - Integrate mDNS into DigiScriptServer with toggleable setting - Add mdns_advertising setting (enabled by default) with callback - Support graceful start/stop when setting changes - Deduplicate IP addresses from getaddrinfo() Client changes: - Fix bonjour-service import (use named export with constructor) - MDNSDiscovery service already implemented, just needed import fix Technical details: - Use AsyncZeroconf instead of sync Zeroconf to avoid blocking Tornado's event loop - Service type: _digiscript._tcp.local. - Advertise on all non-loopback IPv4 addresses - Async settings access pattern for proper lock handling Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Configure linting and formatting for the Electron project to match the client project's code quality standards. Changes: - Add ESLint 9 with flat config (eslint.config.mjs) - Add Prettier for code formatting (.prettierrc.json) - Add lint and format npm scripts matching client project - Install required dev dependencies: - eslint, @eslint/js - prettier, eslint-config-prettier, eslint-plugin-prettier - globals for environment definitions Scripts added: - npm run lint: Format and lint with auto-fix - npm run ci-lint: Check formatting and linting (CI mode) - npm run format: Auto-format all JavaScript and JSON files - npm run format:check: Check formatting without changes Configuration: - ESLint: Node.js globals, ES2021 features, Prettier integration - Prettier: Single quotes, 100 char width, ES5 trailing commas - Automatically formatted existing code to match standards Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Client Test Results83 tests 83 ✅ 0s ⏱️ Results for commit 30f8c3a. ♻️ This comment has been updated with latest results. |
Python Test Results 1 files 1 suites 37s ⏱️ Results for commit 30f8c3a. ♻️ This comment has been updated with latest results. |
…tain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
cb3c582 to
d075af9
Compare
Create dedicated /api/v1/health endpoint for version checking that exposes only minimal, non-sensitive information (version and status). Previously, the Electron client used /api/v1/settings which exposed sensitive system data (database paths, log paths, debug mode, etc.) to unauthenticated clients. Backend changes: - Add GET /api/v1/health endpoint (public, no auth required) - Restore @api_authenticated decorator to GET /api/v1/settings - Keep @allow_when_password_required for password reset workflow - Export get_version() function from settings module - Fix test infrastructure: add missing port parameter to DigiScriptTestCase Frontend changes: - Update Electron VersionChecker to use /api/v1/health endpoint - Update ServerSelector UI enhancements (text alignment, time formatting) Tests: - Add comprehensive test suite for health endpoint (4 tests) - Add authentication tests for settings endpoint (2 tests) - All 315 backend tests passing - All 83 frontend tests passing Security impact: - Before: 10+ sensitive fields exposed publicly via /api/v1/settings - After: Only 2 non-sensitive fields exposed via /api/v1/health - Settings endpoint now requires authentication (401 without token) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
d075af9 to
cd149ef
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.