diff --git a/frontend/src/app/settings/page.tsx b/frontend/src/app/settings/page.tsx index cc439f53..7530bcbb 100644 --- a/frontend/src/app/settings/page.tsx +++ b/frontend/src/app/settings/page.tsx @@ -1,7 +1,7 @@ "use client"; -import { ArrowUpRight, Loader2, PlugZap, RefreshCw } from "lucide-react"; -import { useSearchParams } from "next/navigation"; +import { ArrowUpRight, Loader2, PlugZap, Plus, RefreshCw } from "lucide-react"; +import { useRouter, useSearchParams } from "next/navigation"; import { Suspense, useCallback, useEffect, useState } from "react"; import { useUpdateFlowSettingMutation } from "@/app/api/mutations/useUpdateFlowSettingMutation"; import { @@ -35,7 +35,11 @@ import { Textarea } from "@/components/ui/textarea"; import { useAuth } from "@/contexts/auth-context"; import { useTask } from "@/contexts/task-context"; import { useDebounce } from "@/lib/debounce"; -import { DEFAULT_AGENT_SETTINGS, DEFAULT_KNOWLEDGE_SETTINGS, UI_CONSTANTS } from "@/lib/constants"; +import { + DEFAULT_AGENT_SETTINGS, + DEFAULT_KNOWLEDGE_SETTINGS, + UI_CONSTANTS, +} from "@/lib/constants"; import { getFallbackModels, type ModelProvider } from "./helpers/model-helpers"; import { ModelSelectItems } from "./helpers/model-select-item"; import { LabelWrapper } from "@/components/label-wrapper"; @@ -92,6 +96,7 @@ function KnowledgeSourcesPage() { const { isAuthenticated, isNoAuthMode } = useAuth(); const { addTask, tasks } = useTask(); const searchParams = useSearchParams(); + const router = useRouter(); // Connectors state const [connectors, setConnectors] = useState([]); @@ -159,7 +164,7 @@ function KnowledgeSourcesPage() { onSuccess: () => { console.log("Setting updated successfully"); }, - onError: (error) => { + onError: error => { console.error("Failed to update setting:", error.message); }, }); @@ -298,8 +303,8 @@ function KnowledgeSourcesPage() { // Initialize connectors list with metadata from backend const initialConnectors = connectorTypes - .filter((type) => connectorsResult.connectors[type].available) // Only show available connectors - .map((type) => ({ + .filter(type => connectorsResult.connectors[type].available) // Only show available connectors + .map(type => ({ id: type, name: connectorsResult.connectors[type].name, description: connectorsResult.connectors[type].description, @@ -322,8 +327,8 @@ function KnowledgeSourcesPage() { ); const isConnected = activeConnection !== undefined; - setConnectors((prev) => - prev.map((c) => + setConnectors(prev => + prev.map(c => c.type === connectorType ? { ...c, @@ -342,7 +347,7 @@ function KnowledgeSourcesPage() { const handleConnect = async (connector: Connector) => { setIsConnecting(connector.id); - setSyncResults((prev) => ({ ...prev, [connector.id]: null })); + setSyncResults(prev => ({ ...prev, [connector.id]: null })); try { // Use the shared auth callback URL, same as connectors page @@ -392,58 +397,58 @@ function KnowledgeSourcesPage() { } }; - const handleSync = async (connector: Connector) => { - if (!connector.connectionId) return; + // const handleSync = async (connector: Connector) => { + // if (!connector.connectionId) return; - setIsSyncing(connector.id); - setSyncResults((prev) => ({ ...prev, [connector.id]: null })); + // setIsSyncing(connector.id); + // setSyncResults(prev => ({ ...prev, [connector.id]: null })); - try { - const syncBody: { - connection_id: string; - max_files?: number; - selected_files?: string[]; - } = { - connection_id: connector.connectionId, - max_files: syncAllFiles ? 0 : maxFiles || undefined, - }; + // try { + // const syncBody: { + // connection_id: string; + // max_files?: number; + // selected_files?: string[]; + // } = { + // connection_id: connector.connectionId, + // max_files: syncAllFiles ? 0 : maxFiles || undefined, + // }; - // Note: File selection is now handled via the cloud connectors dialog + // // Note: File selection is now handled via the cloud connectors dialog - const response = await fetch(`/api/connectors/${connector.type}/sync`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(syncBody), - }); + // const response = await fetch(`/api/connectors/${connector.type}/sync`, { + // method: "POST", + // headers: { + // "Content-Type": "application/json", + // }, + // body: JSON.stringify(syncBody), + // }); - const result = await response.json(); + // const result = await response.json(); - if (response.status === 201) { - const taskId = result.task_id; - if (taskId) { - addTask(taskId); - setSyncResults((prev) => ({ - ...prev, - [connector.id]: { - processed: 0, - total: result.total_files || 0, - }, - })); - } - } else if (response.ok) { - setSyncResults((prev) => ({ ...prev, [connector.id]: result })); - // Note: Stats will auto-refresh via task completion watcher for async syncs - } else { - console.error("Sync failed:", result.error); - } - } catch (error) { - console.error("Sync error:", error); - } finally { - setIsSyncing(null); - } - }; + // if (response.status === 201) { + // const taskId = result.task_id; + // if (taskId) { + // addTask(taskId); + // setSyncResults(prev => ({ + // ...prev, + // [connector.id]: { + // processed: 0, + // total: result.total_files || 0, + // }, + // })); + // } + // } else if (response.ok) { + // setSyncResults(prev => ({ ...prev, [connector.id]: result })); + // // Note: Stats will auto-refresh via task completion watcher for async syncs + // } else { + // console.error("Sync failed:", result.error); + // } + // } catch (error) { + // console.error("Sync error:", error); + // } finally { + // setIsSyncing(null); + // } + // }; const getStatusBadge = (status: Connector["status"]) => { switch (status) { @@ -479,6 +484,11 @@ function KnowledgeSourcesPage() { } }; + const navigateToKnowledgePage = (connector: Connector) => { + const provider = connector.type.replace(/-/g, "_"); + router.push(`/upload/${provider}`); + }; + // Check connector status on mount and when returning from OAuth useEffect(() => { if (isAuthenticated) { @@ -498,9 +508,9 @@ function KnowledgeSourcesPage() { // Watch for task completions and refresh stats useEffect(() => { // Find newly completed tasks by comparing with previous state - const newlyCompletedTasks = tasks.filter((task) => { + const newlyCompletedTasks = tasks.filter(task => { const wasCompleted = - prevTasks.find((prev) => prev.task_id === task.task_id)?.status === + prevTasks.find(prev => prev.task_id === task.task_id)?.status === "completed"; return task.status === "completed" && !wasCompleted; }); @@ -554,7 +564,7 @@ function KnowledgeSourcesPage() { fetch(`/api/reset-flow/retrieval`, { method: "POST", }) - .then((response) => { + .then(response => { if (response.ok) { return response.json(); } @@ -567,7 +577,7 @@ function KnowledgeSourcesPage() { handleModelChange(DEFAULT_AGENT_SETTINGS.llm_model); closeDialog(); // Close after successful completion }) - .catch((error) => { + .catch(error => { console.error("Error restoring retrieval flow:", error); closeDialog(); // Close even on error (could show error toast instead) }); @@ -577,7 +587,7 @@ function KnowledgeSourcesPage() { fetch(`/api/reset-flow/ingest`, { method: "POST", }) - .then((response) => { + .then(response => { if (response.ok) { return response.json(); } @@ -592,7 +602,7 @@ function KnowledgeSourcesPage() { setPictureDescriptions(false); closeDialog(); // Close after successful completion }) - .catch((error) => { + .catch(error => { console.error("Error restoring ingest flow:", error); closeDialog(); // Close even on error (could show error toast instead) }); @@ -609,85 +619,88 @@ function KnowledgeSourcesPage() { {/* Conditional Sync Settings or No-Auth Message */} - {isNoAuthMode ? ( - - - - Cloud connectors are only available with auth mode enabled - - - Please provide the following environment variables and restart: - - - -
-
- # make here https://console.cloud.google.com/apis/credentials + { + isNoAuthMode ? ( + + + + Cloud connectors are only available with auth mode enabled + + + Please provide the following environment variables and + restart: + + + +
+
+ # make here + https://console.cloud.google.com/apis/credentials +
+
GOOGLE_OAUTH_CLIENT_ID=
+
GOOGLE_OAUTH_CLIENT_SECRET=
-
GOOGLE_OAUTH_CLIENT_ID=
-
GOOGLE_OAUTH_CLIENT_SECRET=
-
- - - ) : ( -
-
-

Sync Settings

-

- Configure how many files to sync when manually triggering a sync -

-
-
-
- { - setSyncAllFiles(!!checked); - if (checked) { - setMaxFiles(0); - } else { - setMaxFiles(10); - } - }} - /> - -
- -
- setMaxFiles(parseInt(e.target.value) || 10)} - disabled={syncAllFiles} - className="w-16 min-w-16 max-w-16 flex-shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" - min="1" - max="100" - title={ - syncAllFiles - ? "Disabled when 'Sync all files' is checked" - : "Leave blank or set to 0 for unlimited" - } - /> -
-
-
- )} + + + ) : null + //
+ //
+ //

