merge develop into release
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-07-09 11:27:42 +09:00
+49 -34
View File
@@ -1,5 +1,5 @@
import { Loader2, RotateCcw } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Badge, Button, Card, CardHeader } from '../../components/ui';
import { useToast } from '../../components/toast';
import { PageTitle } from '../../layout/AppLayout';
@@ -30,6 +30,45 @@ export function CommonAppBuildPage() {
);
const selectedPipeline = pipelines.find((pipeline) => pipeline.repoId === selectedRepoId) ?? pipelines[0];
const refreshHistory = useCallback((repoId: string, page: number, silent = false) => {
if (!repoId) {
setHistory([]);
setHistoryTotal(null);
setHistoryTotalPages(null);
setHasNextHistoryPage(false);
return () => undefined;
}
let canceled = false;
if (!silent) setHistoryLoading(true);
listCommonAppPipelineHistory(repoId, page, historyPageSize)
.then((result) => {
if (canceled) return;
setHistory(result.pipelines ?? []);
setHistoryTotal(result.total ?? null);
setHistoryTotalPages(result.totalPages ?? null);
setHasNextHistoryPage(Boolean(result.hasNext));
})
.catch((error: Error) => {
if (canceled) return;
if (!silent) {
setHistory([]);
setHistoryTotal(null);
setHistoryTotalPages(null);
setHasNextHistoryPage(false);
toast({ type: 'error', title: '파이프라인 이력 조회 실패', message: error.message });
}
})
.finally(() => {
if (!canceled && !silent) setHistoryLoading(false);
});
return () => {
canceled = true;
};
}, [toast]);
const refresh = (silent = false) => {
if (!silent) setLoading(true);
listCommonAppPipelines()
@@ -63,40 +102,16 @@ export function CommonAppBuildPage() {
}, [selectedRepoId]);
useEffect(() => {
let canceled = false;
if (!selectedRepoId) {
setHistory([]);
setHistoryTotal(null);
setHistoryTotalPages(null);
setHasNextHistoryPage(false);
return;
}
return refreshHistory(selectedRepoId, historyPage);
}, [historyPage, refreshHistory, selectedRepoId]);
setHistoryLoading(true);
listCommonAppPipelineHistory(selectedRepoId, historyPage, historyPageSize)
.then((result) => {
if (canceled) return;
setHistory(result.pipelines ?? []);
setHistoryTotal(result.total ?? null);
setHistoryTotalPages(result.totalPages ?? null);
setHasNextHistoryPage(Boolean(result.hasNext));
})
.catch((error: Error) => {
if (canceled) return;
setHistory([]);
setHistoryTotal(null);
setHistoryTotalPages(null);
setHasNextHistoryPage(false);
toast({ type: 'error', title: '파이프라인 이력 조회 실패', message: error.message });
})
.finally(() => {
if (!canceled) setHistoryLoading(false);
});
useEffect(() => {
const timer = window.setInterval(() => {
if (selectedRepoId && historyPage === 1) refreshHistory(selectedRepoId, 1, true);
}, 5000);
return () => {
canceled = true;
};
}, [historyPage, selectedRepoId, toast]);
return () => window.clearInterval(timer);
}, [historyPage, refreshHistory, selectedRepoId]);
return (
<>
@@ -146,7 +161,7 @@ export function CommonAppBuildPage() {
<div className="flex min-w-0 items-center gap-2">
<span className={cn('size-2.5 shrink-0 rounded-full', pipelineStatusDotClass(pipeline.status))} />
<p className="truncate text-sm font-semibold">{formatRepositoryName(pipeline.repository)}</p>
{isActivePipelineStatus(pipeline.status) ? <Loader2 className="size-3.5 shrink-0 animate-spin text-sky-300" /> : null}
{isActivePipelineStatus(pipeline.status) ? <Loader2 className="size-3.5 shrink-0 animate-spin text-white/90" /> : null}
</div>
<p className="mt-1 truncate text-sm text-muted-foreground">
<span className="mr-1 font-mono text-xs">#{pipeline.number ?? '-'}</span>