@@ -0,0 +1,138 @@
|
||||
import {
|
||||
Anchor,
|
||||
Group,
|
||||
List,
|
||||
Text,
|
||||
Switch,
|
||||
TextInput,
|
||||
ActionIcon,
|
||||
Tooltip,
|
||||
Stack,
|
||||
Alert,
|
||||
} from "@mantine/core";
|
||||
import { useAtom } from "jotai";
|
||||
import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { updateWorkspace } from "@/features/workspace/services/workspace-service.ts";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useIsCloudEE } from "@/hooks/use-is-cloud-ee.tsx";
|
||||
import { getAppUrl } from "@/lib/config.ts";
|
||||
import { IconCheck, IconCopy, IconInfoCircle } from "@tabler/icons-react";
|
||||
import { CopyButton } from "@/components/common/copy-button.tsx";
|
||||
|
||||
export default function McpSettings() {
|
||||
const { t } = useTranslation();
|
||||
const [workspace, setWorkspace] = useAtom(workspaceAtom);
|
||||
const [checked, setChecked] = useState(workspace?.settings?.ai?.mcp);
|
||||
const hasAccess = useIsCloudEE();
|
||||
|
||||
const mcpUrl = `${getAppUrl()}/api/mcp`;
|
||||
|
||||
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.currentTarget.checked;
|
||||
try {
|
||||
const updatedWorkspace = await updateWorkspace({ mcpEnabled: value });
|
||||
setChecked(value);
|
||||
setWorkspace(updatedWorkspace);
|
||||
} catch (err) {
|
||||
notifications.show({
|
||||
message: err?.response?.data?.message,
|
||||
color: "red",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack gap="lg">
|
||||
{!hasAccess && (
|
||||
<Alert
|
||||
icon={<IconInfoCircle />}
|
||||
title={t("Enterprise feature")}
|
||||
color="blue"
|
||||
>
|
||||
{t(
|
||||
"MCP is only available in the Docmost enterprise edition. Contact sales@docmost.com.",
|
||||
)}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Group justify="space-between" wrap="nowrap" gap="xl">
|
||||
<div>
|
||||
<Text size="md">{t("Model Context Protocol (MCP)")}</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{t(
|
||||
"Enable the MCP server to allow AI assistants and tools to interact with your workspace content.",
|
||||
)}{" "}
|
||||
{t("View the")}{" "}
|
||||
<Anchor
|
||||
href="https://docmost.com/docs/user-guide/mcp"
|
||||
target="_blank"
|
||||
size="sm"
|
||||
>
|
||||
{t("MCP documentation")}
|
||||
</Anchor>
|
||||
.
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Switch
|
||||
defaultChecked={checked}
|
||||
onChange={handleChange}
|
||||
disabled={!hasAccess}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
{checked && (
|
||||
<div>
|
||||
<Text size="sm" fw={500} mb={4}>
|
||||
{t("MCP Server URL")}
|
||||
</Text>
|
||||
<Group gap="xs">
|
||||
<TextInput
|
||||
value={mcpUrl}
|
||||
readOnly
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<CopyButton value={mcpUrl} timeout={2000}>
|
||||
{({ copied, copy }) => (
|
||||
<Tooltip
|
||||
label={copied ? t("Copied") : t("Copy")}
|
||||
withArrow
|
||||
position="right"
|
||||
>
|
||||
<ActionIcon
|
||||
color={copied ? "teal" : "gray"}
|
||||
variant="subtle"
|
||||
onClick={copy}
|
||||
>
|
||||
{copied ? <IconCheck size={16} /> : <IconCopy size={16} />}
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Group>
|
||||
<Text size="sm" c="dimmed" mt="xs">
|
||||
{t(
|
||||
"Use your API key for authentication. You can manage API keys in your account settings.",
|
||||
)}
|
||||
</Text>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={500} mt="md" mb={4}>
|
||||
{t("Supported tools")}
|
||||
</Text>
|
||||
<List size="sm" spacing={2}>
|
||||
<List.Item><Text size="sm" c="dimmed" span>search_pages, get_page, create_page, update_page</Text></List.Item>
|
||||
<List.Item><Text size="sm" c="dimmed" span>list_pages, list_child_pages, duplicate_page</Text></List.Item>
|
||||
<List.Item><Text size="sm" c="dimmed" span>copy_page_to_space, move_page, move_page_to_space</Text></List.Item>
|
||||
<List.Item><Text size="sm" c="dimmed" span>get_space, list_spaces, create_space, update_space</Text></List.Item>
|
||||
<List.Item><Text size="sm" c="dimmed" span>get_comments, create_comment, update_comment</Text></List.Item>
|
||||
<List.Item><Text size="sm" c="dimmed" span>search_attachments, list_workspace_members, get_current_user</Text></List.Item>
|
||||
</List>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -6,44 +6,75 @@ import useUserRole from "@/hooks/use-user-role.tsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import EnableAiSearch from "@/ee/ai/components/enable-ai-search.tsx";
|
||||
import EnableGenerativeAi from "@/ee/ai/components/enable-generative-ai.tsx";
|
||||
import { Alert, Stack } from "@mantine/core";
|
||||
import McpSettings from "@/ee/ai/components/mcp-settings.tsx";
|
||||
import { Alert, Stack, Tabs } from "@mantine/core";
|
||||
import { IconInfoCircle } from "@tabler/icons-react";
|
||||
import { useIsCloudEE } from "@/hooks/use-is-cloud-ee.tsx";
|
||||
import { isCloud } from "@/lib/config.ts";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
export default function AiSettings() {
|
||||
const { t } = useTranslation();
|
||||
const { isAdmin } = useUserRole();
|
||||
const hasAccess = useIsCloudEE();
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const activeTab = location.pathname.endsWith("/mcp") ? "mcp" : "ai";
|
||||
|
||||
if (!isAdmin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleTabChange = (value: string | null) => {
|
||||
if (value === "mcp") {
|
||||
navigate("/settings/ai/mcp");
|
||||
} else {
|
||||
navigate("/settings/ai");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>AI - {getAppName()}</title>
|
||||
</Helmet>
|
||||
<SettingsTitle title={t("AI settings")} />
|
||||
<SettingsTitle title={t("AI")} />
|
||||
|
||||
{!hasAccess && (
|
||||
<Alert
|
||||
icon={<IconInfoCircle />}
|
||||
title={t("Enterprise feature")}
|
||||
color="blue"
|
||||
mb="lg"
|
||||
>
|
||||
{t(
|
||||
"AI is only available in the Docmost enterprise edition. Contact sales@docmost.com.",
|
||||
<Tabs color="dark" value={activeTab} onChange={handleTabChange}>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab fw={500} value="ai">
|
||||
{t("AI")}
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab fw={500} value="mcp">
|
||||
{t("MCP")}
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="ai" pt="md">
|
||||
{!hasAccess && (
|
||||
<Alert
|
||||
icon={<IconInfoCircle />}
|
||||
title={t("Enterprise feature")}
|
||||
color="blue"
|
||||
mb="lg"
|
||||
>
|
||||
{t(
|
||||
"AI is only available in the Docmost enterprise edition. Contact sales@docmost.com.",
|
||||
)}
|
||||
</Alert>
|
||||
)}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Stack gap="md">
|
||||
{!isCloud() && <EnableAiSearch />}
|
||||
<EnableGenerativeAi />
|
||||
</Stack>
|
||||
<Stack gap="md">
|
||||
{!isCloud() && <EnableAiSearch />}
|
||||
<EnableGenerativeAi />
|
||||
</Stack>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="mcp" pt="md">
|
||||
<McpSettings />
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { lazy, Suspense, useState } from "react";
|
||||
import { Modal, TextInput, Button, Group, Stack, Select } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod/v4";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCreateApiKeyMutation } from "@/ee/api-key/queries/api-key-query";
|
||||
import { IconCalendar } from "@tabler/icons-react";
|
||||
@@ -36,7 +36,7 @@ export function CreateApiKeyModal({
|
||||
const createApiKeyMutation = useCreateApiKeyMutation();
|
||||
|
||||
const form = useForm<FormValues>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
name: "",
|
||||
expiresAt: "",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Modal, TextInput, Button, Group, Stack } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod/v4";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useUpdateApiKeyMutation } from "@/ee/api-key/queries/api-key-query";
|
||||
import { IApiKey } from "@/ee/api-key";
|
||||
@@ -27,7 +27,7 @@ export function UpdateApiKeyModal({
|
||||
const updateApiKeyMutation = useUpdateApiKeyMutation();
|
||||
|
||||
const form = useForm<FormValues>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
name: "",
|
||||
},
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useState } from "react";
|
||||
import { Button, Group, Space } from "@mantine/core";
|
||||
import { Anchor, Alert, Button, Group, Space, Text } from "@mantine/core";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SettingsTitle from "@/components/settings/settings-title";
|
||||
import { getAppName } from "@/lib/config";
|
||||
import { getAppName, getAppUrl } from "@/lib/config";
|
||||
import { ApiKeyTable } from "@/ee/api-key/components/api-key-table";
|
||||
import { CreateApiKeyModal } from "@/ee/api-key/components/create-api-key-modal";
|
||||
import { ApiKeyCreatedModal } from "@/ee/api-key/components/api-key-created-modal";
|
||||
@@ -13,6 +13,8 @@ import Paginate from "@/components/common/paginate";
|
||||
import { useCursorPaginate } from "@/hooks/use-cursor-paginate";
|
||||
import { useGetApiKeysQuery } from "@/ee/api-key/queries/api-key-query.ts";
|
||||
import { IApiKey } from "@/ee/api-key";
|
||||
import { useAtom } from "jotai";
|
||||
import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts";
|
||||
|
||||
export default function UserApiKeys() {
|
||||
const { t } = useTranslation();
|
||||
@@ -23,6 +25,8 @@ export default function UserApiKeys() {
|
||||
const [revokeModalOpened, setRevokeModalOpened] = useState(false);
|
||||
const [selectedApiKey, setSelectedApiKey] = useState<IApiKey | null>(null);
|
||||
const { data, isLoading } = useGetApiKeysQuery({ cursor });
|
||||
const [workspace] = useAtom(workspaceAtom);
|
||||
const mcpEnabled = workspace?.settings?.ai?.mcp === true;
|
||||
|
||||
const handleCreateSuccess = (response: IApiKey) => {
|
||||
setCreatedApiKey(response);
|
||||
@@ -48,6 +52,37 @@ export default function UserApiKeys() {
|
||||
|
||||
<SettingsTitle title={t("API keys")} />
|
||||
|
||||
<Text size="sm" c="dimmed" mb="md">
|
||||
{t("View the")}{" "}
|
||||
<Anchor href="https://docmost.com/api-docs" target="_blank" size="sm">
|
||||
{t("API documentation")}
|
||||
</Anchor>{" "}
|
||||
{t("for usage details.")}
|
||||
</Text>
|
||||
|
||||
{mcpEnabled && (
|
||||
<Alert variant="light" color="blue" mb="md" p="sm">
|
||||
<Text size="sm">
|
||||
{t(
|
||||
"Your workspace has MCP enabled. Use your API key to connect AI assistants.",
|
||||
)}{" "}
|
||||
<Anchor
|
||||
href="https://docmost.com/docs/user-guide/mcp"
|
||||
target="_blank"
|
||||
size="sm"
|
||||
>
|
||||
{t("Learn more")}
|
||||
</Anchor>
|
||||
</Text>
|
||||
<Text size="sm" mt={4}>
|
||||
{t("MCP server URL:")}{" "}
|
||||
<Text size="sm" fw={500} span ff="monospace">
|
||||
{`${getAppUrl()}/api/mcp`}
|
||||
</Text>
|
||||
</Text>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Group justify="flex-end" mb="md">
|
||||
<Button onClick={() => setCreateModalOpened(true)}>
|
||||
{t("Create API Key")}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { Button, Group, Space, Text } from "@mantine/core";
|
||||
import { Anchor, Button, Group, Space, Text } from "@mantine/core";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SettingsTitle from "@/components/settings/settings-title";
|
||||
@@ -54,8 +54,13 @@ export default function WorkspaceApiKeys() {
|
||||
|
||||
<SettingsTitle title={t("API management")} />
|
||||
|
||||
<Text size="md" c="dimmed" mb="md">
|
||||
{t("Manage API keys for all users in the workspace")}
|
||||
<Text size="sm" c="dimmed" mb="md">
|
||||
{t("Manage API keys for all users in the workspace.")}{" "}
|
||||
{t("View the")}{" "}
|
||||
<Anchor href="https://docmost.com/api-docs" target="_blank" size="sm">
|
||||
{t("API documentation")}
|
||||
</Anchor>{" "}
|
||||
{t("for usage details.")}
|
||||
</Text>
|
||||
|
||||
<Group justify="flex-end" mb="md">
|
||||
|
||||
@@ -235,6 +235,7 @@ export default function AuditLogsTable({
|
||||
{entry.actor ? (
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<CustomAvatar
|
||||
avatarUrl={entry.actor.avatarUrl}
|
||||
name={entry.actor.name}
|
||||
size={36}
|
||||
/>
|
||||
|
||||
@@ -18,6 +18,7 @@ export type IAuditLog = {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
avatarUrl?: string;
|
||||
};
|
||||
resource?: {
|
||||
id: string;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as z from "zod";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { z } from "zod/v4";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import {
|
||||
Container,
|
||||
Title,
|
||||
@@ -30,7 +31,7 @@ export function CloudLoginForm() {
|
||||
const { data: joinedWorkspaces } = useJoinedWorkspacesQuery();
|
||||
|
||||
const form = useForm<any>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
hostname: "",
|
||||
},
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { useState } from "react";
|
||||
import { Modal, TextInput, PasswordInput, Button, Stack } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod/v4";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -34,7 +34,7 @@ export function LdapLoginModal({
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const form = useForm({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
username: "",
|
||||
password: "",
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { Button, Group, Text, Modal, TextInput } from "@mantine/core";
|
||||
import * as z from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { useState } from "react";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import * as React from "react";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getSubdomainHost } from "@/lib/config.ts";
|
||||
import { IWorkspace } from "@/features/workspace/types/workspace.types.ts";
|
||||
import { updateWorkspace } from "@/features/workspace/services/workspace-service.ts";
|
||||
import { getHostnameUrl } from "@/ee/utils.ts";
|
||||
import { useAtom } from "jotai/index";
|
||||
import { useAtom } from "jotai";
|
||||
import {
|
||||
currentUserAtom,
|
||||
workspaceAtom,
|
||||
@@ -66,7 +67,7 @@ function ChangeHostnameForm({ onClose }: ChangeHostnameFormProps) {
|
||||
const [currentUser, setCurrentUser] = useAtom(currentUserAtom);
|
||||
|
||||
const form = useForm<FormValues>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
hostname: currentUser?.workspace?.hostname,
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import * as z from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import React from "react";
|
||||
import { Button, Group, Modal, Textarea } from "@mantine/core";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useActivateMutation } from "@/ee/licence/queries/license-query.ts";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
@@ -49,7 +50,7 @@ export function ActivateLicenseForm({ onClose }: ActivateLicenseFormProps) {
|
||||
const activateLicenseMutation = useActivateMutation();
|
||||
|
||||
const form = useForm<FormValues>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
licenseKey: "",
|
||||
},
|
||||
|
||||
@@ -23,8 +23,8 @@ import { notifications } from "@mantine/notifications";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { regenerateBackupCodes } from "@/ee/mfa";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod/v4";
|
||||
import useCurrentUser from "@/features/user/hooks/use-current-user";
|
||||
|
||||
interface MfaBackupCodesModalProps {
|
||||
@@ -51,7 +51,7 @@ export function MfaBackupCodesModal({
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
confirmPassword: "",
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
ThemeIcon,
|
||||
} from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { IconDeviceMobile, IconLock } from "@tabler/icons-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
@@ -20,7 +20,7 @@ import classes from "./mfa-challenge.module.css";
|
||||
import { verifyMfa } from "@/ee/mfa";
|
||||
import APP_ROUTE, { getPostLoginRedirect } from "@/lib/app-route";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import * as z from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { MfaBackupCodeInput } from "./mfa-backup-code-input";
|
||||
|
||||
const formSchema = z.object({
|
||||
@@ -43,7 +43,7 @@ export function MfaChallenge() {
|
||||
const [useBackupCode, setUseBackupCode] = useState(false);
|
||||
|
||||
const form = useForm<MfaChallengeFormValues>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
code: "",
|
||||
},
|
||||
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { IconShieldOff, IconAlertTriangle } from "@tabler/icons-react";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { disableMfa } from "@/ee/mfa";
|
||||
import useCurrentUser from "@/features/user/hooks/use-current-user";
|
||||
|
||||
@@ -41,7 +41,7 @@ export function MfaDisableModal({
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
confirmPassword: "",
|
||||
},
|
||||
@@ -63,7 +63,7 @@ export function MfaDisableModal({
|
||||
|
||||
const handleSubmit = async (values: { confirmPassword?: string }) => {
|
||||
// Only send confirmPassword if it's required (non-SSO users)
|
||||
const payload = requiresPassword
|
||||
const payload = requiresPassword
|
||||
? { confirmPassword: values.confirmPassword }
|
||||
: {};
|
||||
await disableMutation.mutateAsync(payload);
|
||||
|
||||
@@ -36,8 +36,8 @@ import { useMutation } from "@tanstack/react-query";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { setupMfa, enableMfa } from "@/ee/mfa";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
interface MfaSetupModalProps {
|
||||
opened: boolean;
|
||||
@@ -71,7 +71,7 @@ export function MfaSetupModal({
|
||||
const [manualEntryOpen, setManualEntryOpen] = useState(false);
|
||||
|
||||
const form = useForm({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
verificationCode: "",
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useAtom } from "jotai";
|
||||
import * as z from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts";
|
||||
import React, { useState } from "react";
|
||||
import { Button, Text, TagsInput } from "@mantine/core";
|
||||
@@ -22,7 +22,7 @@ export default function AllowedDomains() {
|
||||
const [, setDomains] = useState<string[]>([]);
|
||||
|
||||
const form = useForm<FormValues>({
|
||||
validate: zodResolver(formSchema),
|
||||
validate: zod4Resolver(formSchema),
|
||||
initialValues: {
|
||||
emailDomains: workspace?.emailDomains || [],
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { Box, Button, Group, Stack, Switch, TextInput } from "@mantine/core";
|
||||
import classes from "@/ee/security/components/sso.module.css";
|
||||
import { IAuthProvider } from "@/ee/security/types/security.types.ts";
|
||||
@@ -30,7 +30,7 @@ export function SsoGoogleForm({ provider, onClose }: SsoFormProps) {
|
||||
isEnabled: provider.isEnabled,
|
||||
allowSignup: provider.allowSignup,
|
||||
},
|
||||
validate: zodResolver(ssoSchema),
|
||||
validate: zod4Resolver(ssoSchema),
|
||||
});
|
||||
|
||||
const handleSubmit = async (values: SSOFormValues) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -59,7 +59,7 @@ export function SsoLDAPForm({ provider, onClose }: SsoFormProps) {
|
||||
allowSignup: provider.allowSignup,
|
||||
groupSync: provider.groupSync || false,
|
||||
},
|
||||
validate: zodResolver(ssoSchema),
|
||||
validate: zod4Resolver(ssoSchema),
|
||||
});
|
||||
|
||||
const handleSubmit = async (values: SSOFormValues) => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import { z } from "zod";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { z } from "zod/v4";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import { Box, Button, Group, Stack, Switch, TextInput } from "@mantine/core";
|
||||
import { buildCallbackUrl } from "@/ee/security/sso.utils.ts";
|
||||
import classes from "@/ee/security/components/sso.module.css";
|
||||
@@ -39,7 +40,7 @@ export function SsoOIDCForm({ provider, onClose }: SsoFormProps) {
|
||||
allowSignup: provider.allowSignup,
|
||||
groupSync: provider.groupSync || false,
|
||||
},
|
||||
validate: zodResolver(ssoSchema),
|
||||
validate: zod4Resolver(ssoSchema),
|
||||
});
|
||||
|
||||
const callbackUrl = buildCallbackUrl({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import { zod4Resolver } from "mantine-form-zod-resolver";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -49,7 +49,7 @@ export function SsoSamlForm({ provider, onClose }: SsoFormProps) {
|
||||
allowSignup: provider.allowSignup,
|
||||
groupSync: provider.groupSync || false,
|
||||
},
|
||||
validate: zodResolver(ssoSchema),
|
||||
validate: zod4Resolver(ssoSchema),
|
||||
});
|
||||
|
||||
const callbackUrl = buildCallbackUrl({
|
||||
|
||||
Reference in New Issue
Block a user