mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
refactor: update mass edit dialog and introduce new select components
- Removed advanced options toggle and related state from the mass edit dialog for a cleaner UI. - Replaced ProfileQuickSelect with ProfileSelect for better profile management. - Introduced new PlanningModeSelect and PrioritySelect components for streamlined selection of planning modes and priorities. - Updated imports in shared index to include new select components. - Enhanced the mass edit dialog to utilize the new components, improving user experience during bulk edits.
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
import { Zap, ClipboardList, FileText, ScrollText } from 'lucide-react';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { PlanningMode } from '@automaker/types';
|
||||
|
||||
interface PlanningModeSelectProps {
|
||||
mode: PlanningMode;
|
||||
onModeChange: (mode: PlanningMode) => void;
|
||||
requireApproval?: boolean;
|
||||
onRequireApprovalChange?: (require: boolean) => void;
|
||||
testIdPrefix?: string;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const modes = [
|
||||
{
|
||||
value: 'skip' as const,
|
||||
label: 'Skip',
|
||||
description: 'Direct implementation, no upfront planning',
|
||||
icon: Zap,
|
||||
color: 'text-emerald-500',
|
||||
},
|
||||
{
|
||||
value: 'lite' as const,
|
||||
label: 'Lite',
|
||||
description: 'Think through approach, create task list',
|
||||
icon: ClipboardList,
|
||||
color: 'text-blue-500',
|
||||
},
|
||||
{
|
||||
value: 'spec' as const,
|
||||
label: 'Spec',
|
||||
description: 'Generate spec with acceptance criteria',
|
||||
icon: FileText,
|
||||
color: 'text-purple-500',
|
||||
},
|
||||
{
|
||||
value: 'full' as const,
|
||||
label: 'Full',
|
||||
description: 'Comprehensive spec with phased plan',
|
||||
icon: ScrollText,
|
||||
color: 'text-amber-500',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* PlanningModeSelect - Compact dropdown selector for planning modes
|
||||
*
|
||||
* A lightweight alternative to PlanningModeSelector for contexts where
|
||||
* spec management UI is not needed (e.g., mass edit, bulk operations).
|
||||
*
|
||||
* Shows icon + label in dropdown, with description text below.
|
||||
* Does not include spec generation, approval, or require-approval checkbox.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <PlanningModeSelect
|
||||
* mode={planningMode}
|
||||
* onModeChange={(mode) => {
|
||||
* setPlanningMode(mode);
|
||||
* setRequireApproval(mode === 'spec' || mode === 'full');
|
||||
* }}
|
||||
* testIdPrefix="mass-edit-planning"
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
export function PlanningModeSelect({
|
||||
mode,
|
||||
onModeChange,
|
||||
requireApproval,
|
||||
onRequireApprovalChange,
|
||||
testIdPrefix = 'planning-mode',
|
||||
className,
|
||||
disabled = false,
|
||||
}: PlanningModeSelectProps) {
|
||||
const selectedMode = modes.find((m) => m.value === mode);
|
||||
|
||||
// Disable approval checkbox for skip/lite modes since they don't use planning
|
||||
const isApprovalDisabled = disabled || mode === 'skip' || mode === 'lite';
|
||||
|
||||
return (
|
||||
<div className={cn('space-y-2', className)}>
|
||||
<Select
|
||||
value={mode}
|
||||
onValueChange={(value: string) => onModeChange(value as PlanningMode)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<SelectTrigger className="h-9" data-testid={`${testIdPrefix}-select-trigger`}>
|
||||
<SelectValue>
|
||||
{selectedMode && (
|
||||
<div className="flex items-center gap-2">
|
||||
<selectedMode.icon className={cn('h-4 w-4', selectedMode.color)} />
|
||||
<span>{selectedMode.label}</span>
|
||||
</div>
|
||||
)}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{modes.map((m) => {
|
||||
const Icon = m.icon;
|
||||
return (
|
||||
<SelectItem
|
||||
key={m.value}
|
||||
value={m.value}
|
||||
data-testid={`${testIdPrefix}-option-${m.value}`}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Icon className={cn('h-3.5 w-3.5', m.color)} />
|
||||
<span>{m.label}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{selectedMode && <p className="text-xs text-muted-foreground">{selectedMode.description}</p>}
|
||||
{onRequireApprovalChange && (
|
||||
<div className="flex items-center gap-2 pt-1">
|
||||
<Checkbox
|
||||
id={`${testIdPrefix}-require-approval`}
|
||||
checked={requireApproval && !isApprovalDisabled}
|
||||
onCheckedChange={(checked) => onRequireApprovalChange(!!checked)}
|
||||
disabled={isApprovalDisabled}
|
||||
data-testid={`${testIdPrefix}-require-approval-checkbox`}
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`${testIdPrefix}-require-approval`}
|
||||
className={cn(
|
||||
'text-sm font-normal',
|
||||
isApprovalDisabled ? 'cursor-not-allowed text-muted-foreground' : 'cursor-pointer'
|
||||
)}
|
||||
>
|
||||
Require plan approval before execution
|
||||
</Label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user