mirror of
https://github.com/documenso/documenso.git
synced 2026-08-25 15:52:29 +10:00
fix: lint project (#2693)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { redirect } from 'react-router';
|
||||
|
||||
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
|
||||
import { redirect } from 'react-router';
|
||||
|
||||
import type { Route } from './+types/_index';
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { SubscriptionStatus } from '@prisma/client';
|
||||
import { Link, Outlet } from 'react-router';
|
||||
|
||||
import {
|
||||
DEFAULT_MINIMUM_ENVELOPE_ITEM_COUNT,
|
||||
PAID_PLAN_LIMITS,
|
||||
} from '@documenso/ee/server-only/limits/constants';
|
||||
import { DEFAULT_MINIMUM_ENVELOPE_ITEM_COUNT, PAID_PLAN_LIMITS } from '@documenso/ee/server-only/limits/constants';
|
||||
import { LimitsProvider } from '@documenso/ee/server-only/limits/provider/client';
|
||||
import { useOptionalCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
|
||||
import { TrpcProvider } from '@documenso/trpc/react';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { SubscriptionStatus } from '@prisma/client';
|
||||
import { useMemo } from 'react';
|
||||
import { Link, Outlet } from 'react-router';
|
||||
|
||||
import { GenericErrorLayout } from '~/components/general/generic-error-layout';
|
||||
import { useOptionalCurrentTeam } from '~/providers/team';
|
||||
@@ -26,10 +21,7 @@ export default function Layout() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
organisation?.subscription &&
|
||||
organisation.subscription.status === SubscriptionStatus.INACTIVE
|
||||
) {
|
||||
if (organisation?.subscription && organisation.subscription.status === SubscriptionStatus.INACTIVE) {
|
||||
return {
|
||||
quota: {
|
||||
documents: 0,
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Plural, Trans, useLingui } from '@lingui/react/macro';
|
||||
import { DocumentStatus } from '@prisma/client';
|
||||
import { ChevronLeft, Users2 } from 'lucide-react';
|
||||
import { Link } from 'react-router';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { EnvelopeRenderProvider } from '@documenso/lib/client-only/providers/envelope-render-provider';
|
||||
import { useSession } from '@documenso/lib/client-only/providers/session';
|
||||
import { PDF_VIEWER_ERROR_MESSAGES } from '@documenso/lib/constants/pdf-viewer-i18n';
|
||||
@@ -22,6 +15,12 @@ import { Badge } from '@documenso/ui/primitives/badge';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||
import { Spinner } from '@documenso/ui/primitives/spinner';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Plural, Trans, useLingui } from '@lingui/react/macro';
|
||||
import { DocumentStatus } from '@prisma/client';
|
||||
import { ChevronLeft, Users2 } from 'lucide-react';
|
||||
import { Link } from 'react-router';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { DocumentPageViewButton } from '~/components/general/document/document-page-view-button';
|
||||
import { DocumentPageViewDropdown } from '~/components/general/document/document-page-view-dropdown';
|
||||
@@ -68,8 +67,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
},
|
||||
{
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
enabled:
|
||||
envelope && envelope.internalVersion === 2 && envelope.status === DocumentStatus.PENDING,
|
||||
enabled: envelope && envelope.internalVersion === 2 && envelope.status === DocumentStatus.PENDING,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -121,16 +119,12 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
|
||||
<div className="flex flex-row justify-between gap-4">
|
||||
<div className="min-w-0">
|
||||
<h1 className="mt-4 block text-2xl font-semibold md:text-3xl" title={envelope.title}>
|
||||
<h1 className="mt-4 block font-semibold text-2xl md:text-3xl" title={envelope.title}>
|
||||
{envelope.title}
|
||||
</h1>
|
||||
|
||||
<div className="mt-2.5 flex items-center gap-x-6">
|
||||
<DocumentStatusComponent
|
||||
inheritColor
|
||||
status={envelope.status}
|
||||
className="text-muted-foreground"
|
||||
/>
|
||||
<DocumentStatusComponent inheritColor status={envelope.status} className="text-muted-foreground" />
|
||||
|
||||
{envelope.recipients.length > 0 && (
|
||||
<div className="flex items-center text-muted-foreground">
|
||||
@@ -142,11 +136,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
position="bottom"
|
||||
>
|
||||
<span>
|
||||
<Plural
|
||||
value={envelope.recipients.length}
|
||||
one="# Recipient"
|
||||
other="# Recipients"
|
||||
/>
|
||||
<Plural value={envelope.recipients.length} one="# Recipient" other="# Recipients" />
|
||||
</span>
|
||||
</StackAvatarsWithTooltip>
|
||||
</div>
|
||||
@@ -177,9 +167,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
showRecipientTooltip: true,
|
||||
}}
|
||||
>
|
||||
{isMultiEnvelopeItem && (
|
||||
<EnvelopeRendererFileSelector fields={envelope.fields} className="mb-4 p-0" />
|
||||
)}
|
||||
{isMultiEnvelopeItem && <EnvelopeRendererFileSelector fields={envelope.fields} className="mb-4 p-0" />}
|
||||
|
||||
<Card className="rounded-xl before:rounded-xl" gradient>
|
||||
<CardContent className="p-2">
|
||||
@@ -193,10 +181,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
</EnvelopeRenderProvider>
|
||||
</div>
|
||||
) : (
|
||||
<Card
|
||||
className="relative col-span-12 rounded-xl before:rounded-xl lg:col-span-6 xl:col-span-7"
|
||||
gradient
|
||||
>
|
||||
<Card className="relative col-span-12 rounded-xl before:rounded-xl lg:col-span-6 xl:col-span-7" gradient>
|
||||
<CardContent className="p-2">
|
||||
{envelope.status !== DocumentStatus.COMPLETED && (
|
||||
<DocumentReadOnlyFields
|
||||
@@ -224,27 +209,21 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={cn('col-span-12 lg:col-span-6 xl:col-span-5', isMultiEnvelopeItem && 'mt-20')}
|
||||
>
|
||||
<div className={cn('col-span-12 lg:col-span-6 xl:col-span-5', isMultiEnvelopeItem && 'mt-20')}>
|
||||
<div className="space-y-6">
|
||||
<section className="flex flex-col rounded-xl border border-border bg-widget pb-4 pt-6">
|
||||
<section className="flex flex-col rounded-xl border border-border bg-widget pt-6 pb-4">
|
||||
<div className="flex flex-row items-center justify-between px-4">
|
||||
<h3 className="text-2xl font-semibold text-foreground">
|
||||
<h3 className="font-semibold text-2xl text-foreground">
|
||||
{t(FRIENDLY_STATUS_MAP[envelope.status].labelExtended)}
|
||||
</h3>
|
||||
|
||||
<DocumentPageViewDropdown envelope={envelope} />
|
||||
</div>
|
||||
|
||||
<p className="mt-2 px-4 text-sm text-muted-foreground">
|
||||
<p className="mt-2 px-4 text-muted-foreground text-sm">
|
||||
{match(envelope.status)
|
||||
.with(DocumentStatus.COMPLETED, () => (
|
||||
<Trans>This document has been signed by all recipients</Trans>
|
||||
))
|
||||
.with(DocumentStatus.REJECTED, () => (
|
||||
<Trans>This document has been rejected by a recipient</Trans>
|
||||
))
|
||||
.with(DocumentStatus.COMPLETED, () => <Trans>This document has been signed by all recipients</Trans>)
|
||||
.with(DocumentStatus.REJECTED, () => <Trans>This document has been rejected by a recipient</Trans>)
|
||||
.with(DocumentStatus.DRAFT, () => (
|
||||
<Trans>This document is currently a draft and has not been sent</Trans>
|
||||
))
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { ChevronLeftIcon } from 'lucide-react';
|
||||
import { Link, Outlet, isRouteErrorResponse, redirect } from 'react-router';
|
||||
import type { ShouldRevalidateFunctionArgs } from 'react-router';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { ChevronLeftIcon } from 'lucide-react';
|
||||
import type { ShouldRevalidateFunctionArgs } from 'react-router';
|
||||
import { isRouteErrorResponse, Link, Outlet, redirect } from 'react-router';
|
||||
|
||||
import { GenericErrorLayout } from '~/components/general/generic-error-layout';
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { Link, useNavigate } from 'react-router';
|
||||
|
||||
import { EnvelopeEditorProvider } from '@documenso/lib/client-only/providers/envelope-editor-provider';
|
||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||
import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/teams';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Spinner } from '@documenso/ui/primitives/spinner';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { useEffect } from 'react';
|
||||
import { Link, useNavigate } from 'react-router';
|
||||
|
||||
import { EnvelopeEditor } from '~/components/general/envelope-editor/envelope-editor';
|
||||
import { EnvelopeEditorRenderProviderWrapper } from '~/components/general/envelope-editor/envelope-editor-renderer-provider-wrapper';
|
||||
@@ -48,9 +46,7 @@ export default function EnvelopeEditorPage({ params }: Route.ComponentProps) {
|
||||
}
|
||||
|
||||
const pathPrefix =
|
||||
envelope.type === EnvelopeType.DOCUMENT
|
||||
? formatDocumentsPath(team.url)
|
||||
: formatTemplatesPath(team.url);
|
||||
envelope.type === EnvelopeType.DOCUMENT ? formatDocumentsPath(team.url) : formatTemplatesPath(team.url);
|
||||
|
||||
if (envelope.teamId !== team.id) {
|
||||
void navigate(pathPrefix, { replace: true });
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Plural, Trans } from '@lingui/react/macro';
|
||||
import { ChevronLeft, Users2 } from 'lucide-react';
|
||||
import { Link, redirect } from 'react-router';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { getDocumentWithDetailsById } from '@documenso/lib/server-only/document/get-document-with-details-by-id';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { isDocumentCompleted } from '@documenso/lib/utils/document';
|
||||
import { logDocumentAccess } from '@documenso/lib/utils/logger';
|
||||
import { canAccessTeamDocument, formatDocumentsPath } from '@documenso/lib/utils/teams';
|
||||
import { Plural, Trans } from '@lingui/react/macro';
|
||||
import { ChevronLeft, Users2 } from 'lucide-react';
|
||||
import { Link, redirect } from 'react-router';
|
||||
|
||||
import { DocumentAttachmentsPopover } from '~/components/general/document/document-attachments-popover';
|
||||
import { DocumentEditForm } from '~/components/general/document/document-edit-form';
|
||||
@@ -92,28 +91,20 @@ export default function DocumentEditPage() {
|
||||
<div className="mt-4 flex w-full items-end justify-between">
|
||||
<div className="flex-1">
|
||||
<h1
|
||||
className="block max-w-[20rem] truncate text-2xl font-semibold md:max-w-[30rem] md:text-3xl"
|
||||
className="block max-w-[20rem] truncate font-semibold text-2xl md:max-w-[30rem] md:text-3xl"
|
||||
title={document.title}
|
||||
>
|
||||
{document.title}
|
||||
</h1>
|
||||
|
||||
<div className="mt-2.5 flex items-center gap-x-6">
|
||||
<DocumentStatus
|
||||
inheritColor
|
||||
status={document.status}
|
||||
className="text-muted-foreground"
|
||||
/>
|
||||
<DocumentStatus inheritColor status={document.status} className="text-muted-foreground" />
|
||||
|
||||
{recipients.length > 0 && (
|
||||
<div className="flex items-center text-muted-foreground">
|
||||
<Users2 className="mr-2 h-5 w-5" />
|
||||
|
||||
<StackAvatarsWithTooltip
|
||||
recipients={recipients}
|
||||
documentStatus={document.status}
|
||||
position="bottom"
|
||||
>
|
||||
<StackAvatarsWithTooltip recipients={recipients} documentStatus={document.status} position="bottom">
|
||||
<span>
|
||||
<Plural one="1 Recipient" other="# Recipients" value={recipients.length} />
|
||||
</span>
|
||||
@@ -126,17 +117,11 @@ export default function DocumentEditPage() {
|
||||
<div className="flex items-center gap-x-4">
|
||||
<DocumentAttachmentsPopover envelopeId={document.envelopeId} />
|
||||
|
||||
{document.useLegacyFieldInsertion && (
|
||||
<LegacyFieldWarningPopover type="document" documentId={document.id} />
|
||||
)}
|
||||
{document.useLegacyFieldInsertion && <LegacyFieldWarningPopover type="document" documentId={document.id} />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DocumentEditForm
|
||||
className="mt-6"
|
||||
initialDocument={document}
|
||||
documentRootPath={documentRootPath}
|
||||
/>
|
||||
<DocumentEditForm className="mt-6" initialDocument={document} documentRootPath={documentRootPath} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
import { logDocumentAccess } from '@documenso/lib/utils/logger';
|
||||
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
|
||||
import { Card } from '@documenso/ui/primitives/card';
|
||||
import type { MessageDescriptor } from '@lingui/core';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
@@ -7,14 +14,6 @@ import { ChevronLeft } from 'lucide-react';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
import { logDocumentAccess } from '@documenso/lib/utils/logger';
|
||||
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
|
||||
import { Card } from '@documenso/ui/primitives/card';
|
||||
|
||||
import { DocumentAuditLogDownloadButton } from '~/components/general/document/document-audit-log-download-button';
|
||||
import { DocumentCertificateDownloadButton } from '~/components/general/document/document-certificate-download-button';
|
||||
import {
|
||||
@@ -99,9 +98,7 @@ export default function DocumentsLogsPage({ loaderData }: Route.ComponentProps)
|
||||
},
|
||||
{
|
||||
description: msg`Created by`,
|
||||
value: document.user.name
|
||||
? `${document.user.name} (${document.user.email})`
|
||||
: document.user.email,
|
||||
value: document.user.name ? `${document.user.name} (${document.user.email})` : document.user.email,
|
||||
},
|
||||
{
|
||||
description: msg`Date created`,
|
||||
@@ -143,7 +140,7 @@ export default function DocumentsLogsPage({ loaderData }: Route.ComponentProps)
|
||||
<div className="flex flex-col">
|
||||
<div>
|
||||
<h1
|
||||
className="mt-4 block max-w-[20rem] truncate text-2xl font-semibold md:max-w-[30rem] md:text-3xl"
|
||||
className="mt-4 block max-w-[20rem] truncate font-semibold text-2xl md:max-w-[30rem] md:text-3xl"
|
||||
title={document.title}
|
||||
>
|
||||
{document.title}
|
||||
@@ -151,11 +148,7 @@ export default function DocumentsLogsPage({ loaderData }: Route.ComponentProps)
|
||||
</div>
|
||||
<div className="mt-1 flex flex-col justify-between sm:flex-row">
|
||||
<div className="mt-2.5 flex items-center gap-x-6">
|
||||
<DocumentStatusComponent
|
||||
inheritColor
|
||||
status={document.status}
|
||||
className="text-muted-foreground"
|
||||
/>
|
||||
<DocumentStatusComponent inheritColor status={document.status} className="text-muted-foreground" />
|
||||
</div>
|
||||
<div className="mt-4 flex w-full flex-row sm:mt-0 sm:w-auto sm:self-end">
|
||||
<DocumentCertificateDownloadButton
|
||||
@@ -172,13 +165,13 @@ export default function DocumentsLogsPage({ loaderData }: Route.ComponentProps)
|
||||
<section className="mt-6">
|
||||
<Card className="grid grid-cols-1 gap-4 p-4 sm:grid-cols-2" degrees={45} gradient>
|
||||
{documentInformation.map((info, i) => (
|
||||
<div className="text-sm text-foreground" key={i}>
|
||||
<div className="text-foreground text-sm" key={i}>
|
||||
<h3 className="font-semibold">{_(info.description)}</h3>
|
||||
<p className="truncate text-muted-foreground">{info.value}</p>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="text-sm text-foreground">
|
||||
<div className="text-foreground text-sm">
|
||||
<h3 className="font-semibold">
|
||||
<Trans>Recipients</Trans>
|
||||
</h3>
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { FolderType, OrganisationType } from '@prisma/client';
|
||||
import { useParams, useSearchParams } from 'react-router';
|
||||
import { Link } from 'react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { useSessionStorage } from '@documenso/lib/client-only/hooks/use-session-storage';
|
||||
import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
|
||||
import { STATS_COUNT_CAP } from '@documenso/lib/constants/document';
|
||||
@@ -22,6 +12,12 @@ import { ZFindDocumentsInternalRequestSchema } from '@documenso/trpc/server/docu
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/avatar';
|
||||
import type { RowSelectionState } from '@documenso/ui/primitives/data-table';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType, FolderType, OrganisationType } from '@prisma/client';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Link, useParams, useSearchParams } from 'react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { DocumentMoveToFolderDialog } from '~/components/dialogs/document-move-to-folder-dialog';
|
||||
import { EnvelopesBulkDeleteDialog } from '~/components/dialogs/envelopes-bulk-delete-dialog';
|
||||
@@ -62,10 +58,7 @@ export default function DocumentsPage() {
|
||||
const [isMovingDocument, setIsMovingDocument] = useState(false);
|
||||
const [documentToMove, setDocumentToMove] = useState<number | null>(null);
|
||||
|
||||
const [rowSelection, setRowSelection] = useSessionStorage<RowSelectionState>(
|
||||
'documents-bulk-selection',
|
||||
{},
|
||||
);
|
||||
const [rowSelection, setRowSelection] = useSessionStorage<RowSelectionState>('documents-bulk-selection', {});
|
||||
const [isBulkMoveDialogOpen, setIsBulkMoveDialogOpen] = useState(false);
|
||||
const [isBulkDeleteDialogOpen, setIsBulkDeleteDialogOpen] = useState(false);
|
||||
|
||||
@@ -140,14 +133,12 @@ export default function DocumentsPage() {
|
||||
|
||||
<div className="mt-8 flex flex-wrap items-center justify-between gap-x-4 gap-y-8">
|
||||
<div className="flex flex-row items-center">
|
||||
<Avatar className="mr-3 h-12 w-12 border-2 border-solid border-white dark:border-border">
|
||||
<Avatar className="mr-3 h-12 w-12 border-2 border-white border-solid dark:border-border">
|
||||
{team.avatarImageId && <AvatarImage src={formatAvatarUrl(team.avatarImageId)} />}
|
||||
<AvatarFallback className="text-xs text-muted-foreground">
|
||||
{team.name.slice(0, 1)}
|
||||
</AvatarFallback>
|
||||
<AvatarFallback className="text-muted-foreground text-xs">{team.name.slice(0, 1)}</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<h2 className="text-4xl font-semibold">
|
||||
<h2 className="font-semibold text-4xl">
|
||||
<Trans>Documents</Trans>
|
||||
</h2>
|
||||
</div>
|
||||
@@ -170,20 +161,13 @@ export default function DocumentsPage() {
|
||||
return true;
|
||||
})
|
||||
.map((value) => (
|
||||
<TabsTrigger
|
||||
key={value}
|
||||
className="min-w-[60px] hover:text-foreground"
|
||||
value={value}
|
||||
asChild
|
||||
>
|
||||
<TabsTrigger key={value} className="min-w-[60px] hover:text-foreground" value={value} asChild>
|
||||
<Link to={getTabHref(value)} preventScrollReset>
|
||||
<DocumentStatus status={value} />
|
||||
|
||||
{value !== ExtendedDocumentStatus.ALL && (
|
||||
<span className="ml-1 inline-block opacity-50">
|
||||
{stats[value] >= STATS_COUNT_CAP
|
||||
? `${STATS_COUNT_CAP.toLocaleString()}+`
|
||||
: stats[value]}
|
||||
{stats[value] >= STATS_COUNT_CAP ? `${STATS_COUNT_CAP.toLocaleString()}+` : stats[value]}
|
||||
</span>
|
||||
)}
|
||||
</Link>
|
||||
@@ -206,9 +190,7 @@ export default function DocumentsPage() {
|
||||
<div className="mt-8">
|
||||
<div>
|
||||
{data && data.count === 0 ? (
|
||||
<DocumentsTableEmptyState
|
||||
status={findDocumentSearchParams.status || ExtendedDocumentStatus.ALL}
|
||||
/>
|
||||
<DocumentsTableEmptyState status={findDocumentSearchParams.status || ExtendedDocumentStatus.ALL} />
|
||||
) : (
|
||||
<DocumentsTable
|
||||
data={data}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
|
||||
import { Link, useSearchParams } from 'react-router';
|
||||
|
||||
import { FolderType } from '@documenso/lib/types/folder-type';
|
||||
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { type TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema';
|
||||
import type { TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import { Link, useSearchParams } from 'react-router';
|
||||
|
||||
import { FolderCreateDialog } from '~/components/dialogs/folder-create-dialog';
|
||||
import { FolderDeleteDialog } from '~/components/dialogs/folder-delete-dialog';
|
||||
@@ -64,11 +62,8 @@ export default function DocumentsFoldersPage() {
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="flex flex-1 items-center text-sm font-medium text-muted-foreground">
|
||||
<Link
|
||||
to={formatDocumentsPath(team.url)}
|
||||
className="flex items-center hover:text-muted-foreground/80"
|
||||
>
|
||||
<div className="flex flex-1 items-center font-medium text-muted-foreground text-sm">
|
||||
<Link to={formatDocumentsPath(team.url)} className="flex items-center hover:text-muted-foreground/80">
|
||||
<HomeIcon className="mr-2 h-4 w-4" />
|
||||
<Trans>Home</Trans>
|
||||
</Link>
|
||||
@@ -76,10 +71,7 @@ export default function DocumentsFoldersPage() {
|
||||
{foldersData?.breadcrumbs.map((folder) => (
|
||||
<div key={folder.id} className="flex items-center">
|
||||
<span className="px-3">/</span>
|
||||
<Link
|
||||
to={formatBreadcrumbPath(folder.id)}
|
||||
className="flex items-center hover:text-muted-foreground/80"
|
||||
>
|
||||
<Link to={formatBreadcrumbPath(folder.id)} className="flex items-center hover:text-muted-foreground/80">
|
||||
<FolderIcon className="mr-2 h-4 w-4" />
|
||||
<span>{folder.name}</span>
|
||||
</Link>
|
||||
@@ -93,7 +85,7 @@ export default function DocumentsFoldersPage() {
|
||||
</div>
|
||||
|
||||
<div className="relative w-full max-w-md py-6">
|
||||
<SearchIcon className="absolute left-2 top-9 h-4 w-4 text-muted-foreground" />
|
||||
<SearchIcon className="absolute top-9 left-2 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder={t`Search folders...`}
|
||||
value={searchTerm}
|
||||
@@ -102,7 +94,7 @@ export default function DocumentsFoldersPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h1 className="mt-4 truncate text-2xl font-semibold md:text-3xl">
|
||||
<h1 className="mt-4 truncate font-semibold text-2xl md:text-3xl">
|
||||
<Trans>All Folders</Trans>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { CheckCircle2, Clock } from 'lucide-react';
|
||||
import { P, match } from 'ts-pattern';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { getTeamWithEmail } from '@documenso/lib/server-only/team/get-team-email-by-email';
|
||||
import { formatAvatarUrl } from '@documenso/lib/utils/avatars';
|
||||
@@ -9,6 +5,9 @@ import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
|
||||
import { canExecuteTeamAction } from '@documenso/lib/utils/teams';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert';
|
||||
import { AvatarWithText } from '@documenso/ui/primitives/avatar';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { CheckCircle2, Clock } from 'lucide-react';
|
||||
import { match, P } from 'ts-pattern';
|
||||
|
||||
import { TeamDeleteDialog } from '~/components/dialogs/team-delete-dialog';
|
||||
import { TeamEmailAddDialog } from '~/components/dialogs/team-email-add-dialog';
|
||||
@@ -55,34 +54,29 @@ export default function TeamsSettingsPage({ loaderData }: Route.ComponentProps)
|
||||
|
||||
<AlertDescription className="mr-2">
|
||||
<Trans>
|
||||
You can view documents associated with this email and use this identity when sending
|
||||
documents.
|
||||
You can view documents associated with this email and use this identity when sending documents.
|
||||
</Trans>
|
||||
</AlertDescription>
|
||||
|
||||
<hr className="border-border/50 mt-2" />
|
||||
<hr className="mt-2 border-border/50" />
|
||||
|
||||
<div className="flex flex-row items-center justify-between pt-4">
|
||||
<AvatarWithText
|
||||
avatarClass="h-12 w-12"
|
||||
avatarSrc={formatAvatarUrl(team.avatarImageId)}
|
||||
avatarFallback={extractInitials(
|
||||
(team.teamEmail?.name || team.emailVerification?.name) ?? '',
|
||||
)}
|
||||
avatarFallback={extractInitials((team.teamEmail?.name || team.emailVerification?.name) ?? '')}
|
||||
primaryText={
|
||||
<span className="text-foreground/80 text-sm font-semibold">
|
||||
<span className="font-semibold text-foreground/80 text-sm">
|
||||
{team.teamEmail?.name || team.emailVerification?.name}
|
||||
</span>
|
||||
}
|
||||
secondaryText={
|
||||
<span className="text-sm">
|
||||
{team.teamEmail?.email || team.emailVerification?.email}
|
||||
</span>
|
||||
<span className="text-sm">{team.teamEmail?.email || team.emailVerification?.email}</span>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="flex flex-row items-center pr-2">
|
||||
<div className="text-muted-foreground mr-4 flex flex-row items-center text-sm xl:mr-8">
|
||||
<div className="mr-4 flex flex-row items-center text-muted-foreground text-sm xl:mr-8">
|
||||
{match({
|
||||
teamEmail: team.teamEmail,
|
||||
emailVerification: team.emailVerification,
|
||||
@@ -96,8 +90,7 @@ export default function TeamsSettingsPage({ loaderData }: Route.ComponentProps)
|
||||
.with(
|
||||
{
|
||||
emailVerification: P.when(
|
||||
(emailVerification) =>
|
||||
emailVerification && emailVerification?.expiresAt < new Date(),
|
||||
(emailVerification) => emailVerification && emailVerification?.expiresAt < new Date(),
|
||||
),
|
||||
},
|
||||
() => (
|
||||
@@ -123,17 +116,14 @@ export default function TeamsSettingsPage({ loaderData }: Route.ComponentProps)
|
||||
)}
|
||||
|
||||
{!team.teamEmail && !team.emailVerification && (
|
||||
<Alert
|
||||
className="flex flex-col justify-between p-6 sm:flex-row sm:items-center"
|
||||
variant="neutral"
|
||||
>
|
||||
<Alert className="flex flex-col justify-between p-6 sm:flex-row sm:items-center" variant="neutral">
|
||||
<div className="mb-4 sm:mb-0">
|
||||
<AlertTitle>
|
||||
<Trans>Team email</Trans>
|
||||
</AlertTitle>
|
||||
|
||||
<AlertDescription className="mr-2">
|
||||
<ul className="text-muted-foreground mt-0.5 list-inside list-disc text-sm">
|
||||
<ul className="mt-0.5 list-inside list-disc text-muted-foreground text-sm">
|
||||
{/* Feature not available yet. */}
|
||||
{/* <li>Display this name and email when sending documents</li> */}
|
||||
{/* <li>View documents associated with this email</li> */}
|
||||
@@ -150,10 +140,7 @@ export default function TeamsSettingsPage({ loaderData }: Route.ComponentProps)
|
||||
)}
|
||||
|
||||
{canExecuteTeamAction('MANAGE_TEAM', currentTeam.currentTeamRole) && (
|
||||
<Alert
|
||||
className="flex flex-col justify-between p-6 sm:flex-row sm:items-center"
|
||||
variant="neutral"
|
||||
>
|
||||
<Alert className="flex flex-col justify-between p-6 sm:flex-row sm:items-center" variant="neutral">
|
||||
<div className="mb-4 sm:mb-0">
|
||||
<AlertTitle>
|
||||
<Trans>Delete team</Trans>
|
||||
@@ -161,8 +148,7 @@ export default function TeamsSettingsPage({ loaderData }: Route.ComponentProps)
|
||||
|
||||
<AlertDescription className="mr-2">
|
||||
<Trans>
|
||||
This team, and any associated data excluding billing invoices will be permanently
|
||||
deleted.
|
||||
This team, and any associated data excluding billing invoices will be permanently deleted.
|
||||
</Trans>
|
||||
</AlertDescription>
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import {
|
||||
BracesIcon,
|
||||
Globe2Icon,
|
||||
GroupIcon,
|
||||
Settings2Icon,
|
||||
SettingsIcon,
|
||||
Users2Icon,
|
||||
WebhookIcon,
|
||||
} from 'lucide-react';
|
||||
import { Link, NavLink, Outlet, redirect } from 'react-router';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { canExecuteTeamAction } from '@documenso/lib/utils/teams';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { BracesIcon, Globe2Icon, GroupIcon, Settings2Icon, SettingsIcon, Users2Icon, WebhookIcon } from 'lucide-react';
|
||||
import { Link, NavLink, Outlet, redirect } from 'react-router';
|
||||
|
||||
import { GenericErrorLayout } from '~/components/general/generic-error-layout';
|
||||
import { useCurrentTeam } from '~/providers/team';
|
||||
@@ -128,7 +119,7 @@ export default function TeamsSettingsLayout() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
||||
<h1 className="text-4xl font-semibold">
|
||||
<h1 className="font-semibold text-4xl">
|
||||
<Trans>Team Settings</Trans>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Loader } from 'lucide-react';
|
||||
|
||||
import { putFile } from '@documenso/lib/universal/upload/put-file';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Loader } from 'lucide-react';
|
||||
|
||||
import {
|
||||
BrandingPreferencesForm,
|
||||
@@ -34,7 +33,7 @@ export default function TeamsSettingsPage() {
|
||||
try {
|
||||
const { brandingEnabled, brandingLogo, brandingUrl, brandingCompanyDetails } = data;
|
||||
|
||||
let uploadedBrandingLogo: string | undefined = undefined;
|
||||
let uploadedBrandingLogo: string | undefined;
|
||||
|
||||
if (brandingLogo) {
|
||||
uploadedBrandingLogo = JSON.stringify(await putFile(brandingLogo));
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Loader } from 'lucide-react';
|
||||
import { useLoaderData } from 'react-router';
|
||||
|
||||
import { IS_AI_FEATURES_CONFIGURED } from '@documenso/lib/constants/app';
|
||||
import { DocumentSignatureType } from '@documenso/lib/constants/document';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Loader } from 'lucide-react';
|
||||
import { useLoaderData } from 'react-router';
|
||||
|
||||
import {
|
||||
DocumentPreferencesForm,
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { SpinnerBox } from '@documenso/ui/primitives/spinner';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
import {
|
||||
EmailPreferencesForm,
|
||||
type TEmailPreferencesFormSchema,
|
||||
} from '~/components/forms/email-preferences-form';
|
||||
import { EmailPreferencesForm, type TEmailPreferencesFormSchema } from '~/components/forms/email-preferences-form';
|
||||
import { SettingsHeader } from '~/components/general/settings-header';
|
||||
import { useCurrentTeam } from '~/providers/team';
|
||||
import { appMetaTags } from '~/utils/meta';
|
||||
@@ -62,10 +58,7 @@ export default function TeamEmailSettingsGeneral() {
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl">
|
||||
<SettingsHeader
|
||||
title={t`Email Preferences`}
|
||||
subtitle={t`You can manage your email preferences here.`}
|
||||
/>
|
||||
<SettingsHeader title={t`Email Preferences`} subtitle={t`You can manage your email preferences here.`} />
|
||||
|
||||
<section>
|
||||
<EmailPreferencesForm
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { OrganisationGroupType, OrganisationMemberRole } from '@prisma/client';
|
||||
import { useLocation, useSearchParams } from 'react-router';
|
||||
|
||||
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { AnimateGenericFadeInOut } from '@documenso/ui/components/animate/animate-generic-fade-in-out';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { OrganisationGroupType, OrganisationMemberRole } from '@prisma/client';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation, useSearchParams } from 'react-router';
|
||||
|
||||
import { TeamGroupCreateDialog } from '~/components/dialogs/team-group-create-dialog';
|
||||
import { SettingsHeader } from '~/components/general/settings-header';
|
||||
@@ -72,9 +70,7 @@ export default function TeamsSettingsGroupsPage() {
|
||||
<TeamGroupsTable />
|
||||
|
||||
<AnimateGenericFadeInOut key={everyoneGroupQuery.isFetched ? 'true' : 'false'}>
|
||||
{everyoneGroupQuery.isFetched && (
|
||||
<TeamInheritMemberAlert memberAccessTeamGroup={memberAccessTeamGroup} />
|
||||
)}
|
||||
{everyoneGroupQuery.isFetched && <TeamInheritMemberAlert memberAccessTeamGroup={memberAccessTeamGroup} />}
|
||||
</AnimateGenericFadeInOut>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useLocation, useSearchParams } from 'react-router';
|
||||
|
||||
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation, useSearchParams } from 'react-router';
|
||||
|
||||
import { TeamMemberCreateDialog } from '~/components/dialogs/team-member-create-dialog';
|
||||
import { SettingsHeader } from '~/components/general/settings-header';
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { type TemplateDirectLink, TemplateType } from '@prisma/client';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { useSession } from '@documenso/lib/client-only/providers/session';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
@@ -16,6 +9,10 @@ import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Switch } from '@documenso/ui/primitives/switch';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { type TemplateDirectLink, TemplateType } from '@prisma/client';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { ManagePublicTemplateDialog } from '~/components/dialogs/public-profile-template-manage-dialog';
|
||||
import type { TPublicProfileFormSchema } from '~/components/forms/public-profile-form';
|
||||
@@ -72,20 +69,16 @@ export default function PublicProfilePage({ loaderData }: Route.ComponentProps)
|
||||
perPage: 100,
|
||||
});
|
||||
|
||||
const { mutateAsync: updateTeam, isPending: isUpdatingTeamProfile } =
|
||||
trpc.team.update.useMutation({
|
||||
onSuccess: async () => {
|
||||
await refreshSession();
|
||||
},
|
||||
});
|
||||
const { mutateAsync: updateTeam, isPending: isUpdatingTeamProfile } = trpc.team.update.useMutation({
|
||||
onSuccess: async () => {
|
||||
await refreshSession();
|
||||
},
|
||||
});
|
||||
|
||||
const isUpdating = isUpdatingTeamProfile;
|
||||
|
||||
const enabledPrivateDirectTemplates = useMemo(
|
||||
() =>
|
||||
(data?.data ?? []).filter(
|
||||
(template): template is DirectTemplate => template.directLink?.enabled === true,
|
||||
),
|
||||
() => (data?.data ?? []).filter((template): template is DirectTemplate => template.directLink?.enabled === true),
|
||||
[data],
|
||||
);
|
||||
|
||||
@@ -143,13 +136,10 @@ export default function PublicProfilePage({ loaderData }: Route.ComponentProps)
|
||||
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-row items-center justify-center space-x-2 text-xs text-muted-foreground/50',
|
||||
{
|
||||
'[&>*:first-child]:text-muted-foreground': !isPublicProfileVisible,
|
||||
'[&>*:last-child]:text-muted-foreground': isPublicProfileVisible,
|
||||
},
|
||||
)}
|
||||
className={cn('flex flex-row items-center justify-center space-x-2 text-muted-foreground/50 text-xs', {
|
||||
'[&>*:first-child]:text-muted-foreground': !isPublicProfileVisible,
|
||||
'[&>*:last-child]:text-muted-foreground': isPublicProfileVisible,
|
||||
})}
|
||||
>
|
||||
<span>
|
||||
<Trans>Hide</Trans>
|
||||
@@ -208,9 +198,7 @@ export default function PublicProfilePage({ loaderData }: Route.ComponentProps)
|
||||
directTemplates={enabledPrivateDirectTemplates}
|
||||
trigger={
|
||||
<Button variant="outline">
|
||||
<Trans context="Action button to link template to public profile">
|
||||
Link template
|
||||
</Trans>
|
||||
<Trans context="Action button to link template to public profile">Link template</Trans>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { TeamMemberRole } from '@prisma/client';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { Alert, AlertDescription } from '@documenso/ui/primitives/alert';
|
||||
import { AlertTitle } from '@documenso/ui/primitives/alert';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
|
||||
import TokenDeleteDialog from '~/components/dialogs/token-delete-dialog';
|
||||
import { ApiTokenForm } from '~/components/forms/token';
|
||||
import { SettingsHeader } from '~/components/general/settings-header';
|
||||
@@ -37,6 +35,7 @@ export default function ApiTokensPage() {
|
||||
className="text-primary underline"
|
||||
href={'https://docs.documenso.com/developers/public-api'}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Documentation
|
||||
</a>{' '}
|
||||
@@ -46,10 +45,7 @@ export default function ApiTokensPage() {
|
||||
/>
|
||||
|
||||
{team && team?.currentTeamRole !== TeamMemberRole.ADMIN ? (
|
||||
<Alert
|
||||
className="flex flex-col items-center justify-between gap-4 p-6 md:flex-row"
|
||||
variant="warning"
|
||||
>
|
||||
<Alert className="flex flex-col items-center justify-between gap-4 p-6 md:flex-row" variant="warning">
|
||||
<div>
|
||||
<AlertTitle>
|
||||
<Trans>Unauthorized</Trans>
|
||||
@@ -63,15 +59,15 @@ export default function ApiTokensPage() {
|
||||
<>
|
||||
<ApiTokenForm className="max-w-xl" tokens={tokens} />
|
||||
|
||||
<hr className="mb-4 mt-8" />
|
||||
<hr className="mt-8 mb-4" />
|
||||
|
||||
<h4 className="text-xl font-medium">
|
||||
<h4 className="font-medium text-xl">
|
||||
<Trans>Your existing tokens</Trans>
|
||||
</h4>
|
||||
|
||||
{tokens && tokens.length === 0 && (
|
||||
<div className="mb-4">
|
||||
<p className="mt-2 text-sm italic text-muted-foreground">
|
||||
<p className="mt-2 text-muted-foreground text-sm italic">
|
||||
<Trans>Your tokens will be shown here once you create them.</Trans>
|
||||
</p>
|
||||
</div>
|
||||
@@ -85,19 +81,15 @@ export default function ApiTokensPage() {
|
||||
<div>
|
||||
<h5 className="text-base">{token.name}</h5>
|
||||
|
||||
<p className="mt-2 text-xs text-muted-foreground">
|
||||
<Trans>
|
||||
Created on {i18n.date(token.createdAt, DateTime.DATETIME_FULL)}
|
||||
</Trans>
|
||||
<p className="mt-2 text-muted-foreground text-xs">
|
||||
<Trans>Created on {i18n.date(token.createdAt, DateTime.DATETIME_FULL)}</Trans>
|
||||
</p>
|
||||
{token.expires ? (
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
<Trans>
|
||||
Expires on {i18n.date(token.expires, DateTime.DATETIME_FULL)}
|
||||
</Trans>
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
<Trans>Expires on {i18n.date(token.expires, DateTime.DATETIME_FULL)}</Trans>
|
||||
</p>
|
||||
) : (
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
<Trans>Token doesn't have an expiration date</Trans>
|
||||
</p>
|
||||
)}
|
||||
|
||||
+12
-30
@@ -1,22 +1,3 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { WebhookCallStatus, WebhookTriggerEvents } from '@prisma/client';
|
||||
import {
|
||||
CheckCircle2Icon,
|
||||
ChevronRightIcon,
|
||||
PencilIcon,
|
||||
TerminalIcon,
|
||||
XCircleIcon,
|
||||
} from 'lucide-react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useLocation, useSearchParams } from 'react-router';
|
||||
import { Link } from 'react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
|
||||
import { useIsMounted } from '@documenso/lib/client-only/hooks/use-is-mounted';
|
||||
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
|
||||
@@ -35,6 +16,13 @@ import { SpinnerBox } from '@documenso/ui/primitives/spinner';
|
||||
import { TableCell } from '@documenso/ui/primitives/table';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { WebhookCallStatus, WebhookTriggerEvents } from '@prisma/client';
|
||||
import { CheckCircle2Icon, ChevronRightIcon, PencilIcon, TerminalIcon, XCircleIcon } from 'lucide-react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Link, useLocation, useNavigate, useSearchParams } from 'react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { WebhookEditDialog } from '~/components/dialogs/webhook-edit-dialog';
|
||||
import { WebhookTestDialog } from '~/components/dialogs/webhook-test-dialog';
|
||||
@@ -71,9 +59,7 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
|
||||
|
||||
const debouncedSearchQuery = useDebouncedValue(searchQuery, 500);
|
||||
|
||||
const parsedSearchParams = WebhookSearchParamsSchema.parse(
|
||||
Object.fromEntries(searchParams ?? []),
|
||||
);
|
||||
const parsedSearchParams = WebhookSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
|
||||
|
||||
const { data: webhook, isLoading } = trpc.webhook.getWebhookById.useQuery(
|
||||
{
|
||||
@@ -151,10 +137,8 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
|
||||
accessorKey: 'event',
|
||||
cell: ({ row }) => (
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-foreground">
|
||||
{toFriendlyWebhookEventName(row.original.event)}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">{row.original.id}</p>
|
||||
<p className="font-semibold text-foreground text-sm">{toFriendlyWebhookEventName(row.original.event)}</p>
|
||||
<p className="text-muted-foreground text-xs">{row.original.id}</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@@ -170,7 +154,7 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
|
||||
})}
|
||||
</p>
|
||||
|
||||
<div className="data-state-selected:block opacity-0 transition-opacity group-hover:opacity-100">
|
||||
<div className="opacity-0 transition-opacity group-hover:opacity-100 data-state-selected:block">
|
||||
<ChevronRightIcon className="h-4 w-4" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -330,9 +314,7 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
|
||||
}}
|
||||
>
|
||||
{(table) =>
|
||||
results.totalPages > 1 && (
|
||||
<DataTablePagination additionalInformation="VisibleCount" table={table} />
|
||||
)
|
||||
results.totalPages > 1 && <DataTablePagination additionalInformation="VisibleCount" table={table} />
|
||||
}
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Plural, useLingui } from '@lingui/react/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import type { Webhook } from '@prisma/client';
|
||||
import { EditIcon, Loader, MoreHorizontalIcon, ScrollTextIcon, Trash2Icon } from 'lucide-react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import { toFriendlyWebhookEventName } from '@documenso/lib/universal/webhook/to-friendly-webhook-event-name';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { Badge } from '@documenso/ui/primitives/badge';
|
||||
@@ -20,6 +11,12 @@ import {
|
||||
} from '@documenso/ui/primitives/dropdown-menu';
|
||||
import { Skeleton } from '@documenso/ui/primitives/skeleton';
|
||||
import { TableCell } from '@documenso/ui/primitives/table';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Plural, Trans, useLingui } from '@lingui/react/macro';
|
||||
import type { Webhook } from '@prisma/client';
|
||||
import { EditIcon, Loader, MoreHorizontalIcon, ScrollTextIcon, Trash2Icon } from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import { WebhookCreateDialog } from '~/components/dialogs/webhook-create-dialog';
|
||||
import { WebhookDeleteDialog } from '~/components/dialogs/webhook-delete-dialog';
|
||||
@@ -52,11 +49,8 @@ export default function WebhookPage() {
|
||||
header: t`Webhook`,
|
||||
cell: ({ row }) => (
|
||||
<Link to={`/t/${team.url}/settings/webhooks/${row.original.id}`}>
|
||||
<p className="text-xs text-muted-foreground">{row.original.id}</p>
|
||||
<p
|
||||
className="max-w-sm truncate text-xs font-semibold text-foreground"
|
||||
title={row.original.webhookUrl}
|
||||
>
|
||||
<p className="text-muted-foreground text-xs">{row.original.id}</p>
|
||||
<p className="max-w-sm truncate font-semibold text-foreground text-xs" title={row.original.webhookUrl}>
|
||||
{row.original.webhookUrl}
|
||||
</p>
|
||||
</Link>
|
||||
@@ -75,9 +69,7 @@ export default function WebhookPage() {
|
||||
cell: ({ row }) => (
|
||||
<p
|
||||
className="text-foreground"
|
||||
title={row.original.eventTriggers
|
||||
.map((event) => toFriendlyWebhookEventName(event))
|
||||
.join(', ')}
|
||||
title={row.original.eventTriggers.map((event) => toFriendlyWebhookEventName(event)).join(', ')}
|
||||
>
|
||||
<Plural value={row.original.eventTriggers.length} one="# Event" other="# Events" />
|
||||
</p>
|
||||
@@ -120,9 +112,7 @@ export default function WebhookPage() {
|
||||
emptyState={
|
||||
<div className="flex h-60 flex-col items-center justify-center gap-y-4 text-muted-foreground/60">
|
||||
<p>
|
||||
<Trans>
|
||||
You have no webhooks yet. Your webhooks will be shown here once you create them.
|
||||
</Trans>
|
||||
<Trans>You have no webhooks yet. Your webhooks will be shown here once you create them.</Trans>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { DocumentSigningOrder, SigningStatus } from '@prisma/client';
|
||||
import { ChevronLeft, LucideEdit } from 'lucide-react';
|
||||
import { Link, useNavigate } from 'react-router';
|
||||
|
||||
import { EnvelopeRenderProvider } from '@documenso/lib/client-only/providers/envelope-render-provider';
|
||||
import { useSession } from '@documenso/lib/client-only/providers/session';
|
||||
import { PDF_VIEWER_ERROR_MESSAGES } from '@documenso/lib/constants/pdf-viewer-i18n';
|
||||
@@ -16,6 +10,11 @@ import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||
import { Spinner } from '@documenso/ui/primitives/spinner';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { DocumentSigningOrder, SigningStatus } from '@prisma/client';
|
||||
import { ChevronLeft, LucideEdit } from 'lucide-react';
|
||||
import { Link, useNavigate } from 'react-router';
|
||||
|
||||
import { TemplateBulkSendDialog } from '~/components/dialogs/template-bulk-send-dialog';
|
||||
import { TemplateDirectLinkDialog } from '~/components/dialogs/template-direct-link-dialog';
|
||||
@@ -53,8 +52,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
|
||||
const envelope = teamTemplateQuery.data ?? orgTemplateQuery.data;
|
||||
const isLoadingEnvelope =
|
||||
teamTemplateQuery.isLoading ||
|
||||
(teamTemplateQuery.isError && !orgTemplateQuery.isError && !orgTemplateQuery.data);
|
||||
teamTemplateQuery.isLoading || (teamTemplateQuery.isError && !orgTemplateQuery.isError && !orgTemplateQuery.data);
|
||||
const isErrorEnvelope = teamTemplateQuery.isError && orgTemplateQuery.isError;
|
||||
|
||||
if (isLoadingEnvelope) {
|
||||
@@ -94,9 +92,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
|
||||
// Remap to fit the DocumentReadOnlyFields component.
|
||||
const readOnlyFields = envelope.fields.map((field) => {
|
||||
const recipient = envelope.recipients.find(
|
||||
(recipient) => recipient.id === field.recipientId,
|
||||
) || {
|
||||
const recipient = envelope.recipients.find((recipient) => recipient.id === field.recipientId) || {
|
||||
name: '',
|
||||
email: '',
|
||||
signingStatus: SigningStatus.NOT_SIGNED,
|
||||
@@ -122,10 +118,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
return (
|
||||
<div className="mx-auto -mt-4 w-full max-w-screen-xl px-4 md:px-8">
|
||||
<div className="flex flex-row justify-between">
|
||||
<Link
|
||||
to={templateRootPath}
|
||||
className="flex items-center text-documenso-700 hover:opacity-80"
|
||||
>
|
||||
<Link to={templateRootPath} className="flex items-center text-documenso-700 hover:opacity-80">
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Templates</Trans>
|
||||
</Link>
|
||||
@@ -157,16 +150,12 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
</div>
|
||||
|
||||
<div className="min-w-0">
|
||||
<h1 className="mt-4 block text-2xl font-semibold md:text-3xl" title={envelope.title}>
|
||||
<h1 className="mt-4 block font-semibold text-2xl md:text-3xl" title={envelope.title}>
|
||||
{envelope.title}
|
||||
</h1>
|
||||
|
||||
<div className="mt-2.5 flex items-center">
|
||||
<TemplateType
|
||||
inheritColor
|
||||
className="text-muted-foreground"
|
||||
type={envelope.templateType}
|
||||
/>
|
||||
<TemplateType inheritColor className="text-muted-foreground" type={envelope.templateType} />
|
||||
|
||||
{envelope.directLink?.token && (
|
||||
<TemplateDirectLinkBadge
|
||||
@@ -192,9 +181,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
showRecipientTooltip: true,
|
||||
}}
|
||||
>
|
||||
{isMultiEnvelopeItem && (
|
||||
<EnvelopeRendererFileSelector fields={envelope.fields} className="mb-4 p-0" />
|
||||
)}
|
||||
{isMultiEnvelopeItem && <EnvelopeRendererFileSelector fields={envelope.fields} className="mb-4 p-0" />}
|
||||
|
||||
<Card className="rounded-xl before:rounded-xl" gradient>
|
||||
<CardContent className="p-2">
|
||||
@@ -208,10 +195,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
</EnvelopeRenderProvider>
|
||||
</div>
|
||||
) : (
|
||||
<Card
|
||||
className="relative col-span-12 rounded-xl before:rounded-xl lg:col-span-6 xl:col-span-7"
|
||||
gradient
|
||||
>
|
||||
<Card className="relative col-span-12 rounded-xl before:rounded-xl lg:col-span-6 xl:col-span-7" gradient>
|
||||
<CardContent className="p-2">
|
||||
<DocumentReadOnlyFields
|
||||
fields={readOnlyFields}
|
||||
@@ -238,13 +222,11 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={cn('col-span-12 lg:col-span-6 xl:col-span-5', isMultiEnvelopeItem && 'mt-20')}
|
||||
>
|
||||
<div className={cn('col-span-12 lg:col-span-6 xl:col-span-5', isMultiEnvelopeItem && 'mt-20')}>
|
||||
<div className="space-y-6">
|
||||
<section className="flex flex-col rounded-xl border border-border bg-widget pb-4 pt-6">
|
||||
<section className="flex flex-col rounded-xl border border-border bg-widget pt-6 pb-4">
|
||||
<div className="flex flex-row items-center justify-between px-4">
|
||||
<h3 className="text-2xl font-semibold text-foreground">
|
||||
<h3 className="font-semibold text-2xl text-foreground">
|
||||
<Trans>Template</Trans>
|
||||
</h3>
|
||||
|
||||
@@ -262,7 +244,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="mt-2 px-4 text-sm text-muted-foreground">
|
||||
<p className="mt-2 px-4 text-muted-foreground text-sm">
|
||||
{isOwnTeamTemplate ? (
|
||||
<Trans>Manage and view template</Trans>
|
||||
) : (
|
||||
@@ -307,13 +289,11 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
|
||||
</div>
|
||||
|
||||
<div className="mt-16" id="documents">
|
||||
<h1 className="mb-4 text-2xl font-bold">
|
||||
<h1 className="mb-4 font-bold text-2xl">
|
||||
<Trans>Documents created from template</Trans>
|
||||
</h1>
|
||||
|
||||
<TemplatePageViewDocumentsTable
|
||||
templateId={mapSecondaryIdToTemplateId(envelope.secondaryId)}
|
||||
/>
|
||||
<TemplatePageViewDocumentsTable templateId={mapSecondaryIdToTemplateId(envelope.secondaryId)} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { ChevronLeftIcon } from 'lucide-react';
|
||||
import {
|
||||
Link,
|
||||
Outlet,
|
||||
type ShouldRevalidateFunctionArgs,
|
||||
isRouteErrorResponse,
|
||||
redirect,
|
||||
} from 'react-router';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { getOrganisationTemplateById } from '@documenso/lib/server-only/template/get-organisation-template-by-id';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { ChevronLeftIcon } from 'lucide-react';
|
||||
import { isRouteErrorResponse, Link, Outlet, redirect, type ShouldRevalidateFunctionArgs } from 'react-router';
|
||||
|
||||
import { GenericErrorLayout } from '~/components/general/generic-error-layout';
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { ChevronLeft } from 'lucide-react';
|
||||
import { Link, redirect } from 'react-router';
|
||||
|
||||
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
|
||||
import { getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
|
||||
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
|
||||
import { formatTemplatesPath } from '@documenso/lib/utils/teams';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { ChevronLeft } from 'lucide-react';
|
||||
import { Link, redirect } from 'react-router';
|
||||
|
||||
import { TemplateDirectLinkDialog } from '~/components/dialogs/template-direct-link-dialog';
|
||||
import { DocumentAttachmentsPopover } from '~/components/general/document/document-attachments-popover';
|
||||
@@ -68,7 +67,7 @@ export default function TemplateEditPage() {
|
||||
</Link>
|
||||
|
||||
<h1
|
||||
className="mt-4 block max-w-[20rem] truncate text-2xl font-semibold md:max-w-[30rem] md:text-3xl"
|
||||
className="mt-4 block max-w-[20rem] truncate font-semibold text-2xl md:max-w-[30rem] md:text-3xl"
|
||||
title={template.title}
|
||||
>
|
||||
{template.title}
|
||||
@@ -104,11 +103,7 @@ export default function TemplateEditPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TemplateEditForm
|
||||
className="mt-6"
|
||||
initialTemplate={template}
|
||||
templateRootPath={templateRootPath}
|
||||
/>
|
||||
<TemplateEditForm className="mt-6" initialTemplate={template} templateRootPath={templateRootPath} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType, OrganisationType } from '@prisma/client';
|
||||
import { Bird } from 'lucide-react';
|
||||
import { parseAsStringLiteral, useQueryState } from 'nuqs';
|
||||
import { useParams, useSearchParams } from 'react-router';
|
||||
|
||||
import { useSessionStorage } from '@documenso/lib/client-only/hooks/use-session-storage';
|
||||
import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
|
||||
import { FolderType } from '@documenso/lib/types/folder-type';
|
||||
@@ -16,6 +7,13 @@ import { trpc } from '@documenso/trpc/react';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/avatar';
|
||||
import type { RowSelectionState } from '@documenso/ui/primitives/data-table';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { EnvelopeType, OrganisationType } from '@prisma/client';
|
||||
import { Bird } from 'lucide-react';
|
||||
import { parseAsStringLiteral, useQueryState } from 'nuqs';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useParams, useSearchParams } from 'react-router';
|
||||
|
||||
import { EnvelopesBulkDeleteDialog } from '~/components/dialogs/envelopes-bulk-delete-dialog';
|
||||
import { EnvelopesBulkMoveDialog } from '~/components/dialogs/envelopes-bulk-move-dialog';
|
||||
@@ -44,18 +42,12 @@ export default function TemplatesPage() {
|
||||
const page = Number(searchParams.get('page')) || 1;
|
||||
const perPage = Number(searchParams.get('perPage')) || 10;
|
||||
|
||||
const [view, setView] = useQueryState(
|
||||
'view',
|
||||
parseAsStringLiteral(TEMPLATE_VIEWS).withDefault('team'),
|
||||
);
|
||||
const [view, setView] = useQueryState('view', parseAsStringLiteral(TEMPLATE_VIEWS).withDefault('team'));
|
||||
|
||||
const isOrgView = view === 'organisation';
|
||||
const showOrgTab = organisation.type !== OrganisationType.PERSONAL;
|
||||
|
||||
const [rowSelection, setRowSelection] = useSessionStorage<RowSelectionState>(
|
||||
'templates-bulk-selection',
|
||||
{},
|
||||
);
|
||||
const [rowSelection, setRowSelection] = useSessionStorage<RowSelectionState>('templates-bulk-selection', {});
|
||||
const [isBulkMoveDialogOpen, setIsBulkMoveDialogOpen] = useState(false);
|
||||
const [isBulkDeleteDialogOpen, setIsBulkDeleteDialogOpen] = useState(false);
|
||||
|
||||
@@ -104,14 +96,12 @@ export default function TemplatesPage() {
|
||||
|
||||
<div className="mt-8">
|
||||
<div className="flex flex-row items-center">
|
||||
<Avatar className="mr-3 h-12 w-12 border-2 border-solid border-white dark:border-border">
|
||||
<Avatar className="mr-3 h-12 w-12 border-2 border-white border-solid dark:border-border">
|
||||
{team.avatarImageId && <AvatarImage src={formatAvatarUrl(team.avatarImageId)} />}
|
||||
<AvatarFallback className="text-xs text-muted-foreground">
|
||||
{team.name.slice(0, 1)}
|
||||
</AvatarFallback>
|
||||
<AvatarFallback className="text-muted-foreground text-xs">{team.name.slice(0, 1)}</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<h1 className="truncate text-2xl font-semibold md:text-3xl">
|
||||
<h1 className="truncate font-semibold text-2xl md:text-3xl">
|
||||
<Trans>Templates</Trans>
|
||||
</h1>
|
||||
</div>
|
||||
@@ -145,7 +135,7 @@ export default function TemplatesPage() {
|
||||
<Bird className="h-12 w-12" strokeWidth={1.5} />
|
||||
|
||||
<div className="text-center">
|
||||
<h3 className="text-lg font-semibold">
|
||||
<h3 className="font-semibold text-lg">
|
||||
<Trans>We're all empty</Trans>
|
||||
</h3>
|
||||
|
||||
@@ -153,10 +143,7 @@ export default function TemplatesPage() {
|
||||
{isOrgView ? (
|
||||
<Trans>No organisation templates are shared with your team yet.</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
You have not yet created any templates. To create a template please upload
|
||||
one.
|
||||
</Trans>
|
||||
<Trans>You have not yet created any templates. To create a template please upload one.</Trans>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
|
||||
import { Link, useSearchParams } from 'react-router';
|
||||
|
||||
import { FolderType } from '@documenso/lib/types/folder-type';
|
||||
import { formatTemplatesPath } from '@documenso/lib/utils/teams';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { type TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema';
|
||||
import type { TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import { Link, useSearchParams } from 'react-router';
|
||||
|
||||
import { FolderCreateDialog } from '~/components/dialogs/folder-create-dialog';
|
||||
import { FolderDeleteDialog } from '~/components/dialogs/folder-delete-dialog';
|
||||
@@ -64,11 +62,8 @@ export default function TemplatesFoldersPage() {
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="flex flex-1 items-center text-sm font-medium text-muted-foreground">
|
||||
<Link
|
||||
to={formatTemplatesPath(team.url)}
|
||||
className="flex items-center hover:text-muted-foreground/80"
|
||||
>
|
||||
<div className="flex flex-1 items-center font-medium text-muted-foreground text-sm">
|
||||
<Link to={formatTemplatesPath(team.url)} className="flex items-center hover:text-muted-foreground/80">
|
||||
<HomeIcon className="mr-2 h-4 w-4" />
|
||||
<Trans>Home</Trans>
|
||||
</Link>
|
||||
@@ -76,10 +71,7 @@ export default function TemplatesFoldersPage() {
|
||||
{foldersData?.breadcrumbs.map((folder) => (
|
||||
<div key={folder.id} className="flex items-center">
|
||||
<span className="px-3">/</span>
|
||||
<Link
|
||||
to={formatBreadcrumbPath(folder.id)}
|
||||
className="flex items-center hover:text-muted-foreground/80"
|
||||
>
|
||||
<Link to={formatBreadcrumbPath(folder.id)} className="flex items-center hover:text-muted-foreground/80">
|
||||
<FolderIcon className="mr-2 h-4 w-4" />
|
||||
<span>{folder.name}</span>
|
||||
</Link>
|
||||
@@ -93,7 +85,7 @@ export default function TemplatesFoldersPage() {
|
||||
</div>
|
||||
|
||||
<div className="relative w-full max-w-md py-6">
|
||||
<SearchIcon className="absolute left-2 top-9 h-4 w-4 text-muted-foreground" />
|
||||
<SearchIcon className="absolute top-9 left-2 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder={t`Search folders...`}
|
||||
value={searchTerm}
|
||||
@@ -102,7 +94,7 @@ export default function TemplatesFoldersPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h1 className="mt-4 truncate text-2xl font-semibold md:text-3xl">
|
||||
<h1 className="mt-4 truncate font-semibold text-2xl md:text-3xl">
|
||||
<Trans>All Folders</Trans>
|
||||
</h1>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user