mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 21:03:08 +00:00
adding button to make when creating a new feature
This commit is contained in:
@@ -523,6 +523,29 @@ export function BoardView() {
|
|||||||
[handleAddFeature, handleStartImplementation, defaultSkipTests]
|
[handleAddFeature, handleStartImplementation, defaultSkipTests]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Handler for "Make" button - creates a feature and immediately starts it
|
||||||
|
const handleAddAndStartFeature = useCallback(
|
||||||
|
async (featureData: Parameters<typeof handleAddFeature>[0]) => {
|
||||||
|
await handleAddFeature(featureData);
|
||||||
|
|
||||||
|
// Find the newly created feature and start it
|
||||||
|
setTimeout(async () => {
|
||||||
|
const latestFeatures = useAppStore.getState().features;
|
||||||
|
const newFeature = latestFeatures.find(
|
||||||
|
(f) =>
|
||||||
|
f.status === 'backlog' &&
|
||||||
|
f.description === featureData.description &&
|
||||||
|
f.branchName === featureData.branchName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newFeature) {
|
||||||
|
await handleStartImplementation(newFeature);
|
||||||
|
}
|
||||||
|
}, FEATURE_CREATION_SETTLE_DELAY_MS);
|
||||||
|
},
|
||||||
|
[handleAddFeature, handleStartImplementation]
|
||||||
|
);
|
||||||
|
|
||||||
// Client-side auto mode: periodically check for backlog items and move them to in-progress
|
// Client-side auto mode: periodically check for backlog items and move them to in-progress
|
||||||
// Use a ref to track the latest auto mode state so async operations always check the current value
|
// Use a ref to track the latest auto mode state so async operations always check the current value
|
||||||
const autoModeRunningRef = useRef(autoMode.isRunning);
|
const autoModeRunningRef = useRef(autoMode.isRunning);
|
||||||
@@ -1137,6 +1160,7 @@ export function BoardView() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onAdd={handleAddFeature}
|
onAdd={handleAddFeature}
|
||||||
|
onAddAndStart={handleAddAndStartFeature}
|
||||||
categorySuggestions={categorySuggestions}
|
categorySuggestions={categorySuggestions}
|
||||||
branchSuggestions={branchSuggestions}
|
branchSuggestions={branchSuggestions}
|
||||||
branchCardCounts={branchCardCounts}
|
branchCardCounts={branchCardCounts}
|
||||||
|
|||||||
@@ -19,7 +19,14 @@ import {
|
|||||||
FeatureTextFilePath as DescriptionTextFilePath,
|
FeatureTextFilePath as DescriptionTextFilePath,
|
||||||
ImagePreviewMap,
|
ImagePreviewMap,
|
||||||
} from '@/components/ui/description-image-dropzone';
|
} from '@/components/ui/description-image-dropzone';
|
||||||
import { MessageSquare, Settings2, SlidersHorizontal, Sparkles, ChevronDown } from 'lucide-react';
|
import {
|
||||||
|
MessageSquare,
|
||||||
|
Settings2,
|
||||||
|
SlidersHorizontal,
|
||||||
|
Sparkles,
|
||||||
|
ChevronDown,
|
||||||
|
Play,
|
||||||
|
} from 'lucide-react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { getElectronAPI } from '@/lib/electron';
|
import { getElectronAPI } from '@/lib/electron';
|
||||||
import { modelSupportsThinking } from '@/lib/utils';
|
import { modelSupportsThinking } from '@/lib/utils';
|
||||||
@@ -55,25 +62,28 @@ import {
|
|||||||
type AncestorContext,
|
type AncestorContext,
|
||||||
} from '@automaker/dependency-resolver';
|
} from '@automaker/dependency-resolver';
|
||||||
|
|
||||||
|
type FeatureData = {
|
||||||
|
title: string;
|
||||||
|
category: string;
|
||||||
|
description: string;
|
||||||
|
images: FeatureImage[];
|
||||||
|
imagePaths: DescriptionImagePath[];
|
||||||
|
textFilePaths: DescriptionTextFilePath[];
|
||||||
|
skipTests: boolean;
|
||||||
|
model: AgentModel;
|
||||||
|
thinkingLevel: ThinkingLevel;
|
||||||
|
branchName: string; // Can be empty string to use current branch
|
||||||
|
priority: number;
|
||||||
|
planningMode: PlanningMode;
|
||||||
|
requirePlanApproval: boolean;
|
||||||
|
dependencies?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
interface AddFeatureDialogProps {
|
interface AddFeatureDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
onAdd: (feature: {
|
onAdd: (feature: FeatureData) => void;
|
||||||
title: string;
|
onAddAndStart?: (feature: FeatureData) => void;
|
||||||
category: string;
|
|
||||||
description: string;
|
|
||||||
images: FeatureImage[];
|
|
||||||
imagePaths: DescriptionImagePath[];
|
|
||||||
textFilePaths: DescriptionTextFilePath[];
|
|
||||||
skipTests: boolean;
|
|
||||||
model: AgentModel;
|
|
||||||
thinkingLevel: ThinkingLevel;
|
|
||||||
branchName: string; // Can be empty string to use current branch
|
|
||||||
priority: number;
|
|
||||||
planningMode: PlanningMode;
|
|
||||||
requirePlanApproval: boolean;
|
|
||||||
dependencies?: string[];
|
|
||||||
}) => void;
|
|
||||||
categorySuggestions: string[];
|
categorySuggestions: string[];
|
||||||
branchSuggestions: string[];
|
branchSuggestions: string[];
|
||||||
branchCardCounts?: Record<string, number>; // Map of branch name to unarchived card count
|
branchCardCounts?: Record<string, number>; // Map of branch name to unarchived card count
|
||||||
@@ -92,6 +102,7 @@ export function AddFeatureDialog({
|
|||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
onAdd,
|
onAdd,
|
||||||
|
onAddAndStart,
|
||||||
categorySuggestions,
|
categorySuggestions,
|
||||||
branchSuggestions,
|
branchSuggestions,
|
||||||
branchCardCounts,
|
branchCardCounts,
|
||||||
@@ -188,16 +199,16 @@ export function AddFeatureDialog({
|
|||||||
allFeatures,
|
allFeatures,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleAdd = () => {
|
const buildFeatureData = (): FeatureData | null => {
|
||||||
if (!newFeature.description.trim()) {
|
if (!newFeature.description.trim()) {
|
||||||
setDescriptionError(true);
|
setDescriptionError(true);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate branch selection when "other branch" is selected
|
// Validate branch selection when "other branch" is selected
|
||||||
if (useWorktrees && !useCurrentBranch && !newFeature.branchName.trim()) {
|
if (useWorktrees && !useCurrentBranch && !newFeature.branchName.trim()) {
|
||||||
toast.error('Please select a branch name');
|
toast.error('Please select a branch name');
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const category = newFeature.category || 'Uncategorized';
|
const category = newFeature.category || 'Uncategorized';
|
||||||
@@ -235,7 +246,7 @@ export function AddFeatureDialog({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd({
|
return {
|
||||||
title: newFeature.title,
|
title: newFeature.title,
|
||||||
category,
|
category,
|
||||||
description: finalDescription,
|
description: finalDescription,
|
||||||
@@ -251,9 +262,10 @@ export function AddFeatureDialog({
|
|||||||
requirePlanApproval,
|
requirePlanApproval,
|
||||||
// In spawn mode, automatically add parent as dependency
|
// In spawn mode, automatically add parent as dependency
|
||||||
dependencies: isSpawnMode && parentFeature ? [parentFeature.id] : undefined,
|
dependencies: isSpawnMode && parentFeature ? [parentFeature.id] : undefined,
|
||||||
});
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Reset form
|
const resetForm = () => {
|
||||||
setNewFeature({
|
setNewFeature({
|
||||||
title: '',
|
title: '',
|
||||||
category: '',
|
category: '',
|
||||||
@@ -276,6 +288,24 @@ export function AddFeatureDialog({
|
|||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
const featureData = buildFeatureData();
|
||||||
|
if (!featureData) return;
|
||||||
|
|
||||||
|
onAdd(featureData);
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddAndStart = () => {
|
||||||
|
if (!onAddAndStart) return;
|
||||||
|
|
||||||
|
const featureData = buildFeatureData();
|
||||||
|
if (!featureData) return;
|
||||||
|
|
||||||
|
onAddAndStart(featureData);
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
const handleDialogClose = (open: boolean) => {
|
const handleDialogClose = (open: boolean) => {
|
||||||
onOpenChange(open);
|
onOpenChange(open);
|
||||||
if (!open) {
|
if (!open) {
|
||||||
@@ -575,6 +605,17 @@ export function AddFeatureDialog({
|
|||||||
<Button variant="ghost" onClick={() => onOpenChange(false)}>
|
<Button variant="ghost" onClick={() => onOpenChange(false)}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
|
{onAddAndStart && (
|
||||||
|
<Button
|
||||||
|
onClick={handleAddAndStart}
|
||||||
|
variant="secondary"
|
||||||
|
data-testid="confirm-add-and-start-feature"
|
||||||
|
disabled={useWorktrees && !useCurrentBranch && !newFeature.branchName.trim()}
|
||||||
|
>
|
||||||
|
<Play className="w-4 h-4 mr-2" />
|
||||||
|
Make
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<HotkeyButton
|
<HotkeyButton
|
||||||
onClick={handleAdd}
|
onClick={handleAdd}
|
||||||
hotkey={{ key: 'Enter', cmdCtrl: true }}
|
hotkey={{ key: 'Enter', cmdCtrl: true }}
|
||||||
|
|||||||
Reference in New Issue
Block a user