mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
refactor: Remove commit actions and update badge logic in Kanban components
- Removed the onCommit action from KanbanBoard and related components to streamline functionality. - Updated CardActions to replace the Commit button with a Mark as Verified button, enhancing clarity in user interactions. - Introduced a new CardBadge component for consistent styling of badges across KanbanCard, improving code reusability and maintainability. - Refactored badge rendering logic to include a Just Finished badge, ensuring accurate representation of feature status.
This commit is contained in:
@@ -6,7 +6,6 @@ import {
|
||||
RotateCcw,
|
||||
StopCircle,
|
||||
CheckCircle2,
|
||||
GitCommit,
|
||||
FileText,
|
||||
Eye,
|
||||
Wand2,
|
||||
@@ -25,7 +24,6 @@ interface CardActionsProps {
|
||||
onForceStop?: () => void;
|
||||
onManualVerify?: () => void;
|
||||
onFollowUp?: () => void;
|
||||
onCommit?: () => void;
|
||||
onImplement?: () => void;
|
||||
onComplete?: () => void;
|
||||
onViewPlan?: () => void;
|
||||
@@ -44,7 +42,6 @@ export function CardActions({
|
||||
onForceStop,
|
||||
onManualVerify,
|
||||
onFollowUp,
|
||||
onCommit,
|
||||
onImplement,
|
||||
onComplete,
|
||||
onViewPlan,
|
||||
@@ -251,7 +248,7 @@ export function CardActions({
|
||||
<span className="truncate">Refine</span>
|
||||
</Button>
|
||||
)}
|
||||
{/* Show Verify button if PR was created (changes are committed), otherwise show Commit button */}
|
||||
{/* Show Verify button if PR was created (changes are committed), otherwise show Mark as Verified button */}
|
||||
{feature.prUrl && onManualVerify ? (
|
||||
<Button
|
||||
variant="default"
|
||||
@@ -267,20 +264,20 @@ export function CardActions({
|
||||
<CheckCircle2 className="w-3 h-3 mr-1" />
|
||||
Verify
|
||||
</Button>
|
||||
) : onCommit ? (
|
||||
) : onManualVerify ? (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="flex-1 h-7 text-[11px]"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onCommit();
|
||||
onManualVerify();
|
||||
}}
|
||||
onPointerDown={(e) => e.stopPropagation()}
|
||||
data-testid={`commit-${feature.id}`}
|
||||
data-testid={`mark-as-verified-${feature.id}`}
|
||||
>
|
||||
<GitCommit className="w-3 h-3 mr-1" />
|
||||
Commit
|
||||
<CheckCircle2 className="w-3 h-3 mr-1" />
|
||||
Mark as Verified
|
||||
</Button>
|
||||
) : null}
|
||||
</>
|
||||
@@ -338,4 +335,3 @@ export function CardActions({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,46 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { AlertCircle, Lock, Sparkles, Hand } from "lucide-react";
|
||||
import { AlertCircle, Lock, Hand, Sparkles } from "lucide-react";
|
||||
import { getBlockingDependencies } from "@/lib/dependency-resolver";
|
||||
|
||||
interface CardBadgeProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
"data-testid"?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared badge component matching the "Just Finished" badge style
|
||||
* Used for priority badges and other card badges
|
||||
*/
|
||||
function CardBadge({
|
||||
children,
|
||||
className,
|
||||
"data-testid": dataTestId,
|
||||
title,
|
||||
}: CardBadgeProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium",
|
||||
className
|
||||
)}
|
||||
data-testid={dataTestId}
|
||||
title={title}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface CardBadgesProps {
|
||||
feature: Feature;
|
||||
}
|
||||
|
||||
export function CardBadges({ feature }: CardBadgesProps) {
|
||||
const { enableDependencyBlocking, features } = useAppStore();
|
||||
const [currentTime, setCurrentTime] = useState(() => Date.now());
|
||||
|
||||
// Calculate blocking dependencies (if feature is in backlog and has incomplete dependencies)
|
||||
const blockingDependencies = useMemo(() => {
|
||||
@@ -26,50 +56,13 @@ export function CardBadges({ feature }: CardBadgesProps) {
|
||||
return getBlockingDependencies(feature, features);
|
||||
}, [enableDependencyBlocking, feature, features]);
|
||||
|
||||
const isJustFinished = useMemo(() => {
|
||||
if (
|
||||
!feature.justFinishedAt ||
|
||||
feature.status !== "waiting_approval" ||
|
||||
feature.error
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const finishedTime = new Date(feature.justFinishedAt).getTime();
|
||||
const twoMinutes = 2 * 60 * 1000;
|
||||
return currentTime - finishedTime < twoMinutes;
|
||||
}, [feature.justFinishedAt, feature.status, feature.error, currentTime]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!feature.justFinishedAt || feature.status !== "waiting_approval") {
|
||||
return;
|
||||
}
|
||||
|
||||
const finishedTime = new Date(feature.justFinishedAt).getTime();
|
||||
const twoMinutes = 2 * 60 * 1000;
|
||||
const timeRemaining = twoMinutes - (currentTime - finishedTime);
|
||||
|
||||
if (timeRemaining <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const interval = setInterval(() => {
|
||||
setCurrentTime(Date.now());
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [feature.justFinishedAt, feature.status, currentTime]);
|
||||
// Status badges row (error, blocked, just finished)
|
||||
// Status badges row (error, blocked)
|
||||
const showStatusBadges =
|
||||
feature.error ||
|
||||
(blockingDependencies.length > 0 &&
|
||||
!feature.error &&
|
||||
!feature.skipTests &&
|
||||
feature.status === "backlog") ||
|
||||
isJustFinished;
|
||||
feature.status === "backlog");
|
||||
|
||||
if (!showStatusBadges) {
|
||||
return null;
|
||||
@@ -117,13 +110,12 @@ export function CardBadges({ feature }: CardBadgesProps) {
|
||||
<Lock className="w-3 h-3" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side="bottom"
|
||||
className="text-xs max-w-[250px]"
|
||||
>
|
||||
<TooltipContent side="bottom" className="text-xs max-w-[250px]">
|
||||
<p className="font-medium mb-1">
|
||||
Blocked by {blockingDependencies.length} incomplete{" "}
|
||||
{blockingDependencies.length === 1 ? "dependency" : "dependencies"}
|
||||
{blockingDependencies.length === 1
|
||||
? "dependency"
|
||||
: "dependencies"}
|
||||
</p>
|
||||
<p className="text-muted-foreground">
|
||||
{blockingDependencies
|
||||
@@ -137,21 +129,6 @@ export function CardBadges({ feature }: CardBadgesProps) {
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)}
|
||||
|
||||
{/* Just Finished badge */}
|
||||
{isJustFinished && (
|
||||
<div
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium",
|
||||
"bg-[var(--status-success-bg)] border-[var(--status-success)]/40 text-[var(--status-success)]",
|
||||
"animate-pulse"
|
||||
)}
|
||||
data-testid={`just-finished-badge-${feature.id}`}
|
||||
title="Agent just finished working on this feature"
|
||||
>
|
||||
<Sparkles className="w-3 h-3" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -161,11 +138,49 @@ interface PriorityBadgesProps {
|
||||
}
|
||||
|
||||
export function PriorityBadges({ feature }: PriorityBadgesProps) {
|
||||
const [currentTime, setCurrentTime] = useState(() => Date.now());
|
||||
|
||||
const isJustFinished = useMemo(() => {
|
||||
if (
|
||||
!feature.justFinishedAt ||
|
||||
feature.status !== "waiting_approval" ||
|
||||
feature.error
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const finishedTime = new Date(feature.justFinishedAt).getTime();
|
||||
const twoMinutes = 2 * 60 * 1000;
|
||||
return currentTime - finishedTime < twoMinutes;
|
||||
}, [feature.justFinishedAt, feature.status, feature.error, currentTime]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!feature.justFinishedAt || feature.status !== "waiting_approval") {
|
||||
return;
|
||||
}
|
||||
|
||||
const finishedTime = new Date(feature.justFinishedAt).getTime();
|
||||
const twoMinutes = 2 * 60 * 1000;
|
||||
const timeRemaining = twoMinutes - (currentTime - finishedTime);
|
||||
|
||||
if (timeRemaining <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const interval = setInterval(() => {
|
||||
setCurrentTime(Date.now());
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [feature.justFinishedAt, feature.status, currentTime]);
|
||||
|
||||
const showPriorityBadges =
|
||||
feature.priority ||
|
||||
(feature.skipTests &&
|
||||
!feature.error &&
|
||||
feature.status === "backlog");
|
||||
(feature.skipTests && !feature.error && feature.status === "backlog") ||
|
||||
isJustFinished;
|
||||
|
||||
if (!showPriorityBadges) {
|
||||
return null;
|
||||
@@ -178,24 +193,32 @@ export function PriorityBadges({ feature }: PriorityBadgesProps) {
|
||||
<TooltipProvider delayDuration={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
<CardBadge
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center gap-1 rounded-full border-2 px-1.5 py-0.5 text-[10px] font-bold",
|
||||
"bg-opacity-90 border rounded-[6px] px-1.5 py-0.5 flex items-center justify-center border-[1.5px] w-5 h-5", // badge style from example
|
||||
feature.priority === 1 &&
|
||||
"bg-red-500/20 text-red-500 border-red-500/50",
|
||||
"bg-[var(--status-error-bg)] border-[var(--status-error)]/40 text-[var(--status-error)]",
|
||||
feature.priority === 2 &&
|
||||
"bg-yellow-500/20 text-yellow-500 border-yellow-500/50",
|
||||
"bg-[var(--status-warning-bg)] border-[var(--status-warning)]/40 text-[var(--status-warning)]",
|
||||
feature.priority === 3 &&
|
||||
"bg-blue-500/20 text-blue-500 border-blue-500/50"
|
||||
"bg-[var(--status-info-bg)] border-[var(--status-info)]/40 text-[var(--status-info)]"
|
||||
)}
|
||||
data-testid={`priority-badge-${feature.id}`}
|
||||
>
|
||||
{feature.priority === 1
|
||||
? "H"
|
||||
: feature.priority === 2
|
||||
? "M"
|
||||
: "L"}
|
||||
</div>
|
||||
{feature.priority === 1 ? (
|
||||
<span className="font-bold text-xs flex items-center gap-0.5">
|
||||
H
|
||||
</span>
|
||||
) : feature.priority === 2 ? (
|
||||
<span className="font-bold text-xs flex items-center gap-0.5">
|
||||
M
|
||||
</span>
|
||||
) : (
|
||||
<span className="font-bold text-xs flex items-center gap-0.5">
|
||||
L
|
||||
</span>
|
||||
)}
|
||||
</CardBadge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" className="text-xs">
|
||||
<p>
|
||||
@@ -210,29 +233,34 @@ export function PriorityBadges({ feature }: PriorityBadgesProps) {
|
||||
</TooltipProvider>
|
||||
)}
|
||||
{/* Manual verification badge */}
|
||||
{feature.skipTests &&
|
||||
!feature.error &&
|
||||
feature.status === "backlog" && (
|
||||
<TooltipProvider delayDuration={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 rounded-full border-2 px-1.5 py-0.5 text-[10px] font-bold",
|
||||
"bg-[var(--status-warning-bg)] border-[var(--status-warning)]/50 text-[var(--status-warning)]"
|
||||
)}
|
||||
data-testid={`skip-tests-badge-${feature.id}`}
|
||||
>
|
||||
<Hand className="w-3 h-3" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" className="text-xs">
|
||||
<p>Manual verification required</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)}
|
||||
{feature.skipTests && !feature.error && feature.status === "backlog" && (
|
||||
<TooltipProvider delayDuration={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<CardBadge
|
||||
className="bg-[var(--status-warning-bg)] border-[var(--status-warning)]/40 text-[var(--status-warning)]"
|
||||
data-testid={`skip-tests-badge-${feature.id}`}
|
||||
>
|
||||
<Hand className="w-3 h-3" />
|
||||
</CardBadge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" className="text-xs">
|
||||
<p>Manual verification required</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)}
|
||||
|
||||
{/* Just Finished badge */}
|
||||
{isJustFinished && (
|
||||
<CardBadge
|
||||
className="bg-[var(--status-success-bg)] border-[var(--status-success)]/40 text-[var(--status-success)] animate-pulse"
|
||||
data-testid={`just-finished-badge-${feature.id}`}
|
||||
title="Agent just finished working on this feature"
|
||||
>
|
||||
<Sparkles className="w-3 h-3" />
|
||||
</CardBadge>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ interface KanbanCardProps {
|
||||
onManualVerify?: () => void;
|
||||
onMoveBackToInProgress?: () => void;
|
||||
onFollowUp?: () => void;
|
||||
onCommit?: () => void;
|
||||
onImplement?: () => void;
|
||||
onComplete?: () => void;
|
||||
onViewPlan?: () => void;
|
||||
@@ -48,7 +47,6 @@ export const KanbanCard = memo(function KanbanCard({
|
||||
onManualVerify,
|
||||
onMoveBackToInProgress: _onMoveBackToInProgress,
|
||||
onFollowUp,
|
||||
onCommit,
|
||||
onImplement,
|
||||
onComplete,
|
||||
onViewPlan,
|
||||
@@ -198,7 +196,6 @@ export const KanbanCard = memo(function KanbanCard({
|
||||
onForceStop={onForceStop}
|
||||
onManualVerify={onManualVerify}
|
||||
onFollowUp={onFollowUp}
|
||||
onCommit={onCommit}
|
||||
onImplement={onImplement}
|
||||
onComplete={onComplete}
|
||||
onViewPlan={onViewPlan}
|
||||
|
||||
@@ -194,7 +194,6 @@ export function KanbanBoard({
|
||||
onMoveBackToInProgress(feature)
|
||||
}
|
||||
onFollowUp={() => onFollowUp(feature)}
|
||||
onCommit={() => onCommit(feature)}
|
||||
onComplete={() => onComplete(feature)}
|
||||
onImplement={() => onImplement(feature)}
|
||||
onViewPlan={() => onViewPlan(feature)}
|
||||
|
||||
Reference in New Issue
Block a user