Add Vite + React 19 Blackhorse ʞ Graph dashboard frontend#21
Add Vite + React 19 Blackhorse ʞ Graph dashboard frontend#21Igor Holt (igor-holt) wants to merge 1 commit into
Conversation
Summary of ChangesHello Igor Holt (@igor-holt), I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request adds a new frontend application to the repository, providing a user interface for monitoring and controlling the Blackhorse ʞ Graph system. The frontend is built using modern web technologies and offers real-time data visualization and interactive components for managing threats, knowledge graphs, and system modalities. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new frontend dashboard for Blackhorse ʞ Graph monitoring. The implementation uses React 19, Vite, and TypeScript, and includes real-time data visualization with Socket.IO, Cytoscape.js, and Recharts. The code is well-structured, but there are several areas for improvement regarding maintainability and configuration. My feedback includes suggestions to use environment variables for configuration, improve type safety, and make the code more robust and easier to maintain by refactoring hardcoded values and complex logic.
| const [activeTab, setActiveTab] = useState<'threats' | 'knowledge' | 'modality' | 'sovereignty'>('threats'); | ||
|
|
||
| useEffect(() => { | ||
| const newSocket = io('ws://localhost:8080', { |
There was a problem hiding this comment.
The WebSocket URL is hardcoded. This makes it difficult to configure the application for different environments (development, staging, production). It's a best practice to use environment variables for such configurations.
With Vite, you can create a .env file and access the variable as import.meta.env.VITE_SOCKET_URL.
| const newSocket = io('ws://localhost:8080', { | |
| const newSocket = io(import.meta.env.VITE_SOCKET_URL || 'ws://localhost:8080', { |
| .dashboard { | ||
| min-height: 100vh; | ||
| background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); | ||
| color: #f8fafc; | ||
| font-family: 'JetBrains Mono', 'Fira Code', monospace; | ||
| } |
There was a problem hiding this comment.
This stylesheet uses hardcoded color values in multiple places (e.g., #0f172a, #f8fafc, #334155). To improve maintainability and make theming easier, consider defining these colors as CSS custom properties (variables) in a :root block and reusing them throughout the file.
Example:
:root {
--background-start: #0f172a;
--text-color: #f8fafc;
--border-color: #334155;
}
.dashboard {
/* ... */
background: linear-gradient(135deg, var(--background-start) 0%, #1e293b 100%);
color: var(--text-color);
}| target: | ||
| modality.current_model === 'Haiku' ? 'Sonnet' : modality.current_model === 'Sonnet' ? 'Opus' : 'Haiku', |
There was a problem hiding this comment.
| <div className={styles.titleSection}> | ||
| <Shield className={styles.logoIcon} size={32} /> | ||
| <h1>BLACKHORSE // ʞ GRAPH</h1> | ||
| <span className={styles.version}>v4.20-DELTA</span> |
| <span className={styles.version}>v4.20-DELTA</span> | ||
| </div> | ||
| <div className={styles.statusBar}> | ||
| <div className={`${styles.statusIndicator} ${styles[modality.thermal_status.toLowerCase()]}`}> |
There was a problem hiding this comment.
Dynamically constructing class names from API data using toLowerCase() can be fragile. If the API returns a value that doesn't have a corresponding CSS class, it will fail silently without applying the intended style. A safer approach is to use a mapping object to resolve the class name. This also applies to other similar cases in this component for sovereignty.status and threat.severity.
| cy={(cy: any) => { | ||
| cy.on('tap', 'node', (evt: any) => { | ||
| console.log('[ʞGRAPH] Node selected:', evt.target.data()); | ||
| }); | ||
| }} |
There was a problem hiding this comment.
Using any for the Cytoscape instance (cy) and event (evt) bypasses TypeScript's type checking. You should provide proper types to ensure type safety. You can import Core and EventObject from the cytoscape library.
For example:
import { Core, EventObject } from 'cytoscape';
// ...
cy={(cy: Core) => {
cy.on('tap', 'node', (evt: EventObject) => {
console.log('[ʞGRAPH] Node selected:', evt.target.data());
});
}} cy={(cy: import('cytoscape').Core) => {
cy.on('tap', 'node', (evt: import('cytoscape').EventObject) => {
console.log('[ʞGRAPH] Node selected:', evt.target.data());
});
}}
| @@ -0,0 +1 @@ | |||
| declare module 'react-cytoscapejs'; | |||
There was a problem hiding this comment.
This module declaration is too generic and provides no type safety. To leverage TypeScript's benefits, you should define the props for the CytoscapeComponent. This will enable type checking and autocompletion where the component is used.
Example of a more complete declaration:
declare module 'react-cytoscapejs' {
import { ElementDefinition, Stylesheet, LayoutOptions, Core } from 'cytoscape';
import * as React from 'react';
interface CytoscapeComponentProps {
elements: ElementDefinition[];
stylesheet?: Stylesheet[];
style?: React.CSSProperties;
layout?: LayoutOptions;
cy?: (cy: Core) => void;
}
const CytoscapeComponent: React.FC<CytoscapeComponentProps>;
export default CytoscapeComponent;
}
Motivation
Description
frontend/app withpackage.json,tsconfigfiles,vite.config.ts,index.html, andREADME.md.BlackhorseKGraphReact component (frontend/src/BlackhorseKGraph.tsx) which includes Socket.IO subscriptions, tabbed panels forThreats/Knowledge/Modality/Sovereignty, Cytoscape graph rendering and Recharts charts, plus GLASS_BREAK and modality escalation controls.frontend/src/BlackhorseKGraph.module.css) providing the cyber-themed layout, responsive rules and UI components.frontend/src/types/react-cytoscapejs.d.tsto satisfy missing types forreact-cytoscapejsand a simplemain.tsxentrypoint.Testing
npm installinfrontend/which completed successfully.npm run buildinfrontend/which initially failed due to missingreact-cytoscapejstypes, then succeeded after addingsrc/types/react-cytoscapejs.d.ts.npm run dev -- --host 0.0.0.0 --port 4173and captured a full-page screenshot via Playwright to validate the UI served correctly.frontend/files to the repo; build succeeded with a Vite chunk-size warning (noted) during production build.Codex Task