fixed spacing and flex
This commit is contained in:
parent
1d4a91eb7b
commit
1dc0a370f1
6 changed files with 641 additions and 782 deletions
|
|
@ -25,6 +25,7 @@ import {
|
||||||
FilterIconPopover,
|
FilterIconPopover,
|
||||||
IconKey,
|
IconKey,
|
||||||
} from "@/components/filter-icon-popover";
|
} from "@/components/filter-icon-popover";
|
||||||
|
import { useLayout } from "@/contexts/layout-context";
|
||||||
|
|
||||||
interface FacetBucket {
|
interface FacetBucket {
|
||||||
key: string;
|
key: string;
|
||||||
|
|
@ -48,7 +49,15 @@ export const filterAccentClasses: Record<FilterColor, string> = {
|
||||||
red: "bg-accent-red text-accent-red-foreground",
|
red: "bg-accent-red text-accent-red-foreground",
|
||||||
};
|
};
|
||||||
|
|
||||||
export function KnowledgeFilterPanel() {
|
interface KnowledgeFilterPanelProps {
|
||||||
|
totalTopOffset: number;
|
||||||
|
headerHeight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function KnowledgeFilterPanel({
|
||||||
|
totalTopOffset,
|
||||||
|
headerHeight,
|
||||||
|
}: KnowledgeFilterPanelProps) {
|
||||||
const {
|
const {
|
||||||
selectedFilter,
|
selectedFilter,
|
||||||
parsedFilterData,
|
parsedFilterData,
|
||||||
|
|
@ -135,7 +144,7 @@ export function KnowledgeFilterPanel() {
|
||||||
// Load available facets using search aggregations hook
|
// Load available facets using search aggregations hook
|
||||||
const { data: aggregations } = useGetSearchAggregations("*", 1, 0, {
|
const { data: aggregations } = useGetSearchAggregations("*", 1, 0, {
|
||||||
enabled: isPanelOpen,
|
enabled: isPanelOpen,
|
||||||
placeholderData: (prev) => prev,
|
placeholderData: prev => prev,
|
||||||
staleTime: 60_000,
|
staleTime: 60_000,
|
||||||
gcTime: 5 * 60_000,
|
gcTime: 5 * 60_000,
|
||||||
});
|
});
|
||||||
|
|
@ -213,7 +222,7 @@ export function KnowledgeFilterPanel() {
|
||||||
facetType: keyof typeof selectedFilters,
|
facetType: keyof typeof selectedFilters,
|
||||||
newValues: string[]
|
newValues: string[]
|
||||||
) => {
|
) => {
|
||||||
setSelectedFilters((prev) => ({
|
setSelectedFilters(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
[facetType]: newValues,
|
[facetType]: newValues,
|
||||||
}));
|
}));
|
||||||
|
|
@ -231,7 +240,10 @@ export function KnowledgeFilterPanel() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed right-0 top-14 bottom-0 w-80 bg-background border-l z-40 overflow-y-auto">
|
<div
|
||||||
|
className={`fixed right-0 bottom-0 w-80 bg-background border-l z-40 overflow-y-auto`}
|
||||||
|
style={{ top: `${totalTopOffset}px` }}
|
||||||
|
>
|
||||||
<Card className="h-full rounded-none border-0 shadow-lg flex flex-col">
|
<Card className="h-full rounded-none border-0 shadow-lg flex flex-col">
|
||||||
<CardHeader className="pb-3">
|
<CardHeader className="pb-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -270,7 +282,7 @@ export function KnowledgeFilterPanel() {
|
||||||
<Input
|
<Input
|
||||||
id="filter-name"
|
id="filter-name"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => {
|
onChange={e => {
|
||||||
const v = e.target.value;
|
const v = e.target.value;
|
||||||
setName(v);
|
setName(v);
|
||||||
if (nameError && v.trim()) {
|
if (nameError && v.trim()) {
|
||||||
|
|
@ -301,7 +313,7 @@ export function KnowledgeFilterPanel() {
|
||||||
<Textarea
|
<Textarea
|
||||||
id="filter-description"
|
id="filter-description"
|
||||||
value={description}
|
value={description}
|
||||||
onChange={(e) => setDescription(e.target.value)}
|
onChange={e => setDescription(e.target.value)}
|
||||||
placeholder="Provide a brief description of your knowledge filter..."
|
placeholder="Provide a brief description of your knowledge filter..."
|
||||||
rows={3}
|
rows={3}
|
||||||
/>
|
/>
|
||||||
|
|
@ -318,7 +330,7 @@ export function KnowledgeFilterPanel() {
|
||||||
placeholder="Enter your search query..."
|
placeholder="Enter your search query..."
|
||||||
value={query}
|
value={query}
|
||||||
className="font-mono placeholder:font-mono"
|
className="font-mono placeholder:font-mono"
|
||||||
onChange={(e) => setQuery(e.target.value)}
|
onChange={e => setQuery(e.target.value)}
|
||||||
rows={2}
|
rows={2}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -327,13 +339,13 @@ export function KnowledgeFilterPanel() {
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
options={(availableFacets.data_sources || []).map((bucket) => ({
|
options={(availableFacets.data_sources || []).map(bucket => ({
|
||||||
value: bucket.key,
|
value: bucket.key,
|
||||||
label: bucket.key,
|
label: bucket.key,
|
||||||
count: bucket.count,
|
count: bucket.count,
|
||||||
}))}
|
}))}
|
||||||
value={selectedFilters.data_sources}
|
value={selectedFilters.data_sources}
|
||||||
onValueChange={(values) =>
|
onValueChange={values =>
|
||||||
handleFilterChange("data_sources", values)
|
handleFilterChange("data_sources", values)
|
||||||
}
|
}
|
||||||
placeholder="Select sources..."
|
placeholder="Select sources..."
|
||||||
|
|
@ -343,15 +355,13 @@ export function KnowledgeFilterPanel() {
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
options={(availableFacets.document_types || []).map(
|
options={(availableFacets.document_types || []).map(bucket => ({
|
||||||
(bucket) => ({
|
|
||||||
value: bucket.key,
|
value: bucket.key,
|
||||||
label: bucket.key,
|
label: bucket.key,
|
||||||
count: bucket.count,
|
count: bucket.count,
|
||||||
})
|
}))}
|
||||||
)}
|
|
||||||
value={selectedFilters.document_types}
|
value={selectedFilters.document_types}
|
||||||
onValueChange={(values) =>
|
onValueChange={values =>
|
||||||
handleFilterChange("document_types", values)
|
handleFilterChange("document_types", values)
|
||||||
}
|
}
|
||||||
placeholder="Select types..."
|
placeholder="Select types..."
|
||||||
|
|
@ -361,13 +371,13 @@ export function KnowledgeFilterPanel() {
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
options={(availableFacets.owners || []).map((bucket) => ({
|
options={(availableFacets.owners || []).map(bucket => ({
|
||||||
value: bucket.key,
|
value: bucket.key,
|
||||||
label: bucket.key,
|
label: bucket.key,
|
||||||
count: bucket.count,
|
count: bucket.count,
|
||||||
}))}
|
}))}
|
||||||
value={selectedFilters.owners}
|
value={selectedFilters.owners}
|
||||||
onValueChange={(values) => handleFilterChange("owners", values)}
|
onValueChange={values => handleFilterChange("owners", values)}
|
||||||
placeholder="Select owners..."
|
placeholder="Select owners..."
|
||||||
allOptionLabel="All Owners"
|
allOptionLabel="All Owners"
|
||||||
/>
|
/>
|
||||||
|
|
@ -376,14 +386,14 @@ export function KnowledgeFilterPanel() {
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
options={(availableFacets.connector_types || []).map(
|
options={(availableFacets.connector_types || []).map(
|
||||||
(bucket) => ({
|
bucket => ({
|
||||||
value: bucket.key,
|
value: bucket.key,
|
||||||
label: bucket.key,
|
label: bucket.key,
|
||||||
count: bucket.count,
|
count: bucket.count,
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
value={selectedFilters.connector_types}
|
value={selectedFilters.connector_types}
|
||||||
onValueChange={(values) =>
|
onValueChange={values =>
|
||||||
handleFilterChange("connector_types", values)
|
handleFilterChange("connector_types", values)
|
||||||
}
|
}
|
||||||
placeholder="Select connectors..."
|
placeholder="Select connectors..."
|
||||||
|
|
@ -403,7 +413,7 @@ export function KnowledgeFilterPanel() {
|
||||||
min="1"
|
min="1"
|
||||||
max="1000"
|
max="1000"
|
||||||
value={resultLimit}
|
value={resultLimit}
|
||||||
onChange={(e) => {
|
onChange={e => {
|
||||||
const newLimit = Math.max(
|
const newLimit = Math.max(
|
||||||
1,
|
1,
|
||||||
Math.min(1000, parseInt(e.target.value) || 1)
|
Math.min(1000, parseInt(e.target.value) || 1)
|
||||||
|
|
@ -416,7 +426,7 @@ export function KnowledgeFilterPanel() {
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
value={[resultLimit]}
|
value={[resultLimit]}
|
||||||
onValueChange={(values) => setResultLimit(values[0])}
|
onValueChange={values => setResultLimit(values[0])}
|
||||||
max={1000}
|
max={1000}
|
||||||
min={1}
|
min={1}
|
||||||
step={1}
|
step={1}
|
||||||
|
|
@ -436,7 +446,7 @@ export function KnowledgeFilterPanel() {
|
||||||
max="5"
|
max="5"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
value={scoreThreshold}
|
value={scoreThreshold}
|
||||||
onChange={(e) =>
|
onChange={e =>
|
||||||
setScoreThreshold(parseFloat(e.target.value) || 0)
|
setScoreThreshold(parseFloat(e.target.value) || 0)
|
||||||
}
|
}
|
||||||
className="h-6 text-xs text-right px-2 bg-muted/30 !border-0 rounded ml-auto focus:ring-0 focus:outline-none"
|
className="h-6 text-xs text-right px-2 bg-muted/30 !border-0 rounded ml-auto focus:ring-0 focus:outline-none"
|
||||||
|
|
@ -445,7 +455,7 @@ export function KnowledgeFilterPanel() {
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
value={[scoreThreshold]}
|
value={[scoreThreshold]}
|
||||||
onValueChange={(values) => setScoreThreshold(values[0])}
|
onValueChange={values => setScoreThreshold(values[0])}
|
||||||
max={5}
|
max={5}
|
||||||
min={0}
|
min={0}
|
||||||
step={0.1}
|
step={0.1}
|
||||||
|
|
|
||||||
|
|
@ -2047,21 +2047,10 @@ function ChatPage() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="h-full flex flex-col container">
|
||||||
className={`fixed inset-0 md:left-72 flex flex-col transition-all duration-300 ${
|
|
||||||
isMenuOpen && isPanelOpen
|
|
||||||
? "md:right-[704px]" // Both open: 384px (menu) + 320px (KF panel)
|
|
||||||
: isMenuOpen
|
|
||||||
? "md:right-96" // Only menu open: 384px
|
|
||||||
: isPanelOpen
|
|
||||||
? "md:right-80" // Only KF panel open: 320px
|
|
||||||
: "md:right-6" // Neither open: 24px
|
|
||||||
}`}
|
|
||||||
style={{ top: `${totalTopOffset}px` }}
|
|
||||||
>
|
|
||||||
{/* Debug header - only show in debug mode */}
|
{/* Debug header - only show in debug mode */}
|
||||||
{isDebugMode && (
|
{isDebugMode && (
|
||||||
<div className="flex items-center justify-between mb-6 px-6 pt-6">
|
<div className="flex items-center justify-between mb-6 px-6 pt-6 ">
|
||||||
<div className="flex items-center gap-2"></div>
|
<div className="flex items-center gap-2"></div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{/* Async Mode Toggle */}
|
{/* Async Mode Toggle */}
|
||||||
|
|
|
||||||
|
|
@ -133,22 +133,8 @@ function ChunksPageContent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="flex flex-row h-full">
|
||||||
className={`fixed inset-0 md:left-72 flex flex-row transition-all duration-300 ${
|
<div className="flex-1 flex flex-col min-h-0">
|
||||||
isMenuOpen && isPanelOpen
|
|
||||||
? "md:right-[704px]"
|
|
||||||
: // Both open: 384px (menu) + 320px (KF panel)
|
|
||||||
isMenuOpen
|
|
||||||
? "md:right-96"
|
|
||||||
: // Only menu open: 384px
|
|
||||||
isPanelOpen
|
|
||||||
? "md:right-80"
|
|
||||||
: // Only KF panel open: 320px
|
|
||||||
"md:right-6" // Neither open: 24px
|
|
||||||
}`}
|
|
||||||
style={{ top: `${totalTopOffset}px` }}
|
|
||||||
>
|
|
||||||
<div className="flex-1 flex flex-col min-h-0 px-6 py-6">
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col mb-6">
|
<div className="flex flex-col mb-6">
|
||||||
<div className="flex flex-row items-center gap-3 mb-6">
|
<div className="flex flex-row items-center gap-3 mb-6">
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import { KnowledgeDropdown } from "@/components/knowledge-dropdown";
|
||||||
import { ProtectedRoute } from "@/components/protected-route";
|
import { ProtectedRoute } from "@/components/protected-route";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useKnowledgeFilter } from "@/contexts/knowledge-filter-context";
|
import { useKnowledgeFilter } from "@/contexts/knowledge-filter-context";
|
||||||
import { useLayout } from "@/contexts/layout-context";
|
|
||||||
import { useTask } from "@/contexts/task-context";
|
import { useTask } from "@/contexts/task-context";
|
||||||
import { type File, useGetSearchQuery } from "../api/queries/useGetSearchQuery";
|
import { type File, useGetSearchQuery } from "../api/queries/useGetSearchQuery";
|
||||||
import "@/components/AgGrid/registerAgGridModules";
|
import "@/components/AgGrid/registerAgGridModules";
|
||||||
|
|
@ -47,9 +46,8 @@ function getSourceIcon(connectorType?: string) {
|
||||||
|
|
||||||
function SearchPage() {
|
function SearchPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { isMenuOpen, files: taskFiles } = useTask();
|
const { files: taskFiles } = useTask();
|
||||||
const { totalTopOffset } = useLayout();
|
const { selectedFilter, setSelectedFilter, parsedFilterData } =
|
||||||
const { selectedFilter, setSelectedFilter, parsedFilterData, isPanelOpen } =
|
|
||||||
useKnowledgeFilter();
|
useKnowledgeFilter();
|
||||||
const [selectedRows, setSelectedRows] = useState<File[]>([]);
|
const [selectedRows, setSelectedRows] = useState<File[]>([]);
|
||||||
const [showBulkDeleteDialog, setShowBulkDeleteDialog] = useState(false);
|
const [showBulkDeleteDialog, setShowBulkDeleteDialog] = useState(false);
|
||||||
|
|
@ -230,24 +228,11 @@ function SearchPage() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="h-full flex flex-col container">
|
||||||
className={`fixed inset-0 md:left-72 flex flex-col transition-all duration-300 ${
|
<div className="flex items-center justify-between mb-6">
|
||||||
isMenuOpen && isPanelOpen
|
<h2 className="flex items-center h-[40px] text-lg font-semibold">
|
||||||
? "md:right-[704px]"
|
Project Knowledge
|
||||||
: // Both open: 384px (menu) + 320px (KF panel)
|
</h2>
|
||||||
isMenuOpen
|
|
||||||
? "md:right-96"
|
|
||||||
: // Only menu open: 384px
|
|
||||||
isPanelOpen
|
|
||||||
? "md:right-80"
|
|
||||||
: // Only KF panel open: 320px
|
|
||||||
"md:right-6" // Neither open: 24px
|
|
||||||
}`}
|
|
||||||
style={{ top: `${totalTopOffset}px` }}
|
|
||||||
>
|
|
||||||
<div className="flex-1 flex flex-col min-h-0 px-6 py-6">
|
|
||||||
<div className="flex items-center justify-between mb-6 h-10">
|
|
||||||
<h2 className="text-lg font-semibold">Project Knowledge</h2>
|
|
||||||
<KnowledgeDropdown variant="button" />
|
<KnowledgeDropdown variant="button" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -282,26 +267,6 @@ function SearchPage() {
|
||||||
onChange={handleTableSearch}
|
onChange={handleTableSearch}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/* <Button
|
|
||||||
type="submit"
|
|
||||||
variant="outline"
|
|
||||||
className="rounded-lg p-0 flex-shrink-0"
|
|
||||||
>
|
|
||||||
{isFetching ? (
|
|
||||||
<Loader2 className="h-4 w-4 animate-spin" />
|
|
||||||
) : (
|
|
||||||
<Search className="h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</Button> */}
|
|
||||||
{/* //TODO: Implement sync button */}
|
|
||||||
{/* <Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
className="rounded-lg flex-shrink-0"
|
|
||||||
onClick={() => alert("Not implemented")}
|
|
||||||
>
|
|
||||||
Sync
|
|
||||||
</Button> */}
|
|
||||||
{selectedRows.length > 0 && (
|
{selectedRows.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -314,7 +279,8 @@ function SearchPage() {
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-h-0 max-h-[700px] overflow-hidden h-full">
|
|
||||||
|
<div className="flex-1 min-h-0">
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
className="h-full w-full"
|
className="h-full w-full"
|
||||||
columnDefs={columnDefs}
|
columnDefs={columnDefs}
|
||||||
|
|
@ -340,7 +306,6 @@ function SearchPage() {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Bulk Delete Confirmation Dialog */}
|
{/* Bulk Delete Confirmation Dialog */}
|
||||||
<DeleteConfirmationDialog
|
<DeleteConfirmationDialog
|
||||||
|
|
|
||||||
|
|
@ -131,19 +131,16 @@ const DEFAULT_CONNECTORS: Connector[] = [
|
||||||
|
|
||||||
function KnowledgeSourcesPage() {
|
function KnowledgeSourcesPage() {
|
||||||
const { isAuthenticated, isNoAuthMode } = useAuth();
|
const { isAuthenticated, isNoAuthMode } = useAuth();
|
||||||
const { addTask, tasks } = useTask();
|
const { tasks } = useTask();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// Connectors state
|
// Connectors state
|
||||||
const [connectors, setConnectors] = useState<Connector[]>([]);
|
const [connectors, setConnectors] = useState<Connector[]>([]);
|
||||||
const [isConnecting, setIsConnecting] = useState<string | null>(null);
|
|
||||||
const [isSyncing, setIsSyncing] = useState<string | null>(null);
|
const [isSyncing, setIsSyncing] = useState<string | null>(null);
|
||||||
const [syncResults, setSyncResults] = useState<{
|
const [syncResults, setSyncResults] = useState<{
|
||||||
[key: string]: SyncResult | null;
|
[key: string]: SyncResult | null;
|
||||||
}>({});
|
}>({});
|
||||||
const [maxFiles, setMaxFiles] = useState<number>(10);
|
|
||||||
const [syncAllFiles, setSyncAllFiles] = useState<boolean>(false);
|
|
||||||
|
|
||||||
// Only keep systemPrompt state since it needs manual save button
|
// Only keep systemPrompt state since it needs manual save button
|
||||||
const [systemPrompt, setSystemPrompt] = useState<string>("");
|
const [systemPrompt, setSystemPrompt] = useState<string>("");
|
||||||
|
|
@ -380,58 +377,6 @@ function KnowledgeSourcesPage() {
|
||||||
}
|
}
|
||||||
}, [getConnectorIcon]);
|
}, [getConnectorIcon]);
|
||||||
|
|
||||||
const handleConnect = async (connector: Connector) => {
|
|
||||||
setIsConnecting(connector.id);
|
|
||||||
setSyncResults(prev => ({ ...prev, [connector.id]: null }));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Use the shared auth callback URL, same as connectors page
|
|
||||||
const redirectUri = `${window.location.origin}/auth/callback`;
|
|
||||||
|
|
||||||
const response = await fetch("/api/auth/init", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
connector_type: connector.type,
|
|
||||||
purpose: "data_source",
|
|
||||||
name: `${connector.name} Connection`,
|
|
||||||
redirect_uri: redirectUri,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.oauth_config) {
|
|
||||||
localStorage.setItem("connecting_connector_id", result.connection_id);
|
|
||||||
localStorage.setItem("connecting_connector_type", connector.type);
|
|
||||||
|
|
||||||
const authUrl =
|
|
||||||
`${result.oauth_config.authorization_endpoint}?` +
|
|
||||||
`client_id=${result.oauth_config.client_id}&` +
|
|
||||||
`response_type=code&` +
|
|
||||||
`scope=${result.oauth_config.scopes.join(" ")}&` +
|
|
||||||
`redirect_uri=${encodeURIComponent(
|
|
||||||
result.oauth_config.redirect_uri
|
|
||||||
)}&` +
|
|
||||||
`access_type=offline&` +
|
|
||||||
`prompt=consent&` +
|
|
||||||
`state=${result.connection_id}`;
|
|
||||||
|
|
||||||
window.location.href = authUrl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error("Failed to initiate connection");
|
|
||||||
setIsConnecting(null);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Connection error:", error);
|
|
||||||
setIsConnecting(null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// const handleSync = async (connector: Connector) => {
|
// const handleSync = async (connector: Connector) => {
|
||||||
// if (!connector.connectionId) return;
|
// if (!connector.connectionId) return;
|
||||||
|
|
||||||
|
|
@ -623,108 +568,66 @@ function KnowledgeSourcesPage() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="h-full flex flex-col container">
|
||||||
{/* Connectors Section */}
|
<div className="flex items-center justify-between mb-6">
|
||||||
<div className="space-y-6">
|
<h2 className="flex items-center h-[40px] text-lg font-semibold">
|
||||||
<div>
|
|
||||||
<h2 className="text-lg font-semibold tracking-tight mb-2">
|
|
||||||
Cloud Connectors
|
Cloud Connectors
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Conditional Sync Settings or No-Auth Message */}
|
{/* Conditional Sync Settings or No-Auth Message */}
|
||||||
{
|
{isNoAuthMode ? (
|
||||||
isNoAuthMode ? (
|
<div className="flex-1 flex flex-col pb-2">
|
||||||
<Card className="border-yellow-500/50 bg-yellow-500/5">
|
<Card className="border-yellow-500/50 bg-yellow-500/5">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-lg text-yellow-600">
|
<CardTitle className="text-lg text-yellow-600">
|
||||||
Cloud connectors are only available with auth mode enabled
|
Cloud connectors are only available with auth mode enabled
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="text-sm">
|
<CardDescription className="text-sm">
|
||||||
Please provide the following environment variables and
|
Please provide the following environment variables and restart:
|
||||||
restart:
|
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="bg-muted rounded-md p-4 font-mono text-sm">
|
<div className="bg-muted rounded-md p-4 font-mono text-sm">
|
||||||
<div className="text-muted-foreground mb-2">
|
<div className="text-muted-foreground mb-2">
|
||||||
# make here
|
# make here https://console.cloud.google.com/apis/credentials
|
||||||
https://console.cloud.google.com/apis/credentials
|
|
||||||
</div>
|
</div>
|
||||||
<div>GOOGLE_OAUTH_CLIENT_ID=</div>
|
<div>GOOGLE_OAUTH_CLIENT_ID=</div>
|
||||||
<div>GOOGLE_OAUTH_CLIENT_SECRET=</div>
|
<div>GOOGLE_OAUTH_CLIENT_SECRET=</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
) : null
|
</div>
|
||||||
// <div className="flex items-center justify-between py-4">
|
) : null}
|
||||||
// <div>
|
|
||||||
// <h3 className="text-lg font-medium">Sync Settings</h3>
|
|
||||||
// <p className="text-sm text-muted-foreground">
|
|
||||||
// Configure how many files to sync when manually triggering a sync
|
|
||||||
// </p>
|
|
||||||
// </div>
|
|
||||||
// <div className="flex items-center gap-4">
|
|
||||||
// <div className="flex items-center space-x-2">
|
|
||||||
// <Checkbox
|
|
||||||
// id="syncAllFiles"
|
|
||||||
// checked={syncAllFiles}
|
|
||||||
// onCheckedChange={checked => {
|
|
||||||
// setSyncAllFiles(!!checked);
|
|
||||||
// if (checked) {
|
|
||||||
// setMaxFiles(0);
|
|
||||||
// } else {
|
|
||||||
// setMaxFiles(10);
|
|
||||||
// }
|
|
||||||
// }}
|
|
||||||
// />
|
|
||||||
// <Label
|
|
||||||
// htmlFor="syncAllFiles"
|
|
||||||
// className="font-medium whitespace-nowrap"
|
|
||||||
// >
|
|
||||||
// Sync all files
|
|
||||||
// </Label>
|
|
||||||
// </div>
|
|
||||||
// <Label
|
|
||||||
// htmlFor="maxFiles"
|
|
||||||
// className="font-medium whitespace-nowrap"
|
|
||||||
// >
|
|
||||||
// Max files per sync:
|
|
||||||
// </Label>
|
|
||||||
// <div className="relative">
|
|
||||||
// <Input
|
|
||||||
// id="maxFiles"
|
|
||||||
// type="number"
|
|
||||||
// value={syncAllFiles ? 0 : maxFiles}
|
|
||||||
// onChange={e => 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"
|
|
||||||
// }
|
|
||||||
// />
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{/* Connectors Grid */}
|
{/* Connectors Section */}
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="flex-1 flex flex-col pb-2">
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<div>
|
||||||
|
<CardTitle className="text-lg mb-4">Cloud Connectors</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Connect to cloud storage providers to sync your knowledge.
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{DEFAULT_CONNECTORS.map(connector => {
|
{DEFAULT_CONNECTORS.map(connector => {
|
||||||
const actualConnector = connectors.find(c => c.id === connector.id);
|
const actualConnector = connectors.find(
|
||||||
|
c => c.id === connector.id
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Card key={connector.id} className="relative flex flex-col">
|
<Card key={connector.id} className="flex flex-col">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex flex-col items-start justify-between">
|
<div className="flex flex-col items-start justify-between">
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<div className="mb-1">
|
<div className="mb-1">
|
||||||
<div
|
<div
|
||||||
className={`w-8 h-8 ${
|
className={`w-8 h-8 ${
|
||||||
actualConnector ? "bg-white" : "bg-muted grayscale"
|
actualConnector
|
||||||
|
? "bg-white"
|
||||||
|
: "bg-muted grayscale"
|
||||||
} rounded flex items-center justify-center`}
|
} rounded flex items-center justify-center`}
|
||||||
>
|
>
|
||||||
{connector.icon}
|
{connector.icon}
|
||||||
|
|
@ -792,8 +695,12 @@ function KnowledgeSourcesPage() {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Agent Behavior Section */}
|
{/* Agent Behavior Section */}
|
||||||
|
<div className="flex-1 flex flex-col py-2">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -939,8 +846,10 @@ function KnowledgeSourcesPage() {
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Knowledge Ingest Section */}
|
{/* Knowledge Ingest Section */}
|
||||||
|
<div className="flex-1 flex flex-col py-2">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -1028,7 +937,8 @@ function KnowledgeSourcesPage() {
|
||||||
disabled={true}
|
disabled={true}
|
||||||
value={
|
value={
|
||||||
settings.knowledge?.embedding_model ||
|
settings.knowledge?.embedding_model ||
|
||||||
modelsData?.embedding_models?.find(m => m.default)?.value ||
|
modelsData?.embedding_models?.find(m => m.default)
|
||||||
|
?.value ||
|
||||||
"text-embedding-ada-002"
|
"text-embedding-ada-002"
|
||||||
}
|
}
|
||||||
onValueChange={handleEmbeddingModelChange}
|
onValueChange={handleEmbeddingModelChange}
|
||||||
|
|
@ -1208,6 +1118,7 @@ function KnowledgeSourcesPage() {
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,18 +172,16 @@ export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
||||||
headerHeight={headerHeight}
|
headerHeight={headerHeight}
|
||||||
totalTopOffset={totalTopOffset}
|
totalTopOffset={totalTopOffset}
|
||||||
>
|
>
|
||||||
<div
|
<div className={cn("py-6 lg:py-8 px-4 lg:px-6 h-full")}>
|
||||||
className={cn(
|
|
||||||
"py-6 lg:py-8 px-4 lg:px-6",
|
|
||||||
isSmallWidthPath ? "max-w-[850px]" : "container"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</LayoutProvider>
|
</LayoutProvider>
|
||||||
</main>
|
</main>
|
||||||
<TaskNotificationMenu />
|
<TaskNotificationMenu />
|
||||||
<KnowledgeFilterPanel />
|
<KnowledgeFilterPanel
|
||||||
|
totalTopOffset={totalTopOffset}
|
||||||
|
headerHeight={headerHeight}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue