* Refactor translation imports and update text for localization across settings and system monitor routes - Changed translation import from 'react-i18next' to '@/i18n/react-i18next-compat' in multiple files. - Updated various text strings to use translation keys for better localization support in: - Local API Server settings - MCP Servers settings - Privacy settings - Provider settings - Shortcuts settings - System Monitor - Thread details - Ensured consistent use of translation keys for all user-facing text. Update web-app/src/routes/settings/appearance.tsx Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> Update web-app/src/routes/settings/appearance.tsx Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> Update web-app/src/locales/vn/settings.json Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> Update web-app/src/containers/dialogs/DeleteMCPServerConfirm.tsx Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> Update web-app/src/locales/id/common.json Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Add Chinese (Simplified and Traditional) localization files for various components - Created `tools.json`, `updater.json`, `assistants.json`, `chat.json`, `common.json`, `hub.json`, `logs.json`, `mcp-servers.json`, `provider.json`, `providers.json`, `settings.json`, `setup.json`, `system-monitor.json`, `tool-approval.json` in both `zh-CN` and `zh-TW` locales. - Added translations for tool approval, updater notifications, assistant management, chat interface, common UI elements, hub interactions, logging messages, MCP server configurations, provider management, settings options, setup instructions, and system monitoring. * Refactor localization strings for improved clarity and consistency in English, Indonesian, and Vietnamese settings files * Fix missing key and reword * fix pr comment --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
103 lines
2.9 KiB
TypeScript
103 lines
2.9 KiB
TypeScript
import { createFileRoute } from '@tanstack/react-router'
|
|
import { route } from '@/constants/routes'
|
|
|
|
import { useEffect, useState, useRef } from 'react'
|
|
import { readLogs } from '@/services/app'
|
|
import { useTranslation } from '@/i18n/react-i18next-compat'
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
export const Route = createFileRoute(route.appLogs as any)({
|
|
component: LogsViewer,
|
|
})
|
|
|
|
// Define log entry type
|
|
|
|
function LogsViewer() {
|
|
const { t } = useTranslation()
|
|
const [logs, setLogs] = useState<LogEntry[]>([])
|
|
const logsContainerRef = useRef<HTMLDivElement>(null)
|
|
|
|
useEffect(() => {
|
|
let lastLogsLength = 0
|
|
function updateLogs() {
|
|
readLogs().then((logData) => {
|
|
let needScroll = false
|
|
const filteredLogs = logData.filter(Boolean) as LogEntry[]
|
|
if (filteredLogs.length > lastLogsLength) needScroll = true
|
|
|
|
lastLogsLength = filteredLogs.length
|
|
setLogs(filteredLogs)
|
|
|
|
// Scroll to bottom after initial logs are loaded
|
|
if (needScroll) setTimeout(() => scrollToBottom(), 100)
|
|
})
|
|
}
|
|
updateLogs()
|
|
|
|
// repeat action each 3s
|
|
const intervalId = setInterval(() => updateLogs(), 3000)
|
|
|
|
return () => {
|
|
clearInterval(intervalId)
|
|
}
|
|
}, [])
|
|
|
|
// Function to scroll to the bottom of the logs container
|
|
const scrollToBottom = () => {
|
|
if (logsContainerRef.current) {
|
|
const { scrollHeight, clientHeight } = logsContainerRef.current
|
|
logsContainerRef.current.scrollTop = scrollHeight - clientHeight
|
|
}
|
|
}
|
|
|
|
// Function to get appropriate color for log level
|
|
const getLogLevelColor = (level: string) => {
|
|
switch (level) {
|
|
case 'error':
|
|
return 'text-red-500'
|
|
case 'warn':
|
|
return 'text-yellow-500'
|
|
case 'info':
|
|
return 'text-blue-500'
|
|
case 'debug':
|
|
return 'text-gray-500'
|
|
default:
|
|
return 'text-gray-500'
|
|
}
|
|
}
|
|
|
|
// Format timestamp to be more readable
|
|
const formatTimestamp = (timestamp: string | number) => {
|
|
const date = new Date(timestamp)
|
|
return date.toLocaleTimeString()
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-col h-full bg-main-view">
|
|
<div className="flex-1 overflow-auto" ref={logsContainerRef}>
|
|
<div className="font-mono p-2">
|
|
{logs.length === 0 ? (
|
|
<div className="text-center text-main-view-fg/50 py-8">
|
|
{t('logs:noLogs')}
|
|
</div>
|
|
) : (
|
|
logs.map((log, index) => (
|
|
<div key={index} className="mb-1 flex">
|
|
<span className="text-muted-foreground mr-2">
|
|
[{formatTimestamp(log.timestamp)}]
|
|
</span>
|
|
<span
|
|
className={`mr-2 font-semibold ${getLogLevelColor(log.level)}`}
|
|
>
|
|
{log.level.toUpperCase()}
|
|
</span>
|
|
<span>{log.message}</span>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|