# Integration Example - Adding New Features to Dashboard
This guide shows how to integrate the new React components into the existing StrikePackageGPT dashboard.
## Current Architecture
StrikePackageGPT currently uses:
- **Backend**: FastAPI (Python)
- **Frontend**: HTML templates with Jinja2 (no React build system yet)
- **Static files**: Served from `services/dashboard/static/`
## Integration Options
### Option 1: Add React Build System (Recommended for Production)
This approach sets up a proper React application:
1. **Create React App Structure**
```bash
cd services/dashboard
npm init -y
npm install react react-dom
npm install --save-dev @babel/core @babel/preset-react webpack webpack-cli babel-loader css-loader style-loader
npm install cytoscape # For NetworkMap
```
2. **Create webpack.config.js**
```javascript
const path = require('path');
module.exports = {
entry: './src/index.jsx',
output: {
path: path.resolve(__dirname, 'static/dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
resolve: {
extensions: ['.js', '.jsx']
}
};
```
3. **Create src/index.jsx**
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(, document.getElementById('root'));
```
4. **Create src/App.jsx**
```jsx
import React, { useState } from 'react';
import NetworkMap from '../NetworkMap';
import VoiceControls from '../VoiceControls';
import HelpChat from '../HelpChat';
import GuidedWizard from '../GuidedWizard';
function App() {
const [showHelp, setShowHelp] = useState(false);
const [showWizard, setShowWizard] = useState(false);
const [currentScanId, setCurrentScanId] = useState(null);
return (
StrikePackageGPT Dashboard
{currentScanId && (
console.log('Host clicked:', host)}
/>
)}
{/* Floating components */}
setShowHelp(false)}
currentPage="dashboard"
/>
{showWizard && (
{
console.log('Wizard completed:', data);
setShowWizard(false);
}}
onCancel={() => setShowWizard(false)}
/>
)}
);
}
function handleVoiceCommand(result) {
console.log('Voice command:', result);
// Handle voice commands
}
export default App;
```
5. **Update package.json scripts**
```json
{
"scripts": {
"build": "webpack --mode production",
"dev": "webpack --mode development --watch"
}
}
```
6. **Build and Deploy**
```bash
npm run build
```
7. **Update templates/index.html**
```html
StrikePackageGPT
```
---
### Option 2: Use Components via CDN (Quick Start)
For quick testing without build system:
1. **Create static/js/components.js**
```javascript
// Load React and ReactDOM from CDN
// Then include the component code
// Example: Simple integration
function initStrikePackageGPT() {
// Initialize voice controls
const voiceContainer = document.createElement('div');
voiceContainer.id = 'voice-controls';
document.body.appendChild(voiceContainer);
// Initialize help chat button
const helpButton = document.createElement('button');
helpButton.textContent = 'π¬ Help';
helpButton.onclick = () => toggleHelpChat();
document.body.appendChild(helpButton);
}
document.addEventListener('DOMContentLoaded', initStrikePackageGPT);
```
2. **Update templates/index.html**
```html
StrikePackageGPT
```
---
### Option 3: Progressive Enhancement (Current Setup Compatible)
Use the new features as API endpoints with vanilla JavaScript:
1. **Create static/js/app.js**
```javascript
// Voice Control Integration
class VoiceController {
constructor() {
this.isListening = false;
this.mediaRecorder = null;
this.setupButton();
}
setupButton() {
const button = document.createElement('button');
button.id = 'voice-button';
button.innerHTML = 'ποΈ';
button.onclick = () => this.toggleListening();
document.body.appendChild(button);
}
async toggleListening() {
if (!this.isListening) {
await this.startListening();
} else {
this.stopListening();
}
}
async startListening() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
this.mediaRecorder = new MediaRecorder(stream);
const chunks = [];
this.mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
this.mediaRecorder.onstop = async () => {
const blob = new Blob(chunks, { type: 'audio/webm' });
await this.processAudio(blob);
stream.getTracks().forEach(track => track.stop());
};
this.mediaRecorder.start();
this.isListening = true;
document.getElementById('voice-button').innerHTML = 'βΈοΈ';
}
stopListening() {
if (this.mediaRecorder) {
this.mediaRecorder.stop();
this.isListening = false;
document.getElementById('voice-button').innerHTML = 'ποΈ';
}
}
async processAudio(blob) {
const formData = new FormData();
formData.append('audio', blob);
const response = await fetch('/api/voice/transcribe', {
method: 'POST',
body: formData
});
const result = await response.json();
console.log('Transcribed:', result.text);
// Route command
const cmdResponse = await fetch('/api/voice/command', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: result.text })
});
const command = await cmdResponse.json();
this.executeCommand(command);
}
executeCommand(command) {
// Execute the command based on routing info
console.log('Command:', command);
}
}
// Help Chat Integration
class HelpChat {
constructor() {
this.isOpen = false;
this.messages = [];
this.sessionId = `session-${Date.now()}`;
this.setupUI();
}
setupUI() {
const container = document.createElement('div');
container.id = 'help-chat';
container.style.display = 'none';
document.body.appendChild(container);
const button = document.createElement('button');
button.id = 'help-button';
button.innerHTML = 'π¬';
button.onclick = () => this.toggle();
document.body.appendChild(button);
}
toggle() {
this.isOpen = !this.isOpen;
const chat = document.getElementById('help-chat');
chat.style.display = this.isOpen ? 'block' : 'none';
if (this.isOpen && this.messages.length === 0) {
this.addMessage('assistant', 'Hi! How can I help you?');
}
}
async sendMessage(text) {
this.addMessage('user', text);
const response = await fetch('/api/llm/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: text,
session_id: this.sessionId
})
});
const result = await response.json();
this.addMessage('assistant', result.message);
}
addMessage(role, content) {
this.messages.push({ role, content });
this.render();
}
render() {
const chat = document.getElementById('help-chat');
chat.innerHTML = this.messages.map(msg => `
${msg.content}
`).join('');
}
}
// Network Map Integration
class NetworkMapViewer {
constructor(containerId) {
this.container = document.getElementById(containerId);
this.hosts = [];
}
async loadScan(scanId) {
const response = await fetch(`/api/nmap/hosts?scan_id=${scanId}`);
const data = await response.json();
this.hosts = data.hosts || [];
this.render();
}
render() {
this.container.innerHTML = `
`;
}
renderHost(host) {
const iconUrl = `/static/${this.getIcon(host)}.svg`;
return `
${host.ip}
${host.hostname || 'Unknown'}
${host.os_type || 'Unknown OS'}
`;
}
getIcon(host) {
const osType = (host.os_type || '').toLowerCase();
if (osType.includes('windows')) return 'windows';
if (osType.includes('linux')) return 'linux';
if (osType.includes('mac')) return 'mac';
if (host.device_type?.includes('server')) return 'server';
if (host.device_type?.includes('network')) return 'network';
return 'unknown';
}
exportCSV() {
const csv = [
['IP', 'Hostname', 'OS', 'Device Type', 'Ports'].join(','),
...this.hosts.map(h => [
h.ip,
h.hostname || '',
h.os_type || '',
h.device_type || '',
(h.ports || []).map(p => p.port).join(';')
].join(','))
].join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `network-${Date.now()}.csv`;
a.click();
}
showHostDetails(ip) {
const host = this.hosts.find(h => h.ip === ip);
alert(JSON.stringify(host, null, 2));
}
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', () => {
window.voiceController = new VoiceController();
window.helpChat = new HelpChat();
window.networkMap = new NetworkMapViewer('network-map-container');
});
```
2. **Add CSS (static/css/components.css)**
```css
/* Voice Button */
#voice-button {
position: fixed;
bottom: 20px;
right: 20px;
width: 60px;
height: 60px;
border-radius: 50%;
border: none;
background: #3498DB;
color: white;
font-size: 24px;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
z-index: 1000;
}
/* Help Chat */
#help-chat {
position: fixed;
right: 20px;
top: 20px;
width: 400px;
height: 600px;
background: white;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.2);
z-index: 999;
padding: 20px;
overflow-y: auto;
}
#help-button {
position: fixed;
top: 20px;
right: 20px;
background: #3498DB;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
z-index: 1001;
}
.message {
margin: 10px 0;
padding: 10px;
border-radius: 8px;
}
.message.user {
background: #3498DB;
color: white;
text-align: right;
}
.message.assistant {
background: #ECF0F1;
color: #2C3E50;
}
/* Network Map */
.network-map {
width: 100%;
padding: 20px;
}
.hosts {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
margin-top: 20px;
}
.host {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
cursor: pointer;
transition: all 0.2s;
}
.host:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
transform: translateY(-2px);
}
.host img {
width: 48px;
height: 48px;
}
.host-info {
margin-top: 10px;
}
```
3. **Update templates/index.html**
```html
StrikePackageGPT
```
---
## Testing the Integration
### Test Voice Control
1. Open browser console
2. Click the mic button
3. Speak a command
4. Check console for transcription result
### Test Help Chat
1. Click the help button
2. Type a message
3. Wait for AI response
### Test Network Map
```javascript
// In browser console
networkMap.loadScan('your-scan-id');
```
---
## Deployment Checklist
- [ ] Choose integration method (build system vs progressive enhancement)
- [ ] Install required npm packages (if using React build)
- [ ] Configure API endpoints in backend
- [ ] Add environment variables for API keys
- [ ] Test voice control permissions
- [ ] Verify LLM service connectivity
- [ ] Test network map with real scan data
- [ ] Configure CORS if needed
- [ ] Add error handling for API failures
- [ ] Test on multiple browsers
- [ ] Document any additional setup steps
---
## Next Steps
1. Choose your integration approach
2. Set up the build system (if needed)
3. Test each component individually
4. Integrate components into main dashboard
5. Add error handling and loading states
6. Style components to match your theme
7. Deploy and test in production environment
For questions or issues, refer to FEATURES.md or use the Help Chat! π