diff --git a/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx b/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx index d8814dfa..a85b7188 100644 --- a/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx +++ b/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx @@ -12,7 +12,8 @@ import { import { executionProcessesApi } from '@/lib/api.ts'; import { ProfileVariantBadge } from '@/components/common/ProfileVariantBadge.tsx'; import { useExecutionProcesses } from '@/hooks/useExecutionProcesses'; -import ProcessLogsViewer from './ProcessLogsViewer'; +import { useLogStream } from '@/hooks/useLogStream'; +import { ProcessLogsViewerContent } from './ProcessLogsViewer'; import type { ExecutionProcessStatus, ExecutionProcess } from 'shared/types'; import { useProcessSelection } from '@/contexts/ProcessSelectionContext'; @@ -36,12 +37,33 @@ function ProcessesTab({ attemptId }: ProcessesTabProps) { const [localProcessDetails, setLocalProcessDetails] = useState< Record >({}); + const [copied, setCopied] = useState(false); + + const selectedProcess = selectedProcessId + ? localProcessDetails[selectedProcessId] || + executionProcessesById[selectedProcessId] + : null; + + const { logs, error: logsError } = useLogStream(selectedProcess?.id ?? ''); useEffect(() => { setLocalProcessDetails({}); setLoadingProcessId(null); }, [attemptId]); + const handleCopyLogs = useCallback(async () => { + if (logs.length === 0) return; + + const text = logs.map((entry) => entry.content).join('\n'); + try { + await navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.warn('Copy to clipboard failed:', err); + } + }, [logs]); + const getStatusIcon = (status: ExecutionProcessStatus) => { switch (status) { case 'running': @@ -126,10 +148,6 @@ function ProcessesTab({ attemptId }: ProcessesTabProps) { } }; - const selectedProcess = selectedProcessId - ? localProcessDetails[selectedProcessId] || - executionProcessesById[selectedProcessId] - : null; const { isProcessGreyed } = useRetryUi(); if (!attemptId) { @@ -261,17 +279,32 @@ function ProcessesTab({ attemptId }: ProcessesTabProps) {

{t('processes.detailsTitle')}

- +
+ + +
{selectedProcess ? ( - + ) : loadingProcessId === selectedProcessId ? (

{t('processes.loadingDetails')}

diff --git a/frontend/src/i18n/locales/en/tasks.json b/frontend/src/i18n/locales/en/tasks.json index ce25a9d8..4627f725 100644 --- a/frontend/src/i18n/locales/en/tasks.json +++ b/frontend/src/i18n/locales/en/tasks.json @@ -126,7 +126,9 @@ "detailsTitle": "Process Details", "backToList": "Back to list", "loadingDetails": "Loading process details...", - "errorLoadingDetails": "Failed to load process details. Please try again." + "errorLoadingDetails": "Failed to load process details. Please try again.", + "copyLogs": "Copy logs", + "logsCopied": "Copied!" }, "taskHeader": { "editTask": "Edit task", diff --git a/frontend/src/i18n/locales/es/tasks.json b/frontend/src/i18n/locales/es/tasks.json index 7d6f7f66..7f448013 100644 --- a/frontend/src/i18n/locales/es/tasks.json +++ b/frontend/src/i18n/locales/es/tasks.json @@ -304,7 +304,9 @@ "processId": "Process ID: {{id}}", "reconnecting": "Reconnecting...", "selectAttempt": "Select an attempt to view execution processes.", - "started": "Started: {{date}}" + "started": "Started: {{date}}", + "copyLogs": "Copiar registros", + "logsCopied": "¡Copiado!" }, "rebase": { "common": { diff --git a/frontend/src/i18n/locales/ja/tasks.json b/frontend/src/i18n/locales/ja/tasks.json index fd2484f2..62de801c 100644 --- a/frontend/src/i18n/locales/ja/tasks.json +++ b/frontend/src/i18n/locales/ja/tasks.json @@ -304,7 +304,9 @@ "processId": "Process ID: {{id}}", "reconnecting": "Reconnecting...", "selectAttempt": "Select an attempt to view execution processes.", - "started": "Started: {{date}}" + "started": "Started: {{date}}", + "copyLogs": "ログをコピー", + "logsCopied": "コピーしました!" }, "rebase": { "common": { diff --git a/frontend/src/i18n/locales/ko/tasks.json b/frontend/src/i18n/locales/ko/tasks.json index 23f92593..c3962ee9 100644 --- a/frontend/src/i18n/locales/ko/tasks.json +++ b/frontend/src/i18n/locales/ko/tasks.json @@ -304,7 +304,9 @@ "processId": "Process ID: {{id}}", "reconnecting": "Reconnecting...", "selectAttempt": "Select an attempt to view execution processes.", - "started": "Started: {{date}}" + "started": "Started: {{date}}", + "copyLogs": "로그 복사", + "logsCopied": "복사됨!" }, "rebase": { "common": {