update edit connectors page to support linear connector

This commit is contained in:
Adamsmith6300 2025-04-16 22:06:50 -07:00
parent f2f426d5eb
commit 32c721113c
5 changed files with 68 additions and 23 deletions

View file

@ -18,8 +18,9 @@ from app.db import get_async_session, User, SearchSourceConnector, SearchSourceC
from app.schemas import SearchSourceConnectorCreate, SearchSourceConnectorUpdate, SearchSourceConnectorRead, SearchSourceConnectorBase from app.schemas import SearchSourceConnectorCreate, SearchSourceConnectorUpdate, SearchSourceConnectorRead, SearchSourceConnectorBase
from app.users import current_active_user from app.users import current_active_user
from app.utils.check_ownership import check_ownership from app.utils.check_ownership import check_ownership
from pydantic import ValidationError from pydantic import BaseModel, Field, ValidationError
from app.tasks.connectors_indexing_tasks import index_slack_messages, index_notion_pages, index_github_repos, index_linear_issues from app.tasks.connectors_indexing_tasks import index_slack_messages, index_notion_pages, index_github_repos, index_linear_issues
from app.connectors.github_connector import GitHubConnector
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
import logging import logging
@ -28,7 +29,7 @@ logger = logging.getLogger(__name__)
router = APIRouter() router = APIRouter()
# --- New Schema for GitHub PAT --- # Use Pydantic's BaseModel here
class GitHubPATRequest(BaseModel): class GitHubPATRequest(BaseModel):
github_pat: str = Field(..., description="GitHub Personal Access Token") github_pat: str = Field(..., description="GitHub Personal Access Token")
@ -104,6 +105,7 @@ async def create_search_source_connector(
await session.rollback() await session.rollback()
raise raise
except Exception as e: except Exception as e:
logger.error(f"Failed to create search source connector: {str(e)}")
await session.rollback() await session.rollback()
raise HTTPException( raise HTTPException(
status_code=500, status_code=500,

View file

@ -149,6 +149,17 @@ export default function EditConnectorPage() {
/> />
)} )}
{/* == Linear == */}
{connector.connector_type === 'LINEAR_CONNECTOR' && (
<EditSimpleTokenForm
control={editForm.control}
fieldName="LINEAR_API_KEY"
fieldLabel="Linear API Key"
fieldDescription="Update your Linear API Key if needed."
placeholder="Begins with lin_api_..."
/>
)}
</CardContent> </CardContent>
<CardFooter className="border-t pt-6"> <CardFooter className="border-t pt-6">
<Button type="submit" disabled={isSaving} className="w-full sm:w-auto"> <Button type="submit" disabled={isSaving} className="w-full sm:w-auto">

View file

@ -29,5 +29,6 @@ export const editConnectorSchema = z.object({
NOTION_INTEGRATION_TOKEN: z.string().optional(), NOTION_INTEGRATION_TOKEN: z.string().optional(),
SERPER_API_KEY: z.string().optional(), SERPER_API_KEY: z.string().optional(),
TAVILY_API_KEY: z.string().optional(), TAVILY_API_KEY: z.string().optional(),
LINEAR_API_KEY: z.string().optional(),
}); });
export type EditConnectorFormValues = z.infer<typeof editConnectorSchema>; export type EditConnectorFormValues = z.infer<typeof editConnectorSchema>;

View file

