Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Replaced legacy components with new `SettingsCard`, `SettingsField`, and `SettingsToggleRow` for a unified design. - Enhanced `AdminListControls` to support compact mode and improved pagination controls. - Updated various sections including `AiAssistantSection`, `AuthenticationSection`, and `DriveMountOAuthSection` to utilize new components, streamlining the settings interface. - Improved accessibility and user experience across admin settings with clearer labels and hints. - Deprecated old components while maintaining backward compatibility for existing admin sections.
198 lines
7.7 KiB
TypeScript
198 lines
7.7 KiB
TypeScript
"use client"
|
|
|
|
import { OrgSettingsSection } from "@/components/admin/settings/org-settings-form"
|
|
import {
|
|
SettingsCard,
|
|
SettingsField,
|
|
SettingsGrid,
|
|
SettingsToggleRow,
|
|
} from "@/components/settings/settings-kit"
|
|
import { DeployLockedHint, useDeployFieldLocked } from "@/components/admin/settings/deploy-locked-hint"
|
|
import { AutomationTabMasonry } from "@/components/gmail/settings/automation/automation-tab-masonry"
|
|
import { WebSearchProvidersEditor } from "@/components/web-search/web-search-providers-editor"
|
|
import { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
|
|
import { Input } from "@/components/ui/input"
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select"
|
|
import { normalizeSearchProviders } from "@/lib/web-search/search-provider-catalog"
|
|
import { TechBrandSelectLabel } from "@/components/admin/settings/tech-brand-select-label"
|
|
|
|
export function SearchSection() {
|
|
const search = useOrgSettingsStore((s) => s.search)
|
|
const setSearch = useOrgSettingsStore((s) => s.setSearch)
|
|
const effective = useOrgSettingsStore((s) => s.meta?.effective.search)
|
|
const providerSecrets = useOrgSettingsStore((s) => s.meta?.secrets?.web_search_providers)
|
|
const webSearch = normalizeSearchProviders(search.web_search)
|
|
|
|
const engineLocked = useDeployFieldLocked("search", "suite_engine")
|
|
const meiliURLLocked = useDeployFieldLocked("search", "meilisearch_url")
|
|
const meiliKeyLocked = useDeployFieldLocked("search", "meilisearch_api_key")
|
|
const typesenseURLLocked = useDeployFieldLocked("search", "typesense_url")
|
|
const typesenseKeyLocked = useDeployFieldLocked("search", "typesense_api_key")
|
|
|
|
const suiteEngine = engineLocked
|
|
? ((effective?.suite_engine as typeof search.suite_engine) ?? search.suite_engine)
|
|
: search.suite_engine
|
|
const meiliURL = meiliURLLocked
|
|
? (effective?.meilisearch_url ?? search.meilisearch_url)
|
|
: search.meilisearch_url
|
|
const typesenseURL = typesenseURLLocked
|
|
? (effective?.typesense_url ?? search.typesense_url)
|
|
: search.typesense_url
|
|
|
|
return (
|
|
<OrgSettingsSection
|
|
title="Moteur de recherche"
|
|
description="Index de recherche suite (mail, drive) et recherche web (contacts, UltiAI)."
|
|
policySection="search"
|
|
>
|
|
<AutomationTabMasonry columns={2}>
|
|
<SettingsCard
|
|
title="Recherche web"
|
|
description={
|
|
<>
|
|
Fournisseurs pour l'enrichissement IA contacts et le tool UltiAI{" "}
|
|
<code className="rounded bg-muted px-1">web_search</code>. Les utilisateurs peuvent
|
|
surcharger cette config dans leurs réglages si l'imposition org. est désactivée.
|
|
</>
|
|
}
|
|
>
|
|
<SettingsToggleRow
|
|
title="Imposer la config organisation"
|
|
description="Sinon, chaque utilisateur configure ses propres fournisseurs."
|
|
checked={search.enforce_org_search}
|
|
onCheckedChange={(enforce_org_search) => setSearch({ enforce_org_search })}
|
|
/>
|
|
|
|
<WebSearchProvidersEditor
|
|
value={webSearch}
|
|
onChange={(web_search) => setSearch({ web_search })}
|
|
providerSecrets={providerSecrets}
|
|
columns={1}
|
|
/>
|
|
</SettingsCard>
|
|
|
|
<SettingsCard
|
|
title="Recherche suite"
|
|
description="Moteur d'indexation pour la recherche globale (variables SEARCH_ENGINE côté serveur)."
|
|
hint={engineLocked ? <DeployLockedHint section="search" field="suite_engine" /> : null}
|
|
>
|
|
<SettingsField label="Moteur">
|
|
<Select
|
|
value={suiteEngine}
|
|
disabled={engineLocked}
|
|
onValueChange={(suite_engine) =>
|
|
setSearch({
|
|
suite_engine: suite_engine as typeof search.suite_engine,
|
|
})
|
|
}
|
|
>
|
|
<SelectTrigger className="h-9 w-full min-w-0">
|
|
<SelectValue>
|
|
<TechBrandSelectLabel brand={suiteEngine}>
|
|
{suiteEngine === "postgres"
|
|
? "PostgreSQL (full-text)"
|
|
: suiteEngine === "meilisearch"
|
|
? "Meilisearch"
|
|
: "Typesense"}
|
|
</TechBrandSelectLabel>
|
|
</SelectValue>
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="postgres">
|
|
<TechBrandSelectLabel brand="postgres">PostgreSQL (full-text)</TechBrandSelectLabel>
|
|
</SelectItem>
|
|
<SelectItem value="meilisearch">
|
|
<TechBrandSelectLabel brand="meilisearch">Meilisearch</TechBrandSelectLabel>
|
|
</SelectItem>
|
|
<SelectItem value="typesense">
|
|
<TechBrandSelectLabel brand="typesense">Typesense</TechBrandSelectLabel>
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</SettingsField>
|
|
|
|
{suiteEngine === "meilisearch" ? (
|
|
<SettingsGrid columns={1}>
|
|
<SettingsField
|
|
label="URL Meilisearch"
|
|
hint={
|
|
meiliURLLocked ? (
|
|
<DeployLockedHint section="search" field="meilisearch_url" />
|
|
) : undefined
|
|
}
|
|
>
|
|
<Input
|
|
className="h-9"
|
|
value={meiliURL}
|
|
disabled={meiliURLLocked}
|
|
onChange={(e) => setSearch({ meilisearch_url: e.target.value })}
|
|
/>
|
|
</SettingsField>
|
|
<SettingsField
|
|
label="Clé API"
|
|
hint={
|
|
meiliKeyLocked ? (
|
|
<DeployLockedHint section="search" field="meilisearch_api_key" />
|
|
) : undefined
|
|
}
|
|
>
|
|
<Input
|
|
className="h-9"
|
|
type="password"
|
|
value={search.meilisearch_api_key}
|
|
disabled={meiliKeyLocked}
|
|
onChange={(e) => setSearch({ meilisearch_api_key: e.target.value })}
|
|
placeholder={meiliKeyLocked ? "Défini via MEILISEARCH_API_KEY" : undefined}
|
|
/>
|
|
</SettingsField>
|
|
</SettingsGrid>
|
|
) : null}
|
|
|
|
{suiteEngine === "typesense" ? (
|
|
<SettingsGrid columns={1}>
|
|
<SettingsField
|
|
label="URL Typesense"
|
|
hint={
|
|
typesenseURLLocked ? (
|
|
<DeployLockedHint section="search" field="typesense_url" />
|
|
) : undefined
|
|
}
|
|
>
|
|
<Input
|
|
className="h-9"
|
|
value={typesenseURL}
|
|
disabled={typesenseURLLocked}
|
|
onChange={(e) => setSearch({ typesense_url: e.target.value })}
|
|
/>
|
|
</SettingsField>
|
|
<SettingsField
|
|
label="Clé API"
|
|
hint={
|
|
typesenseKeyLocked ? (
|
|
<DeployLockedHint section="search" field="typesense_api_key" />
|
|
) : undefined
|
|
}
|
|
>
|
|
<Input
|
|
className="h-9"
|
|
type="password"
|
|
value={search.typesense_api_key}
|
|
disabled={typesenseKeyLocked}
|
|
onChange={(e) => setSearch({ typesense_api_key: e.target.value })}
|
|
placeholder={typesenseKeyLocked ? "Défini via TYPESENSE_API_KEY" : undefined}
|
|
/>
|
|
</SettingsField>
|
|
</SettingsGrid>
|
|
) : null}
|
|
</SettingsCard>
|
|
</AutomationTabMasonry>
|
|
</OrgSettingsSection>
|
|
)
|
|
}
|