ultisuite-client/components/gmail/settings/automation/search-providers-panel.tsx
R3D347HR4Y 6ec95262af Add OnlyOffice integration and update project configurations
- Updated .env.example to include configuration for OnlyOffice Document Server.
- Modified the workspace configuration to remove the drive-suite path.
- Adjusted TypeScript environment imports for consistency.
- Enhanced Next.js configuration to disable canvas in Webpack.
- Updated package.json to include new dependencies for OnlyOffice and PDF.js.
- Added global styles for OnlyOffice theme integration in the CSS.
- Created new layout and page components for the Drive feature, including public sharing and editing functionalities.
- Updated metadata handling across various layouts to reflect the new app structure.
2026-06-07 15:49:21 +02:00

124 lines
3.9 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import { ExternalLink } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
useSearchSettings,
useUpdateSearchSettings,
} from "@/lib/api/hooks/use-contact-discovery"
import type { ApiSearchProvider, ApiSearchSettings } from "@/lib/contacts/discovery-types"
import {
CONTACTS_MUTED_TEXT,
CONTACTS_PRIMARY_BTN_CLASS,
} from "@/lib/contacts-chrome-classes"
import { cn } from "@/lib/utils"
const BRAVE_PROVIDER_ID = "brave-default"
function defaultBraveProvider(): ApiSearchProvider {
return {
id: BRAVE_PROVIDER_ID,
name: "Brave Search",
type: "brave",
api_key: "",
}
}
function normalizeDraft(raw: ApiSearchSettings | undefined): ApiSearchSettings {
const providers = raw?.providers?.length ? raw.providers : [defaultBraveProvider()]
const brave = providers.find((p) => p.type === "brave") ?? defaultBraveProvider()
return {
default_provider_id: raw?.default_provider_id || brave.id,
providers: [brave],
}
}
export function SearchProvidersPanel() {
const { data: remote, isLoading } = useSearchSettings()
const updateSettings = useUpdateSearchSettings()
const [draft, setDraft] = useState<ApiSearchSettings>(normalizeDraft(undefined))
const [saved, setSaved] = useState(false)
useEffect(() => {
if (remote) {
setDraft(normalizeDraft(remote))
}
}, [remote])
const brave = draft.providers[0] ?? defaultBraveProvider()
function updateBrave(patch: Partial<ApiSearchProvider>) {
setDraft((prev) => {
const current = prev.providers[0] ?? defaultBraveProvider()
const updated = { ...current, ...patch }
return {
default_provider_id: updated.id,
providers: [updated],
}
})
}
async function handleSave() {
await updateSettings.mutateAsync(draft)
setSaved(true)
setTimeout(() => setSaved(false), 2000)
}
if (isLoading) {
return <p className={cn("text-sm", CONTACTS_MUTED_TEXT)}>Chargement</p>
}
return (
<div className="space-y-6">
<div>
<h3 className="text-base font-medium">Fournisseurs de recherche</h3>
<p className={cn("mt-1 text-sm", CONTACTS_MUTED_TEXT)}>
Recherche web utilisée lors de l&apos;amélioration IA des fiches contacts (profils
publics, réseaux sociaux, poste, entreprise).
</p>
</div>
<div className="space-y-3 rounded-lg border border-border p-4">
<div className="flex items-center justify-between gap-2">
<span className="text-sm font-medium">{brave.name}</span>
<a
href="https://api.search.brave.com"
target="_blank"
rel="noopener noreferrer"
className={cn("inline-flex items-center gap-1 text-xs hover:underline", CONTACTS_MUTED_TEXT)}
>
Obtenir une clé API
<ExternalLink className="h-3 w-3" />
</a>
</div>
<div>
<Label className="text-xs">Token API (X-Subscription-Token)</Label>
<Input
className="mt-1 h-9"
type="password"
value={brave.api_key ?? ""}
onChange={(e) => updateBrave({ api_key: e.target.value })}
placeholder="BSA…"
autoComplete="off"
/>
<p className={cn("mt-1.5 text-xs", CONTACTS_MUTED_TEXT)}>
Les 5 premiers résultats web sont ajoutés au prompt LLM avec un avertissement sur les
homonymes. Sans token, l&apos;amélioration IA fonctionne sans recherche en ligne.
</p>
</div>
</div>
<Button
onClick={handleSave}
disabled={updateSettings.isPending}
className={CONTACTS_PRIMARY_BTN_CLASS}
>
{updateSettings.isPending ? "Enregistrement…" : saved ? "Enregistré ✓" : "Enregistrer"}
</Button>
</div>
)
}