This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
getLauncherSource,
|
getLauncherSource,
|
||||||
listLauncherBuildEnv,
|
listLauncherBuildEnv,
|
||||||
listLauncherBuildJobs,
|
listLauncherBuildJobs,
|
||||||
|
listLauncherBuildJobsPage,
|
||||||
listLauncherVersions,
|
listLauncherVersions,
|
||||||
saveLauncherBuildEnv,
|
saveLauncherBuildEnv,
|
||||||
type LauncherSource,
|
type LauncherSource,
|
||||||
@@ -104,7 +105,7 @@ export function LauncherBuildPage() {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [range, setRange] = useState<BuildRange>('week');
|
const [range, setRange] = useState<BuildRange>('week');
|
||||||
const [hasNextPage, setHasNextPage] = useState(false);
|
const [totalJobs, setTotalJobs] = useState(0);
|
||||||
const loadingVisible = useMinimumLoading(loading);
|
const loadingVisible = useMinimumLoading(loading);
|
||||||
|
|
||||||
const activeVersion = useMemo(() => versions.find((item) => item.isActive) ?? versions[0], [versions]);
|
const activeVersion = useMemo(() => versions.find((item) => item.isActive) ?? versions[0], [versions]);
|
||||||
@@ -117,18 +118,19 @@ export function LauncherBuildPage() {
|
|||||||
const uploadPath = launcherArtifactKey(version || activeVersion?.version || '0.0.0', branch, commitSha, artifactName);
|
const uploadPath = launcherArtifactKey(version || activeVersion?.version || '0.0.0', branch, commitSha, artifactName);
|
||||||
const downloadUrl = r2PublicBaseUrl ? `${r2PublicBaseUrl.replace(/\/$/, '')}/${encodeObjectKey(uploadPath)}` : '백엔드 R2 설정 기준으로 생성됩니다.';
|
const downloadUrl = r2PublicBaseUrl ? `${r2PublicBaseUrl.replace(/\/$/, '')}/${encodeObjectKey(uploadPath)}` : '백엔드 R2 설정 기준으로 생성됩니다.';
|
||||||
const currentPage = page;
|
const currentPage = page;
|
||||||
|
const totalPages = Math.max(1, Math.ceil(totalJobs / launcherBuildJobPageSize));
|
||||||
const pagedJobs = jobs;
|
const pagedJobs = jobs;
|
||||||
const hasActiveJob = jobs.some((job) => job.status === 'PENDING' || job.status === 'RUNNING');
|
const hasActiveJob = jobs.some((job) => job.status === 'PENDING' || job.status === 'RUNNING');
|
||||||
|
|
||||||
const loadBuildJobs = (nextPage = page, nextTarget = target, nextRange = range) => (
|
const loadBuildJobs = (nextPage = page, nextTarget = target, nextRange = range) => (
|
||||||
listLauncherBuildJobs({
|
listLauncherBuildJobsPage({
|
||||||
target: nextTarget,
|
target: nextTarget,
|
||||||
page: nextPage,
|
page: nextPage,
|
||||||
limit: launcherBuildJobPageSize + 1,
|
limit: launcherBuildJobPageSize,
|
||||||
since: buildRangeSince(nextRange)
|
since: buildRangeSince(nextRange)
|
||||||
}).then((nextJobs) => {
|
}).then((result) => {
|
||||||
setJobs(nextJobs.slice(0, launcherBuildJobPageSize));
|
setJobs(result.jobs);
|
||||||
setHasNextPage(nextJobs.length > launcherBuildJobPageSize);
|
setTotalJobs(result.total);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -136,10 +138,10 @@ export function LauncherBuildPage() {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
Promise.all([
|
Promise.all([
|
||||||
listLauncherVersions(),
|
listLauncherVersions(),
|
||||||
listLauncherBuildJobs({
|
listLauncherBuildJobsPage({
|
||||||
target,
|
target,
|
||||||
page,
|
page,
|
||||||
limit: launcherBuildJobPageSize + 1,
|
limit: launcherBuildJobPageSize,
|
||||||
since: buildRangeSince(range)
|
since: buildRangeSince(range)
|
||||||
}),
|
}),
|
||||||
getLauncherSource(),
|
getLauncherSource(),
|
||||||
@@ -147,8 +149,8 @@ export function LauncherBuildPage() {
|
|||||||
])
|
])
|
||||||
.then(([nextVersions, nextJobs, nextSource, nextBuildEnv]) => {
|
.then(([nextVersions, nextJobs, nextSource, nextBuildEnv]) => {
|
||||||
setVersions(nextVersions);
|
setVersions(nextVersions);
|
||||||
setJobs(nextJobs.slice(0, launcherBuildJobPageSize));
|
setJobs(nextJobs.jobs);
|
||||||
setHasNextPage(nextJobs.length > launcherBuildJobPageSize);
|
setTotalJobs(nextJobs.total);
|
||||||
setSource(nextSource.source);
|
setSource(nextSource.source);
|
||||||
setBuildEnv(nextBuildEnv.variables ?? []);
|
setBuildEnv(nextBuildEnv.variables ?? []);
|
||||||
const nextVersion = nextVersions.find((item) => item.isActive) ?? nextVersions[0];
|
const nextVersion = nextVersions.find((item) => item.isActive) ?? nextVersions[0];
|
||||||
@@ -173,7 +175,7 @@ export function LauncherBuildPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadBuildJobs().catch((error: Error) => {
|
loadBuildJobs().catch((error: Error) => {
|
||||||
setJobs([]);
|
setJobs([]);
|
||||||
setHasNextPage(false);
|
setTotalJobs(0);
|
||||||
toast({ type: 'error', title: '빌드 작업 조회 실패', message: error.message });
|
toast({ type: 'error', title: '빌드 작업 조회 실패', message: error.message });
|
||||||
});
|
});
|
||||||
}, [target, page, range]);
|
}, [target, page, range]);
|
||||||
@@ -226,7 +228,7 @@ export function LauncherBuildPage() {
|
|||||||
setPage(1);
|
setPage(1);
|
||||||
setRange('week');
|
setRange('week');
|
||||||
setJobs((prev) => [job, ...prev].slice(0, launcherBuildJobPageSize));
|
setJobs((prev) => [job, ...prev].slice(0, launcherBuildJobPageSize));
|
||||||
setHasNextPage(jobs.length >= launcherBuildJobPageSize);
|
setTotalJobs((prev) => prev + 1);
|
||||||
setSelectedJob(job);
|
setSelectedJob(job);
|
||||||
toast({ type: 'success', title: '빌드 작업', message: '런처 빌드 작업이 생성되었습니다.' });
|
toast({ type: 'success', title: '빌드 작업', message: '런처 빌드 작업이 생성되었습니다.' });
|
||||||
})
|
})
|
||||||
@@ -385,7 +387,7 @@ export function LauncherBuildPage() {
|
|||||||
새로고침
|
새로고침
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3 p-4">
|
<div className="min-h-[638px] space-y-3 p-4">
|
||||||
{jobs.length === 0 ? (
|
{jobs.length === 0 ? (
|
||||||
<div className="flex min-h-44 items-center justify-center text-center text-sm text-muted-foreground">
|
<div className="flex min-h-44 items-center justify-center text-center text-sm text-muted-foreground">
|
||||||
빌드 작업이 없습니다.
|
빌드 작업이 없습니다.
|
||||||
@@ -429,7 +431,7 @@ export function LauncherBuildPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between gap-4 border-t border-border px-5 py-3 text-sm">
|
<div className="flex items-center justify-between gap-4 border-t border-border px-5 py-3 text-sm">
|
||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-muted-foreground">
|
||||||
{loading ? '불러오는 중' : `페이지 ${currentPage}`}
|
{loading ? '불러오는 중' : `총 ${totalJobs}건 · ${currentPage} / ${totalPages}`}
|
||||||
</span>
|
</span>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button
|
<Button
|
||||||
@@ -444,8 +446,8 @@ export function LauncherBuildPage() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="h-8 px-3 text-[13px]"
|
className="h-8 px-3 text-[13px]"
|
||||||
disabled={!hasNextPage}
|
disabled={currentPage >= totalPages}
|
||||||
onClick={() => setPage((prev) => prev + 1)}
|
onClick={() => setPage((prev) => Math.min(totalPages, prev + 1))}
|
||||||
>
|
>
|
||||||
다음
|
다음
|
||||||
<ChevronRight className="size-4" />
|
<ChevronRight className="size-4" />
|
||||||
|
|||||||
@@ -239,7 +239,26 @@ export function listLauncherBuildJobs(options?: {
|
|||||||
if (options?.limit) params.set('limit', String(options.limit));
|
if (options?.limit) params.set('limit', String(options.limit));
|
||||||
if (options?.since) params.set('since', options.since);
|
if (options?.since) params.set('since', options.since);
|
||||||
const query = params.toString() ? `?${params.toString()}` : '';
|
const query = params.toString() ? `?${params.toString()}` : '';
|
||||||
return apiRequest<LauncherBuildJob[]>(`/launcher/builds${query}`);
|
if (query) {
|
||||||
|
return apiRequest<{ jobs: LauncherBuildJob[]; total: number; page: number; limit: number }>(`/launcher/builds${query}`)
|
||||||
|
.then((result) => result.jobs);
|
||||||
|
}
|
||||||
|
return apiRequest<LauncherBuildJob[]>('/launcher/builds');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listLauncherBuildJobsPage(options: {
|
||||||
|
target: string;
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
since?: string;
|
||||||
|
}) {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
target: options.target,
|
||||||
|
page: String(options.page),
|
||||||
|
limit: String(options.limit)
|
||||||
|
});
|
||||||
|
if (options.since) params.set('since', options.since);
|
||||||
|
return apiRequest<{ jobs: LauncherBuildJob[]; total: number; page: number; limit: number }>(`/launcher/builds?${params.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLauncherBackendDeployment() {
|
export function getLauncherBackendDeployment() {
|
||||||
|
|||||||
Reference in New Issue
Block a user