128 lines
4.7 KiB
TypeScript
128 lines
4.7 KiB
TypeScript
"use client"
|
|
|
|
import { OrgSettingsSection } from "@/components/admin/settings/org-settings-form"
|
|
import { DeployLockedHint, useDeployFieldLocked } from "@/components/admin/settings/deploy-locked-hint"
|
|
import { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import { Switch } from "@/components/ui/switch"
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
|
|
export function NextcloudSection() {
|
|
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 (
|
|
<OrgSettingsSection
|
|
title="Nextcloud"
|
|
description="Connexion au serveur Nextcloud pour drive, agenda, contacts et Talk."
|
|
policySection="nextcloud"
|
|
>
|
|
<Card>
|
|
<CardHeader className="pb-3">
|
|
<div className="flex items-center justify-between gap-4">
|
|
<div>
|
|
<CardTitle className="text-sm font-medium">Intégration Nextcloud</CardTitle>
|
|
<CardDescription>Variables NEXTCLOUD_* côté serveur.</CardDescription>
|
|
{enabledLocked ? <DeployLockedHint section="nextcloud" field="enabled" /> : null}
|
|
</div>
|
|
<Switch
|
|
checked={enabled}
|
|
disabled={enabledLocked}
|
|
onCheckedChange={(v) => setNextcloud({ enabled: v })}
|
|
/>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="grid gap-4 sm:grid-cols-2">
|
|
<div className="sm:col-span-2">
|
|
<Label>URL de base</Label>
|
|
<Input
|
|
className="mt-1 h-9"
|
|
value={baseURL}
|
|
disabled={urlLocked}
|
|
onChange={(e) => setNextcloud({ base_url: e.target.value })}
|
|
placeholder="https://cloud.example.com"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label>Utilisateur admin</Label>
|
|
<Input
|
|
className="mt-1 h-9"
|
|
value={adminUser}
|
|
disabled={userLocked}
|
|
onChange={(e) => setNextcloud({ admin_user: e.target.value })}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label>Mot de passe admin</Label>
|
|
<Input
|
|
className="mt-1 h-9"
|
|
type="password"
|
|
value={nextcloud.admin_password}
|
|
disabled={passLocked}
|
|
onChange={(e) => setNextcloud({ admin_password: e.target.value })}
|
|
placeholder={passLocked ? "Défini via NC_ADMIN_PASSWORD" : undefined}
|
|
/>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-sm font-medium">Services activés</CardTitle>
|
|
<CardDescription>Modules suite exposés aux utilisateurs.</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-3">
|
|
<ServiceToggle
|
|
label="UltiDrive (fichiers)"
|
|
checked={nextcloud.drive_enabled}
|
|
onChange={(drive_enabled) => setNextcloud({ drive_enabled })}
|
|
/>
|
|
<ServiceToggle
|
|
label="Agenda"
|
|
checked={nextcloud.calendar_enabled}
|
|
onChange={(calendar_enabled) => setNextcloud({ calendar_enabled })}
|
|
/>
|
|
<ServiceToggle
|
|
label="Contacts"
|
|
checked={nextcloud.contacts_enabled}
|
|
onChange={(contacts_enabled) => setNextcloud({ contacts_enabled })}
|
|
/>
|
|
<ServiceToggle
|
|
label="Talk (visio)"
|
|
checked={nextcloud.talk_enabled}
|
|
onChange={(talk_enabled) => setNextcloud({ talk_enabled })}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
</OrgSettingsSection>
|
|
)
|
|
}
|
|
|
|
function ServiceToggle({
|
|
label,
|
|
checked,
|
|
onChange,
|
|
}: {
|
|
label: string
|
|
checked: boolean
|
|
onChange: (v: boolean) => void
|
|
}) {
|
|
return (
|
|
<label className="flex items-center justify-between gap-4 rounded-lg border p-3">
|
|
<span className="text-sm font-medium">{label}</span>
|
|
<Switch checked={checked} onCheckedChange={onChange} />
|
|
</label>
|
|
)
|
|
}
|