diff --git a/.agents/plans/happy-teal-tree-platform-signing-page-branding.md b/.agents/plans/happy-teal-tree-platform-signing-page-branding.md new file mode 100644 index 000000000..efe3c75b7 --- /dev/null +++ b/.agents/plans/happy-teal-tree-platform-signing-page-branding.md @@ -0,0 +1,138 @@ +--- +date: 2026-05-06 +title: Platform Signing Page Branding +--- + +## What + +Platform-plan organisations (and their teams) can customise the **non-embed +signing pages** (`/sign/:token`, `/d/:token`, and the sibling +complete/expired/rejected/waiting pages) with: + +- Six brand colour tokens (background, foreground, primary, primary-foreground, + border, ring) plus a border-radius length. +- A free-text custom CSS block (up to 256 KB). + +Settings live on `OrganisationGlobalSettings` and `TeamGlobalSettings`. Teams +inherit from the org via the existing `brandingEnabled === null` mechanism. + +## Why + +- Embed customers already have white-label CSS; Platform customers want the + same coverage on direct signing URLs that they iframe or link to. +- Persisting on org/team (not per envelope) means it's set-and-forget. +- Sanitising **on save** lets us inline the verbatim string at SSR — no + per-render parsing cost, no `; +}; diff --git a/apps/remix/app/components/general/settings-header.tsx b/apps/remix/app/components/general/settings-header.tsx index 06de2ff24..4023326aa 100644 --- a/apps/remix/app/components/general/settings-header.tsx +++ b/apps/remix/app/components/general/settings-header.tsx @@ -1,6 +1,5 @@ -import React from 'react'; - import { cn } from '@documenso/ui/lib/utils'; +import type React from 'react'; export type SettingsHeaderProps = { title: string | React.ReactNode; @@ -10,18 +9,12 @@ export type SettingsHeaderProps = { className?: string; }; -export const SettingsHeader = ({ - children, - title, - subtitle, - className, - hideDivider, -}: SettingsHeaderProps) => { +export const SettingsHeader = ({ children, title, subtitle, className, hideDivider }: SettingsHeaderProps) => { return ( <>
-

{title}

+

{title}

{subtitle}

