diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.js b/src/app/(dashboard)/dashboard/providers/[id]/page.js index d2ee0d3e..e034df7e 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/page.js +++ b/src/app/(dashboard)/dashboard/providers/[id]/page.js @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect, useCallback } from "react"; +import { useState, useEffect, useCallback, useRef } from "react"; import PropTypes from "prop-types"; import { useParams, useRouter } from "next/navigation"; import Link from "next/link"; @@ -364,35 +364,6 @@ export default function ProviderDetailPage() { } }; - const selectionToolbar = connections.length > 0 ? ( -
-
- - {selectedConnectionIds.length > 0 && ( - - )} -
- -
- {selectedConnectionIds.length} selected - -
-
- ) : null; const isSelected = (connectionId) => selectedConnectionIds.includes(connectionId); @@ -402,16 +373,6 @@ export default function ProviderDetailPage() { .sort((a, b) => (a.priority || 0) - (b.priority || 0)) .map((conn, index) => (
-
- toggleSelectConnection(conn.id)} - className="size-4 rounded border-border bg-transparent" - title="Select connection" - aria-label={`Select ${conn.name || conn.email || conn.id}`} - /> -
handleSwapPriority(conn, connections[index - 1])} onMoveDown={() => handleSwapPriority(conn, connections[index + 1])} onToggleActive={(isActive) => handleUpdateConnectionStatus(conn.id, isActive)} + onUpdateProxy={async (proxyPoolId) => { + try { + const res = await fetch(`/api/providers/${conn.id}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ proxyPoolId: proxyPoolId || null }), + }); + if (res.ok) { + setConnections(prev => prev.map(c => + c.id === conn.id + ? { ...c, providerSpecificData: { ...c.providerSpecificData, proxyPoolId: proxyPoolId || null } } + : c + )); + } + } catch (error) { + console.log("Error updating proxy:", error); + } + }} onEdit={() => { setSelectedConnection(conn); setShowEditModal(true); @@ -770,7 +749,6 @@ export default function ProviderDetailPage() {
) : ( <> - {selectionToolbar} {connectionsList} )} @@ -1322,7 +1300,11 @@ CooldownTimer.propTypes = { until: PropTypes.string.isRequired, }; -function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMoveUp, onMoveDown, onToggleActive, onEdit, onDelete }) { +function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMoveUp, onMoveDown, onToggleActive, onUpdateProxy, onEdit, onDelete }) { + const [showProxyDropdown, setShowProxyDropdown] = useState(false); + const [updatingProxy, setUpdatingProxy] = useState(false); + const proxyDropdownRef = useRef(null); + const proxyPoolMap = new Map((proxyPools || []).map((pool) => [pool.id, pool])); const boundProxyPoolId = connection.providerSpecificData?.proxyPoolId || null; const boundProxyPool = boundProxyPoolId ? proxyPoolMap.get(boundProxyPoolId) : null; @@ -1336,13 +1318,6 @@ function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMov ? `Legacy: ${connection.providerSpecificData?.connectionProxyUrl}` : ""; - let proxyBadgeVariant = "default"; - if (boundProxyPool?.isActive === true) { - proxyBadgeVariant = "success"; - } else if (boundProxyPoolId || hasLegacyProxy) { - proxyBadgeVariant = "error"; - } - let maskedProxyUrl = ""; if (boundProxyPool?.proxyUrl || connection.providerSpecificData?.connectionProxyUrl) { const rawProxyUrl = boundProxyPool?.proxyUrl || connection.providerSpecificData?.connectionProxyUrl; @@ -1356,6 +1331,35 @@ function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMov const noProxyText = boundProxyPool?.noProxy || connection.providerSpecificData?.connectionNoProxy || ""; + let proxyBadgeVariant = "default"; + if (boundProxyPool?.isActive === true) { + proxyBadgeVariant = "success"; + } else if (boundProxyPoolId || hasLegacyProxy) { + proxyBadgeVariant = "error"; + } + + // Close dropdown when clicking outside + useEffect(() => { + if (!showProxyDropdown) return; + const handler = (e) => { + if (proxyDropdownRef.current && !proxyDropdownRef.current.contains(e.target)) { + setShowProxyDropdown(false); + } + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, [showProxyDropdown]); + + const handleSelectProxy = async (poolId) => { + setUpdatingProxy(true); + try { + await onUpdateProxy(poolId === "__none__" ? null : poolId); + } finally { + setUpdatingProxy(false); + setShowProxyDropdown(false); + } + }; + const displayName = isOAuth ? connection.name || connection.email || connection.displayName || "OAuth Account" : connection.name; @@ -1464,20 +1468,56 @@ function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMov
+
+ {/* Proxy button with inline dropdown */} + {(proxyPools || []).length > 0 && ( +
+ + {showProxyDropdown && ( +
+ + {(proxyPools || []).map((pool) => ( + + ))} +
+ )} +
+ )} + + +
-
- - -
); @@ -1509,6 +1549,7 @@ ConnectionRow.propTypes = { onMoveUp: PropTypes.func.isRequired, onMoveDown: PropTypes.func.isRequired, onToggleActive: PropTypes.func.isRequired, + onUpdateProxy: PropTypes.func, onEdit: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, }; @@ -1672,13 +1713,10 @@ AddApiKeyModal.propTypes = { }; function EditConnectionModal({ isOpen, connection, proxyPools, onSave, onClose }) { - const NONE_PROXY_POOL_VALUE = "__none__"; - const [formData, setFormData] = useState({ name: "", priority: 1, apiKey: "", - proxyPoolId: NONE_PROXY_POOL_VALUE, }); const [testing, setTesting] = useState(false); const [testResult, setTestResult] = useState(null); @@ -1692,7 +1730,6 @@ function EditConnectionModal({ isOpen, connection, proxyPools, onSave, onClose } name: connection.name || "", priority: connection.priority || 1, apiKey: "", - proxyPoolId: connection.providerSpecificData?.proxyPoolId || NONE_PROXY_POOL_VALUE, }); setTestResult(null); setValidationResult(null); @@ -1739,7 +1776,6 @@ function EditConnectionModal({ isOpen, connection, proxyPools, onSave, onClose } const updates = { name: formData.name, priority: formData.priority, - proxyPoolId: formData.proxyPoolId === NONE_PROXY_POOL_VALUE ? null : formData.proxyPoolId, }; if (!isOAuth && formData.apiKey) { updates.apiKey = formData.apiKey; @@ -1801,58 +1837,6 @@ function EditConnectionModal({ isOpen, connection, proxyPools, onSave, onClose } onChange={(e) => setFormData({ ...formData, priority: Number.parseInt(e.target.value) || 1 })} /> -