import { useContext, useState, useEffect } from 'react' import { Descriptions, Button, Typography, Flex, Space, Dropdown, message, Tag, Input, InputNumber, Select } from 'antd' import ReloadIcon from '../../Icons/ReloadIcon.jsx' import CloudIcon from '../../Icons/CloudIcon.jsx' import { ApiServerContext } from '../context/ApiServerContext.jsx' import BoolDisplay from '../common/BoolDisplay.jsx' import InfoCollapse from '../common/InfoCollapse.jsx' import loglevel from 'loglevel' import config from '../../../config' const logger = loglevel.getLogger('ApiContextDebug') logger.setLevel(config.logLevel) const { Text, Paragraph } = Typography const ApiContextDebug = () => { const { apiServer, error, connecting, connected, fetchLoading, lockObject, unlockObject, fetchObjectLock, updateObject, createObject, deleteObject, subscribeToObjectUpdates, subscribeToObjectEvent, subscribeToObjectTypeUpdates, subscribeToObjectLock, fetchObject, fetchObjects, fetchObjectsByProperty, fetchSpotlightData, fetchFileContent, fetchTemplatePreview, fetchNotes, fetchHostOTP, sendObjectAction } = useContext(ApiServerContext) const [msgApi, contextHolder] = message.useMessage() const [connectionStatus, setConnectionStatus] = useState('disconnected') const [socketId, setSocketId] = useState(null) // Test input states const [testInputs, setTestInputs] = useState({ objectId: 'test-id', objectType: 'user', hostId: 'test-host-id', parentId: 'test-parent-id', fileName: 'test.gcode', query: 'test query', action: 'start', eventType: 'status', properties: ['name', 'email'], filter: { active: true }, scale: 1.0, templateContent: 'Test template content', testObject: { name: 'Test Object' } }) // Collapse states const [collapseStates, setCollapseStates] = useState({ fetchTests: false, crudTests: false, subscriptionTests: false, specialTests: false }) useEffect(() => { if (apiServer) { setConnectionStatus(apiServer.connected ? 'connected' : 'disconnected') setSocketId(apiServer.id) // Listen for connection status changes const handleConnect = () => { setConnectionStatus('connected') setSocketId(apiServer.id) } const handleDisconnect = () => { setConnectionStatus('disconnected') setSocketId(null) } apiServer.on('connect', handleConnect) apiServer.on('disconnect', handleDisconnect) return () => { apiServer.off('connect', handleConnect) apiServer.off('disconnect', handleDisconnect) } } else { setConnectionStatus('disconnected') setSocketId(null) } }, [apiServer]) // Helper functions const updateTestInput = (key, value) => { setTestInputs((prev) => ({ ...prev, [key]: value })) } const toggleCollapse = (key) => { setCollapseStates((prev) => ({ ...prev, [key]: !prev[key] })) } const handleReconnect = () => { if (apiServer) { apiServer.connect() msgApi.info('Attempting to reconnect...') } else { msgApi.warning('No API server instance available') } } const handleDisconnect = () => { if (apiServer) { apiServer.disconnect() msgApi.info('Disconnected from API server') } } const testFetchObject = async () => { try { msgApi.loading('Testing fetchObject...', 0) const result = await fetchObject( testInputs.objectId, testInputs.objectType ) msgApi.destroy() msgApi.success('fetchObject test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchObject test failed') logger.error('fetchObject error:', err) } } const testFetchObjects = async () => { try { msgApi.loading('Testing fetchObjects...', 0) const result = await fetchObjects(testInputs.objectType, { page: 1, limit: 5 }) msgApi.destroy() msgApi.success('fetchObjects test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchObjects test failed') logger.error('fetchObjects error:', err) } } const testLockObject = () => { try { lockObject(testInputs.objectId, testInputs.objectType) msgApi.success('Lock command sent') } catch (err) { msgApi.error('Lock command failed') logger.error('Lock error:', err) } } const testUnlockObject = () => { try { unlockObject(testInputs.objectId, testInputs.objectType) msgApi.success('Unlock command sent') } catch (err) { msgApi.error('Unlock command failed') logger.error('Unlock error:', err) } } const testFetchObjectLock = async () => { try { msgApi.loading('Testing fetchObjectLock...', 0) const result = await fetchObjectLock( testInputs.objectId, testInputs.objectType ) msgApi.destroy() msgApi.success('fetchObjectLock test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchObjectLock test failed') logger.error('fetchObjectLock error:', err) } } const testUpdateObject = async () => { try { msgApi.loading('Testing updateObject...', 0) const testData = { name: 'Test Update', updated: new Date().toISOString() } const result = await updateObject( testInputs.objectId, testInputs.objectType, testData ) msgApi.destroy() msgApi.success('updateObject test completed') } catch (err) { msgApi.destroy() msgApi.error('updateObject test failed') logger.error('updateObject error:', err) } } const testCreateObject = async () => { try { msgApi.loading('Testing createObject...', 0) const testData = { name: 'Test Create', created: new Date().toISOString() } const result = await createObject(testInputs.objectType, testData) msgApi.destroy() msgApi.success('createObject test completed') } catch (err) { msgApi.destroy() msgApi.error('createObject test failed') logger.error('createObject error:', err) } } const testDeleteObject = async () => { try { msgApi.loading('Testing deleteObject...', 0) const result = await deleteObject( testInputs.objectId, testInputs.objectType ) msgApi.destroy() msgApi.success('deleteObject test completed') } catch (err) { msgApi.destroy() msgApi.error('deleteObject test failed') logger.error('deleteObject error:', err) } } const testFetchObjectsByProperty = async () => { try { msgApi.loading('Testing fetchObjectsByProperty...', 0) const params = { properties: testInputs.properties, filter: testInputs.filter, masterFilter: {} } const result = await fetchObjectsByProperty(testInputs.objectType, params) msgApi.destroy() msgApi.success('fetchObjectsByProperty test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchObjectsByProperty test failed') logger.error('fetchObjectsByProperty error:', err) } } const testFetchSpotlightData = async () => { try { msgApi.loading('Testing fetchSpotlightData...', 0) const result = await fetchSpotlightData(testInputs.query) msgApi.destroy() msgApi.success('fetchSpotlightData test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchSpotlightData test failed') logger.error('fetchSpotlightData error:', err) } } const testfetchFileContent = async () => { try { msgApi.loading('Testing fetchFileContent...', 0) await fetchFileContent( testInputs.objectId, 'gcodefile', testInputs.fileName ) msgApi.destroy() msgApi.success('fetchFileContent test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchFileContent test failed') logger.error('fetchFileContent error:', err) } } const testFetchTemplatePreview = async () => { try { msgApi.loading('Testing fetchTemplatePreview...', 0) fetchTemplatePreview( testInputs.objectId, testInputs.templateContent, testInputs.testObject, testInputs.scale, (result) => { msgApi.destroy() if (result.success) { msgApi.success('fetchTemplatePreview test completed') } else { msgApi.error('fetchTemplatePreview test failed') } } ) } catch (err) { msgApi.destroy() msgApi.error('fetchTemplatePreview test failed') logger.error('fetchTemplatePreview error:', err) } } const testFetchNotes = async () => { try { msgApi.loading('Testing fetchNotes...', 0) const result = await fetchNotes(testInputs.parentId) msgApi.destroy() msgApi.success('fetchNotes test completed') } catch (err) { msgApi.destroy() msgApi.error('fetchNotes test failed') logger.error('fetchNotes error:', err) } } const testFetchHostOTP = async () => { try { msgApi.loading('Testing fetchHostOTP...', 0) fetchHostOTP(testInputs.hostId, (result) => { msgApi.destroy() if (result.otp) { msgApi.success('fetchHostOTP test completed: ' + result.otp) } else { msgApi.error('fetchHostOTP test failed') } }) } catch (err) { msgApi.destroy() msgApi.error('fetchHostOTP test failed') logger.error('fetchHostOTP error:', err) } } const testSendObjectAction = async () => { try { msgApi.loading('Testing sendObjectAction...', 0) sendObjectAction( testInputs.objectId, 'printer', testInputs.action, (result) => { msgApi.destroy() if (result.success) { msgApi.success('sendObjectAction test completed') } else { msgApi.error('sendObjectAction test failed') } } ) } catch (err) { msgApi.destroy() msgApi.error('sendObjectAction test failed') logger.error('sendObjectAction error:', err) } } const testSubscribeToObjectUpdates = () => { try { const callback = (data) => { logger.debug('Object update received:', data) } const unsubscribe = subscribeToObjectUpdates( testInputs.objectId, testInputs.objectType, callback ) msgApi.success('Subscribed to object updates') logger.debug('Subscribed to object updates for test-id') // Store unsubscribe function for cleanup setTimeout(() => { if (unsubscribe) { unsubscribe() logger.debug('Unsubscribed from object updates') } }, 10000) // Auto-unsubscribe after 10 seconds } catch (err) { msgApi.error('Subscribe to object updates failed') logger.error('Subscribe error:', err) } } const testSubscribeToObjectEvent = () => { try { const callback = (event) => { logger.debug('Object event received:', event) } const unsubscribe = subscribeToObjectEvent( testInputs.objectId, 'printer', testInputs.eventType, callback ) msgApi.success('Subscribed to object events') logger.debug('Subscribed to object events for test-id') // Store unsubscribe function for cleanup setTimeout(() => { if (unsubscribe) { unsubscribe() logger.debug('Unsubscribed from object events') } }, 10000) // Auto-unsubscribe after 10 seconds } catch (err) { msgApi.error('Subscribe to object events failed') logger.error('Subscribe error:', err) } } const testSubscribeToObjectTypeUpdates = () => { try { const callback = (data) => { logger.debug('Object type update received:', data) } const unsubscribe = subscribeToObjectTypeUpdates( testInputs.objectType, callback ) msgApi.success('Subscribed to object type updates') logger.debug('Subscribed to object type updates for user') // Store unsubscribe function for cleanup setTimeout(() => { if (unsubscribe) { unsubscribe() logger.debug('Unsubscribed from object type updates') } }, 10000) // Auto-unsubscribe after 10 seconds } catch (err) { msgApi.error('Subscribe to object type updates failed') logger.error('Subscribe error:', err) } } const testSubscribeToObjectLock = () => { try { const callback = (lockData) => { logger.debug('Object lock update received:', lockData) } const unsubscribe = subscribeToObjectLock( testInputs.objectId, testInputs.objectType, callback ) msgApi.success('Subscribed to object lock updates') logger.debug('Subscribed to object lock updates for test-id') // Store unsubscribe function for cleanup setTimeout(() => { if (unsubscribe) { unsubscribe() logger.debug('Unsubscribed from object lock updates') } }, 10000) // Auto-unsubscribe after 10 seconds } catch (err) { msgApi.error('Subscribe to object lock updates failed') logger.error('Subscribe error:', err) } } const actionItems = { items: [ { label: 'Reconnect', key: 'reconnect', disabled: connected }, { label: 'Disconnect', key: 'disconnect', disabled: !connected }, { type: 'divider' }, { label: 'Reload', key: 'reload', icon: } ], onClick: ({ key }) => { switch (key) { case 'reconnect': handleReconnect() break case 'disconnect': handleDisconnect() break case 'reload': msgApi.info('Reloading API State...') window.location.reload() break default: break } } } const getConnectionStatusColor = () => { switch (connectionStatus) { case 'connected': return 'success' case 'connecting': return 'processing' case 'disconnected': return 'error' default: return 'default' } } return ( {contextHolder} {/* Header with Actions */} }> {connectionStatus.charAt(0).toUpperCase() + connectionStatus.slice(1)} {socketId || 'None'} {error || 'None'} 🔎} active={collapseStates.params} onToggle={() => toggleCollapse('params')} collapseKey='params' > updateTestInput('objectId', e.target.value)} placeholder='Enter object ID' size='small' /> updateTestInput('hostId', e.target.value)} placeholder='Enter host ID' /> updateTestInput('parentId', e.target.value)} placeholder='Enter parent ID' /> updateTestInput('fileName', e.target.value)} placeholder='Enter file name' /> updateTestInput('query', e.target.value)} placeholder='Enter search query' /> updateTestInput('eventType', value)} style={{ width: '100%' }} options={[ { value: 'status', label: 'Status' }, { value: 'progress', label: 'Progress' }, { value: 'error', label: 'Error' }, { value: 'complete', label: 'Complete' } ]} /> updateTestInput('scale', value)} min={0.1} max={10} step={0.1} style={{ width: '100%' }} /> updateTestInput('templateContent', e.target.value) } placeholder='Enter template content' rows={2} /> {/* Test Sections */}
{/* Fetch Tests */} 📥} active={collapseStates.fetchTests} onToggle={() => toggleCollapse('fetchTests')} collapseKey='fetchTests' > {/* CRUD Tests */} ✏️} active={collapseStates.crudTests} onToggle={() => toggleCollapse('crudTests')} collapseKey='crudTests' > {/* Special Tests */} 🔧} active={collapseStates.specialTests} onToggle={() => toggleCollapse('specialTests')} collapseKey='specialTests' > {/* Subscription Tests */} 📡} active={collapseStates.subscriptionTests} onToggle={() => toggleCollapse('subscriptionTests')} collapseKey='subscriptionTests' > {/* API Server Instance Info */} 🖥️} active={false} onToggle={() => {}} collapseKey='apiServer' >
              {apiServer ? (
                
                  
                    {JSON.stringify(
                      {
                        connected: apiServer.connected,
                        id: apiServer.id,
                        transport: apiServer.io.engine.transport.name,
                        readyState: apiServer.io.engine.readyState
                      },
                      null,
                      2
                    )}
                  
) : ( No API server instance )}
) } export default ApiContextDebug