feat: Add vision controls, function menu, and custom alert dialogs
- Add Vision menu with Camera (QRCode) and Barcode (Keyence) controls - Add Function menu with Manage, Log Viewer, and folder navigation - Add quick action buttons (Manual, Light, Print, Cancel) to header - Replace browser alert() with custom AlertDialog component - Add MachineBridge methods for vision, lighting, folders, and manual operations - Add WebSocketServer handlers for all new commands - Add communication layer methods for frontend-backend integration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Camera, ChevronRight, X } from 'lucide-react';
|
||||
import { comms } from '../communication';
|
||||
import { useAlert } from '../contexts/AlertContext';
|
||||
|
||||
interface VisionMenuProps {
|
||||
isOpen: boolean;
|
||||
@@ -9,6 +11,7 @@ interface VisionMenuProps {
|
||||
export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
const [activeSubmenu, setActiveSubmenu] = useState<string | null>(null);
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
const { showAlert } = useAlert();
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
@@ -28,14 +31,27 @@ export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleQRCodeCamera = () => {
|
||||
console.log('[VisionMenu] Camera (QRCode) clicked');
|
||||
// TODO: Implement QR Code camera functionality
|
||||
};
|
||||
|
||||
const handleKeyenceBarcode = () => {
|
||||
console.log('[VisionMenu] Barcode (Keyence) clicked');
|
||||
// TODO: Implement Keyence barcode functionality
|
||||
const handleVisionCommand = async (commandFn: () => Promise<{ success: boolean; message: string }>, actionName: string) => {
|
||||
try {
|
||||
const result = await commandFn();
|
||||
if (result.success) {
|
||||
console.log(`[VisionMenu] ${actionName}: ${result.message}`);
|
||||
} else {
|
||||
console.error(`[VisionMenu] ${actionName} failed: ${result.message}`);
|
||||
showAlert({
|
||||
type: 'error',
|
||||
title: `${actionName} Failed`,
|
||||
message: result.message
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`[VisionMenu] ${actionName} error:`, error);
|
||||
showAlert({
|
||||
type: 'error',
|
||||
title: `${actionName} Error`,
|
||||
message: error.message || 'Unknown error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -63,7 +79,6 @@ export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
<div className="relative">
|
||||
<button
|
||||
onMouseEnter={() => setActiveSubmenu('qrcode')}
|
||||
onClick={handleQRCodeCamera}
|
||||
className="w-full flex items-center justify-between px-4 py-3 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors font-tech"
|
||||
>
|
||||
<span>Camera (QRCode)</span>
|
||||
@@ -77,26 +92,26 @@ export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
onMouseLeave={() => setActiveSubmenu(null)}
|
||||
>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Connect')}
|
||||
onClick={() => handleVisionCommand(() => comms.cameraConnect(), 'Camera Connect')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
<div className="h-px bg-white/10 my-1" />
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Get Image')}
|
||||
onClick={() => handleVisionCommand(() => comms.cameraGetImage(), 'Camera Get Image')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Get Image
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Live View')}
|
||||
onClick={() => handleVisionCommand(() => comms.cameraLiveView(), 'Camera Live View')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Live View
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] QRCode - Read Test')}
|
||||
onClick={() => handleVisionCommand(() => comms.cameraReadTest(), 'Camera Read Test')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Read Test
|
||||
@@ -109,7 +124,6 @@ export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
<div className="relative">
|
||||
<button
|
||||
onMouseEnter={() => setActiveSubmenu('keyence')}
|
||||
onClick={handleKeyenceBarcode}
|
||||
className="w-full flex items-center justify-between px-4 py-3 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors font-tech"
|
||||
>
|
||||
<span>Barcode (Keyence)</span>
|
||||
@@ -123,26 +137,26 @@ export const VisionMenu: React.FC<VisionMenuProps> = ({ isOpen, onClose }) => {
|
||||
onMouseLeave={() => setActiveSubmenu(null)}
|
||||
>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Get Image')}
|
||||
onClick={() => handleVisionCommand(() => comms.keyenceGetImage(), 'Keyence Get Image')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Get Image
|
||||
</button>
|
||||
<div className="h-px bg-white/10 my-1" />
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Trigger On')}
|
||||
onClick={() => handleVisionCommand(() => comms.keyenceTriggerOn(), 'Keyence Trigger On')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Trigger On
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Trigger Off')}
|
||||
onClick={() => handleVisionCommand(() => comms.keyenceTriggerOff(), 'Keyence Trigger Off')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Trigger Off
|
||||
</button>
|
||||
<button
|
||||
onClick={() => console.log('[VisionMenu] Keyence - Save Image')}
|
||||
onClick={() => handleVisionCommand(() => comms.keyenceSaveImage(), 'Keyence Save Image')}
|
||||
className="w-full px-4 py-2 text-left text-slate-300 hover:bg-neon-blue/10 hover:text-neon-blue rounded transition-colors text-sm"
|
||||
>
|
||||
Save Image
|
||||
|
||||
Reference in New Issue
Block a user