mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-03-18 03:13:08 +00:00
feat: fix tooltip shortcuts and add dev server config dialog
Tooltip fixes (PR #177 follow-up): - Remove duplicate title attr on Settings button that caused double-tooltip - Restore keyboard shortcut hints in tooltip text: Settings (,), Reset (R) - Clean up spurious peer markers in package-lock.json Dev server config dialog: - Add DevServerConfigDialog component for custom dev commands - Open config dialog automatically when start fails with "no dev command" - Add useDevServerConfig/useUpdateDevServerConfig hooks - Add updateDevServerConfig API function - Add config gear button next to dev server start Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { Globe, Square, Loader2, ExternalLink, AlertTriangle } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { Globe, Square, Loader2, ExternalLink, AlertTriangle, Settings2 } from 'lucide-react'
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import type { DevServerStatus } from '../lib/types'
|
||||
import { startDevServer, stopDevServer } from '../lib/api'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { DevServerConfigDialog } from './DevServerConfigDialog'
|
||||
|
||||
// Re-export DevServerStatus from lib/types for consumers that import from here
|
||||
export type { DevServerStatus }
|
||||
@@ -59,17 +61,27 @@ interface DevServerControlProps {
|
||||
* - Shows loading state during operations
|
||||
* - Displays clickable URL when server is running
|
||||
* - Uses neobrutalism design with cyan accent when running
|
||||
* - Config dialog for setting custom dev commands
|
||||
*/
|
||||
export function DevServerControl({ projectName, status, url }: DevServerControlProps) {
|
||||
const startDevServerMutation = useStartDevServer(projectName)
|
||||
const stopDevServerMutation = useStopDevServer(projectName)
|
||||
const [showConfigDialog, setShowConfigDialog] = useState(false)
|
||||
const [autoStartOnSave, setAutoStartOnSave] = useState(false)
|
||||
|
||||
const isLoading = startDevServerMutation.isPending || stopDevServerMutation.isPending
|
||||
|
||||
const handleStart = () => {
|
||||
// Clear any previous errors before starting
|
||||
stopDevServerMutation.reset()
|
||||
startDevServerMutation.mutate()
|
||||
startDevServerMutation.mutate(undefined, {
|
||||
onError: (err) => {
|
||||
if (err.message?.includes('No dev command available')) {
|
||||
setAutoStartOnSave(true)
|
||||
setShowConfigDialog(true)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
const handleStop = () => {
|
||||
// Clear any previous errors before stopping
|
||||
@@ -77,6 +89,19 @@ export function DevServerControl({ projectName, status, url }: DevServerControlP
|
||||
stopDevServerMutation.mutate()
|
||||
}
|
||||
|
||||
const handleOpenConfig = () => {
|
||||
setAutoStartOnSave(false)
|
||||
setShowConfigDialog(true)
|
||||
}
|
||||
|
||||
const handleCloseConfig = () => {
|
||||
setShowConfigDialog(false)
|
||||
// Clear the start error if config dialog was opened reactively
|
||||
if (startDevServerMutation.error?.message?.includes('No dev command available')) {
|
||||
startDevServerMutation.reset()
|
||||
}
|
||||
}
|
||||
|
||||
// Server is stopped when status is 'stopped' or 'crashed' (can restart)
|
||||
const isStopped = status === 'stopped' || status === 'crashed'
|
||||
// Server is in a running state
|
||||
@@ -84,25 +109,40 @@ export function DevServerControl({ projectName, status, url }: DevServerControlP
|
||||
// Server has crashed
|
||||
const isCrashed = status === 'crashed'
|
||||
|
||||
// Hide inline error when config dialog is handling it
|
||||
const startError = startDevServerMutation.error
|
||||
const showInlineError = startError && !startError.message?.includes('No dev command available')
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
{isStopped ? (
|
||||
<Button
|
||||
onClick={handleStart}
|
||||
disabled={isLoading}
|
||||
variant={isCrashed ? "destructive" : "outline"}
|
||||
size="sm"
|
||||
title={isCrashed ? "Dev Server Crashed - Click to Restart" : "Start Dev Server"}
|
||||
aria-label={isCrashed ? "Restart Dev Server (crashed)" : "Start Dev Server"}
|
||||
>
|
||||
{isLoading ? (
|
||||
<Loader2 size={18} className="animate-spin" />
|
||||
) : isCrashed ? (
|
||||
<AlertTriangle size={18} />
|
||||
) : (
|
||||
<Globe size={18} />
|
||||
)}
|
||||
</Button>
|
||||
<>
|
||||
<Button
|
||||
onClick={handleStart}
|
||||
disabled={isLoading}
|
||||
variant={isCrashed ? "destructive" : "outline"}
|
||||
size="sm"
|
||||
title={isCrashed ? "Dev Server Crashed - Click to Restart" : "Start Dev Server"}
|
||||
aria-label={isCrashed ? "Restart Dev Server (crashed)" : "Start Dev Server"}
|
||||
>
|
||||
{isLoading ? (
|
||||
<Loader2 size={18} className="animate-spin" />
|
||||
) : isCrashed ? (
|
||||
<AlertTriangle size={18} />
|
||||
) : (
|
||||
<Globe size={18} />
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleOpenConfig}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
title="Configure Dev Server"
|
||||
aria-label="Configure Dev Server"
|
||||
>
|
||||
<Settings2 size={16} />
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
onClick={handleStop}
|
||||
@@ -139,12 +179,20 @@ export function DevServerControl({ projectName, status, url }: DevServerControlP
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Error display */}
|
||||
{(startDevServerMutation.error || stopDevServerMutation.error) && (
|
||||
{/* Error display (hide "no dev command" error when config dialog handles it) */}
|
||||
{(showInlineError || stopDevServerMutation.error) && (
|
||||
<span className="text-xs font-mono text-destructive ml-2">
|
||||
{String((startDevServerMutation.error || stopDevServerMutation.error)?.message || 'Operation failed')}
|
||||
{String((showInlineError ? startError : stopDevServerMutation.error)?.message || 'Operation failed')}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Dev Server Config Dialog */}
|
||||
<DevServerConfigDialog
|
||||
projectName={projectName}
|
||||
isOpen={showConfigDialog}
|
||||
onClose={handleCloseConfig}
|
||||
autoStartOnSave={autoStartOnSave}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user