fix: improve deployment progress UI and prevent duplicate deployment rows
- Redesign DeploymentProgress component: track-based layout with amber brand color, checkmarks for completed steps, user-friendly labels (Prepare, Image, Network, Launch, Verify, Activate, Live) - Delete terminal (STOPPED/FAILED) deployments before creating new ones for the same app+environment, preventing duplicate rows in the UI - Update CLAUDE.md with comprehensive key class locations, correct deploy stages, database migration reference, and REST endpoint summary Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import styles from './DeploymentProgress.module.css';
|
||||
|
||||
const STAGES = [
|
||||
{ key: 'PRE_FLIGHT', label: 'Pre-flight' },
|
||||
{ key: 'PULL_IMAGE', label: 'Pull' },
|
||||
{ key: 'PRE_FLIGHT', label: 'Prepare' },
|
||||
{ key: 'PULL_IMAGE', label: 'Image' },
|
||||
{ key: 'CREATE_NETWORK', label: 'Network' },
|
||||
{ key: 'START_REPLICAS', label: 'Start' },
|
||||
{ key: 'HEALTH_CHECK', label: 'Health' },
|
||||
{ key: 'SWAP_TRAFFIC', label: 'Swap' },
|
||||
{ key: 'COMPLETE', label: 'Done' },
|
||||
{ key: 'START_REPLICAS', label: 'Launch' },
|
||||
{ key: 'HEALTH_CHECK', label: 'Verify' },
|
||||
{ key: 'SWAP_TRAFFIC', label: 'Activate' },
|
||||
{ key: 'COMPLETE', label: 'Live' },
|
||||
];
|
||||
|
||||
interface DeploymentProgressProps {
|
||||
@@ -22,25 +22,48 @@ export function DeploymentProgress({ currentStage, failed }: DeploymentProgressP
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
{STAGES.map((stage, i) => {
|
||||
const isCompleted = i < currentIndex;
|
||||
const isActive = i === currentIndex && !failed;
|
||||
const isFailed = i === currentIndex && failed;
|
||||
<div className={styles.track}>
|
||||
<div
|
||||
className={`${styles.trackFill} ${failed ? styles.trackFailed : ''}`}
|
||||
style={{ width: `${(currentIndex / (STAGES.length - 1)) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.steps}>
|
||||
{STAGES.map((stage, i) => {
|
||||
const isCompleted = i < currentIndex;
|
||||
const isActive = i === currentIndex && !failed;
|
||||
const isFailed = i === currentIndex && failed;
|
||||
|
||||
return (
|
||||
<div key={stage.key} className={styles.step}>
|
||||
{i > 0 && (
|
||||
<div className={`${styles.line} ${isCompleted || isActive || isFailed ? styles.lineCompleted : ''}`} />
|
||||
)}
|
||||
<div className={styles.stepColumn}>
|
||||
<div className={`${styles.dot} ${isCompleted ? styles.dotCompleted : ''} ${isActive ? styles.dotActive : ''} ${isFailed ? styles.dotFailed : ''}`} />
|
||||
<span className={`${styles.label} ${isActive ? styles.labelActive : ''} ${isFailed ? styles.labelFailed : ''}`}>
|
||||
return (
|
||||
<div key={stage.key} className={styles.step}>
|
||||
<div
|
||||
className={[
|
||||
styles.dot,
|
||||
isCompleted ? styles.completed : '',
|
||||
isActive ? styles.active : '',
|
||||
isFailed ? styles.failed : '',
|
||||
].join(' ')}
|
||||
>
|
||||
{isCompleted && (
|
||||
<svg width="8" height="8" viewBox="0 0 12 12" fill="none">
|
||||
<path d="M2 6l3 3 5-5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
<span
|
||||
className={[
|
||||
styles.label,
|
||||
isCompleted ? styles.labelDone : '',
|
||||
isActive ? styles.labelActive : '',
|
||||
isFailed ? styles.labelFailed : '',
|
||||
].join(' ')}
|
||||
>
|
||||
{stage.label}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user