ultisuite-client/components/admin/settings/sections/drive-mount-oauth-section.tsx
R3D347HR4Y 8f81d7aba1
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(admin-settings): refactor admin settings components for improved usability and consistency
- 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.
2026-06-15 11:10:17 +02:00

178 lines
5.7 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import { Check, Copy } from "lucide-react"
import { toast } from "sonner"
import { TechBrandSelectLabel } from "@/components/admin/settings/tech-brand-select-label"
import {
SettingsCard,
SettingsField,
SettingsGrid,
SettingsHint,
SettingsToggleRow,
} from "@/components/settings/settings-kit"
import { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
import type { DriveMountOAuthProvider, DriveMountOAuthSettings } from "@/lib/admin-settings/org-settings-types"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { buildDriveMountOAuthRedirectURI } from "@/lib/drive/drive-mount-oauth"
const PROVIDERS: {
id: DriveMountOAuthProvider
label: string
hint: string
icon: string
}[] = [
{
id: "google",
label: "Google Drive",
hint: "Console Google Cloud — API Drive, redirect URI ci-dessous",
icon: "logos:google-drive",
},
{
id: "dropbox",
label: "Dropbox",
hint: "App Dropbox — permissions files.metadata.read, files.content.read/write",
icon: "logos:dropbox",
},
{
id: "microsoft",
label: "Microsoft OneDrive",
hint: "Azure AD — Microsoft Graph Files.ReadWrite",
icon: "logos:microsoft-onedrive",
},
]
const SECRET_KEYS: Record<DriveMountOAuthProvider, "mount_oauth_google" | "mount_oauth_dropbox" | "mount_oauth_microsoft"> = {
google: "mount_oauth_google",
dropbox: "mount_oauth_dropbox",
microsoft: "mount_oauth_microsoft",
}
export function DriveMountOAuthSection({
draft,
onChange,
embedded = false,
}: {
draft: DriveMountOAuthSettings
onChange: (next: DriveMountOAuthSettings) => void
embedded?: boolean
}) {
const secrets = useOrgSettingsStore((s) => s.meta?.secrets)
const [redirectUri, setRedirectUri] = useState("")
const [copied, setCopied] = useState(false)
useEffect(() => {
setRedirectUri(buildDriveMountOAuthRedirectURI())
}, [])
const updateProvider = (provider: DriveMountOAuthProvider, patch: Partial<DriveMountOAuthSettings[typeof provider]>) => {
onChange({
...draft,
[provider]: { ...draft[provider], ...patch },
})
}
const copyRedirectUri = async () => {
const uri = redirectUri || buildDriveMountOAuthRedirectURI()
try {
await navigator.clipboard.writeText(uri)
setCopied(true)
toast.success("URI de redirection copiée")
window.setTimeout(() => setCopied(false), 2000)
} catch {
toast.error("Impossible de copier l'URI")
}
}
const content = (
<>
<SettingsField
label="URI de redirection OAuth"
hint="Basée sur l'URL actuelle du navigateur. Enregistrez-la chez chaque fournisseur OAuth (Google, Dropbox, Microsoft)."
>
<div className="flex gap-2">
<Input
className="h-9 flex-1 font-mono text-xs"
readOnly
value={redirectUri}
placeholder="Chargement…"
/>
<Button
type="button"
variant="outline"
size="sm"
className="h-9 shrink-0 gap-1.5 px-3"
onClick={() => void copyRedirectUri()}
disabled={!redirectUri}
>
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
Copier
</Button>
</div>
</SettingsField>
<div className="space-y-4">
{PROVIDERS.map(({ id, label, hint, icon }) => {
const provider = draft[id]
const configured = Boolean(secrets?.[SECRET_KEYS[id]]?.configured)
return (
<div key={id} className="space-y-3 rounded-md border border-mail-border bg-mail-surface-muted/40 p-3">
<SettingsToggleRow
variant="plain"
title={
<TechBrandSelectLabel icon={icon} className="text-sm font-medium">
{label}
</TechBrandSelectLabel>
}
description={hint}
checked={provider.enabled}
onCheckedChange={(enabled) => updateProvider(id, { enabled })}
/>
{provider.enabled ? (
<SettingsGrid columns={1}>
<SettingsField label="Client ID">
<Input
className="h-9 font-mono text-xs"
value={provider.client_id}
onChange={(e) => updateProvider(id, { client_id: e.target.value })}
autoComplete="off"
/>
</SettingsField>
<SettingsField
label="Client secret"
hint={
configured && !provider.client_secret.trim() ? (
<SettingsHint>Secret configuré</SettingsHint>
) : undefined
}
>
<Input
className="h-9 font-mono text-xs"
type="password"
value={provider.client_secret}
onChange={(e) => updateProvider(id, { client_secret: e.target.value })}
placeholder={configured ? "•••••••• (laisser vide pour conserver)" : "Coller le secret"}
autoComplete="off"
/>
</SettingsField>
</SettingsGrid>
) : null}
</div>
)
})}
</div>
</>
)
if (embedded) return <div className="space-y-4">{content}</div>
return (
<SettingsCard
title="Connexion cloud (OAuth)"
description="Permet aux utilisateurs de monter Google Drive, Dropbox ou OneDrive depuis UltiDrive."
>
{content}
</SettingsCard>
)
}