"use client"
import Link from "next/link"
import { ChevronDown, Settings2 } from "lucide-react"
import { useState } from "react"
import { AutomationTabMasonry } from "@/components/gmail/settings/automation/automation-tab-masonry"
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 { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
import { isPluginDeployLocked } from "@/lib/admin/deploy-runtime"
import { Switch } from "@/components/ui/switch"
import { Badge } from "@/components/ui/badge"
import { TechBrandSelectLabel } from "@/components/admin/settings/tech-brand-select-label"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { ULTICAL_APP_NAME, ULTICARDS_APP_NAME } from "@/lib/suite/page-metadata"
import { cn } from "@/lib/utils"
const SIMPLE_PLUGIN_IDS = new Set(["mail-automation", "contact-discovery", "public-share"])
const CONFIG_PLUGIN_IDS = new Set(["office-editor", "richtext-editor", "ai-assistant"])
export function PluginsSection() {
const plugins = useOrgSettingsStore((s) => s.plugins)
const togglePlugin = useOrgSettingsStore((s) => s.togglePlugin)
const deployLocked = useOrgSettingsStore((s) => s.meta?.deployLocked)
const simplePlugins = plugins.filter((p) => SIMPLE_PLUGIN_IDS.has(p.id))
const configPlugins = plugins.filter((p) => CONFIG_PLUGIN_IDS.has(p.id))
return (
{simplePlugins.map((plugin) => {
const locked = isPluginDeployLocked(deployLocked, plugin.id)
return (
togglePlugin(plugin.id, enabled)}
/>
)
})}
{configPlugins.map((plugin) => {
const locked = isPluginDeployLocked(deployLocked, plugin.id)
if (plugin.id === "office-editor") {
return (
togglePlugin(plugin.id, enabled)}
/>
)
}
if (plugin.id === "richtext-editor") {
return (
togglePlugin(plugin.id, enabled)}
/>
)
}
return (
togglePlugin(plugin.id, enabled)}
/>
)
})}
)
}
function PluginToggleCard({
name,
description,
version,
enabled,
locked,
lockSection,
lockField,
onToggle,
hint,
action,
children,
defaultOpen = false,
}: {
name: string
description: string
version?: string
enabled: boolean
locked?: boolean
lockSection?: string
lockField?: string
onToggle: (enabled: boolean) => void
hint?: React.ReactNode
action?: React.ReactNode
children?: React.ReactNode
defaultOpen?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)
const hasConfig = Boolean(children)
const body = action ? (
action
) : hasConfig ? (
{children}
) : null
return (
{name}
{version ? v{version} : null}
}
description={description}
action={}
hint={
hint || (locked && lockSection && lockField) ? (
<>
{hint}
{locked && lockSection && lockField ? (
) : null}
>
) : null
}
divider={false}
contentClassName="space-y-0 !mt-3 !pt-0"
>
{body}
)
}
function NextcloudPluginCard() {
const nextcloud = useOrgSettingsStore((s) => s.nextcloud)
const setNextcloud = useOrgSettingsStore((s) => s.setNextcloud)
const effective = useOrgSettingsStore((s) => s.meta?.effective.nextcloud)
const enabledLocked = useDeployFieldLocked("nextcloud", "enabled")
const urlLocked = useDeployFieldLocked("nextcloud", "base_url")
const userLocked = useDeployFieldLocked("nextcloud", "admin_user")
const passLocked = useDeployFieldLocked("nextcloud", "admin_password")
const enabled = enabledLocked ? (effective?.enabled ?? nextcloud.enabled) : nextcloud.enabled
const baseURL = urlLocked ? (effective?.base_url ?? nextcloud.base_url) : nextcloud.base_url
const adminUser = userLocked ? (effective?.admin_user ?? nextcloud.admin_user) : nextcloud.admin_user
return (
setNextcloud({ enabled: v })}
defaultOpen={enabled}
>
: undefined}
>
setNextcloud({ base_url: e.target.value })}
placeholder="https://cloud.example.com"
/>
: undefined}
>
setNextcloud({ admin_user: e.target.value })}
/>
: undefined}
>
setNextcloud({ admin_password: e.target.value })}
placeholder={passLocked ? "Défini via NC_ADMIN_PASSWORD" : undefined}
/>
Modules exposés
Active ou masque chaque application Nextcloud dans la suite.
setNextcloud({ drive_enabled })}
/>
setNextcloud({ calendar_enabled })}
/>
setNextcloud({ contacts_enabled })}
/>
setNextcloud({ talk_enabled })}
/>
)
}
function OnlyOfficePluginCard({
plugin,
locked,
onToggle,
}: {
plugin: { name: string; description: string; version: string; enabled: boolean }
locked: boolean
onToggle: (enabled: boolean) => void
}) {
const onlyoffice = useOrgSettingsStore((s) => s.onlyoffice)
const setOnlyoffice = useOrgSettingsStore((s) => s.setOnlyoffice)
const effective = useOrgSettingsStore((s) => s.meta?.effective.onlyoffice)
const enabledLocked = useDeployFieldLocked("onlyoffice", "enabled")
const urlLocked = useDeployFieldLocked("onlyoffice", "document_server_url")
const jwtLocked = useDeployFieldLocked("onlyoffice", "jwt_secret")
const headerLocked = useDeployFieldLocked("onlyoffice", "jwt_header")
const enabled = enabledLocked
? (effective?.enabled ?? plugin.enabled)
: plugin.enabled
const docURL = urlLocked
? (effective?.document_server_url ?? onlyoffice.document_server_url)
: onlyoffice.document_server_url
return (
{enabledLocked ? : null}
: undefined
}
>
setOnlyoffice({ document_server_url: e.target.value })}
placeholder="https://office.example.com"
/>
: undefined}
>
setOnlyoffice({ jwt_secret: e.target.value })}
placeholder={jwtLocked ? "Défini via ONLYOFFICE_JWT_SECRET" : undefined}
/>
: undefined}
>
setOnlyoffice({ jwt_header: e.target.value })}
/>
)
}
function RichtextPluginCard({
plugin,
locked,
onToggle,
}: {
plugin: { name: string; description: string; version: string; enabled: boolean }
locked: boolean
onToggle: (enabled: boolean) => void
}) {
const richtext = useOrgSettingsStore((s) => s.richtext)
const setRichtext = useOrgSettingsStore((s) => s.setRichtext)
return (
setRichtext({ hocuspocus_url: e.target.value })}
placeholder="ws://localhost:1234"
/>
)
}
function AiAssistantPluginCard({
plugin,
locked,
onToggle,
}: {
plugin: { name: string; description: string; version: string; enabled: boolean }
locked: boolean
onToggle: (enabled: boolean) => void
}) {
return (
OpenWebUI doit être déployé (
AI_ASSISTANT_ENABLED=true
).
) : null
}
action={
}
/>
)
}
function ServiceToggle({
label,
checked,
onChange,
}: {
label: string
checked: boolean
onChange: (v: boolean) => void
}) {
return
}