47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
|
|
import { LogViewer } from '@cameleer/design-system';
|
||
|
|
import { useStartupLogs } from '../api/queries/logs';
|
||
|
|
import type { Deployment } from '../api/queries/admin/apps';
|
||
|
|
import styles from './StartupLogPanel.module.css';
|
||
|
|
|
||
|
|
interface StartupLogPanelProps {
|
||
|
|
deployment: Deployment;
|
||
|
|
appSlug: string;
|
||
|
|
envSlug: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function StartupLogPanel({ deployment, appSlug, envSlug }: StartupLogPanelProps) {
|
||
|
|
const isStarting = deployment.status === 'STARTING';
|
||
|
|
const isFailed = deployment.status === 'FAILED';
|
||
|
|
|
||
|
|
const { data } = useStartupLogs(appSlug, envSlug, deployment.createdAt, isStarting);
|
||
|
|
|
||
|
|
const entries = data?.data ?? [];
|
||
|
|
|
||
|
|
if (entries.length === 0 && !isStarting) return null;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className={styles.panel}>
|
||
|
|
<div className={styles.header}>
|
||
|
|
<div className={styles.headerLeft}>
|
||
|
|
<span className={styles.title}>Startup Logs</span>
|
||
|
|
{isStarting && (
|
||
|
|
<>
|
||
|
|
<span className={`${styles.badge} ${styles.badgeLive}`}>● live</span>
|
||
|
|
<span className={styles.pollingHint}>polling every 3s</span>
|
||
|
|
</>
|
||
|
|
)}
|
||
|
|
{isFailed && (
|
||
|
|
<span className={`${styles.badge} ${styles.badgeStopped}`}>stopped</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<span className={styles.lineCount}>{entries.length} lines</span>
|
||
|
|
</div>
|
||
|
|
{entries.length > 0 ? (
|
||
|
|
<LogViewer entries={entries} maxHeight={300} />
|
||
|
|
) : (
|
||
|
|
<div className={styles.empty}>Waiting for container output...</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|