diff --git a/apps/frontend/src/renderer/components/ProjectSettings.tsx b/apps/frontend/src/renderer/components/ProjectSettings.tsx deleted file mode 100644 index ef28746f..00000000 --- a/apps/frontend/src/renderer/components/ProjectSettings.tsx +++ /dev/null @@ -1,312 +0,0 @@ -import { useState } from 'react'; -import { Settings2, Save, Loader2 } from 'lucide-react'; -import { LinearTaskImportModal } from './LinearTaskImportModal'; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from './ui/dialog'; -import { Button } from './ui/button'; -import { Separator } from './ui/separator'; -import { updateProjectSettings, initializeProject, updateProjectAutoBuild, checkProjectVersion } from '../stores/project-store'; -import type { Project } from '../../shared/types'; - -// Import custom hooks -import { useProjectSettings } from '../hooks/useProjectSettings'; -import { useEnvironmentConfig } from '../hooks/useEnvironmentConfig'; -import { useClaudeAuth } from '../hooks/useClaudeAuth'; -import { useLinearConnection } from '../hooks/useLinearConnection'; -import { useGitHubConnection } from '../hooks/useGitHubConnection'; -import { useInfrastructureStatus } from '../hooks/useInfrastructureStatus'; - -// Import section components -import { AutoBuildIntegration } from './project-settings/AutoBuildIntegration'; -import { ClaudeAuthSection } from './project-settings/ClaudeAuthSection'; -import { LinearIntegrationSection } from './project-settings/LinearIntegrationSection'; -import { GitHubIntegrationSection } from './project-settings/GitHubIntegrationSection'; -import { MemoryBackendSection } from './project-settings/MemoryBackendSection'; -import { AgentConfigSection } from './project-settings/AgentConfigSection'; -import { NotificationsSection } from './project-settings/NotificationsSection'; - -interface ProjectSettingsProps { - project: Project; - open: boolean; - onOpenChange: (open: boolean) => void; -} - -export function ProjectSettings({ project, open, onOpenChange }: ProjectSettingsProps) { - const [isSaving, setIsSaving] = useState(false); - const [error, setError] = useState(null); - const [isUpdating, setIsUpdating] = useState(false); - const [showLinearImportModal, setShowLinearImportModal] = useState(false); - - // Collapsible sections state - const [expandedSections, setExpandedSections] = useState>({ - claude: true, - linear: false, - github: false, - graphiti: false - }); - - // Custom hooks for state management - const { settings, setSettings, versionInfo, setVersionInfo, isCheckingVersion } = useProjectSettings(project, open); - - const { - envConfig, - setEnvConfig, - updateEnvConfig, - isLoadingEnv, - envError, - setEnvError: _setEnvError, - isSavingEnv, - } = useEnvironmentConfig(project.id, project.autoBuildPath, open); - - const { isCheckingClaudeAuth, claudeAuthStatus, handleClaudeSetup } = useClaudeAuth( - project.id, - project.autoBuildPath, - open - ); - - const { linearConnectionStatus, isCheckingLinear } = useLinearConnection( - project.id, - envConfig?.linearEnabled, - envConfig?.linearApiKey - ); - - const { gitHubConnectionStatus, isCheckingGitHub } = useGitHubConnection( - project.id, - envConfig?.githubEnabled, - envConfig?.githubToken, - envConfig?.githubRepo - ); - - const { - infrastructureStatus, - isCheckingInfrastructure, - } = useInfrastructureStatus( - envConfig?.graphitiEnabled, - envConfig?.graphitiDbPath, - open - ); - - const toggleSection = (section: string) => { - setExpandedSections(prev => ({ ...prev, [section]: !prev[section] })); - }; - - const handleInitialize = async () => { - setIsUpdating(true); - setError(null); - try { - const result = await initializeProject(project.id); - if (result?.success) { - // Refresh version info - const info = await checkProjectVersion(project.id); - setVersionInfo(info); - // Load env config for newly initialized project - const envResult = await window.electronAPI.getProjectEnv(project.id); - if (envResult.success && envResult.data) { - setEnvConfig(envResult.data); - } - } else { - setError(result?.error || 'Failed to initialize'); - } - } catch (err) { - setError(err instanceof Error ? err.message : 'Unknown error'); - } finally { - setIsUpdating(false); - } - }; - - const handleUpdate = async () => { - setIsUpdating(true); - setError(null); - try { - const result = await updateProjectAutoBuild(project.id); - if (result?.success) { - // Refresh version info - const info = await checkProjectVersion(project.id); - setVersionInfo(info); - } else { - setError(result?.error || 'Failed to update'); - } - } catch (err) { - setError(err instanceof Error ? err.message : 'Unknown error'); - } finally { - setIsUpdating(false); - } - }; - - const handleSave = async () => { - setIsSaving(true); - setError(null); - - try { - // Save project settings - const success = await updateProjectSettings(project.id, settings); - if (!success) { - setError('Failed to save settings'); - return; - } - - // Save env config if loaded - if (envConfig) { - const envResult = await window.electronAPI.updateProjectEnv(project.id, envConfig); - if (!envResult.success) { - setError(envResult.error || 'Failed to save environment config'); - return; - } - } - - onOpenChange(false); - } catch (err) { - setError(err instanceof Error ? err.message : 'Unknown error'); - } finally { - setIsSaving(false); - } - }; - - const handleClaudeSetupWithCallback = () => { - handleClaudeSetup((newEnvConfig) => { - setEnvConfig(newEnvConfig); - }); - }; - - return ( - - - - - - Project Settings - - - Configure settings for {project.name} - - - -
-
- {/* Auto-Build Integration */} - - - {/* Environment Configuration - Only show if initialized */} - {project.autoBuildPath && envConfig && ( - <> - - - {/* Claude Authentication Section */} - toggleSection('claude')} - envConfig={envConfig} - isLoadingEnv={isLoadingEnv} - envError={envError} - isCheckingAuth={isCheckingClaudeAuth} - authStatus={claudeAuthStatus} - onClaudeSetup={handleClaudeSetupWithCallback} - onUpdateConfig={updateEnvConfig} - /> - - - - {/* Linear Integration Section */} - toggleSection('linear')} - envConfig={envConfig} - onUpdateConfig={updateEnvConfig} - linearConnectionStatus={linearConnectionStatus} - isCheckingLinear={isCheckingLinear} - onOpenImportModal={() => setShowLinearImportModal(true)} - /> - - - - {/* GitHub Integration Section */} - toggleSection('github')} - envConfig={envConfig} - onUpdateConfig={updateEnvConfig} - gitHubConnectionStatus={gitHubConnectionStatus} - isCheckingGitHub={isCheckingGitHub} - projectName={project.name} - /> - - - - {/* Memory Backend Section */} - toggleSection('graphiti')} - envConfig={envConfig} - settings={settings} - onUpdateConfig={updateEnvConfig} - onUpdateSettings={(updates) => setSettings({ ...settings, ...updates })} - infrastructureStatus={infrastructureStatus} - isCheckingInfrastructure={isCheckingInfrastructure} - /> - - - - )} - - {/* Agent Settings */} - setSettings({ ...settings, ...updates })} - /> - - - - {/* Notifications */} - setSettings({ ...settings, ...updates })} - /> - - {/* Error */} - {(error || envError) && ( -
- {error || envError} -
- )} -
-
- - - - - -
- - {/* Linear Task Import Modal */} - { - // Optionally refresh or notify - console.log('Import complete:', result); - }} - /> -
- ); -} diff --git a/apps/frontend/src/renderer/components/index.ts b/apps/frontend/src/renderer/components/index.ts index 8b06fe1e..f84b30a6 100644 --- a/apps/frontend/src/renderer/components/index.ts +++ b/apps/frontend/src/renderer/components/index.ts @@ -5,7 +5,6 @@ export * from './TaskCard'; export * from './TaskDetailPanel'; export * from './TaskCreationWizard'; export * from './TaskEditDialog'; -// Note: ProjectSettings modal is deprecated - use unified AppSettings instead export * from './AppSettings'; export * from './Context'; export * from './Ideation'; diff --git a/apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx b/apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx deleted file mode 100644 index 7b7a68bc..00000000 --- a/apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import { Settings2, Save, Loader2 } from 'lucide-react'; -import { LinearTaskImportModal } from '../LinearTaskImportModal'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle -} from '../ui/dialog'; -import { Button } from '../ui/button'; -import { Separator } from '../ui/separator'; -import { GeneralSettings } from './GeneralSettings'; -import { EnvironmentSettings } from './EnvironmentSettings'; -import { IntegrationSettings } from './IntegrationSettings'; -import { SecuritySettings } from './SecuritySettings'; -import { useProjectSettings } from './hooks/useProjectSettings'; -import type { Project } from '../../../shared/types'; - -interface ProjectSettingsProps { - project: Project; - open: boolean; - onOpenChange: (open: boolean) => void; -} - -export function ProjectSettings({ project, open, onOpenChange }: ProjectSettingsProps) { - const hook = useProjectSettings(project, open); - - const { - settings, - setSettings, - isSaving, - error, - versionInfo, - isCheckingVersion, - isUpdating, - envConfig, - isLoadingEnv, - envError, - isSavingEnv, - updateEnvConfig, - showClaudeToken, - setShowClaudeToken, - showLinearKey, - setShowLinearKey, - showOpenAIKey, - setShowOpenAIKey, - showGitHubToken, - setShowGitHubToken, - expandedSections, - toggleSection, - gitHubConnectionStatus, - isCheckingGitHub, - isCheckingClaudeAuth, - claudeAuthStatus, - showLinearImportModal, - setShowLinearImportModal, - linearConnectionStatus, - isCheckingLinear, - handleInitialize, - handleUpdate, - handleClaudeSetup, - handleSave - } = hook; - - return ( - - - - - - Project Settings - - - Configure settings for {project.name} - - - -
-
- {/* General Settings (Auto-Build, Agent Config, Notifications) */} - - - {/* Environment Configuration - Only show if initialized */} - {project.autoBuildPath && ( - <> - - - {/* Claude Authentication */} - toggleSection('claude')} - /> - - - - {/* Linear and GitHub Integrations */} - toggleSection('linear')} - onOpenLinearImport={() => setShowLinearImportModal(true)} - showGitHubToken={showGitHubToken} - setShowGitHubToken={setShowGitHubToken} - gitHubConnectionStatus={gitHubConnectionStatus} - isCheckingGitHub={isCheckingGitHub} - githubExpanded={expandedSections.github} - onGitHubToggle={() => toggleSection('github')} - /> - - - - {/* Memory Backend (Graphiti) */} - toggleSection('graphiti')} - /> - - )} - - {/* Error Display */} - {(error || envError) && ( -
- {error || envError} -
- )} -
-
- - - - - -
- - {/* Linear Task Import Modal */} - { - console.log('Import complete:', result); - }} - /> -
- ); -} diff --git a/apps/frontend/src/renderer/hooks/index.ts b/apps/frontend/src/renderer/hooks/index.ts index b2ffad81..0793d045 100644 --- a/apps/frontend/src/renderer/hooks/index.ts +++ b/apps/frontend/src/renderer/hooks/index.ts @@ -1,9 +1,3 @@ // Export all custom hooks -export { useProjectSettings } from './useProjectSettings'; -export { useEnvironmentConfig } from './useEnvironmentConfig'; -export { useClaudeAuth } from './useClaudeAuth'; -export { useLinearConnection } from './useLinearConnection'; -export { useGitHubConnection } from './useGitHubConnection'; -export { useInfrastructureStatus } from './useInfrastructureStatus'; export { useIpcListeners } from './useIpc'; export { useVirtualizedTree } from './useVirtualizedTree'; diff --git a/apps/frontend/src/renderer/hooks/useClaudeAuth.ts b/apps/frontend/src/renderer/hooks/useClaudeAuth.ts deleted file mode 100644 index 3ab94031..00000000 --- a/apps/frontend/src/renderer/hooks/useClaudeAuth.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { useState, useEffect } from 'react'; -import type { ProjectEnvConfig } from '../../shared/types'; - -type AuthStatus = 'checking' | 'authenticated' | 'not_authenticated' | 'error'; - -export function useClaudeAuth(projectId: string, autoBuildPath: string | null, open: boolean) { - const [isCheckingClaudeAuth, setIsCheckingClaudeAuth] = useState(false); - const [claudeAuthStatus, setClaudeAuthStatus] = useState('checking'); - - // Check Claude authentication status - useEffect(() => { - const checkAuth = async () => { - if (open && autoBuildPath) { - setIsCheckingClaudeAuth(true); - try { - const result = await window.electronAPI.checkClaudeAuth(projectId); - if (result.success && result.data) { - setClaudeAuthStatus(result.data.authenticated ? 'authenticated' : 'not_authenticated'); - } else { - setClaudeAuthStatus('error'); - } - } catch { - setClaudeAuthStatus('error'); - } finally { - setIsCheckingClaudeAuth(false); - } - } - }; - checkAuth(); - }, [open, projectId, autoBuildPath]); - - const handleClaudeSetup = async ( - onSuccess?: (envConfig: ProjectEnvConfig) => void - ) => { - setIsCheckingClaudeAuth(true); - try { - const result = await window.electronAPI.invokeClaudeSetup(projectId); - if (result.success && result.data?.authenticated) { - setClaudeAuthStatus('authenticated'); - // Refresh env config - const envResult = await window.electronAPI.getProjectEnv(projectId); - if (envResult.success && envResult.data && onSuccess) { - onSuccess(envResult.data); - } - } - } catch { - setClaudeAuthStatus('error'); - } finally { - setIsCheckingClaudeAuth(false); - } - }; - - return { - isCheckingClaudeAuth, - claudeAuthStatus, - handleClaudeSetup, - }; -} diff --git a/apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts b/apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts deleted file mode 100644 index a25cccc4..00000000 --- a/apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { useState, useEffect } from 'react'; -import type { ProjectEnvConfig } from '../../shared/types'; - -export function useEnvironmentConfig(projectId: string, autoBuildPath: string | null, open: boolean) { - const [envConfig, setEnvConfig] = useState(null); - const [isLoadingEnv, setIsLoadingEnv] = useState(false); - const [envError, setEnvError] = useState(null); - const [isSavingEnv, setIsSavingEnv] = useState(false); - - // Load environment config when dialog opens - useEffect(() => { - const loadEnvConfig = async () => { - if (open && autoBuildPath) { - setIsLoadingEnv(true); - setEnvError(null); - try { - const result = await window.electronAPI.getProjectEnv(projectId); - if (result.success && result.data) { - setEnvConfig(result.data); - } else { - setEnvError(result.error || 'Failed to load environment config'); - } - } catch (err) { - setEnvError(err instanceof Error ? err.message : 'Unknown error'); - } finally { - setIsLoadingEnv(false); - } - } - }; - loadEnvConfig(); - }, [open, projectId, autoBuildPath]); - - const updateEnvConfig = (updates: Partial) => { - if (envConfig) { - setEnvConfig({ ...envConfig, ...updates }); - } - }; - - const saveEnvConfig = async () => { - if (!envConfig) return { success: false, error: 'No config to save' }; - - setIsSavingEnv(true); - setEnvError(null); - try { - const result = await window.electronAPI.updateProjectEnv(projectId, envConfig); - if (!result.success) { - setEnvError(result.error || 'Failed to save environment config'); - return { success: false, error: result.error }; - } - return { success: true }; - } catch (err) { - const error = err instanceof Error ? err.message : 'Unknown error'; - setEnvError(error); - return { success: false, error }; - } finally { - setIsSavingEnv(false); - } - }; - - return { - envConfig, - setEnvConfig, - updateEnvConfig, - isLoadingEnv, - envError, - setEnvError, - isSavingEnv, - saveEnvConfig, - }; -} diff --git a/apps/frontend/src/renderer/hooks/useGitHubConnection.ts b/apps/frontend/src/renderer/hooks/useGitHubConnection.ts deleted file mode 100644 index d7d5e791..00000000 --- a/apps/frontend/src/renderer/hooks/useGitHubConnection.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useState, useEffect } from 'react'; -import type { GitHubSyncStatus } from '../../shared/types'; - -export function useGitHubConnection( - projectId: string, - githubEnabled: boolean | undefined, - githubToken: string | undefined, - githubRepo: string | undefined -) { - const [gitHubConnectionStatus, setGitHubConnectionStatus] = useState(null); - const [isCheckingGitHub, setIsCheckingGitHub] = useState(false); - - useEffect(() => { - const checkGitHubConnection = async () => { - if (!githubEnabled || !githubToken || !githubRepo) { - setGitHubConnectionStatus(null); - return; - } - - setIsCheckingGitHub(true); - try { - const result = await window.electronAPI.checkGitHubConnection(projectId); - if (result.success && result.data) { - setGitHubConnectionStatus(result.data); - } - } catch { - setGitHubConnectionStatus({ connected: false, error: 'Failed to check connection' }); - } finally { - setIsCheckingGitHub(false); - } - }; - - if (githubEnabled && githubToken && githubRepo) { - checkGitHubConnection(); - } - }, [githubEnabled, githubToken, githubRepo, projectId]); - - return { - gitHubConnectionStatus, - isCheckingGitHub, - }; -} diff --git a/apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts b/apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts deleted file mode 100644 index 03cf1a34..00000000 --- a/apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { useState, useEffect } from 'react'; -import type { InfrastructureStatus } from '../../shared/types'; - -/** - * Hook for checking memory infrastructure status (LadybugDB) - * No Docker required - uses embedded database - */ -export function useInfrastructureStatus( - graphitiEnabled: boolean | undefined, - dbPath: string | undefined, - open: boolean -) { - const [infrastructureStatus, setInfrastructureStatus] = useState(null); - const [isCheckingInfrastructure, setIsCheckingInfrastructure] = useState(false); - - useEffect(() => { - const checkInfrastructure = async () => { - if (!graphitiEnabled) { - setInfrastructureStatus(null); - return; - } - - setIsCheckingInfrastructure(true); - try { - const result = await window.electronAPI.getMemoryInfrastructureStatus(dbPath); - if (result.success && result.data) { - setInfrastructureStatus(result.data); - } - } catch { - // Silently fail - infrastructure check is optional - } finally { - setIsCheckingInfrastructure(false); - } - }; - - checkInfrastructure(); - // Refresh every 10 seconds while Graphiti is enabled - let interval: NodeJS.Timeout | undefined; - if (graphitiEnabled && open) { - interval = setInterval(checkInfrastructure, 10000); - } - return () => { - if (interval) clearInterval(interval); - }; - }, [graphitiEnabled, dbPath, open]); - - return { - infrastructureStatus, - isCheckingInfrastructure, - }; -} diff --git a/apps/frontend/src/renderer/hooks/useLinearConnection.ts b/apps/frontend/src/renderer/hooks/useLinearConnection.ts deleted file mode 100644 index 84579e49..00000000 --- a/apps/frontend/src/renderer/hooks/useLinearConnection.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useState, useEffect } from 'react'; -import type { LinearSyncStatus } from '../../shared/types'; - -export function useLinearConnection( - projectId: string, - linearEnabled: boolean | undefined, - linearApiKey: string | undefined -) { - const [linearConnectionStatus, setLinearConnectionStatus] = useState(null); - const [isCheckingLinear, setIsCheckingLinear] = useState(false); - - useEffect(() => { - const checkLinearConnection = async () => { - if (!linearEnabled || !linearApiKey) { - setLinearConnectionStatus(null); - return; - } - - setIsCheckingLinear(true); - try { - const result = await window.electronAPI.checkLinearConnection(projectId); - if (result.success && result.data) { - setLinearConnectionStatus(result.data); - } - } catch { - setLinearConnectionStatus({ connected: false, error: 'Failed to check connection' }); - } finally { - setIsCheckingLinear(false); - } - }; - - if (linearEnabled && linearApiKey) { - checkLinearConnection(); - } - }, [linearEnabled, linearApiKey, projectId]); - - return { - linearConnectionStatus, - isCheckingLinear, - }; -} diff --git a/apps/frontend/src/renderer/hooks/useProjectSettings.ts b/apps/frontend/src/renderer/hooks/useProjectSettings.ts deleted file mode 100644 index eca84162..00000000 --- a/apps/frontend/src/renderer/hooks/useProjectSettings.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useState, useEffect } from 'react'; -import type { Project, ProjectSettings, AutoBuildVersionInfo } from '../../shared/types'; -import { checkProjectVersion } from '../stores/project-store'; - -export function useProjectSettings(project: Project, open: boolean) { - const [settings, setSettings] = useState(project.settings); - const [versionInfo, setVersionInfo] = useState(null); - const [isCheckingVersion, setIsCheckingVersion] = useState(false); - - // Reset settings when project changes - useEffect(() => { - setSettings(project.settings); - }, [project]); - - // Check version when dialog opens - useEffect(() => { - const checkVersion = async () => { - if (open && project.autoBuildPath) { - setIsCheckingVersion(true); - const info = await checkProjectVersion(project.id); - setVersionInfo(info); - setIsCheckingVersion(false); - } - }; - checkVersion(); - }, [open, project.id, project.autoBuildPath]); - - return { - settings, - setSettings, - versionInfo, - setVersionInfo, - isCheckingVersion, - }; -}