Sync Settings

+ //

+ // Configure how many files to sync when manually triggering a sync + //

+ //
+ //
+ //
+ // { + // setSyncAllFiles(!!checked); + // if (checked) { + // setMaxFiles(0); + // } else { + // setMaxFiles(10); + // } + // }} + // /> + // + //
+ // + //
+ // setMaxFiles(parseInt(e.target.value) || 10)} + // disabled={syncAllFiles} + // className="w-16 min-w-16 max-w-16 flex-shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" + // min="1" + // max="100" + // title={ + // syncAllFiles + // ? "Disabled when 'Sync all files' is checked" + // : "Leave blank or set to 0 for unlimited" + // } + // /> + //
+ //
+ //
+ } {/* Connectors Grid */}
- {connectors.map((connector) => ( + {connectors.map(connector => (
@@ -709,22 +722,13 @@ function KnowledgeSourcesPage() { {connector.status === "connected" ? (
{syncResults[connector.id] && ( @@ -830,7 +834,7 @@ function KnowledgeSourcesPage() { } confirmText="Proceed" confirmIcon={} - onConfirm={(closeDialog) => + onConfirm={closeDialog => handleEditInLangflow("chat", closeDialog) } variant="warning" @@ -850,8 +854,7 @@ function KnowledgeSourcesPage() {