Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Updated login and signup components to utilize AuthCard for better user experience during redirection. - Introduced AuthentikEmbedDialog for seamless integration of Authentik's identity portal within the application. - Enhanced password recovery and signup flows with dynamic theme handling and improved loading states. - Refactored existing components to streamline authentication processes and improve maintainability.
198 lines
6.0 KiB
TypeScript
198 lines
6.0 KiB
TypeScript
"use client"
|
|
|
|
import Link from "next/link"
|
|
import { AutomationTabMasonry } from "@/components/gmail/settings/automation/automation-tab-masonry"
|
|
import {
|
|
SettingsCard,
|
|
SettingsField,
|
|
SettingsGrid,
|
|
} from "@/components/settings/settings-kit"
|
|
import { OrgSettingsSection } from "@/components/admin/settings/org-settings-form"
|
|
import { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
|
|
import { Button } from "@/components/ui/button"
|
|
import {
|
|
InputGroup,
|
|
InputGroupAddon,
|
|
InputGroupInput,
|
|
InputGroupText,
|
|
} from "@/components/ui/input-group"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
export function QuotasSection() {
|
|
const storageQuotas = useOrgSettingsStore((s) => s.storageQuotas)
|
|
const setStorageQuotas = useOrgSettingsStore((s) => s.setStorageQuotas)
|
|
const usageQuotas = useOrgSettingsStore((s) => s.usageQuotas)
|
|
const setUsageQuotas = useOrgSettingsStore((s) => s.setUsageQuotas)
|
|
|
|
return (
|
|
<OrgSettingsSection
|
|
title="Quotas"
|
|
description="Limites de stockage et d'usage appliquées par défaut aux comptes de l'organisation."
|
|
policySection={["storage_quotas", "usage_quotas"]}
|
|
>
|
|
<AutomationTabMasonry columns={2}>
|
|
<SettingsCard
|
|
title="Stockage par défaut"
|
|
description="Mail, drive et photos. Les quotas individuels se gèrent depuis la fiche utilisateur."
|
|
>
|
|
<SettingsGrid columns={2} className="sm:grid-cols-3">
|
|
<QuotaInput
|
|
label="Mail"
|
|
unit="Go"
|
|
value={storageQuotas.default_mail_gib}
|
|
onChange={(v) => setStorageQuotas({ default_mail_gib: v })}
|
|
/>
|
|
<QuotaInput
|
|
label="Drive"
|
|
unit="Go"
|
|
value={storageQuotas.default_drive_gib}
|
|
onChange={(v) => setStorageQuotas({ default_drive_gib: v })}
|
|
/>
|
|
<QuotaInput
|
|
label="Photos"
|
|
unit="Go"
|
|
value={storageQuotas.default_photos_gib}
|
|
onChange={(v) => setStorageQuotas({ default_photos_gib: v })}
|
|
/>
|
|
</SettingsGrid>
|
|
<SettingsNumberField
|
|
label="Seuil d'alerte"
|
|
unit="%"
|
|
min={50}
|
|
max={100}
|
|
fallback={90}
|
|
value={storageQuotas.warn_threshold_pct}
|
|
onChange={(v) => setStorageQuotas({ warn_threshold_pct: v })}
|
|
/>
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href="/admin/settings/users">Gérer les quotas par utilisateur</Link>
|
|
</Button>
|
|
</SettingsCard>
|
|
|
|
<SettingsCard
|
|
title="Intelligence artificielle"
|
|
description="Plafonds par utilisateur (clés org) : usage quotidien et mensuel raisonnable pour une PME."
|
|
>
|
|
<SettingsGrid columns={2}>
|
|
<SettingsNumberField
|
|
label="Plafond journalier"
|
|
unit="€"
|
|
step={0.5}
|
|
value={usageQuotas.llm_daily_cost_limit_eur}
|
|
onChange={(v) => setUsageQuotas({ llm_daily_cost_limit_eur: v })}
|
|
/>
|
|
<SettingsNumberField
|
|
label="Plafond mensuel"
|
|
unit="€"
|
|
step={1}
|
|
value={usageQuotas.llm_monthly_cost_limit_eur}
|
|
onChange={(v) => setUsageQuotas({ llm_monthly_cost_limit_eur: v })}
|
|
/>
|
|
</SettingsGrid>
|
|
<SettingsNumberField
|
|
label="Seuil d'alerte"
|
|
unit="%"
|
|
min={50}
|
|
max={100}
|
|
fallback={80}
|
|
value={usageQuotas.llm_cost_warn_threshold_pct}
|
|
onChange={(v) => setUsageQuotas({ llm_cost_warn_threshold_pct: v })}
|
|
/>
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href="/admin/settings/ai-usage">Voir la consommation IA</Link>
|
|
</Button>
|
|
</SettingsCard>
|
|
|
|
<SettingsCard
|
|
title="Recherche et automatisations"
|
|
description="Recherche web, tokens API et webhooks par utilisateur."
|
|
>
|
|
<SettingsGrid columns={2} className="lg:grid-cols-1 xl:grid-cols-3">
|
|
<SettingsNumberField
|
|
label="Recherches web"
|
|
unit="/ jour"
|
|
value={usageQuotas.search_requests_per_day}
|
|
onChange={(v) => setUsageQuotas({ search_requests_per_day: v })}
|
|
/>
|
|
<SettingsNumberField
|
|
label="Tokens API"
|
|
unit="/ utilisateur"
|
|
value={usageQuotas.max_api_tokens_per_user}
|
|
onChange={(v) => setUsageQuotas({ max_api_tokens_per_user: v })}
|
|
/>
|
|
<SettingsNumberField
|
|
label="Webhooks"
|
|
unit="/ utilisateur"
|
|
value={usageQuotas.max_webhooks_per_user}
|
|
onChange={(v) => setUsageQuotas({ max_webhooks_per_user: v })}
|
|
/>
|
|
</SettingsGrid>
|
|
</SettingsCard>
|
|
</AutomationTabMasonry>
|
|
</OrgSettingsSection>
|
|
)
|
|
}
|
|
|
|
function QuotaInput({
|
|
label,
|
|
unit,
|
|
value,
|
|
onChange,
|
|
}: {
|
|
label: string
|
|
unit: string
|
|
value: number
|
|
onChange: (v: number) => void
|
|
}) {
|
|
return (
|
|
<SettingsNumberField
|
|
label={label}
|
|
unit={unit}
|
|
step={0.5}
|
|
value={value}
|
|
onChange={onChange}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function SettingsNumberField({
|
|
label,
|
|
unit,
|
|
value,
|
|
onChange,
|
|
min = 0,
|
|
max,
|
|
step,
|
|
fallback = 0,
|
|
className,
|
|
}: {
|
|
label: string
|
|
unit: string
|
|
value: number
|
|
onChange: (v: number) => void
|
|
min?: number
|
|
max?: number
|
|
step?: number
|
|
fallback?: number
|
|
className?: string
|
|
}) {
|
|
return (
|
|
<SettingsField label={label}>
|
|
<InputGroup className={cn("w-fit max-w-full", className)}>
|
|
<InputGroupInput
|
|
type="number"
|
|
min={min}
|
|
max={max}
|
|
step={step}
|
|
value={value}
|
|
className="w-20 flex-none tabular-nums"
|
|
onChange={(e) => onChange(Number(e.target.value) || fallback)}
|
|
/>
|
|
<InputGroupAddon align="inline-end">
|
|
<InputGroupText>{unit}</InputGroupText>
|
|
</InputGroupAddon>
|
|
</InputGroup>
|
|
</SettingsField>
|
|
)
|
|
}
|