admin firs step
This commit is contained in:
190
complete_ailogs.py
Normal file
190
complete_ailogs.py
Normal file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
# Read the existing file
|
||||
with open('frontend/admin/components/AiLogsTile.vue', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find where the file is truncated
|
||||
if 'case \'success\': return \'green' in content and not 'case \'warning\': return \'orange\'' in content:
|
||||
# The file is truncated at the getLogColor function
|
||||
# Let's find the exact position and complete it
|
||||
lines = content.split('\n')
|
||||
|
||||
# Find the line with getLogColor
|
||||
for i, line in enumerate(lines):
|
||||
if 'const getLogColor = (type: AiLogEntry[\'type\']) => {' in line:
|
||||
start_idx = i
|
||||
# Find where this function ends (look for the next function or end of file)
|
||||
for j in range(i+1, len(lines)):
|
||||
if lines[j].strip().startswith('const ') or lines[j].strip().startswith('//'):
|
||||
# Found next function or comment
|
||||
end_idx = j
|
||||
break
|
||||
else:
|
||||
end_idx = len(lines)
|
||||
|
||||
# Replace the incomplete function with complete version
|
||||
new_function = '''const getLogColor = (type: AiLogEntry['type']) => {
|
||||
switch (type) {
|
||||
case 'info': return 'blue'
|
||||
case 'success': return 'green'
|
||||
case 'warning': return 'orange'
|
||||
case 'error': return 'red'
|
||||
case 'gold': return 'amber'
|
||||
default: return 'grey'
|
||||
}
|
||||
}
|
||||
|
||||
const getLogIcon = (type: AiLogEntry['type']) => {
|
||||
switch (type) {
|
||||
case 'info': return 'mdi-information'
|
||||
case 'success': return 'mdi-check-circle'
|
||||
case 'warning': return 'mdi-alert'
|
||||
case 'error': return 'mdi-alert-circle'
|
||||
case 'gold': return 'mdi-star'
|
||||
default: return 'mdi-help-circle'
|
||||
}
|
||||
}
|
||||
|
||||
const getRobotColor = (robotName: string) => {
|
||||
const robot = robots.value.find(r => r.name === robotName)
|
||||
return robot?.statusColor || 'grey'
|
||||
}
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status.toLowerCase()) {
|
||||
case 'running': return 'success'
|
||||
case 'idle': return 'warning'
|
||||
case 'error': return 'error'
|
||||
case 'paused': return 'grey'
|
||||
default: return 'grey'
|
||||
}
|
||||
}
|
||||
|
||||
const formatTime = (timestamp: Date) => {
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - timestamp.getTime()
|
||||
|
||||
if (diff < 60000) return 'Just now'
|
||||
if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`
|
||||
if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`
|
||||
return timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
|
||||
// Data fetching and polling
|
||||
const fetchLogs = async () => {
|
||||
if (isRefreshing.value) return
|
||||
|
||||
isRefreshing.value = true
|
||||
try {
|
||||
// Simulate API call
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// Add new mock log
|
||||
const newLog = generateMockLog()
|
||||
logs.value.push(newLog)
|
||||
|
||||
// Keep only last 50 logs
|
||||
if (logs.value.length > 50) {
|
||||
logs.value = logs.value.slice(-50)
|
||||
}
|
||||
|
||||
// Mark old logs as not new
|
||||
setTimeout(() => {
|
||||
logs.value.forEach(log => {
|
||||
if (log.isNew && Date.now() - log.timestamp.getTime() > 5000) {
|
||||
log.isNew = false
|
||||
}
|
||||
})
|
||||
}, 5000)
|
||||
|
||||
// Update connection status randomly
|
||||
if (Math.random() > 0.95) {
|
||||
connectionStatus.value = 'disconnected'
|
||||
} else if (Math.random() > 0.98) {
|
||||
connectionStatus.value = 'error'
|
||||
} else {
|
||||
connectionStatus.value = 'connected'
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch AI logs:', error)
|
||||
connectionStatus.value = 'error'
|
||||
} finally {
|
||||
isRefreshing.value = false
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const forceRefresh = () => {
|
||||
fetchLogs()
|
||||
}
|
||||
|
||||
const toggleAutoScroll = () => {
|
||||
autoScroll.value = !autoScroll.value
|
||||
}
|
||||
|
||||
const clearLogs = () => {
|
||||
logs.value = []
|
||||
}
|
||||
|
||||
const scrollToBottom = () => {
|
||||
if (logContainer.value && autoScroll.value) {
|
||||
nextTick(() => {
|
||||
logContainer.value!.scrollTop = logContainer.value!.scrollHeight
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Polling management
|
||||
let pollInterval: number | null = null
|
||||
|
||||
const startPolling = () => {
|
||||
if (pollInterval) clearInterval(pollInterval)
|
||||
pollInterval = setInterval(() => {
|
||||
fetchLogs()
|
||||
scrollToBottom()
|
||||
}, pollingInterval.value) as unknown as number
|
||||
}
|
||||
|
||||
const stopPolling = () => {
|
||||
if (pollInterval) {
|
||||
clearInterval(pollInterval)
|
||||
pollInterval = null
|
||||
}
|
||||
}
|
||||
|
||||
// Lifecycle hooks
|
||||
onMounted(() => {
|
||||
// Initial load
|
||||
fetchLogs()
|
||||
|
||||
// Start polling
|
||||
startPolling()
|
||||
|
||||
// Generate initial logs
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const log = generateMockLog()
|
||||
log.timestamp = new Date(Date.now() - (10 - i) * 60000) // Staggered times
|
||||
log.isNew = false
|
||||
logs.value.push(log)
|
||||
}
|
||||
|
||||
isLoading.value = false
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stopPolling()
|
||||
})'''
|
||||
|
||||
# Replace the lines
|
||||
new_lines = lines[:start_idx] + new_function.split('\n')
|
||||
content = '\n'.join(new_lines)
|
||||
break
|
||||
|
||||
# Write the complete file
|
||||
with open('frontend/admin/components/AiLogsTile.vue', 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print("File completed successfully")
|
||||
Reference in New Issue
Block a user