Files
EJClaw/src/dashboard-render.ts
2026-03-23 06:39:26 +09:00

91 lines
2.5 KiB
TypeScript

import { STATUS_SHOW_ROOMS } from './config.js';
import type { GroupStatus } from './group-queue.js';
export function formatElapsed(ms: number): string {
const s = Math.floor(ms / 1000);
if (s < 60) return `${s}s`;
if (s < 3600) {
const m = Math.floor(s / 60);
const rem = s % 60;
return `${m}m${rem.toString().padStart(2, '0')}s`;
}
const h = Math.floor(s / 3600);
const m = Math.floor((s % 3600) / 60);
if (h < 24) return `${h}h${m.toString().padStart(2, '0')}m`;
const d = Math.floor(h / 24);
const remH = h % 24;
return `${d}d${remH}h`;
}
export function getStatusLabel(status: {
status: GroupStatus['status'];
elapsedMs: number | null;
pendingTasks: number;
}): string {
if (status.status === 'processing') {
return `처리 중 (${formatElapsed(status.elapsedMs || 0)})`;
}
if (status.status === 'waiting') {
return status.pendingTasks > 0
? `큐 대기 (태스크 ${status.pendingTasks}개)`
: '큐 대기 (메시지)';
}
return '비활성';
}
export interface DashboardRoomLine {
category: string;
categoryPosition: number;
position: number;
line: string;
}
export function renderCategorizedRoomSections(args: {
lines: DashboardRoomLine[];
showCategoryHeaders: boolean;
}): string {
const { lines, showCategoryHeaders } = args;
const categoryMap = new Map<string, DashboardRoomLine[]>();
for (const line of lines) {
if (!categoryMap.has(line.category)) {
categoryMap.set(line.category, []);
}
categoryMap.get(line.category)!.push(line);
}
const sortedCategories = [...categoryMap.entries()].sort(
([, a], [, b]) =>
(a[0]?.categoryPosition ?? Number.MAX_SAFE_INTEGER) -
(b[0]?.categoryPosition ?? Number.MAX_SAFE_INTEGER),
);
return sortedCategories
.map(([category, entries]) => {
entries.sort((a, b) => a.position - b.position);
const content = entries.map((entry) => entry.line).join('\n');
if (!showCategoryHeaders || category === '기타') {
return content;
}
return `📁 **${category}**\n${content}`;
})
.join('\n\n');
}
export function composeDashboardContent(
sections: string[],
now = new Date(),
): string {
const parts = sections.map((section) => section.trim()).filter(Boolean);
if (parts.length === 0) return '';
parts.push(
`_${now.toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit' })}_`,
);
return parts.join('\n\n');
}
export function shouldShowRoomStatus(): boolean {
return STATUS_SHOW_ROOMS;
}