mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
fix(ui): bulk update cache invalidation and model dropdown display (#633)
Fix two related issues with bulk model updates in Kanban view: 1. Bulk update now properly invalidates React Query cache - Changed handleBulkUpdate and bulk verify handler to call loadFeatures() - This ensures UI immediately reflects bulk changes 2. Custom provider models (GLM, MiniMax, etc.) now display correctly - Added fallback lookup in PhaseModelSelector by model ID - Updated mass-edit-dialog to track providerId after selection
This commit is contained in:
committed by
GitHub
parent
47a6033b43
commit
4f584f9a89
@@ -636,10 +636,8 @@ export function BoardView() {
|
||||
const result = await api.features.bulkUpdate(currentProject.path, featureIds, finalUpdates);
|
||||
|
||||
if (result.success) {
|
||||
// Update local state
|
||||
featureIds.forEach((featureId) => {
|
||||
updateFeature(featureId, finalUpdates);
|
||||
});
|
||||
// Invalidate React Query cache to refetch features with server-updated values
|
||||
loadFeatures();
|
||||
toast.success(`Updated ${result.updatedCount} features`);
|
||||
exitSelectionMode();
|
||||
} else {
|
||||
@@ -655,7 +653,7 @@ export function BoardView() {
|
||||
[
|
||||
currentProject,
|
||||
selectedFeatureIds,
|
||||
updateFeature,
|
||||
loadFeatures,
|
||||
exitSelectionMode,
|
||||
getPrimaryWorktreeBranch,
|
||||
addAndSelectWorktree,
|
||||
@@ -783,10 +781,8 @@ export function BoardView() {
|
||||
const result = await api.features.bulkUpdate(currentProject.path, featureIds, updates);
|
||||
|
||||
if (result.success) {
|
||||
// Update local state for all features
|
||||
featureIds.forEach((featureId) => {
|
||||
updateFeature(featureId, updates);
|
||||
});
|
||||
// Invalidate React Query cache to refetch features with server-updated values
|
||||
loadFeatures();
|
||||
toast.success(`Verified ${result.updatedCount} features`);
|
||||
exitSelectionMode();
|
||||
} else {
|
||||
@@ -798,7 +794,7 @@ export function BoardView() {
|
||||
logger.error('Bulk verify failed:', error);
|
||||
toast.error('Failed to verify features');
|
||||
}
|
||||
}, [currentProject, selectedFeatureIds, updateFeature, exitSelectionMode]);
|
||||
}, [currentProject, selectedFeatureIds, loadFeatures, exitSelectionMode]);
|
||||
|
||||
// Handler for addressing PR comments - creates a feature and starts it automatically
|
||||
const handleAddressPRComments = useCallback(
|
||||
|
||||
@@ -128,6 +128,7 @@ export function MassEditDialog({
|
||||
// Field values
|
||||
const [model, setModel] = useState<ModelAlias>('claude-sonnet');
|
||||
const [thinkingLevel, setThinkingLevel] = useState<ThinkingLevel>('none');
|
||||
const [providerId, setProviderId] = useState<string | undefined>(undefined);
|
||||
const [planningMode, setPlanningMode] = useState<PlanningMode>('skip');
|
||||
const [requirePlanApproval, setRequirePlanApproval] = useState(false);
|
||||
const [priority, setPriority] = useState(2);
|
||||
@@ -162,6 +163,7 @@ export function MassEditDialog({
|
||||
});
|
||||
setModel(getInitialValue(selectedFeatures, 'model', 'claude-sonnet') as ModelAlias);
|
||||
setThinkingLevel(getInitialValue(selectedFeatures, 'thinkingLevel', 'none') as ThinkingLevel);
|
||||
setProviderId(undefined); // Features don't store providerId, but we track it after selection
|
||||
setPlanningMode(getInitialValue(selectedFeatures, 'planningMode', 'skip') as PlanningMode);
|
||||
setRequirePlanApproval(getInitialValue(selectedFeatures, 'requirePlanApproval', false));
|
||||
setPriority(getInitialValue(selectedFeatures, 'priority', 2));
|
||||
@@ -226,10 +228,11 @@ export function MassEditDialog({
|
||||
Select a specific model configuration
|
||||
</p>
|
||||
<PhaseModelSelector
|
||||
value={{ model, thinkingLevel }}
|
||||
value={{ model, thinkingLevel, providerId }}
|
||||
onChange={(entry: PhaseModelEntry) => {
|
||||
setModel(entry.model as ModelAlias);
|
||||
setThinkingLevel(entry.thinkingLevel || 'none');
|
||||
setProviderId(entry.providerId);
|
||||
// Auto-enable model and thinking level for apply state
|
||||
setApplyState((prev) => ({
|
||||
...prev,
|
||||
|
||||
@@ -415,6 +415,44 @@ export function PhaseModelSelector({
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Check ClaudeCompatibleProvider models by model ID only (when providerId is not set)
|
||||
// This handles cases where features store model ID but not providerId
|
||||
for (const provider of enabledProviders) {
|
||||
const providerModel = provider.models?.find((m) => m.id === selectedModel);
|
||||
if (providerModel) {
|
||||
// Count providers of same type to determine if we need provider name suffix
|
||||
const sameTypeCount = enabledProviders.filter(
|
||||
(p) => p.providerType === provider.providerType
|
||||
).length;
|
||||
const suffix = sameTypeCount > 1 ? ` (${provider.name})` : '';
|
||||
// Add thinking level to label if not 'none'
|
||||
const thinkingLabel =
|
||||
selectedThinkingLevel !== 'none'
|
||||
? ` (${THINKING_LEVEL_LABELS[selectedThinkingLevel]} Thinking)`
|
||||
: '';
|
||||
// Get icon based on provider type
|
||||
const getIconForProviderType = () => {
|
||||
switch (provider.providerType) {
|
||||
case 'glm':
|
||||
return GlmIcon;
|
||||
case 'minimax':
|
||||
return MiniMaxIcon;
|
||||
case 'openrouter':
|
||||
return OpenRouterIcon;
|
||||
default:
|
||||
return getProviderIconForModel(providerModel.id) || OpenRouterIcon;
|
||||
}
|
||||
};
|
||||
return {
|
||||
id: selectedModel,
|
||||
label: `${providerModel.displayName}${suffix}${thinkingLabel}`,
|
||||
description: provider.name,
|
||||
provider: 'claude-compatible' as const,
|
||||
icon: getIconForProviderType(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [
|
||||
selectedModel,
|
||||
|
||||
Reference in New Issue
Block a user