import React, { useEffect, useRef, useState } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import ReactJson from 'react-json-view'; import { useTheme } from 'providers/Theme'; import { IconX, IconTrash, IconFilter, IconAlertTriangle, IconAlertCircle, IconBug, IconCode, IconChevronDown, IconTerminal2, IconNetwork, IconDashboard } from '@tabler/icons'; import { closeConsole, clearLogs, updateFilter, toggleAllFilters, setActiveTab, clearDebugErrors, updateNetworkFilter, toggleAllNetworkFilters } from 'providers/ReduxStore/slices/logs'; import NetworkTab from './NetworkTab'; import TerminalTab from './TerminalTab'; import RequestDetailsPanel from './RequestDetailsPanel'; // import DebugTab from './DebugTab'; import ErrorDetailsPanel from './ErrorDetailsPanel'; import Performance from '../Performance'; import StyledWrapper from './StyledWrapper'; const LogIcon = ({ type }) => { const iconProps = { size: 16, strokeWidth: 1.5 }; switch (type) { case 'error': return ; case 'warn': return ; case 'info': return ; // case 'debug': // return ; default: return ; } }; const LogTimestamp = ({ timestamp }) => { const date = new Date(timestamp); const time = date.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }); return {time}; }; const LogMessage = ({ message, args }) => { const { displayedTheme } = useTheme(); const formatMessage = (msg, originalArgs) => { if (originalArgs && originalArgs.length > 0) { return originalArgs.map((arg, index) => { if (typeof arg === 'object' && arg !== null) { return (
props.theme.font.size.sm}', fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace' }} />
); } return String(arg); }); } return msg; }; const formattedMessage = formatMessage(message, args); return ( {Array.isArray(formattedMessage) ? formattedMessage.map((item, index) => ( {item} )) : formattedMessage} ); }; const FilterDropdown = ({ filters, logCounts, onFilterToggle, onToggleAll }) => { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); const allFiltersEnabled = Object.values(filters).every((f) => f); const activeFilters = Object.entries(filters).filter(([_, enabled]) => enabled); useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); return (
{isOpen && (
Filter by Type
{Object.entries(filters).map(([filterType, enabled]) => ( ))}
)}
); }; const NetworkFilterDropdown = ({ filters, requestCounts, onFilterToggle, onToggleAll }) => { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); const allFiltersEnabled = Object.values(filters).every((f) => f); const activeFilters = Object.entries(filters).filter(([_, enabled]) => enabled); const getMethodColor = (method) => { switch (method?.toUpperCase()) { case 'GET': return '#10b981'; case 'POST': return '#8b5cf6'; case 'PUT': return '#f59e0b'; case 'DELETE': return '#ef4444'; case 'PATCH': return '#06b6d4'; case 'HEAD': return '#6b7280'; case 'OPTIONS': return '#84cc16'; default: return '#6b7280'; } }; useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); return (
{isOpen && (
Filter by Method
{Object.entries(filters).map(([method, enabled]) => ( ))}
)}
); }; const ConsoleTab = ({ logs, filters, logCounts, onFilterToggle, onToggleAll, onClearLogs }) => { const logsEndRef = useRef(null); const prevLogsCountRef = useRef(0); useEffect(() => { // Only scroll when new logs are added, not when switching tabs if (logsEndRef.current && logs.length > prevLogsCountRef.current) { logsEndRef.current.scrollIntoView({ behavior: 'auto' }); } prevLogsCountRef.current = logs.length; }, [logs]); const filteredLogs = logs.filter((log) => filters[log.type]); return (
{filteredLogs.length === 0 ? (

No logs to display

Logs will appear here as your application runs
) : (
{filteredLogs.map((log) => (
))}
)}
); }; const Console = () => { const dispatch = useDispatch(); const { logs, filters, activeTab, selectedRequest, selectedError, networkFilters, debugErrors } = useSelector((state) => state.logs); const collections = useSelector((state) => state.collections.collections); const consoleRef = useRef(null); const logCounts = logs.reduce((counts, log) => { counts[log.type] = (counts[log.type] || 0) + 1; return counts; }, {}); const allRequests = React.useMemo(() => { const requests = []; collections.forEach((collection) => { if (collection.timeline) { collection.timeline .filter((entry) => entry.type === 'request') .forEach((entry) => { requests.push({ ...entry, collectionName: collection.name, collectionUid: collection.uid }); }); } }); return requests.sort((a, b) => a.timestamp - b.timestamp); }, [collections]); const filteredLogs = logs.filter((log) => filters[log.type]); const filteredRequests = allRequests.filter((request) => { const method = request.data?.request?.method?.toUpperCase() || 'GET'; return networkFilters[method]; }); const requestCounts = allRequests.reduce((counts, request) => { const method = request.data?.request?.method?.toUpperCase() || 'GET'; counts[method] = (counts[method] || 0) + 1; return counts; }, {}); const handleFilterToggle = (filterType, enabled) => { dispatch(updateFilter({ filterType, enabled })); }; const handleNetworkFilterToggle = (method, enabled) => { dispatch(updateNetworkFilter({ method, enabled })); }; const handleClearLogs = () => { dispatch(clearLogs()); }; const handleClearDebugErrors = () => { dispatch(clearDebugErrors()); }; const handlecloseConsole = () => { dispatch(closeConsole()); }; const handleToggleAllFilters = (enabled) => { dispatch(toggleAllFilters(enabled)); }; const handleToggleAllNetworkFilters = (enabled) => { dispatch(toggleAllNetworkFilters(enabled)); }; const handleTabChange = (tab) => { dispatch(setActiveTab(tab)); }; const renderTabContent = () => { switch (activeTab) { case 'console': return ( ); case 'network': return ; case 'performance': return ; case 'terminal': return ; // case 'debug': // return ; default: return ( ); } }; const renderTabControls = () => { switch (activeTab) { case 'console': return (
); case 'network': return (
); case 'terminal': return null; // No controls needed for terminal // case 'debug': // return ( //
//
// {debugErrors.length > 0 && ( // // )} //
//
// ); default: return null; } }; return (
{/* */}
{renderTabControls()}
{activeTab === 'network' && selectedRequest ? (
{renderTabContent()}
) : activeTab === 'debug' && selectedError ? (
{renderTabContent()}
) : ( renderTabContent() )}
); }; export default Console;