@ -35,7 +35,14 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
}); });
const editForm = useForm<EditConnectorFormValues>({ const editForm = useForm<EditConnectorFormValues>({
resolver: zodResolver(editConnectorSchema), resolver: zodResolver(editConnectorSchema),
defaultValues: { name: "", SLACK_BOT_TOKEN: "", NOTION_INTEGRATION_TOKEN: "", SERPER_API_KEY: "", TAVILY_API_KEY: "" }, defaultValues: {
name: "",
SLACK_BOT_TOKEN: "",
NOTION_INTEGRATION_TOKEN: "",
SERPER_API_KEY: "",
TAVILY_API_KEY: "",
LINEAR_API_KEY: ""
},
}); });
// Effect to load initial data // Effect to load initial data
@ -52,6 +59,7 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
NOTION_INTEGRATION_TOKEN: config.NOTION_INTEGRATION_TOKEN || "", NOTION_INTEGRATION_TOKEN: config.NOTION_INTEGRATION_TOKEN || "",
SERPER_API_KEY: config.SERPER_API_KEY || "", SERPER_API_KEY: config.SERPER_API_KEY || "",
TAVILY_API_KEY: config.TAVILY_API_KEY || "", TAVILY_API_KEY: config.TAVILY_API_KEY || "",
LINEAR_API_KEY: config.LINEAR_API_KEY || ""
}); });
if (currentConnector.connector_type === 'GITHUB_CONNECTOR') { if (currentConnector.connector_type === 'GITHUB_CONNECTOR') {
const savedRepos = config.repo_full_names || []; const savedRepos = config.repo_full_names || [];
@ -127,25 +135,35 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
newConfig = { SLACK_BOT_TOKEN: formData.SLACK_BOT_TOKEN }; newConfig = { SLACK_BOT_TOKEN: formData.SLACK_BOT_TOKEN };
} }
break; break;
// ... other cases ...
case 'NOTION_CONNECTOR': case 'NOTION_CONNECTOR':
if (formData.NOTION_INTEGRATION_TOKEN !== originalConfig.NOTION_INTEGRATION_TOKEN) { if (formData.NOTION_INTEGRATION_TOKEN !== originalConfig.NOTION_INTEGRATION_TOKEN) {
if (!formData.NOTION_INTEGRATION_TOKEN) { toast.error("Notion Token empty."); setIsSaving(false); return; } if (!formData.NOTION_INTEGRATION_TOKEN) { toast.error("Notion Token empty."); setIsSaving(false); return; }
newConfig = { NOTION_INTEGRATION_TOKEN: formData.NOTION_INTEGRATION_TOKEN }; newConfig = { NOTION_INTEGRATION_TOKEN: formData.NOTION_INTEGRATION_TOKEN };
} }
break; break;
case 'SERPER_API': case 'SERPER_API':
if (formData.SERPER_API_KEY !== originalConfig.SERPER_API_KEY) { if (formData.SERPER_API_KEY !== originalConfig.SERPER_API_KEY) {
if (!formData.SERPER_API_KEY) { toast.error("Serper Key empty."); setIsSaving(false); return; } if (!formData.SERPER_API_KEY) { toast.error("Serper Key empty."); setIsSaving(false); return; }
newConfig = { SERPER_API_KEY: formData.SERPER_API_KEY }; newConfig = { SERPER_API_KEY: formData.SERPER_API_KEY };
} }
break; break;
case 'TAVILY_API': case 'TAVILY_API':
if (formData.TAVILY_API_KEY !== originalConfig.TAVILY_API_KEY) { if (formData.TAVILY_API_KEY !== originalConfig.TAVILY_API_KEY) {
if (!formData.TAVILY_API_KEY) { toast.error("Tavily Key empty."); setIsSaving(false); return; } if (!formData.TAVILY_API_KEY) { toast.error("Tavily Key empty."); setIsSaving(false); return; }
newConfig = { TAVILY_API_KEY: formData.TAVILY_API_KEY }; newConfig = { TAVILY_API_KEY: formData.TAVILY_API_KEY };
} }
break; break;
case 'LINEAR_CONNECTOR':
if (formData.LINEAR_API_KEY !== originalConfig.LINEAR_API_KEY) {
if (!formData.LINEAR_API_KEY) {
toast.error("Linear API Key cannot be empty.");
setIsSaving(false);
return;
}
newConfig = { LINEAR_API_KEY: formData.LINEAR_API_KEY };
}
break;
} }
if (newConfig !== null) { if (newConfig !== null) {
@ -168,12 +186,24 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
if (updatePayload.name) { if (updatePayload.name) {
setConnector(prev => prev ? { ...prev, name: updatePayload.name!, config: newlySavedConfig } : null); setConnector(prev => prev ? { ...prev, name: updatePayload.name!, config: newlySavedConfig } : null);
} }
if (connector.connector_type === 'GITHUB_CONNECTOR' && configChanged) { if (configChanged) {
const savedGitHubConfig = newlySavedConfig as { GITHUB_PAT?: string; repo_full_names?: string[] }; if (connector.connector_type === 'GITHUB_CONNECTOR') {
setCurrentSelectedRepos(savedGitHubConfig.repo_full_names || []); const savedGitHubConfig = newlySavedConfig as { GITHUB_PAT?: string; repo_full_names?: string[] };
setOriginalPat(savedGitHubConfig.GITHUB_PAT || ""); setCurrentSelectedRepos(savedGitHubConfig.repo_full_names || []);
setNewSelectedRepos(savedGitHubConfig.repo_full_names || []); setOriginalPat(savedGitHubConfig.GITHUB_PAT || "");
patForm.reset({ github_pat: savedGitHubConfig.GITHUB_PAT || "" }); setNewSelectedRepos(savedGitHubConfig.repo_full_names || []);
patForm.reset({ github_pat: savedGitHubConfig.GITHUB_PAT || "" });
} else if(connector.connector_type === 'SLACK_CONNECTOR') {
editForm.setValue('SLACK_BOT_TOKEN', newlySavedConfig.SLACK_BOT_TOKEN || "");
} else if(connector.connector_type === 'NOTION_CONNECTOR') {
editForm.setValue('NOTION_INTEGRATION_TOKEN', newlySavedConfig.NOTION_INTEGRATION_TOKEN || "");
} else if(connector.connector_type === 'SERPER_API') {
editForm.setValue('SERPER_API_KEY', newlySavedConfig.SERPER_API_KEY || "");
} else if(connector.connector_type === 'TAVILY_API') {
editForm.setValue('TAVILY_API_KEY', newlySavedConfig.TAVILY_API_KEY || "");
} else if(connector.connector_type === 'LINEAR_CONNECTOR') {
editForm.setValue('LINEAR_API_KEY', newlySavedConfig.LINEAR_API_KEY || "");
}
} }
if (connector.connector_type === 'GITHUB_CONNECTOR') { if (connector.connector_type === 'GITHUB_CONNECTOR') {
setEditMode('viewing'); setEditMode('viewing');
@ -184,7 +214,7 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
console.error("Error updating connector:", error); console.error("Error updating connector:", error);
toast.error(error instanceof Error ? error.message : "Failed to update connector."); toast.error(error instanceof Error ? error.message : "Failed to update connector.");
} finally { setIsSaving(false); } } finally { setIsSaving(false); }
}, [connector, originalConfig, updateConnector, connectorId, patForm, originalPat, currentSelectedRepos, newSelectedRepos, editMode, fetchedRepos]); // Added dependencies }, [connector, originalConfig, updateConnector, connectorId, patForm, originalPat, currentSelectedRepos, newSelectedRepos, editMode, fetchedRepos, editForm]); // Added editForm to dependencies
// Return values needed by the component // Return values needed by the component
return { return {

View file

@ -6,6 +6,7 @@ export const getConnectorTypeDisplay = (type: string): string => {
"SLACK_CONNECTOR": "Slack", "SLACK_CONNECTOR": "Slack",
"NOTION_CONNECTOR": "Notion", "NOTION_CONNECTOR": "Notion",
"GITHUB_CONNECTOR": "GitHub", "GITHUB_CONNECTOR": "GitHub",
"LINEAR_CONNECTOR": "Linear",
}; };
return typeMap[type] || type; return typeMap[type] || type;
}; };