refactor(settings): remove deprecated ProjectSettings modal and hooks (#343)
The old ProjectSettings modal has been replaced by the unified AppSettings dialog. This removes: - `ProjectSettings.tsx` - deprecated modal component - `project-settings/ProjectSettings.tsx` - unused refactored version - `hooks/useProjectSettings.ts` - replaced by project-settings/hooks/ - `hooks/useEnvironmentConfig.ts` - only used by deprecated modal - `hooks/useClaudeAuth.ts` - only used by deprecated modal - `hooks/useLinearConnection.ts` - only used by deprecated modal - `hooks/useGitHubConnection.ts` - only used by deprecated modal - `hooks/useInfrastructureStatus.ts` - only used by deprecated modal Updated index files to remove deprecated exports.
This commit is contained in:
@@ -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<string | null>(null);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
const [showLinearImportModal, setShowLinearImportModal] = useState(false);
|
||||
|
||||
// Collapsible sections state
|
||||
const [expandedSections, setExpandedSections] = useState<Record<string, boolean>>({
|
||||
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 (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[600px] max-h-[85vh] flex flex-col overflow-hidden">
|
||||
<DialogHeader className="shrink-0">
|
||||
<DialogTitle className="flex items-center gap-2 text-foreground">
|
||||
<Settings2 className="h-5 w-5" />
|
||||
Project Settings
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Configure settings for {project.name}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 min-h-0 -mx-6 overflow-y-auto">
|
||||
<div className="px-6 py-4 space-y-6">
|
||||
{/* Auto-Build Integration */}
|
||||
<AutoBuildIntegration
|
||||
autoBuildPath={project.autoBuildPath}
|
||||
versionInfo={versionInfo}
|
||||
isCheckingVersion={isCheckingVersion}
|
||||
isUpdating={isUpdating}
|
||||
onInitialize={handleInitialize}
|
||||
onUpdate={handleUpdate}
|
||||
/>
|
||||
|
||||
{/* Environment Configuration - Only show if initialized */}
|
||||
{project.autoBuildPath && envConfig && (
|
||||
<>
|
||||
<Separator />
|
||||
|
||||
{/* Claude Authentication Section */}
|
||||
<ClaudeAuthSection
|
||||
isExpanded={expandedSections.claude}
|
||||
onToggle={() => toggleSection('claude')}
|
||||
envConfig={envConfig}
|
||||
isLoadingEnv={isLoadingEnv}
|
||||
envError={envError}
|
||||
isCheckingAuth={isCheckingClaudeAuth}
|
||||
authStatus={claudeAuthStatus}
|
||||
onClaudeSetup={handleClaudeSetupWithCallback}
|
||||
onUpdateConfig={updateEnvConfig}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Linear Integration Section */}
|
||||
<LinearIntegrationSection
|
||||
isExpanded={expandedSections.linear}
|
||||
onToggle={() => toggleSection('linear')}
|
||||
envConfig={envConfig}
|
||||
onUpdateConfig={updateEnvConfig}
|
||||
linearConnectionStatus={linearConnectionStatus}
|
||||
isCheckingLinear={isCheckingLinear}
|
||||
onOpenImportModal={() => setShowLinearImportModal(true)}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* GitHub Integration Section */}
|
||||
<GitHubIntegrationSection
|
||||
isExpanded={expandedSections.github}
|
||||
onToggle={() => toggleSection('github')}
|
||||
envConfig={envConfig}
|
||||
onUpdateConfig={updateEnvConfig}
|
||||
gitHubConnectionStatus={gitHubConnectionStatus}
|
||||
isCheckingGitHub={isCheckingGitHub}
|
||||
projectName={project.name}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Memory Backend Section */}
|
||||
<MemoryBackendSection
|
||||
isExpanded={expandedSections.graphiti}
|
||||
onToggle={() => toggleSection('graphiti')}
|
||||
envConfig={envConfig}
|
||||
settings={settings}
|
||||
onUpdateConfig={updateEnvConfig}
|
||||
onUpdateSettings={(updates) => setSettings({ ...settings, ...updates })}
|
||||
infrastructureStatus={infrastructureStatus}
|
||||
isCheckingInfrastructure={isCheckingInfrastructure}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Agent Settings */}
|
||||
<AgentConfigSection
|
||||
settings={settings}
|
||||
onUpdateSettings={(updates) => setSettings({ ...settings, ...updates })}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Notifications */}
|
||||
<NotificationsSection
|
||||
settings={settings}
|
||||
onUpdateSettings={(updates) => setSettings({ ...settings, ...updates })}
|
||||
/>
|
||||
|
||||
{/* Error */}
|
||||
{(error || envError) && (
|
||||
<div className="rounded-lg bg-destructive/10 border border-destructive/30 p-3 text-sm text-destructive">
|
||||
{error || envError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="shrink-0">
|
||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleSave} disabled={isSaving || isSavingEnv}>
|
||||
{isSaving || isSavingEnv ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Saving...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Save className="mr-2 h-4 w-4" />
|
||||
Save Settings
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
{/* Linear Task Import Modal */}
|
||||
<LinearTaskImportModal
|
||||
projectId={project.id}
|
||||
open={showLinearImportModal}
|
||||
onOpenChange={setShowLinearImportModal}
|
||||
onImportComplete={(result) => {
|
||||
// Optionally refresh or notify
|
||||
console.log('Import complete:', result);
|
||||
}}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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 (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[600px] max-h-[85vh] flex flex-col overflow-hidden">
|
||||
<DialogHeader className="shrink-0">
|
||||
<DialogTitle className="flex items-center gap-2 text-foreground">
|
||||
<Settings2 className="h-5 w-5" />
|
||||
Project Settings
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Configure settings for {project.name}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 min-h-0 -mx-6 overflow-y-auto">
|
||||
<div className="px-6 py-4 space-y-6">
|
||||
{/* General Settings (Auto-Build, Agent Config, Notifications) */}
|
||||
<GeneralSettings
|
||||
project={project}
|
||||
settings={settings}
|
||||
setSettings={setSettings}
|
||||
versionInfo={versionInfo}
|
||||
isCheckingVersion={isCheckingVersion}
|
||||
isUpdating={isUpdating}
|
||||
handleInitialize={handleInitialize}
|
||||
handleUpdate={handleUpdate}
|
||||
/>
|
||||
|
||||
{/* Environment Configuration - Only show if initialized */}
|
||||
{project.autoBuildPath && (
|
||||
<>
|
||||
<Separator />
|
||||
|
||||
{/* Claude Authentication */}
|
||||
<EnvironmentSettings
|
||||
envConfig={envConfig}
|
||||
isLoadingEnv={isLoadingEnv}
|
||||
envError={envError}
|
||||
updateEnvConfig={updateEnvConfig}
|
||||
isCheckingClaudeAuth={isCheckingClaudeAuth}
|
||||
claudeAuthStatus={claudeAuthStatus}
|
||||
handleClaudeSetup={handleClaudeSetup}
|
||||
showClaudeToken={showClaudeToken}
|
||||
setShowClaudeToken={setShowClaudeToken}
|
||||
expanded={expandedSections.claude}
|
||||
onToggle={() => toggleSection('claude')}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Linear and GitHub Integrations */}
|
||||
<IntegrationSettings
|
||||
envConfig={envConfig}
|
||||
updateEnvConfig={updateEnvConfig}
|
||||
project={project}
|
||||
settings={settings}
|
||||
setSettings={setSettings}
|
||||
showLinearKey={showLinearKey}
|
||||
setShowLinearKey={setShowLinearKey}
|
||||
linearConnectionStatus={linearConnectionStatus}
|
||||
isCheckingLinear={isCheckingLinear}
|
||||
linearExpanded={expandedSections.linear}
|
||||
onLinearToggle={() => toggleSection('linear')}
|
||||
onOpenLinearImport={() => setShowLinearImportModal(true)}
|
||||
showGitHubToken={showGitHubToken}
|
||||
setShowGitHubToken={setShowGitHubToken}
|
||||
gitHubConnectionStatus={gitHubConnectionStatus}
|
||||
isCheckingGitHub={isCheckingGitHub}
|
||||
githubExpanded={expandedSections.github}
|
||||
onGitHubToggle={() => toggleSection('github')}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Memory Backend (Graphiti) */}
|
||||
<SecuritySettings
|
||||
envConfig={envConfig}
|
||||
settings={settings}
|
||||
setSettings={setSettings}
|
||||
updateEnvConfig={updateEnvConfig}
|
||||
showOpenAIKey={showOpenAIKey}
|
||||
setShowOpenAIKey={setShowOpenAIKey}
|
||||
expanded={expandedSections.graphiti}
|
||||
onToggle={() => toggleSection('graphiti')}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Error Display */}
|
||||
{(error || envError) && (
|
||||
<div className="rounded-lg bg-destructive/10 border border-destructive/30 p-3 text-sm text-destructive">
|
||||
{error || envError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="shrink-0">
|
||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={() => handleSave(() => onOpenChange(false))} disabled={isSaving || isSavingEnv}>
|
||||
{isSaving || isSavingEnv ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Saving...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Save className="mr-2 h-4 w-4" />
|
||||
Save Settings
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
{/* Linear Task Import Modal */}
|
||||
<LinearTaskImportModal
|
||||
projectId={project.id}
|
||||
open={showLinearImportModal}
|
||||
onOpenChange={setShowLinearImportModal}
|
||||
onImportComplete={(result) => {
|
||||
console.log('Import complete:', result);
|
||||
}}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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<AuthStatus>('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,
|
||||
};
|
||||
}
|
||||
@@ -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<ProjectEnvConfig | null>(null);
|
||||
const [isLoadingEnv, setIsLoadingEnv] = useState(false);
|
||||
const [envError, setEnvError] = useState<string | null>(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<ProjectEnvConfig>) => {
|
||||
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,
|
||||
};
|
||||
}
|
||||
@@ -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<GitHubSyncStatus | null>(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,
|
||||
};
|
||||
}
|
||||
@@ -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<InfrastructureStatus | null>(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,
|
||||
};
|
||||
}
|
||||
@@ -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<LinearSyncStatus | null>(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,
|
||||
};
|
||||
}
|
||||
@@ -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<ProjectSettings>(project.settings);
|
||||
const [versionInfo, setVersionInfo] = useState<AutoBuildVersionInfo | null>(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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user