mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-05 13:47:59 +08:00
Remove TaskListItem and TaskLogsModal components along with their adapter
This commit is contained in:
@@ -1,139 +0,0 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { ScheduledTaskEntity } from '@shared/data/types/agent'
|
||||
import { Popconfirm, Tag } from 'antd'
|
||||
import { Clock, Edit2, History, Pause, Play, Trash2 } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type TaskListItemProps = {
|
||||
task: ScheduledTaskEntity
|
||||
onEdit: (task: ScheduledTaskEntity) => void
|
||||
onToggleStatus: (task: ScheduledTaskEntity) => void
|
||||
onDelete: (taskId: string) => void
|
||||
onRun: (task: ScheduledTaskEntity) => void
|
||||
onViewLogs: (task: ScheduledTaskEntity) => void
|
||||
}
|
||||
|
||||
const statusDotColors: Record<string, string> = {
|
||||
active: 'bg-green-500',
|
||||
paused: 'bg-yellow-500',
|
||||
completed: 'bg-blue-500'
|
||||
}
|
||||
|
||||
const scheduleTypeConfig: Record<string, { label: string; color: string }> = {
|
||||
cron: { label: 'Cron', color: 'purple' },
|
||||
interval: { label: 'Interval', color: 'blue' },
|
||||
once: { label: 'Once', color: 'orange' }
|
||||
}
|
||||
|
||||
const IconButton: FC<{
|
||||
icon: React.ReactNode
|
||||
tooltip: string
|
||||
onClick: () => void
|
||||
danger?: boolean
|
||||
}> = ({ icon, tooltip, onClick, danger }) => (
|
||||
<Tooltip title={tooltip}>
|
||||
<button
|
||||
type="button"
|
||||
className={`flex h-7 w-7 items-center justify-center rounded-md transition-colors hover:bg-[var(--color-muted)] ${danger ? 'text-red-500 hover:text-red-600' : 'text-foreground-400 hover:text-foreground'}`}
|
||||
onClick={onClick}>
|
||||
{icon}
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
const TaskListItem: FC<TaskListItemProps> = ({ task, onEdit, onToggleStatus, onDelete, onRun, onViewLogs }) => {
|
||||
const { t, i18n } = useTranslation()
|
||||
const locale = i18n.language
|
||||
|
||||
const formatScheduleValue = () => {
|
||||
if (task.scheduleType === 'cron') return task.scheduleValue
|
||||
if (task.scheduleType === 'interval') return `${task.scheduleValue} min`
|
||||
if (task.scheduleType === 'once' && task.scheduleValue) {
|
||||
return new Date(task.scheduleValue).toLocaleString(locale)
|
||||
}
|
||||
return task.scheduleValue
|
||||
}
|
||||
|
||||
const formatTime = (iso: string | null | undefined) => {
|
||||
if (!iso) return '-'
|
||||
const d = new Date(iso)
|
||||
const now = Date.now()
|
||||
const diff = now - d.getTime()
|
||||
|
||||
if (diff < 60_000) return t('agent.cherryClaw.tasks.logs.justNow', 'just now')
|
||||
if (diff < 3600_000) return t('agent.cherryClaw.tasks.time.minutesAgo', { count: Math.floor(diff / 60_000) })
|
||||
if (diff < 86400_000) return t('agent.cherryClaw.tasks.time.hoursAgo', { count: Math.floor(diff / 3600_000) })
|
||||
return d.toLocaleDateString(locale)
|
||||
}
|
||||
|
||||
const isCompleted = task.status === 'completed'
|
||||
const typeConfig = scheduleTypeConfig[task.scheduleType] ?? { label: task.scheduleType, color: 'default' }
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between rounded-lg border border-[var(--color-border)] p-3">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={`inline-block h-2 w-2 shrink-0 rounded-full ${statusDotColors[task.status] ?? 'bg-gray-400'}`}
|
||||
/>
|
||||
<span className="truncate font-medium text-sm">{task.name}</span>
|
||||
</div>
|
||||
<div className="mt-1.5 flex flex-wrap items-center gap-2 text-xs">
|
||||
<Tag color={typeConfig.color} className="!mr-0">
|
||||
{typeConfig.label}
|
||||
</Tag>
|
||||
<span className="text-foreground-400">
|
||||
<Clock size={11} className="mr-0.5 inline" />
|
||||
{formatScheduleValue()}
|
||||
</span>
|
||||
{task.nextRun && <span className="text-foreground-400">→ Next: {formatTime(task.nextRun)}</span>}
|
||||
{task.lastRun && <span className="text-foreground-400">Last: {formatTime(task.lastRun)}</span>}
|
||||
</div>
|
||||
{task.lastResult && (
|
||||
<Tooltip title={task.lastResult}>
|
||||
<div className="mt-1 max-w-[400px] truncate text-foreground-500 text-xs">{task.lastResult}</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="ml-3 flex shrink-0 items-center gap-0.5">
|
||||
{!isCompleted && (
|
||||
<IconButton icon={<Play size={14} />} tooltip={t('agent.cherryClaw.tasks.run')} onClick={() => onRun(task)} />
|
||||
)}
|
||||
<IconButton
|
||||
icon={<History size={14} />}
|
||||
tooltip={t('agent.cherryClaw.tasks.logs.label')}
|
||||
onClick={() => onViewLogs(task)}
|
||||
/>
|
||||
{!isCompleted && (
|
||||
<IconButton
|
||||
icon={<Edit2 size={14} />}
|
||||
tooltip={t('agent.cherryClaw.tasks.edit')}
|
||||
onClick={() => onEdit(task)}
|
||||
/>
|
||||
)}
|
||||
{!isCompleted && (
|
||||
<IconButton
|
||||
icon={<Pause size={14} />}
|
||||
tooltip={task.status === 'active' ? t('agent.cherryClaw.tasks.pause') : t('agent.cherryClaw.tasks.resume')}
|
||||
onClick={() => onToggleStatus(task)}
|
||||
/>
|
||||
)}
|
||||
<Popconfirm
|
||||
title={t('agent.cherryClaw.tasks.delete.confirm')}
|
||||
onConfirm={() => onDelete(task.id)}
|
||||
okText={t('agent.cherryClaw.tasks.delete.label')}
|
||||
cancelText={t('agent.cherryClaw.tasks.cancel')}>
|
||||
<IconButton
|
||||
icon={<Trash2 size={14} />}
|
||||
tooltip={t('agent.cherryClaw.tasks.delete.label')}
|
||||
onClick={() => {}}
|
||||
danger
|
||||
/>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TaskListItem
|
||||
@@ -1,80 +0,0 @@
|
||||
import { Spinner } from '@cherrystudio/ui'
|
||||
import { useTaskLogs } from '@renderer/hooks/agents/useTasks'
|
||||
import { Modal, Table, Tag } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type TaskLogsModalProps = {
|
||||
open: boolean
|
||||
agentId: string | null
|
||||
taskId: string | null
|
||||
taskName: string
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const TaskLogsModal: FC<TaskLogsModalProps> = ({ open, agentId, taskId, taskName, onClose }) => {
|
||||
const { t, i18n } = useTranslation()
|
||||
const locale = i18n.language
|
||||
const { logs, isLoading, error } = useTaskLogs(open ? agentId : null, open ? taskId : null)
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t('agent.cherryClaw.tasks.logs.runAt'),
|
||||
dataIndex: 'run_at',
|
||||
key: 'run_at',
|
||||
width: 180,
|
||||
render: (val: string) => new Date(val).toLocaleString(locale)
|
||||
},
|
||||
{
|
||||
title: t('agent.cherryClaw.tasks.logs.duration'),
|
||||
dataIndex: 'duration_ms',
|
||||
key: 'duration_ms',
|
||||
width: 100,
|
||||
render: (val: number) => {
|
||||
if (val < 1000) return `${val}ms`
|
||||
if (val < 60_000) return `${(val / 1000).toFixed(1)}s`
|
||||
return `${(val / 60_000).toFixed(1)}m`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: t('agent.cherryClaw.tasks.logs.status'),
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 80,
|
||||
render: (val: string) => <Tag color={val === 'success' ? 'green' : 'red'}>{val}</Tag>
|
||||
},
|
||||
{
|
||||
title: t('agent.cherryClaw.tasks.logs.result'),
|
||||
dataIndex: 'result',
|
||||
key: 'result',
|
||||
ellipsis: true,
|
||||
render: (val: string | null, record: any) =>
|
||||
record.status === 'error' ? <span className="text-red-500">{record.error}</span> : (val ?? '-')
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
title={`${t('agent.cherryClaw.tasks.logs.label')} — ${taskName}`}
|
||||
onCancel={onClose}
|
||||
footer={null}
|
||||
width={700}
|
||||
transitionName="animation-move-down"
|
||||
destroyOnClose>
|
||||
{isLoading ? (
|
||||
<div className="flex justify-center py-8">
|
||||
<Spinner text={t('common.loading')} />
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="py-8 text-center text-red-400">{t('agent.cherryClaw.tasks.logs.loadError')}</div>
|
||||
) : logs.length === 0 ? (
|
||||
<div className="py-8 text-center text-gray-400">{t('agent.cherryClaw.tasks.logs.empty')}</div>
|
||||
) : (
|
||||
<Table dataSource={logs} columns={columns} rowKey="id" size="small" pagination={false} scroll={{ y: 400 }} />
|
||||
)}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default TaskLogsModal
|
||||
@@ -1 +0,0 @@
|
||||
export {}
|
||||
Reference in New Issue
Block a user