Files
studio-admin-fe/src/pages/common-apps/common-app-utils.ts
T
chyoo 6dd1166c7a
ci/woodpecker/push/woodpecker Pipeline was successful
connect tailscale node status through platform gateway
2026-07-08 18:02:10 +09:00

98 lines
3.6 KiB
TypeScript

export const COMMON_APP_NAMESPACE = 'studio-system';
export type CommonAppComponent = {
key: string;
name: string;
description: string;
repository: string;
kind: 'Deployment';
workloadName: string;
serviceName?: string;
};
export const commonAppComponents: CommonAppComponent[] = [
{
key: 'studio-admin-fe',
name: 'Admin FE',
description: '관리자 웹 콘솔 프론트엔드입니다.',
repository: 'studio/studio-admin-fe',
kind: 'Deployment',
workloadName: 'studio-admin-fe',
serviceName: 'studio-admin-fe'
},
{
key: 'studio-admin-be',
name: 'Admin BE',
description: '관리자 웹 콘솔 API 서버입니다.',
repository: 'studio/studio-admin-be',
kind: 'Deployment',
workloadName: 'studio-admin-be',
serviceName: 'studio-admin-be'
},
{
key: 'studio-auth-be',
name: 'Auth BE',
description: '공통 인증, 사용자, 라이센스 API 서버입니다.',
repository: 'studio/studio-auth-be',
kind: 'Deployment',
workloadName: 'studio-auth-be',
serviceName: 'studio-auth-be'
},
{
key: 'platform-gateway',
name: 'Platform Gateway',
description: 'Headscale, Agent, 클러스터 연동용 게이트웨이입니다.',
repository: 'studio/platform-gateway',
kind: 'Deployment',
workloadName: 'platform-gateway',
serviceName: 'platform-gateway'
}
];
export function formatPipelineTime(value?: number | null) {
if (!value) return '-';
const ms = value < 10_000_000_000 ? value * 1000 : value;
return new Date(ms).toLocaleString();
}
export function formatPipelineRelativeTime(value?: number | null) {
if (!value) return '-';
const ms = value < 10_000_000_000 ? value * 1000 : value;
const seconds = Math.max(0, Math.floor((Date.now() - ms) / 1000));
if (seconds < 60) return '방금 전';
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes}분 전`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}시간 전`;
const days = Math.floor(hours / 24);
if (days < 30) return `${days}일 전`;
return new Intl.DateTimeFormat('ko-KR', { month: 'short', day: 'numeric' }).format(new Date(ms));
}
export function formatRepositoryName(repository: string) {
return repository.replace('/', ' / ');
}
export function pipelineStatusTone(status?: string | null): 'green' | 'amber' | 'red' | 'blue' | 'neutral' {
const value = (status ?? '').toLowerCase();
if (['success', 'succeeded', 'passed'].includes(value)) return 'green';
if (['running', 'started'].includes(value)) return 'blue';
if (['pending', 'queued', 'blocked', 'created'].includes(value)) return 'amber';
if (['failure', 'failed', 'error', 'killed', 'declined'].includes(value)) return 'red';
return 'neutral';
}
export function pipelineStatusDotClass(status?: string | null) {
const value = (status ?? '').toLowerCase();
if (['success', 'succeeded', 'passed'].includes(value)) return 'bg-emerald-400 shadow-[0_0_0_3px_rgba(52,211,153,0.15)]';
if (['running', 'started'].includes(value)) return 'bg-sky-400 shadow-[0_0_0_3px_rgba(56,189,248,0.15)]';
if (['pending', 'queued', 'blocked', 'created'].includes(value)) return 'bg-amber-400 shadow-[0_0_0_3px_rgba(251,191,36,0.15)]';
if (['failure', 'failed', 'error', 'killed', 'declined'].includes(value)) return 'bg-rose-400 shadow-[0_0_0_3px_rgba(251,113,133,0.15)]';
return 'bg-muted-foreground/60';
}
export function isActivePipelineStatus(status?: string | null) {
const value = (status ?? '').toLowerCase();
return ['running', 'started', 'pending', 'queued', 'blocked', 'created'].includes(value);
}