mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 09:12:02 +10:00
Merge branch 'main' into staging
This commit is contained in:
2
.github/workflows/translations-upload.yml
vendored
2
.github/workflows/translations-upload.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
token: ${{ secrets.GH_PAT }}
|
||||||
|
|
||||||
- uses: ./.github/actions/node-install
|
- uses: ./.github/actions/node-install
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@documenso/marketing",
|
"name": "@documenso/marketing",
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3001",
|
"dev": "next dev -p 3001",
|
||||||
"build": "turbo run translate:extract && turbo run translate:compile && next build",
|
"build": "npm run translate:extract --prefix ../../ && turbo run translate:compile && next build",
|
||||||
"start": "next start -p 3001",
|
"start": "next start -p 3001",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"lint:fix": "next lint --fix",
|
"lint:fix": "next lint --fix",
|
||||||
|
|||||||
@ -30,8 +30,8 @@ const mdxComponents: MDXComponents = {
|
|||||||
*
|
*
|
||||||
* Will render the document if it exists, otherwise will return a 404.
|
* Will render the document if it exists, otherwise will return a 404.
|
||||||
*/
|
*/
|
||||||
export default function ContentPage({ params }: { params: { content: string } }) {
|
export default async function ContentPage({ params }: { params: { content: string } }) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const post = allDocuments.find((post) => post._raw.flattenedPath === params.content);
|
const post = allDocuments.find((post) => post._raw.flattenedPath === params.content);
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,8 @@ const mdxComponents: MDXComponents = {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function BlogPostPage({ params }: { params: { post: string } }) {
|
export default async function BlogPostPage({ params }: { params: { post: string } }) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const post = allBlogPosts.find((post) => post._raw.flattenedPath === `blog/${params.post}`);
|
const post = allBlogPosts.find((post) => post._raw.flattenedPath === `blog/${params.post}`);
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Blog',
|
title: 'Blog',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function BlogPage() {
|
export default async function BlogPage() {
|
||||||
const { i18n } = setupI18nSSR();
|
const { i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
const blogPosts = allBlogPosts.sort((a, b) => {
|
const blogPosts = allBlogPosts.sort((a, b) => {
|
||||||
const dateA = new Date(a.date);
|
const dateA = new Date(a.date);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
import { Trans, msg } from '@lingui/macro';
|
import { Trans, msg } from '@lingui/macro';
|
||||||
import { useLingui } from '@lingui/react';
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
||||||
@ -131,9 +130,9 @@ const fetchEarlyAdopters = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function OpenPage() {
|
export default async function OpenPage() {
|
||||||
setupI18nSSR();
|
const { i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = i18n;
|
||||||
|
|
||||||
const [
|
const [
|
||||||
{ forks_count: forksCount, stargazers_count: stargazersCount },
|
{ forks_count: forksCount, stargazers_count: stargazersCount },
|
||||||
|
|||||||
@ -26,7 +26,7 @@ const fontCaveat = Caveat({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default async function IndexPage() {
|
export default async function IndexPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const starCount = await fetch('https://api.github.com/repos/documenso/documenso', {
|
const starCount = await fetch('https://api.github.com/repos/documenso/documenso', {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -30,8 +30,8 @@ export type PricingPageProps = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function PricingPage() {
|
export default async function PricingPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 sm:mt-12">
|
<div className="mt-6 sm:mt-12">
|
||||||
|
|||||||
@ -14,8 +14,8 @@ export const dynamic = 'force-dynamic';
|
|||||||
// !: This entire file is a hack to get around failed prerendering of
|
// !: This entire file is a hack to get around failed prerendering of
|
||||||
// !: the Single Player Mode page. This regression was introduced during
|
// !: the Single Player Mode page. This regression was introduced during
|
||||||
// !: the upgrade of Next.js to v13.5.x.
|
// !: the upgrade of Next.js to v13.5.x.
|
||||||
export default function SingleplayerPage() {
|
export default async function SingleplayerPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <SinglePlayerClient />;
|
return <SinglePlayerClient />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export function generateMetadata() {
|
|||||||
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
const flags = await getAllAnonymousFlags();
|
const flags = await getAllAnonymousFlags();
|
||||||
|
|
||||||
const { lang, locales, i18n } = setupI18nSSR();
|
const { lang, locales, i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html
|
<html
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@documenso/web",
|
"name": "@documenso/web",
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3000",
|
"dev": "next dev -p 3000",
|
||||||
"build": "turbo run translate:extract && turbo run translate:compile && next build",
|
"build": "npm run translate:extract --prefix ../../ && turbo run translate:compile && next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"e2e:prepare": "next build && next start",
|
"e2e:prepare": "next build && next start",
|
||||||
|
|||||||
@ -24,7 +24,7 @@ type AdminDocumentDetailsPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function AdminDocumentDetailsPage({ params }: AdminDocumentDetailsPageProps) {
|
export default async function AdminDocumentDetailsPage({ params }: AdminDocumentDetailsPageProps) {
|
||||||
const { i18n } = setupI18nSSR();
|
const { i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
const document = await getEntireDocument({ id: Number(params.id) });
|
const document = await getEntireDocument({ id: Number(params.id) });
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
|||||||
|
|
||||||
import { AdminDocumentResults } from './document-results';
|
import { AdminDocumentResults } from './document-results';
|
||||||
|
|
||||||
export default function AdminDocumentsPage() {
|
export default async function AdminDocumentsPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export type AdminSectionLayoutProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function AdminSectionLayout({ children }: AdminSectionLayoutProps) {
|
export default async function AdminSectionLayout({ children }: AdminSectionLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { user } = await getRequiredServerComponentSession();
|
const { user } = await getRequiredServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { BannerForm } from './banner-form';
|
|||||||
// import { BannerForm } from './banner-form';
|
// import { BannerForm } from './banner-form';
|
||||||
|
|
||||||
export default async function AdminBannerPage() {
|
export default async function AdminBannerPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import { SignerConversionChart } from './signer-conversion-chart';
|
|||||||
import { UserWithDocumentChart } from './user-with-document';
|
import { UserWithDocumentChart } from './user-with-document';
|
||||||
|
|
||||||
export default async function AdminStatsPage() {
|
export default async function AdminStatsPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import {
|
|||||||
} from '@documenso/ui/primitives/table';
|
} from '@documenso/ui/primitives/table';
|
||||||
|
|
||||||
export default async function Subscriptions() {
|
export default async function Subscriptions() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const subscriptions = await findSubscriptions();
|
const subscriptions = await findSubscriptions();
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ type AdminManageUsersProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function AdminManageUsers({ searchParams = {} }: AdminManageUsersProps) {
|
export default async function AdminManageUsers({ searchParams = {} }: AdminManageUsersProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const page = Number(searchParams.page) || 1;
|
const page = Number(searchParams.page) || 1;
|
||||||
const perPage = Number(searchParams.perPage) || 10;
|
const perPage = Number(searchParams.perPage) || 10;
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useRouter, useSearchParams } from 'next/navigation';
|
|||||||
import { msg } from '@lingui/macro';
|
import { msg } from '@lingui/macro';
|
||||||
import { useLingui } from '@lingui/react';
|
import { useLingui } from '@lingui/react';
|
||||||
|
|
||||||
|
import { isValidLanguageCode } from '@documenso/lib/constants/i18n';
|
||||||
import {
|
import {
|
||||||
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||||
SKIP_QUERY_BATCH_META,
|
SKIP_QUERY_BATCH_META,
|
||||||
@ -201,7 +202,7 @@ export const EditDocumentForm = ({
|
|||||||
|
|
||||||
const onAddSettingsFormSubmit = async (data: TAddSettingsFormSchema) => {
|
const onAddSettingsFormSubmit = async (data: TAddSettingsFormSchema) => {
|
||||||
try {
|
try {
|
||||||
const { timezone, dateFormat, redirectUrl } = data.meta;
|
const { timezone, dateFormat, redirectUrl, language } = data.meta;
|
||||||
|
|
||||||
await setSettingsForDocument({
|
await setSettingsForDocument({
|
||||||
documentId: document.id,
|
documentId: document.id,
|
||||||
@ -217,6 +218,7 @@ export const EditDocumentForm = ({
|
|||||||
timezone,
|
timezone,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
redirectUrl,
|
redirectUrl,
|
||||||
|
language: isValidLanguageCode(language) ? language : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,8 @@ export type DocumentPageProps = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DocumentEditPage({ params }: DocumentPageProps) {
|
export default async function DocumentEditPage({ params }: DocumentPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <DocumentEditPageView params={params} />;
|
return <DocumentEditPageView params={params} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,8 @@ import { ChevronLeft, Loader } from 'lucide-react';
|
|||||||
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
||||||
import { Skeleton } from '@documenso/ui/primitives/skeleton';
|
import { Skeleton } from '@documenso/ui/primitives/skeleton';
|
||||||
|
|
||||||
export default function Loading() {
|
export default async function Loading() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto -mt-4 flex w-full max-w-screen-xl flex-col px-4 md:px-8">
|
<div className="mx-auto -mt-4 flex w-full max-w-screen-xl flex-col px-4 md:px-8">
|
||||||
|
|||||||
@ -8,8 +8,8 @@ export type DocumentsLogsPageProps = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DocumentsLogsPage({ params }: DocumentsLogsPageProps) {
|
export default async function DocumentsLogsPage({ params }: DocumentsLogsPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <DocumentLogsPageView params={params} />;
|
return <DocumentLogsPageView params={params} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,8 @@ export type DocumentPageProps = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DocumentPage({ params }: DocumentPageProps) {
|
export default async function DocumentPage({ params }: DocumentPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <DocumentPageView params={params} />;
|
return <DocumentPageView params={params} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { ChevronLeft } from 'lucide-react';
|
|||||||
|
|
||||||
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
||||||
|
|
||||||
export default function DocumentSentPage() {
|
export default async function DocumentSentPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto -mt-4 flex w-full max-w-screen-xl flex-col px-4 md:px-8">
|
<div className="mx-auto -mt-4 flex w-full max-w-screen-xl flex-col px-4 md:px-8">
|
||||||
|
|||||||
@ -87,7 +87,7 @@ export const DeleteDocumentDialog = ({
|
|||||||
|
|
||||||
const onInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const onInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setInputValue(event.target.value);
|
setInputValue(event.target.value);
|
||||||
setIsDeleteEnabled(event.target.value === 'delete');
|
setIsDeleteEnabled(event.target.value === _(msg`delete`));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -117,10 +117,10 @@ export const MoveDocumentDialog = ({ documentId, open, onOpenChange }: MoveDocum
|
|||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button variant="secondary" onClick={() => onOpenChange(false)}>
|
<Button variant="secondary" onClick={() => onOpenChange(false)}>
|
||||||
Cancel
|
<Trans>Cancel</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={onMove} loading={isLoading} disabled={!selectedTeamId || isLoading}>
|
<Button onClick={onMove} loading={isLoading} disabled={!selectedTeamId || isLoading}>
|
||||||
{isLoading ? 'Moving...' : 'Move'}
|
{isLoading ? <Trans>Moving...</Trans> : <Trans>Move</Trans>}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function DocumentsPage({ searchParams = {} }: DocumentsPageProps) {
|
export default async function DocumentsPage({ searchParams = {} }: DocumentsPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { user } = await getRequiredServerComponentSession();
|
const { user } = await getRequiredServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export type AuthenticatedDashboardLayoutProps = {
|
|||||||
export default async function AuthenticatedDashboardLayout({
|
export default async function AuthenticatedDashboardLayout({
|
||||||
children,
|
children,
|
||||||
}: AuthenticatedDashboardLayoutProps) {
|
}: AuthenticatedDashboardLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const session = await getServerSession(NEXT_AUTH_OPTIONS);
|
const session = await getServerSession(NEXT_AUTH_OPTIONS);
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function BillingSettingsPage() {
|
export default async function BillingSettingsPage() {
|
||||||
const { i18n } = setupI18nSSR();
|
const { i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
let { user } = await getRequiredServerComponentSession();
|
let { user } = await getRequiredServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,8 @@ export type DashboardSettingsLayoutProps = {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DashboardSettingsLayout({ children }: DashboardSettingsLayoutProps) {
|
export default async function DashboardSettingsLayout({ children }: DashboardSettingsLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function ProfileSettingsPage() {
|
export default async function ProfileSettingsPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
const { user } = await getRequiredServerComponentSession();
|
const { user } = await getRequiredServerComponentSession();
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { getUserPublicProfile } from '@documenso/lib/server-only/user/get-user-p
|
|||||||
import { PublicProfilePageView } from './public-profile-page-view';
|
import { PublicProfilePageView } from './public-profile-page-view';
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { user } = await getRequiredServerComponentSession();
|
const { user } = await getRequiredServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -14,8 +14,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Security activity',
|
title: 'Security activity',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SettingsSecurityActivityPage() {
|
export default async function SettingsSecurityActivityPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function SecuritySettingsPage() {
|
export default async function SecuritySettingsPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
const { user } = await getRequiredServerComponentSession();
|
const { user } = await getRequiredServerComponentSession();
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function SettingsManagePasskeysPage() {
|
export default async function SettingsManagePasskeysPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
const isPasskeyEnabled = await getServerComponentFlag('app_passkey');
|
const isPasskeyEnabled = await getServerComponentFlag('app_passkey');
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import DeleteTokenDialog from '~/components/(dashboard)/settings/token/delete-to
|
|||||||
import { ApiTokenForm } from '~/components/forms/token';
|
import { ApiTokenForm } from '~/components/forms/token';
|
||||||
|
|
||||||
export default async function ApiTokensPage() {
|
export default async function ApiTokensPage() {
|
||||||
const { i18n } = setupI18nSSR();
|
const { i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
const { user } = await getRequiredServerComponentSession();
|
const { user } = await getRequiredServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useRouter } from 'next/navigation';
|
|||||||
import { msg } from '@lingui/macro';
|
import { msg } from '@lingui/macro';
|
||||||
import { useLingui } from '@lingui/react';
|
import { useLingui } from '@lingui/react';
|
||||||
|
|
||||||
|
import { isValidLanguageCode } from '@documenso/lib/constants/i18n';
|
||||||
import {
|
import {
|
||||||
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||||
SKIP_QUERY_BATCH_META,
|
SKIP_QUERY_BATCH_META,
|
||||||
@ -151,7 +152,10 @@ export const EditTemplateForm = ({
|
|||||||
globalAccessAuth: data.globalAccessAuth ?? null,
|
globalAccessAuth: data.globalAccessAuth ?? null,
|
||||||
globalActionAuth: data.globalActionAuth ?? null,
|
globalActionAuth: data.globalActionAuth ?? null,
|
||||||
},
|
},
|
||||||
meta: data.meta,
|
meta: {
|
||||||
|
...data.meta,
|
||||||
|
language: isValidLanguageCode(data.meta.language) ? data.meta.language : undefined,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Router refresh is here to clear the router cache for when navigating to /documents.
|
// Router refresh is here to clear the router cache for when navigating to /documents.
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import { TemplatePageView } from './template-page-view';
|
|||||||
|
|
||||||
type TemplatePageProps = Pick<TemplatePageViewProps, 'params'>;
|
type TemplatePageProps = Pick<TemplatePageViewProps, 'params'>;
|
||||||
|
|
||||||
export default function TemplatePage({ params }: TemplatePageProps) {
|
export default async function TemplatePage({ params }: TemplatePageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <TemplatePageView params={params} />;
|
return <TemplatePageView params={params} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Templates',
|
title: 'Templates',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function TemplatesPage({ searchParams = {} }: TemplatesPageProps) {
|
export default async function TemplatesPage({ searchParams = {} }: TemplatesPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <TemplatesPageView searchParams={searchParams} />;
|
return <TemplatesPageView searchParams={searchParams} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ type PublicProfileLayoutProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function PublicProfileLayout({ children }: PublicProfileLayoutProps) {
|
export default async function PublicProfileLayout({ children }: PublicProfileLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { user, session } = await getServerComponentSession();
|
const { user, session } = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ const BADGE_DATA = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function PublicProfilePage({ params }: PublicProfilePageProps) {
|
export default async function PublicProfilePage({ params }: PublicProfilePageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { url: profileUrl } = params;
|
const { url: profileUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { Trans } from '@lingui/macro';
|
import { Trans, msg } from '@lingui/macro';
|
||||||
import { useLingui } from '@lingui/react';
|
import { useLingui } from '@lingui/react';
|
||||||
import { useSession } from 'next-auth/react';
|
import { useSession } from 'next-auth/react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
@ -77,7 +77,7 @@ export const ConfigureDirectTemplateFormPartial = ({
|
|||||||
if (template.Recipient.map((recipient) => recipient.email).includes(items.email)) {
|
if (template.Recipient.map((recipient) => recipient.email).includes(items.email)) {
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
code: z.ZodIssueCode.custom,
|
code: z.ZodIssueCode.custom,
|
||||||
message: 'Email cannot already exist in the template',
|
message: _(msg`Email cannot already exist in the template`),
|
||||||
path: ['email'],
|
path: ['email'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export type TemplatesDirectPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TemplatesDirectPage({ params }: TemplatesDirectPageProps) {
|
export default async function TemplatesDirectPage({ params }: TemplatesDirectPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { token } = params;
|
const { token } = params;
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type RecipientLayoutProps = {
|
|||||||
* Such as direct template access, or signing.
|
* Such as direct template access, or signing.
|
||||||
*/
|
*/
|
||||||
export default async function RecipientLayout({ children }: RecipientLayoutProps) {
|
export default async function RecipientLayout({ children }: RecipientLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { user, session } = await getServerComponentSession();
|
const { user, session } = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,8 @@ export type SigningLayoutProps = {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SigningLayout({ children }: SigningLayoutProps) {
|
export default async function SigningLayout({ children }: SigningLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export type CompletedSigningPageProps = {
|
|||||||
export default async function CompletedSigningPage({
|
export default async function CompletedSigningPage({
|
||||||
params: { token },
|
params: { token },
|
||||||
}: CompletedSigningPageProps) {
|
}: CompletedSigningPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ export default async function CompletedSigningPage({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{isLoggedIn && (
|
{isLoggedIn && (
|
||||||
<Link href="/documents" className="text-documenso-700 hover:text-documenso-600">
|
<Link href="/documents" className="text-documenso-700 hover:text-documenso-600 mt-2">
|
||||||
<Trans>Go Back Home</Trans>
|
<Trans>Go Back Home</Trans>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -124,9 +124,9 @@ export const SigningForm = ({
|
|||||||
>
|
>
|
||||||
<div className={cn('flex flex-1 flex-col')}>
|
<div className={cn('flex flex-1 flex-col')}>
|
||||||
<h3 className="text-foreground text-2xl font-semibold">
|
<h3 className="text-foreground text-2xl font-semibold">
|
||||||
{recipient.role === RecipientRole.VIEWER && 'View Document'}
|
{recipient.role === RecipientRole.VIEWER && <Trans>View Document</Trans>}
|
||||||
{recipient.role === RecipientRole.SIGNER && 'Sign Document'}
|
{recipient.role === RecipientRole.SIGNER && <Trans>Sign Document</Trans>}
|
||||||
{recipient.role === RecipientRole.APPROVER && 'Approve Document'}
|
{recipient.role === RecipientRole.APPROVER && <Trans>Approve Document</Trans>}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{recipient.role === RecipientRole.VIEWER ? (
|
{recipient.role === RecipientRole.VIEWER ? (
|
||||||
@ -166,7 +166,7 @@ export const SigningForm = ({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className="text-muted-foreground mt-2 text-sm">
|
<p className="text-muted-foreground mt-2 text-sm">
|
||||||
Please review the document before signing.
|
<Trans>Please review the document before signing.</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<hr className="border-border mb-8 mt-4" />
|
<hr className="border-border mb-8 mt-4" />
|
||||||
@ -174,7 +174,9 @@ export const SigningForm = ({
|
|||||||
<div className="-mx-2 flex flex-1 flex-col gap-4 overflow-y-auto px-2">
|
<div className="-mx-2 flex flex-1 flex-col gap-4 overflow-y-auto px-2">
|
||||||
<div className="flex flex-1 flex-col gap-y-4">
|
<div className="flex flex-1 flex-col gap-y-4">
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="full-name">Full Name</Label>
|
<Label htmlFor="full-name">
|
||||||
|
<Trans>Full Name</Trans>
|
||||||
|
</Label>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
@ -186,7 +188,9 @@ export const SigningForm = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="Signature">Signature</Label>
|
<Label htmlFor="Signature">
|
||||||
|
<Trans>Signature</Trans>
|
||||||
|
</Label>
|
||||||
|
|
||||||
<Card className="mt-2" gradient degrees={-120}>
|
<Card className="mt-2" gradient degrees={-120}>
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
@ -213,7 +217,7 @@ export const SigningForm = ({
|
|||||||
disabled={typeof window !== 'undefined' && window.history.length <= 1}
|
disabled={typeof window !== 'undefined' && window.history.length <= 1}
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
>
|
>
|
||||||
Cancel
|
<Trans>Cancel</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<SignDialog
|
<SignDialog
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { useTransition } from 'react';
|
|||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
|
import { Trans, msg } from '@lingui/macro';
|
||||||
|
import { useLingui } from '@lingui/react';
|
||||||
import { Loader } from 'lucide-react';
|
import { Loader } from 'lucide-react';
|
||||||
|
|
||||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||||
@ -37,6 +39,7 @@ export const InitialsField = ({
|
|||||||
}: InitialsFieldProps) => {
|
}: InitialsFieldProps) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const { _ } = useLingui();
|
||||||
|
|
||||||
const { fullName } = useRequiredSigningContext();
|
const { fullName } = useRequiredSigningContext();
|
||||||
const initials = extractInitials(fullName);
|
const initials = extractInitials(fullName);
|
||||||
@ -83,8 +86,8 @@ export const InitialsField = ({
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: 'Error',
|
title: _(msg`Error`),
|
||||||
description: 'An error occurred while signing the document.',
|
description: _(msg`An error occurred while signing the document.`),
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -109,8 +112,8 @@ export const InitialsField = ({
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: 'Error',
|
title: _(msg`Error`),
|
||||||
description: 'An error occurred while removing the signature.',
|
description: _(msg`An error occurred while removing the field.`),
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -126,7 +129,7 @@ export const InitialsField = ({
|
|||||||
|
|
||||||
{!field.inserted && (
|
{!field.inserted && (
|
||||||
<p className="group-hover:text-primary text-muted-foreground duration-200 group-hover:text-yellow-300">
|
<p className="group-hover:text-primary text-muted-foreground duration-200 group-hover:text-yellow-300">
|
||||||
Initials
|
<Trans>Initials</Trans>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export type SigningLayoutProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function SigningLayout({ children }: SigningLayoutProps) {
|
export default async function SigningLayout({ children }: SigningLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { user, session } = await getServerComponentSession();
|
const { user, session } = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export type SigningPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function SigningPage({ params: { token } }: SigningPageProps) {
|
export default async function SigningPage({ params: { token } }: SigningPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return notFound();
|
return notFound();
|
||||||
@ -43,12 +43,6 @@ export default async function SigningPage({ params: { token } }: SigningPageProp
|
|||||||
|
|
||||||
const requestMetadata = extractNextHeaderRequestMetadata(requestHeaders);
|
const requestMetadata = extractNextHeaderRequestMetadata(requestHeaders);
|
||||||
|
|
||||||
const isRecipientsTurn = await getIsRecipientsTurnToSign({ token });
|
|
||||||
|
|
||||||
if (!isRecipientsTurn) {
|
|
||||||
return redirect(`/sign/${token}/waiting`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [document, fields, recipient, completedFields] = await Promise.all([
|
const [document, fields, recipient, completedFields] = await Promise.all([
|
||||||
getDocumentAndSenderByToken({
|
getDocumentAndSenderByToken({
|
||||||
token,
|
token,
|
||||||
@ -69,6 +63,12 @@ export default async function SigningPage({ params: { token } }: SigningPageProp
|
|||||||
return notFound();
|
return notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isRecipientsTurn = await getIsRecipientsTurnToSign({ token });
|
||||||
|
|
||||||
|
if (!isRecipientsTurn) {
|
||||||
|
return redirect(`/sign/${token}/waiting`);
|
||||||
|
}
|
||||||
|
|
||||||
const { derivedRecipientAccessAuth } = extractDocumentAuthMethods({
|
const { derivedRecipientAccessAuth } = extractDocumentAuthMethods({
|
||||||
documentAuth: document.authOptions,
|
documentAuth: document.authOptions,
|
||||||
recipientAuth: recipient.authOptions,
|
recipientAuth: recipient.authOptions,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ type WaitingForTurnToSignPageProps = {
|
|||||||
export default async function WaitingForTurnToSignPage({
|
export default async function WaitingForTurnToSignPage({
|
||||||
params: { token },
|
params: { token },
|
||||||
}: WaitingForTurnToSignPageProps) {
|
}: WaitingForTurnToSignPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return notFound();
|
return notFound();
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export type DocumentPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TeamsDocumentEditPage({ params }: DocumentPageProps) {
|
export default async function TeamsDocumentEditPage({ params }: DocumentPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export type TeamDocumentsLogsPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TeamsDocumentsLogsPage({ params }: TeamDocumentsLogsPageProps) {
|
export default async function TeamsDocumentsLogsPage({ params }: TeamDocumentsLogsPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export type DocumentPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function DocumentPage({ params }: DocumentPageProps) {
|
export default async function DocumentPage({ params }: DocumentPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export default async function TeamsDocumentPage({
|
|||||||
params,
|
params,
|
||||||
searchParams = {},
|
searchParams = {},
|
||||||
}: TeamsDocumentPageProps) {
|
}: TeamsDocumentPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export default async function AuthenticatedTeamsLayout({
|
|||||||
children,
|
children,
|
||||||
params,
|
params,
|
||||||
}: AuthenticatedTeamsLayoutProps) {
|
}: AuthenticatedTeamsLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { session, user } = await getServerComponentSession();
|
const { session, user } = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export type TeamsSettingsBillingPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TeamsSettingBillingPage({ params }: TeamsSettingsBillingPageProps) {
|
export default async function TeamsSettingBillingPage({ params }: TeamsSettingsBillingPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export default async function TeamsSettingsLayout({
|
|||||||
children,
|
children,
|
||||||
params: { teamUrl },
|
params: { teamUrl },
|
||||||
}: TeamSettingsLayoutProps) {
|
}: TeamSettingsLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const session = await getRequiredServerComponentSession();
|
const session = await getRequiredServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export type TeamsSettingsMembersPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TeamsSettingsMembersPage({ params }: TeamsSettingsMembersPageProps) {
|
export default async function TeamsSettingsMembersPage({ params }: TeamsSettingsMembersPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export type TeamsSettingsPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TeamsSettingsPage({ params }: TeamsSettingsPageProps) {
|
export default async function TeamsSettingsPage({ params }: TeamsSettingsPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export type TeamsSettingsPublicProfilePageProps = {
|
|||||||
export default async function TeamsSettingsPublicProfilePage({
|
export default async function TeamsSettingsPublicProfilePage({
|
||||||
params,
|
params,
|
||||||
}: TeamsSettingsPublicProfilePageProps) {
|
}: TeamsSettingsPublicProfilePageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ type ApiTokensPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function ApiTokensPage({ params }: ApiTokensPageProps) {
|
export default async function ApiTokensPage({ params }: ApiTokensPageProps) {
|
||||||
const { i18n } = setupI18nSSR();
|
const { i18n } = await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
@ -97,17 +97,11 @@ export default async function ApiTokensPage({ params }: ApiTokensPageProps) {
|
|||||||
<h5 className="text-base">{token.name}</h5>
|
<h5 className="text-base">{token.name}</h5>
|
||||||
|
|
||||||
<p className="text-muted-foreground mt-2 text-xs">
|
<p className="text-muted-foreground mt-2 text-xs">
|
||||||
<Trans>
|
<Trans>Created on {i18n.date(token.createdAt, DateTime.DATETIME_FULL)}</Trans>
|
||||||
Created on
|
|
||||||
{i18n.date(token.createdAt, DateTime.DATETIME_FULL)}
|
|
||||||
</Trans>
|
|
||||||
</p>
|
</p>
|
||||||
{token.expires ? (
|
{token.expires ? (
|
||||||
<p className="text-muted-foreground mt-1 text-xs">
|
<p className="text-muted-foreground mt-1 text-xs">
|
||||||
<Trans>
|
<Trans>Expires on {i18n.date(token.expires, DateTime.DATETIME_FULL)}</Trans>
|
||||||
Expires on
|
|
||||||
{i18n.date(token.expires, DateTime.DATETIME_FULL)}
|
|
||||||
</Trans>
|
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-muted-foreground mt-1 text-xs">
|
<p className="text-muted-foreground mt-1 text-xs">
|
||||||
|
|||||||
@ -14,7 +14,7 @@ type TeamTemplatePageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TeamTemplatePage({ params }: TeamTemplatePageProps) {
|
export default async function TeamTemplatePage({ params }: TeamTemplatePageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export default async function TeamTemplatesPage({
|
|||||||
searchParams = {},
|
searchParams = {},
|
||||||
params,
|
params,
|
||||||
}: TeamTemplatesPageProps) {
|
}: TeamTemplatesPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { teamUrl } = params;
|
const { teamUrl } = params;
|
||||||
|
|
||||||
|
|||||||
@ -5,101 +5,156 @@ import { Trans } from '@lingui/macro';
|
|||||||
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
||||||
import { Button } from '@documenso/ui/primitives/button';
|
import { Button } from '@documenso/ui/primitives/button';
|
||||||
|
|
||||||
export default function SignatureDisclosure() {
|
const SUPPORT_EMAIL = 'support@documenso.com';
|
||||||
setupI18nSSR();
|
|
||||||
|
export default async function SignatureDisclosure() {
|
||||||
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<article className="prose dark:prose-invert">
|
<article className="prose dark:prose-invert">
|
||||||
<h1>Electronic Signature Disclosure</h1>
|
<h1>
|
||||||
|
<Trans>Electronic Signature Disclosure</Trans>
|
||||||
|
</h1>
|
||||||
|
|
||||||
<h2>Welcome</h2>
|
<h2>
|
||||||
|
<Trans>Welcome</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Thank you for using Documenso to perform your electronic document signing. The purpose of
|
<Trans>
|
||||||
this disclosure is to inform you about the process, legality, and your rights regarding
|
Thank you for using Documenso to perform your electronic document signing. The purpose
|
||||||
the use of electronic signatures on our platform. By opting to use an electronic
|
of this disclosure is to inform you about the process, legality, and your rights
|
||||||
signature, you are agreeing to the terms and conditions outlined below.
|
regarding the use of electronic signatures on our platform. By opting to use an
|
||||||
|
electronic signature, you are agreeing to the terms and conditions outlined below.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Acceptance and Consent</h2>
|
<h2>
|
||||||
|
<Trans>Acceptance and Consent</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
When you use our platform to affix your electronic signature to documents, you are
|
<Trans>
|
||||||
consenting to do so under the Electronic Signatures in Global and National Commerce Act
|
When you use our platform to affix your electronic signature to documents, you are
|
||||||
(E-Sign Act) and other applicable laws. This action indicates your agreement to use
|
consenting to do so under the Electronic Signatures in Global and National Commerce Act
|
||||||
electronic means to sign documents and receive notifications.
|
(E-Sign Act) and other applicable laws. This action indicates your agreement to use
|
||||||
|
electronic means to sign documents and receive notifications.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Legality of Electronic Signatures</h2>
|
<h2>
|
||||||
|
<Trans>Legality of Electronic Signatures</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
An electronic signature provided by you on our platform, achieved through clicking through
|
<Trans>
|
||||||
to a document and entering your name, or any other electronic signing method we provide,
|
An electronic signature provided by you on our platform, achieved through clicking
|
||||||
is legally binding. It carries the same weight and enforceability as a manual signature
|
through to a document and entering your name, or any other electronic signing method we
|
||||||
written with ink on paper.
|
provide, is legally binding. It carries the same weight and enforceability as a manual
|
||||||
|
signature written with ink on paper.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>System Requirements</h2>
|
<h2>
|
||||||
<p>To use our electronic signature service, you must have access to:</p>
|
<Trans>System Requirements</Trans>
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
<Trans>To use our electronic signature service, you must have access to:</Trans>
|
||||||
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>A stable internet connection</li>
|
<li>
|
||||||
<li>An email account</li>
|
<Trans>A stable internet connection</Trans>
|
||||||
<li>A device capable of accessing, opening, and reading documents</li>
|
</li>
|
||||||
<li>A means to print or download documents for your records</li>
|
<li>
|
||||||
|
<Trans>An email account</Trans>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Trans>A device capable of accessing, opening, and reading documents</Trans>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Trans>A means to print or download documents for your records</Trans>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Electronic Delivery of Documents</h2>
|
<h2>
|
||||||
|
<Trans>Electronic Delivery of Documents</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
All documents related to the electronic signing process will be provided to you
|
<Trans>
|
||||||
electronically through our platform or via email. It is your responsibility to ensure that
|
All documents related to the electronic signing process will be provided to you
|
||||||
your email address is current and that you can receive and open our emails.
|
electronically through our platform or via email. It is your responsibility to ensure
|
||||||
|
that your email address is current and that you can receive and open our emails.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Consent to Electronic Transactions</h2>
|
<h2>
|
||||||
|
<Trans>Consent to Electronic Transactions</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
By using the electronic signature feature, you are consenting to conduct transactions and
|
<Trans>
|
||||||
receive disclosures electronically. You acknowledge that your electronic signature on
|
By using the electronic signature feature, you are consenting to conduct transactions
|
||||||
documents is binding and that you accept the terms outlined in the documents you are
|
and receive disclosures electronically. You acknowledge that your electronic signature
|
||||||
signing.
|
on documents is binding and that you accept the terms outlined in the documents you are
|
||||||
|
signing.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Withdrawing Consent</h2>
|
<h2>
|
||||||
|
<Trans>Withdrawing Consent</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
You have the right to withdraw your consent to use electronic signatures at any time
|
<Trans>
|
||||||
before completing the signing process. To withdraw your consent, please contact the sender
|
You have the right to withdraw your consent to use electronic signatures at any time
|
||||||
of the document. In failing to contact the sender you may reach out to{' '}
|
before completing the signing process. To withdraw your consent, please contact the
|
||||||
<a href="mailto:support@documenso.com">support@documenso.com</a> for assistance. Be aware
|
sender of the document. In failing to contact the sender you may reach out to{' '}
|
||||||
that withdrawing consent may delay or halt the completion of the related transaction or
|
<a href={`mailto:${SUPPORT_EMAIL}`}>{SUPPORT_EMAIL}</a> for assistance. Be aware that
|
||||||
service.
|
withdrawing consent may delay or halt the completion of the related transaction or
|
||||||
|
service.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Updating Your Information</h2>
|
<h2>
|
||||||
|
<Trans>Updating Your Information</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
It is crucial to keep your contact information, especially your email address, up to date
|
<Trans>
|
||||||
with us. Please notify us immediately of any changes to ensure that you continue to
|
It is crucial to keep your contact information, especially your email address, up to
|
||||||
receive all necessary communications.
|
date with us. Please notify us immediately of any changes to ensure that you continue to
|
||||||
|
receive all necessary communications.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Retention of Documents</h2>
|
<h2>
|
||||||
|
<Trans>Retention of Documents</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
After signing a document electronically, you will be provided the opportunity to view,
|
<Trans>
|
||||||
download, and print the document for your records. It is highly recommended that you
|
After signing a document electronically, you will be provided the opportunity to view,
|
||||||
retain a copy of all electronically signed documents for your personal records. We will
|
download, and print the document for your records. It is highly recommended that you
|
||||||
also retain a copy of the signed document for our records however we may not be able to
|
retain a copy of all electronically signed documents for your personal records. We will
|
||||||
provide you with a copy of the signed document after a certain period of time.
|
also retain a copy of the signed document for our records however we may not be able to
|
||||||
|
provide you with a copy of the signed document after a certain period of time.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Acknowledgment</h2>
|
<h2>
|
||||||
|
<Trans>Acknowledgment</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
By proceeding to use the electronic signature service provided by Documenso, you affirm
|
<Trans>
|
||||||
that you have read and understood this disclosure. You agree to all terms and conditions
|
By proceeding to use the electronic signature service provided by Documenso, you affirm
|
||||||
related to the use of electronic signatures and electronic transactions as outlined
|
that you have read and understood this disclosure. You agree to all terms and conditions
|
||||||
herein.
|
related to the use of electronic signatures and electronic transactions as outlined
|
||||||
|
herein.
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Contact Information</h2>
|
<h2>
|
||||||
|
<Trans>Contact Information</Trans>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
For any questions regarding this disclosure, electronic signatures, or any related
|
<Trans>
|
||||||
process, please contact us at:{' '}
|
For any questions regarding this disclosure, electronic signatures, or any related
|
||||||
<a href="mailto:support@documenso.com">support@documenso.com</a>
|
process, please contact us at: <a href={`mailto:${SUPPORT_EMAIL}`}>{SUPPORT_EMAIL}</a>
|
||||||
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Forgot password',
|
title: 'Forgot password',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ForgotPasswordPage() {
|
export default async function ForgotPasswordPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-screen max-w-lg px-4">
|
<div className="w-screen max-w-lg px-4">
|
||||||
|
|||||||
@ -11,8 +11,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Forgot Password',
|
title: 'Forgot Password',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ForgotPasswordPage() {
|
export default async function ForgotPasswordPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-screen max-w-lg px-4">
|
<div className="w-screen max-w-lg px-4">
|
||||||
|
|||||||
@ -9,8 +9,8 @@ type UnauthenticatedLayoutProps = {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function UnauthenticatedLayout({ children }: UnauthenticatedLayoutProps) {
|
export default async function UnauthenticatedLayout({ children }: UnauthenticatedLayoutProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-4 py-12 md:p-12 lg:p-24">
|
<main className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-4 py-12 md:p-12 lg:p-24">
|
||||||
|
|||||||
@ -15,7 +15,7 @@ type ResetPasswordPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function ResetPasswordPage({ params: { token } }: ResetPasswordPageProps) {
|
export default async function ResetPasswordPage({ params: { token } }: ResetPasswordPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const isValid = await getResetTokenValidity({ token });
|
const isValid = await getResetTokenValidity({ token });
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Reset Password',
|
title: 'Reset Password',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ResetPasswordPage() {
|
export default async function ResetPasswordPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-screen max-w-lg px-4">
|
<div className="w-screen max-w-lg px-4">
|
||||||
|
|||||||
@ -17,8 +17,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Sign In',
|
title: 'Sign In',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SignInPage() {
|
export default async function SignInPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const NEXT_PUBLIC_DISABLE_SIGNUP = env('NEXT_PUBLIC_DISABLE_SIGNUP');
|
const NEXT_PUBLIC_DISABLE_SIGNUP = env('NEXT_PUBLIC_DISABLE_SIGNUP');
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Sign Up',
|
title: 'Sign Up',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SignUpPage() {
|
export default async function SignUpPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const NEXT_PUBLIC_DISABLE_SIGNUP = env('NEXT_PUBLIC_DISABLE_SIGNUP');
|
const NEXT_PUBLIC_DISABLE_SIGNUP = env('NEXT_PUBLIC_DISABLE_SIGNUP');
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ type DeclineInvitationPageProps = {
|
|||||||
export default async function DeclineInvitationPage({
|
export default async function DeclineInvitationPage({
|
||||||
params: { token },
|
params: { token },
|
||||||
}: DeclineInvitationPageProps) {
|
}: DeclineInvitationPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const session = await getServerComponentSession();
|
const session = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ type AcceptInvitationPageProps = {
|
|||||||
export default async function AcceptInvitationPage({
|
export default async function AcceptInvitationPage({
|
||||||
params: { token },
|
params: { token },
|
||||||
}: AcceptInvitationPageProps) {
|
}: AcceptInvitationPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const session = await getServerComponentSession();
|
const session = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ type VerifyTeamEmailPageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function VerifyTeamEmailPage({ params: { token } }: VerifyTeamEmailPageProps) {
|
export default async function VerifyTeamEmailPage({ params: { token } }: VerifyTeamEmailPageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const teamEmailVerification = await prisma.teamEmailVerification.findUnique({
|
const teamEmailVerification = await prisma.teamEmailVerification.findUnique({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ type VerifyTeamTransferPage = {
|
|||||||
export default async function VerifyTeamTransferPage({
|
export default async function VerifyTeamTransferPage({
|
||||||
params: { token },
|
params: { token },
|
||||||
}: VerifyTeamTransferPage) {
|
}: VerifyTeamTransferPage) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const teamTransferVerification = await prisma.teamTransferVerification.findUnique({
|
const teamTransferVerification = await prisma.teamTransferVerification.findUnique({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
|||||||
|
|
||||||
import { SendConfirmationEmailForm } from '~/components/forms/send-confirmation-email';
|
import { SendConfirmationEmailForm } from '~/components/forms/send-confirmation-email';
|
||||||
|
|
||||||
export default function UnverifiedAccount() {
|
export default async function UnverifiedAccount() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-screen max-w-lg px-4">
|
<div className="w-screen max-w-lg px-4">
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export type PageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function VerifyEmailPage({ params: { token } }: PageProps) {
|
export default async function VerifyEmailPage({ params: { token } }: PageProps) {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -11,8 +11,8 @@ export const metadata: Metadata = {
|
|||||||
title: 'Verify Email',
|
title: 'Verify Email',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function EmailVerificationWithoutTokenPage() {
|
export default async function EmailVerificationWithoutTokenPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-screen max-w-lg px-4">
|
<div className="w-screen max-w-lg px-4">
|
||||||
|
|||||||
@ -318,6 +318,7 @@ export const EmbedDirectTemplateClientPage = ({
|
|||||||
|
|
||||||
{/* Widget */}
|
{/* Widget */}
|
||||||
<div
|
<div
|
||||||
|
key={isExpanded ? 'expanded' : 'collapsed'}
|
||||||
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
|
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
|
||||||
data-expanded={isExpanded || undefined}
|
data-expanded={isExpanded || undefined}
|
||||||
>
|
>
|
||||||
@ -367,7 +368,7 @@ export const EmbedDirectTemplateClientPage = ({
|
|||||||
className="bg-background mt-2"
|
className="bg-background mt-2"
|
||||||
disabled={isNameLocked}
|
disabled={isNameLocked}
|
||||||
value={fullName}
|
value={fullName}
|
||||||
onChange={(e) => !isNameLocked && setFullName(e.target.value.trim())}
|
onChange={(e) => !isNameLocked && setFullName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -394,13 +395,17 @@ export const EmbedDirectTemplateClientPage = ({
|
|||||||
<Card className="mt-2" gradient degrees={-120}>
|
<Card className="mt-2" gradient degrees={-120}>
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<SignaturePad
|
<SignaturePad
|
||||||
key={signature}
|
|
||||||
className="h-44 w-full"
|
className="h-44 w-full"
|
||||||
disabled={isThrottled || isSubmitting}
|
disabled={isThrottled || isSubmitting}
|
||||||
defaultValue={signature ?? undefined}
|
defaultValue={signature ?? undefined}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setSignature(value);
|
setSignature(value);
|
||||||
}}
|
}}
|
||||||
|
allowTypedSignature={Boolean(
|
||||||
|
metadata &&
|
||||||
|
'typedSignatureEnabled' in metadata &&
|
||||||
|
metadata.typedSignatureEnabled,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -198,6 +198,7 @@ export const EmbedSignDocumentClientPage = ({
|
|||||||
|
|
||||||
{/* Widget */}
|
{/* Widget */}
|
||||||
<div
|
<div
|
||||||
|
key={isExpanded ? 'expanded' : 'collapsed'}
|
||||||
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
|
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
|
||||||
data-expanded={isExpanded || undefined}
|
data-expanded={isExpanded || undefined}
|
||||||
>
|
>
|
||||||
@ -247,7 +248,7 @@ export const EmbedSignDocumentClientPage = ({
|
|||||||
className="bg-background mt-2"
|
className="bg-background mt-2"
|
||||||
disabled={isNameLocked}
|
disabled={isNameLocked}
|
||||||
value={fullName}
|
value={fullName}
|
||||||
onChange={(e) => !isNameLocked && setFullName(e.target.value.trim())}
|
onChange={(e) => !isNameLocked && setFullName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -273,13 +274,17 @@ export const EmbedSignDocumentClientPage = ({
|
|||||||
<Card className="mt-2" gradient degrees={-120}>
|
<Card className="mt-2" gradient degrees={-120}>
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<SignaturePad
|
<SignaturePad
|
||||||
key={signature}
|
|
||||||
className="h-44 w-full"
|
className="h-44 w-full"
|
||||||
disabled={isThrottled || isSubmitting}
|
disabled={isThrottled || isSubmitting}
|
||||||
defaultValue={signature ?? undefined}
|
defaultValue={signature ?? undefined}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setSignature(value);
|
setSignature(value);
|
||||||
}}
|
}}
|
||||||
|
allowTypedSignature={Boolean(
|
||||||
|
metadata &&
|
||||||
|
'typedSignatureEnabled' in metadata &&
|
||||||
|
metadata.typedSignatureEnabled,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export function generateMetadata() {
|
|||||||
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
const flags = await getServerComponentAllFlags();
|
const flags = await getServerComponentAllFlags();
|
||||||
|
|
||||||
const { i18n, lang, locales } = setupI18nSSR();
|
const { i18n, lang, locales } = await setupI18nSSR();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html
|
<html
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { Button } from '@documenso/ui/primitives/button';
|
|||||||
import NotFoundPartial from '~/components/partials/not-found';
|
import NotFoundPartial from '~/components/partials/not-found';
|
||||||
|
|
||||||
export default async function NotFound() {
|
export default async function NotFound() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
const { session } = await getServerComponentSession();
|
const { session } = await getServerComponentSession();
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default async function DashboardPage() {
|
||||||
setupI18nSSR();
|
await setupI18nSSR();
|
||||||
|
|
||||||
return <div>Documenso</div>;
|
return <div>Documenso</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,18 @@ import { useCallback, useEffect, useState } from 'react';
|
|||||||
|
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
|
|
||||||
|
import { msg } from '@lingui/macro';
|
||||||
|
import { useLingui } from '@lingui/react';
|
||||||
|
|
||||||
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
|
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
|
||||||
import { Input } from '@documenso/ui/primitives/input';
|
import { Input } from '@documenso/ui/primitives/input';
|
||||||
|
|
||||||
export const DocumentSearch = ({ initialValue = '' }: { initialValue?: string }) => {
|
export const DocumentSearch = ({ initialValue = '' }: { initialValue?: string }) => {
|
||||||
|
const { _ } = useLingui();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
const [searchTerm, setSearchTerm] = useState(initialValue);
|
const [searchTerm, setSearchTerm] = useState(initialValue);
|
||||||
const debouncedSearchTerm = useDebouncedValue(searchTerm, 500);
|
const debouncedSearchTerm = useDebouncedValue(searchTerm, 500);
|
||||||
|
|
||||||
@ -33,7 +39,7 @@ export const DocumentSearch = ({ initialValue = '' }: { initialValue?: string })
|
|||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="Search documents..."
|
placeholder={_(msg`Search documents...`)}
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
|
import { msg } from '@lingui/macro';
|
||||||
|
|
||||||
export const EXPIRATION_DATES = {
|
export const EXPIRATION_DATES = {
|
||||||
ONE_WEEK: '7 days',
|
ONE_WEEK: msg`7 days`,
|
||||||
ONE_MONTH: '1 month',
|
ONE_MONTH: msg`1 month`,
|
||||||
THREE_MONTHS: '3 months',
|
THREE_MONTHS: msg`3 months`,
|
||||||
SIX_MONTHS: '6 months',
|
SIX_MONTHS: msg`6 months`,
|
||||||
ONE_YEAR: '12 months',
|
ONE_YEAR: msg`12 months`,
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export default function DeleteTokenDialog({
|
|||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const deleteMessage = `delete ${token.name}`;
|
const deleteMessage = _(msg`delete ${token.name}`);
|
||||||
|
|
||||||
const ZDeleteTokenDialogSchema = z.object({
|
const ZDeleteTokenDialogSchema = z.object({
|
||||||
tokenName: z.literal(deleteMessage, {
|
tokenName: z.literal(deleteMessage, {
|
||||||
|
|||||||
@ -51,7 +51,7 @@ export const DeleteWebhookDialog = ({ webhook, children }: DeleteWebhookDialogPr
|
|||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const deleteMessage = `delete ${webhook.webhookUrl}`;
|
const deleteMessage = _(msg`delete ${webhook.webhookUrl}`);
|
||||||
|
|
||||||
const ZDeleteWebhookFormSchema = z.object({
|
const ZDeleteWebhookFormSchema = z.object({
|
||||||
webhookUrl: z.literal(deleteMessage, {
|
webhookUrl: z.literal(deleteMessage, {
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export const DeleteTeamDialog = ({ trigger, teamId, teamName }: DeleteTeamDialog
|
|||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const deleteMessage = `delete ${teamName}`;
|
const deleteMessage = _(msg`delete ${teamName}`);
|
||||||
|
|
||||||
const ZDeleteTeamFormSchema = z.object({
|
const ZDeleteTeamFormSchema = z.object({
|
||||||
teamName: z.literal(deleteMessage, {
|
teamName: z.literal(deleteMessage, {
|
||||||
|
|||||||
@ -73,7 +73,7 @@ export const TransferTeamDialog = ({
|
|||||||
teamId,
|
teamId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const confirmTransferMessage = `transfer ${teamName}`;
|
const confirmTransferMessage = _(msg`transfer ${teamName}`);
|
||||||
|
|
||||||
const ZTransferTeamFormSchema = z.object({
|
const ZTransferTeamFormSchema = z.object({
|
||||||
teamName: z.literal(confirmTransferMessage, {
|
teamName: z.literal(confirmTransferMessage, {
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export const CurrentUserTeamsDataTable = () => {
|
|||||||
accessorKey: 'role',
|
accessorKey: 'role',
|
||||||
cell: ({ row }) =>
|
cell: ({ row }) =>
|
||||||
row.original.ownerUserId === row.original.currentTeamMember.userId
|
row.original.ownerUserId === row.original.currentTeamMember.userId
|
||||||
? 'Owner'
|
? _(msg`Owner`)
|
||||||
: _(TEAM_MEMBER_ROLE_MAP[row.original.currentTeamMember.role]),
|
: _(TEAM_MEMBER_ROLE_MAP[row.original.currentTeamMember.role]),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -106,7 +106,7 @@ export const TeamMembersDataTable = ({
|
|||||||
accessorKey: 'role',
|
accessorKey: 'role',
|
||||||
cell: ({ row }) =>
|
cell: ({ row }) =>
|
||||||
teamOwnerUserId === row.original.userId
|
teamOwnerUserId === row.original.userId
|
||||||
? 'Owner'
|
? _(msg`Owner`)
|
||||||
: _(TEAM_MEMBER_ROLE_MAP[row.original.role]),
|
: _(TEAM_MEMBER_ROLE_MAP[row.original.role]),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { useLingui } from '@lingui/react';
|
||||||
import { EyeOffIcon } from 'lucide-react';
|
import { EyeOffIcon } from 'lucide-react';
|
||||||
import { P, match } from 'ts-pattern';
|
import { P, match } from 'ts-pattern';
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ import {
|
|||||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||||
import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones';
|
import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones';
|
||||||
import type { DocumentField } from '@documenso/lib/server-only/field/get-fields-for-document';
|
import type { DocumentField } from '@documenso/lib/server-only/field/get-fields-for-document';
|
||||||
|
import { parseMessageDescriptor } from '@documenso/lib/utils/i18n';
|
||||||
import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
|
import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
|
||||||
import type { DocumentMeta } from '@documenso/prisma/client';
|
import type { DocumentMeta } from '@documenso/prisma/client';
|
||||||
import { FieldType, SigningStatus } from '@documenso/prisma/client';
|
import { FieldType, SigningStatus } from '@documenso/prisma/client';
|
||||||
@ -28,6 +30,8 @@ export type DocumentReadOnlyFieldsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnlyFieldsProps) => {
|
export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnlyFieldsProps) => {
|
||||||
|
const { _ } = useLingui();
|
||||||
|
|
||||||
const [hiddenFieldIds, setHiddenFieldIds] = useState<Record<string, boolean>>({});
|
const [hiddenFieldIds, setHiddenFieldIds] = useState<Record<string, boolean>>({});
|
||||||
|
|
||||||
const handleHideField = (fieldId: string) => {
|
const handleHideField = (fieldId: string) => {
|
||||||
@ -59,7 +63,7 @@ export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnl
|
|||||||
>
|
>
|
||||||
<p className="font-semibold">
|
<p className="font-semibold">
|
||||||
{field.Recipient.signingStatus === SigningStatus.SIGNED ? 'Signed' : 'Pending'}{' '}
|
{field.Recipient.signingStatus === SigningStatus.SIGNED ? 'Signed' : 'Pending'}{' '}
|
||||||
{FRIENDLY_FIELD_TYPE[field.type].toLowerCase()} field
|
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type]).toLowerCase()} field
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-muted-foreground text-xs">
|
<p className="text-muted-foreground text-xs">
|
||||||
@ -127,7 +131,7 @@ export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnl
|
|||||||
field.type === FieldType.FREE_SIGNATURE,
|
field.type === FieldType.FREE_SIGNATURE,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{FRIENDLY_FIELD_TYPE[field.type]}
|
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type])}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -202,7 +202,7 @@ export const ApiTokenForm = ({ className, teamId, tokens }: ApiTokenFormProps) =
|
|||||||
<SelectContent>
|
<SelectContent>
|
||||||
{Object.entries(EXPIRATION_DATES).map(([key, date]) => (
|
{Object.entries(EXPIRATION_DATES).map(([key, date]) => (
|
||||||
<SelectItem key={key} value={key}>
|
<SelectItem key={key} value={key}>
|
||||||
{date}
|
{_(date)}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import type { HTMLAttributes } from 'react';
|
|||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
import { Trans } from '@lingui/macro';
|
||||||
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
|
|
||||||
export type SigningDisclosureProps = HTMLAttributes<HTMLParagraphElement>;
|
export type SigningDisclosureProps = HTMLAttributes<HTMLParagraphElement>;
|
||||||
@ -9,20 +11,24 @@ export type SigningDisclosureProps = HTMLAttributes<HTMLParagraphElement>;
|
|||||||
export const SigningDisclosure = ({ className, ...props }: SigningDisclosureProps) => {
|
export const SigningDisclosure = ({ className, ...props }: SigningDisclosureProps) => {
|
||||||
return (
|
return (
|
||||||
<p className={cn('text-muted-foreground text-xs', className)} {...props}>
|
<p className={cn('text-muted-foreground text-xs', className)} {...props}>
|
||||||
By proceeding with your electronic signature, you acknowledge and consent that it will be used
|
<Trans>
|
||||||
to sign the given document and holds the same legal validity as a handwritten signature. By
|
By proceeding with your electronic signature, you acknowledge and consent that it will be
|
||||||
completing the electronic signing process, you affirm your understanding and acceptance of
|
used to sign the given document and holds the same legal validity as a handwritten
|
||||||
these conditions.
|
signature. By completing the electronic signing process, you affirm your understanding and
|
||||||
|
acceptance of these conditions.
|
||||||
|
</Trans>
|
||||||
<span className="mt-2 block">
|
<span className="mt-2 block">
|
||||||
Read the full{' '}
|
<Trans>
|
||||||
<Link
|
Read the full{' '}
|
||||||
className="text-documenso-700 underline"
|
<Link
|
||||||
href="/articles/signature-disclosure"
|
className="text-documenso-700 underline"
|
||||||
target="_blank"
|
href="/articles/signature-disclosure"
|
||||||
>
|
target="_blank"
|
||||||
signature disclosure
|
>
|
||||||
</Link>
|
signature disclosure
|
||||||
.
|
</Link>
|
||||||
|
.
|
||||||
|
</Trans>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const config: LinguiConfig = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '<rootDir>/packages/lib/translations/{locale}/common',
|
path: '<rootDir>/packages/lib/translations/{locale}/common',
|
||||||
include: ['packages/ui', 'packages/lib'],
|
include: ['packages/ui', 'packages/lib', 'packages/email'],
|
||||||
exclude: ['**/node_modules/**'],
|
exclude: ['**/node_modules/**'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
11
package-lock.json
generated
11
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@documenso/root",
|
"name": "@documenso/root",
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@documenso/root",
|
"name": "@documenso/root",
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
"packages/*"
|
"packages/*"
|
||||||
@ -80,7 +80,7 @@
|
|||||||
},
|
},
|
||||||
"apps/marketing": {
|
"apps/marketing": {
|
||||||
"name": "@documenso/marketing",
|
"name": "@documenso/marketing",
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@documenso/assets": "*",
|
"@documenso/assets": "*",
|
||||||
@ -441,7 +441,7 @@
|
|||||||
},
|
},
|
||||||
"apps/web": {
|
"apps/web": {
|
||||||
"name": "@documenso/web",
|
"name": "@documenso/web",
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@documenso/api": "*",
|
"@documenso/api": "*",
|
||||||
@ -36774,6 +36774,9 @@
|
|||||||
"@documenso/email": "*",
|
"@documenso/email": "*",
|
||||||
"@documenso/prisma": "*",
|
"@documenso/prisma": "*",
|
||||||
"@documenso/signing": "*",
|
"@documenso/signing": "*",
|
||||||
|
"@lingui/core": "^4.11.3",
|
||||||
|
"@lingui/macro": "^4.11.3",
|
||||||
|
"@lingui/react": "^4.11.3",
|
||||||
"@next-auth/prisma-adapter": "1.0.7",
|
"@next-auth/prisma-adapter": "1.0.7",
|
||||||
"@noble/ciphers": "0.4.0",
|
"@noble/ciphers": "0.4.0",
|
||||||
"@noble/hashes": "1.3.2",
|
"@noble/hashes": "1.3.2",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.7.2-rc.1",
|
"version": "1.7.2-rc.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "turbo run build",
|
"build": "turbo run build",
|
||||||
"build:web": "turbo run build --filter=@documenso/web",
|
"build:web": "turbo run build --filter=@documenso/web",
|
||||||
|
|||||||
@ -301,6 +301,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
|
|||||||
dateFormat: dateFormat?.value,
|
dateFormat: dateFormat?.value,
|
||||||
redirectUrl: body.meta.redirectUrl,
|
redirectUrl: body.meta.redirectUrl,
|
||||||
signingOrder: body.meta.signingOrder,
|
signingOrder: body.meta.signingOrder,
|
||||||
|
language: body.meta.language,
|
||||||
requestMetadata: extractNextApiRequestMetadata(args.req),
|
requestMetadata: extractNextApiRequestMetadata(args.req),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
|
import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
|
||||||
|
import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n';
|
||||||
import '@documenso/lib/constants/time-zones';
|
import '@documenso/lib/constants/time-zones';
|
||||||
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
|
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
|
||||||
import { ZUrlSchema } from '@documenso/lib/schemas/common';
|
import { ZUrlSchema } from '@documenso/lib/schemas/common';
|
||||||
@ -127,6 +128,7 @@ export const ZCreateDocumentMutationSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
redirectUrl: z.string(),
|
redirectUrl: z.string(),
|
||||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||||
|
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(),
|
||||||
})
|
})
|
||||||
.partial(),
|
.partial(),
|
||||||
authOptions: z
|
authOptions: z
|
||||||
@ -181,6 +183,7 @@ export const ZCreateDocumentFromTemplateMutationSchema = z.object({
|
|||||||
dateFormat: z.string(),
|
dateFormat: z.string(),
|
||||||
redirectUrl: z.string(),
|
redirectUrl: z.string(),
|
||||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||||
|
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(),
|
||||||
})
|
})
|
||||||
.partial()
|
.partial()
|
||||||
.optional(),
|
.optional(),
|
||||||
@ -247,6 +250,7 @@ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
|
|||||||
dateFormat: z.string(),
|
dateFormat: z.string(),
|
||||||
redirectUrl: ZUrlSchema,
|
redirectUrl: ZUrlSchema,
|
||||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||||
|
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(),
|
||||||
})
|
})
|
||||||
.partial()
|
.partial()
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user