Add persistent deployment progress bar with minimize support.

Deployments can continue in the background via a dashboard progress bar; tables use truncation and admin migration status for cleaner layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-05-19 22:41:31 +03:30
parent 18c6abd0e8
commit 736509708b
11 changed files with 563 additions and 157 deletions
+21
View File
@@ -0,0 +1,21 @@
'use client';
import { create } from 'zustand';
interface DeployProgressState {
minimized: boolean;
focusedAppId: string | null;
minimize: (appId: string) => void;
expand: (appId?: string) => void;
}
export const useDeployProgressStore = create<DeployProgressState>((set) => ({
minimized: false,
focusedAppId: null,
minimize: (appId) => set({ minimized: true, focusedAppId: appId }),
expand: (appId) =>
set((state) => ({
minimized: false,
focusedAppId: appId ?? state.focusedAppId,
})),
}));
+25
View File
@@ -0,0 +1,25 @@
import type { Application, Deployment, DeploymentStatus } from '@/types';
import type { BuildProgress } from '@/components/build-progress-modal';
export function isDeploymentInProgress(status?: DeploymentStatus | string): boolean {
return status === 'building' || status === 'deploying' || status === 'pending';
}
export function getLatestDeployment(deployments?: Deployment[]): Deployment | undefined {
if (!deployments?.length) return undefined;
return [...deployments].sort(
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
)[0];
}
export function getAppsInProgress(apps: Application[]): Application[] {
return apps.filter((app) => {
const latest = getLatestDeployment(app.deployments);
return isDeploymentInProgress(latest?.status);
});
}
export function isActiveBuildProgress(progress: BuildProgress | null | undefined): boolean {
if (!progress) return true;
return progress.phase !== 'done' && progress.phase !== 'failed' && progress.phase !== 'cancelled';
}