diff --git a/apps/remix/app/components/general/settings-nav-desktop.tsx b/apps/remix/app/components/general/settings-nav-desktop.tsx index 20000f6d8..0c6166727 100644 --- a/apps/remix/app/components/general/settings-nav-desktop.tsx +++ b/apps/remix/app/components/general/settings-nav-desktop.tsx @@ -1,24 +1,12 @@ -import type { HTMLAttributes } from 'react'; - -import { Trans } from '@lingui/react/macro'; -import { - BracesIcon, - CreditCardIcon, - Globe2Icon, - Lock, - Settings2Icon, - User, - Users, - WebhookIcon, -} from 'lucide-react'; -import { useLocation } from 'react-router'; -import { Link } from 'react-router'; - import { useSession } from '@documenso/lib/client-only/providers/session'; import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app'; import { canExecuteOrganisationAction, isPersonalLayout } from '@documenso/lib/utils/organisations'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; +import { Trans } from '@lingui/react/macro'; +import { BracesIcon, CreditCardIcon, Globe2Icon, Lock, Settings2Icon, User, Users, WebhookIcon } from 'lucide-react'; +import type { HTMLAttributes } from 'react'; +import { Link, useLocation } from 'react-router'; export type SettingsDesktopNavProps = HTMLAttributes; @@ -38,10 +26,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr @@ -72,10 +54,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr @@ -84,10 +63,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr @@ -96,10 +72,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr @@ -67,12 +66,12 @@ export const TemplatePageViewRecentActivity = ({
@@ -64,13 +59,13 @@ export const TemplatePageViewRecipients = ({ } primaryText={ isTemplateRecipientEmailPlaceholder(recipient.email) ? ( -

{recipient.name}

+

{recipient.name}

) : ( -

{recipient.email}

+

{recipient.email}

) } secondaryText={ -

+

{_(RECIPIENT_ROLES_DESCRIPTION[recipient.role].roleName)}

} diff --git a/apps/remix/app/components/general/template/template-type.tsx b/apps/remix/app/components/general/template/template-type.tsx index 02ef11298..a0a742c2a 100644 --- a/apps/remix/app/components/general/template/template-type.tsx +++ b/apps/remix/app/components/general/template/template-type.tsx @@ -1,4 +1,4 @@ -import type { HTMLAttributes } from 'react'; +import { cn } from '@documenso/ui/lib/utils'; import type { MessageDescriptor } from '@lingui/core'; import { msg } from '@lingui/core/macro'; @@ -6,8 +6,7 @@ import { useLingui } from '@lingui/react'; import type { TemplateType as TemplateTypePrisma } from '@prisma/client'; import { Building2, Globe2, Lock } from 'lucide-react'; import type { LucideIcon } from 'lucide-react/dist/lucide-react'; - -import { cn } from '@documenso/ui/lib/utils'; +import type { HTMLAttributes } from 'react'; type TemplateTypeIcon = { label: MessageDescriptor; diff --git a/apps/remix/app/components/general/user-profile-skeleton.tsx b/apps/remix/app/components/general/user-profile-skeleton.tsx index 087785ad9..022bbdcea 100644 --- a/apps/remix/app/components/general/user-profile-skeleton.tsx +++ b/apps/remix/app/components/general/user-profile-skeleton.tsx @@ -1,10 +1,9 @@ -import { Trans } from '@lingui/react/macro'; -import { File, User2 } from 'lucide-react'; - import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { VerifiedIcon } from '@documenso/ui/icons/verified'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; +import { Trans } from '@lingui/react/macro'; +import { File, User2 } from 'lucide-react'; export type UserProfileSkeletonProps = { className?: string; @@ -19,13 +18,8 @@ export const UserProfileSkeleton = ({ className, user, rows = 2 }: UserProfileSk const baseUrl = new URL(NEXT_PUBLIC_WEBAPP_URL() ?? 'http://localhost:3000'); return ( -
-
+
+
{baseUrl.host}/u/{user.url}
@@ -39,7 +33,7 @@ export const UserProfileSkeleton = ({ className, user, rows = 2 }: UserProfileSk
-

{user.name}

+

{user.name}

@@ -57,10 +51,7 @@ export const UserProfileSkeleton = ({ className, user, rows = 2 }: UserProfileSk {Array(rows) .fill(0) .map((_, index) => ( -
+
diff --git a/apps/remix/app/components/general/user-profile-timur.tsx b/apps/remix/app/components/general/user-profile-timur.tsx index f3484bc71..cec7204d3 100644 --- a/apps/remix/app/components/general/user-profile-timur.tsx +++ b/apps/remix/app/components/general/user-profile-timur.tsx @@ -1,11 +1,10 @@ -import { Trans } from '@lingui/react/macro'; -import { File } from 'lucide-react'; - import timurImage from '@documenso/assets/images/timur.png'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { VerifiedIcon } from '@documenso/ui/icons/verified'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; +import { Trans } from '@lingui/react/macro'; +import { File } from 'lucide-react'; export type UserProfileTimurProps = { className?: string; @@ -16,59 +15,47 @@ export const UserProfileTimur = ({ className, rows = 2 }: UserProfileTimurProps) const baseUrl = new URL(NEXT_PUBLIC_WEBAPP_URL() ?? 'http://localhost:3000'); return ( -
-
+
+
{baseUrl.host}/u/timur
- image of timur ercan founder of documenso + image of timur ercan founder of documenso
-

Timur Ercan

+

Timur Ercan

- +
-

+

Hey I’m Timur

-

+

Pick any of the following agreements below and start signing to get started

-
-
+
+
Documents
{Array(rows) .fill(0) .map((_, index) => ( -
+
- +
-
-
+
+
diff --git a/apps/remix/app/components/general/verify-email-banner.tsx b/apps/remix/app/components/general/verify-email-banner.tsx index 547b089c6..e9957f9fb 100644 --- a/apps/remix/app/components/general/verify-email-banner.tsx +++ b/apps/remix/app/components/general/verify-email-banner.tsx @@ -1,20 +1,13 @@ -import { useEffect, useState } from 'react'; - +import { authClient } from '@documenso/auth/client'; +import { ONE_DAY, ONE_SECOND } from '@documenso/lib/constants/time'; +import { Button } from '@documenso/ui/primitives/button'; +import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@documenso/ui/primitives/dialog'; +import { useToast } from '@documenso/ui/primitives/use-toast'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { AlertTriangle } from 'lucide-react'; - -import { authClient } from '@documenso/auth/client'; -import { ONE_DAY, ONE_SECOND } from '@documenso/lib/constants/time'; -import { Button } from '@documenso/ui/primitives/button'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogTitle, -} from '@documenso/ui/primitives/dialog'; -import { useToast } from '@documenso/ui/primitives/use-toast'; +import { useEffect, useState } from 'react'; export type VerifyEmailBannerProps = { email: string; @@ -66,9 +59,7 @@ export const VerifyEmailBanner = ({ email }: VerifyEmailBannerProps) => { // Check localStorage to see if we've recently automatically displayed the dialog // if it was within the past 24 hours, don't show it again // otherwise, show it again and update the localStorage timestamp - const emailVerificationDialogLastShown = localStorage.getItem( - 'emailVerificationDialogLastShown', - ); + const emailVerificationDialogLastShown = localStorage.getItem('emailVerificationDialogLastShown'); if (emailVerificationDialogLastShown) { const lastShownTimestamp = parseInt(emailVerificationDialogLastShown); @@ -86,7 +77,7 @@ export const VerifyEmailBanner = ({ email }: VerifyEmailBannerProps) => { return ( <>
-
+
Verify your email address to unlock all features. @@ -100,11 +91,7 @@ export const VerifyEmailBanner = ({ email }: VerifyEmailBannerProps) => { onClick={() => setIsOpen(true)} size="sm" > - {isButtonDisabled ? ( - Verification Email Sent - ) : ( - Verify Now - )} + {isButtonDisabled ? Verification Email Sent : Verify Now}
@@ -118,17 +105,13 @@ export const VerifyEmailBanner = ({ email }: VerifyEmailBannerProps) => { - We've sent a confirmation email to {email}. Please check your inbox - and click the link in the email to verify your account. + We've sent a confirmation email to {email}. Please check your inbox and click the link in + the email to verify your account.
-
diff --git a/apps/remix/app/components/general/virtual-list/use-virtual-list.ts b/apps/remix/app/components/general/virtual-list/use-virtual-list.ts index 21db2e5c9..42abdf617 100644 --- a/apps/remix/app/components/general/virtual-list/use-virtual-list.ts +++ b/apps/remix/app/components/general/virtual-list/use-virtual-list.ts @@ -289,16 +289,7 @@ export const useVirtualList = (options: VirtualListOptions): VirtualListResult = } return items; - }, [ - itemCount, - constraintWidth, - scrollTop, - viewportHeight, - overscan, - offsets, - getItemSize, - findStartIndex, - ]); + }, [itemCount, constraintWidth, scrollTop, viewportHeight, overscan, offsets, getItemSize, findStartIndex]); /** * Imperatively scroll the scroll container so that the item at the given diff --git a/apps/remix/app/components/general/webhook-logs-sheet.tsx b/apps/remix/app/components/general/webhook-logs-sheet.tsx index 9e18f8e81..e16685c78 100644 --- a/apps/remix/app/components/general/webhook-logs-sheet.tsx +++ b/apps/remix/app/components/general/webhook-logs-sheet.tsx @@ -1,10 +1,3 @@ -import { useMemo, useState } from 'react'; - -import { Trans, useLingui } from '@lingui/react/macro'; -import { WebhookCallStatus } from '@prisma/client'; -import { RotateCwIcon } from 'lucide-react'; -import { createCallable } from 'react-call'; - import { toFriendlyWebhookEventName } from '@documenso/lib/universal/webhook/to-friendly-webhook-event-name'; import { trpc } from '@documenso/trpc/react'; import type { TFindWebhookCallsResponse } from '@documenso/trpc/server/webhook-router/find-webhook-calls.types'; @@ -13,182 +6,174 @@ import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; import { Sheet, SheetContent, SheetTitle } from '@documenso/ui/primitives/sheet'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { WebhookCallStatus } from '@prisma/client'; +import { RotateCwIcon } from 'lucide-react'; +import { useMemo, useState } from 'react'; +import { createCallable } from 'react-call'; export type WebhookLogsSheetProps = { webhookCall: TFindWebhookCallsResponse['data'][number]; }; -export const WebhookLogsSheet = createCallable( - ({ call, webhookCall }) => { - const { t } = useLingui(); - const { toast } = useToast(); +export const WebhookLogsSheet = createCallable(({ call, webhookCall }) => { + const { t } = useLingui(); + const { toast } = useToast(); - const [activeTab, setActiveTab] = useState<'request' | 'response'>('request'); + const [activeTab, setActiveTab] = useState<'request' | 'response'>('request'); - const { mutateAsync: resendWebhookCall, isPending: isResending } = - trpc.webhook.calls.resend.useMutation({ - onSuccess: () => { - toast({ title: t`Webhook queued for resend` }); - }, - onError: () => { - toast({ title: t`Something went wrong` }); - }, - }); + const { mutateAsync: resendWebhookCall, isPending: isResending } = trpc.webhook.calls.resend.useMutation({ + onSuccess: () => { + toast({ title: t`Webhook queued for resend` }); + }, + onError: () => { + toast({ title: t`Something went wrong` }); + }, + }); - const generalWebhookDetails = useMemo(() => { - return [ - { - header: t`Status`, - value: webhookCall.status === WebhookCallStatus.SUCCESS ? t`Success` : t`Failed`, - }, - { - header: t`Event`, - value: toFriendlyWebhookEventName(webhookCall.event), - }, - { - header: t`Sent`, - value: new Date(webhookCall.createdAt).toLocaleString(), - }, - { - header: t`Response Code`, - value: webhookCall.responseCode, - }, - { - header: t`Destination`, - value: webhookCall.url, - }, - ]; - }, [webhookCall]); + const generalWebhookDetails = useMemo(() => { + return [ + { + header: t`Status`, + value: webhookCall.status === WebhookCallStatus.SUCCESS ? t`Success` : t`Failed`, + }, + { + header: t`Event`, + value: toFriendlyWebhookEventName(webhookCall.event), + }, + { + header: t`Sent`, + value: new Date(webhookCall.createdAt).toLocaleString(), + }, + { + header: t`Response Code`, + value: webhookCall.responseCode, + }, + { + header: t`Destination`, + value: webhookCall.url, + }, + ]; + }, [webhookCall]); - return ( - (!value ? call.end(null) : null)}> - - -

- Webhook Details -

-

{webhookCall.id}

-
+ return ( + (!value ? call.end(null) : null)}> + + +

+ Webhook Details +

+

{webhookCall.id}

+
- {/* Content */} -
-
-
-

- Details -

+ {/* Content */} +
+
+
+

+ Details +

- -
-
- - - {generalWebhookDetails.map(({ header, value }, index) => ( - - - - - ))} - -
- {header} - - {value} -
-
+ +
+
+ + + {generalWebhookDetails.map(({ header, value }, index) => ( + + + + + ))} + +
+ {header} + {value}
+
+
+ + {/* Payload Tabs */} +
+
+ + +
- {/* Payload Tabs */} -
-
- - - -
- -
-
- toast({ title: t`Copied to clipboard` })} - /> -
-
-                  {JSON.stringify(
+            
+
+ + onCopySuccess={() => toast({ title: t`Copied to clipboard` })} + />
- - {activeTab === 'response' && ( -
-

- Response Headers -

-
- - - {Object.entries(webhookCall.responseHeaders as Record).map( - ([key, value]) => ( - - - - - ), - )} - -
- {key} - - {value as string} -
-
-
- )} +
+                {JSON.stringify(activeTab === 'request' ? webhookCall.requestBody : webhookCall.responseBody, null, 2)}
+              
+ + {activeTab === 'response' && ( +
+

+ Response Headers +

+
+ + + {Object.entries(webhookCall.responseHeaders as Record).map(([key, value]) => ( + + + + + ))} + +
+ {key} + {value as string}
+
+
+ )}
- - - ); - }, -); +
+ + + ); +}); diff --git a/apps/remix/app/components/general/webhook-multiselect-combobox.tsx b/apps/remix/app/components/general/webhook-multiselect-combobox.tsx index e08916973..552bebf88 100644 --- a/apps/remix/app/components/general/webhook-multiselect-combobox.tsx +++ b/apps/remix/app/components/general/webhook-multiselect-combobox.tsx @@ -1,11 +1,10 @@ +import { toFriendlyWebhookEventName } from '@documenso/lib/universal/webhook/to-friendly-webhook-event-name'; +import { MultiSelect, type Option } from '@documenso/ui/primitives/multiselect'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { WebhookTriggerEvents } from '@prisma/client'; -import { toFriendlyWebhookEventName } from '@documenso/lib/universal/webhook/to-friendly-webhook-event-name'; -import { MultiSelect, type Option } from '@documenso/ui/primitives/multiselect'; - type WebhookMultiSelectComboboxProps = { listValues: string[]; onChange: (_values: string[]) => void; @@ -16,10 +15,7 @@ const triggerEvents = Object.values(WebhookTriggerEvents).map((event) => ({ label: toFriendlyWebhookEventName(event), })); -export const WebhookMultiSelectCombobox = ({ - listValues, - onChange, -}: WebhookMultiSelectComboboxProps) => { +export const WebhookMultiSelectCombobox = ({ listValues, onChange }: WebhookMultiSelectComboboxProps) => { const { _ } = useLingui(); const value = listValues.map((event) => ({ diff --git a/apps/remix/app/components/tables/admin-claims-table.tsx b/apps/remix/app/components/tables/admin-claims-table.tsx index cf6d82aac..b569fd6bf 100644 --- a/apps/remix/app/components/tables/admin-claims-table.tsx +++ b/apps/remix/app/components/tables/admin-claims-table.tsx @@ -1,10 +1,3 @@ -import { useMemo } from 'react'; - -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import { EditIcon, MoreHorizontalIcon, Trash2Icon } from 'lucide-react'; -import { Link, useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import type { TLicenseClaim } from '@documenso/lib/types/license'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params'; @@ -24,6 +17,10 @@ import { import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { EditIcon, MoreHorizontalIcon, Trash2Icon } from 'lucide-react'; +import { useMemo } from 'react'; +import { Link, useSearchParams } from 'react-router'; import { ClaimDeleteDialog } from '../dialogs/claim-delete-dialog'; import { ClaimUpdateDialog } from '../dialogs/claim-update-dialog'; @@ -68,20 +65,13 @@ export const AdminClaimsTable = ({ licenseFlags }: AdminClaimsTableProps) => { accessorKey: 'id', maxSize: 50, cell: ({ row }) => ( - toast({ title: t`ID copied to clipboard` })} - /> + toast({ title: t`ID copied to clipboard` })} /> ), }, { header: t`Name`, accessorKey: 'name', - cell: ({ row }) => ( - - {row.original.name} - - ), + cell: ({ row }) => {row.original.name}, }, { header: t`Allowed teams`, @@ -97,16 +87,14 @@ export const AdminClaimsTable = ({ licenseFlags }: AdminClaimsTableProps) => { { header: t`Feature Flags`, cell: ({ row }) => { - const flags = Object.values(SUBSCRIPTION_CLAIM_FEATURE_FLAGS).filter( - ({ key }) => row.original.flags[key], - ); + const flags = Object.values(SUBSCRIPTION_CLAIM_FEATURE_FLAGS).filter(({ key }) => row.original.flags[key]); if (flags.length === 0) { - return

{t`None`}

; + return

{t`None`}

; } return ( -
    +
      {flags.map(({ key, label }) => (
    • {label}
    • ))} diff --git a/apps/remix/app/components/tables/admin-dashboard-users-table.tsx b/apps/remix/app/components/tables/admin-dashboard-users-table.tsx index 0a93ec45f..c6ea2cfb7 100644 --- a/apps/remix/app/components/tables/admin-dashboard-users-table.tsx +++ b/apps/remix/app/components/tables/admin-dashboard-users-table.tsx @@ -1,12 +1,3 @@ -import { useEffect, useMemo, useState, useTransition } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import type { Role, Subscription } from '@prisma/client'; -import { Edit, Loader } from 'lucide-react'; -import { Link } from 'react-router'; - import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { Button } from '@documenso/ui/primitives/button'; @@ -14,6 +5,13 @@ import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Input } from '@documenso/ui/primitives/input'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import type { Role, Subscription } from '@prisma/client'; +import { Edit, Loader } from 'lucide-react'; +import { useEffect, useMemo, useState, useTransition } from 'react'; +import { Link } from 'react-router'; type UserData = { id: number; @@ -24,10 +22,7 @@ type UserData = { documentCount: number; }; -type SubscriptionLite = Pick< - Subscription, - 'id' | 'status' | 'planId' | 'priceId' | 'createdAt' | 'periodEnd' ->; +type SubscriptionLite = Pick; type AdminDashboardUsersTableProps = { users: UserData[]; @@ -36,12 +31,7 @@ type AdminDashboardUsersTableProps = { page: number; }; -export const AdminDashboardUsersTable = ({ - users, - totalPages, - perPage, - page, -}: AdminDashboardUsersTableProps) => { +export const AdminDashboardUsersTable = ({ users, totalPages, perPage, page }: AdminDashboardUsersTableProps) => { const { _ } = useLingui(); const [isPending, startTransition] = useTransition(); @@ -82,7 +72,7 @@ export const AdminDashboardUsersTable = ({ return ( diff --git a/apps/remix/app/components/tables/admin-document-jobs-table.tsx b/apps/remix/app/components/tables/admin-document-jobs-table.tsx index 7528b00eb..40c26781b 100644 --- a/apps/remix/app/components/tables/admin-document-jobs-table.tsx +++ b/apps/remix/app/components/tables/admin-document-jobs-table.tsx @@ -1,9 +1,3 @@ -import { useMemo } from 'react'; - -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import { useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params'; import { trpc } from '@documenso/trpc/react'; @@ -13,6 +7,9 @@ import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { useMemo } from 'react'; +import { useSearchParams } from 'react-router'; export const AdminDocumentJobsTable = ({ envelopeId }: { envelopeId: string }) => { const { t, i18n } = useLingui(); @@ -22,12 +19,11 @@ export const AdminDocumentJobsTable = ({ envelopeId }: { envelopeId: string }) = const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? [])); - const { data, isLoading, isLoadingError, refetch, isFetching } = - trpc.admin.document.findJobs.useQuery({ - envelopeId: envelopeId, - page: parsedSearchParams.page, - perPage: parsedSearchParams.perPage, - }); + const { data, isLoading, isLoadingError, refetch, isFetching } = trpc.admin.document.findJobs.useQuery({ + envelopeId: envelopeId, + page: parsedSearchParams.page, + perPage: parsedSearchParams.perPage, + }); const onPaginationChange = (page: number, perPage: number) => { updateSearchParams({ @@ -65,8 +61,7 @@ export const AdminDocumentJobsTable = ({ envelopeId }: { envelopeId: string }) = { header: t`Last Retried`, accessorKey: 'lastRetriedAt', - cell: ({ row }) => - row.original.lastRetriedAt ? i18n.date(row.original.lastRetriedAt) : 'N/A', + cell: ({ row }) => (row.original.lastRetriedAt ? i18n.date(row.original.lastRetriedAt) : 'N/A'), }, { header: t`Completed`, @@ -79,7 +74,7 @@ export const AdminDocumentJobsTable = ({ envelopeId }: { envelopeId: string }) = return (
      -

      +

      Background Jobs

      @@ -126,9 +121,7 @@ export const AdminDocumentJobsTable = ({ envelopeId }: { envelopeId: string }) = }} > {(table) => - results.totalPages > 1 && ( - - ) + results.totalPages > 1 && }
      diff --git a/apps/remix/app/components/tables/admin-document-logs-table.tsx b/apps/remix/app/components/tables/admin-document-logs-table.tsx index 4a036c571..dd1d25aa5 100644 --- a/apps/remix/app/components/tables/admin-document-logs-table.tsx +++ b/apps/remix/app/components/tables/admin-document-logs-table.tsx @@ -1,13 +1,3 @@ -import { useMemo, useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { DateTime } from 'luxon'; -import type { DateTimeFormatOptions } from 'luxon'; -import { useSearchParams } from 'react-router'; -import { UAParser } from 'ua-parser-js'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import type { TDocumentAuditLog } from '@documenso/lib/types/document-audit-logs'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params'; @@ -22,6 +12,14 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@documenso/ui/ import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import type { DateTimeFormatOptions } from 'luxon'; +import { DateTime } from 'luxon'; +import { useMemo, useState } from 'react'; +import { useSearchParams } from 'react-router'; +import { UAParser } from 'ua-parser-js'; export type AdminDocumentLogsTableProps = { envelopeId: string; @@ -104,9 +102,7 @@ export const AdminDocumentLogsTable = ({ envelopeId }: AdminDocumentLogsTablePro { header: _(msg`Action`), accessorKey: 'type', - cell: ({ row }) => ( - {formatDocumentAuditLogAction(i18n, row.original).description} - ), + cell: ({ row }) => {formatDocumentAuditLogAction(i18n, row.original).description}, }, { header: _(msg`IP Address`), @@ -193,14 +189,14 @@ export const AdminDocumentLogsTable = ({ envelopeId }: AdminDocumentLogsTablePro {selectedAuditLog && (
      -
      +
      toast({ title: _(msg`Copied to clipboard`) })} />
      -
      +              
                       {JSON.stringify(selectedAuditLog, null, 2)}
                     
      diff --git a/apps/remix/app/components/tables/admin-document-recipient-item-table.tsx b/apps/remix/app/components/tables/admin-document-recipient-item-table.tsx index fee406368..329ccacbe 100644 --- a/apps/remix/app/components/tables/admin-document-recipient-item-table.tsx +++ b/apps/remix/app/components/tables/admin-document-recipient-item-table.tsx @@ -1,41 +1,20 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { - type Field, - type Recipient, - RecipientRole, - type Signature, - SigningStatus, -} from '@prisma/client'; -import { useForm } from 'react-hook-form'; -import { useRevalidator } from 'react-router'; -import { z } from 'zod'; - import { zEmail } from '@documenso/lib/utils/zod'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@documenso/ui/primitives/select'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@documenso/ui/primitives/select'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { type Field, type Recipient, RecipientRole, type Signature, SigningStatus } from '@prisma/client'; +import { useMemo } from 'react'; +import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; +import { z } from 'zod'; const RECIPIENT_ROLE_LABELS: Record = { [RecipientRole.SIGNER]: 'Signer', @@ -105,9 +84,7 @@ export const AdminDocumentRecipientItemTable = ({ recipient }: RecipientItemProp accessorKey: 'signature', cell: ({ row }) => (
      - {row.original.signature?.typedSignature && ( - {row.original.signature.typedSignature} - )} + {row.original.signature?.typedSignature && {row.original.signature.typedSignature}} {row.original.signature?.signatureImageAsBase64 && ( []; }, []); - const onUpdateRecipientFormSubmit = async ({ - name, - email, - role, - }: TAdminUpdateRecipientFormSchema) => { + const onUpdateRecipientFormSubmit = async ({ name, email, role }: TAdminUpdateRecipientFormSchema) => { try { await updateRecipient({ id: recipient.id, @@ -156,9 +129,7 @@ export const AdminDocumentRecipientItemTable = ({ recipient }: RecipientItemProp
      @@ -244,7 +212,7 @@ export const AdminDocumentRecipientItemTable = ({ recipient }: RecipientItemProp
      -

      +

      Fields

      diff --git a/apps/remix/app/components/tables/admin-organisation-overview-table.tsx b/apps/remix/app/components/tables/admin-organisation-overview-table.tsx index eb38e04f4..87286a0d4 100644 --- a/apps/remix/app/components/tables/admin-organisation-overview-table.tsx +++ b/apps/remix/app/components/tables/admin-organisation-overview-table.tsx @@ -1,11 +1,3 @@ -import { useEffect, useMemo, useState, useTransition } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { ChevronDownIcon, ChevronUpIcon, ChevronsUpDown, Loader } from 'lucide-react'; -import { Link } from 'react-router'; - import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import type { DateRange } from '@documenso/lib/types/search-params'; @@ -13,6 +5,12 @@ import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Input } from '@documenso/ui/primitives/input'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { ChevronDownIcon, ChevronsUpDown, ChevronUpIcon, Loader } from 'lucide-react'; +import { useEffect, useMemo, useState, useTransition } from 'react'; +import { Link } from 'react-router'; export type OrganisationOverview = { id: string; @@ -56,10 +54,7 @@ export const AdminOrganisationOverviewTable = ({ return [ { header: () => ( -
      handleColumnSort('name')} - > +
      handleColumnSort('name')}> {_(msg`Name`)} {sortBy === 'name' ? ( sortOrder === 'asc' ? ( @@ -89,10 +84,7 @@ export const AdminOrganisationOverviewTable = ({ }, { header: () => ( -
      handleColumnSort('signingVolume')} - > +
      handleColumnSort('signingVolume')}> Document Volume @@ -130,10 +122,7 @@ export const AdminOrganisationOverviewTable = ({ { header: () => { return ( -
      handleColumnSort('createdAt')} - > +
      handleColumnSort('createdAt')}> Created diff --git a/apps/remix/app/components/tables/admin-organisations-table.tsx b/apps/remix/app/components/tables/admin-organisations-table.tsx index 144fb20b8..e8e031afe 100644 --- a/apps/remix/app/components/tables/admin-organisations-table.tsx +++ b/apps/remix/app/components/tables/admin-organisations-table.tsx @@ -1,17 +1,3 @@ -import { useMemo, useState } from 'react'; - -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import { - ArrowRightLeftIcon, - CreditCardIcon, - ExternalLinkIcon, - MoreHorizontalIcon, - SettingsIcon, - UserIcon, -} from 'lucide-react'; -import { Link, useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { SUBSCRIPTION_STATUS_MAP } from '@documenso/lib/constants/billing'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params'; @@ -29,6 +15,17 @@ import { } from '@documenso/ui/primitives/dropdown-menu'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { + ArrowRightLeftIcon, + CreditCardIcon, + ExternalLinkIcon, + MoreHorizontalIcon, + SettingsIcon, + UserIcon, +} from 'lucide-react'; +import { useMemo, useState } from 'react'; +import { Link, useSearchParams } from 'react-router'; import { AdminSwapSubscriptionDialog } from '~/components/dialogs/admin-swap-subscription-dialog'; @@ -85,9 +82,7 @@ export const AdminOrganisationsTable = ({ { header: t`Organisation`, accessorKey: 'name', - cell: ({ row }) => ( - {row.original.name} - ), + cell: ({ row }) => {row.original.name}, }, { header: t`Created At`, @@ -97,17 +92,13 @@ export const AdminOrganisationsTable = ({ { header: t`Owner`, accessorKey: 'owner', - cell: ({ row }) => ( - {row.original.owner.name} - ), + cell: ({ row }) => {row.original.owner.name}, }, { id: 'role', header: t`Role`, cell: ({ row }) => ( - - {row.original.owner.id === memberUserId ? t`Owner` : t`Member`} - + {row.original.owner.id === memberUserId ? t`Owner` : t`Member`} ), }, { @@ -118,7 +109,7 @@ export const AdminOrganisationsTable = ({ const isPaid = subscription && subscription.status === 'ACTIVE'; return (
      @@ -183,8 +174,7 @@ export const AdminOrganisationsTable = ({ {row.original.subscription && - (row.original.subscription.status === 'ACTIVE' || - row.original.subscription.status === 'PAST_DUE') && ( + (row.original.subscription.status === 'ACTIVE' || row.original.subscription.status === 'PAST_DUE') && ( setSwapSource({ diff --git a/apps/remix/app/components/tables/admin-user-teams-table.tsx b/apps/remix/app/components/tables/admin-user-teams-table.tsx index 39eaaa5b4..901205b1c 100644 --- a/apps/remix/app/components/tables/admin-user-teams-table.tsx +++ b/apps/remix/app/components/tables/admin-user-teams-table.tsx @@ -1,9 +1,3 @@ -import { useMemo } from 'react'; - -import { useLingui } from '@lingui/react'; -import { useLingui as useLinguiMacro } from '@lingui/react/macro'; -import { Link, useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams-translations'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params'; @@ -16,6 +10,10 @@ import { DataTablePagination } from '@documenso/ui/primitives/data-table-paginat import { HoverCard, HoverCardContent, HoverCardTrigger } from '@documenso/ui/primitives/hover-card'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { useLingui } from '@lingui/react'; +import { useLingui as useLinguiMacro } from '@lingui/react/macro'; +import { useMemo } from 'react'; +import { Link, useSearchParams } from 'react-router'; type AdminUserTeamsTableProps = { userId: number; @@ -61,10 +59,7 @@ export const AdminUserTeamsTable = ({ userId }: AdminUserTeamsTableProps) => { {row.original.name} - +
      id
      {row.original.id}
      @@ -79,10 +74,7 @@ export const AdminUserTeamsTable = ({ userId }: AdminUserTeamsTableProps) => { header: t`Organisation`, accessorKey: 'organisation', cell: ({ row }) => ( - + {row.original.organisation.name} ), @@ -91,9 +83,7 @@ export const AdminUserTeamsTable = ({ userId }: AdminUserTeamsTableProps) => { header: t`Role`, accessorKey: 'teamRole', cell: ({ row }) => ( - - {i18n._(TEAM_MEMBER_ROLE_MAP[row.original.teamRole as TeamMemberRole])} - + {i18n._(TEAM_MEMBER_ROLE_MAP[row.original.teamRole as TeamMemberRole])} ), }, { @@ -137,9 +127,7 @@ export const AdminUserTeamsTable = ({ userId }: AdminUserTeamsTableProps) => { }} > {(table) => - table.getPageCount() > 1 ? ( - - ) : null + table.getPageCount() > 1 ? : null } ); diff --git a/apps/remix/app/components/tables/document-logs-table.tsx b/apps/remix/app/components/tables/document-logs-table.tsx index c37235130..892a27a50 100644 --- a/apps/remix/app/components/tables/document-logs-table.tsx +++ b/apps/remix/app/components/tables/document-logs-table.tsx @@ -1,13 +1,3 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { DateTime } from 'luxon'; -import type { DateTimeFormatOptions } from 'luxon'; -import { useSearchParams } from 'react-router'; -import { UAParser } from 'ua-parser-js'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params'; import { formatDocumentAuditLogAction } from '@documenso/lib/utils/document-audit-logs'; @@ -17,6 +7,14 @@ import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import type { DateTimeFormatOptions } from 'luxon'; +import { DateTime } from 'luxon'; +import { useMemo } from 'react'; +import { useSearchParams } from 'react-router'; +import { UAParser } from 'ua-parser-js'; export type DocumentLogsTableProps = { documentId: number; @@ -97,9 +95,7 @@ export const DocumentLogsTable = ({ documentId, userId }: DocumentLogsTableProps { header: _(msg`Action`), accessorKey: 'type', - cell: ({ row }) => ( - {formatDocumentAuditLogAction(i18n, row.original, userId).description} - ), + cell: ({ row }) => {formatDocumentAuditLogAction(i18n, row.original, userId).description}, }, { header: _(msg`IP Address`), diff --git a/apps/remix/app/components/tables/documents-table-action-button.tsx b/apps/remix/app/components/tables/documents-table-action-button.tsx index 506c6afa0..a6e9a9edd 100644 --- a/apps/remix/app/components/tables/documents-table-action-button.tsx +++ b/apps/remix/app/components/tables/documents-table-action-button.tsx @@ -1,15 +1,14 @@ -import { Trans } from '@lingui/react/macro'; -import { DocumentStatus, RecipientRole, SigningStatus } from '@prisma/client'; -import { CheckCircle, Download, Edit, EyeIcon, Pencil } from 'lucide-react'; -import { Link } from 'react-router'; -import { match } from 'ts-pattern'; - import { useSession } from '@documenso/lib/client-only/providers/session'; import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document'; import { isDocumentCompleted } from '@documenso/lib/utils/document'; import { findRecipientByEmail } from '@documenso/lib/utils/recipients'; import { formatDocumentsPath } from '@documenso/lib/utils/teams'; import { Button } from '@documenso/ui/primitives/button'; +import { Trans } from '@lingui/react/macro'; +import { DocumentStatus, RecipientRole, SigningStatus } from '@prisma/client'; +import { CheckCircle, Download, Edit, EyeIcon, Pencil } from 'lucide-react'; +import { Link } from 'react-router'; +import { match } from 'ts-pattern'; import { useCurrentTeam } from '~/providers/team'; @@ -57,36 +56,33 @@ export const DocumentsTableActionButton = ({ row }: DocumentsTableActionButtonPr isCurrentTeamDocument, internalVersion: row.internalVersion, }) - .with( - isOwner ? { isDraft: true, isOwner: true } : { isDraft: true, isCurrentTeamDocument: true }, - () => ( - - ), - ) + .with(isOwner ? { isDraft: true, isOwner: true } : { isDraft: true, isCurrentTeamDocument: true }, () => ( + + )) .with({ isRecipient: true, isPending: true, isSigned: false }, () => ( )) @@ -106,7 +102,7 @@ export const DocumentsTableActionButton = ({ row }: DocumentsTableActionButtonPr token={recipient?.token} trigger={ } diff --git a/apps/remix/app/components/tables/documents-table-action-dropdown.tsx b/apps/remix/app/components/tables/documents-table-action-dropdown.tsx index 509be3880..1555d54a2 100644 --- a/apps/remix/app/components/tables/documents-table-action-dropdown.tsx +++ b/apps/remix/app/components/tables/documents-table-action-dropdown.tsx @@ -1,5 +1,18 @@ -import { useState } from 'react'; - +import { useSession } from '@documenso/lib/client-only/providers/session'; +import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document'; +import { isDocumentCompleted } from '@documenso/lib/utils/document'; +import { getEnvelopeItemPermissions } from '@documenso/lib/utils/envelope'; +import { findRecipientByEmail } from '@documenso/lib/utils/recipients'; +import { formatDocumentsPath } from '@documenso/lib/utils/teams'; +import { trpc as trpcReact } from '@documenso/trpc/react'; +import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuTrigger, +} from '@documenso/ui/primitives/dropdown-menu'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; @@ -18,24 +31,9 @@ import { Share, Trash2, } from 'lucide-react'; +import { useState } from 'react'; import { Link } from 'react-router'; -import { useSession } from '@documenso/lib/client-only/providers/session'; -import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document'; -import { isDocumentCompleted } from '@documenso/lib/utils/document'; -import { getEnvelopeItemPermissions } from '@documenso/lib/utils/envelope'; -import { findRecipientByEmail } from '@documenso/lib/utils/recipients'; -import { formatDocumentsPath } from '@documenso/lib/utils/teams'; -import { trpc as trpcReact } from '@documenso/trpc/react'; -import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuTrigger, -} from '@documenso/ui/primitives/dropdown-menu'; - import { DocumentResendDialog } from '~/components/dialogs/document-resend-dialog'; import { EnvelopeDeleteDialog } from '~/components/dialogs/envelope-delete-dialog'; import { EnvelopeDuplicateDialog } from '~/components/dialogs/envelope-duplicate-dialog'; @@ -51,10 +49,7 @@ export type DocumentsTableActionDropdownProps = { onMoveDocument?: () => void; }; -export const DocumentsTableActionDropdown = ({ - row, - onMoveDocument, -}: DocumentsTableActionDropdownProps) => { +export const DocumentsTableActionDropdown = ({ row, onMoveDocument }: DocumentsTableActionDropdownProps) => { const { user } = useSession(); const team = useCurrentTeam(); @@ -152,7 +147,8 @@ export const DocumentsTableActionDropdown = ({ e.preventDefault()}>
      diff --git a/apps/remix/app/components/tables/documents-table-empty-state.tsx b/apps/remix/app/components/tables/documents-table-empty-state.tsx index e02a1c2bd..1b049cdac 100644 --- a/apps/remix/app/components/tables/documents-table-empty-state.tsx +++ b/apps/remix/app/components/tables/documents-table-empty-state.tsx @@ -1,10 +1,9 @@ +import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Bird, CheckCircle2 } from 'lucide-react'; import { match } from 'ts-pattern'; -import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status'; - export type DocumentsTableEmptyStateProps = { status: ExtendedDocumentStatus }; export const DocumentsTableEmptyState = ({ status }: DocumentsTableEmptyStateProps) => { @@ -38,13 +37,13 @@ export const DocumentsTableEmptyState = ({ status }: DocumentsTableEmptyStatePro return (
      -

      {_(title)}

      +

      {_(title)}

      {_(message)}

      diff --git a/apps/remix/app/components/tables/documents-table-sender-filter.tsx b/apps/remix/app/components/tables/documents-table-sender-filter.tsx index 4a44edd51..c4c2bbd4a 100644 --- a/apps/remix/app/components/tables/documents-table-sender-filter.tsx +++ b/apps/remix/app/components/tables/documents-table-sender-filter.tsx @@ -1,10 +1,9 @@ -import { msg } from '@lingui/core/macro'; -import { Trans } from '@lingui/react/macro'; -import { useLocation, useNavigate, useSearchParams } from 'react-router'; - import { useIsMounted } from '@documenso/lib/client-only/hooks/use-is-mounted'; import { trpc } from '@documenso/trpc/react'; import { MultiSelectCombobox } from '@documenso/ui/primitives/multi-select-combobox'; +import { msg } from '@lingui/core/macro'; +import { Trans } from '@lingui/react/macro'; +import { useLocation, useNavigate, useSearchParams } from 'react-router'; type DocumentsTableSenderFilterProps = { teamId: number; @@ -17,9 +16,7 @@ export const DocumentsTableSenderFilter = ({ teamId }: DocumentsTableSenderFilte const isMounted = useIsMounted(); - const senderIds = (searchParams?.get('senderIds') ?? '') - .split(',') - .filter((value) => value !== ''); + const senderIds = (searchParams?.get('senderIds') ?? '').split(',').filter((value) => value !== ''); const { data, isLoading } = trpc.team.member.getMany.useQuery({ teamId, @@ -49,7 +46,7 @@ export const DocumentsTableSenderFilter = ({ teamId }: DocumentsTableSenderFilte return ( +

      Sender: All diff --git a/apps/remix/app/components/tables/documents-table-title.tsx b/apps/remix/app/components/tables/documents-table-title.tsx index 914a59625..b9ff67c2e 100644 --- a/apps/remix/app/components/tables/documents-table-title.tsx +++ b/apps/remix/app/components/tables/documents-table-title.tsx @@ -1,10 +1,9 @@ -import { Link } from 'react-router'; -import { match } from 'ts-pattern'; - import { useSession } from '@documenso/lib/client-only/providers/session'; import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document'; import { findRecipientByEmail } from '@documenso/lib/utils/recipients'; import { formatDocumentsPath } from '@documenso/lib/utils/teams'; +import { Link } from 'react-router'; +import { match } from 'ts-pattern'; import { useCurrentTeam } from '~/providers/team'; @@ -53,8 +52,6 @@ export const DataTableTitle = ({ row, teamUrl }: DataTableTitleProps) => { )) .otherwise(() => ( - - {row.title} - + {row.title} )); }; diff --git a/apps/remix/app/components/tables/documents-table.tsx b/apps/remix/app/components/tables/documents-table.tsx index 7f1d104dd..ddffc8a9c 100644 --- a/apps/remix/app/components/tables/documents-table.tsx +++ b/apps/remix/app/components/tables/documents-table.tsx @@ -1,12 +1,3 @@ -import { useMemo, useTransition } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Loader } from 'lucide-react'; -import { DateTime } from 'luxon'; -import { Link } from 'react-router'; -import { match } from 'ts-pattern'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useSession } from '@documenso/lib/client-only/providers/session'; import { isDocumentCompleted } from '@documenso/lib/utils/document'; @@ -19,6 +10,13 @@ import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Loader } from 'lucide-react'; +import { DateTime } from 'luxon'; +import { useMemo, useTransition } from 'react'; +import { Link } from 'react-router'; +import { match } from 'ts-pattern'; import { DocumentStatus } from '~/components/general/document/document-status'; import { useCurrentTeam } from '~/providers/team'; @@ -87,18 +85,11 @@ export const DocumentsTable = ({ { header: _(msg`Created`), accessorKey: 'createdAt', - cell: ({ row }) => - i18n.date(row.original.createdAt, { ...DateTime.DATETIME_SHORT, hourCycle: 'h12' }), + cell: ({ row }) => i18n.date(row.original.createdAt, { ...DateTime.DATETIME_SHORT, hourCycle: 'h12' }), }, { header: _(msg`Title`), - cell: ({ row }) => ( - - ), + cell: ({ row }) => , }, { id: 'sender', @@ -109,10 +100,7 @@ export const DocumentsTable = ({ header: _(msg`Recipient`), accessorKey: 'recipient', cell: ({ row }) => ( - + ), }, { @@ -263,8 +251,6 @@ const DataTableTitle = ({ row, teamUrl, teamEmail }: DataTableTitleProps) => { )) .otherwise(() => ( - - {row.title} - + {row.title} )); }; diff --git a/apps/remix/app/components/tables/envelopes-table-bulk-action-bar.tsx b/apps/remix/app/components/tables/envelopes-table-bulk-action-bar.tsx index a7e0efa25..3a7d89dc5 100644 --- a/apps/remix/app/components/tables/envelopes-table-bulk-action-bar.tsx +++ b/apps/remix/app/components/tables/envelopes-table-bulk-action-bar.tsx @@ -1,8 +1,6 @@ -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import { FolderInputIcon, Trash2Icon, XIcon } from 'lucide-react'; - import { Button } from '@documenso/ui/primitives/button'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { FolderInputIcon, Trash2Icon, XIcon } from 'lucide-react'; export type EnvelopesTableBulkActionBarProps = { selectedCount: number; @@ -25,7 +23,7 @@ export const EnvelopesTableBulkActionBar = ({ return (

      - + {selectedCount} selected diff --git a/apps/remix/app/components/tables/inbox-table.tsx b/apps/remix/app/components/tables/inbox-table.tsx index eb72219b4..d0d6a9e21 100644 --- a/apps/remix/app/components/tables/inbox-table.tsx +++ b/apps/remix/app/components/tables/inbox-table.tsx @@ -1,15 +1,3 @@ -import { useMemo, useTransition } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { DocumentStatus as DocumentStatusEnum } from '@prisma/client'; -import { RecipientRole, SigningStatus } from '@prisma/client'; -import { CheckCircleIcon, DownloadIcon, EyeIcon, Loader, PencilIcon } from 'lucide-react'; -import { DateTime } from 'luxon'; -import { Link, useSearchParams } from 'react-router'; -import { match } from 'ts-pattern'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useSession } from '@documenso/lib/client-only/providers/session'; import { isDocumentCompleted } from '@documenso/lib/utils/document'; @@ -22,6 +10,15 @@ import { DataTablePagination } from '@documenso/ui/primitives/data-table-paginat import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { DocumentStatus as DocumentStatusEnum, RecipientRole, SigningStatus } from '@prisma/client'; +import { CheckCircleIcon, DownloadIcon, EyeIcon, Loader, PencilIcon } from 'lucide-react'; +import { DateTime } from 'luxon'; +import { useMemo, useTransition } from 'react'; +import { Link, useSearchParams } from 'react-router'; +import { match } from 'ts-pattern'; import { DocumentStatus } from '~/components/general/document/document-status'; import { useOptionalCurrentTeam } from '~/providers/team'; @@ -59,15 +56,12 @@ export const InboxTable = () => { { header: _(msg`Created`), accessorKey: 'createdAt', - cell: ({ row }) => - i18n.date(row.original.createdAt, { ...DateTime.DATETIME_SHORT, hourCycle: 'h12' }), + cell: ({ row }) => i18n.date(row.original.createdAt, { ...DateTime.DATETIME_SHORT, hourCycle: 'h12' }), }, { header: _(msg`Title`), cell: ({ row }) => ( - - {row.original.title} - + {row.original.title} ), }, { @@ -79,10 +73,7 @@ export const InboxTable = () => { header: _(msg`Recipient`), accessorKey: 'recipient', cell: ({ row }) => ( - + ), }, { @@ -130,7 +121,7 @@ export const InboxTable = () => { enable: isLoadingError || false, }} emptyState={ -
      +

      Documents that require your attention will appear here

      @@ -163,15 +154,13 @@ export const InboxTable = () => { }} > {(table) => - results.totalPages > 1 && ( - - ) + results.totalPages > 1 && } {isPending && ( -
      - +
      +
      )}
      @@ -215,19 +204,19 @@ export const InboxTableActionButton = ({ row }: InboxTableActionButtonProps) => {match(role) .with(RecipientRole.SIGNER, () => ( <> - + Sign )) .with(RecipientRole.APPROVER, () => ( <> - + Approve )) .otherwise(() => ( <> - + View ))} @@ -236,7 +225,7 @@ export const InboxTableActionButton = ({ row }: InboxTableActionButtonProps) => )) .with({ isPending: true, isSigned: true }, () => ( )) @@ -247,7 +236,7 @@ export const InboxTableActionButton = ({ row }: InboxTableActionButtonProps) => token={recipient?.token} trigger={ } diff --git a/apps/remix/app/components/tables/internal-audit-log-table.tsx b/apps/remix/app/components/tables/internal-audit-log-table.tsx index 5449bb052..03cff1d83 100644 --- a/apps/remix/app/components/tables/internal-audit-log-table.tsx +++ b/apps/remix/app/components/tables/internal-audit-log-table.tsx @@ -1,19 +1,15 @@ +import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n'; +import { DOCUMENT_AUDIT_LOG_TYPE, type TDocumentAuditLog } from '@documenso/lib/types/document-audit-logs'; +import { formatDocumentAuditLogAction } from '@documenso/lib/utils/document-audit-logs'; +import { cn } from '@documenso/ui/lib/utils'; +import { Card, CardContent } from '@documenso/ui/primitives/card'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import type { DateTimeFormatOptions } from 'luxon'; import { DateTime } from 'luxon'; -import { P, match } from 'ts-pattern'; +import { match, P } from 'ts-pattern'; import { UAParser } from 'ua-parser-js'; -import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n'; -import { - DOCUMENT_AUDIT_LOG_TYPE, - type TDocumentAuditLog, -} from '@documenso/lib/types/document-audit-logs'; -import { formatDocumentAuditLogAction } from '@documenso/lib/utils/document-audit-logs'; -import { cn } from '@documenso/ui/lib/utils'; -import { Card, CardContent } from '@documenso/ui/primitives/card'; - export type AuditLogDataTableProps = { logs: TDocumentAuditLog[]; }; @@ -33,10 +29,7 @@ const getAuditLogIndicatorColor = (type: string) => .with(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_REJECTED, () => 'bg-red-500') .with(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_SENT, () => 'bg-orange-500') .with( - P.union( - DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_INSERTED, - DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_UNINSERTED, - ), + P.union(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_INSERTED, DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_UNINSERTED), () => 'bg-blue-500', ) .otherwise(() => 'bg-muted'); @@ -90,22 +83,20 @@ export const InternalAuditLogTable = ({ logs }: AuditLogDataTableProps) => { {/* Header Section with indicator, event type, and timestamp */}
      -
      +
      -
      +
      {log.type.replace(/_/g, ' ')}
      -
      +
      {formattedAction.description}
      -
      +
      {DateTime.fromJSDate(log.createdAt) .setLocale(APP_I18N_OPTIONS.defaultLocale) .toLocaleString(dateFormat)} @@ -117,15 +108,13 @@ export const InternalAuditLogTable = ({ logs }: AuditLogDataTableProps) => { {/* Details Section - Two column layout */}
      -
      - {_(msg`User`)} -
      +
      {_(msg`User`)}
      {log.email || 'N/A'}
      -
      +
      {_(msg`IP Address`)}
      @@ -133,13 +122,11 @@ export const InternalAuditLogTable = ({ logs }: AuditLogDataTableProps) => {
      -
      +
      {_(msg`User Agent`)}
      -
      - {_(formatUserAgent(log.userAgent, userAgentInfo))} -
      +
      {_(formatUserAgent(log.userAgent, userAgentInfo))}
      diff --git a/apps/remix/app/components/tables/organisation-billing-invoices-table.tsx b/apps/remix/app/components/tables/organisation-billing-invoices-table.tsx index 9cc84d903..19cf98cda 100644 --- a/apps/remix/app/components/tables/organisation-billing-invoices-table.tsx +++ b/apps/remix/app/components/tables/organisation-billing-invoices-table.tsx @@ -1,18 +1,16 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { File } from 'lucide-react'; -import { DateTime } from 'luxon'; -import { Link } from 'react-router'; - import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { File } from 'lucide-react'; +import { DateTime } from 'luxon'; +import { useMemo } from 'react'; +import { Link } from 'react-router'; export type OrganisationBillingInvoicesTableProps = { organisationId: string; @@ -59,7 +57,7 @@ export const OrganisationBillingInvoicesTable = ({
      -
      +
      {DateTime.fromSeconds(row.original.created).toFormat('MMMM yyyy')}
      @@ -87,21 +85,13 @@ export const OrganisationBillingInvoicesTable = ({ id: 'actions', cell: ({ row }) => (
      - - { }} > {(table) => - results.totalPages > 1 && ( - - ) + results.totalPages > 1 && } {results.data.length > 0 && ( - +
      Sync Email Domains - - This will check and sync the status of all email domains for this organisation - + This will check and sync the status of all email domains for this organisation
      diff --git a/apps/remix/app/components/tables/organisation-groups-table.tsx b/apps/remix/app/components/tables/organisation-groups-table.tsx index 5656c7580..a6e586d85 100644 --- a/apps/remix/app/components/tables/organisation-groups-table.tsx +++ b/apps/remix/app/components/tables/organisation-groups-table.tsx @@ -1,11 +1,3 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { OrganisationGroupType } from '@prisma/client'; -import { Link, useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { EXTENDED_ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations'; @@ -17,6 +9,12 @@ import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { OrganisationGroupType } from '@prisma/client'; +import { useMemo } from 'react'; +import { Link, useSearchParams } from 'react-router'; import { OrganisationGroupDeleteDialog } from '../dialogs/organisation-group-delete-dialog'; @@ -141,11 +139,7 @@ export const OrganisationGroupsDataTable = () => { ), }} > - {(table) => - results.totalPages > 1 && ( - - ) - } + {(table) => results.totalPages > 1 && } ); }; diff --git a/apps/remix/app/components/tables/organisation-insights-table.tsx b/apps/remix/app/components/tables/organisation-insights-table.tsx index 5d6c5dc44..30d52b859 100644 --- a/apps/remix/app/components/tables/organisation-insights-table.tsx +++ b/apps/remix/app/components/tables/organisation-insights-table.tsx @@ -1,11 +1,3 @@ -import { useTransition } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Building2, Loader, TrendingUp, Users } from 'lucide-react'; -import { Link } from 'react-router'; -import { useNavigation } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import type { OrganisationDetailedInsights } from '@documenso/lib/server-only/admin/get-organisation-detailed-insights'; import type { DateRange } from '@documenso/lib/types/search-params'; @@ -14,6 +6,11 @@ import { Button } from '@documenso/ui/primitives/button'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Building2, Loader, TrendingUp, Users } from 'lucide-react'; +import { useTransition } from 'react'; +import { Link, useNavigation } from 'react-router'; import { DateRangeFilter } from '~/components/filters/date-range-filter'; import { DocumentStatus } from '~/components/general/document/document-status'; @@ -63,10 +60,7 @@ export const OrganisationInsightsTable = ({ header: _(msg`Team Name`), accessorKey: 'name', cell: ({ row }) => ( - + {row.getValue('name')} ), @@ -97,10 +91,7 @@ export const OrganisationInsightsTable = ({ header: () => {_(msg`Name`)}, accessorKey: 'name', cell: ({ row }) => ( - + {(row.getValue('name') as string) || (row.getValue('email') as string)} ), @@ -150,9 +141,7 @@ export const OrganisationInsightsTable = ({ { header: () => {_(msg`Status`)}, accessorKey: 'status', - cell: ({ row }) => ( - - ), + cell: ({ row }) => , size: 120, }, { @@ -286,9 +275,9 @@ const SummaryCard = ({
      -

      {title}

      -

      {value}

      - {subtitle &&

      {subtitle}

      } +

      {title}

      +

      {value}

      + {subtitle &&

      {subtitle}

      }
      ); diff --git a/apps/remix/app/components/tables/organisation-member-invites-table.tsx b/apps/remix/app/components/tables/organisation-member-invites-table.tsx index 5ce733df6..08cd46ee4 100644 --- a/apps/remix/app/components/tables/organisation-member-invites-table.tsx +++ b/apps/remix/app/components/tables/organisation-member-invites-table.tsx @@ -1,12 +1,3 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { OrganisationMemberInviteStatus } from '@prisma/client'; -import { History, MoreHorizontal, Trash2 } from 'lucide-react'; -import { useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations'; @@ -27,6 +18,13 @@ import { import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { OrganisationMemberInviteStatus } from '@prisma/client'; +import { History, MoreHorizontal, Trash2 } from 'lucide-react'; +import { useMemo } from 'react'; +import { useSearchParams } from 'react-router'; export const OrganisationMemberInvitesTable = () => { const [searchParams] = useSearchParams(); @@ -51,39 +49,37 @@ export const OrganisationMemberInvitesTable = () => { }, ); - const { mutateAsync: resendOrganisationMemberInvitation } = - trpc.organisation.member.invite.resend.useMutation({ - onSuccess: () => { - toast({ - title: _(msg`Success`), - description: _(msg`Invitation has been resent`), - }); - }, - onError: () => { - toast({ - title: _(msg`Something went wrong`), - description: _(msg`Unable to resend invitation. Please try again.`), - variant: 'destructive', - }); - }, - }); + const { mutateAsync: resendOrganisationMemberInvitation } = trpc.organisation.member.invite.resend.useMutation({ + onSuccess: () => { + toast({ + title: _(msg`Success`), + description: _(msg`Invitation has been resent`), + }); + }, + onError: () => { + toast({ + title: _(msg`Something went wrong`), + description: _(msg`Unable to resend invitation. Please try again.`), + variant: 'destructive', + }); + }, + }); - const { mutateAsync: deleteOrganisationMemberInvitations } = - trpc.organisation.member.invite.deleteMany.useMutation({ - onSuccess: () => { - toast({ - title: _(msg`Success`), - description: _(msg`Invitation has been deleted`), - }); - }, - onError: () => { - toast({ - title: _(msg`Something went wrong`), - description: _(msg`Unable to delete invitation. Please try again.`), - variant: 'destructive', - }); - }, - }); + const { mutateAsync: deleteOrganisationMemberInvitations } = trpc.organisation.member.invite.deleteMany.useMutation({ + onSuccess: () => { + toast({ + title: _(msg`Success`), + description: _(msg`Invitation has been deleted`), + }); + }, + onError: () => { + toast({ + title: _(msg`Something went wrong`), + description: _(msg`Unable to delete invitation. Please try again.`), + variant: 'destructive', + }); + }, + }); const onPaginationChange = (page: number, perPage: number) => { updateSearchParams({ @@ -108,9 +104,7 @@ export const OrganisationMemberInvitesTable = () => { {row.original.email} - } + primaryText={{row.original.email}} /> ); }, @@ -208,11 +202,7 @@ export const OrganisationMemberInvitesTable = () => { ), }} > - {(table) => - results.totalPages > 1 && ( - - ) - } + {(table) => results.totalPages > 1 && } ); }; diff --git a/apps/remix/app/components/tables/organisation-members-table.tsx b/apps/remix/app/components/tables/organisation-members-table.tsx index 8295efe2a..f98fc1889 100644 --- a/apps/remix/app/components/tables/organisation-members-table.tsx +++ b/apps/remix/app/components/tables/organisation-members-table.tsx @@ -1,12 +1,3 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { OrganisationGroupType } from '@prisma/client'; -import { Edit, MoreHorizontal, Trash2 } from 'lucide-react'; -import { useSearchParams } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { EXTENDED_ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations'; @@ -27,6 +18,13 @@ 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 { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { OrganisationGroupType } from '@prisma/client'; +import { Edit, MoreHorizontal, Trash2 } from 'lucide-react'; +import { useMemo } from 'react'; +import { useSearchParams } from 'react-router'; import { OrganisationMemberDeleteDialog } from '~/components/dialogs/organisation-member-delete-dialog'; import { OrganisationMemberUpdateDialog } from '~/components/dialogs/organisation-member-update-dialog'; @@ -79,9 +77,7 @@ export const OrganisationMembersDataTable = () => { {row.original.name} - } + primaryText={{row.original.name}} secondaryText={row.original.email} /> ); @@ -102,15 +98,14 @@ export const OrganisationMembersDataTable = () => { }, { header: _(msg`Groups`), - cell: ({ row }) => - row.original.groups.filter((group) => group.type === OrganisationGroupType.CUSTOM).length, + cell: ({ row }) => row.original.groups.filter((group) => group.type === OrganisationGroupType.CUSTOM).length, }, { header: _(msg`Actions`), cell: ({ row }) => ( - + @@ -209,11 +204,7 @@ export const OrganisationMembersDataTable = () => { ), }} > - {(table) => - results.totalPages > 1 && ( - - ) - } + {(table) => results.totalPages > 1 && } ); }; diff --git a/apps/remix/app/components/tables/organisation-teams-table.tsx b/apps/remix/app/components/tables/organisation-teams-table.tsx index 73632814f..86d1e2161 100644 --- a/apps/remix/app/components/tables/organisation-teams-table.tsx +++ b/apps/remix/app/components/tables/organisation-teams-table.tsx @@ -1,11 +1,3 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { useSearchParams } from 'react-router'; -import { Link } from 'react-router'; - import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; @@ -19,6 +11,11 @@ import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useMemo } from 'react'; +import { Link, useSearchParams } from 'react-router'; import { TeamDeleteDialog } from '../dialogs/team-delete-dialog'; @@ -63,9 +60,7 @@ export const OrganisationTeamsTable = () => { avatarSrc={formatAvatarUrl(row.original.avatarImageId)} avatarClass="h-12 w-12" avatarFallback={row.original.name.slice(0, 1).toUpperCase()} - primaryText={ - {row.original.name} - } + primaryText={{row.original.name}} secondaryText={`${NEXT_PUBLIC_WEBAPP_URL()}/t/${row.original.url}`} /> @@ -143,11 +138,7 @@ export const OrganisationTeamsTable = () => { ), }} > - {(table) => - results.totalPages > 1 && ( - - ) - } + {(table) => results.totalPages > 1 && } ); }; diff --git a/apps/remix/app/components/tables/settings-public-profile-templates-table.tsx b/apps/remix/app/components/tables/settings-public-profile-templates-table.tsx index 6fa8f1d07..1a2593000 100644 --- a/apps/remix/app/components/tables/settings-public-profile-templates-table.tsx +++ b/apps/remix/app/components/tables/settings-public-profile-templates-table.tsx @@ -1,11 +1,3 @@ -import { useMemo, useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { type TemplateDirectLink, TemplateType } from '@prisma/client'; -import { EditIcon, FileIcon, LinkIcon, MoreHorizontalIcon, Trash2Icon } from 'lucide-react'; - import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard'; import { formatDirectTemplatePath } from '@documenso/lib/utils/templates'; import { trpc } from '@documenso/trpc/react'; @@ -19,6 +11,12 @@ import { } from '@documenso/ui/primitives/dropdown-menu'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { type TemplateDirectLink, TemplateType } from '@prisma/client'; +import { EditIcon, FileIcon, LinkIcon, MoreHorizontalIcon, Trash2Icon } from 'lucide-react'; +import { useMemo, useState } from 'react'; import { ManagePublicTemplateDialog } from '~/components/dialogs/public-profile-template-manage-dialog'; @@ -82,10 +80,7 @@ export const SettingsPublicProfileTemplatesTable = () => { Array(3) .fill(0) .map((_, index) => ( -
      +
      @@ -100,7 +95,7 @@ export const SettingsPublicProfileTemplatesTable = () => { ))} {isLoadingError && ( -
      +
      Unable to load your public profile templates at this time
      + } + /> + + e.preventDefault()}> +
      + + Delete +
      + + } + /> + )} diff --git a/apps/remix/app/components/tables/templates-table.tsx b/apps/remix/app/components/tables/templates-table.tsx index 46240d4ca..cc7754ffd 100644 --- a/apps/remix/app/components/tables/templates-table.tsx +++ b/apps/remix/app/components/tables/templates-table.tsx @@ -1,19 +1,3 @@ -import { useMemo, useTransition } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { - AlertTriangle, - Building2Icon, - Globe2Icon, - InfoIcon, - Link2Icon, - Loader, - LockIcon, -} from 'lucide-react'; -import { Link } from 'react-router'; - import { useLimits } from '@documenso/ee/server-only/limits/provider/client'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; @@ -27,6 +11,12 @@ import { DataTablePagination } from '@documenso/ui/primitives/data-table-paginat import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { AlertTriangle, Building2Icon, Globe2Icon, InfoIcon, Link2Icon, Loader, LockIcon } from 'lucide-react'; +import { useMemo, useTransition } from 'react'; +import { Link } from 'react-router'; import { TemplateType } from '~/components/general/template/template-type'; import { useCurrentTeam } from '~/providers/team'; @@ -128,7 +118,7 @@ export const TemplatesTable = ({ - +
      • @@ -138,8 +128,8 @@ export const TemplatesTable = ({

        - Public templates are connected to your public profile. Any modifications to - public templates will also appear in your public profile. + Public templates are connected to your public profile. Any modifications to public templates + will also appear in your public profile.

      • @@ -151,9 +141,8 @@ export const TemplatesTable = ({

        - Direct link templates contain one dynamic recipient placeholder. Anyone with - access to this link can sign the document, and it will then appear on your - documents page. + Direct link templates contain one dynamic recipient placeholder. Anyone with access to this link + can sign the document, and it will then appear on your documents page.

        @@ -165,10 +154,7 @@ export const TemplatesTable = ({

        {team?.id ? ( - - Team only templates are not linked anywhere and are visible only to your - team. - + Team only templates are not linked anywhere and are visible only to your team. ) : ( Private templates can only be modified and viewed by you. )} @@ -182,8 +168,8 @@ export const TemplatesTable = ({

        - Organisation templates are shared across all teams within the same - organisation. Only the owning team can edit them. + Organisation templates are shared across all teams within the same organisation. Only the owning + team can edit them.

        @@ -201,9 +187,7 @@ export const TemplatesTable = ({ {isFromOtherTeam && row.original.team?.name && ( - - ({row.original.team.name}) - + ({row.original.team.name}) )} {row.original.directLink?.token && ( @@ -232,11 +216,7 @@ export const TemplatesTable = ({ documentRootPath={documentRootPath} /> - +
      ); }, @@ -273,10 +253,7 @@ export const TemplatesTable = ({ You have reached your document limit.{' '} - + Upgrade your account to continue! diff --git a/apps/remix/app/components/tables/user-billing-organisations-table.tsx b/apps/remix/app/components/tables/user-billing-organisations-table.tsx index bc6a2c604..9cf3aebfc 100644 --- a/apps/remix/app/components/tables/user-billing-organisations-table.tsx +++ b/apps/remix/app/components/tables/user-billing-organisations-table.tsx @@ -1,10 +1,3 @@ -import { useMemo } from 'react'; - -import { Trans, useLingui } from '@lingui/react/macro'; -import { SubscriptionStatus } from '@prisma/client'; -import { Link } from 'react-router'; -import { match } from 'ts-pattern'; - import { useSession } from '@documenso/lib/client-only/providers/session'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { formatAvatarUrl } from '@documenso/lib/utils/avatars'; @@ -14,15 +7,18 @@ import { Badge } from '@documenso/ui/primitives/badge'; import { Button } from '@documenso/ui/primitives/button'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { SubscriptionStatus } from '@prisma/client'; +import { useMemo } from 'react'; +import { Link } from 'react-router'; +import { match } from 'ts-pattern'; export const UserBillingOrganisationsTable = () => { const { t } = useLingui(); const { organisations } = useSession(); const billingOrganisations = useMemo(() => { - return organisations.filter((org) => - canExecuteOrganisationAction('MANAGE_BILLING', org.currentOrganisationRole), - ); + return organisations.filter((org) => canExecuteOrganisationAction('MANAGE_BILLING', org.currentOrganisationRole)); }, [organisations]); const getSubscriptionStatusDisplay = (status: SubscriptionStatus | undefined) => { @@ -56,9 +52,7 @@ export const UserBillingOrganisationsTable = () => { avatarSrc={formatAvatarUrl(row.original.avatarImageId)} avatarClass="h-12 w-12" avatarFallback={row.original.name.slice(0, 1).toUpperCase()} - primaryText={ - {row.original.name} - } + primaryText={{row.original.name}} secondaryText={`${NEXT_PUBLIC_WEBAPP_URL()}/o/${row.original.url}`} /> @@ -91,7 +85,7 @@ export const UserBillingOrganisationsTable = () => { if (billingOrganisations.length === 0) { return ( -
      +

      You don't manage billing for any organisations.

      diff --git a/apps/remix/app/components/tables/user-organisations-table.tsx b/apps/remix/app/components/tables/user-organisations-table.tsx index 6bfdedadc..ca1131a81 100644 --- a/apps/remix/app/components/tables/user-organisations-table.tsx +++ b/apps/remix/app/components/tables/user-organisations-table.tsx @@ -1,10 +1,3 @@ -import { useMemo } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { Link } from 'react-router'; - import { useSession } from '@documenso/lib/client-only/providers/session'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations'; @@ -17,6 +10,11 @@ import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { Skeleton } from '@documenso/ui/primitives/skeleton'; import { TableCell } from '@documenso/ui/primitives/table'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useMemo } from 'react'; +import { Link } from 'react-router'; import { OrganisationLeaveDialog } from '../dialogs/organisation-leave-dialog'; @@ -55,7 +53,7 @@ export const UserOrganisationsTable = () => { avatarClass="h-12 w-12" avatarFallback={row.original.name.slice(0, 1).toUpperCase()} primaryText={ - + {isPersonalLayoutMode ? _( msg({ @@ -92,10 +90,7 @@ export const UserOrganisationsTable = () => { id: 'actions', cell: ({ row }) => (
      - {canExecuteOrganisationAction( - 'MANAGE_ORGANISATION', - row.original.currentOrganisationRole, - ) && ( + {canExecuteOrganisationAction('MANAGE_ORGANISATION', row.original.currentOrganisationRole) && (